Added few functions

This commit is contained in:
2026-02-16 14:43:02 +01:00
parent 0c908a21ac
commit 1ec4c935c9
31 changed files with 352 additions and 35 deletions

View File

@@ -4,6 +4,8 @@ import { useState, useEffect, useRef } from 'react';
import TrajetMap from './TrajetMap';
import AddressAutocomplete from './AddressAutocomplete';
import { useNotification } from './NotificationProvider';
import { calculerDureeTrajet } from '@/lib/trajet-duree';
import { useBodyScrollLock } from '@/lib/body-scroll-lock';
interface Adherent {
id: string;
@@ -27,6 +29,8 @@ interface Chauffeur {
prenom: string;
telephone: string;
email: string;
heuresRestantes?: number;
heuresContrat?: number;
}
interface TrajetFormProps {
@@ -47,6 +51,7 @@ interface TrajetFormProps {
export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetFormProps) {
const { showNotification } = useNotification();
useBodyScrollLock(true); // TrajetForm est toujours affiché en modal quand monté
const [loading, setLoading] = useState(false);
const [adherents, setAdherents] = useState<Adherent[]>([]);
const [chauffeurs, setChauffeurs] = useState<Chauffeur[]>([]);
@@ -56,6 +61,7 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
const [showChauffeurDropdown, setShowChauffeurDropdown] = useState(false);
const adherentDropdownRef = useRef<HTMLDivElement>(null);
const chauffeurDropdownRef = useRef<HTMLDivElement>(null);
const [dureeEstimee, setDureeEstimee] = useState<number | null>(null);
const [formData, setFormData] = useState({
adherentId: trajetToEdit?.adherentId || '',
@@ -83,6 +89,50 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
fetchChauffeurs();
}, []);
// Heures minimales requises pour ce trajet (arrondi au supérieur pour être conservateur)
const heuresRequerues = dureeEstimee != null ? Math.ceil(dureeEstimee) : 0;
// Calculer la durée du trajet quand les adresses sont remplies (pour filtrer les chauffeurs)
useEffect(() => {
if (!formData.adresseDepart?.trim() || !formData.adresseArrivee?.trim()) {
setDureeEstimee(null);
return;
}
let cancelled = false;
calculerDureeTrajet(formData.adresseDepart, formData.adresseArrivee).then((duree) => {
if (!cancelled && duree != null) {
setDureeEstimee(duree);
}
});
return () => {
cancelled = true;
};
}, [formData.adresseDepart, formData.adresseArrivee]);
// Si la durée estimée exclut le chauffeur sélectionné, le désélectionner
useEffect(() => {
if (heuresRequerues > 0 && formData.chauffeurId) {
const selectedChauffeur = chauffeurs.find((c) => c.id === formData.chauffeurId);
if (selectedChauffeur) {
const heuresDispo = selectedChauffeur.heuresRestantes ?? selectedChauffeur.heuresContrat ?? 35;
if (heuresDispo < heuresRequerues) {
setFormData((prev) => ({
...prev,
chauffeurId: '',
chauffeurNom: '',
chauffeurPrenom: '',
chauffeurTelephone: '',
}));
setSearchChauffeur('');
showNotification(
'warning',
`${selectedChauffeur.prenom} ${selectedChauffeur.nom} n'a que ${heuresDispo}h disponibles (trajet estimé ~${dureeEstimee}h)`
);
}
}
}
}, [heuresRequerues, dureeEstimee, formData.chauffeurId, chauffeurs]);
useEffect(() => {
// Si on modifie un trajet, charger les données de l'adhérent et du chauffeur
if (trajetToEdit) {
@@ -276,13 +326,20 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
a.telephone.includes(searchAdherent)
);
const filteredChauffeurs = chauffeurs.filter(
(c) =>
!searchChauffeur ||
`${c.prenom} ${c.nom}`.toLowerCase().includes(searchChauffeur.toLowerCase()) ||
c.email.toLowerCase().includes(searchChauffeur.toLowerCase()) ||
c.telephone.includes(searchChauffeur)
);
const filteredChauffeurs = chauffeurs
.filter((c) => {
// Exclure les chauffeurs qui n'ont pas assez d'heures restantes
if (heuresRequerues > 0) {
const heuresDispo = c.heuresRestantes ?? c.heuresContrat ?? 35;
if (heuresDispo < heuresRequerues) return false;
}
return (
!searchChauffeur ||
`${c.prenom} ${c.nom}`.toLowerCase().includes(searchChauffeur.toLowerCase()) ||
c.email.toLowerCase().includes(searchChauffeur.toLowerCase()) ||
c.telephone.includes(searchChauffeur)
);
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
@@ -460,6 +517,11 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
<div>
<label className="block text-sm font-semibold text-gray-900 mb-2">
Chauffeur
{dureeEstimee != null && (
<span className="ml-2 text-xs font-normal text-gray-500">
(trajet ~{dureeEstimee}h chauffeurs avec &lt;{heuresRequerues}h restantes masqués)
</span>
)}
</label>
<div className="relative" ref={chauffeurDropdownRef}>
<input