import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import '../../core/constants/app_constants.dart'; import '../../core/theme/app_theme.dart'; import '../../data/models/session.dart'; import '../../data/models/target_type.dart'; import '../../data/repositories/session_repository.dart'; import 'session_detail_screen.dart'; import 'widgets/session_list_item.dart'; import 'widgets/history_chart.dart'; class HistoryScreen extends StatefulWidget { const HistoryScreen({super.key}); @override State createState() => _HistoryScreenState(); } class _HistoryScreenState extends State { List _sessions = []; bool _isLoading = true; TargetType? _filterType; // --- MODIFICATION : Remplacement de DateTime par DateTimeRange --- DateTimeRange? _selectedDateRange; @override void initState() { super.initState(); _loadSessions(); } Future _loadSessions() async { if (!mounted) return; setState(() => _isLoading = true); try { final repository = context.read(); final sessions = await repository.getAllSessions(); if (mounted) { setState(() { _sessions = sessions; // --- LOGIQUE DE FILTRAGE PAR PÉRIODE --- if (_selectedDateRange != null) { _sessions = _sessions.where((s) { // On compare uniquement les dates (sans les heures) pour éviter les bugs final sessionDate = DateTime( s.createdAt.year, s.createdAt.month, s.createdAt.day, ); final startDate = DateTime( _selectedDateRange!.start.year, _selectedDateRange!.start.month, _selectedDateRange!.start.day, ); final endDate = DateTime( _selectedDateRange!.end.year, _selectedDateRange!.end.month, _selectedDateRange!.end.day, ); return sessionDate.isAtSameMomentAs(startDate) || sessionDate.isAtSameMomentAs(endDate) || (sessionDate.isAfter(startDate) && sessionDate.isBefore(endDate)); }).toList(); } _isLoading = false; }); } } catch (e) { if (mounted) { setState(() => _isLoading = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur: $e'), backgroundColor: AppTheme.errorColor, ), ); } } } // --- MODIFICATION : Fonction DateRangePicker --- Future _pickDateRange() async { final DateTimeRange? picked = await showDateRangePicker( context: context, initialDateRange: _selectedDateRange, firstDate: DateTime(2020), lastDate: DateTime.now().add(const Duration(days: 1)), locale: const Locale('fr', 'FR'), builder: (context, child) { return Theme( data: ThemeData.light().copyWith( colorScheme: ColorScheme.light( primary: AppTheme.primaryColor, // En-tête et sélection onPrimary: Colors.white, // Texte sur en-tête/sélection surface: Colors.white, // Fond du calendrier onSurface: Colors.black87, // Texte des dates (Noir sur Blanc) secondary: AppTheme.primaryColor, ), dialogBackgroundColor: Colors.white, textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom(foregroundColor: AppTheme.primaryColor), ), ), child: child!, ); }, ); if (picked != null) { setState(() => _selectedDateRange = picked); _loadSessions(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Historique'), actions: [ PopupMenuButton( icon: const Icon(Icons.filter_list), onSelected: (type) { setState(() => _filterType = type); _loadSessions(); }, itemBuilder: (context) => [ const PopupMenuItem(value: null, child: Text('Tous')), ...TargetType.values.map( (type) => PopupMenuItem(value: type, child: Text(type.displayName)), ), ], ), ], ), body: Column( children: [ Expanded( child: _isLoading ? const Center(child: CircularProgressIndicator()) : _sessions.isEmpty ? _buildEmptyState() : _buildContent(), ), _buildBottomFilterBar(), ], ), ); } Widget _buildBottomFilterBar() { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Theme.of(context).cardColor, boxShadow: const [ BoxShadow( color: Colors.black26, blurRadius: 4, offset: Offset(0, -2), ), ], ), child: SafeArea( top: false, child: Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: _pickDateRange, icon: const Icon(Icons.date_range, size: 18), label: Text( _selectedDateRange == null ? 'Choisir une période' : '${DateFormat('dd/MM/yy').format(_selectedDateRange!.start)} - ${DateFormat('dd/MM/yy').format(_selectedDateRange!.end)}', ), ), ), if (_selectedDateRange != null) IconButton( icon: const Icon(Icons.close, color: AppTheme.errorColor), onPressed: () { setState(() => _selectedDateRange = null); _loadSessions(); }, ), ], ), ), ); } Widget _buildEmptyState() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.history, size: 64, color: Colors.grey[400]), const SizedBox(height: 16), const Text('Aucune session sur cette période'), ], ), ); } Widget _buildContent() { return RefreshIndicator( onRefresh: _loadSessions, child: CustomScrollView( slivers: [ if (_sessions.length >= 2 && _selectedDateRange == null) SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(AppConstants.defaultPadding), child: HistoryChart(sessions: _sessions), ), ), SliverPadding( padding: const EdgeInsets.all(AppConstants.defaultPadding), sliver: SliverList( delegate: SliverChildBuilderDelegate((context, index) { final session = _sessions[index]; return Padding( padding: const EdgeInsets.only(bottom: 12), child: SessionListItem( session: session, onTap: () => _openSessionDetail(session), onDelete: () => _deleteSession(session), ), ); }, childCount: _sessions.length), ), ), ], ), ); } void _openSessionDetail(Session session) async { await Navigator.push( context, MaterialPageRoute(builder: (_) => SessionDetailScreen(session: session)), ); _loadSessions(); } Future _deleteSession(Session session) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Supprimer'), content: Text( 'Supprimer la session du ${DateFormat('dd/MM/yyyy').format(session.createdAt)}?', ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Annuler'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text( 'Supprimer', style: TextStyle(color: AppTheme.errorColor), ), ), ], ), ); if (confirmed == true && mounted) { try { final repository = context.read(); await repository.deleteSession(session.id); _loadSessions(); } catch (e) { debugPrint('Erreur suppression: $e'); } } } }