leafittome/lib/core/router/app_router.dart
cschlaefke f0b420b656 V3: Stellplatz-Bewertung (Standort-Analyse per Foto + Eignungs-Sterne auf Abruf)
Letzter Roadmap-Punkt von V3. Foto-basierte Lichtverhältnis-Analyse pro
Stellplatz (Cloud Function analyzeLocation) und darauf aufbauende, rein
textbasierte Eignungs-Bewertung einer Pflanze (assessPlantFit) — beides
ausschließlich auf Abruf, nicht automatisch (Kostenkontrolle, eigener
Anthropic-Key). Neue Stellplatz-Detailseite, Verlinkung im Pflanzen-Detail,
Erkennung veralteter Bewertungen bei Umzug/Neuanalyse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 00:17:18 +02:00

124 lines
4.2 KiB
Dart

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../features/auth/presentation/login_screen.dart';
import '../../features/household/presentation/household_screen.dart';
import '../../features/locations/presentation/location_detail_screen.dart';
import '../../features/locations/presentation/locations_screen.dart';
import '../../features/plants/domain/plant.dart';
import '../../features/plants/presentation/plant_detail_screen.dart';
import '../../features/plants/presentation/plant_diagnoses_screen.dart';
import '../../features/plants/presentation/plant_form_screen.dart';
import '../../features/plants/presentation/plants_screen.dart';
import '../../features/settings/presentation/settings_screen.dart';
import '../../features/today/presentation/today_screen.dart';
import '../firebase/firebase_providers.dart';
/// Zentrale Routen-Definition. Die Pfade werden auch vom Drawer genutzt,
/// deshalb hier als Konstanten.
abstract final class AppRoutes {
static const today = '/';
static const login = '/login';
static const plants = '/plants';
static const plantAdd = '/plants/add';
static const plantEdit = '/plants/edit';
static const locations = '/locations';
static const household = '/household';
static const settings = '/settings';
/// Untersuchungs-Seite einer Pflanze.
static String plantDiagnoses(String plantId) =>
'/plants/$plantId/diagnoses';
/// Detailseite eines Stellplatzes (Foto, Standort-Analyse, Eignung).
static String locationDetail(String locationId) => '/locations/$locationId';
}
/// Übersetzt einen Stream in ein Listenable, damit der Router bei
/// Login/Logout sofort neu auswertet, wohin umgeleitet werden muss.
class _StreamListenable extends ChangeNotifier {
_StreamListenable(Stream<dynamic> stream) {
_subscription = stream.listen((_) => notifyListeners());
}
late final StreamSubscription<dynamic> _subscription;
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}
final appRouterProvider = Provider<GoRouter>((ref) {
final auth = ref.watch(firebaseAuthProvider);
final refreshListenable = _StreamListenable(auth.authStateChanges());
ref.onDispose(refreshListenable.dispose);
final router = GoRouter(
initialLocation: AppRoutes.today,
refreshListenable: refreshListenable,
redirect: (context, state) {
final loggedIn = auth.currentUser != null;
final onLoginScreen = state.matchedLocation == AppRoutes.login;
if (!loggedIn) return onLoginScreen ? null : AppRoutes.login;
if (onLoginScreen) return AppRoutes.today;
return null;
},
routes: [
GoRoute(
path: AppRoutes.login,
builder: (context, state) => const LoginScreen(),
),
GoRoute(
path: AppRoutes.today,
builder: (context, state) => const TodayScreen(),
),
GoRoute(
path: AppRoutes.plants,
builder: (context, state) => const PlantsScreen(),
),
GoRoute(
path: AppRoutes.plantAdd,
builder: (context, state) => const PlantFormScreen(),
),
GoRoute(
path: AppRoutes.plantEdit,
builder: (context, state) =>
PlantFormScreen(existing: state.extra as Plant?),
),
GoRoute(
path: '/plants/:id',
builder: (context, state) =>
PlantDetailScreen(plantId: state.pathParameters['id']!),
),
GoRoute(
path: '/plants/:id/diagnoses',
builder: (context, state) =>
PlantDiagnosesScreen(plantId: state.pathParameters['id']!),
),
GoRoute(
path: AppRoutes.locations,
builder: (context, state) => const LocationsScreen(),
),
GoRoute(
path: '/locations/:id',
builder: (context, state) =>
LocationDetailScreen(locationId: state.pathParameters['id']!),
),
GoRoute(
path: AppRoutes.household,
builder: (context, state) => const HouseholdScreen(),
),
GoRoute(
path: AppRoutes.settings,
builder: (context, state) => const SettingsScreen(),
),
],
);
ref.onDispose(router.dispose);
return router;
});