import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../core/controllers/theme_controller.dart'; import '../../core/controllers/locale_controller.dart'; import '../../core/services/auth_service.dart'; import '../../core/services/api_service.dart'; import '../../core/utils/snackbar_util.dart'; import '../../l10n/app_localizations.dart'; import '../../l10n/l10n_x.dart'; String _themeModeLabel(AppLocalizations l10n) { switch (ThemeController.to.themeMode) { case ThemeMode.light: return l10n.themeLight; case ThemeMode.dark: return l10n.themeDark; case ThemeMode.system: return l10n.themeSystem; } } class SettingsPage extends StatelessWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context) { final l10n = context.l10n; return Scaffold( appBar: AppBar( title: Text(l10n.settingsTitle), ), body: ListView( padding: EdgeInsets.all(16.w), children: [ _buildSectionHeader(context, l10n.sectionAppearance), _buildThemeSettings(context, l10n), SizedBox(height: 24.h), _buildSectionHeader(context, l10n.sectionLanguage), _buildLanguageSettings(context, l10n), SizedBox(height: 24.h), _buildSectionHeader(context, l10n.sectionAccount), _buildAccountSettings(context, l10n), SizedBox(height: 24.h), Obx(() { final user = AuthService.to.currentUser.value; if (user?.role == 'manager') { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSectionHeader(context, l10n.sectionPaymentSettings), _buildPaymentSettings(context, l10n), SizedBox(height: 24.h), ], ); } return const SizedBox.shrink(); }), _buildSectionHeader(context, l10n.sectionNotifications), _buildNotificationSettings(context, l10n), SizedBox(height: 24.h), _buildSectionHeader(context, l10n.sectionAbout), _buildAboutSettings(context, l10n), SizedBox(height: 32.h), _buildLogoutButton(context, l10n), ], ), ); } Widget _buildSectionHeader(BuildContext context, String title) { final scheme = Theme.of(context).colorScheme; return Padding( padding: EdgeInsets.only(left: 8.w, bottom: 12.h), child: Text( title, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: scheme.onSurfaceVariant, letterSpacing: 0.5, ), ), ); } Widget _buildLanguageSettings(BuildContext context, AppLocalizations l10n) { final scheme = Theme.of(context).colorScheme; return Card( child: Obx( () => ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.secondaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.language_rounded, color: scheme.onSecondaryContainer, size: 24.w, ), ), title: Text( l10n.languageTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( LocaleController.to.currentLanguageLabel(l10n), style: TextStyle(fontSize: 14.sp), ), trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w), onTap: () => _showLanguageDialog(context, l10n), ), ), ); } void _showLanguageDialog(BuildContext context, AppLocalizations l10n) { final scheme = Theme.of(context).colorScheme; Get.dialog( Obx( () { final code = LocaleController.to.locale.value.languageCode; return AlertDialog( title: Text(l10n.chooseLanguageTitle), content: Column( mainAxisSize: MainAxisSize.min, children: [ RadioListTile( title: Text(l10n.languageEnglish), value: 'en', groupValue: code, onChanged: (v) async { if (v != null) { await LocaleController.to.setLocale(Locale(v)); Get.back(); } }, activeColor: scheme.primary, ), RadioListTile( title: Text(l10n.languageTelugu), value: 'te', groupValue: code, onChanged: (v) async { if (v != null) { await LocaleController.to.setLocale(Locale(v)); Get.back(); } }, activeColor: scheme.primary, ), ], ), ); }, ), ); } Widget _buildThemeSettings(BuildContext context, AppLocalizations l10n) { final scheme = Theme.of(context).colorScheme; return Card( child: Column( children: [ Obx( () => ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( ThemeController.to.getThemeIcon(), color: scheme.onPrimaryContainer, size: 24.w, ), ), title: Text( l10n.themeTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( _themeModeLabel(l10n), style: TextStyle(fontSize: 14.sp), ), trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w), onTap: () => _showThemeDialog(context, l10n), ), ), Divider(height: 1.h, indent: 72.w), Obx( () => SwitchListTile( secondary: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.tertiaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.brightness_6_rounded, color: scheme.onTertiaryContainer, size: 24.w, ), ), title: Text( l10n.darkModeTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.darkModeSubtitle, style: TextStyle(fontSize: 14.sp), ), value: ThemeController.to.isDarkMode, onChanged: (value) { ThemeController.to.toggleTheme(); }, activeColor: scheme.primary, ), ), ], ), ); } Widget _buildAccountSettings(BuildContext context, AppLocalizations l10n) { final scheme = Theme.of(context).colorScheme; return Card( child: Column( children: [ Obx( () { final user = AuthService.to.currentUser.value; return ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.person_rounded, color: scheme.onPrimaryContainer, size: 24.w, ), ), title: Text( user?.fullName ?? 'User', style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( user?.mobileNumber ?? '', style: TextStyle(fontSize: 14.sp), ), trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w), onTap: () { SnackbarUtil.showInfo(l10n.profileComingSoon); }, ); }, ), Divider(height: 1.h, indent: 72.w), ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.secondaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.lock_rounded, color: scheme.onSecondaryContainer, size: 24.w, ), ), title: Text( l10n.changePasswordTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.changePasswordSubtitle, style: TextStyle(fontSize: 14.sp), ), trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w), onTap: () { SnackbarUtil.showInfo(l10n.changePasswordComingSoon); }, ), ], ), ); } Widget _buildNotificationSettings( BuildContext context, AppLocalizations l10n) { final scheme = Theme.of(context).colorScheme; return Card( child: Column( children: [ SwitchListTile( secondary: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.errorContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.notifications_rounded, color: scheme.onErrorContainer, size: 24.w, ), ), title: Text( l10n.pushNotificationsTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.pushNotificationsSubtitle, style: TextStyle(fontSize: 14.sp), ), value: true, onChanged: (value) { SnackbarUtil.showInfo(l10n.notificationComingSoon); }, activeColor: scheme.primary, ), Divider(height: 1.h, indent: 72.w), SwitchListTile( secondary: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.tertiaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.payment_rounded, color: scheme.onTertiaryContainer, size: 24.w, ), ), title: Text( l10n.paymentRemindersTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.paymentRemindersSubtitle, style: TextStyle(fontSize: 14.sp), ), value: true, onChanged: (value) { SnackbarUtil.showInfo(l10n.notificationComingSoon); }, activeColor: scheme.primary, ), Divider(height: 1.h, indent: 72.w), SwitchListTile( secondary: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.casino_rounded, color: scheme.onPrimaryContainer, size: 24.w, ), ), title: Text( l10n.drawNotificationsTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.drawNotificationsSubtitle, style: TextStyle(fontSize: 14.sp), ), value: true, onChanged: (value) { SnackbarUtil.showInfo(l10n.notificationComingSoon); }, activeColor: scheme.primary, ), ], ), ); } Widget _buildPaymentSettings(BuildContext context, AppLocalizations l10n) { final apiService = ApiService(); final scheme = Theme.of(context).colorScheme; return Card( child: Column( children: [ FutureBuilder>( future: apiService.get('/payments/phonepe/settings/upi'), builder: (ctx, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.secondaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.account_balance_rounded, color: scheme.onSecondaryContainer, size: 24.w, ), ), title: Text( l10n.upiIdTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.loading, style: TextStyle(fontSize: 14.sp), ), ); } final upiId = snapshot.data?['data']?['upi_id'] ?? l10n.notConfigured; final isConfigured = snapshot.data?['data']?['is_configured'] ?? false; return ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: isConfigured ? scheme.secondaryContainer : scheme.tertiaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.account_balance_rounded, color: isConfigured ? scheme.onSecondaryContainer : scheme.onTertiaryContainer, size: 24.w, ), ), title: Row( children: [ Text( l10n.upiIdTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), if (isConfigured) ...[ SizedBox(width: 8.w), Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Text( l10n.active, style: TextStyle( fontSize: 10.sp, fontWeight: FontWeight.w600, color: scheme.onPrimaryContainer, ), ), ), ], ], ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 4.h), SelectableText( upiId.toString(), style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: isConfigured ? scheme.onSecondaryContainer : scheme.onTertiaryContainer, fontFamily: 'monospace', ), ), if (!isConfigured) ...[ SizedBox(height: 4.h), Text( l10n.configureBackend, style: TextStyle( fontSize: 12.sp, color: scheme.tertiary, fontStyle: FontStyle.italic, ), ), ], ], ), trailing: isConfigured ? IconButton( onPressed: () { Clipboard.setData(ClipboardData(text: upiId.toString())); SnackbarUtil.showSuccess(l10n.upiCopiedClipboard); }, icon: Icon( Icons.copy_rounded, size: 20.w, color: scheme.secondary, ), tooltip: l10n.copyUpiIdTooltip, ) : Icon( Icons.warning_rounded, size: 20.w, color: scheme.tertiary, ), onTap: () => _showUPIInfoDialog(context, l10n, upiId.toString(), isConfigured), ); }, ), Divider(height: 1.h, indent: 72.w), ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.payment_rounded, color: scheme.onPrimaryContainer, size: 24.w, ), ), title: Text( l10n.paymentStatisticsTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.paymentStatisticsSubtitle, style: TextStyle(fontSize: 14.sp), ), trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w), onTap: () { SnackbarUtil.showInfo(l10n.paymentStatsComingSoon); }, ), Divider(height: 1.h, indent: 72.w), ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.currency_rupee_rounded, color: scheme.onPrimaryContainer, size: 24.w, ), ), title: Text( l10n.transactionFeesTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( l10n.transactionFeesSubtitle, style: TextStyle( fontSize: 14.sp, color: scheme.primary, fontWeight: FontWeight.w600, ), ), trailing: Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(8.r), ), child: Text( l10n.free, style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w800, color: scheme.onPrimaryContainer, ), ), ), ), ], ), ); } void _showUPIInfoDialog( BuildContext context, AppLocalizations l10n, String upiId, bool isConfigured, ) { final scheme = Theme.of(context).colorScheme; Get.dialog( AlertDialog( title: Row( children: [ Icon( Icons.account_balance_rounded, color: scheme.secondary, size: 24.w, ), SizedBox(width: 12.w), Expanded(child: Text(l10n.upiPaymentSettingsTitle)), ], ), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.currentUpiId, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: scheme.onSurfaceVariant, ), ), SizedBox(height: 8.h), Container( width: double.infinity, padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: isConfigured ? scheme.secondaryContainer : scheme.tertiaryContainer, borderRadius: BorderRadius.circular(8.r), border: Border.all( color: isConfigured ? scheme.outlineVariant : scheme.tertiary.withOpacity(0.4), ), ), child: Row( children: [ Expanded( child: SelectableText( upiId, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w700, color: isConfigured ? scheme.onSecondaryContainer : scheme.onTertiaryContainer, fontFamily: 'monospace', ), ), ), if (isConfigured) IconButton( onPressed: () { Clipboard.setData(ClipboardData(text: upiId)); SnackbarUtil.showSuccess(l10n.copied); }, icon: Icon( Icons.copy_rounded, size: 20.w, color: scheme.secondary, ), ), ], ), ), if (!isConfigured) ...[ SizedBox(height: 16.h), Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: scheme.tertiaryContainer, borderRadius: BorderRadius.circular(8.r), ), child: Row( children: [ Icon( Icons.warning_rounded, color: scheme.onTertiaryContainer, size: 20.w, ), SizedBox(width: 8.w), Expanded( child: Text( l10n.upiNotConfiguredMessage, style: TextStyle( fontSize: 12.sp, color: scheme.onTertiaryContainer, ), ), ), ], ), ), ], SizedBox(height: 16.h), const Divider(), SizedBox(height: 16.h), Text( l10n.howToUpdateUpi, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: scheme.onSurfaceVariant, ), ), SizedBox(height: 12.h), _buildInfoStep(context, '1', l10n.stepOpenEnv), _buildInfoStep(context, '2', l10n.stepUpdatePhonepe), _buildInfoStep(context, '3', l10n.stepRestartBackend), _buildInfoStep(context, '4', l10n.stepRefreshScreen), SizedBox(height: 16.h), Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(8.r), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.lightbulb_rounded, color: scheme.onPrimaryContainer, size: 18.w, ), SizedBox(width: 8.w), Text( l10n.proTipTitle, style: TextStyle( fontSize: 13.sp, fontWeight: FontWeight.w600, color: scheme.onPrimaryContainer, ), ), ], ), SizedBox(height: 8.h), Text( l10n.proTipBody, style: TextStyle( fontSize: 12.sp, color: scheme.onPrimaryContainer.withOpacity(0.92), height: 1.4, ), ), ], ), ), ], ), ), actions: [ TextButton( onPressed: () => Get.back(), child: Text(l10n.close), ), ], ), ); } Widget _buildInfoStep(BuildContext context, String number, String text) { final scheme = Theme.of(context).colorScheme; return Padding( padding: EdgeInsets.only(bottom: 8.h), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 24.w, height: 24.w, decoration: BoxDecoration( color: scheme.secondaryContainer, shape: BoxShape.circle, ), child: Center( child: Text( number, style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w700, color: scheme.onSecondaryContainer, ), ), ), ), SizedBox(width: 12.w), Expanded( child: Padding( padding: EdgeInsets.only(top: 2.h), child: Text( text, style: TextStyle( fontSize: 13.sp, color: scheme.onSurfaceVariant, height: 1.4, ), ), ), ), ], ), ); } Widget _buildAboutSettings(BuildContext context, AppLocalizations l10n) { final scheme = Theme.of(context).colorScheme; return Card( child: Column( children: [ ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.info_rounded, color: scheme.onPrimaryContainer, size: 24.w, ), ), title: Text( l10n.appVersionTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), subtitle: Text( '1.0.0', style: TextStyle(fontSize: 14.sp), ), ), Divider(height: 1.h, indent: 72.w), ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.primaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.privacy_tip_rounded, color: scheme.onPrimaryContainer, size: 24.w, ), ), title: Text( l10n.privacyPolicyTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w), onTap: () { SnackbarUtil.showInfo(l10n.privacyComingSoon); }, ), Divider(height: 1.h, indent: 72.w), ListTile( leading: Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: scheme.secondaryContainer, borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.description_rounded, color: scheme.onSecondaryContainer, size: 24.w, ), ), title: Text( l10n.termsOfServiceTitle, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w), onTap: () { SnackbarUtil.showInfo(l10n.termsComingSoon); }, ), ], ), ); } Widget _buildLogoutButton(BuildContext context, AppLocalizations l10n) { return SizedBox( width: double.infinity, height: 52.h, child: ElevatedButton.icon( onPressed: () => _showLogoutDialog(context, l10n), icon: Icon(Icons.logout_rounded, size: 20.w), label: Text( l10n.logout, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.error, foregroundColor: Theme.of(context).colorScheme.onError, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.r), ), ), ), ); } void _showThemeDialog(BuildContext context, AppLocalizations l10n) { final scheme = Theme.of(context).colorScheme; Get.dialog( AlertDialog( title: Text(l10n.chooseThemeTitle), content: Column( mainAxisSize: MainAxisSize.min, children: [ RadioListTile( title: Text(l10n.themeLight), value: ThemeMode.light, groupValue: ThemeController.to.themeMode, onChanged: (value) { ThemeController.to.setLightTheme(); Get.back(); }, activeColor: scheme.primary, ), RadioListTile( title: Text(l10n.themeDark), value: ThemeMode.dark, groupValue: ThemeController.to.themeMode, onChanged: (value) { ThemeController.to.setDarkTheme(); Get.back(); }, activeColor: scheme.primary, ), RadioListTile( title: Text(l10n.themeSystem), value: ThemeMode.system, groupValue: ThemeController.to.themeMode, onChanged: (value) { ThemeController.to.setSystemTheme(); Get.back(); }, activeColor: scheme.primary, ), ], ), ), ); } void _showLogoutDialog(BuildContext context, AppLocalizations l10n) { showDialog( context: context, builder: (context) => AlertDialog( title: Text(l10n.logoutConfirmTitle), content: Text(l10n.logoutConfirmMessage), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(l10n.cancel), ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); AuthService.to.logout(); SnackbarUtil.showSuccess(l10n.loggedOutSuccess); }, style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.error, foregroundColor: Theme.of(context).colorScheme.onError, ), child: Text(l10n.logout), ), ], ), ); } }