import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../providers/settings_provider.dart'; import '../../../auth/presentation/providers/auth_provider.dart'; import '../../../../core/constants/app_constants.dart'; /// Settings page class SettingsPage extends ConsumerWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final settingsAsync = ref.watch(settingsProvider); return Scaffold( appBar: AppBar( title: const Text('Settings'), ), body: settingsAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, size: 64, color: Theme.of(context).colorScheme.error, ), const SizedBox(height: 16), Text('Error: $error'), const SizedBox(height: 16), ElevatedButton( onPressed: () => ref.invalidate(settingsProvider), child: const Text('Retry'), ), ], ), ), data: (settings) { final user = ref.watch(currentUserProvider); return ListView( children: [ // User Profile Section if (user != null) ...[ Card( margin: const EdgeInsets.all(16), child: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ CircleAvatar( radius: 40, backgroundColor: Theme.of(context).colorScheme.primaryContainer, child: Text( user.name.isNotEmpty ? user.name[0].toUpperCase() : '?', style: TextStyle( fontSize: 32, color: Theme.of(context).colorScheme.onPrimaryContainer, ), ), ), const SizedBox(height: 12), Text( user.name, style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 4), Text( user.email, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), if (user.roles.isNotEmpty) ...[ const SizedBox(height: 12), Wrap( spacing: 8, alignment: WrapAlignment.center, children: user.roles .map((role) => Chip( label: Text( role.toUpperCase(), style: const TextStyle(fontSize: 11), ), padding: const EdgeInsets.symmetric(horizontal: 8), backgroundColor: Theme.of(context).colorScheme.primaryContainer, labelStyle: TextStyle( color: Theme.of(context).colorScheme.onPrimaryContainer, ), )) .toList(), ), ], const SizedBox(height: 16), FilledButton.icon( onPressed: () async { // Show confirmation dialog final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Logout'), content: const Text('Are you sure you want to logout?'), actions: [ TextButton( onPressed: () => context.pop(false), child: const Text('Cancel'), ), FilledButton( onPressed: () => context.pop(true), style: FilledButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.error, ), child: const Text('Logout'), ), ], ), ); if (confirmed == true && context.mounted) { await ref.read(authProvider.notifier).logout(); } }, icon: const Icon(Icons.logout), label: const Text('Logout'), style: FilledButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.error, foregroundColor: Theme.of(context).colorScheme.onError, ), ), ], ), ), ), const Divider(), ], // Appearance Section _buildSectionHeader(context, 'Appearance'), ListTile( leading: const Icon(Icons.palette_outlined), title: const Text('Theme'), subtitle: Text(_getThemeModeName(settings.themeMode)), trailing: const Icon(Icons.chevron_right), onTap: () { _showThemeDialog(context, ref, settings.themeMode); }, ), const Divider(), // Localization Section _buildSectionHeader(context, 'Localization'), ListTile( leading: const Icon(Icons.language), title: const Text('Language'), subtitle: Text(_getLanguageName(settings.language)), trailing: const Icon(Icons.chevron_right), onTap: () { _showLanguageDialog(context, ref, settings.language); }, ), ListTile( leading: const Icon(Icons.attach_money), title: const Text('Currency'), subtitle: Text(settings.currency), trailing: const Icon(Icons.chevron_right), onTap: () { _showCurrencyDialog(context, ref, settings.currency); }, ), const Divider(), // Business Settings Section _buildSectionHeader(context, 'Business Settings'), ListTile( leading: const Icon(Icons.store), title: const Text('Store Name'), subtitle: Text(settings.storeName), trailing: const Icon(Icons.chevron_right), onTap: () { _showStoreNameDialog(context, ref, settings.storeName); }, ), ListTile( leading: const Icon(Icons.percent), title: const Text('Tax Rate'), subtitle: Text('${(settings.taxRate * 100).toStringAsFixed(1)}%'), trailing: const Icon(Icons.chevron_right), onTap: () { _showTaxRateDialog(context, ref, settings.taxRate); }, ), const Divider(), // Data Management Section _buildSectionHeader(context, 'Data Management'), ListTile( leading: const Icon(Icons.sync), title: const Text('Sync Data'), subtitle: settings.lastSyncAt != null ? Text('Last synced: ${_formatDateTime(settings.lastSyncAt!)}') : const Text('Never synced'), trailing: const Icon(Icons.cloud_upload), onTap: () => _performSync(context, ref), ), ListTile( leading: const Icon(Icons.delete_sweep), title: const Text('Clear Cache'), subtitle: const Text('Remove cached images and data'), trailing: const Icon(Icons.chevron_right), onTap: () => _showClearCacheDialog(context), ), const Divider(), // About Section _buildSectionHeader(context, 'About'), ListTile( leading: const Icon(Icons.info_outline), title: const Text('App Version'), subtitle: Text(AppConstants.appVersion), ), ListTile( leading: const Icon(Icons.business), title: const Text('About ${AppConstants.appName}'), trailing: const Icon(Icons.chevron_right), onTap: () => _showAboutDialog(context), ), ], ); }, ), ); } Widget _buildSectionHeader(BuildContext context, String title) { return Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 8), child: Text( title, style: Theme.of(context).textTheme.titleSmall?.copyWith( color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold, ), ), ); } String _getThemeModeName(ThemeMode mode) { switch (mode) { case ThemeMode.light: return 'Light'; case ThemeMode.dark: return 'Dark'; case ThemeMode.system: return 'System'; } } String _getLanguageName(String code) { switch (code) { case 'en': return 'English'; case 'es': return 'Spanish'; case 'fr': return 'French'; default: return code; } } String _formatDateTime(DateTime dateTime) { return '${dateTime.day}/${dateTime.month}/${dateTime.year} ${dateTime.hour}:${dateTime.minute.toString().padLeft(2, '0')}'; } void _showThemeDialog(BuildContext context, WidgetRef ref, ThemeMode currentMode) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Select Theme'), content: Column( mainAxisSize: MainAxisSize.min, children: [ RadioListTile( title: const Text('Light'), value: ThemeMode.light, groupValue: currentMode, onChanged: (value) { if (value != null) { ref.read(settingsProvider.notifier).updateTheme(value); context.pop(); } }, ), RadioListTile( title: const Text('Dark'), value: ThemeMode.dark, groupValue: currentMode, onChanged: (value) { if (value != null) { ref.read(settingsProvider.notifier).updateTheme(value); context.pop(); } }, ), RadioListTile( title: const Text('System'), value: ThemeMode.system, groupValue: currentMode, onChanged: (value) { if (value != null) { ref.read(settingsProvider.notifier).updateTheme(value); context.pop(); } }, ), ], ), ), ); } void _showLanguageDialog(BuildContext context, WidgetRef ref, String currentLanguage) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Select Language'), content: Column( mainAxisSize: MainAxisSize.min, children: [ RadioListTile( title: const Text('English'), value: 'en', groupValue: currentLanguage, onChanged: (value) { if (value != null) { ref.read(settingsProvider.notifier).updateLanguage(value); context.pop(); } }, ), RadioListTile( title: const Text('Spanish'), value: 'es', groupValue: currentLanguage, onChanged: (value) { if (value != null) { ref.read(settingsProvider.notifier).updateLanguage(value); context.pop(); } }, ), RadioListTile( title: const Text('French'), value: 'fr', groupValue: currentLanguage, onChanged: (value) { if (value != null) { ref.read(settingsProvider.notifier).updateLanguage(value); context.pop(); } }, ), ], ), ), ); } void _showCurrencyDialog(BuildContext context, WidgetRef ref, String currentCurrency) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Select Currency'), content: Column( mainAxisSize: MainAxisSize.min, children: [ RadioListTile( title: const Text('USD - US Dollar'), value: 'USD', groupValue: currentCurrency, onChanged: (value) { if (value != null) { // TODO: Implement currency update context.pop(); } }, ), RadioListTile( title: const Text('EUR - Euro'), value: 'EUR', groupValue: currentCurrency, onChanged: (value) { if (value != null) { // TODO: Implement currency update context.pop(); } }, ), RadioListTile( title: const Text('GBP - British Pound'), value: 'GBP', groupValue: currentCurrency, onChanged: (value) { if (value != null) { // TODO: Implement currency update context.pop(); } }, ), ], ), ), ); } void _showStoreNameDialog(BuildContext context, WidgetRef ref, String currentName) { final controller = TextEditingController(text: currentName); showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Store Name'), content: TextField( controller: controller, decoration: const InputDecoration( labelText: 'Store Name', hintText: 'Enter store name', ), autofocus: true, ), actions: [ TextButton( onPressed: () => context.pop(), child: const Text('Cancel'), ), FilledButton( onPressed: () { // TODO: Implement store name update context.pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Store name updated')), ); }, child: const Text('Save'), ), ], ), ); } void _showTaxRateDialog(BuildContext context, WidgetRef ref, double currentRate) { final controller = TextEditingController( text: (currentRate * 100).toStringAsFixed(1), ); showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Tax Rate'), content: TextField( controller: controller, decoration: const InputDecoration( labelText: 'Tax Rate (%)', hintText: 'Enter tax rate', suffixText: '%', ), keyboardType: const TextInputType.numberWithOptions(decimal: true), autofocus: true, ), actions: [ TextButton( onPressed: () => context.pop(), child: const Text('Cancel'), ), FilledButton( onPressed: () { // TODO: Implement tax rate update context.pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Tax rate updated')), ); }, child: const Text('Save'), ), ], ), ); } void _performSync(BuildContext context, WidgetRef ref) async { // Show loading dialog showDialog( context: context, barrierDismissible: false, builder: (context) => const Center( child: Card( child: Padding( padding: EdgeInsets.all(24.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text('Syncing data...'), ], ), ), ), ), ); // Perform sync await Future.delayed(const Duration(seconds: 2)); // Simulated delay // Close loading dialog if (context.mounted) { context.pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Data synced successfully')), ); } } void _showClearCacheDialog(BuildContext context) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Clear Cache'), content: const Text( 'This will remove all cached images and data. The app may need to reload content from the server.', ), actions: [ TextButton( onPressed: () => context.pop(), child: const Text('Cancel'), ), FilledButton( onPressed: () { context.pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Cache cleared')), ); }, child: const Text('Clear'), ), ], ), ); } void _showAboutDialog(BuildContext context) { showAboutDialog( context: context, applicationName: AppConstants.appName, applicationVersion: AppConstants.appVersion, applicationIcon: const Icon(Icons.store, size: 48), children: [ const Text( 'A modern Point of Sale application built with Flutter.', ), const SizedBox(height: 16), const Text( 'Features:\n' '• Product management\n' '• Category organization\n' '• Shopping cart\n' '• Transaction processing\n' '• Offline-first architecture', ), ], ); } }