leafittome/lib/features/plants/presentation/diagnosis_sheet.dart
cschlaefke 23560768e2 V3: Untersuchungshistorie auf eigene Seite ausgelagert
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>
2026-07-23 23:21:21 +02:00

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,
),
),
],
),
);
},
);
}