This commit is contained in:
Louis Mazin 2026-09-25 16:42:59 +02:00
parent e2800c3d57
commit 30eab16473

View File

@ -195,6 +195,9 @@ const TimeClockPage = () => {
.slice(0, 5),
);
const [conflictDate, setConflictDate] = useState(getTodayValue());
const [resolvingConflict, setResolvingConflict] = useState(false);
const [
error,
setError,
@ -1212,6 +1215,10 @@ const TimeClockPage = () => {
nowTime,
);
setConflictDate(
scanError.scanDate || getTodayValue(),
);
setScanConflict({
code,
type:
@ -1254,7 +1261,7 @@ const TimeClockPage = () => {
'Une entrée est déjà ouverte',
confirmationMessage:
'Vous avez déjà pointer une entrée, voulez vous saisir son heure de sortie ?',
'Une entrée est déjà ouverte. Voulez-vous indiquer sa date et son heure de sortie, puis enregistrer la nouvelle entrée ?',
timeLabel:
'Heure de sortie',
@ -1273,7 +1280,7 @@ const TimeClockPage = () => {
'Aucune entrée ouverte',
confirmationMessage:
'Vous n\avez pas pointer d\'entrée, voulez vous poursuivre et indiquer l\'heure d\'entrée ?',
'Aucune entrée ouverte. Voulez-vous indiquer la date et l’heure de l’entrée manquante, puis enregistrer cette sortie ?',
timeLabel:
"Heure d'entrée",
@ -1292,7 +1299,7 @@ const TimeClockPage = () => {
'Une sortie sans entrée existe',
confirmationMessage:
"Voulez-vous renseigner l’heure d’entrée ?",
"Voulez-vous indiquer la date et l’heure de l’entrée manquante, puis enregistrer le nouveau pointage ?",
timeLabel:
"Heure d'entrée",
@ -1328,7 +1335,7 @@ const TimeClockPage = () => {
const resolveScanConflict =
async () => {
if (!scanConflict) {
if (!scanConflict || resolvingConflict) {
return;
}
@ -1339,14 +1346,28 @@ const TimeClockPage = () => {
return;
}
if (!conflictDate || !conflictTime) {
setError('Indiquez la date et l’heure du pointage manquant.');
return;
}
if (scanConflict.scanDate && conflictDate > scanConflict.scanDate) {
setError('Le pointage manquant ne peut pas être postérieur au scan.');
return;
}
setError('');
setResolvingConflict(true);
let resolved = false;
try {
const options = {
resolution:
config.resolution,
time: conflictTime,
scan_date: scanConflict.scanDate,
scan_date: conflictDate,
entry_id: scanConflict.entryId,
};
@ -1357,25 +1378,39 @@ const TimeClockPage = () => {
scanConflict.scanTime;
}
const response =
await timeApi.scanTimeEntry(
await timeApi.scanTimeEntry(scanConflict.code, options);
resolved = true;
// La résolution ne rejoue pas le scan qui a déclenché le conflit.
const scanOptions = {};
if (scanConflict.scanDate) {
scanOptions.scan_date = scanConflict.scanDate;
}
if (scanConflict.scanTime) {
scanOptions.scan_time = scanConflict.scanTime;
}
const response = await timeApi.scanTimeEntry(
scanConflict.code,
options,
);
setScanMessage(
response.message,
scanOptions,
);
setScanMessage(response.message || 'Pointage enregistré.');
setScanConflict(null);
await loadTimeEntries();
} catch (
resolutionError
) {
if (resolved) {
setScanConflict(null);
await loadTimeEntries();
}
setError(
resolutionError.message,
resolved
? `Le conflit a été résolu, mais le nouveau pointage n’a pas été enregistré : ${resolutionError.message}`
: resolutionError.message,
);
} finally {
setResolvingConflict(false);
}
};
@ -1950,6 +1985,17 @@ const TimeClockPage = () => {
</p>
<div className="grid grid-cols-[140px_minmax(0,1fr)] items-center gap-3">
<Label>
{scanConflictConfig.timeLabel === 'Heure de sortie'
? 'Date de sortie'
: "Date d'entrée"}
</Label>
<DatePicker
value={conflictDate}
onChange={setConflictDate}
/>
<Label>
{
scanConflictConfig.timeLabel
@ -1973,6 +2019,7 @@ const TimeClockPage = () => {
onClick={
cancelScanConflict
}
disabled={resolvingConflict}
>
Annuler
</Button>
@ -1982,8 +2029,9 @@ const TimeClockPage = () => {
onClick={
resolveScanConflict
}
disabled={resolvingConflict}
>
Enregistrer
{resolvingConflict ? 'Enregistrement…' : 'Résoudre et pointer'}
</Button>
</div>
</>