import 'package:flutter/material.dart'; import '../models/delivery_route.dart'; import '../theme/spacing_system.dart'; import '../theme/size_system.dart'; import '../theme/animation_system.dart'; import '../theme/color_system.dart'; import '../utils/breakpoints.dart'; import 'route_list_item.dart'; class CollapsibleRoutesSidebar extends StatefulWidget { final List routes; final DeliveryRoute? selectedRoute; final ValueChanged onRouteSelected; const CollapsibleRoutesSidebar({ super.key, required this.routes, this.selectedRoute, required this.onRouteSelected, }); @override State createState() => _CollapsibleRoutesSidebarState(); } class _CollapsibleRoutesSidebarState extends State with SingleTickerProviderStateMixin { late AnimationController _animationController; bool _isExpanded = true; @override void initState() { super.initState(); _animationController = AnimationController( duration: const Duration(milliseconds: 300), vsync: this, ); if (_isExpanded) { _animationController.forward(); } } @override void dispose() { _animationController.dispose(); super.dispose(); } void _toggleSidebar() { setState(() { _isExpanded = !_isExpanded; }); if (_isExpanded) { _animationController.forward(); } else { _animationController.reverse(); } } @override Widget build(BuildContext context) { final isMobile = context.isMobile; final isDarkMode = Theme.of(context).brightness == Brightness.dark; // On mobile, always show as collapsible if (isMobile) { return Container( color: isDarkMode ? SvrntyColors.almostBlack : Colors.white, child: Column( children: [ // Header with toggle button Container( padding: EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: isDarkMode ? SvrntyColors.darkSlate : SvrntyColors.slateGray.withValues(alpha: 0.2), width: 1, ), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (_isExpanded) Text( 'Routes', style: Theme.of(context).textTheme.titleMedium, ), IconButton( icon: AnimatedRotation( turns: _isExpanded ? 0 : -0.25, duration: Duration( milliseconds: AppAnimations.durationFast.inMilliseconds, ), child: const Icon(Icons.chevron_right), ), onPressed: _toggleSidebar, iconSize: AppSizes.iconMd, ), ], ), ), // Collapsible content if (_isExpanded) Expanded( child: _buildRoutesList(context), ), ], ), ); } // On tablet/desktop, show full sidebar with toggle (expanded: 420px, collapsed: 80px for badge) return Container( width: _isExpanded ? 420 : 80, color: isDarkMode ? SvrntyColors.almostBlack : Colors.white, child: Column( children: [ // Header with toggle button Container( height: kToolbarHeight, padding: EdgeInsets.symmetric(horizontal: AppSpacing.xs), decoration: BoxDecoration( border: Border( left: BorderSide( color: isDarkMode ? SvrntyColors.darkSlate : SvrntyColors.slateGray.withValues(alpha: 0.2), width: 1, ), ), ), child: Row( mainAxisAlignment: _isExpanded ? MainAxisAlignment.spaceBetween : MainAxisAlignment.center, children: [ if (_isExpanded) Expanded( child: Text( 'Routes', style: Theme.of(context).textTheme.titleMedium, overflow: TextOverflow.ellipsis, ), ), SizedBox( width: AppSizes.buttonHeightMd, height: AppSizes.buttonHeightMd, child: IconButton( icon: AnimatedRotation( turns: _isExpanded ? 0 : -0.5, duration: Duration( milliseconds: AppAnimations.durationFast.inMilliseconds, ), child: const Icon(Icons.chevron_right), ), onPressed: _toggleSidebar, iconSize: AppSizes.iconMd, ), ), ], ), ), // Routes list Expanded( child: _buildRoutesList(context), ), ], ), ); } Widget _buildRoutesList(BuildContext context) { return ListView.builder( padding: const EdgeInsets.only(top: 4, bottom: 8), physics: const AlwaysScrollableScrollPhysics(), itemCount: widget.routes.length, itemBuilder: (context, index) { final route = widget.routes[index]; final isSelected = widget.selectedRoute?.id == route.id; return RouteListItem( route: route, isSelected: isSelected, onTap: () => widget.onRouteSelected(route), animationIndex: index, isCollapsed: !_isExpanded, ); }, ); } }