checkpoint
This commit is contained in:
@@ -13,11 +13,17 @@ import '../components/delivery_list_item.dart';
|
||||
class DeliveriesPage extends ConsumerStatefulWidget {
|
||||
final int routeFragmentId;
|
||||
final String routeName;
|
||||
final VoidCallback? onBack;
|
||||
final bool showAsEmbedded;
|
||||
final ValueChanged<Delivery?>? onDeliverySelected;
|
||||
|
||||
const DeliveriesPage({
|
||||
super.key,
|
||||
required this.routeFragmentId,
|
||||
required this.routeName,
|
||||
this.onBack,
|
||||
this.showAsEmbedded = false,
|
||||
this.onDeliverySelected,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -60,10 +66,114 @@ class _DeliveriesPageState extends ConsumerState<DeliveriesPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final deliveriesData = ref.watch(deliveriesProvider(widget.routeFragmentId));
|
||||
final routesData = ref.watch(deliveryRoutesProvider);
|
||||
final tokenAsync = ref.watch(authTokenProvider);
|
||||
final token = tokenAsync.hasValue ? tokenAsync.value : null;
|
||||
|
||||
// When embedded in sidebar, show only the delivery list with back button
|
||||
// This is a responsive sidebar that collapses like routes
|
||||
if (widget.showAsEmbedded) {
|
||||
final isExpanded = ref.watch(collapseStateProvider);
|
||||
|
||||
return deliveriesData.when(
|
||||
data: (deliveries) {
|
||||
// Auto-scroll to first pending delivery when page loads or route changes
|
||||
if (_lastRouteFragmentId != widget.routeFragmentId) {
|
||||
_lastRouteFragmentId = widget.routeFragmentId;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_autoScrollToFirstPending(deliveries);
|
||||
});
|
||||
}
|
||||
|
||||
// Responsive sidebar that changes width when collapsed (420px expanded, 80px collapsed)
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
width: isExpanded ? 420 : 80,
|
||||
child: Column(
|
||||
children: [
|
||||
// Header with back button
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isExpanded ? 12 : 8,
|
||||
vertical: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: isExpanded
|
||||
? MainAxisAlignment.start
|
||||
: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (isExpanded) ...[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: widget.onBack,
|
||||
tooltip: 'Back to routes',
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
widget.routeName,
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
IconButton(
|
||||
icon: Icon(isExpanded ? Icons.menu_open : Icons.menu),
|
||||
onPressed: () {
|
||||
ref.read(collapseStateProvider.notifier).toggle();
|
||||
},
|
||||
tooltip: isExpanded ? 'Collapse' : 'Expand',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Delivery list
|
||||
Expanded(
|
||||
child: UnifiedDeliveryListView(
|
||||
deliveries: deliveries,
|
||||
selectedDelivery: _selectedDelivery,
|
||||
scrollController: _listScrollController,
|
||||
onDeliverySelected: (delivery) {
|
||||
setState(() {
|
||||
_selectedDelivery = delivery;
|
||||
});
|
||||
// Notify parent about delivery selection
|
||||
widget.onDeliverySelected?.call(delivery);
|
||||
},
|
||||
onItemAction: (delivery, action) {
|
||||
_handleDeliveryAction(context, delivery, action, token);
|
||||
_autoScrollToFirstPending(deliveries);
|
||||
},
|
||||
isCollapsed: !isExpanded,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
error: (error, stackTrace) => Center(
|
||||
child: Text('Error: $error'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// When not embedded, show full page with map
|
||||
final routesData = ref.watch(deliveryRoutesProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.routeName),
|
||||
|
||||
+56
-45
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../models/delivery.dart';
|
||||
import '../models/delivery_route.dart';
|
||||
import '../providers/providers.dart';
|
||||
import '../utils/breakpoints.dart';
|
||||
@@ -18,6 +19,8 @@ class RoutesPage extends ConsumerStatefulWidget {
|
||||
|
||||
class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
late LocationPermissionService _permissionService;
|
||||
DeliveryRoute? _selectedRoute;
|
||||
Delivery? _selectedDelivery;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -51,15 +54,17 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
}
|
||||
}
|
||||
|
||||
void _navigateToDeliveries(BuildContext context, DeliveryRoute route) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => DeliveriesPage(
|
||||
routeFragmentId: route.id,
|
||||
routeName: route.name,
|
||||
),
|
||||
),
|
||||
);
|
||||
void _selectRoute(DeliveryRoute route) {
|
||||
setState(() {
|
||||
_selectedRoute = route;
|
||||
});
|
||||
}
|
||||
|
||||
void _backToRoutes() {
|
||||
setState(() {
|
||||
_selectedRoute = null;
|
||||
_selectedDelivery = null;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -73,6 +78,14 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
title: const Text('Delivery Routes'),
|
||||
elevation: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
ref.refresh(deliveryRoutesProvider);
|
||||
ref.refresh(allDeliveriesProvider);
|
||||
},
|
||||
tooltip: 'Refresh',
|
||||
),
|
||||
userProfile.when(
|
||||
data: (profile) => PopupMenuButton<String>(
|
||||
onSelected: (value) {
|
||||
@@ -134,43 +147,41 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
// ignore: unused_result
|
||||
ref.refresh(allDeliveriesProvider);
|
||||
},
|
||||
child: context.isDesktop
|
||||
? Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DarkModeMapComponent(
|
||||
deliveries: allDeliveries,
|
||||
selectedDelivery: null,
|
||||
onDeliverySelected: null,
|
||||
),
|
||||
),
|
||||
CollapsibleRoutesSidebar(
|
||||
routes: routes,
|
||||
selectedRoute: null,
|
||||
onRouteSelected: (route) {
|
||||
_navigateToDeliveries(context, route);
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DarkModeMapComponent(
|
||||
deliveries: allDeliveries,
|
||||
selectedDelivery: null,
|
||||
onDeliverySelected: null,
|
||||
),
|
||||
),
|
||||
CollapsibleRoutesSidebar(
|
||||
routes: routes,
|
||||
selectedRoute: null,
|
||||
onRouteSelected: (route) {
|
||||
_navigateToDeliveries(context, route);
|
||||
},
|
||||
),
|
||||
],
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DarkModeMapComponent(
|
||||
deliveries: allDeliveries,
|
||||
selectedDelivery: _selectedDelivery,
|
||||
onDeliverySelected: (delivery) {
|
||||
setState(() {
|
||||
_selectedDelivery = delivery;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
_selectedRoute == null
|
||||
? CollapsibleRoutesSidebar(
|
||||
routes: routes,
|
||||
selectedRoute: null,
|
||||
onRouteSelected: _selectRoute,
|
||||
)
|
||||
: SizedBox(
|
||||
width: 300,
|
||||
child: DeliveriesPage(
|
||||
routeFragmentId: _selectedRoute!.id,
|
||||
routeName: _selectedRoute!.name,
|
||||
onBack: _backToRoutes,
|
||||
showAsEmbedded: true,
|
||||
onDeliverySelected: (delivery) {
|
||||
setState(() {
|
||||
_selectedDelivery = delivery;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => const Center(
|
||||
|
||||
Reference in New Issue
Block a user