fix: Pré-sélection des dates lors de la réouverture des modales de sélection + amélioration UI du bouton Appliquer
This commit is contained in:
parent
3435581761
commit
91adeb8fc8
3 changed files with 66 additions and 12 deletions
|
|
@ -41,16 +41,21 @@ export default function DatePickerCalendar({
|
|||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
const prevIsOpenRef = useRef(isOpen);
|
||||
|
||||
// Initialiser avec les dates initiales
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
// Vérifier si la modale vient de s'ouvrir (transition de false à true)
|
||||
const justOpened = isOpen && !prevIsOpenRef.current;
|
||||
prevIsOpenRef.current = isOpen;
|
||||
|
||||
if (justOpened) {
|
||||
if (initialDates.length > 0) {
|
||||
// Convertir format input "12/10" en ISO
|
||||
// On utilise le minDate ou maxDate comme contexte d'année
|
||||
const yearContext = minDate || maxDate || new Date().toISOString().slice(0, 10);
|
||||
const isos = initialDates
|
||||
.map(d => parseFrenchedDate(d, yearContext))
|
||||
.map(d => parseFrenchedDate(d.trim(), yearContext))
|
||||
.filter(iso => iso.length === 10);
|
||||
setSelectedIsos(isos);
|
||||
|
||||
|
|
@ -59,10 +64,14 @@ export default function DatePickerCalendar({
|
|||
const firstDate = new Date(isos[0] + "T00:00:00Z");
|
||||
setCurrentMonth(firstDate);
|
||||
}
|
||||
} else if (minDate) {
|
||||
// Si pas de dates initiales, utiliser la date de début du contrat
|
||||
const startDate = new Date(minDate + "T00:00:00Z");
|
||||
setCurrentMonth(startDate);
|
||||
} else {
|
||||
// Réinitialiser les sélections si pas de dates initiales
|
||||
setSelectedIsos([]);
|
||||
if (minDate) {
|
||||
// Si pas de dates initiales, utiliser la date de début du contrat
|
||||
const startDate = new Date(minDate + "T00:00:00Z");
|
||||
setCurrentMonth(startDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [isOpen, initialDates, minDate, maxDate]);
|
||||
|
|
|
|||
|
|
@ -432,13 +432,13 @@ export default function DatesQuantityModal({
|
|||
className="w-24"
|
||||
/>
|
||||
<span className="text-sm text-emerald-700">{getUnitLabel(dateType, false)}</span>
|
||||
<Button
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleApplyToAll}
|
||||
className="ml-auto bg-emerald-600 hover:bg-emerald-700 text-white text-sm px-3 py-1.5"
|
||||
className="ml-auto bg-emerald-600 hover:bg-emerald-700 text-white text-sm px-3 py-1.5 rounded-md font-medium transition-colors"
|
||||
>
|
||||
Appliquer
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -169,6 +169,51 @@ function parseFormattedDatesWithQuantities(
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrait uniquement les dates (format DD/MM) d'une chaîne formatée PDFMonkey
|
||||
* Utile pour initialDates des modales de calendrier
|
||||
*
|
||||
* @param dateStr - Chaîne formatée (ex: "1 représentation par jour du 24/11 au 26/11 ; 2 représentations le 28/11.")
|
||||
* @param yearContext - Contexte de l'année (ex: "2025-11-01")
|
||||
* @returns Array de dates au format "DD/MM"
|
||||
*/
|
||||
function extractDatesFromFormatted(dateStr: string, yearContext: string): string[] {
|
||||
if (!dateStr || !dateStr.trim()) return [];
|
||||
|
||||
const dates: string[] = [];
|
||||
const groups = dateStr.split(" ; ");
|
||||
|
||||
groups.forEach((group) => {
|
||||
// Vérifier si c'est une plage (contient "du ... au ...")
|
||||
const rangeMatch = group.match(/du\s+(\d{2}\/\d{2})\s+au\s+(\d{2}\/\d{2})/);
|
||||
if (rangeMatch) {
|
||||
// C'est une plage : générer toutes les dates intermédiaires
|
||||
const startFr = rangeMatch[1];
|
||||
const endFr = rangeMatch[2];
|
||||
|
||||
// Convertir en ISO
|
||||
const startIso = parseFrenchedDate(startFr, yearContext);
|
||||
const endIso = parseFrenchedDate(endFr, yearContext);
|
||||
|
||||
// Générer toutes les dates de la plage
|
||||
const allDatesIso = generateDateRange(startIso, endIso);
|
||||
|
||||
// Convertir en format DD/MM
|
||||
allDatesIso.forEach((iso) => {
|
||||
dates.push(formatDateFr(iso));
|
||||
});
|
||||
} else {
|
||||
// Date isolée (ex: "le 28/11")
|
||||
const dateMatch = group.match(/(\d{2}\/\d{2})/);
|
||||
if (dateMatch) {
|
||||
dates.push(dateMatch[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
// Petit hook local de debounce (réutilisable)
|
||||
function useDebouncedValue<T>(value: T, delay = 300) {
|
||||
const [debounced, setDebounced] = useState<T>(value);
|
||||
|
|
@ -2319,14 +2364,14 @@ useEffect(() => {
|
|||
isOpen={datesRepOpen}
|
||||
onClose={() => setDatesRepOpen(false)}
|
||||
onApply={handleDatesRepApply}
|
||||
initialDates={datesRep ? datesRep.split(", ") : []}
|
||||
initialDates={datesRep ? extractDatesFromFormatted(datesRep, dateDebut || new Date().toISOString().slice(0, 10)) : []}
|
||||
title="Sélectionner les dates de représentations"
|
||||
/>
|
||||
<DatePickerCalendar
|
||||
isOpen={datesServOpen}
|
||||
onClose={() => setDatesServOpen(false)}
|
||||
onApply={handleDatesServApply}
|
||||
initialDates={datesServ ? datesServ.split(", ") : []}
|
||||
initialDates={datesServ ? extractDatesFromFormatted(datesServ, dateDebut || new Date().toISOString().slice(0, 10)) : []}
|
||||
title="Sélectionner les dates de répétitions"
|
||||
/>
|
||||
</>
|
||||
|
|
@ -2404,7 +2449,7 @@ useEffect(() => {
|
|||
isOpen={joursTravailOpen}
|
||||
onClose={() => setJoursTravailOpen(false)}
|
||||
onApply={handleJoursTravailApply}
|
||||
initialDates={joursTravailRaw}
|
||||
initialDates={joursTravailRaw.length > 0 ? joursTravailRaw : (joursTravail ? extractDatesFromFormatted(joursTravail, dateDebut || new Date().toISOString().slice(0, 10)) : [])}
|
||||
title="Sélectionner les jours de travail"
|
||||
/>
|
||||
</>
|
||||
|
|
|
|||
Loading…
Reference in a new issue