ionic-planb-logistic-app-fl.../lib/utils/breakpoints.dart
Claude Code 4b03e9aba5 Initial commit: Plan B Logistics Flutter app with dark mode and responsive design
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>
2025-10-31 04:58:10 -04:00

169 lines
4.1 KiB
Dart

library;
import 'package:flutter/material.dart';
enum DeviceType {
mobile,
tablet,
desktop,
}
class Breakpoints {
Breakpoints._();
static const double mobile = 600;
static const double tablet = 1024;
static const double desktop = 1024;
static const double mobileSmall = 360;
static const double mobileLarge = 480;
static const double tabletSmall = 600;
static const double tabletLarge = 840;
static const double desktopSmall = 1024;
static const double desktopMedium = 1440;
static const double desktopLarge = 1920;
static const double desktopUltra = 2560;
static DeviceType getDeviceType(BuildContext context) {
final double width = MediaQuery.of(context).size.width;
return getDeviceTypeFromWidth(width);
}
static DeviceType getDeviceTypeFromWidth(double width) {
if (width < mobile) {
return DeviceType.mobile;
} else if (width < desktop) {
return DeviceType.tablet;
} else {
return DeviceType.desktop;
}
}
static bool isMobile(BuildContext context) {
return getDeviceType(context) == DeviceType.mobile;
}
static bool isTablet(BuildContext context) {
return getDeviceType(context) == DeviceType.tablet;
}
static bool isDesktop(BuildContext context) {
return getDeviceType(context) == DeviceType.desktop;
}
static bool isTabletOrLarger(BuildContext context) {
final DeviceType type = getDeviceType(context);
return type == DeviceType.tablet || type == DeviceType.desktop;
}
static bool isMobileOrTablet(BuildContext context) {
final DeviceType type = getDeviceType(context);
return type == DeviceType.mobile || type == DeviceType.tablet;
}
static T adaptive<T>({
required BuildContext context,
required T mobile,
T? tablet,
T? desktop,
}) {
final DeviceType deviceType = getDeviceType(context);
switch (deviceType) {
case DeviceType.mobile:
return mobile;
case DeviceType.tablet:
return tablet ?? mobile;
case DeviceType.desktop:
return desktop ?? tablet ?? mobile;
}
}
static int getGridColumns(BuildContext context) {
final double width = MediaQuery.of(context).size.width;
if (width < mobileSmall) {
return 1;
} else if (width < mobileLarge) {
return 2;
} else if (width < tabletSmall) {
return 3;
} else if (width < tabletLarge) {
return 4;
} else if (width < desktopSmall) {
return 6;
} else if (width < desktopMedium) {
return 8;
} else {
return 12;
}
}
static EdgeInsets getAdaptivePadding(BuildContext context) {
return adaptive<EdgeInsets>(
context: context,
mobile: const EdgeInsets.all(16),
tablet: const EdgeInsets.all(24),
desktop: const EdgeInsets.all(32),
);
}
static EdgeInsets getHorizontalPadding(BuildContext context) {
return adaptive<EdgeInsets>(
context: context,
mobile: const EdgeInsets.symmetric(horizontal: 16),
tablet: const EdgeInsets.symmetric(horizontal: 32),
desktop: const EdgeInsets.symmetric(horizontal: 48),
);
}
static double getSpacing(BuildContext context) {
return adaptive<double>(
context: context,
mobile: 8,
tablet: 12,
desktop: 16,
);
}
static double getFontScale(BuildContext context) {
return adaptive<double>(
context: context,
mobile: 1.0,
tablet: 1.1,
desktop: 1.0,
);
}
}
extension ResponsiveContext on BuildContext {
DeviceType get deviceType => Breakpoints.getDeviceType(this);
bool get isMobile => Breakpoints.isMobile(this);
bool get isTablet => Breakpoints.isTablet(this);
bool get isDesktop => Breakpoints.isDesktop(this);
bool get isTabletOrLarger => Breakpoints.isTabletOrLarger(this);
bool get isMobileOrTablet => Breakpoints.isMobileOrTablet(this);
double get screenWidth => MediaQuery.of(this).size.width;
double get screenHeight => MediaQuery.of(this).size.height;
T adaptive<T>({
required T mobile,
T? tablet,
T? desktop,
}) {
return Breakpoints.adaptive<T>(
context: this,
mobile: mobile,
tablet: tablet,
desktop: desktop,
);
}
}