feat: implement equipment and container loading rollback functionality with corresponding backend cloud functions
This commit is contained in:
@@ -12,7 +12,7 @@ enum ChecklistStep {
|
||||
}
|
||||
|
||||
/// Widget pour afficher un équipement dans une checklist de préparation/retour
|
||||
class EquipmentChecklistItem extends StatelessWidget {
|
||||
class EquipmentChecklistItem extends StatefulWidget {
|
||||
final EquipmentModel equipment;
|
||||
final EventEquipment eventEquipment;
|
||||
final ChecklistStep step;
|
||||
@@ -34,92 +34,120 @@ class EquipmentChecklistItem extends StatelessWidget {
|
||||
this.wasMissingBefore = false,
|
||||
});
|
||||
|
||||
/// Retourne la quantité actuelle selon l'étape
|
||||
@override
|
||||
State<EquipmentChecklistItem> createState() => _EquipmentChecklistItemState();
|
||||
}
|
||||
|
||||
class _EquipmentChecklistItemState extends State<EquipmentChecklistItem> {
|
||||
late TextEditingController _quantityController;
|
||||
|
||||
int _getCurrentQuantity() {
|
||||
switch (step) {
|
||||
switch (widget.step) {
|
||||
case ChecklistStep.preparation:
|
||||
return eventEquipment.quantityAtPreparation ?? eventEquipment.quantity;
|
||||
return widget.eventEquipment.quantityAtPreparation ?? widget.eventEquipment.quantity;
|
||||
case ChecklistStep.loading:
|
||||
return eventEquipment.quantityAtLoading ?? eventEquipment.quantityAtPreparation ?? eventEquipment.quantity;
|
||||
return widget.eventEquipment.quantityAtLoading ?? widget.eventEquipment.quantityAtPreparation ?? widget.eventEquipment.quantity;
|
||||
case ChecklistStep.unloading:
|
||||
return eventEquipment.quantityAtUnloading ?? eventEquipment.quantityAtLoading ?? eventEquipment.quantity;
|
||||
return widget.eventEquipment.quantityAtUnloading ?? widget.eventEquipment.quantityAtLoading ?? widget.eventEquipment.quantityAtPreparation ?? widget.eventEquipment.quantity;
|
||||
case ChecklistStep.return_:
|
||||
return eventEquipment.quantityAtReturn ?? eventEquipment.quantityAtUnloading ?? eventEquipment.quantity;
|
||||
return widget.eventEquipment.quantityAtReturn ?? widget.eventEquipment.quantityAtUnloading ?? widget.eventEquipment.quantityAtLoading ?? widget.eventEquipment.quantityAtPreparation ?? widget.eventEquipment.quantity;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_quantityController = TextEditingController(text: _getCurrentQuantity().toString());
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant EquipmentChecklistItem oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
final currentQty = _getCurrentQuantity();
|
||||
final controllerQty = int.tryParse(_quantityController.text);
|
||||
if (controllerQty != currentQty) {
|
||||
_quantityController.text = currentQty.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_quantityController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasQuantity = equipment.hasQuantity;
|
||||
final hasQuantity = widget.equipment.hasQuantity;
|
||||
|
||||
// Déterminer la quantité actuelle selon l'étape
|
||||
final int currentQuantity = _getCurrentQuantity();
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: isChild ? 32.0 : 0.0, // Indentation pour les enfants
|
||||
left: widget.isChild ? 32.0 : 0.0, // Indentation pour les enfants
|
||||
top: 4.0,
|
||||
bottom: 4.0,
|
||||
),
|
||||
child: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
elevation: isChild ? 0 : 1, // Pas d'élévation pour les enfants
|
||||
color: wasMissingBefore
|
||||
elevation: widget.isChild ? 0 : 1, // Pas d'élévation pour les enfants
|
||||
color: widget.wasMissingBefore
|
||||
? Colors.orange.shade50
|
||||
: (isChild ? Colors.grey.shade50 : Colors.white),
|
||||
: (widget.isChild ? Colors.grey.shade50 : Colors.white),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(
|
||||
color: wasMissingBefore
|
||||
color: widget.wasMissingBefore
|
||||
? Colors.orange
|
||||
: (isValidated ? Colors.green : Colors.grey.shade300),
|
||||
width: (isValidated || wasMissingBefore) ? 2 : 1,
|
||||
: (widget.isValidated ? Colors.green : Colors.grey.shade300),
|
||||
width: (widget.isValidated || widget.wasMissingBefore) ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: ListTile(
|
||||
dense: isChild, // Plus compact pour les enfants
|
||||
dense: widget.isChild, // Plus compact pour les enfants
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: isChild ? 8.0 : 16.0,
|
||||
vertical: isChild ? 4.0 : 8.0,
|
||||
horizontal: widget.isChild ? 8.0 : 16.0,
|
||||
vertical: widget.isChild ? 4.0 : 8.0,
|
||||
),
|
||||
leading: Container(
|
||||
width: isChild ? 32 : 40,
|
||||
height: isChild ? 32 : 40,
|
||||
width: widget.isChild ? 32 : 40,
|
||||
height: widget.isChild ? 32 : 40,
|
||||
decoration: BoxDecoration(
|
||||
color: wasMissingBefore
|
||||
color: widget.wasMissingBefore
|
||||
? Colors.orange.shade100
|
||||
: (isValidated ? Colors.green.shade100 : Colors.grey.shade100),
|
||||
: (widget.isValidated ? Colors.green.shade100 : Colors.grey.shade100),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
wasMissingBefore
|
||||
widget.wasMissingBefore
|
||||
? Icons.warning
|
||||
: (isValidated ? Icons.check_circle : Icons.radio_button_unchecked),
|
||||
color: wasMissingBefore
|
||||
: (widget.isValidated ? Icons.check_circle : Icons.radio_button_unchecked),
|
||||
color: widget.wasMissingBefore
|
||||
? Colors.orange
|
||||
: (isValidated ? Colors.green : Colors.grey),
|
||||
size: isChild ? 18 : 24,
|
||||
: (widget.isValidated ? Colors.green : Colors.grey),
|
||||
size: widget.isChild ? 18 : 24,
|
||||
),
|
||||
onPressed: onToggle,
|
||||
onPressed: widget.onToggle,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
equipment.name,
|
||||
widget.equipment.name,
|
||||
style: TextStyle(
|
||||
fontWeight: isChild ? FontWeight.w500 : FontWeight.w600,
|
||||
fontSize: isChild ? 13 : 15,
|
||||
decoration: isValidated ? TextDecoration.lineThrough : null,
|
||||
color: isValidated ? Colors.grey : null,
|
||||
fontWeight: widget.isChild ? FontWeight.w500 : FontWeight.w600,
|
||||
fontSize: widget.isChild ? 13 : 15,
|
||||
decoration: widget.isValidated ? TextDecoration.lineThrough : null,
|
||||
color: widget.isValidated ? Colors.grey : null,
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (equipment.model != null)
|
||||
if (widget.equipment.model != null)
|
||||
Text(
|
||||
equipment.model!,
|
||||
widget.equipment.model!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey.shade600,
|
||||
@@ -127,12 +155,12 @@ class EquipmentChecklistItem extends StatelessWidget {
|
||||
),
|
||||
|
||||
// Indicateur si manquant à l'étape précédente
|
||||
if (wasMissingBefore)
|
||||
if (widget.wasMissingBefore)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.warning_amber, size: 14, color: Colors.orange),
|
||||
const Icon(Icons.warning_amber, size: 14, color: Colors.orange),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'Était manquant à l\'étape précédente',
|
||||
@@ -151,7 +179,7 @@ class EquipmentChecklistItem extends StatelessWidget {
|
||||
const SizedBox(height: 6),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'Quantité : ',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
@@ -159,11 +187,11 @@ class EquipmentChecklistItem extends StatelessWidget {
|
||||
color: AppColors.bleuFonce,
|
||||
),
|
||||
),
|
||||
if (onQuantityChanged != null)
|
||||
if (widget.onQuantityChanged != null)
|
||||
SizedBox(
|
||||
width: 60,
|
||||
child: TextFormField(
|
||||
initialValue: currentQuantity.toString(),
|
||||
controller: _quantityController,
|
||||
keyboardType: TextInputType.number,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: InputDecoration(
|
||||
@@ -175,14 +203,14 @@ class EquipmentChecklistItem extends StatelessWidget {
|
||||
),
|
||||
onChanged: (value) {
|
||||
final qty = int.tryParse(value) ?? currentQuantity;
|
||||
onQuantityChanged!(qty);
|
||||
widget.onQuantityChanged!(qty);
|
||||
},
|
||||
),
|
||||
)
|
||||
else
|
||||
Text(
|
||||
currentQuantity.toString(),
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.bleuFonce,
|
||||
@@ -193,16 +221,16 @@ class EquipmentChecklistItem extends StatelessWidget {
|
||||
],
|
||||
],
|
||||
),
|
||||
trailing: isValidated
|
||||
trailing: widget.isValidated
|
||||
? Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green.shade100,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
child: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: const [
|
||||
children: [
|
||||
Icon(Icons.check, size: 16, color: Colors.green),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
|
||||
Reference in New Issue
Block a user