leafittome/lib/features/plants/presentation/plants_screen.dart
cschlaefke 6e22d9c3aa Projekt-Gerüst: Flutter-App mit Heute-Checkliste, Pflanzenverwaltung, Stellplätzen und Einstellungen
- Flutter/Dart (iOS + Android), Riverpod, go_router, i18n via ARB (deutsch)
- Feature-Struktur: today, plants, locations, household (V2-Platzhalter), settings
- Intervall-Modell: Aufgaben werden aus lastWatered/lastFertilized + Intervall berechnet
- In-Memory-Demo-Daten, Firebase-Anbindung folgt im nächsten Block
- Doku: Architektur, Firebase-Einrichtung, Forgejo-Git-Hosting

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 21:13:18 +02:00

92 lines
3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../core/router/app_router.dart';
import '../../../core/widgets/app_drawer.dart';
import '../../../l10n/generated/app_localizations.dart';
import '../../locations/data/locations_provider.dart';
import '../data/plants_provider.dart';
class PlantsScreen extends ConsumerWidget {
const PlantsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context);
final plants = ref.watch(plantsProvider);
return Scaffold(
appBar: AppBar(title: Text(l10n.plantsTitle)),
drawer: const AppDrawer(),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => context.push(AppRoutes.plantAdd),
icon: const Icon(Icons.add),
label: Text(l10n.addPlant),
),
body: plants.isEmpty
? _EmptyView(l10n: l10n)
: ListView.separated(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 96),
itemCount: plants.length,
separatorBuilder: (_, _) => const Divider(height: 1),
itemBuilder: (context, index) {
final plant = plants[index];
final location =
ref.watch(locationByIdProvider(plant.locationId));
return ListTile(
leading: CircleAvatar(
radius: 24,
child: const Icon(Icons.local_florist),
),
title: Text(
plant.nickname,
style: Theme.of(context).textTheme.titleMedium,
),
subtitle: Text(
location != null
? '${plant.species}\n${location.name}'
: plant.species,
),
isThreeLine: location != null,
trailing: const Icon(Icons.chevron_right),
onTap: () => context.push('/plants/${plant.id}'),
);
},
),
);
}
}
class _EmptyView extends StatelessWidget {
const _EmptyView({required this.l10n});
final AppLocalizations l10n;
@override
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.local_florist, size: 72),
const SizedBox(height: 16),
Text(
l10n.plantsEmpty,
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
l10n.plantsEmptyHint,
style: Theme.of(context).textTheme.bodyLarge,
textAlign: TextAlign.center,
),
],
),
),
);
}
}