193 lines
5.6 KiB
Dart
193 lines
5.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:p_tits_pas/models/absence_garde.dart';
|
|
import 'package:p_tits_pas/services/api/absences_garde_service.dart';
|
|
import 'package:p_tits_pas/widgets/quotidien/quotidien_theme.dart';
|
|
|
|
class AgendaAbsencesStub extends StatefulWidget {
|
|
final String? placementId;
|
|
|
|
const AgendaAbsencesStub({super.key, this.placementId});
|
|
|
|
@override
|
|
State<AgendaAbsencesStub> createState() => _AgendaAbsencesStubState();
|
|
}
|
|
|
|
class _AgendaAbsencesStubState extends State<AgendaAbsencesStub> {
|
|
List<AbsenceGarde> _absences = [];
|
|
bool _loading = true;
|
|
String? _error;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadAbsences();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(covariant AgendaAbsencesStub oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (oldWidget.placementId != widget.placementId) {
|
|
_loadAbsences();
|
|
}
|
|
}
|
|
|
|
Future<void> _loadAbsences() async {
|
|
setState(() {
|
|
_loading = true;
|
|
_error = null;
|
|
});
|
|
try {
|
|
final absences = await AbsencesGardeService.getAbsences(
|
|
placementId: widget.placementId,
|
|
);
|
|
if (!mounted) return;
|
|
setState(() {
|
|
_absences = absences;
|
|
_loading = false;
|
|
});
|
|
} catch (e) {
|
|
if (!mounted) return;
|
|
setState(() {
|
|
_error = e.toString();
|
|
_loading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
color: QuotidienTheme.ivory,
|
|
child: Center(
|
|
child: ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 600),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
const Icon(
|
|
Icons.calendar_month_outlined,
|
|
size: 64,
|
|
color: QuotidienTheme.peach,
|
|
),
|
|
const SizedBox(height: 24),
|
|
Text(
|
|
"Agenda (Stub) - Lignes d'absence",
|
|
textAlign: TextAlign.center,
|
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
|
color: QuotidienTheme.ink,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Text(
|
|
'ID Placement courant: ${widget.placementId ?? 'Tous'}',
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(color: QuotidienTheme.muted),
|
|
),
|
|
const SizedBox(height: 24),
|
|
Expanded(
|
|
child: _buildList(),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildList() {
|
|
if (_loading) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
if (_error != null) {
|
|
return Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Icon(Icons.error_outline, color: Colors.red, size: 48),
|
|
const SizedBox(height: 16),
|
|
Text(_error!, style: const TextStyle(color: Colors.red)),
|
|
const SizedBox(height: 16),
|
|
ElevatedButton(
|
|
onPressed: _loadAbsences,
|
|
child: const Text('Réessayer'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
if (_absences.isEmpty) {
|
|
return const Center(
|
|
child: Text('Aucune absence ou congé trouvé.',
|
|
style: TextStyle(color: QuotidienTheme.muted)),
|
|
);
|
|
}
|
|
return ListView.separated(
|
|
itemCount: _absences.length,
|
|
separatorBuilder: (_, __) => const Divider(),
|
|
itemBuilder: (context, index) {
|
|
final abs = _absences[index];
|
|
return ListTile(
|
|
leading: _getIcon(abs.type),
|
|
title: Text('${abs.type} (${abs.statut})'),
|
|
subtitle: Text(
|
|
'Du ${abs.dateDebut} au ${abs.dateFin}\n'
|
|
'Enfant: ${abs.prenomEnfant ?? 'N/A'}, AM: ${abs.prenomAm ?? 'N/A'}',
|
|
),
|
|
trailing: IconButton(
|
|
icon: const Icon(Icons.delete_outline, color: Colors.red),
|
|
onPressed: () => _confirmDelete(abs),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Icon _getIcon(String type) {
|
|
switch (type) {
|
|
case 'absence_enfant':
|
|
return const Icon(Icons.child_care, color: QuotidienTheme.coral);
|
|
case 'conge_am':
|
|
return const Icon(Icons.beach_access, color: QuotidienTheme.turquoise);
|
|
case 'arret_maladie_am':
|
|
return const Icon(Icons.medical_services, color: QuotidienTheme.coral);
|
|
default:
|
|
return const Icon(Icons.event);
|
|
}
|
|
}
|
|
|
|
Future<void> _confirmDelete(AbsenceGarde abs) async {
|
|
final confirm = await showDialog<bool>(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text('Supprimer ?'),
|
|
content: Text("Supprimer l'absence ${abs.type} du ${abs.dateDebut} ?"),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context, false),
|
|
child: const Text('Annuler'),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context, true),
|
|
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
|
child: const Text('Supprimer'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (confirm == true) {
|
|
try {
|
|
await AbsencesGardeService.supprimerAbsence(abs.id);
|
|
_loadAbsences();
|
|
} catch (e) {
|
|
if (!mounted) return;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Erreur: $e')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|