import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../providers/auth_provider.dart'; import '../providers/settings_provider.dart'; import '../theme.dart'; import '../l10n/app_localizations.dart'; class SettingsPage extends ConsumerStatefulWidget { const SettingsPage({super.key}); @override ConsumerState createState() => _SettingsPageState(); } class _SettingsPageState extends ConsumerState { final ScrollController _scrollController = ScrollController(); bool _scrolled = false; static const double _scrollThreshold = 120; @override void initState() { super.initState(); _scrollController.addListener(_onScroll); } @override void dispose() { _scrollController.removeListener(_onScroll); _scrollController.dispose(); super.dispose(); } void _onScroll() { final shouldBe = _scrollController.offset > _scrollThreshold; if (shouldBe != _scrolled) { setState(() => _scrolled = shouldBe); } } void _showThemePicker(BuildContext context) { final current = ref.read(settingsProvider).themeMode; showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (ctx) { final l10n = AppLocalizations.of(ctx)!; return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.surface, borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), ), child: SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container(width: 40, height: 4, decoration: BoxDecoration(color: AppColors.divider, borderRadius: BorderRadius.circular(2))), const SizedBox(height: 20), Text(l10n.themeSettings, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: AppColors.textPrimary)), const SizedBox(height: 20), _themeOption(ctx, AppThemeMode.light, l10n.lightMode, Icons.wb_sunny_outlined, current), _themeOption(ctx, AppThemeMode.dark, l10n.darkMode, Icons.nights_stay_outlined, current), _themeOption(ctx, AppThemeMode.system, l10n.followSystem, Icons.settings_suggest_outlined, current), ], ), ), ); }, ); } Widget _themeOption(BuildContext ctx, AppThemeMode mode, String label, IconData icon, AppThemeMode current) { final selected = current == mode; return ListTile( leading: Icon(icon, color: selected ? AppColors.primary : AppColors.textTertiary), title: Text(label, style: TextStyle(fontWeight: selected ? FontWeight.w600 : FontWeight.w400, color: AppColors.textPrimary)), trailing: selected ? const Icon(Icons.check_circle, color: AppColors.primary) : null, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), onTap: () { ref.read(settingsProvider.notifier).setThemeMode(mode); Navigator.of(ctx).pop(); }, ); } void _showLanguagePicker(BuildContext context) { final current = ref.read(settingsProvider).locale; showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (ctx) { final l10n = AppLocalizations.of(ctx)!; return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.surface, borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), ), child: SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container(width: 40, height: 4, decoration: BoxDecoration(color: AppColors.divider, borderRadius: BorderRadius.circular(2))), const SizedBox(height: 20), Text(l10n.languageSettings, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: AppColors.textPrimary)), const SizedBox(height: 20), _languageOption(ctx, const Locale('zh', 'CN'), l10n.simplifiedChinese, current), _languageOption(ctx, const Locale('en', 'US'), l10n.english, current), _languageOption(ctx, const Locale('th', 'TH'), l10n.thai, current), ], ), ), ); }, ); } Widget _languageOption(BuildContext ctx, Locale locale, String label, Locale current) { final selected = current.languageCode == locale.languageCode; return ListTile( title: Text(label, style: TextStyle(fontWeight: selected ? FontWeight.w600 : FontWeight.w400, color: AppColors.textPrimary)), trailing: selected ? const Icon(Icons.check_circle, color: AppColors.primary) : null, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), onTap: () { ref.read(settingsProvider.notifier).setLocale(locale); Navigator.of(ctx).pop(); }, ); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final authState = ref.watch(authProvider); final settings = ref.watch(settingsProvider); final user = authState.user; final isBoss = user?.isBoss ?? false; final themeLabel = switch (settings.themeMode) { AppThemeMode.light => l10n.lightMode, AppThemeMode.dark => l10n.darkMode, AppThemeMode.system => l10n.followSystem, }; final localeLabel = switch (settings.locale.languageCode) { 'zh' => l10n.simplifiedChinese, 'en' => l10n.english, 'th' => l10n.thai, _ => l10n.simplifiedChinese, }; return AnnotatedRegion( value: _scrolled ? (AppColors.isDark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark) : SystemUiOverlayStyle.light, child: Scaffold( backgroundColor: AppColors.background, body: Stack( children: [ ListView( controller: _scrollController, padding: EdgeInsets.zero, children: [ _buildHeader(context, user, l10n, isBoss), Padding( padding: const EdgeInsets.fromLTRB(20, 28, 20, 32), child: Column( children: [ Align( alignment: Alignment.centerLeft, child: _buildSectionTitle(l10n.appConfiguration), ), const SizedBox(height: 14), _buildSettingsCard([ _SettingItem( icon: Icons.notifications_outlined, iconColor: const Color(0xFF8B5CF6), title: l10n.pushNotification, subtitle: settings.pushNotification ? l10n.enabled : l10n.disabled, trailing: Switch( value: settings.pushNotification, onChanged: (v) => ref.read(settingsProvider.notifier).setPushNotification(v), activeTrackColor: AppColors.primary, ), onTap: () => ref.read(settingsProvider.notifier).setPushNotification(!settings.pushNotification), ), _SettingItem( icon: Icons.volume_up_outlined, iconColor: const Color(0xFFEC4899), title: l10n.soundNotification, subtitle: settings.soundNotification ? l10n.enabled : l10n.disabled, trailing: Switch( value: settings.soundNotification, onChanged: (v) => ref.read(settingsProvider.notifier).setSoundNotification(v), activeTrackColor: AppColors.primary, ), onTap: () => ref.read(settingsProvider.notifier).setSoundNotification(!settings.soundNotification), ), _SettingItem( icon: Icons.palette_outlined, iconColor: const Color(0xFFEC4899), title: l10n.themeSettings, subtitle: themeLabel, onTap: () => _showThemePicker(context), ), _SettingItem( icon: Icons.language_outlined, iconColor: const Color(0xFF3B82F6), title: l10n.languageSettings, subtitle: localeLabel, onTap: () => _showLanguagePicker(context), ), ]), const SizedBox(height: 28), Align( alignment: Alignment.centerLeft, child: _buildSectionTitle(l10n.businessExtension), ), const SizedBox(height: 14), _buildSettingsCard([ _SettingItem( icon: Icons.people_outline, iconColor: const Color(0xFF10B981), title: l10n.employeeManagement, subtitle: l10n.employeeDesc, showBadge: isBoss, onTap: () => context.push('/settings/employees'), ), _SettingItem( icon: Icons.analytics_outlined, iconColor: const Color(0xFFEF4444), title: l10n.dataReport, subtitle: l10n.reportDesc, showBadge: isBoss, onTap: () => context.push('/settings/report'), ), _SettingItem( icon: Icons.extension_outlined, iconColor: const Color(0xFF6366F1), title: l10n.appMarket, subtitle: l10n.marketDesc, onTap: () => context.push('/settings/app-market'), ), ]), const SizedBox(height: 28), Align( alignment: Alignment.centerLeft, child: _buildSectionTitle(l10n.system), ), const SizedBox(height: 14), _buildSettingsCard([ _SettingItem( icon: Icons.help_outline, iconColor: const Color(0xFF64748B), title: l10n.helpCenter, subtitle: l10n.helpDesc, onTap: () => context.push('/settings/help'), ), _SettingItem( icon: Icons.info_outline, iconColor: const Color(0xFF64748B), title: l10n.aboutUs, subtitle: '${l10n.version} 1.0.0', onTap: () => context.push('/settings/about'), ), ]), const SizedBox(height: 36), SizedBox( width: double.infinity, height: 52, child: ElevatedButton( onPressed: () { ref.read(authProvider.notifier).logout(); context.go('/login'); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.error.withValues(alpha: 0.1), foregroundColor: AppColors.error, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), child: Text( l10n.logout, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), ), ), ], ), ), ], ), Positioned( top: 0, left: 0, right: 0, child: SafeArea( bottom: false, child: SizedBox( height: 44, child: Align( alignment: Alignment.centerLeft, child: IconButton( icon: Icon( Icons.arrow_back_ios_new, color: _scrolled ? AppColors.textPrimary : Colors.white, size: 20, ), onPressed: () { if (Navigator.of(context).canPop()) { Navigator.of(context).pop(); } else { context.go('/home'); } }, ), ), ), ), ), ], ), ), ); } Widget _buildHeader(BuildContext context, user, AppLocalizations l10n, bool isBoss) { final initial = (user?.name is String && (user!.name as String).isNotEmpty) ? (user.name as String).substring(0, 1) : l10n.user.substring(0, 1); return Container( decoration: BoxDecoration( gradient: AppGradients.primary, borderRadius: const BorderRadius.vertical(bottom: Radius.circular(28)), ), child: SafeArea( bottom: false, child: Padding( padding: const EdgeInsets.fromLTRB(12, 60, 12, 36), child: Column( children: [ Container( width: 96, height: 96, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withValues(alpha: 0.16), border: Border.all( color: Colors.white.withValues(alpha: 0.32), width: 1.5, ), ), child: Center( child: Text( initial, style: const TextStyle( fontSize: 36, fontWeight: FontWeight.w700, color: Colors.white, ), ), ), ), const SizedBox(height: 18), Text( user?.name ?? l10n.user, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.w700, color: Colors.white, letterSpacing: 1.5, ), ), const SizedBox(height: 8), Text( user?.phone ?? '', style: TextStyle( fontSize: 14, color: Colors.white.withValues(alpha: 0.82), letterSpacing: 1, ), ), const SizedBox(height: 18), Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.22), borderRadius: BorderRadius.circular(22), ), child: Text( isBoss ? l10n.boss : l10n.employee, style: const TextStyle( fontSize: 13, color: Colors.white, fontWeight: FontWeight.w500, letterSpacing: 1.5, ), ), ), ], ), ), ), ); } Widget _buildSectionTitle(String title) { return Padding( padding: const EdgeInsets.only(left: 4), child: Text( title, style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: AppColors.textSecondary, letterSpacing: 1.2, ), ), ); } Widget _buildSettingsCard(List<_SettingItem> items) { return Container( decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.03), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: items.asMap().entries.map((entry) { final item = entry.value; final isLast = entry.key == items.length - 1; return Column( children: [ ListTile( leading: Container( width: 40, height: 40, decoration: BoxDecoration( color: item.iconColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10), ), child: Icon(item.icon, color: item.iconColor, size: 20), ), title: Row( children: [ Text( item.title, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.textPrimary, ), ), if (item.showBadge) ...[ const SizedBox(width: 8), Container( width: 8, height: 8, decoration: const BoxDecoration( color: AppColors.error, shape: BoxShape.circle, ), ), ], ], ), subtitle: Text( item.subtitle, style: TextStyle( fontSize: 13, color: AppColors.textTertiary, ), ), trailing: item.trailing ?? Icon(Icons.chevron_right, color: AppColors.textTertiary, size: 20), onTap: item.onTap, ), if (!isLast) const Divider(height: 1, indent: 72), ], ); }).toList(), ), ); } } class _SettingItem { final IconData icon; final Color iconColor; final String title; final String subtitle; final VoidCallback onTap; final bool showBadge; final Widget? trailing; const _SettingItem({ required this.icon, required this.iconColor, required this.title, required this.subtitle, required this.onTap, this.showBadge = false, this.trailing, }); }