import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:image_picker/image_picker.dart'; import '../app/app_state.dart'; import '../app/app_router.dart'; import '../services/api.dart'; import '../services/auth_storage.dart'; import '../widgets/rescan_button.dart'; class AccountScreen extends StatefulWidget { const AccountScreen({super.key}); @override State createState() => _AccountScreenState(); } class _AccountScreenState extends State { bool _isLoggingOut = false; bool _isLoadingAvatar = true; bool _isUploadingAvatar = false; String? _avatarUrl; String? _userName; final ImagePicker _picker = ImagePicker(); @override void initState() { super.initState(); _loadAvatar(); _loadProfile(); } Future _loadAvatar() async { // Don't try to load avatar if not logged in final appState = context.read(); if (!appState.isLoggedIn) { setState(() => _isLoadingAvatar = false); return; } try { final avatarInfo = await Api.getAvatar(); if (mounted) { setState(() { _avatarUrl = avatarInfo.hasAvatar ? avatarInfo.avatarUrl : null; _isLoadingAvatar = false; }); } } catch (e) { debugPrint('Error loading avatar: $e'); if (mounted) { setState(() => _isLoadingAvatar = false); } } } Future _loadProfile() async { final appState = context.read(); if (!appState.isLoggedIn) return; try { final profile = await Api.getProfile(); if (mounted) { final firstName = profile.firstName; final lastInitial = profile.lastName.isNotEmpty ? '${profile.lastName[0]}.' : ''; setState(() { _userName = '$firstName $lastInitial'.trim(); }); } } catch (e) { debugPrint('Error loading profile: $e'); } } Future _pickAndUploadAvatar() async { // Check if user is logged in first final appState = context.read(); if (!appState.isLoggedIn) { final shouldLogin = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Login Required'), content: const Text('Please login to upload a profile photo.'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel'), ), FilledButton( onPressed: () => Navigator.pop(context, true), child: const Text('Login'), ), ], ), ); if (shouldLogin == true && mounted) { Navigator.of(context).pushNamed(AppRoutes.login); } return; } // Show picker options final source = await showModalBottomSheet( context: context, builder: (context) => SafeArea( child: Wrap( children: [ ListTile( leading: const Icon(Icons.camera_alt), title: const Text('Take Photo'), onTap: () => Navigator.pop(context, ImageSource.camera), ), ListTile( leading: const Icon(Icons.photo_library), title: const Text('Choose from Gallery'), onTap: () => Navigator.pop(context, ImageSource.gallery), ), ], ), ), ); if (source == null) return; try { final XFile? image = await _picker.pickImage( source: source, maxWidth: 500, maxHeight: 500, imageQuality: 85, ); if (image == null) return; setState(() => _isUploadingAvatar = true); final newAvatarUrl = await Api.uploadAvatar(image.path); if (mounted) { setState(() { _avatarUrl = newAvatarUrl; _isUploadingAvatar = false; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('Avatar updated! Servers can now recognize you.', style: TextStyle(color: Colors.black)), backgroundColor: const Color(0xFF90EE90), behavior: SnackBarBehavior.floating, margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); } } catch (e) { debugPrint('Error uploading avatar: $e'); if (mounted) { setState(() => _isUploadingAvatar = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Failed to upload avatar: $e', style: const TextStyle(color: Colors.black)), backgroundColor: const Color(0xFF90EE90), behavior: SnackBarBehavior.floating, margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); } } } Future _handleSignOut() async { final confirm = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Sign Out'), content: const Text('Are you sure you want to sign out?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('Sign Out'), ), ], ), ); if (confirm != true || !mounted) return; setState(() => _isLoggingOut = true); try { // Clear stored auth await AuthStorage.clearAuth(); // Clear API token Api.clearAuthToken(); // Clear app state if (mounted) { final appState = context.read(); appState.clearAll(); // Navigate to login Navigator.of(context).pushNamedAndRemoveUntil( AppRoutes.login, (route) => false, ); } } catch (e) { if (mounted) { setState(() => _isLoggingOut = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Error signing out: $e', style: const TextStyle(color: Colors.black)), backgroundColor: const Color(0xFF90EE90), behavior: SnackBarBehavior.floating, margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); } } } Widget _buildAvatar() { if (_isLoadingAvatar) { return CircleAvatar( radius: 40, backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, child: const SizedBox( width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2), ), ); } if (_isUploadingAvatar) { return Stack( children: [ CircleAvatar( radius: 40, backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, backgroundImage: _avatarUrl != null ? NetworkImage(_avatarUrl!) : null, child: _avatarUrl == null ? Icon( Icons.person, size: 40, color: Theme.of(context).colorScheme.onSurfaceVariant, ) : null, ), Positioned.fill( child: Container( decoration: BoxDecoration( color: Colors.black45, shape: BoxShape.circle, ), child: const Center( child: SizedBox( width: 24, height: 24, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ), ), ), ), ], ); } return GestureDetector( onTap: _pickAndUploadAvatar, child: Stack( children: [ CircleAvatar( radius: 40, backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, backgroundImage: _avatarUrl != null ? NetworkImage(_avatarUrl!) : null, child: _avatarUrl == null ? Icon( Icons.person, size: 40, color: Theme.of(context).colorScheme.onSurfaceVariant, ) : null, ), Positioned( right: 0, bottom: 0, child: Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, shape: BoxShape.circle, border: Border.all( color: Theme.of(context).colorScheme.surface, width: 2, ), ), child: Icon( Icons.camera_alt, size: 16, color: Theme.of(context).colorScheme.onPrimary, ), ), ), ], ), ); } @override Widget build(BuildContext context) { final appState = context.watch(); // If not logged in, show login prompt if (!appState.isLoggedIn) { return Scaffold( appBar: AppBar( title: const Text('Account'), actions: const [ RescanButton(), ], ), body: Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.person_outline, size: 80, color: Theme.of(context).colorScheme.onSurfaceVariant, ), const SizedBox(height: 24), Text( 'Sign in to access your account', style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( 'View order history, manage your profile, and more.', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), textAlign: TextAlign.center, ), const SizedBox(height: 32), FilledButton.icon( onPressed: () { Navigator.of(context).pushNamed(AppRoutes.login); }, icon: const Icon(Icons.login), label: const Text('Sign In'), style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16), ), ), ], ), ), ), ); } return Scaffold( appBar: AppBar( title: const Text('Account'), actions: const [ RescanButton(), ], ), body: ListView( children: [ // User info header with avatar Container( padding: const EdgeInsets.all(24), color: Theme.of(context).colorScheme.primaryContainer.withValues(alpha: 0.3), child: Column( children: [ _buildAvatar(), const SizedBox(height: 16), Text( _userName ?? 'User #${appState.userId ?? "?"}', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 4), Text( _avatarUrl != null ? 'Tap photo to update' : 'Tap to add a photo for server recognition', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], ), ), const SizedBox(height: 8), // Order History ListTile( leading: const Icon(Icons.receipt_long), title: const Text('Order History'), subtitle: const Text('View your past orders'), trailing: const Icon(Icons.chevron_right), onTap: () => Navigator.pushNamed(context, AppRoutes.orderHistory), ), const Divider(height: 1), // Delivery Addresses ListTile( leading: const Icon(Icons.location_on), title: const Text('Delivery Addresses'), subtitle: const Text('Manage your addresses'), trailing: const Icon(Icons.chevron_right), onTap: () => Navigator.pushNamed(context, AppRoutes.addressList), ), const Divider(height: 1), // Profile Settings ListTile( leading: const Icon(Icons.settings), title: const Text('Profile Settings'), subtitle: const Text('Update your name'), trailing: const Icon(Icons.chevron_right), onTap: () => Navigator.pushNamed(context, AppRoutes.profileSettings), ), const Divider(height: 1), // About Payfrit ListTile( leading: const Icon(Icons.info_outline), title: const Text('About Payfrit'), subtitle: const Text('App info and features'), trailing: const Icon(Icons.chevron_right), onTap: () => Navigator.pushNamed(context, AppRoutes.about), ), const Divider(height: 1), const SizedBox(height: 24), // Sign Out button Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: OutlinedButton.icon( onPressed: _isLoggingOut ? null : _handleSignOut, icon: _isLoggingOut ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.logout), label: Text(_isLoggingOut ? 'Signing out...' : 'Sign Out'), style: OutlinedButton.styleFrom( foregroundColor: Theme.of(context).colorScheme.error, side: BorderSide(color: Theme.of(context).colorScheme.error), padding: const EdgeInsets.symmetric(vertical: 12), ), ), ), const SizedBox(height: 32), ], ), ); } }