ionic-planb-logistic-app-fl.../lib/providers/providers.dart

182 lines
5.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/types.dart';
import '../api/client.dart';
import '../api/openapi_config.dart';
import '../services/auth_service.dart';
import '../models/user_profile.dart';
import '../models/delivery_route.dart';
import '../models/delivery.dart';
final authServiceProvider = Provider<AuthService>((ref) {
return AuthService(config: AuthConfig.development);
});
final apiClientProvider = Provider<CqrsApiClient>((ref) {
final authService = ref.watch(authServiceProvider);
return CqrsApiClient(
config: ApiClientConfig.development,
authService: authService,
);
});
final isAuthenticatedProvider = FutureProvider<bool>((ref) async {
final authService = ref.watch(authServiceProvider);
return await authService.isAuthenticated();
});
final userProfileProvider = FutureProvider<UserProfile?>((ref) async {
final authService = ref.watch(authServiceProvider);
final token = await authService.getToken();
if (token == null) return null;
return authService.decodeToken(token);
});
final authTokenProvider = FutureProvider<String?>((ref) async {
final authService = ref.watch(authServiceProvider);
return await authService.getToken();
});
final deliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) async {
final authService = ref.watch(authServiceProvider);
final isAuthenticated = await authService.isAuthenticated();
if (!isAuthenticated) {
throw Exception('User not authenticated');
}
// Create a new client with auth service for automatic token refresh
final authClient = CqrsApiClient(
config: ApiClientConfig.development,
authService: authService,
);
final result = await authClient.executeQuery<List<DeliveryRoute>>(
endpoint: 'simpleDeliveryRouteQueryItems',
query: _EmptyQuery(),
fromJson: (json) {
// API returns data wrapped in object with "data" field
if (json is Map<String, dynamic>) {
final data = json['data'];
if (data is List<dynamic>) {
return data.map((r) => DeliveryRoute.fromJson(r as Map<String, dynamic>)).toList();
}
}
return [];
},
);
return result.whenSuccess((routes) => routes) ?? [];
});
final deliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref, routeFragmentId) async {
final authService = ref.watch(authServiceProvider);
final isAuthenticated = await authService.isAuthenticated();
if (!isAuthenticated) {
throw Exception('User not authenticated');
}
final authClient = CqrsApiClient(
config: ApiClientConfig.development,
authService: authService,
);
final result = await authClient.executeQuery<List<Delivery>>(
endpoint: 'simpleDeliveriesQueryItems',
query: _DeliveriesQuery(routeFragmentId: routeFragmentId),
fromJson: (json) {
// API returns data wrapped in object with "data" field
if (json is Map<String, dynamic>) {
final data = json['data'];
if (data is List<dynamic>) {
return data.map((d) => Delivery.fromJson(d as Map<String, dynamic>)).toList();
}
}
return [];
},
);
return result.whenSuccess((deliveries) => deliveries) ?? [];
});
/// Provider to get all deliveries from all routes
final allDeliveriesProvider = FutureProvider<List<Delivery>>((ref) async {
final routes = await ref.read(deliveryRoutesProvider.future);
if (routes.isEmpty) {
return [];
}
// Fetch deliveries for all routes in parallel using Future.wait
final deliveriesFutures = routes.map((route) {
return ref.read(deliveriesProvider(route.id).future);
}).toList();
// Wait for all futures to complete
final deliveriesLists = await Future.wait(deliveriesFutures);
// Combine all deliveries into a single list
final allDeliveries = <Delivery>[];
for (final deliveries in deliveriesLists) {
allDeliveries.addAll(deliveries);
}
return allDeliveries;
});
// Language notifier for state management
class LanguageNotifier extends Notifier<String> {
@override
String build() => 'system';
void setLanguage(String lang) => state = lang;
}
final languageProvider = NotifierProvider<LanguageNotifier, String>(() {
return LanguageNotifier();
});
// Theme mode notifier for manual theme switching
class ThemeModeNotifier extends Notifier<ThemeMode> {
@override
ThemeMode build() => ThemeMode.dark;
void setThemeMode(ThemeMode mode) => state = mode;
}
final themeModeProvider = NotifierProvider<ThemeModeNotifier, ThemeMode>(() {
return ThemeModeNotifier();
});
// Collapse state notifier for sidebar persistence
class CollapseStateNotifier extends Notifier<bool> {
@override
bool build() => true; // Default: expanded
void toggle() => state = !state;
void setExpanded(bool expanded) => state = expanded;
}
final collapseStateProvider = NotifierProvider<CollapseStateNotifier, bool>(() {
return CollapseStateNotifier();
});
class _EmptyQuery implements Serializable {
@override
Map<String, Object?> toJson() => {};
}
class _DeliveriesQuery implements Serializable {
final int routeFragmentId;
_DeliveriesQuery({required this.routeFragmentId});
@override
Map<String, Object?> toJson() => {
'params': {
'routeFragmentId': routeFragmentId,
},
};
}