import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../l10n/app_localizations.dart'; import '../theme/app_colors.dart'; import '../theme/app_text_styles.dart'; /// Settings Screen - MVP version with duration presets class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); /// Get the saved default duration (for use in other screens) static Future getDefaultDuration() async { final prefs = await SharedPreferences.getInstance(); return prefs.getInt(_durationKey) ?? 25; } /// Get the saved locale static Future getSavedLocale() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString(_localeKey); } /// Save the locale static Future saveLocale(String localeCode) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(_localeKey, localeCode); } static const String _durationKey = 'default_duration'; static const String _localeKey = 'app_locale'; @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { int _selectedDuration = 25; // Default String _selectedLocale = 'en'; // Default final List _durationOptions = [15, 25, 45]; @override void initState() { super.initState(); _loadSavedDuration(); _loadSavedLocale(); } Future _loadSavedDuration() async { final prefs = await SharedPreferences.getInstance(); setState(() { _selectedDuration = prefs.getInt(SettingsScreen._durationKey) ?? 25; }); } Future _loadSavedLocale() async { final prefs = await SharedPreferences.getInstance(); setState(() { _selectedLocale = prefs.getString(SettingsScreen._localeKey) ?? 'en'; }); } Future _saveDuration(int duration) async { final prefs = await SharedPreferences.getInstance(); await prefs.setInt(SettingsScreen._durationKey, duration); setState(() { _selectedDuration = duration; }); } Future _saveLocale(String localeCode) async { await SettingsScreen.saveLocale(localeCode); setState(() { _selectedLocale = localeCode; }); // Show snackbar to inform user to restart if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context)!.onboardingReset), duration: const Duration(seconds: 2), ), ); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Scaffold( backgroundColor: AppColors.background, appBar: AppBar( title: Text(l10n.settings), backgroundColor: AppColors.background, ), body: ListView( padding: const EdgeInsets.all(24), children: [ // Focus Duration Section _buildSection( title: l10n.focusSettings, children: [ Padding( padding: const EdgeInsets.only(bottom: 16), child: Text( l10n.defaultFocusDuration, style: AppTextStyles.bodyText, ), ), ..._durationOptions.map((duration) { return _buildDurationOption(l10n, duration); }), ], ), const SizedBox(height: 32), // Language Section _buildSection( title: l10n.language, children: [ _buildLanguageOption(l10n, 'en', l10n.english), const Divider(color: AppColors.divider), _buildLanguageOption(l10n, 'zh', l10n.chinese), ], ), const SizedBox(height: 32), // About Section _buildSection( title: l10n.about, children: [ ListTile( contentPadding: EdgeInsets.zero, title: Text( l10n.privacyPolicy, style: AppTextStyles.bodyText, ), trailing: const Icon( Icons.arrow_forward_ios, size: 16, color: AppColors.textSecondary, ), onTap: () { _showPrivacyPolicy(); }, ), const Divider(color: AppColors.divider), ListTile( contentPadding: EdgeInsets.zero, title: Text( l10n.aboutFocusBuddy, style: AppTextStyles.bodyText, ), trailing: const Icon( Icons.arrow_forward_ios, size: 16, color: AppColors.textSecondary, ), onTap: () { _showAboutDialog(); }, ), const Divider(color: AppColors.divider), ListTile( contentPadding: EdgeInsets.zero, title: Text( l10n.resetOnboarding, style: AppTextStyles.bodyText.copyWith( color: AppColors.textSecondary, ), ), trailing: const Icon( Icons.refresh, size: 16, color: AppColors.textSecondary, ), onTap: () { _resetOnboarding(); }, ), ], ), const SizedBox(height: 32), // Version info Center( child: Text( l10n.version, style: AppTextStyles.helperText.copyWith(fontSize: 12), ), ), ], ), ); } Widget _buildSection({ required String title, required List children, }) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.white, borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontFamily: 'Nunito', fontSize: 18, fontWeight: FontWeight.w600, color: AppColors.textPrimary, ), ), const SizedBox(height: 16), ...children, ], ), ); } Widget _buildDurationOption(AppLocalizations l10n, int duration) { final isSelected = _selectedDuration == duration; return GestureDetector( onTap: () => _saveDuration(duration), child: Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: isSelected ? AppColors.primary.withValues(alpha: 0.1) : AppColors.background, border: Border.all( color: isSelected ? AppColors.primary : AppColors.divider, width: isSelected ? 2 : 1, ), borderRadius: BorderRadius.circular(12), ), child: Row( children: [ // Radio button Container( width: 20, height: 20, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: isSelected ? AppColors.primary : AppColors.textSecondary, width: 2, ), color: isSelected ? AppColors.primary : Colors.transparent, ), child: isSelected ? const Center( child: Icon( Icons.check, size: 12, color: AppColors.white, ), ) : null, ), const SizedBox(width: 16), // Duration text Expanded( child: Text( l10n.minutesValue(duration, l10n.minutes(duration)), style: TextStyle( fontFamily: 'Nunito', fontSize: 16, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, color: isSelected ? AppColors.primary : AppColors.textPrimary, ), ), ), // Description if (duration == 25) Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: AppColors.success.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Text( l10n.defaultLabel, style: const TextStyle( fontFamily: 'Nunito', fontSize: 12, fontWeight: FontWeight.w600, color: AppColors.success, ), ), ), ], ), ), ); } Widget _buildLanguageOption(AppLocalizations l10n, String localeCode, String label) { final isSelected = _selectedLocale == localeCode; return ListTile( contentPadding: EdgeInsets.zero, title: Text( label, style: TextStyle( fontFamily: 'Nunito', fontSize: 16, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, color: isSelected ? AppColors.primary : AppColors.textPrimary, ), ), trailing: isSelected ? const Icon( Icons.check_circle, color: AppColors.primary, ) : null, onTap: () => _saveLocale(localeCode), ); } void _showPrivacyPolicy() { final l10n = AppLocalizations.of(context)!; showDialog( context: context, builder: (context) => AlertDialog( title: Text(l10n.privacyPolicyTitle), content: SingleChildScrollView( child: Text( l10n.privacyPolicyContent, style: AppTextStyles.bodyText, ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text(l10n.close), ), ], ), ); } void _showAboutDialog() { final l10n = AppLocalizations.of(context)!; showDialog( context: context, builder: (context) => AlertDialog( title: Text(l10n.aboutTitle), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.appTitle, style: const TextStyle( fontFamily: 'Nunito', fontSize: 20, fontWeight: FontWeight.w700, color: AppColors.primary, ), ), const SizedBox(height: 8), Text( l10n.aboutSubtitle, style: AppTextStyles.bodyText, ), const SizedBox(height: 16), Text( l10n.aboutQuote, style: AppTextStyles.encouragementQuote, ), const SizedBox(height: 16), Text( l10n.aboutFeatures, style: AppTextStyles.bodyText, ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text(l10n.close), ), ], ), ); } void _resetOnboarding() async { final l10n = AppLocalizations.of(context)!; showDialog( context: context, builder: (context) => AlertDialog( title: Text(l10n.resetOnboardingTitle), content: Text( l10n.resetOnboardingMessage, style: AppTextStyles.bodyText, ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text(l10n.cancel), ), TextButton( onPressed: () async { final prefs = await SharedPreferences.getInstance(); await prefs.remove('onboarding_completed'); if (!context.mounted) return; Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(l10n.onboardingReset), duration: const Duration(seconds: 3), ), ); }, child: Text(l10n.reset), ), ], ), ); } }