import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/todo_providers.dart'; class TodoScreen extends ConsumerStatefulWidget { const TodoScreen({super.key}); @override ConsumerState createState() => _TodoScreenState(); } class _TodoScreenState extends ConsumerState { String _searchQuery = ''; final TextEditingController _searchController = TextEditingController(); @override void dispose() { _searchController.dispose(); super.dispose(); } Future _refreshTodos() async { await ref.read(todosProvider.notifier).refresh(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; final todosAsync = ref.watch(todosProvider); final filteredTodos = ref.watch(filteredTodosProvider(_searchQuery)); return Scaffold( appBar: AppBar( title: const Text('My Todos'), elevation: 0, backgroundColor: colorScheme.surfaceVariant, foregroundColor: colorScheme.onSurfaceVariant, actions: [ IconButton( icon: const Icon(Icons.logout), onPressed: () { // Handle logout - will be connected to auth logic later ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Logout functionality will be implemented'), ), ); }, ), ], ), body: Column( children: [ // Search Bar Container( padding: const EdgeInsets.all(16.0), color: colorScheme.surfaceVariant, child: TextField( controller: _searchController, onChanged: (value) { setState(() { _searchQuery = value; }); }, decoration: InputDecoration( hintText: 'Search todos...', prefixIcon: const Icon(Icons.search), suffixIcon: _searchQuery.isNotEmpty ? IconButton( icon: const Icon(Icons.clear), onPressed: () { _searchController.clear(); setState(() { _searchQuery = ''; }); }, ) : null, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), filled: true, fillColor: colorScheme.surface, ), ), ), // Todos List Expanded( child: todosAsync.when( data: (todos) { if (todos.isEmpty) { return _buildEmptyState(); } if (filteredTodos.isEmpty) { return _buildNoResultsState(); } return RefreshIndicator( onRefresh: _refreshTodos, child: ListView.builder( padding: const EdgeInsets.all(16.0), itemCount: filteredTodos.length, itemBuilder: (context, index) { final todo = filteredTodos[index]; return _buildTodoCard(todo); }, ), ); }, loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, size: 64, color: colorScheme.error, ), const SizedBox(height: 16), Text( 'Error loading todos', style: theme.textTheme.headlineSmall?.copyWith( color: colorScheme.error, ), ), const SizedBox(height: 8), Text( error.toString(), style: theme.textTheme.bodyMedium?.copyWith( color: colorScheme.onSurfaceVariant, ), textAlign: TextAlign.center, ), const SizedBox(height: 16), ElevatedButton.icon( onPressed: _refreshTodos, icon: const Icon(Icons.refresh), label: const Text('Retry'), ), ], ), ), ), ), ], ), floatingActionButton: FloatingActionButton.extended( onPressed: () { // Handle add new todo ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Add todo functionality will be implemented'), ), ); }, icon: const Icon(Icons.add), label: const Text('Add Todo'), ), ); } Widget _buildTodoCard(todo) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; final isCompleted = todo.completed; return Card( margin: const EdgeInsets.only(bottom: 8.0), elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: ListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), leading: Checkbox( value: isCompleted, onChanged: (_) => ref.read(todosProvider.notifier).toggleTodo(todo.id), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4), ), ), title: Text( todo.title, style: theme.textTheme.bodyLarge?.copyWith( decoration: isCompleted ? TextDecoration.lineThrough : null, color: isCompleted ? colorScheme.onSurfaceVariant : colorScheme.onSurface, ), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (todo.description != null && todo.description!.isNotEmpty) Text( todo.description!, style: theme.textTheme.bodySmall?.copyWith( color: colorScheme.onSurfaceVariant, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 4), Text( 'ID: ${todo.id}', style: theme.textTheme.bodySmall?.copyWith( color: colorScheme.onSurfaceVariant.withOpacity(0.7), fontSize: 11, ), ), ], ), trailing: PopupMenuButton( onSelected: (value) { switch (value) { case 'edit': ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Edit functionality will be implemented'), ), ); break; case 'delete': ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Delete functionality will be implemented'), ), ); break; } }, itemBuilder: (context) => [ const PopupMenuItem( value: 'edit', child: Row( children: [ Icon(Icons.edit), SizedBox(width: 8), Text('Edit'), ], ), ), const PopupMenuItem( value: 'delete', child: Row( children: [ Icon(Icons.delete), SizedBox(width: 8), Text('Delete'), ], ), ), ], ), ), ); } Widget _buildEmptyState() { final theme = Theme.of(context); final colorScheme = theme.colorScheme; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.task_outlined, size: 64, color: colorScheme.onSurfaceVariant, ), const SizedBox(height: 16), Text( 'No todos yet', style: theme.textTheme.headlineSmall?.copyWith( color: colorScheme.onSurfaceVariant, ), ), const SizedBox(height: 8), Text( 'Add your first todo to get started!', style: theme.textTheme.bodyMedium?.copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), ); } Widget _buildNoResultsState() { final theme = Theme.of(context); final colorScheme = theme.colorScheme; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.search_off, size: 64, color: colorScheme.onSurfaceVariant, ), const SizedBox(height: 16), Text( 'No todos found', style: theme.textTheme.headlineSmall?.copyWith( color: colorScheme.onSurfaceVariant, ), ), const SizedBox(height: 8), Text( 'Try adjusting your search terms', style: theme.textTheme.bodyMedium?.copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), ); } }