Files
impact/lib/features/history/history_screen.dart
2026-05-03 16:46:05 +02:00

258 lines
7.6 KiB
Dart

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<HistoryScreen> createState() => _HistoryScreenState();
}
class _HistoryScreenState extends State<HistoryScreen> {
List<Session> _sessions = [];
bool _isLoading = true;
TargetType? _filterType;
DateTime? _selectedDate; // --- AJOUT : Variable pour le filtre date ---
@override
void initState() {
super.initState();
_loadSessions();
}
Future<void> _loadSessions() async {
setState(() => _isLoading = true);
try {
final repository = context.read<SessionRepository>();
// On récupère toutes les sessions. Le filtrage visuel se fera dans la liste
// ou tu peux adapter ton repository pour accepter un DateTime.
final sessions = await repository.getAllSessions(targetType: _filterType);
if (mounted) {
setState(() {
_sessions = sessions;
if (_selectedDate != null) {
_sessions = _sessions
.where(
(s) =>
s.createdAt.year == _selectedDate!.year &&
s.createdAt.month == _selectedDate!.month &&
s.createdAt.day == _selectedDate!.day,
)
.toList();
}
_isLoading = false;
});
}
} catch (e) {
if (mounted) {
setState(() => _isLoading = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Erreur: $e'),
backgroundColor: AppTheme.errorColor,
),
);
}
}
}
// --- AJOUT : Fonction DatePicker ---
Future<void> _pickDate() async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: _selectedDate ?? DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime.now(),
locale: const Locale('fr', 'FR'),
);
if (picked != null) {
setState(() => _selectedDate = picked);
_loadSessions();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Historique'),
actions: [
PopupMenuButton<TargetType?>(
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)),
),
],
),
],
),
// --- MODIFICATION : Utilisation d'une Column pour fixer le bas ---
body: Column(
children: [
Expanded(
child: _isLoading
? const Center(child: CircularProgressIndicator())
: _sessions.isEmpty
? _buildEmptyState()
: _buildContent(),
),
_buildBottomFilterBar(), // --- AJOUT : La barre de filtre en bas ---
],
),
);
}
// --- AJOUT : Widget de la barre du bas ---
Widget _buildBottomFilterBar() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 4,
offset: const Offset(0, -2),
),
],
),
child: SafeArea(
top: false,
child: Row(
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: _pickDate,
icon: const Icon(Icons.calendar_today, size: 18),
label: Text(
_selectedDate == null
? 'Choisir une date'
: DateFormat(
'dd MMMM yyyy',
'fr_FR',
).format(_selectedDate!),
),
),
),
if (_selectedDate != null)
IconButton(
icon: const Icon(Icons.close, color: AppTheme.errorColor),
onPressed: () {
setState(() => _selectedDate = 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 trouvée'),
],
),
);
}
Widget _buildContent() {
return RefreshIndicator(
onRefresh: _loadSessions,
child: CustomScrollView(
slivers: [
if (_sessions.length >= 2 && _selectedDate == 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),
),
),
],
),
);
}
// Les fonctions _openSessionDetail et _deleteSession restent identiques à ton code original
void _openSessionDetail(Session session) async {
await Navigator.push(
context,
MaterialPageRoute(builder: (_) => SessionDetailScreen(session: session)),
);
_loadSessions();
}
Future<void> _deleteSession(Session session) async {
final confirmed = await showDialog<bool>(
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<SessionRepository>();
await repository.deleteSession(session.id);
_loadSessions();
} catch (e) {
// ... snackbar d'erreur
}
}
}
}