hesabixArc/hesabixUI/hesabix_ui/lib/main.dart

741 lines
29 KiB
Dart
Raw Normal View History

2025-09-15 13:53:54 +03:30
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
2025-09-18 10:44:23 +03:30
import 'package:flutter_web_plugins/url_strategy.dart';
2025-09-25 01:18:59 +03:30
import 'l10n/app_localizations.dart';
2025-09-15 13:53:54 +03:30
import 'pages/login_page.dart';
import 'pages/profile/profile_shell.dart';
import 'pages/profile/profile_dashboard_page.dart';
2025-09-16 00:44:44 +03:30
import 'pages/profile/new_business_page.dart';
import 'pages/profile/businesses_page.dart';
import 'pages/profile/support_page.dart';
import 'pages/profile/change_password_page.dart';
import 'pages/profile/marketing_page.dart';
2025-09-20 22:46:06 +03:30
import 'pages/profile/operator/operator_tickets_page.dart';
2025-09-19 16:40:05 +03:30
import 'pages/system_settings_page.dart';
2025-09-22 11:00:18 +03:30
import 'pages/admin/storage_management_page.dart';
import 'pages/admin/system_configuration_page.dart';
import 'pages/admin/user_management_page.dart';
import 'pages/admin/system_logs_page.dart';
import 'pages/admin/email_settings_page.dart';
import 'pages/business/business_shell.dart';
import 'pages/business/dashboard/business_dashboard_page.dart';
2025-09-25 01:01:27 +03:30
import 'pages/business/users_permissions_page.dart';
2025-09-27 21:19:00 +03:30
import 'pages/business/accounts_page.dart';
2025-10-03 02:25:35 +03:30
import 'pages/business/bank_accounts_page.dart';
2025-09-25 03:55:16 +03:30
import 'pages/business/settings_page.dart';
2025-09-25 22:36:08 +03:30
import 'pages/business/persons_page.dart';
2025-09-30 17:12:53 +03:30
import 'pages/business/product_attributes_page.dart';
import 'pages/business/products_page.dart';
import 'pages/business/price_lists_page.dart';
import 'pages/business/price_list_items_page.dart';
2025-10-03 17:02:07 +03:30
import 'pages/business/cash_registers_page.dart';
2025-09-25 22:36:08 +03:30
import 'pages/error_404_page.dart';
2025-09-15 13:53:54 +03:30
import 'core/locale_controller.dart';
2025-09-18 10:44:23 +03:30
import 'core/calendar_controller.dart';
2025-09-15 13:53:54 +03:30
import 'core/api_client.dart';
import 'theme/theme_controller.dart';
import 'theme/app_theme.dart';
import 'core/auth_store.dart';
2025-09-19 16:40:05 +03:30
import 'core/permission_guard.dart';
import 'widgets/simple_splash_screen.dart';
2025-09-25 01:01:27 +03:30
import 'widgets/url_tracker.dart';
2025-09-15 13:53:54 +03:30
void main() {
2025-09-18 10:44:23 +03:30
// Use path-based routing instead of hash routing
usePathUrlStrategy();
2025-09-15 13:53:54 +03:30
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
LocaleController? _controller;
2025-09-18 10:44:23 +03:30
CalendarController? _calendarController;
2025-09-15 13:53:54 +03:30
ThemeController? _themeController;
AuthStore? _authStore;
bool _isLoading = true;
DateTime? _loadStartTime;
2025-09-15 13:53:54 +03:30
@override
void initState() {
super.initState();
_loadStartTime = DateTime.now();
_loadControllers();
}
2025-09-15 13:53:54 +03:30
Future<void> _loadControllers() async {
// بارگذاری تمام کنترلرها
final localeController = await LocaleController.load();
final calendarController = await CalendarController.load();
final themeController = ThemeController();
await themeController.load();
final authStore = AuthStore();
2025-09-26 02:05:13 +03:30
// بایند کردن AuthStore قبل از load برای ارسال هدر Authorization در درخواست‌های اولیه
ApiClient.bindAuthStore(authStore);
await authStore.load();
// تنظیم کنترلرها
setState(() {
_controller = localeController;
_calendarController = calendarController;
_themeController = themeController;
_authStore = authStore;
2025-09-18 10:44:23 +03:30
});
// اضافه کردن listeners
_controller!.addListener(() {
ApiClient.setCurrentLocale(_controller!.locale);
setState(() {});
2025-09-15 13:53:54 +03:30
});
_calendarController!.addListener(() {
setState(() {});
});
_themeController!.addListener(() {
setState(() {});
});
_authStore!.addListener(() {
setState(() {});
});
// تنظیم API Client
ApiClient.setCurrentLocale(_controller!.locale);
ApiClient.bindCalendarController(_calendarController!);
ApiClient.bindAuthStore(_authStore!);
2025-09-25 01:01:27 +03:30
// اطمینان از حداقل 1 ثانیه نمایش splash screen
final elapsed = DateTime.now().difference(_loadStartTime!);
2025-09-25 01:01:27 +03:30
const minimumDuration = Duration(seconds: 1);
if (elapsed < minimumDuration) {
await Future.delayed(minimumDuration - elapsed);
}
2025-09-25 01:01:27 +03:30
// ذخیره URL فعلی قبل از اتمام loading
if (_authStore != null) {
try {
final currentUrl = Uri.base.path;
print('🔍 LOADING DEBUG: Current URL before finishing loading: $currentUrl');
if (currentUrl.isNotEmpty &&
currentUrl != '/' &&
currentUrl != '/login' &&
(currentUrl.startsWith('/user/profile/') || currentUrl.startsWith('/business/'))) {
print('🔍 LOADING DEBUG: Saving current URL: $currentUrl');
await _authStore!.saveLastUrl(currentUrl);
}
} catch (e) {
print('🔍 LOADING DEBUG: Error saving current URL: $e');
}
}
// اتمام loading
if (mounted) {
2025-09-25 01:01:27 +03:30
print('🔍 LOADING DEBUG: Finishing loading, setting _isLoading to false');
setState(() {
_isLoading = false;
});
}
2025-09-15 13:53:54 +03:30
}
// Root of application with GoRouter
@override
Widget build(BuildContext context) {
2025-09-25 01:01:27 +03:30
print('🔍 BUILD DEBUG: Building app, _isLoading: $_isLoading');
print('🔍 BUILD DEBUG: Controllers - locale: ${_controller != null}, calendar: ${_calendarController != null}, theme: ${_themeController != null}, auth: ${_authStore != null}');
// اگر هنوز loading است، splash screen نمایش بده
if (_isLoading ||
_controller == null ||
_calendarController == null ||
_themeController == null ||
_authStore == null) {
2025-09-25 01:01:27 +03:30
print('🔍 BUILD DEBUG: Still loading, showing splash screen');
final loadingRouter = GoRouter(
redirect: (context, state) {
// در حین loading، هیچ redirect نکن - URL را حفظ کن
return null;
},
routes: <RouteBase>[
// برای تمام مسیرها splash screen نمایش بده
GoRoute(
path: '/:path(.*)',
builder: (context, state) {
// تشخیص نوع loading بر اساس controller های موجود
String loadingMessage = 'Initializing...';
if (_controller == null) {
loadingMessage = 'Loading language settings...';
} else if (_calendarController == null) {
loadingMessage = 'Loading calendar settings...';
} else if (_themeController == null) {
loadingMessage = 'Loading theme settings...';
} else if (_authStore == null) {
loadingMessage = 'Loading authentication...';
}
// اگر controller موجود است، از locale آن استفاده کن
if (_controller != null) {
final isFa = _controller!.locale.languageCode == 'fa';
if (isFa) {
2025-09-25 03:21:15 +03:30
if (_calendarController == null) {
2025-09-25 01:18:59 +03:30
loadingMessage = 'loadingCalendarSettings';
} else if (_themeController == null) {
2025-09-25 01:18:59 +03:30
loadingMessage = 'loadingThemeSettings';
} else if (_authStore == null) {
2025-09-25 01:18:59 +03:30
loadingMessage = 'loadingAuthentication';
} else {
2025-09-25 01:18:59 +03:30
loadingMessage = 'initializing';
}
}
}
2025-09-25 01:18:59 +03:30
return Builder(
builder: (context) {
final t = AppLocalizations.of(context);
String localizedMessage = loadingMessage;
// تبدیل کلیدهای ترجمه به متن
switch (loadingMessage) {
case 'loadingLanguageSettings':
localizedMessage = t.loadingLanguageSettings;
break;
case 'loadingCalendarSettings':
localizedMessage = t.loadingCalendarSettings;
break;
case 'loadingThemeSettings':
localizedMessage = t.loadingThemeSettings;
break;
case 'loadingAuthentication':
localizedMessage = t.loadingAuthentication;
break;
case 'initializing':
localizedMessage = t.initializing;
break;
default:
localizedMessage = loadingMessage;
}
return SimpleSplashScreen(
message: localizedMessage,
showLogo: true,
displayDuration: const Duration(seconds: 1),
locale: _controller?.locale,
authStore: _authStore,
onComplete: () {
// این callback زمانی فراخوانی می‌شود که splash screen تمام شود
// اما ما از splash controller استفاده می‌کنیم
print('🔍 SPLASH DEBUG: Splash screen completed');
},
);
},
);
},
),
],
);
return MaterialApp.router(
title: 'Hesabix',
routerConfig: loadingRouter,
2025-09-25 03:21:15 +03:30
locale: _controller?.locale ?? const Locale('fa'),
supportedLocales: const [Locale('en'), Locale('fa')],
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
2025-09-15 13:53:54 +03:30
);
}
final controller = _controller!;
final themeController = _themeController!;
2025-09-25 01:01:27 +03:30
print('🔍 BUILD DEBUG: All controllers loaded, creating main router');
2025-09-26 02:05:13 +03:30
// حفظ URL فعلی مرورگر هنگام سوئیچ از لودینگ به روتر اصلی
final currentInitialLocation = () {
final base = Uri.base;
final path = base.path.isNotEmpty ? base.path : '/';
final query = base.hasQuery ? '?${base.query}' : '';
final fragment = base.fragment.isNotEmpty ? '#${base.fragment}' : '';
return '$path$query$fragment';
}();
2025-09-15 13:53:54 +03:30
final router = GoRouter(
2025-09-26 02:05:13 +03:30
initialLocation: currentInitialLocation,
2025-09-25 01:01:27 +03:30
redirect: (context, state) async {
2025-09-18 10:44:23 +03:30
final currentPath = state.uri.path;
2025-09-25 01:01:27 +03:30
final fullUri = state.uri.toString();
print('🔍 REDIRECT DEBUG: Current path: $currentPath');
print('🔍 REDIRECT DEBUG: Full URI: $fullUri');
2025-09-18 10:44:23 +03:30
// اگر authStore هنوز load نشده، منتظر بمان
if (_authStore == null) {
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: AuthStore is null, staying on current path');
2025-09-18 10:44:23 +03:30
return null;
}
2025-09-16 00:10:20 +03:30
final hasKey = _authStore!.apiKey != null && _authStore!.apiKey!.isNotEmpty;
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: Has API key: $hasKey');
2025-09-18 10:44:23 +03:30
// اگر API key ندارد
if (!hasKey) {
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: No API key');
2025-09-18 10:44:23 +03:30
// اگر در login نیست، به login برود
if (currentPath != '/login') {
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: Redirecting to login from $currentPath');
2025-09-18 10:44:23 +03:30
return '/login';
}
// اگر در login است، بماند
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: Already on login, staying');
2025-09-18 10:44:23 +03:30
return null;
}
// اگر API key دارد
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: Has API key, checking current path');
2025-09-18 10:44:23 +03:30
// اگر در login است، به dashboard برود
if (currentPath == '/login') {
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: On login page, redirecting to dashboard');
2025-09-18 10:44:23 +03:30
return '/user/profile/dashboard';
}
2025-09-25 01:01:27 +03:30
// اگر در root است، آخرین URL را بررسی کن
2025-09-18 10:44:23 +03:30
if (currentPath == '/') {
2025-09-25 01:01:27 +03:30
print('🔍 REDIRECT DEBUG: On root path, checking last URL');
// اگر آخرین URL موجود است و معتبر است، به آن برود
final lastUrl = await _authStore!.getLastUrl();
print('🔍 REDIRECT DEBUG: Last URL: $lastUrl');
if (lastUrl != null &&
lastUrl.isNotEmpty &&
lastUrl != '/' &&
lastUrl != '/login' &&
(lastUrl.startsWith('/user/profile/') || lastUrl.startsWith('/business/'))) {
print('🔍 REDIRECT DEBUG: Redirecting to last URL: $lastUrl');
return lastUrl;
}
// وگرنه به dashboard برود (فقط اگر در root باشیم)
print('🔍 REDIRECT DEBUG: No valid last URL, redirecting to dashboard');
2025-09-18 10:44:23 +03:30
return '/user/profile/dashboard';
}
2025-09-25 01:01:27 +03:30
// برای سایر صفحات (شامل صفحات profile و business)، redirect نکن (بماند)
// این مهم است: اگر کاربر در صفحات profile یا business است، بماند
print('🔍 REDIRECT DEBUG: On other page ($currentPath), staying on current path');
2025-09-27 21:19:00 +03:30
// ذخیره مسیر فعلی به عنوان آخرین URL معتبر
if (currentPath.isNotEmpty &&
currentPath != '/' &&
currentPath != '/login' &&
(currentPath.startsWith('/user/profile/') || currentPath.startsWith('/business/'))) {
try {
await _authStore!.saveLastUrl(currentPath);
print('🔍 REDIRECT DEBUG: Saved last URL: $currentPath');
} catch (e) {
// صرفاً لاگ برای خطای غیر بحرانی ذخیره آدرس
print('🔍 REDIRECT DEBUG: Error saving last URL: $e');
}
}
2025-09-16 00:10:20 +03:30
return null;
},
2025-09-15 13:53:54 +03:30
routes: <RouteBase>[
GoRoute(
path: '/login',
name: 'login',
builder: (context, state) => LoginPage(
localeController: controller,
2025-09-18 10:44:23 +03:30
calendarController: _calendarController!,
2025-09-15 13:53:54 +03:30
themeController: themeController,
authStore: _authStore!,
2025-09-15 13:53:54 +03:30
),
),
2025-09-18 10:44:23 +03:30
ShellRoute(
builder: (context, state, child) => ProfileShell(
authStore: _authStore!,
2025-09-15 13:53:54 +03:30
localeController: controller,
2025-09-18 10:44:23 +03:30
calendarController: _calendarController!,
2025-09-15 13:53:54 +03:30
themeController: themeController,
2025-09-18 10:44:23 +03:30
child: child,
2025-09-15 13:53:54 +03:30
),
routes: [
GoRoute(
path: '/user/profile/dashboard',
name: 'profile_dashboard',
builder: (context, state) => const ProfileDashboardPage(),
),
2025-09-16 00:44:44 +03:30
GoRoute(
path: '/user/profile/new-business',
name: 'profile_new_business',
2025-09-27 21:19:00 +03:30
builder: (context, state) => NewBusinessPage(calendarController: _calendarController!),
2025-09-16 00:44:44 +03:30
),
GoRoute(
path: '/user/profile/businesses',
name: 'profile_businesses',
builder: (context, state) => const BusinessesPage(),
),
GoRoute(
path: '/user/profile/support',
name: 'profile_support',
2025-09-20 22:46:06 +03:30
builder: (context, state) => SupportPage(calendarController: _calendarController),
2025-09-16 00:44:44 +03:30
),
GoRoute(
path: '/user/profile/marketing',
name: 'profile_marketing',
2025-09-18 10:44:23 +03:30
builder: (context, state) => MarketingPage(calendarController: _calendarController!),
2025-09-16 00:44:44 +03:30
),
GoRoute(
path: '/user/profile/change-password',
name: 'profile_change_password',
builder: (context, state) => const ChangePasswordPage(),
),
2025-09-20 22:46:06 +03:30
GoRoute(
path: '/user/profile/operator',
name: 'profile_operator',
builder: (context, state) {
// بررسی دسترسی اپراتور پشتیبانی
if (_authStore == null) {
return PermissionGuard.buildAccessDeniedPage();
}
if (!_authStore!.canAccessSupportOperator) {
return PermissionGuard.buildAccessDeniedPage();
}
return OperatorTicketsPage(calendarController: _calendarController);
},
),
2025-09-19 16:40:05 +03:30
GoRoute(
path: '/user/profile/system-settings',
name: 'profile_system_settings',
builder: (context, state) {
// بررسی دسترسی SuperAdmin
if (_authStore == null) {
return PermissionGuard.buildAccessDeniedPage();
}
if (!_authStore!.isSuperAdmin) {
return PermissionGuard.buildAccessDeniedPage();
}
return const SystemSettingsPage();
},
2025-09-22 11:00:18 +03:30
routes: [
GoRoute(
path: 'storage',
name: 'system_settings_storage',
builder: (context, state) {
if (_authStore == null || !_authStore!.isSuperAdmin) {
return PermissionGuard.buildAccessDeniedPage();
}
return const AdminStorageManagementPage();
},
),
GoRoute(
path: 'configuration',
name: 'system_settings_configuration',
builder: (context, state) {
if (_authStore == null || !_authStore!.isSuperAdmin) {
return PermissionGuard.buildAccessDeniedPage();
}
return const SystemConfigurationPage();
},
),
GoRoute(
path: 'users',
name: 'system_settings_users',
builder: (context, state) {
if (_authStore == null || !_authStore!.isSuperAdmin) {
return PermissionGuard.buildAccessDeniedPage();
}
return const UserManagementPage();
},
),
GoRoute(
path: 'logs',
name: 'system_settings_logs',
builder: (context, state) {
if (_authStore == null || !_authStore!.isSuperAdmin) {
return PermissionGuard.buildAccessDeniedPage();
}
return const SystemLogsPage();
},
),
GoRoute(
path: 'email',
name: 'system_settings_email',
builder: (context, state) {
if (_authStore == null || !_authStore!.isSuperAdmin) {
return PermissionGuard.buildAccessDeniedPage();
}
return const EmailSettingsPage();
},
),
2025-09-22 11:00:18 +03:30
],
2025-09-19 16:40:05 +03:30
),
2025-09-15 13:53:54 +03:30
],
),
GoRoute(
path: '/business/:business_id',
name: 'business_shell',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
2025-09-25 01:01:27 +03:30
localeController: controller,
calendarController: _calendarController!,
2025-09-25 01:01:27 +03:30
themeController: themeController,
child: const SizedBox.shrink(), // Will be replaced by child routes
);
},
routes: [
GoRoute(
path: 'dashboard',
name: 'business_dashboard',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
2025-09-25 01:01:27 +03:30
localeController: controller,
calendarController: _calendarController!,
2025-09-25 01:01:27 +03:30
themeController: themeController,
child: BusinessDashboardPage(businessId: businessId),
);
},
),
2025-09-25 01:01:27 +03:30
GoRoute(
path: 'users-permissions',
name: 'business_users_permissions',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: UsersPermissionsPage(
businessId: businessId.toString(),
authStore: _authStore!,
calendarController: _calendarController!,
),
);
},
),
2025-09-27 21:19:00 +03:30
GoRoute(
path: 'chart-of-accounts',
name: 'business_chart_of_accounts',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: AccountsPage(businessId: businessId),
);
},
),
GoRoute(
path: 'accounts',
name: 'business_accounts',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
2025-10-03 02:25:35 +03:30
child: BankAccountsPage(
businessId: businessId,
2025-10-03 17:02:07 +03:30
authStore: _authStore!,
),
);
},
),
GoRoute(
path: 'cash-box',
name: 'business_cash_box',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: CashRegistersPage(
businessId: businessId,
2025-10-03 02:25:35 +03:30
authStore: _authStore!,
),
2025-09-27 21:19:00 +03:30
);
},
),
2025-09-25 03:55:16 +03:30
GoRoute(
path: 'settings',
name: 'business_settings',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: SettingsPage(
businessId: businessId,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
),
);
},
),
2025-09-30 17:12:53 +03:30
GoRoute(
path: 'product-attributes',
name: 'business_product_attributes',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: ProductAttributesPage(
businessId: businessId,
authStore: _authStore!,
),
);
},
),
GoRoute(
path: 'products',
name: 'business_products',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: ProductsPage(
businessId: businessId,
authStore: _authStore!,
),
);
},
),
GoRoute(
path: 'price-lists',
name: 'business_price_lists',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: PriceListsPage(
businessId: businessId,
authStore: _authStore!,
),
);
},
),
GoRoute(
path: 'price-lists/:price_list_id/items',
name: 'business_price_list_items',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
final priceListId = int.parse(state.pathParameters['price_list_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: PriceListItemsPage(
businessId: businessId,
priceListId: priceListId,
authStore: _authStore!,
),
);
},
),
2025-09-25 22:36:08 +03:30
GoRoute(
path: 'persons',
name: 'business_persons',
builder: (context, state) {
final businessId = int.parse(state.pathParameters['business_id']!);
return BusinessShell(
businessId: businessId,
authStore: _authStore!,
localeController: controller,
calendarController: _calendarController!,
themeController: themeController,
child: PersonsPage(
businessId: businessId,
authStore: _authStore!,
),
);
},
),
// TODO: Add other business routes (sales, accounting, etc.)
],
),
2025-09-25 22:36:08 +03:30
// صفحه 404 برای مسیرهای نامعتبر
GoRoute(
path: '/404',
name: 'error_404',
builder: (context, state) => const Error404Page(),
),
2025-09-15 13:53:54 +03:30
],
2025-09-25 22:36:08 +03:30
errorBuilder: (context, state) => const Error404Page(),
2025-09-15 13:53:54 +03:30
);
return AnimatedBuilder(
animation: Listenable.merge([controller, themeController]),
builder: (context, _) {
2025-09-25 01:01:27 +03:30
return UrlTracker(
authStore: _authStore!,
child: MaterialApp.router(
title: 'Hesabix',
theme: AppTheme.build(
isDark: false,
locale: controller.locale,
seed: themeController.seedColor,
),
darkTheme: AppTheme.build(
isDark: true,
locale: controller.locale,
seed: themeController.seedColor,
),
themeMode: themeController.mode,
routerConfig: router,
2025-09-15 13:53:54 +03:30
locale: controller.locale,
2025-09-25 01:01:27 +03:30
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
2025-09-15 13:53:54 +03:30
),
);
},
);
}
}