import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/auth_provider.dart'; import '../providers/chat_provider.dart'; import 'chat_conversation_screen.dart'; class ChatListScreen extends StatefulWidget { const ChatListScreen({super.key}); @override State createState() => _ChatListScreenState(); } class _ChatListScreenState extends State { @override void initState() { super.initState(); _loadChats(); } Future _loadChats() async { final authProvider = Provider.of(context, listen: false); final chatProvider = Provider.of(context, listen: false); final accessToken = await authProvider.getValidAccessToken(); if (accessToken == null) { await authProvider.logout(); return; } await chatProvider.fetchChats(accessToken: accessToken); } Future _handleRefresh() async { await _loadChats(); } Future _createNewChat() async { final authProvider = Provider.of(context, listen: false); final chatProvider = Provider.of(context, listen: false); final accessToken = await authProvider.getValidAccessToken(); if (accessToken == null) { await authProvider.logout(); return; } // Show loading dialog if (mounted) { showDialog( context: context, barrierDismissible: false, builder: (context) => const Center( child: CircularProgressIndicator(), ), ); } final chat = await chatProvider.createChat( accessToken: accessToken, title: 'New Chat', ); // Close loading dialog if (mounted) { Navigator.pop(context); } if (chat != null && mounted) { // Navigate to chat conversation await Navigator.push( context, MaterialPageRoute( builder: (context) => ChatConversationScreen(chatId: chat.id), ), ); // Refresh list after returning _loadChats(); } else if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(chatProvider.errorMessage ?? 'Failed to create chat'), backgroundColor: Colors.red, ), ); } } String _formatDateTime(DateTime dateTime) { final now = DateTime.now(); final difference = now.difference(dateTime); if (difference.inMinutes < 1) { return 'Just now'; } else if (difference.inHours < 1) { return '${difference.inMinutes}m ago'; } else if (difference.inDays < 1) { return '${difference.inHours}h ago'; } else if (difference.inDays < 7) { return '${difference.inDays}d ago'; } else { return '${dateTime.day}/${dateTime.month}/${dateTime.year}'; } } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Scaffold( appBar: AppBar( title: const Text('AI Assistant'), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: _handleRefresh, tooltip: 'Refresh', ), ], ), body: Consumer( builder: (context, chatProvider, _) { if (chatProvider.isLoading && chatProvider.chats.isEmpty) { return const Center( child: CircularProgressIndicator(), ); } if (chatProvider.errorMessage != null && chatProvider.chats.isEmpty) { return Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, size: 64, color: colorScheme.error, ), const SizedBox(height: 16), Text( 'Failed to load chats', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), Text( chatProvider.errorMessage!, style: TextStyle(color: colorScheme.onSurfaceVariant), textAlign: TextAlign.center, ), const SizedBox(height: 24), ElevatedButton.icon( onPressed: _handleRefresh, icon: const Icon(Icons.refresh), label: const Text('Try Again'), ), ], ), ), ); } if (chatProvider.chats.isEmpty) { return Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.chat_bubble_outline, size: 64, color: colorScheme.onSurfaceVariant, ), const SizedBox(height: 16), Text( 'No chats yet', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), Text( 'Start a new conversation with the AI assistant.', style: TextStyle(color: colorScheme.onSurfaceVariant), textAlign: TextAlign.center, ), ], ), ), ); } return RefreshIndicator( onRefresh: _handleRefresh, child: ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8), itemCount: chatProvider.chats.length, itemBuilder: (context, index) { final chat = chatProvider.chats[index]; return Dismissible( key: Key(chat.id), direction: DismissDirection.endToStart, background: Container( color: Colors.red, alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 16), child: const Icon( Icons.delete, color: Colors.white, ), ), confirmDismiss: (direction) async { return await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Delete Chat'), content: Text('Are you sure you want to delete "${chat.title}"?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('Delete', style: TextStyle(color: Colors.red)), ), ], ), ); }, onDismissed: (direction) async { final authProvider = Provider.of(context, listen: false); final accessToken = await authProvider.getValidAccessToken(); if (accessToken != null) { await chatProvider.deleteChat( accessToken: accessToken, chatId: chat.id, ); } }, child: ListTile( leading: CircleAvatar( backgroundColor: colorScheme.primaryContainer, child: Icon( Icons.chat, color: colorScheme.onPrimaryContainer, ), ), title: Text( chat.title, maxLines: 1, overflow: TextOverflow.ellipsis, ), subtitle: chat.lastMessageAt != null ? Text(_formatDateTime(chat.lastMessageAt!)) : null, trailing: chat.messageCount != null ? Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(12), ), child: Text( '${chat.messageCount}', style: TextStyle( color: colorScheme.onSecondaryContainer, fontSize: 12, fontWeight: FontWeight.bold, ), ), ) : null, onTap: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) => ChatConversationScreen(chatId: chat.id), ), ); _loadChats(); }, ), ); }, ), ); }, ), floatingActionButton: FloatingActionButton( onPressed: _createNewChat, tooltip: 'New Chat', child: const Icon(Icons.add), ), ); } }