Neue Route /plants/:id/diagnoses mit PlantDiagnosesScreen; im Detail ersetzt der Button „Frühere Untersuchungen" (deaktiviert bei leerer Historie) die Inline-Liste. Ergebnis-Sheet nach diagnosis_sheet.dart ausgelagert und von beiden Screens genutzt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
127 lines
4.5 KiB
Dart
127 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import '../../../l10n/generated/app_localizations.dart';
|
|
import '../data/plant_diagnosis_service.dart';
|
|
|
|
/// Zeigt das Diagnose-Ergebnis als scrollbares Bottom-Sheet — sowohl für
|
|
/// eine frische Untersuchung (Detail-Screen) als auch für Einträge aus der
|
|
/// Untersuchungs-Seite ([createdAt] gesetzt).
|
|
Future<void> showDiagnosisSheet(
|
|
BuildContext context, {
|
|
required DiagnosisResult result,
|
|
required String plantNickname,
|
|
DateTime? createdAt,
|
|
}) {
|
|
final l10n = AppLocalizations.of(context);
|
|
final locale = Localizations.localeOf(context).toString();
|
|
return showModalBottomSheet<void>(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
builder: (sheetContext) {
|
|
final theme = Theme.of(sheetContext);
|
|
final healthyColor = theme.brightness == Brightness.dark
|
|
? Colors.green.shade300
|
|
: Colors.green.shade700;
|
|
return DraggableScrollableSheet(
|
|
expand: false,
|
|
initialChildSize: 0.6,
|
|
maxChildSize: 0.95,
|
|
builder: (context, scrollController) => ListView(
|
|
controller: scrollController,
|
|
padding: const EdgeInsets.all(24),
|
|
children: [
|
|
if (!result.matchesSpecies) ...[
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: theme.colorScheme.errorContainer,
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Icon(
|
|
Icons.swap_horiz,
|
|
color: theme.colorScheme.onErrorContainer,
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Text(
|
|
l10n.diagnosisSpeciesMismatch(plantNickname),
|
|
style: theme.textTheme.bodyMedium?.copyWith(
|
|
color: theme.colorScheme.onErrorContainer,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Icon(
|
|
result.healthy
|
|
? Icons.check_circle
|
|
: Icons.warning_amber_rounded,
|
|
size: 32,
|
|
color:
|
|
result.healthy ? healthyColor : theme.colorScheme.error,
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Text(
|
|
result.summary,
|
|
style: theme.textTheme.titleLarge,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
if (createdAt != null) ...[
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
l10n.diagnosisDate(
|
|
DateFormat('d. MMMM y, HH:mm', locale).format(createdAt),
|
|
),
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
|
color: theme.colorScheme.onSurfaceVariant,
|
|
),
|
|
),
|
|
],
|
|
if (result.details.isNotEmpty) ...[
|
|
const SizedBox(height: 16),
|
|
Text(result.details, style: theme.textTheme.bodyLarge),
|
|
],
|
|
if (result.treatment.isNotEmpty) ...[
|
|
const SizedBox(height: 20),
|
|
Text(
|
|
l10n.diagnosisTreatmentTitle,
|
|
style: theme.textTheme.titleMedium,
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(result.treatment, style: theme.textTheme.bodyLarge),
|
|
],
|
|
if (result.prevention.isNotEmpty) ...[
|
|
const SizedBox(height: 20),
|
|
Text(
|
|
l10n.diagnosisPreventionTitle,
|
|
style: theme.textTheme.titleMedium,
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(result.prevention, style: theme.textTheme.bodyLarge),
|
|
],
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
l10n.diagnosisDisclaimer,
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
|
color: theme.colorScheme.onSurfaceVariant,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|