leafittome/lib/core/widgets/app_drawer.dart
cschlaefke 778b3bd34d V2.2: Besitzer-Konzept, Haushalte umbenennen, Austreten/Entfernen, Checkliste über alle Haushalte
- ownerUid je Haushalt (Alt-Haushalte: erster memberUids-Eintrag = Ersteller);
  Besitzer-Anzeige in Mitglieder- und Haushaltsliste
- Haushalt umbenennen (Dialog im Haushalts-Screen); Rules erlauben Clients am
  Haushalts-Dokument nur noch das Namensfeld
- Cloud Functions leaveHousehold (selbst austreten, auch als Sitter) und
  removeMember (nur Besitzer); beide biegen den aktiven Zeiger des Betroffenen
  um und legen notfalls einen frischen eigenen Haushalt an
- Haushalts-Wechsler im Drawer (PopupMenu, ab zwei Haushalten)
- Tages-Checkliste und nächste Fälligkeit aggregieren über alle Haushalte,
  mit Zwischenüberschrift je Haushalt; Bestätigen schreibt in den
  Herkunfts-Haushalt der Aufgabe
- Widget-Tests: Gruppierung, Besitzer-Rechte, Umbenennen

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

163 lines
5.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../features/household/data/household_providers.dart';
import '../../features/household/domain/household.dart';
import '../../features/today/application/due_tasks_provider.dart';
import '../../l10n/generated/app_localizations.dart';
import '../router/app_router.dart';
/// Das Hamburger-Menü: von jedem Haupt-Screen aus erreichbar,
/// listet alle Funktionen klassisch untereinander auf.
class AppDrawer extends ConsumerWidget {
const AppDrawer({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context);
final currentPath = GoRouterState.of(context).uri.path;
final openTaskCount = ref.watch(dueTasksProvider).length;
final myHouseholds = ref.watch(myHouseholdsProvider).value ?? const [];
final activeHousehold = ref.watch(householdProvider).value;
void goTo(String path) {
Navigator.pop(context);
if (path != currentPath) {
context.go(path);
}
}
return Drawer(
child: SafeArea(
child: ListView(
children: [
Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Icon(
Icons.eco,
size: 36,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(width: 12),
Expanded(
child: Text(
l10n.appTitle,
style: Theme.of(context).textTheme.headlineSmall,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
// Schneller Haushalts-Wechsel, sobald man in mehreren ist.
if (myHouseholds.length > 1)
PopupMenuButton<Household>(
tooltip: l10n.myHouseholds,
onSelected: (target) => ref
.read(householdRepositoryProvider)
.switchHousehold(target.id),
itemBuilder: (context) => [
for (final entry in myHouseholds)
PopupMenuItem(
value: entry,
enabled: entry.id != activeHousehold?.id,
child: Row(
children: [
Icon(
entry.id == activeHousehold?.id
? Icons.home
: Icons.home_outlined,
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(entry.name,
overflow: TextOverflow.ellipsis),
),
],
),
),
],
child: ListTile(
leading: const Icon(Icons.home),
title: Text(
activeHousehold?.name ?? l10n.menuHousehold,
style: const TextStyle(fontSize: 17),
overflow: TextOverflow.ellipsis,
),
trailing: const Icon(Icons.unfold_more),
),
),
const Divider(),
_DrawerItem(
icon: Icons.checklist,
label: l10n.menuToday,
selected: currentPath == AppRoutes.today,
badgeCount: openTaskCount,
onTap: () => goTo(AppRoutes.today),
),
_DrawerItem(
icon: Icons.local_florist,
label: l10n.menuPlants,
selected: currentPath == AppRoutes.plants,
onTap: () => goTo(AppRoutes.plants),
),
_DrawerItem(
icon: Icons.place,
label: l10n.menuLocations,
selected: currentPath == AppRoutes.locations,
onTap: () => goTo(AppRoutes.locations),
),
_DrawerItem(
icon: Icons.group,
label: l10n.menuHousehold,
selected: currentPath == AppRoutes.household,
onTap: () => goTo(AppRoutes.household),
),
_DrawerItem(
icon: Icons.settings,
label: l10n.menuSettings,
selected: currentPath == AppRoutes.settings,
onTap: () => goTo(AppRoutes.settings),
),
],
),
),
);
}
}
class _DrawerItem extends StatelessWidget {
const _DrawerItem({
required this.icon,
required this.label,
required this.selected,
required this.onTap,
this.badgeCount = 0,
});
final IconData icon;
final String label;
final bool selected;
final VoidCallback onTap;
final int badgeCount;
@override
Widget build(BuildContext context) {
return ListTile(
leading: Icon(icon),
title: Text(label, style: const TextStyle(fontSize: 17)),
selected: selected,
trailing: badgeCount > 0
? Badge.count(
count: badgeCount,
backgroundColor: Theme.of(context).colorScheme.primary,
)
: null,
onTap: onTap,
);
}
}