ionic-planb-logistic-app-fl.../lib/components/map_sidebar_layout.dart
Jean-Philippe Brule dc9282e2c7 Improve map navigation UI and add collapsible deliveries sidebar
Changes:
- Remove zoom controls (+ and - buttons) from map navigation
- Remove duplicate delivery info from top of delivery page
- Add collapsible sidebar to map layout with smooth animations
- Sidebar collapses to 64px width when not expanded
- Expanded sidebar shows 280px width with delivery list
- Added "Deliveries" header with animated chevron toggle button
- Updated dark mode styling for collapsible header
- Frees up more space for map navigation window

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 12:20:40 -05:00

138 lines
4.1 KiB
Dart

import 'package:flutter/material.dart';
import '../utils/breakpoints.dart';
import '../theme/spacing_system.dart';
import '../theme/size_system.dart';
import '../theme/animation_system.dart';
import '../theme/color_system.dart';
class MapSidebarLayout extends StatefulWidget {
final Widget mapWidget;
final Widget sidebarWidget;
final double mapRatio;
const MapSidebarLayout({
super.key,
required this.mapWidget,
required this.sidebarWidget,
this.mapRatio = 2 / 3,
});
@override
State<MapSidebarLayout> createState() => _MapSidebarLayoutState();
}
class _MapSidebarLayoutState extends State<MapSidebarLayout>
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 = MediaQuery.of(context).size.width < Breakpoints.tablet;
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
if (isMobile) {
return widget.sidebarWidget;
}
// Desktop: Show map with collapsible sidebar
return Row(
children: [
Expanded(
flex: (widget.mapRatio * 100).toInt(),
child: widget.mapWidget,
),
// Collapsible sidebar with toggle button
AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: _isExpanded ? 280 : 64,
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(
'Deliveries',
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,
),
),
],
),
),
// Sidebar content
Expanded(
child: _isExpanded ? widget.sidebarWidget : const SizedBox.shrink(),
),
],
),
),
],
);
}
}