Implements complete refactor of Ionic Angular logistics app to Flutter/Dart with: - Svrnty dark mode console theme (Material Design 3) - Responsive layouts (mobile, tablet, desktop) following FRONTEND standards - CQRS API integration with Result<T> error handling - OAuth2/OIDC authentication support (mocked for initial testing) - Delivery route and delivery management features - Multi-language support (EN/FR) with i18n - Native integrations (camera, phone calls, maps) - Strict typing throughout codebase - Mock data for UI testing without backend Follows all FRONTEND style guides, design patterns, and conventions. App is running in dark mode and fully responsive across all device sizes. Co-Authored-By: Claude <noreply@anthropic.com>
409 lines
15 KiB
Dart
409 lines
15 KiB
Dart
import "package:flutter/material.dart";
|
|
|
|
class MaterialTheme {
|
|
final TextTheme textTheme;
|
|
|
|
const MaterialTheme(this.textTheme);
|
|
|
|
// Svrnty Brand Colors - Light Theme
|
|
static ColorScheme lightScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.light,
|
|
primary: Color(0xffC44D58), // Svrnty Crimson Red
|
|
surfaceTint: Color(0xffC44D58),
|
|
onPrimary: Color(0xffffffff),
|
|
primaryContainer: Color(0xffffd8db),
|
|
onPrimaryContainer: Color(0xff8b3238),
|
|
secondary: Color(0xff475C6C), // Svrnty Slate Blue
|
|
onSecondary: Color(0xffffffff),
|
|
secondaryContainer: Color(0xffd1dce7),
|
|
onSecondaryContainer: Color(0xff2e3d4a),
|
|
tertiary: Color(0xff5a4a6c),
|
|
onTertiary: Color(0xffffffff),
|
|
tertiaryContainer: Color(0xffe0d3f2),
|
|
onTertiaryContainer: Color(0xff3d2f4d),
|
|
error: Color(0xffba1a1a),
|
|
onError: Color(0xffffffff),
|
|
errorContainer: Color(0xffffdad6),
|
|
onErrorContainer: Color(0xff93000a),
|
|
surface: Color(0xfffafafa),
|
|
onSurface: Color(0xff1a1c1e),
|
|
onSurfaceVariant: Color(0xff43474e),
|
|
outline: Color(0xff74777f),
|
|
outlineVariant: Color(0xffc4c6cf),
|
|
shadow: Color(0xff000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xff2f3033),
|
|
inversePrimary: Color(0xffffb3b9),
|
|
primaryFixed: Color(0xffffd8db),
|
|
onPrimaryFixed: Color(0xff410008),
|
|
primaryFixedDim: Color(0xffffb3b9),
|
|
onPrimaryFixedVariant: Color(0xff8b3238),
|
|
secondaryFixed: Color(0xffd1dce7),
|
|
onSecondaryFixed: Color(0xff0f1a24),
|
|
secondaryFixedDim: Color(0xffb5c0cb),
|
|
onSecondaryFixedVariant: Color(0xff2e3d4a),
|
|
tertiaryFixed: Color(0xffe0d3f2),
|
|
onTertiaryFixed: Color(0xff1f122f),
|
|
tertiaryFixedDim: Color(0xffc4b7d6),
|
|
onTertiaryFixedVariant: Color(0xff3d2f4d),
|
|
surfaceDim: Color(0xffdadcde),
|
|
surfaceBright: Color(0xfffafafa),
|
|
surfaceContainerLowest: Color(0xffffffff),
|
|
surfaceContainerLow: Color(0xfff4f5f7),
|
|
surfaceContainer: Color(0xffeef0f2),
|
|
surfaceContainerHigh: Color(0xffe8eaec),
|
|
surfaceContainerHighest: Color(0xffe2e4e7),
|
|
);
|
|
}
|
|
|
|
ThemeData light() {
|
|
return theme(lightScheme());
|
|
}
|
|
|
|
static ColorScheme lightMediumContrastScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.light,
|
|
primary: Color(0xff0d3665),
|
|
surfaceTint: Color(0xff3d5f90),
|
|
onPrimary: Color(0xffffffff),
|
|
primaryContainer: Color(0xff4d6ea0),
|
|
onPrimaryContainer: Color(0xffffffff),
|
|
secondary: Color(0xff2d3747),
|
|
onSecondary: Color(0xffffffff),
|
|
secondaryContainer: Color(0xff636d80),
|
|
onSecondaryContainer: Color(0xffffffff),
|
|
tertiary: Color(0xff442e4c),
|
|
onTertiary: Color(0xffffffff),
|
|
tertiaryContainer: Color(0xff7d6485),
|
|
onTertiaryContainer: Color(0xffffffff),
|
|
error: Color(0xff740006),
|
|
onError: Color(0xffffffff),
|
|
errorContainer: Color(0xffcf2c27),
|
|
onErrorContainer: Color(0xffffffff),
|
|
surface: Color(0xfff9f9ff),
|
|
onSurface: Color(0xff0f1116),
|
|
onSurfaceVariant: Color(0xff33363d),
|
|
outline: Color(0xff4f525a),
|
|
outlineVariant: Color(0xff6a6d75),
|
|
shadow: Color(0xff000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xff2e3035),
|
|
inversePrimary: Color(0xffa6c8ff),
|
|
primaryFixed: Color(0xff4d6ea0),
|
|
onPrimaryFixed: Color(0xffffffff),
|
|
primaryFixedDim: Color(0xff335686),
|
|
onPrimaryFixedVariant: Color(0xffffffff),
|
|
secondaryFixed: Color(0xff636d80),
|
|
onSecondaryFixed: Color(0xffffffff),
|
|
secondaryFixedDim: Color(0xff4b5567),
|
|
onSecondaryFixedVariant: Color(0xffffffff),
|
|
tertiaryFixed: Color(0xff7d6485),
|
|
onTertiaryFixed: Color(0xffffffff),
|
|
tertiaryFixedDim: Color(0xff644c6c),
|
|
onTertiaryFixedVariant: Color(0xffffffff),
|
|
surfaceDim: Color(0xffc5c6cd),
|
|
surfaceBright: Color(0xfff9f9ff),
|
|
surfaceContainerLowest: Color(0xffffffff),
|
|
surfaceContainerLow: Color(0xfff3f3fa),
|
|
surfaceContainer: Color(0xffe7e8ee),
|
|
surfaceContainerHigh: Color(0xffdcdce3),
|
|
surfaceContainerHighest: Color(0xffd0d1d8),
|
|
);
|
|
}
|
|
|
|
ThemeData lightMediumContrast() {
|
|
return theme(lightMediumContrastScheme());
|
|
}
|
|
|
|
static ColorScheme lightHighContrastScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.light,
|
|
primary: Color(0xff002c58),
|
|
surfaceTint: Color(0xff3d5f90),
|
|
onPrimary: Color(0xffffffff),
|
|
primaryContainer: Color(0xff264a79),
|
|
onPrimaryContainer: Color(0xffffffff),
|
|
secondary: Color(0xff232d3d),
|
|
onSecondary: Color(0xffffffff),
|
|
secondaryContainer: Color(0xff404a5b),
|
|
onSecondaryContainer: Color(0xffffffff),
|
|
tertiary: Color(0xff392441),
|
|
onTertiary: Color(0xffffffff),
|
|
tertiaryContainer: Color(0xff584160),
|
|
onTertiaryContainer: Color(0xffffffff),
|
|
error: Color(0xff600004),
|
|
onError: Color(0xffffffff),
|
|
errorContainer: Color(0xff98000a),
|
|
onErrorContainer: Color(0xffffffff),
|
|
surface: Color(0xfff9f9ff),
|
|
onSurface: Color(0xff000000),
|
|
onSurfaceVariant: Color(0xff000000),
|
|
outline: Color(0xff292c33),
|
|
outlineVariant: Color(0xff464951),
|
|
shadow: Color(0xff000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xff2e3035),
|
|
inversePrimary: Color(0xffa6c8ff),
|
|
primaryFixed: Color(0xff264a79),
|
|
onPrimaryFixed: Color(0xffffffff),
|
|
primaryFixedDim: Color(0xff063361),
|
|
onPrimaryFixedVariant: Color(0xffffffff),
|
|
secondaryFixed: Color(0xff404a5b),
|
|
onSecondaryFixed: Color(0xffffffff),
|
|
secondaryFixedDim: Color(0xff293343),
|
|
onSecondaryFixedVariant: Color(0xffffffff),
|
|
tertiaryFixed: Color(0xff584160),
|
|
onTertiaryFixed: Color(0xffffffff),
|
|
tertiaryFixedDim: Color(0xff402b48),
|
|
onTertiaryFixedVariant: Color(0xffffffff),
|
|
surfaceDim: Color(0xffb7b8bf),
|
|
surfaceBright: Color(0xfff9f9ff),
|
|
surfaceContainerLowest: Color(0xffffffff),
|
|
surfaceContainerLow: Color(0xfff0f0f7),
|
|
surfaceContainer: Color(0xffe1e2e9),
|
|
surfaceContainerHigh: Color(0xffd3d4da),
|
|
surfaceContainerHighest: Color(0xffc5c6cd),
|
|
);
|
|
}
|
|
|
|
ThemeData lightHighContrast() {
|
|
return theme(lightHighContrastScheme());
|
|
}
|
|
|
|
// Svrnty Brand Colors - Dark Theme (Bold & Saturated)
|
|
static ColorScheme darkScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.dark,
|
|
primary: Color(0xffF3574E), // Bold Svrnty Crimson Red (slightly desaturated)
|
|
surfaceTint: Color(0xffF3574E),
|
|
onPrimary: Color(0xffffffff),
|
|
primaryContainer: Color(0xffC44D58), // True brand crimson
|
|
onPrimaryContainer: Color(0xffffffff),
|
|
secondary: Color(0xff5A6F7D), // Rich Svrnty Slate Blue
|
|
onSecondary: Color(0xffffffff),
|
|
secondaryContainer: Color(0xff475C6C), // True brand slate
|
|
onSecondaryContainer: Color(0xffffffff),
|
|
tertiary: Color(0xffA78BBF), // Richer purple
|
|
onTertiary: Color(0xffffffff),
|
|
tertiaryContainer: Color(0xff8B6FA3),
|
|
onTertiaryContainer: Color(0xffffffff),
|
|
error: Color(0xffFF5449),
|
|
onError: Color(0xffffffff),
|
|
errorContainer: Color(0xffD32F2F),
|
|
onErrorContainer: Color(0xffffffff),
|
|
surface: Color(0xff1a1c1e), // Svrnty Dark Background
|
|
onSurface: Color(0xfff0f0f0),
|
|
onSurfaceVariant: Color(0xffc8cad0),
|
|
outline: Color(0xff8d9199),
|
|
outlineVariant: Color(0xff43474e),
|
|
shadow: Color(0xff000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xffe2e4e7),
|
|
inversePrimary: Color(0xffC44D58),
|
|
primaryFixed: Color(0xffFFD8DB),
|
|
onPrimaryFixed: Color(0xff2d0008),
|
|
primaryFixedDim: Color(0xffF3574E),
|
|
onPrimaryFixedVariant: Color(0xffffffff),
|
|
secondaryFixed: Color(0xffD1DCE7),
|
|
onSecondaryFixed: Color(0xff0f1a24),
|
|
secondaryFixedDim: Color(0xff5A6F7D),
|
|
onSecondaryFixedVariant: Color(0xffffffff),
|
|
tertiaryFixed: Color(0xffE0D3F2),
|
|
onTertiaryFixed: Color(0xff1f122f),
|
|
tertiaryFixedDim: Color(0xffA78BBF),
|
|
onTertiaryFixedVariant: Color(0xffffffff),
|
|
surfaceDim: Color(0xff1a1c1e),
|
|
surfaceBright: Color(0xff404244),
|
|
surfaceContainerLowest: Color(0xff0f1113),
|
|
surfaceContainerLow: Color(0xff1f2123),
|
|
surfaceContainer: Color(0xff23252a),
|
|
surfaceContainerHigh: Color(0xff2d2f35),
|
|
surfaceContainerHighest: Color(0xff383940),
|
|
);
|
|
}
|
|
|
|
ThemeData dark() {
|
|
return theme(darkScheme());
|
|
}
|
|
|
|
static ColorScheme darkMediumContrastScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.dark,
|
|
primary: Color(0xffcbddff),
|
|
surfaceTint: Color(0xffa6c8ff),
|
|
onPrimary: Color(0xff00264d),
|
|
primaryContainer: Color(0xff7192c6),
|
|
onPrimaryContainer: Color(0xff000000),
|
|
secondary: Color(0xffd3ddf2),
|
|
onSecondary: Color(0xff1c2636),
|
|
secondaryContainer: Color(0xff8791a5),
|
|
onSecondaryContainer: Color(0xff000000),
|
|
tertiary: Color(0xfff1d2f8),
|
|
onTertiary: Color(0xff321e3a),
|
|
tertiaryContainer: Color(0xffa387aa),
|
|
onTertiaryContainer: Color(0xff000000),
|
|
error: Color(0xffffd2cc),
|
|
onError: Color(0xff540003),
|
|
errorContainer: Color(0xffff5449),
|
|
onErrorContainer: Color(0xff000000),
|
|
surface: Color(0xff111318),
|
|
onSurface: Color(0xffffffff),
|
|
onSurfaceVariant: Color(0xffdadce5),
|
|
outline: Color(0xffafb2bb),
|
|
outlineVariant: Color(0xff8d9099),
|
|
shadow: Color(0xff000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xffe1e2e9),
|
|
inversePrimary: Color(0xff254978),
|
|
primaryFixed: Color(0xffd5e3ff),
|
|
onPrimaryFixed: Color(0xff001129),
|
|
primaryFixedDim: Color(0xffa6c8ff),
|
|
onPrimaryFixedVariant: Color(0xff0d3665),
|
|
secondaryFixed: Color(0xffd9e3f8),
|
|
onSecondaryFixed: Color(0xff071120),
|
|
secondaryFixedDim: Color(0xffbdc7dc),
|
|
onSecondaryFixedVariant: Color(0xff2d3747),
|
|
tertiaryFixed: Color(0xfff8d8ff),
|
|
onTertiaryFixed: Color(0xff1c0924),
|
|
tertiaryFixedDim: Color(0xffdbbde2),
|
|
onTertiaryFixedVariant: Color(0xff442e4c),
|
|
surfaceDim: Color(0xff111318),
|
|
surfaceBright: Color(0xff42444a),
|
|
surfaceContainerLowest: Color(0xff05070c),
|
|
surfaceContainerLow: Color(0xff1b1e22),
|
|
surfaceContainer: Color(0xff26282d),
|
|
surfaceContainerHigh: Color(0xff303338),
|
|
surfaceContainerHighest: Color(0xff3b3e43),
|
|
);
|
|
}
|
|
|
|
ThemeData darkMediumContrast() {
|
|
return theme(darkMediumContrastScheme());
|
|
}
|
|
|
|
static ColorScheme darkHighContrastScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.dark,
|
|
primary: Color(0xffeaf0ff),
|
|
surfaceTint: Color(0xffa6c8ff),
|
|
onPrimary: Color(0xff000000),
|
|
primaryContainer: Color(0xffa3c4fb),
|
|
onPrimaryContainer: Color(0xff000b1e),
|
|
secondary: Color(0xffeaf0ff),
|
|
onSecondary: Color(0xff000000),
|
|
secondaryContainer: Color(0xffb9c3d8),
|
|
onSecondaryContainer: Color(0xff030b1a),
|
|
tertiary: Color(0xfffeeaff),
|
|
onTertiary: Color(0xff000000),
|
|
tertiaryContainer: Color(0xffd7b9de),
|
|
onTertiaryContainer: Color(0xff16041e),
|
|
error: Color(0xffffece9),
|
|
onError: Color(0xff000000),
|
|
errorContainer: Color(0xffffaea4),
|
|
onErrorContainer: Color(0xff220001),
|
|
surface: Color(0xff111318),
|
|
onSurface: Color(0xffffffff),
|
|
onSurfaceVariant: Color(0xffffffff),
|
|
outline: Color(0xffedf0f9),
|
|
outlineVariant: Color(0xffc0c2cb),
|
|
shadow: Color(0xff000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xffe1e2e9),
|
|
inversePrimary: Color(0xff254978),
|
|
primaryFixed: Color(0xffd5e3ff),
|
|
onPrimaryFixed: Color(0xff000000),
|
|
primaryFixedDim: Color(0xffa6c8ff),
|
|
onPrimaryFixedVariant: Color(0xff001129),
|
|
secondaryFixed: Color(0xffd9e3f8),
|
|
onSecondaryFixed: Color(0xff000000),
|
|
secondaryFixedDim: Color(0xffbdc7dc),
|
|
onSecondaryFixedVariant: Color(0xff071120),
|
|
tertiaryFixed: Color(0xfff8d8ff),
|
|
onTertiaryFixed: Color(0xff000000),
|
|
tertiaryFixedDim: Color(0xffdbbde2),
|
|
onTertiaryFixedVariant: Color(0xff1c0924),
|
|
surfaceDim: Color(0xff111318),
|
|
surfaceBright: Color(0xff4e5055),
|
|
surfaceContainerLowest: Color(0xff000000),
|
|
surfaceContainerLow: Color(0xff1d2024),
|
|
surfaceContainer: Color(0xff2e3035),
|
|
surfaceContainerHigh: Color(0xff393b41),
|
|
surfaceContainerHighest: Color(0xff45474c),
|
|
);
|
|
}
|
|
|
|
ThemeData darkHighContrast() {
|
|
return theme(darkHighContrastScheme());
|
|
}
|
|
|
|
|
|
ThemeData theme(ColorScheme colorScheme) => ThemeData(
|
|
useMaterial3: true,
|
|
brightness: colorScheme.brightness,
|
|
colorScheme: colorScheme,
|
|
textTheme: const TextTheme(
|
|
displayLarge: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.bold),
|
|
displayMedium: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.bold),
|
|
displaySmall: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.bold),
|
|
headlineLarge: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w600),
|
|
headlineMedium: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w600),
|
|
headlineSmall: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w600),
|
|
titleLarge: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w600),
|
|
titleMedium: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w500),
|
|
titleSmall: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w500),
|
|
bodyLarge: TextStyle(fontFamily: 'Montserrat'),
|
|
bodyMedium: TextStyle(fontFamily: 'Montserrat'),
|
|
bodySmall: TextStyle(fontFamily: 'Montserrat'),
|
|
labelLarge: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w500),
|
|
labelMedium: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w500),
|
|
labelSmall: TextStyle(fontFamily: 'Montserrat', fontWeight: FontWeight.w500),
|
|
).apply(
|
|
bodyColor: colorScheme.onSurface,
|
|
displayColor: colorScheme.onSurface,
|
|
),
|
|
fontFamily: 'Montserrat',
|
|
scaffoldBackgroundColor: colorScheme.surface,
|
|
canvasColor: colorScheme.surface,
|
|
);
|
|
|
|
|
|
List<ExtendedColor> get extendedColors => [
|
|
];
|
|
}
|
|
|
|
class ExtendedColor {
|
|
final Color seed, value;
|
|
final ColorFamily light;
|
|
final ColorFamily lightHighContrast;
|
|
final ColorFamily lightMediumContrast;
|
|
final ColorFamily dark;
|
|
final ColorFamily darkHighContrast;
|
|
final ColorFamily darkMediumContrast;
|
|
|
|
const ExtendedColor({
|
|
required this.seed,
|
|
required this.value,
|
|
required this.light,
|
|
required this.lightHighContrast,
|
|
required this.lightMediumContrast,
|
|
required this.dark,
|
|
required this.darkHighContrast,
|
|
required this.darkMediumContrast,
|
|
});
|
|
}
|
|
|
|
class ColorFamily {
|
|
const ColorFamily({
|
|
required this.color,
|
|
required this.onColor,
|
|
required this.colorContainer,
|
|
required this.onColorContainer,
|
|
});
|
|
|
|
final Color color;
|
|
final Color onColor;
|
|
final Color colorContainer;
|
|
final Color onColorContainer;
|
|
}
|