From 2dde8eeef9cfc9c05523d5d3808aaf7df39da300 Mon Sep 17 00:00:00 2001 From: Babak Alizadeh Date: Thu, 25 Sep 2025 03:55:16 +0330 Subject: [PATCH] redesign business menu --- hesabixUI/hesabix_ui/lib/l10n/app_en.arb | 34 +- hesabixUI/hesabix_ui/lib/l10n/app_fa.arb | 34 +- .../lib/l10n/app_localizations.dart | 152 +++++- .../lib/l10n/app_localizations_en.dart | 88 +++- .../lib/l10n/app_localizations_fa.dart | 87 +++- hesabixUI/hesabix_ui/lib/main.dart | 21 + .../lib/pages/business/business_shell.dart | 43 +- .../lib/pages/business/settings_page.dart | 368 ++++++++++++++ .../widgets/combined_user_menu_button.dart | 469 ++++++++++++++++++ 9 files changed, 1253 insertions(+), 43 deletions(-) create mode 100644 hesabixUI/hesabix_ui/lib/pages/business/settings_page.dart create mode 100644 hesabixUI/hesabix_ui/lib/widgets/combined_user_menu_button.dart diff --git a/hesabixUI/hesabix_ui/lib/l10n/app_en.arb b/hesabixUI/hesabix_ui/lib/l10n/app_en.arb index 801cda9..aaa158f 100644 --- a/hesabixUI/hesabix_ui/lib/l10n/app_en.arb +++ b/hesabixUI/hesabix_ui/lib/l10n/app_en.arb @@ -745,6 +745,38 @@ "marketplace": "Marketplace", "viewMarketplace": "View Marketplace", "buyPlugins": "Buy Plugins", - "viewInvoices": "View Invoices" + "viewInvoices": "View Invoices", + "generalSettings": "General Settings", + "appearanceSettings": "Appearance Settings", + "advancedSettings": "Advanced Settings", + "businessSettingsDescription": "Manage business information and main settings", + "usersAndPermissionsDescription": "Manage users and set access levels", + "printDocuments": "Print Documents", + "printDocumentsDescription": "Configure print templates and formatting", + "languageDescription": "Select user interface language", + "themeDescription": "Choose light, dark or system theme", + "calendarDescription": "Select calendar type (Jalali or Gregorian)", + "dataBackup": "Data Backup", + "dataBackupDescription": "Create backup of all business data", + "dataRestore": "Data Restore", + "dataRestoreDescription": "Restore data from previous backup", + "systemLogs": "System Logs", + "systemLogsDescription": "View system reports and user activity logs", + "close": "Close", + "edit": "Edit", + "manage": "Manage", + "configure": "Configure", + "set": "Set", + "execute": "Execute", + "backup": "Backup", + "restore": "Restore", + "view": "View", + "businessSettingsDialogContent": "In this section you can manage business information, address, contact numbers and other details.", + "usersAndPermissionsDialogContent": "In this section you can add new users, set permissions and manage roles.", + "printDocumentsDialogContent": "In this section you can configure print templates, letterheads and printer settings.", + "dataBackupDialogContent": "In this section you can create a backup of all business data.", + "dataRestoreDialogContent": "In this section you can restore data from a previous backup.", + "systemLogsDialogContent": "In this section you can view system reports, errors and user activities.", + "accountManagement": "Account Management" } diff --git a/hesabixUI/hesabix_ui/lib/l10n/app_fa.arb b/hesabixUI/hesabix_ui/lib/l10n/app_fa.arb index da20483..162d559 100644 --- a/hesabixUI/hesabix_ui/lib/l10n/app_fa.arb +++ b/hesabixUI/hesabix_ui/lib/l10n/app_fa.arb @@ -744,6 +744,38 @@ "marketplace": "بازار افزونه‌ها", "viewMarketplace": "مشاهده افزونه‌ها", "buyPlugins": "خرید افزونه‌ها", - "viewInvoices": "صورت حساب‌ها" + "viewInvoices": "صورت حساب‌ها", + "generalSettings": "تنظیمات عمومی", + "appearanceSettings": "تنظیمات ظاهری", + "advancedSettings": "تنظیمات پیشرفته", + "businessSettingsDescription": "مدیریت اطلاعات کسب و کار و تنظیمات اصلی", + "usersAndPermissionsDescription": "مدیریت کاربران و تعیین سطح دسترسی", + "printDocuments": "چاپ اسناد", + "printDocumentsDescription": "تنظیمات چاپ و قالب‌بندی اسناد", + "languageDescription": "انتخاب زبان رابط کاربری", + "themeDescription": "انتخاب تم روشن، تاریک یا سیستمی", + "calendarDescription": "انتخاب نوع تقویم (جلالی یا میلادی)", + "dataBackup": "پشتیبان‌گیری", + "dataBackupDescription": "ایجاد نسخه پشتیبان از اطلاعات", + "dataRestore": "بازیابی اطلاعات", + "dataRestoreDescription": "بازیابی اطلاعات از نسخه پشتیبان", + "systemLogs": "گزارش‌های سیستم", + "systemLogsDescription": "مشاهده گزارش‌ها و لاگ‌های سیستم", + "close": "بستن", + "edit": "ویرایش", + "manage": "مدیریت", + "configure": "پیکربندی", + "set": "تنظیم", + "execute": "اجرا", + "backup": "پشتیبان‌گیری", + "restore": "بازیابی", + "view": "مشاهده", + "businessSettingsDialogContent": "در این بخش می‌توانید اطلاعات کسب و کار، آدرس، شماره تماس و سایر جزئیات را مدیریت کنید.", + "usersAndPermissionsDialogContent": "در این بخش می‌توانید کاربران جدید اضافه کنید، دسترسی‌ها را تعیین کنید و نقش‌ها را مدیریت کنید.", + "printDocumentsDialogContent": "در این بخش می‌توانید قالب‌های چاپ، سربرگ‌ها و تنظیمات چاپگر را پیکربندی کنید.", + "dataBackupDialogContent": "در این بخش می‌توانید از تمام اطلاعات کسب و کار نسخه پشتیبان تهیه کنید.", + "dataRestoreDialogContent": "در این بخش می‌توانید اطلاعات را از نسخه پشتیبان قبلی بازیابی کنید.", + "systemLogsDialogContent": "در این بخش می‌توانید گزارش‌های سیستم، خطاها و فعالیت‌های کاربران را مشاهده کنید.", + "accountManagement": "مدیریت حساب کاربری" } diff --git a/hesabixUI/hesabix_ui/lib/l10n/app_localizations.dart b/hesabixUI/hesabix_ui/lib/l10n/app_localizations.dart index 9a917b7..ff62f00 100644 --- a/hesabixUI/hesabix_ui/lib/l10n/app_localizations.dart +++ b/hesabixUI/hesabix_ui/lib/l10n/app_localizations.dart @@ -2561,7 +2561,7 @@ abstract class AppLocalizations { /// No description provided for @systemLogsDescription. /// /// In en, this message translates to: - /// **'View system logs and monitoring'** + /// **'View system reports and user activity logs'** String get systemLogsDescription; /// No description provided for @backToSettings. @@ -4069,6 +4069,156 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Buy Plugins'** String get buyPlugins; + + /// No description provided for @appearanceSettings. + /// + /// In en, this message translates to: + /// **'Appearance Settings'** + String get appearanceSettings; + + /// No description provided for @advancedSettings. + /// + /// In en, this message translates to: + /// **'Advanced Settings'** + String get advancedSettings; + + /// No description provided for @businessSettingsDescription. + /// + /// In en, this message translates to: + /// **'Manage business information and main settings'** + String get businessSettingsDescription; + + /// No description provided for @usersAndPermissionsDescription. + /// + /// In en, this message translates to: + /// **'Manage users and set access levels'** + String get usersAndPermissionsDescription; + + /// No description provided for @printDocumentsDescription. + /// + /// In en, this message translates to: + /// **'Configure print templates and formatting'** + String get printDocumentsDescription; + + /// No description provided for @languageDescription. + /// + /// In en, this message translates to: + /// **'Select user interface language'** + String get languageDescription; + + /// No description provided for @themeDescription. + /// + /// In en, this message translates to: + /// **'Choose light, dark or system theme'** + String get themeDescription; + + /// No description provided for @calendarDescription. + /// + /// In en, this message translates to: + /// **'Select calendar type (Jalali or Gregorian)'** + String get calendarDescription; + + /// No description provided for @dataBackup. + /// + /// In en, this message translates to: + /// **'Data Backup'** + String get dataBackup; + + /// No description provided for @dataBackupDescription. + /// + /// In en, this message translates to: + /// **'Create backup of all business data'** + String get dataBackupDescription; + + /// No description provided for @dataRestore. + /// + /// In en, this message translates to: + /// **'Data Restore'** + String get dataRestore; + + /// No description provided for @dataRestoreDescription. + /// + /// In en, this message translates to: + /// **'Restore data from previous backup'** + String get dataRestoreDescription; + + /// No description provided for @manage. + /// + /// In en, this message translates to: + /// **'Manage'** + String get manage; + + /// No description provided for @configure. + /// + /// In en, this message translates to: + /// **'Configure'** + String get configure; + + /// No description provided for @set. + /// + /// In en, this message translates to: + /// **'Set'** + String get set; + + /// No description provided for @execute. + /// + /// In en, this message translates to: + /// **'Execute'** + String get execute; + + /// No description provided for @backup. + /// + /// In en, this message translates to: + /// **'Backup'** + String get backup; + + /// No description provided for @restore. + /// + /// In en, this message translates to: + /// **'Restore'** + String get restore; + + /// No description provided for @businessSettingsDialogContent. + /// + /// In en, this message translates to: + /// **'In this section you can manage business information, address, contact numbers and other details.'** + String get businessSettingsDialogContent; + + /// No description provided for @usersAndPermissionsDialogContent. + /// + /// In en, this message translates to: + /// **'In this section you can add new users, set permissions and manage roles.'** + String get usersAndPermissionsDialogContent; + + /// No description provided for @printDocumentsDialogContent. + /// + /// In en, this message translates to: + /// **'In this section you can configure print templates, letterheads and printer settings.'** + String get printDocumentsDialogContent; + + /// No description provided for @dataBackupDialogContent. + /// + /// In en, this message translates to: + /// **'In this section you can create a backup of all business data.'** + String get dataBackupDialogContent; + + /// No description provided for @dataRestoreDialogContent. + /// + /// In en, this message translates to: + /// **'In this section you can restore data from a previous backup.'** + String get dataRestoreDialogContent; + + /// No description provided for @systemLogsDialogContent. + /// + /// In en, this message translates to: + /// **'In this section you can view system reports, errors and user activities.'** + String get systemLogsDialogContent; + + /// No description provided for @accountManagement. + /// + /// In en, this message translates to: + /// **'Account Management'** + String get accountManagement; } class _AppLocalizationsDelegate diff --git a/hesabixUI/hesabix_ui/lib/l10n/app_localizations_en.dart b/hesabixUI/hesabix_ui/lib/l10n/app_localizations_en.dart index b34b544..959f2c1 100644 --- a/hesabixUI/hesabix_ui/lib/l10n/app_localizations_en.dart +++ b/hesabixUI/hesabix_ui/lib/l10n/app_localizations_en.dart @@ -1280,7 +1280,8 @@ class AppLocalizationsEn extends AppLocalizations { String get systemLogs => 'System Logs'; @override - String get systemLogsDescription => 'View system logs and monitoring'; + String get systemLogsDescription => + 'View system reports and user activity logs'; @override String get backToSettings => 'Back to Settings'; @@ -2040,4 +2041,89 @@ class AppLocalizationsEn extends AppLocalizations { @override String get buyPlugins => 'Buy Plugins'; + + @override + String get appearanceSettings => 'Appearance Settings'; + + @override + String get advancedSettings => 'Advanced Settings'; + + @override + String get businessSettingsDescription => + 'Manage business information and main settings'; + + @override + String get usersAndPermissionsDescription => + 'Manage users and set access levels'; + + @override + String get printDocumentsDescription => + 'Configure print templates and formatting'; + + @override + String get languageDescription => 'Select user interface language'; + + @override + String get themeDescription => 'Choose light, dark or system theme'; + + @override + String get calendarDescription => + 'Select calendar type (Jalali or Gregorian)'; + + @override + String get dataBackup => 'Data Backup'; + + @override + String get dataBackupDescription => 'Create backup of all business data'; + + @override + String get dataRestore => 'Data Restore'; + + @override + String get dataRestoreDescription => 'Restore data from previous backup'; + + @override + String get manage => 'Manage'; + + @override + String get configure => 'Configure'; + + @override + String get set => 'Set'; + + @override + String get execute => 'Execute'; + + @override + String get backup => 'Backup'; + + @override + String get restore => 'Restore'; + + @override + String get businessSettingsDialogContent => + 'In this section you can manage business information, address, contact numbers and other details.'; + + @override + String get usersAndPermissionsDialogContent => + 'In this section you can add new users, set permissions and manage roles.'; + + @override + String get printDocumentsDialogContent => + 'In this section you can configure print templates, letterheads and printer settings.'; + + @override + String get dataBackupDialogContent => + 'In this section you can create a backup of all business data.'; + + @override + String get dataRestoreDialogContent => + 'In this section you can restore data from a previous backup.'; + + @override + String get systemLogsDialogContent => + 'In this section you can view system reports, errors and user activities.'; + + @override + String get accountManagement => 'Account Management'; } diff --git a/hesabixUI/hesabix_ui/lib/l10n/app_localizations_fa.dart b/hesabixUI/hesabix_ui/lib/l10n/app_localizations_fa.dart index d585782..4eb86f9 100644 --- a/hesabixUI/hesabix_ui/lib/l10n/app_localizations_fa.dart +++ b/hesabixUI/hesabix_ui/lib/l10n/app_localizations_fa.dart @@ -1267,10 +1267,10 @@ class AppLocalizationsFa extends AppLocalizations { String get userManagementDescription => 'مدیریت کاربران، نقش‌ها و مجوزها'; @override - String get systemLogs => 'لاگ‌های سیستم'; + String get systemLogs => 'گزارش‌های سیستم'; @override - String get systemLogsDescription => 'مشاهده لاگ‌های سیستم و نظارت'; + String get systemLogsDescription => 'مشاهده گزارش‌ها و لاگ‌های سیستم'; @override String get backToSettings => 'بازگشت به تنظیمات'; @@ -2029,4 +2029,87 @@ class AppLocalizationsFa extends AppLocalizations { @override String get buyPlugins => 'خرید افزونه‌ها'; + + @override + String get appearanceSettings => 'تنظیمات ظاهری'; + + @override + String get advancedSettings => 'تنظیمات پیشرفته'; + + @override + String get businessSettingsDescription => + 'مدیریت اطلاعات کسب و کار و تنظیمات اصلی'; + + @override + String get usersAndPermissionsDescription => + 'مدیریت کاربران و تعیین سطح دسترسی'; + + @override + String get printDocumentsDescription => 'تنظیمات چاپ و قالب‌بندی اسناد'; + + @override + String get languageDescription => 'انتخاب زبان رابط کاربری'; + + @override + String get themeDescription => 'انتخاب تم روشن، تاریک یا سیستمی'; + + @override + String get calendarDescription => 'انتخاب نوع تقویم (جلالی یا میلادی)'; + + @override + String get dataBackup => 'پشتیبان‌گیری'; + + @override + String get dataBackupDescription => 'ایجاد نسخه پشتیبان از اطلاعات'; + + @override + String get dataRestore => 'بازیابی اطلاعات'; + + @override + String get dataRestoreDescription => 'بازیابی اطلاعات از نسخه پشتیبان'; + + @override + String get manage => 'مدیریت'; + + @override + String get configure => 'پیکربندی'; + + @override + String get set => 'تنظیم'; + + @override + String get execute => 'اجرا'; + + @override + String get backup => 'پشتیبان‌گیری'; + + @override + String get restore => 'بازیابی'; + + @override + String get businessSettingsDialogContent => + 'در این بخش می‌توانید اطلاعات کسب و کار، آدرس، شماره تماس و سایر جزئیات را مدیریت کنید.'; + + @override + String get usersAndPermissionsDialogContent => + 'در این بخش می‌توانید کاربران جدید اضافه کنید، دسترسی‌ها را تعیین کنید و نقش‌ها را مدیریت کنید.'; + + @override + String get printDocumentsDialogContent => + 'در این بخش می‌توانید قالب‌های چاپ، سربرگ‌ها و تنظیمات چاپگر را پیکربندی کنید.'; + + @override + String get dataBackupDialogContent => + 'در این بخش می‌توانید از تمام اطلاعات کسب و کار نسخه پشتیبان تهیه کنید.'; + + @override + String get dataRestoreDialogContent => + 'در این بخش می‌توانید اطلاعات را از نسخه پشتیبان قبلی بازیابی کنید.'; + + @override + String get systemLogsDialogContent => + 'در این بخش می‌توانید گزارش‌های سیستم، خطاها و فعالیت‌های کاربران را مشاهده کنید.'; + + @override + String get accountManagement => 'مدیریت حساب کاربری'; } diff --git a/hesabixUI/hesabix_ui/lib/main.dart b/hesabixUI/hesabix_ui/lib/main.dart index 816b6d8..786eb60 100644 --- a/hesabixUI/hesabix_ui/lib/main.dart +++ b/hesabixUI/hesabix_ui/lib/main.dart @@ -22,6 +22,7 @@ import 'pages/admin/email_settings_page.dart'; import 'pages/business/business_shell.dart'; import 'pages/business/dashboard/business_dashboard_page.dart'; import 'pages/business/users_permissions_page.dart'; +import 'pages/business/settings_page.dart'; import 'core/locale_controller.dart'; import 'core/calendar_controller.dart'; import 'core/api_client.dart'; @@ -495,6 +496,26 @@ class _MyAppState extends State { ); }, ), + 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, + ), + ); + }, + ), // TODO: Add other business routes (sales, accounting, etc.) ], ), diff --git a/hesabixUI/hesabix_ui/lib/pages/business/business_shell.dart b/hesabixUI/hesabix_ui/lib/pages/business/business_shell.dart index cc2bd92..d7c72aa 100644 --- a/hesabixUI/hesabix_ui/lib/pages/business/business_shell.dart +++ b/hesabixUI/hesabix_ui/lib/pages/business/business_shell.dart @@ -4,8 +4,7 @@ import '../../core/auth_store.dart'; import '../../core/locale_controller.dart'; import '../../core/calendar_controller.dart'; import '../../theme/theme_controller.dart'; -import '../../widgets/settings_menu_button.dart'; -import '../../widgets/user_account_menu_button.dart'; +import '../../widgets/combined_user_menu_button.dart'; import 'package:hesabix_ui/l10n/app_localizations.dart'; class BusinessShell extends StatefulWidget { @@ -32,7 +31,6 @@ class BusinessShell extends StatefulWidget { class _BusinessShellState extends State { int _hoverIndex = -1; - bool _isBasicToolsExpanded = false; bool _isPeopleExpanded = false; bool _isProductsAndServicesExpanded = false; bool _isBankingExpanded = false; @@ -362,31 +360,8 @@ class _BusinessShellState extends State { label: t.settings, icon: Icons.settings, selectedIcon: Icons.settings, - path: null, // برای منوی بازشونده - type: _MenuItemType.expandable, - children: [ - _MenuItem( - label: t.businessSettings, - icon: Icons.business, - selectedIcon: Icons.business, - path: '/business/${widget.businessId}/business-settings', - type: _MenuItemType.simple, - ), - _MenuItem( - label: t.printDocuments, - icon: Icons.print, - selectedIcon: Icons.print, - path: '/business/${widget.businessId}/print-documents', - type: _MenuItemType.simple, - ), - _MenuItem( - label: t.usersAndPermissions, - icon: Icons.people_outline, - selectedIcon: Icons.people, - path: '/business/${widget.businessId}/users-permissions', - type: _MenuItemType.simple, - ), - ], + path: '/business/${widget.businessId}/settings', + type: _MenuItemType.simple, ), _MenuItem( label: t.pluginMarketplace, @@ -417,7 +392,6 @@ class _BusinessShellState extends State { if (i == 4) _isBankingExpanded = true; // بانکداری در ایندکس 4 if (i == 6) _isAccountingMenuExpanded = true; // حسابداری در ایندکس 6 if (i == 8) _isWarehouseManagementExpanded = true; // انبارداری در ایندکس 8 - if (i == 9) _isBasicToolsExpanded = true; // تنظیمات در ایندکس 9 break; } } @@ -444,7 +418,6 @@ class _BusinessShellState extends State { if (item.label == t.banking) _isBankingExpanded = !_isBankingExpanded; if (item.label == t.accountingMenu) _isAccountingMenuExpanded = !_isAccountingMenuExpanded; if (item.label == t.warehouseManagement) _isWarehouseManagementExpanded = !_isWarehouseManagementExpanded; - if (item.label == t.settings) _isBasicToolsExpanded = !_isBasicToolsExpanded; setState(() {}); } } @@ -482,7 +455,6 @@ class _BusinessShellState extends State { if (item.label == t.banking) return _isBankingExpanded; if (item.label == t.accountingMenu) return _isAccountingMenuExpanded; if (item.label == t.warehouseManagement) return _isWarehouseManagementExpanded; - if (item.label == t.settings) return _isBasicToolsExpanded; return false; } @@ -533,14 +505,13 @@ class _BusinessShellState extends State { ), ), actions: [ - SettingsMenuButton( + CombinedUserMenuButton( + authStore: widget.authStore, localeController: widget.localeController, calendarController: widget.calendarController, themeController: widget.themeController, ), - const SizedBox(width: 8), - UserAccountMenuButton(authStore: widget.authStore), - const SizedBox(width: 8), + const SizedBox(width: 4), ], ); @@ -767,7 +738,6 @@ class _BusinessShellState extends State { if (item.label == t.banking) _isBankingExpanded = !_isBankingExpanded; if (item.label == t.accountingMenu) _isAccountingMenuExpanded = !_isAccountingMenuExpanded; if (item.label == t.warehouseManagement) _isWarehouseManagementExpanded = !_isWarehouseManagementExpanded; - if (item.label == t.settings) _isBasicToolsExpanded = !_isBasicToolsExpanded; }); } else { onSelect(menuIndex); @@ -927,7 +897,6 @@ class _BusinessShellState extends State { if (item.label == t.banking) _isBankingExpanded = expanded; if (item.label == t.accountingMenu) _isAccountingMenuExpanded = expanded; if (item.label == t.warehouseManagement) _isWarehouseManagementExpanded = expanded; - if (item.label == t.settings) _isBasicToolsExpanded = expanded; }); }, children: item.children?.map((child) => ListTile( diff --git a/hesabixUI/hesabix_ui/lib/pages/business/settings_page.dart b/hesabixUI/hesabix_ui/lib/pages/business/settings_page.dart new file mode 100644 index 0000000..e863058 --- /dev/null +++ b/hesabixUI/hesabix_ui/lib/pages/business/settings_page.dart @@ -0,0 +1,368 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:hesabix_ui/l10n/app_localizations.dart'; +import '../../core/locale_controller.dart'; +import '../../core/calendar_controller.dart'; +import '../../theme/theme_controller.dart'; +import '../../widgets/calendar_switcher.dart'; +import '../../widgets/language_switcher.dart'; +import '../../widgets/theme_mode_switcher.dart'; + +class SettingsPage extends StatefulWidget { + final int businessId; + final LocaleController? localeController; + final CalendarController? calendarController; + final ThemeController? themeController; + + const SettingsPage({ + super.key, + required this.businessId, + this.localeController, + this.calendarController, + this.themeController, + }); + + @override + State createState() => _SettingsPageState(); +} + +class _SettingsPageState extends State { + @override + Widget build(BuildContext context) { + final t = AppLocalizations.of(context); + final cs = Theme.of(context).colorScheme; + + return Scaffold( + appBar: AppBar( + title: Text(t.settings), + backgroundColor: cs.surface, + foregroundColor: cs.onSurface, + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // بخش تنظیمات عمومی + _buildSection( + context, + title: t.generalSettings, + icon: Icons.settings, + children: [ + _buildSettingItem( + context, + title: t.businessSettings, + subtitle: t.businessSettingsDescription, + icon: Icons.business, + onTap: () => _showBusinessSettingsDialog(context), + ), + _buildSettingItem( + context, + title: t.usersAndPermissions, + subtitle: t.usersAndPermissionsDescription, + icon: Icons.people_outline, + onTap: () => _showUsersPermissionsDialog(context), + ), + _buildSettingItem( + context, + title: t.printDocuments, + subtitle: t.printDocumentsDescription, + icon: Icons.print, + onTap: () => _showPrintDocumentsDialog(context), + ), + ], + ), + + const SizedBox(height: 24), + + // بخش تنظیمات ظاهری + _buildSection( + context, + title: t.appearanceSettings, + icon: Icons.palette, + children: [ + _buildSettingItem( + context, + title: t.language, + subtitle: t.languageDescription, + icon: Icons.language, + trailing: widget.localeController != null + ? LanguageSwitcher(controller: widget.localeController!) + : null, + ), + _buildSettingItem( + context, + title: t.theme, + subtitle: t.themeDescription, + icon: Icons.brightness_6, + trailing: widget.themeController != null + ? ThemeModeSwitcher(controller: widget.themeController!) + : null, + ), + _buildSettingItem( + context, + title: t.calendar, + subtitle: t.calendarDescription, + icon: Icons.calendar_today, + trailing: widget.calendarController != null + ? CalendarSwitcher(controller: widget.calendarController!) + : null, + ), + ], + ), + + + const SizedBox(height: 24), + + // بخش تنظیمات پیشرفته + _buildSection( + context, + title: t.advancedSettings, + icon: Icons.engineering, + children: [ + _buildSettingItem( + context, + title: t.dataBackup, + subtitle: t.dataBackupDescription, + icon: Icons.backup, + onTap: () => _showDataBackupDialog(context), + ), + _buildSettingItem( + context, + title: t.dataRestore, + subtitle: t.dataRestoreDescription, + icon: Icons.restore, + onTap: () => _showDataRestoreDialog(context), + ), + _buildSettingItem( + context, + title: t.systemLogs, + subtitle: t.systemLogsDescription, + icon: Icons.assignment, + onTap: () => _showSystemLogsDialog(context), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildSection( + BuildContext context, { + required String title, + required IconData icon, + required List children, + }) { + final cs = Theme.of(context).colorScheme; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(icon, color: cs.primary, size: 24), + const SizedBox(width: 12), + Text( + title, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: cs.onSurface, + ), + ), + ], + ), + const SizedBox(height: 16), + ...children, + ], + ); + } + + Widget _buildSettingItem( + BuildContext context, { + required String title, + required String subtitle, + required IconData icon, + Widget? trailing, + VoidCallback? onTap, + }) { + final cs = Theme.of(context).colorScheme; + + return Card( + margin: const EdgeInsets.only(bottom: 8), + child: ListTile( + leading: Icon(icon, color: cs.primary), + title: Text( + title, + style: TextStyle( + fontWeight: FontWeight.w500, + color: cs.onSurface, + ), + ), + subtitle: Text( + subtitle, + style: TextStyle( + color: cs.onSurfaceVariant, + fontSize: 12, + ), + ), + trailing: trailing ?? const Icon(Icons.arrow_forward_ios, size: 16), + onTap: onTap, + ), + ); + } + + // دیالوگ‌های تنظیمات + void _showBusinessSettingsDialog(BuildContext context) { + final t = AppLocalizations.of(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(t.businessSettings), + content: Text(t.businessSettingsDialogContent), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(t.close), + ), + FilledButton( + onPressed: () { + Navigator.pop(context); + // Navigate to business dashboard for now (until business settings page is created) + context.go('/business/${widget.businessId}/dashboard'); + }, + child: Text(t.edit), + ), + ], + ), + ); + } + + void _showUsersPermissionsDialog(BuildContext context) { + final t = AppLocalizations.of(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(t.usersAndPermissions), + content: Text(t.usersAndPermissionsDialogContent), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(t.close), + ), + FilledButton( + onPressed: () { + Navigator.pop(context); + // Navigate to users permissions page + context.go('/business/${widget.businessId}/users-permissions'); + }, + child: Text(t.manage), + ), + ], + ), + ); + } + + void _showPrintDocumentsDialog(BuildContext context) { + final t = AppLocalizations.of(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(t.printDocuments), + content: Text(t.printDocumentsDialogContent), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(t.close), + ), + FilledButton( + onPressed: () { + Navigator.pop(context); + // Navigate to business dashboard for now (until print documents page is created) + context.go('/business/${widget.businessId}/dashboard'); + }, + child: Text(t.configure), + ), + ], + ), + ); + } + + + void _showDataBackupDialog(BuildContext context) { + final t = AppLocalizations.of(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(t.dataBackup), + content: Text(t.dataBackupDialogContent), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(t.close), + ), + FilledButton( + onPressed: () { + Navigator.pop(context); + // Navigate to business dashboard for now (until backup functionality is implemented) + context.go('/business/${widget.businessId}/dashboard'); + }, + child: Text(t.backup), + ), + ], + ), + ); + } + + void _showDataRestoreDialog(BuildContext context) { + final t = AppLocalizations.of(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(t.dataRestore), + content: Text(t.dataRestoreDialogContent), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(t.close), + ), + FilledButton( + onPressed: () { + Navigator.pop(context); + // Navigate to business dashboard for now (until restore functionality is implemented) + context.go('/business/${widget.businessId}/dashboard'); + }, + child: Text(t.restore), + ), + ], + ), + ); + } + + void _showSystemLogsDialog(BuildContext context) { + final t = AppLocalizations.of(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(t.systemLogs), + content: Text(t.systemLogsDialogContent), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(t.close), + ), + FilledButton( + onPressed: () { + Navigator.pop(context); + // Navigate to business dashboard for now (until system logs page is created) + context.go('/business/${widget.businessId}/dashboard'); + }, + child: Text(t.view), + ), + ], + ), + ); + } +} diff --git a/hesabixUI/hesabix_ui/lib/widgets/combined_user_menu_button.dart b/hesabixUI/hesabix_ui/lib/widgets/combined_user_menu_button.dart new file mode 100644 index 0000000..03081ef --- /dev/null +++ b/hesabixUI/hesabix_ui/lib/widgets/combined_user_menu_button.dart @@ -0,0 +1,469 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:hesabix_ui/l10n/app_localizations.dart'; +import '../core/auth_store.dart'; +import '../core/locale_controller.dart'; +import '../core/calendar_controller.dart'; +import '../theme/theme_controller.dart'; +import 'calendar_switcher.dart'; +import 'language_switcher.dart'; +import 'theme_mode_switcher.dart'; + +class CombinedUserMenuButton extends StatelessWidget { + final AuthStore authStore; + final LocaleController? localeController; + final CalendarController? calendarController; + final ThemeController? themeController; + + const CombinedUserMenuButton({ + super.key, + required this.authStore, + this.localeController, + this.calendarController, + this.themeController, + }); + + void _showUserMenu(BuildContext context) { + final t = AppLocalizations.of(context); + final cs = Theme.of(context).colorScheme; + + showDialog( + context: context, + barrierDismissible: true, + builder: (context) => Dialog( + backgroundColor: Colors.transparent, + elevation: 0, + child: Container( + constraints: const BoxConstraints(maxWidth: 320), + decoration: BoxDecoration( + color: cs.surface, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Header با آواتار و نام کاربر + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: cs.primaryContainer.withOpacity(0.1), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), + ), + child: Row( + children: [ + CircleAvatar( + radius: 24, + backgroundColor: cs.primary, + child: Icon( + Icons.person, + color: cs.onPrimary, + size: 28, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + t.profile, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: cs.onSurface, + ), + ), + Text( + 'کاربر حسابیکس', + style: TextStyle( + fontSize: 14, + color: cs.onSurfaceVariant, + ), + ), + ], + ), + ), + ], + ), + ), + + // محتوای دیالوگ + Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + // آیتم حساب کاربری + Container( + width: double.infinity, + decoration: BoxDecoration( + color: cs.primaryContainer.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: cs.primary.withOpacity(0.2), + width: 1, + ), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(12), + onTap: () { + context.pop(); + context.go('/user/profile/dashboard'); + }, + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + CircleAvatar( + radius: 20, + backgroundColor: cs.primary, + child: Icon( + Icons.account_circle, + color: cs.onPrimary, + size: 24, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + t.profile, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: cs.onSurface, + ), + ), + Text( + t.accountManagement, + style: TextStyle( + fontSize: 14, + color: cs.onSurfaceVariant, + ), + ), + ], + ), + ), + Icon( + Icons.arrow_forward_ios, + color: cs.onSurfaceVariant, + size: 16, + ), + ], + ), + ), + ), + ), + ), + + const SizedBox(height: 16), + + // بخش تنظیمات + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: cs.surfaceContainerHighest.withOpacity(0.3), + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.settings, + color: cs.primary, + size: 20, + ), + const SizedBox(width: 8), + Text( + t.settings, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: cs.onSurface, + ), + ), + ], + ), + const SizedBox(height: 16), + + // تنظیمات تقویم + if (calendarController != null) ...[ + _buildSettingRow( + context, + icon: Icons.calendar_today, + title: t.calendar, + child: CalendarSwitcher(controller: calendarController!), + ), + const SizedBox(height: 12), + ], + + // تنظیمات زبان + if (localeController != null) ...[ + _buildSettingRow( + context, + icon: Icons.language, + title: t.language, + child: LanguageSwitcher(controller: localeController!), + ), + const SizedBox(height: 12), + ], + + // تنظیمات تم + if (themeController != null) ...[ + _buildSettingRow( + context, + icon: Icons.palette, + title: t.theme, + child: ThemeModeSwitcher(controller: themeController!), + ), + ], + ], + ), + ), + + const SizedBox(height: 16), + + // دکمه خروج + Container( + width: double.infinity, + decoration: BoxDecoration( + color: cs.errorContainer.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: cs.error.withOpacity(0.2), + width: 1, + ), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(12), + onTap: () { + context.pop(); + _confirmLogout(context); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + child: Row( + children: [ + Icon( + Icons.logout, + color: cs.error, + size: 20, + ), + const SizedBox(width: 12), + Text( + t.logout, + style: TextStyle( + color: cs.error, + fontWeight: FontWeight.w500, + fontSize: 16, + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildSettingRow( + BuildContext context, { + required IconData icon, + required String title, + required Widget child, + }) { + final cs = Theme.of(context).colorScheme; + + return Row( + children: [ + Icon( + icon, + color: cs.onSurfaceVariant, + size: 20, + ), + const SizedBox(width: 12), + Expanded( + child: Text( + title, + style: TextStyle( + color: cs.onSurface, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ), + child, + ], + ); + } + + void _confirmLogout(BuildContext context) { + final t = AppLocalizations.of(context); + final cs = Theme.of(context).colorScheme; + + showDialog( + context: context, + barrierDismissible: true, + builder: (context) => Dialog( + backgroundColor: Colors.transparent, + elevation: 0, + child: Container( + constraints: const BoxConstraints(maxWidth: 400), + decoration: BoxDecoration( + color: cs.surface, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Header + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: cs.errorContainer.withOpacity(0.1), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), + ), + child: Row( + children: [ + CircleAvatar( + radius: 20, + backgroundColor: cs.error, + child: Icon( + Icons.logout, + color: cs.onError, + size: 20, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + t.logoutConfirmTitle, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: cs.onSurface, + ), + ), + ), + ], + ), + ), + + // Content + Padding( + padding: const EdgeInsets.all(20), + child: Text( + t.logoutConfirmMessage, + style: TextStyle( + fontSize: 16, + color: cs.onSurfaceVariant, + height: 1.5, + ), + textAlign: TextAlign.center, + ), + ), + + // Actions + Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), + child: Row( + children: [ + Expanded( + child: OutlinedButton( + onPressed: () => context.pop(), + style: OutlinedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text(t.cancel), + ), + ), + const SizedBox(width: 12), + Expanded( + child: FilledButton( + onPressed: () async { + context.pop(); + await authStore.saveApiKey(null); + if (!context.mounted) return; + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar(SnackBar(content: Text(t.logoutDone))); + context.go('/login'); + }, + style: FilledButton.styleFrom( + backgroundColor: cs.error, + foregroundColor: cs.onError, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text(t.logout), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + final cs = Theme.of(context).colorScheme; + + return IconButton( + icon: CircleAvatar( + radius: 16, + backgroundColor: cs.surfaceContainerHighest, + foregroundColor: cs.onSurface, + child: const Icon(Icons.person, size: 18), + ), + onPressed: () => _showUserMenu(context), + tooltip: AppLocalizations.of(context).profile, + ); + } +}