diff --git a/frontend/src/pages/TimeClockPage.jsx b/frontend/src/pages/TimeClockPage.jsx index b8a2ab3..4b7c73d 100644 --- a/frontend/src/pages/TimeClockPage.jsx +++ b/frontend/src/pages/TimeClockPage.jsx @@ -6,10 +6,22 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; import { Alert, AlertDescription } from '@/components/ui/alert'; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; import ConfirmDialog from '@/components/ConfirmDialog'; -import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; import { Calendar } from '@/components/ui/calendar'; import { Popover, @@ -51,6 +63,7 @@ const formatDateLabel = (value) => { }); }; + const DatePicker = ({ value, onChange, @@ -74,6 +87,7 @@ const DatePicker = ({ } > + {selectedDate ? formatDateLabel(value) : placeholder} @@ -97,6 +111,7 @@ const DatePicker = ({ ); }; + const TimePicker = ({ value, onChange, @@ -107,18 +122,23 @@ const TimePicker = ({ const [hours = '', minutes = ''] = value ? value.split(':') : []; const setTimePart = (part, nextValue) => { - const nextHours = part === 'hours' ? nextValue : hours || '00'; - const nextMinutes = part === 'minutes' ? nextValue : minutes || '00'; + const nextHours = + part === 'hours' ? nextValue : hours || '00'; + + const nextMinutes = + part === 'minutes' ? nextValue : minutes || '00'; onChange(`${nextHours}:${nextMinutes}`); }; - const hourOptions = Array.from({ length: 24 }, (_, index) => - String(index).padStart(2, '0') + const hourOptions = Array.from( + { length: 24 }, + (_, index) => String(index).padStart(2, '0'), ); - const minuteOptions = Array.from({ length: 60 }, (_, index) => - String(index).padStart(2, '0') + const minuteOptions = Array.from( + { length: 60 }, + (_, index) => String(index).padStart(2, '0'), ); return ( @@ -133,14 +153,21 @@ const TimePicker = ({ } > + {value || placeholder} - +
- Choisir une heure + + Choisir une heure + + {value || '--:--'} @@ -151,6 +178,7 @@ const TimePicker = ({

Heure

+
{hourOptions.map((hour) => ( +

- Si le navigateur a déjà bloqué la caméra, autorisez-la dans les paramètres du site puis cliquez ici pour réessayer. + Si le navigateur a déjà + bloqué la caméra, autorisez-la + dans les paramètres du site + puis cliquez ici pour + réessayer.

)} + {scanMessage && ( - - {scanMessage} + + + {scanMessage} + )} + {scanConflict && ( - Conflit de pointage + + Conflit de pointage + + -

{scanConflict.message}

- +

+ {scanConflict.message} +

+ + + +
- - + +
-
-
- - -
- - ) : ( -
-
-
- - - setNewEntry({ ...newEntry, date: value }) - } - /> + + ) : ( +
+
+ +
+ + + + setNewEntry({ + ...newEntry, + date: value, + }) + } + /> +
+ + +
+ + + + setNewEntry({ + ...newEntry, + end_date: + value, + }) + } + /> +
+ + +
+ + + + setNewEntry({ + ...newEntry, + start_time: + value, + }) + } + /> +
+ + +
+ + + + setNewEntry({ + ...newEntry, + end_time: + value, + }) + } + /> +
-
- - - setNewEntry({ ...newEntry, end_date: value }) - } - /> -
-
- - - setNewEntry({ ...newEntry, start_time: value }) - } - /> -
-
- - - setNewEntry({ ...newEntry, end_time: value }) - } - /> -
-
- - - )} - - - )} + + + + + )} + + + )} + + + {/* ================================================== + POINTAGE QR + ================================================== */}
- {/* Pointage uniquement disponible sur mobile */} +
{ if (open) { - setIsScannerDialogOpen(true); + setIsScannerDialogOpen( + true, + ); } else { closeScanner(); } }} > - + - Aperçu de la caméra + + Aperçu de la caméra + + +
- {/* Sur ordinateur, le pointage est volontairement indisponible */} - {!isAdmin && + + {!isAdmin && (

- Le pointage est indisponible sur ordinateur. + Le pointage est + indisponible sur ordinateur.

- } + )} + + + {/* ================================================== + HISTORIQUE + ================================================== */} {showAllUsers ? 'Historique des pointages' - : `Historique des pointages de${selectedUser ? ` ${getUserLabel(selectedUser)}` : ''}`} + : `Historique des pointages de${ + selectedUser + ? ` ${getUserLabel( + selectedUser, + )}` + : '' + }`} + + {loading ? ( -

Chargement des pointages...

- ) : displayedTimeEntries.length === 0 ? ( -

Aucun pointage enregistré

+

+ Chargement des + pointages... +

+ ) : displayedTimeEntries.length === + 0 ? ( +

+ Aucun pointage + enregistré +

) : (
- {isAdmin && Nom} - Date - Entrée - Sortie - Durée - {isAdmin && Actions} + + {isAdmin && ( + + Nom + + )} + + + Date + + + + Entrée + + + + Sortie + + + + Durée + + + {isAdmin && ( + + Actions + + )} + + + - {getDisplayTimeEntries() - .filter( - (entry) => - !isAdmin || - showAllUsers || - getEntryUserId(entry) === String(selectedUserId), - ) - .map((entry) => ( - - {isAdmin && {entry.user.first_name} {entry.user.last_name}} - {formatDate(entry.date)} - {formatTime(entry.start_time)} - {formatTime(entry.end_time)} - {formatDuration(entry.duration)} - {isAdmin && ( + {displayedTimeEntries.map( + (entry) => ( + + + {isAdmin && ( + + {entry.user + ? getUserLabel( + entry.user, + ) + : 'Utilisateur inconnu'} + + )} + + -
- - handleDeleteEntry(entry.id)}> - - -
+ {formatDate( + entry.date, + )}
- )} -
- ))} + + + + {formatTime( + entry.start_time, + )} + + + + + {formatTime( + entry.end_time, + )} + + + + + + {formatDuration( + entry.duration, + )} + + + + + {isAdmin && ( + +
+ + + + + + handleDeleteEntry( + entry.id, + ) + } + > + + + +
+
+ )} + +
+ ), + )}
)}
+