checkpoint

This commit is contained in:
2025-11-25 17:05:08 -05:00
parent bbcd6d9bf7
commit d46ac9dc14
17 changed files with 705 additions and 193 deletions
+111 -1
View File
@@ -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
View File
@@ -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(