brand theme, allot of features, allot of bug fixes
This commit is contained in:
parent
2ecd1c5b4e
commit
8e6aa6ea8c
@ -78,7 +78,7 @@ class _CollapsibleRoutesSidebarState extends ConsumerState<CollapsibleRoutesSide
|
|||||||
// On mobile, always show as collapsible
|
// On mobile, always show as collapsible
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
return Container(
|
return Container(
|
||||||
color: isDarkMode ? SvrntyColors.almostBlack : Colors.white,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// Header with toggle button
|
// Header with toggle button
|
||||||
@ -125,7 +125,7 @@ class _CollapsibleRoutesSidebarState extends ConsumerState<CollapsibleRoutesSide
|
|||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
width: isExpanded ? 300 : 80,
|
width: isExpanded ? 300 : 80,
|
||||||
color: isDarkMode ? SvrntyColors.almostBlack : Colors.white,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// Header with toggle button
|
// Header with toggle button
|
||||||
|
|||||||
@ -578,37 +578,39 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
// Photo button
|
// Photo button (disabled when no delivery selected or warehouse delivery)
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildBottomActionButton(
|
child: _buildBottomActionButton(
|
||||||
label: 'Photo',
|
label: 'Photo',
|
||||||
icon: Icons.camera_alt,
|
icon: Icons.camera_alt,
|
||||||
onPressed: () => widget.onAction?.call('photo'),
|
onPressed: widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery
|
||||||
|
? () => widget.onAction?.call('photo')
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
// Note button (only enabled if delivery has notes)
|
// Note button (only enabled if delivery has notes and not warehouse)
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildBottomActionButton(
|
child: _buildBottomActionButton(
|
||||||
label: 'Note',
|
label: 'Note',
|
||||||
icon: Icons.note_add,
|
icon: Icons.note_add,
|
||||||
onPressed: _hasNotes()
|
onPressed: _hasNotes() && widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery
|
||||||
? () => widget.onAction?.call('note')
|
? () => widget.onAction?.call('note')
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
// Completed button
|
// Completed button (disabled for warehouse delivery)
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildBottomActionButton(
|
child: _buildBottomActionButton(
|
||||||
label: widget.selectedDelivery?.delivered == true ? 'Undo' : 'Completed',
|
label: widget.selectedDelivery?.delivered == true ? 'Undo' : 'Completed',
|
||||||
icon: widget.selectedDelivery?.delivered == true ? Icons.undo : Icons.check_circle,
|
icon: widget.selectedDelivery?.delivered == true ? Icons.undo : Icons.check_circle,
|
||||||
onPressed: widget.selectedDelivery != null
|
onPressed: widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery
|
||||||
? () => widget.onAction?.call(
|
? () => widget.onAction?.call(
|
||||||
widget.selectedDelivery!.delivered ? 'uncomplete' : 'complete',
|
widget.selectedDelivery!.delivered ? 'uncomplete' : 'complete',
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
isPrimary: widget.selectedDelivery != null && !widget.selectedDelivery!.delivered,
|
isPrimary: widget.selectedDelivery != null && !widget.selectedDelivery!.delivered && !widget.selectedDelivery!.isWarehouseDelivery,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -145,14 +145,20 @@ class _DeliveryListItemState extends State<DeliveryListItem>
|
|||||||
: [],
|
: [],
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: widget.delivery.isWarehouseDelivery
|
||||||
'${widget.delivery.deliveryIndex + 1}',
|
? const Icon(
|
||||||
style: const TextStyle(
|
Icons.warehouse,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 26,
|
size: 32,
|
||||||
fontWeight: FontWeight.w700,
|
)
|
||||||
),
|
: Text(
|
||||||
),
|
'${widget.delivery.deliveryIndex + 1}',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 26,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_hasNote())
|
if (_hasNote())
|
||||||
@ -254,14 +260,20 @@ class _DeliveryListItemState extends State<DeliveryListItem>
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: widget.delivery.isWarehouseDelivery
|
||||||
'${widget.delivery.deliveryIndex + 1}',
|
? const Icon(
|
||||||
style: const TextStyle(
|
Icons.warehouse,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 18,
|
size: 24,
|
||||||
fontWeight: FontWeight.w700,
|
)
|
||||||
),
|
: Text(
|
||||||
),
|
'${widget.delivery.deliveryIndex + 1}',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
|
|||||||
@ -36,6 +36,39 @@ class Delivery implements Serializable {
|
|||||||
required this.name,
|
required this.name,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Special warehouse ID constant
|
||||||
|
static const int warehouseDeliveryId = -1;
|
||||||
|
|
||||||
|
// Check if this is the warehouse delivery
|
||||||
|
bool get isWarehouseDelivery => id == warehouseDeliveryId;
|
||||||
|
|
||||||
|
// Create a static warehouse delivery item
|
||||||
|
static Delivery createWarehouseDelivery() {
|
||||||
|
return Delivery(
|
||||||
|
id: warehouseDeliveryId,
|
||||||
|
routeFragmentId: -1,
|
||||||
|
deliveryIndex: 999,
|
||||||
|
orders: const [],
|
||||||
|
deliveryAddress: const DeliveryAddress(
|
||||||
|
id: -1,
|
||||||
|
line1: '3550 Rue de Cherbourg Suite 108',
|
||||||
|
line2: '',
|
||||||
|
postalCode: 'G8Y 6S6',
|
||||||
|
city: 'Trois-Rivières',
|
||||||
|
subdivision: 'QC',
|
||||||
|
countryCode: 'CA',
|
||||||
|
latitude: 46.3384605,
|
||||||
|
longitude: -72.6080797,
|
||||||
|
formattedAddress: '3550 Rue de Cherbourg Suite 108, Trois-Rivières, QC G8Y 6S6',
|
||||||
|
),
|
||||||
|
createdAt: DateTime.now().toIso8601String(),
|
||||||
|
delivered: false,
|
||||||
|
hasBeenSkipped: false,
|
||||||
|
isSkipped: false,
|
||||||
|
name: 'Return to Warehouse',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
factory Delivery.fromJson(Map<String, dynamic> json) {
|
factory Delivery.fromJson(Map<String, dynamic> json) {
|
||||||
return Delivery(
|
return Delivery(
|
||||||
id: json['id'] as int,
|
id: json['id'] as int,
|
||||||
|
|||||||
@ -2,41 +2,41 @@ import '../api/types.dart';
|
|||||||
|
|
||||||
class DeliveryAddress implements Serializable {
|
class DeliveryAddress implements Serializable {
|
||||||
final int id;
|
final int id;
|
||||||
final String line1;
|
final String? line1;
|
||||||
final String line2;
|
final String? line2;
|
||||||
final String postalCode;
|
final String? postalCode;
|
||||||
final String city;
|
final String? city;
|
||||||
final String subdivision;
|
final String? subdivision;
|
||||||
final String countryCode;
|
final String? countryCode;
|
||||||
final double? latitude;
|
final double? latitude;
|
||||||
final double? longitude;
|
final double? longitude;
|
||||||
final String formattedAddress;
|
final String? formattedAddress;
|
||||||
|
|
||||||
const DeliveryAddress({
|
const DeliveryAddress({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.line1,
|
this.line1,
|
||||||
required this.line2,
|
this.line2,
|
||||||
required this.postalCode,
|
this.postalCode,
|
||||||
required this.city,
|
this.city,
|
||||||
required this.subdivision,
|
this.subdivision,
|
||||||
required this.countryCode,
|
this.countryCode,
|
||||||
this.latitude,
|
this.latitude,
|
||||||
this.longitude,
|
this.longitude,
|
||||||
required this.formattedAddress,
|
this.formattedAddress,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory DeliveryAddress.fromJson(Map<String, dynamic> json) {
|
factory DeliveryAddress.fromJson(Map<String, dynamic> json) {
|
||||||
return DeliveryAddress(
|
return DeliveryAddress(
|
||||||
id: json['id'] as int,
|
id: json['id'] as int,
|
||||||
line1: json['line1'] as String,
|
line1: json['line1'] as String?,
|
||||||
line2: json['line2'] as String,
|
line2: json['line2'] as String?,
|
||||||
postalCode: json['postalCode'] as String,
|
postalCode: json['postalCode'] as String?,
|
||||||
city: json['city'] as String,
|
city: json['city'] as String?,
|
||||||
subdivision: json['subdivision'] as String,
|
subdivision: json['subdivision'] as String?,
|
||||||
countryCode: json['countryCode'] as String,
|
countryCode: json['countryCode'] as String?,
|
||||||
latitude: json['latitude'] as double?,
|
latitude: json['latitude'] as double?,
|
||||||
longitude: json['longitude'] as double?,
|
longitude: json['longitude'] as double?,
|
||||||
formattedAddress: json['formattedAddress'] as String,
|
formattedAddress: json['formattedAddress'] as String?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -292,6 +292,11 @@ class _DeliveriesPageState extends ConsumerState<DeliveriesPage> {
|
|||||||
String action,
|
String action,
|
||||||
String? token,
|
String? token,
|
||||||
) async {
|
) async {
|
||||||
|
// Prevent any actions on warehouse delivery except map navigation
|
||||||
|
if (delivery.isWarehouseDelivery && action != 'map') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
ToastHelper.showError(context, l10n.authenticationRequired);
|
ToastHelper.showError(context, l10n.authenticationRequired);
|
||||||
@ -621,7 +626,7 @@ class DeliveryCard extends StatelessWidget {
|
|||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (delivery.deliveryAddress != null)
|
if (delivery.deliveryAddress != null)
|
||||||
Text(
|
Text(
|
||||||
delivery.deliveryAddress!.formattedAddress,
|
delivery.deliveryAddress!.formattedAddress ?? '',
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
|||||||
@ -520,6 +520,7 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(l10n.deliveryRoutes),
|
title: Text(l10n.deliveryRoutes),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
scrolledUnderElevation: 0,
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: (routesData.isLoading || allDeliveriesData.isLoading)
|
icon: (routesData.isLoading || allDeliveriesData.isLoading)
|
||||||
|
|||||||
@ -98,7 +98,18 @@ final deliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref, rout
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return result.whenSuccess((deliveries) => deliveries) ?? [];
|
// Log error if API call failed
|
||||||
|
result.whenError((error) {
|
||||||
|
print('ERROR fetching deliveries for route $routeFragmentId: ${error.message}');
|
||||||
|
if (error.originalException != null) {
|
||||||
|
print('Original exception: ${error.originalException}');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final deliveries = result.whenSuccess((deliveries) => deliveries) ?? [];
|
||||||
|
|
||||||
|
// Always append the warehouse delivery at the end
|
||||||
|
return [...deliveries, Delivery.createWarehouseDelivery()];
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Provider to get all deliveries from all routes
|
/// Provider to get all deliveries from all routes
|
||||||
|
|||||||
@ -177,7 +177,7 @@ class MaterialTheme {
|
|||||||
return const ColorScheme(
|
return const ColorScheme(
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
primary: Color(0xffDF2D45), // Svrnty Crimson Red
|
primary: Color(0xffDF2D45), // Svrnty Crimson Red
|
||||||
surfaceTint: Color(0xffFF6B7D),
|
surfaceTint: Color(0xff4ADE80), // Success Green tint
|
||||||
onPrimary: Color(0xffffffff),
|
onPrimary: Color(0xffffffff),
|
||||||
primaryContainer: Color(0xff9C1A29),
|
primaryContainer: Color(0xff9C1A29),
|
||||||
onPrimaryContainer: Color(0xffFFE0E5),
|
onPrimaryContainer: Color(0xffFFE0E5),
|
||||||
@ -185,15 +185,15 @@ class MaterialTheme {
|
|||||||
onSecondary: Color(0xffffffff),
|
onSecondary: Color(0xffffffff),
|
||||||
secondaryContainer: Color(0xff3A4958),
|
secondaryContainer: Color(0xff3A4958),
|
||||||
onSecondaryContainer: Color(0xffD0DCE8),
|
onSecondaryContainer: Color(0xffD0DCE8),
|
||||||
tertiary: Color(0xff5A8FA8), // Svrnty Teal variant
|
tertiary: Color(0xff4ADE80), // Svrnty Success Green - Light
|
||||||
onTertiary: Color(0xffffffff),
|
onTertiary: Color(0xff14532D), // Dark green for contrast
|
||||||
tertiaryContainer: Color(0xff1D2C39),
|
tertiaryContainer: Color(0xff15803D), // Svrnty Forest Dark Green
|
||||||
onTertiaryContainer: Color(0xffBFD5E3),
|
onTertiaryContainer: Color(0xffDCFCE7), // Light green tint
|
||||||
error: Color(0xffFF6B6B),
|
error: Color(0xffFF6B6B),
|
||||||
onError: Color(0xff4C0707),
|
onError: Color(0xff4C0707),
|
||||||
errorContainer: Color(0xff93000A),
|
errorContainer: Color(0xff93000A),
|
||||||
onErrorContainer: Color(0xffFEE2E2),
|
onErrorContainer: Color(0xffFEE2E2),
|
||||||
surface: Color(0xff0A0C10), // Svrnty Dark Background
|
surface: Color(0xff0C1410), // Svrnty Dark Green Background
|
||||||
onSurface: Color(0xffF0F0F2),
|
onSurface: Color(0xffF0F0F2),
|
||||||
onSurfaceVariant: Color(0xffBFC3C8),
|
onSurfaceVariant: Color(0xffBFC3C8),
|
||||||
outline: Color(0xff9CA3AF), // Enhanced contrast for dark mode
|
outline: Color(0xff9CA3AF), // Enhanced contrast for dark mode
|
||||||
@ -210,17 +210,17 @@ class MaterialTheme {
|
|||||||
onSecondaryFixed: Color(0xff06080C),
|
onSecondaryFixed: Color(0xff06080C),
|
||||||
secondaryFixedDim: Color(0xff506576),
|
secondaryFixedDim: Color(0xff506576),
|
||||||
onSecondaryFixedVariant: Color(0xff3A4958),
|
onSecondaryFixedVariant: Color(0xff3A4958),
|
||||||
tertiaryFixed: Color(0xffBFD5E3),
|
tertiaryFixed: Color(0xffDCFCE7), // Light green container
|
||||||
onTertiaryFixed: Color(0xff001219),
|
onTertiaryFixed: Color(0xff14532D), // Dark green text
|
||||||
tertiaryFixedDim: Color(0xff5A8FA8),
|
tertiaryFixedDim: Color(0xff4ADE80), // Success green
|
||||||
onTertiaryFixedVariant: Color(0xff1D2C39),
|
onTertiaryFixedVariant: Color(0xff15803D), // Forest green
|
||||||
surfaceDim: Color(0xff0A0C10),
|
surfaceDim: Color(0xff0A110E), // Darker forest green
|
||||||
surfaceBright: Color(0xff404244),
|
surfaceBright: Color(0xff1F2D25), // Brighter green tint
|
||||||
surfaceContainerLowest: Color(0xff040507),
|
surfaceContainerLowest: Color(0xff070D0A), // Deepest green
|
||||||
surfaceContainerLow: Color(0xff0F1114),
|
surfaceContainerLow: Color(0xff141B18), // Low green
|
||||||
surfaceContainer: Color(0xff14161A),
|
surfaceContainer: Color(0xff18221D), // Mid forest green
|
||||||
surfaceContainerHigh: Color(0xff1F2228),
|
surfaceContainerHigh: Color(0xff1D2822), // High green
|
||||||
surfaceContainerHighest: Color(0xff2A2D34),
|
surfaceContainerHighest: Color(0xff222F29), // Highest green tint
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
screenshot_forest_green_theme.png
Normal file
BIN
screenshot_forest_green_theme.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 309 KiB |
Loading…
Reference in New Issue
Block a user