feat: ajout de la gestion de la préparation d'un événement avec page permettant de le gérer
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:em2rp/providers/event_provider.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/event_details_components/event_details_navigation.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/event_details_components/event_details_header.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/event_details_components/event_status_button.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/event_details_components/event_preparation_buttons.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/event_details_components/event_details_info.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/event_details_components/event_details_description.dart';
|
||||
import 'package:em2rp/views/widgets/calendar_widgets/event_details_components/event_details_documents.dart';
|
||||
@@ -60,6 +61,8 @@ class EventDetails extends StatelessWidget {
|
||||
onSelectEvent: onSelectEvent,
|
||||
),
|
||||
),
|
||||
// Boutons de préparation et retour
|
||||
EventPreparationButtons(event: event),
|
||||
const SizedBox(height: 16),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
|
||||
@@ -98,8 +98,8 @@ class _EventDetailsHeaderState extends State<EventDetailsHeader> {
|
||||
_buildStatusIcon(widget.event.status),
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.calendar_today, color: AppColors.rouge),
|
||||
tooltip: 'Exporter vers Google Calendar',
|
||||
icon: const Icon(Icons.add_to_home_screen, color: AppColors.rouge),
|
||||
tooltip: 'Ajouter a mon application de calendrier',
|
||||
onPressed: _exportToCalendar,
|
||||
),
|
||||
if (Provider.of<LocalUserProvider>(context, listen: false)
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:em2rp/models/event_model.dart';
|
||||
import 'package:em2rp/views/event_preparation_page.dart';
|
||||
import 'package:em2rp/utils/colors.dart';
|
||||
|
||||
/// Boutons de préparation et retour d'événement
|
||||
class EventPreparationButtons extends StatefulWidget {
|
||||
final EventModel event;
|
||||
|
||||
const EventPreparationButtons({
|
||||
super.key,
|
||||
required this.event,
|
||||
});
|
||||
|
||||
@override
|
||||
State<EventPreparationButtons> createState() => _EventPreparationButtonsState();
|
||||
}
|
||||
|
||||
class _EventPreparationButtonsState extends State<EventPreparationButtons> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Écouter les changements de l'événement en temps réel
|
||||
return StreamBuilder<DocumentSnapshot>(
|
||||
stream: FirebaseFirestore.instance
|
||||
.collection('events')
|
||||
.doc(widget.event.id)
|
||||
.snapshots(),
|
||||
initialData: null,
|
||||
builder: (context, snapshot) {
|
||||
// Utiliser l'événement du stream si disponible, sinon l'événement initial
|
||||
final EventModel currentEvent;
|
||||
if (snapshot.hasData && snapshot.data != null && snapshot.data!.exists) {
|
||||
currentEvent = EventModel.fromMap(
|
||||
snapshot.data!.data() as Map<String, dynamic>,
|
||||
snapshot.data!.id,
|
||||
);
|
||||
} else {
|
||||
currentEvent = widget.event;
|
||||
}
|
||||
|
||||
return _buildButtons(context, currentEvent);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildButtons(BuildContext context, EventModel event) {
|
||||
// Vérifier s'il y a du matériel assigné
|
||||
final hasMaterial = event.assignedEquipment.isNotEmpty || event.assignedContainers.isNotEmpty;
|
||||
|
||||
if (!hasMaterial) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
// Déterminer l'étape actuelle
|
||||
final prep = event.preparationStatus ?? PreparationStatus.notStarted;
|
||||
final loading = event.loadingStatus ?? LoadingStatus.notStarted;
|
||||
final unloading = event.unloadingStatus ?? UnloadingStatus.notStarted;
|
||||
final returnStatus = event.returnStatus ?? ReturnStatus.notStarted;
|
||||
|
||||
String buttonText;
|
||||
IconData buttonIcon;
|
||||
bool isCompleted = false;
|
||||
|
||||
if (prep != PreparationStatus.completed) {
|
||||
buttonText = 'Préparation dépôt';
|
||||
buttonIcon = Icons.inventory_2;
|
||||
} else if (loading != LoadingStatus.completed) {
|
||||
buttonText = 'Chargement aller';
|
||||
buttonIcon = Icons.local_shipping;
|
||||
} else if (unloading != UnloadingStatus.completed) {
|
||||
buttonText = 'Chargement retour';
|
||||
buttonIcon = Icons.unarchive;
|
||||
} else if (returnStatus != ReturnStatus.completed) {
|
||||
buttonText = 'Retour dépôt';
|
||||
buttonIcon = Icons.assignment_return;
|
||||
} else {
|
||||
buttonText = 'Terminé';
|
||||
buttonIcon = Icons.check_circle;
|
||||
isCompleted = true;
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Bouton de l'étape actuelle
|
||||
if (!isCompleted)
|
||||
ElevatedButton.icon(
|
||||
onPressed: () async {
|
||||
final result = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => EventPreparationPage(
|
||||
initialEvent: event,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Si la validation a réussi, le StreamBuilder se rechargera automatiquement
|
||||
if (result == true && context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Étape validée avec succès'),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
icon: Icon(buttonIcon),
|
||||
label: Text(
|
||||
buttonText,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.bleuFonce,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Indicateur de completion
|
||||
if (isCompleted)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green.shade100,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: Colors.green, width: 1),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
Icon(Icons.check_circle, color: Colors.green, size: 20),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
'Toutes les étapes sont terminées',
|
||||
style: TextStyle(
|
||||
color: Colors.green,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user