This commit is contained in:
Louis Mazin 2026-09-25 17:17:08 +02:00
parent 0fd446fc24
commit 030893089d
2 changed files with 28 additions and 31 deletions

View File

@ -1299,7 +1299,7 @@ const TimeClockPage = () => {
'Une sortie sans entrée existe', 'Une sortie sans entrée existe',
confirmationMessage: confirmationMessage:
"Voulez-vous indiquer la date et l’heure de l’entrée manquante, puis enregistrer le nouveau pointage ?", "Voulez-vous indiquer la date et l’heure de l’entrée manquante, puis enregistrer la sortie scannée ?",
timeLabel: timeLabel:
"Heure d'entrée", "Heure d'entrée",
@ -1347,12 +1347,16 @@ const TimeClockPage = () => {
} }
if (!conflictDate || !conflictTime) { if (!conflictDate || !conflictTime) {
setError('Indiquez la date et l’heure du pointage manquant.'); setError(config.timeLabel === 'Heure de sortie'
? 'Indiquez la date et l’heure de la sortie manquante.'
: 'Indiquez la date et l’heure de l’entrée manquante.');
return; return;
} }
if (scanConflict.scanDate && conflictDate > scanConflict.scanDate) { if (scanConflict.scanDate && conflictDate > scanConflict.scanDate) {
setError('Le pointage manquant ne peut pas être postérieur au scan.'); setError(config.timeLabel === 'Heure de sortie'
? 'La sortie renseignée ne peut pas être postérieure à l’entrée scannée.'
: 'L’entrée renseignée ne peut pas être postérieure à la sortie scannée.');
return; return;
} }
@ -1378,12 +1382,12 @@ const TimeClockPage = () => {
scanConflict.scanTime; scanConflict.scanTime;
} }
const resolutionResponse = await timeApi.scanTimeEntry(scanConflict.code, options); await timeApi.scanTimeEntry(scanConflict.code, options);
resolved = true; resolved = true;
// complete_missing_entry renseigne l'entrée et applique déjà la sortie scannée. // complete_missing_entry renseigne l'entrée et applique déjà la sortie scannée.
if (scanConflict.type === 'missing_entry') { if (scanConflict.type === 'missing_entry') {
setScanMessage(resolutionResponse.message || 'Sortie enregistrée.'); setScanMessage('Entrée renseignée et sortie enregistrée.');
setScanConflict(null); setScanConflict(null);
await loadTimeEntries(); await loadTimeEntries();
return; return;
@ -1397,12 +1401,14 @@ const TimeClockPage = () => {
if (scanConflict.scanTime) { if (scanConflict.scanTime) {
scanOptions.scan_time = scanConflict.scanTime; scanOptions.scan_time = scanConflict.scanTime;
} }
const response = await timeApi.scanTimeEntry( await timeApi.scanTimeEntry(
scanConflict.code, scanConflict.code,
scanOptions, scanOptions,
); );
setScanMessage(response.message || 'Pointage enregistré.'); setScanMessage(scanConflict.type === 'open_entry'
? 'Sortie renseignée et entrée enregistrée.'
: 'Entrée renseignée et sortie enregistrée.');
setScanConflict(null); setScanConflict(null);
await loadTimeEntries(); await loadTimeEntries();
} catch ( } catch (
@ -1414,8 +1420,8 @@ const TimeClockPage = () => {
} }
setError( setError(
resolved resolved
? `Le conflit a été résolu, mais le nouveau pointage n’a pas été enregistré : ${resolutionError.message}` ? `${scanConflict.type === 'open_entry' ? 'La sortie a été renseignée, mais la nouvelle entrée n’a pas été enregistrée' : 'L’entrée manquante a été renseignée, mais la sortie scannée n’a pas été enregistrée'} : ${resolutionError.message || 'erreur inconnue'}`
: resolutionError.message, : `Impossible de ${scanConflict.type === 'open_entry' ? 'renseigner la sortie manquante' : 'renseigner l’entrée manquante et enregistrer la sortie'} : ${resolutionError.message || 'erreur inconnue'}`,
); );
} finally { } finally {
setResolvingConflict(false); setResolvingConflict(false);
@ -2415,17 +2421,6 @@ const TimeClockPage = () => {
</div> </div>
{editingEntry.isGrouped && (
<p className="mb-4 text-xs text-muted-foreground">
Les dates d’un pointage
multi-jours sont liées au
groupe. Seules les heures
peuvent être modifiées ici.
</p>
)}
<div className="flex flex-col gap-2 sm:flex-row"> <div className="flex flex-col gap-2 sm:flex-row">
<Button type="submit"> <Button type="submit">

View File

@ -744,23 +744,23 @@ const WeeklySummaryPage = ({ userId }) => {
*/ */
const getScheduleBounds = ( const getScheduleBounds = (
weekDays, visibleDays,
) => { ) => {
const weekDateKeys = const visibleDateKeys =
new Set( new Set(
weekDays.map( visibleDays.map(
formatDateKey, formatDateKey,
), ),
); );
const weekAttendances = const visibleAttendances =
getFilteredAttendances( getFilteredAttendances(
expandOvernightAttendances( expandOvernightAttendances(
attendances, attendances,
), ),
).filter( ).filter(
(attendance) => (attendance) =>
weekDateKeys.has( visibleDateKeys.has(
String( String(
attendance.start_date, attendance.start_date,
).slice(0, 10), ).slice(0, 10),
@ -768,7 +768,7 @@ const WeeklySummaryPage = ({ userId }) => {
); );
const times = const times =
weekAttendances visibleAttendances
.flatMap( .flatMap(
(attendance) => [ (attendance) => [
getMinutes( getMinutes(
@ -1027,7 +1027,7 @@ const WeeklySummaryPage = ({ userId }) => {
endHour, endHour,
} = } =
getScheduleBounds( getScheduleBounds(
weekDays, isMobile ? [weekDays[selectedDayIndex]] : weekDays,
); );
const hourCount = const hourCount =
@ -1179,7 +1179,7 @@ const WeeklySummaryPage = ({ userId }) => {
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => navigateWeek(-1)} onClick={() => navigateWeek(-1)}
className="flex items-center gap-1" className="flex shrink-0 items-center gap-1"
> >
<ChevronLeft className="h-4 w-4" /> <ChevronLeft className="h-4 w-4" />
Précédente Précédente
@ -1187,7 +1187,7 @@ const WeeklySummaryPage = ({ userId }) => {
<Badge <Badge
variant="secondary" variant="secondary"
className="text-sm" className="h-7 w-56 shrink-0 justify-center whitespace-nowrap text-sm tabular-nums"
> >
Du{' '} Du{' '}
{weekDays[0].toLocaleDateString('fr-FR', { {weekDays[0].toLocaleDateString('fr-FR', {
@ -1205,7 +1205,7 @@ const WeeklySummaryPage = ({ userId }) => {
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => navigateWeek(1)} onClick={() => navigateWeek(1)}
className="flex items-center gap-1" className="flex shrink-0 items-center gap-1"
> >
Suivante Suivante
<ChevronRight className="h-4 w-4" /> <ChevronRight className="h-4 w-4" />
@ -1219,13 +1219,14 @@ const WeeklySummaryPage = ({ userId }) => {
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => navigateDay(-1)} onClick={() => navigateDay(-1)}
className="shrink-0"
> >
<ChevronLeft className="h-4 w-4" /> <ChevronLeft className="h-4 w-4" />
</Button> </Button>
<Badge <Badge
variant="secondary" variant="secondary"
className="text-sm" className="h-7 w-48 shrink-0 justify-center whitespace-nowrap text-sm tabular-nums"
> >
{weekDays[selectedDayIndex].toLocaleDateString( {weekDays[selectedDayIndex].toLocaleDateString(
'fr-FR', 'fr-FR',
@ -1241,6 +1242,7 @@ const WeeklySummaryPage = ({ userId }) => {
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => navigateDay(1)} onClick={() => navigateDay(1)}
className="shrink-0"
> >
<ChevronRight className="h-4 w-4" /> <ChevronRight className="h-4 w-4" />
</Button> </Button>