import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../services/notification_service.dart'; import '../../services/user_service.dart'; import '../../services/auth_service.dart'; import '../../services/post_service.dart'; import '../../models/post_models.dart'; class ProfilePage extends StatefulWidget { @override _ProfilePageState createState() => _ProfilePageState(); } class _ProfilePageState extends State { String? fcmToken; final TextEditingController _tokenController = TextEditingController(); bool isLoading = false; Map? userData; bool isLoadingUser = true; List userPosts = []; bool isLoadingPosts = true; int totalLikes = 0; @override void initState() { super.initState(); _loadFCMToken(); _loadUserData(); _loadUserPosts(); } @override void dispose() { _tokenController.dispose(); super.dispose(); } Future _loadFCMToken() async { setState(() { isLoading = true; }); try { final token = await NotificationService().getToken(); setState(() { fcmToken = token; _tokenController.text = token ?? 'Token not available'; isLoading = false; }); } catch (e) { setState(() { fcmToken = null; _tokenController.text = 'Error loading token: $e'; isLoading = false; }); } } Future _loadUserData() async { setState(() { isLoadingUser = true; }); final result = await UserService.getCurrentUser(); setState(() { isLoadingUser = false; if (result['success'] == true) { userData = result['data']; } else { userData = null; _showErrorAlert(result['message'] ?? 'Failed to load user data'); } }); } Future _loadUserPosts() async { setState(() { isLoadingPosts = true; }); final result = await PostService.getUserPosts(); setState(() { isLoadingPosts = false; if (result['success'] == true) { userPosts = result['posts'] as List; totalLikes = userPosts.fold(0, (sum, post) => sum + post.likes); } else { userPosts = []; totalLikes = 0; _showErrorAlert(result['message'] ?? 'Failed to load posts'); } }); } void _showErrorAlert(String message) { showDialog( context: context, builder: (context) => AlertDialog( title: Text('Error'), content: Text(message), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text('OK', style: TextStyle(color: Color(0xFF6A4C93))), ), ], ), ); } Future _copyToClipboard() async { if (fcmToken != null && fcmToken!.isNotEmpty) { await Clipboard.setData(ClipboardData(text: fcmToken!)); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('FCM Token copied to clipboard'), backgroundColor: Color(0xFF6A4C93), ), ); } } void _navigateToSettings() { Navigator.of( context, ).push(MaterialPageRoute(builder: (context) => SettingsPage())); } String _formatTimestamp(DateTime dateTime) { final now = DateTime.now(); final difference = now.difference(dateTime); if (difference.inDays > 0) { return '${difference.inDays}d ago'; } else if (difference.inHours > 0) { return '${difference.inHours}h ago'; } else if (difference.inMinutes > 0) { return '${difference.inMinutes}m ago'; } else { return 'Just now'; } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Profile', style: TextStyle(fontWeight: FontWeight.w600)), backgroundColor: Colors.white, foregroundColor: Color(0xFF6A4C93), elevation: 0, actions: [ IconButton( onPressed: _navigateToSettings, icon: Icon(Icons.settings), ), ], bottom: PreferredSize( preferredSize: Size.fromHeight(1), child: Container(height: 1, color: Colors.grey[200]), ), automaticallyImplyLeading: false, ), body: SingleChildScrollView( child: Column( children: [ Container( padding: EdgeInsets.all(24), child: Column( children: [ if (isLoadingUser) CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( Color(0xFF6A4C93), ), ) else if (userData != null) ...[ CircleAvatar( radius: 50, backgroundColor: Color(0xFF6A4C93), child: Text( (userData!['displayName'] ?? 'U') .substring(0, 1) .toUpperCase(), style: TextStyle( color: Colors.white, fontSize: 36, fontWeight: FontWeight.bold, ), ), ), SizedBox(height: 16), Text( userData!['displayName'] ?? 'Unknown User', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black87, ), ), SizedBox(height: 4), Text( '@${userData!['username'] ?? 'unknown'}', style: TextStyle(fontSize: 16, color: Colors.grey[600]), ), ] else ...[ Icon( Icons.error_outline, size: 50, color: Colors.grey[400], ), SizedBox(height: 16), Text( 'Failed to load user data', style: TextStyle(fontSize: 18, color: Colors.grey[600]), ), SizedBox(height: 8), ElevatedButton( onPressed: _loadUserData, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF6A4C93), foregroundColor: Colors.white, ), child: Text('Retry'), ), ], SizedBox(height: 20), if (userData != null) Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Column( children: [ Text( '${userPosts.length}', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Color(0xFF6A4C93), ), ), Text( 'Posts', style: TextStyle( fontSize: 14, color: Colors.grey[600], ), ), ], ), Column( children: [ Text( '$totalLikes', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Color(0xFF6A4C93), ), ), Text( 'Likes Received', style: TextStyle( fontSize: 14, color: Colors.grey[600], ), ), ], ), ], ), ], ), ), if (userData != null) ...[ Container( height: 1, color: Colors.grey[200], margin: EdgeInsets.symmetric(horizontal: 16), ), SizedBox(height: 16), if (isLoadingPosts) Container( padding: EdgeInsets.all(32), child: Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( Color(0xFF6A4C93), ), ), ), ) else if (userPosts.isEmpty) Container( padding: EdgeInsets.all(32), child: Center( child: Column( children: [ Icon( Icons.post_add, size: 64, color: Colors.grey[400], ), SizedBox(height: 16), Text( 'No posts yet', style: TextStyle( fontSize: 18, color: Colors.grey[600], fontWeight: FontWeight.w500, ), ), SizedBox(height: 8), Text( 'Start sharing your thoughts!', style: TextStyle( fontSize: 14, color: Colors.grey[500], ), ), ], ), ), ) else ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.symmetric(horizontal: 16), itemCount: userPosts.length, itemBuilder: (context, index) { final post = userPosts[index]; return Container( margin: EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: Offset(0, 2), ), ], ), child: Padding( padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ CircleAvatar( radius: 16, backgroundColor: Color(0xFF6A4C93), child: Text( post.creator.displayName.isNotEmpty ? post.creator.displayName .substring(0, 1) .toUpperCase() : 'U', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 14, ), ), ), SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( post.creator.displayName.isNotEmpty ? post.creator.displayName : 'Unknown User', style: TextStyle( fontWeight: FontWeight.w600, fontSize: 14, color: Colors.black87, ), ), Text( _formatTimestamp(post.creationDate), style: TextStyle( color: Colors.grey[600], fontSize: 12, ), ), ], ), ), ], ), SizedBox(height: 12), Text( post.body, style: TextStyle( fontSize: 15, height: 1.4, color: Colors.black87, ), ), SizedBox(height: 12), Row( children: [ Icon( Icons.favorite_border, color: Colors.grey[600], size: 20, ), SizedBox(width: 4), Text( '${post.likes}', style: TextStyle( color: Colors.grey[700], fontSize: 14, ), ), SizedBox(width: 16), Icon( Icons.chat_bubble_outline, color: Colors.grey[600], size: 20, ), SizedBox(width: 4), Text( '${post.comments}', style: TextStyle( color: Colors.grey[700], fontSize: 14, ), ), ], ), ], ), ), ); }, ), ], SizedBox(height: 24), ], ), ), ); } } class SettingsPage extends StatefulWidget { @override _SettingsPageState createState() => _SettingsPageState(); } class _SettingsPageState extends State { String? fcmToken; final TextEditingController _tokenController = TextEditingController(); bool isLoading = false; @override void initState() { super.initState(); _loadFCMToken(); } @override void dispose() { _tokenController.dispose(); super.dispose(); } Future _loadFCMToken() async { setState(() { isLoading = true; }); try { final token = await NotificationService().getToken(); setState(() { fcmToken = token; _tokenController.text = token ?? 'Token not available'; isLoading = false; }); } catch (e) { setState(() { fcmToken = null; _tokenController.text = 'Error loading token: $e'; isLoading = false; }); } } Future _copyToClipboard() async { if (fcmToken != null && fcmToken!.isNotEmpty) { await Clipboard.setData(ClipboardData(text: fcmToken!)); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('FCM Token copied to clipboard'), backgroundColor: Color(0xFF6A4C93), ), ); } } void _signOut() async { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text('Sign Out'), content: Text('Are you sure you want to sign out?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text('Cancel'), ), TextButton( onPressed: () async { Navigator.of(context).pop(); await AuthService.logout(); Navigator.of( context, ).pushNamedAndRemoveUntil('/', (route) => false); }, child: Text('Sign Out', style: TextStyle(color: Colors.red)), ), ], ); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Settings', style: TextStyle(fontWeight: FontWeight.w600)), backgroundColor: Colors.white, foregroundColor: Color(0xFF6A4C93), elevation: 0, bottom: PreferredSize( preferredSize: Size.fromHeight(1), child: Container(height: 1, color: Colors.grey[200]), ), automaticallyImplyLeading: true, ), body: Padding( padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Development Tools', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, color: Color(0xFF6A4C93), ), ), SizedBox(height: 16), Text( 'FCM Token:', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: Colors.black87, ), ), SizedBox(height: 8), if (isLoading) Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Color(0xFF6A4C93)), ), ) else Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey[300]!), borderRadius: BorderRadius.circular(8), ), child: TextField( controller: _tokenController, readOnly: true, maxLines: 4, style: TextStyle(fontSize: 12, fontFamily: 'monospace'), decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.all(12), hintText: 'FCM Token will appear here...', ), ), ), SizedBox(height: 8), Row( children: [ ElevatedButton.icon( onPressed: fcmToken != null ? _copyToClipboard : null, icon: Icon(Icons.copy, size: 18), label: Text('Copy Token'), style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF6A4C93), foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), SizedBox(width: 12), OutlinedButton.icon( onPressed: _loadFCMToken, icon: Icon(Icons.refresh, size: 18), label: Text('Refresh'), style: OutlinedButton.styleFrom( foregroundColor: Color(0xFF6A4C93), side: BorderSide(color: Color(0xFF6A4C93)), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), ], ), ], ), SizedBox(height: 32), Container( width: double.infinity, child: ElevatedButton.icon( onPressed: _signOut, icon: Icon(Icons.logout, color: Colors.red), label: Text('Sign Out', style: TextStyle(color: Colors.red)), style: ElevatedButton.styleFrom( backgroundColor: Colors.white, side: BorderSide(color: Colors.red), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), padding: EdgeInsets.symmetric(vertical: 16), ), ), ), ], ), ), ); } }