Files
worker/lib/app.dart
Phuoc Nguyen 628c81ce13 runable
2025-10-17 17:22:28 +07:00

354 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:worker/core/theme/app_theme.dart';
import 'package:worker/generated/l10n/app_localizations.dart';
/// Root application widget for Worker Mobile App
///
/// This is the main app widget that:
/// - Sets up Material 3 theme configuration
/// - Configures localization for Vietnamese and English
/// - Provides router configuration (to be implemented)
/// - Integrates with Riverpod for state management
/// - Handles app-level error states
class WorkerApp extends ConsumerWidget {
const WorkerApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
// ==================== App Configuration ====================
debugShowCheckedModeBanner: false,
title: 'Worker App',
// ==================== Theme Configuration ====================
// Material 3 theme with brand colors (Primary Blue: #005B9A)
theme: AppTheme.lightTheme(),
darkTheme: AppTheme.darkTheme(),
themeMode: ThemeMode.light, // TODO: Make this configurable from settings
// ==================== Localization Configuration ====================
// Support for Vietnamese (primary) and English (secondary)
localizationsDelegates: const [
// App-specific localizations
AppLocalizations.delegate,
// Material Design localizations
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
// Supported locales
supportedLocales: const [
Locale('vi', 'VN'), // Vietnamese (primary)
Locale('en', 'US'), // English (secondary)
],
// Default locale (Vietnamese)
locale: const Locale('vi', 'VN'), // TODO: Make this configurable from settings
// Locale resolution strategy
localeResolutionCallback: (locale, supportedLocales) {
// Check if the device locale is supported
for (final supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale?.languageCode) {
return supportedLocale;
}
}
// If device locale is not supported, default to Vietnamese
return const Locale('vi', 'VN');
},
// ==================== Navigation Configuration ====================
// TODO: Replace with actual router configuration when navigation is implemented
// Options:
// 1. Use go_router for declarative routing
// 2. Use Navigator 2.0 for imperative routing
// 3. Use auto_route for type-safe routing
//
// For now, we use a placeholder home screen
home: const _PlaceholderHomePage(),
// Alternative: Use onGenerateRoute for custom routing
// onGenerateRoute: (settings) {
// return AppRouter.onGenerateRoute(settings);
// },
// ==================== Material App Configuration ====================
// Builder for additional context-dependent widgets
builder: (context, child) {
return _AppBuilder(
child: child ?? const SizedBox.shrink(),
);
},
);
}
}
/// App builder widget
///
/// Wraps the entire app with additional widgets:
/// - Error boundary
/// - Connectivity listener
/// - Global overlays (loading, snackbars)
class _AppBuilder extends ConsumerWidget {
const _AppBuilder({
required this.child,
});
final Widget child;
@override
Widget build(BuildContext context, WidgetRef ref) {
// TODO: Add connectivity listener
// final connectivity = ref.watch(connectivityProvider);
// TODO: Add global loading state
// final isLoading = ref.watch(globalLoadingProvider);
return Stack(
children: [
// Main app content
child,
// TODO: Add global loading overlay
// if (isLoading)
// const _GlobalLoadingOverlay(),
// TODO: Add connectivity banner
// if (connectivity == ConnectivityStatus.offline)
// const _OfflineBanner(),
],
);
}
}
/// Placeholder home page
///
/// This is a temporary home screen that will be replaced with the actual
/// home page implementation from features/home/presentation/pages/home_page.dart
///
/// The actual home page will include:
/// - Membership card display (Diamond/Platinum/Gold tiers)
/// - Quick action grid
/// - Bottom navigation bar
/// - Floating action button for chat
class _PlaceholderHomePage extends ConsumerWidget {
const _PlaceholderHomePage();
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);
return Scaffold(
appBar: AppBar(
title: const Text('Worker App'),
centerTitle: true,
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// App logo placeholder
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
color: theme.colorScheme.primary,
borderRadius: BorderRadius.circular(24),
),
child: Icon(
Icons.business_center,
size: 64,
color: theme.colorScheme.onPrimary,
),
),
const SizedBox(height: 32),
// Welcome text
Text(
'Chào mừng đến với Worker App',
style: theme.textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.bold,
color: theme.colorScheme.onSurface,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
// Description
Text(
'Ứng dụng dành cho thầu thợ, kiến trúc sư, đại lý và môi giới',
style: theme.textTheme.bodyLarge?.copyWith(
color: theme.colorScheme.onSurface.withValues(alpha: 0.7),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 48),
// Status indicators
const _StatusIndicator(
icon: Icons.check_circle,
color: Colors.green,
label: 'Hive Database: Initialized',
),
const SizedBox(height: 12),
const _StatusIndicator(
icon: Icons.check_circle,
color: Colors.green,
label: 'Riverpod: Active',
),
const SizedBox(height: 12),
const _StatusIndicator(
icon: Icons.check_circle,
color: Colors.green,
label: 'Material 3 Theme: Loaded',
),
const SizedBox(height: 48),
// Next steps card
Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.info_outline,
color: theme.colorScheme.primary,
),
const SizedBox(width: 12),
Text(
'Next Steps',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 16),
const _NextStepItem(
number: '1',
text: 'Implement authentication flow',
),
const SizedBox(height: 8),
const _NextStepItem(
number: '2',
text: 'Create home page with membership cards',
),
const SizedBox(height: 8),
const _NextStepItem(
number: '3',
text: 'Set up navigation and routing',
),
const SizedBox(height: 8),
const _NextStepItem(
number: '4',
text: 'Implement feature modules',
),
],
),
),
),
],
),
),
),
// Floating action button (will be used for chat)
floatingActionButton: FloatingActionButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Chat feature coming soon!'),
behavior: SnackBarBehavior.floating,
),
);
},
child: const Icon(Icons.chat_bubble_outline),
),
);
}
}
/// Status indicator widget
class _StatusIndicator extends StatelessWidget {
const _StatusIndicator({
required this.icon,
required this.color,
required this.label,
});
final IconData icon;
final Color color;
final String label;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: color, size: 20),
const SizedBox(width: 8),
Text(
label,
style: Theme.of(context).textTheme.bodyMedium,
),
],
);
}
}
/// Next step item widget
class _NextStepItem extends StatelessWidget {
const _NextStepItem({
required this.number,
required this.text,
});
final String number;
final String text;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Row(
children: [
Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: theme.colorScheme.primary.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Text(
number,
style: theme.textTheme.labelSmall?.copyWith(
color: theme.colorScheme.primary,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
text,
style: theme.textTheme.bodyMedium,
),
),
],
);
}
}