test
This commit is contained in:
parent
9d61e6f842
commit
923fbf1fbc
@ -4,6 +4,12 @@ import './TimeClockPage.css';
|
||||
import { timeApi } from '../api/time';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
const getNextDateKey = (dateKey) => {
|
||||
const nextDate = new Date(`${dateKey}T12:00:00`);
|
||||
nextDate.setDate(nextDate.getDate() + 1);
|
||||
return nextDate.toISOString().slice(0, 10);
|
||||
};
|
||||
|
||||
const TimeClockPage = () => {
|
||||
const videoRef = useRef(null);
|
||||
const streamRef = useRef(null);
|
||||
@ -269,9 +275,53 @@ const TimeClockPage = () => {
|
||||
const formatTime = (timeString) => {
|
||||
if (!timeString) return '00h00';
|
||||
const [hours, minutes] = timeString.split(':');
|
||||
if (hours === '24') return '23h59';
|
||||
return `${String(hours).padStart(2, '0')}h${String(minutes).padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const getDisplayTimeEntries = () => {
|
||||
const pairedEndIds = new Set();
|
||||
const expanded = [];
|
||||
const toMinutes = (time) => {
|
||||
const [hours, minutes] = time.split(':').map(Number);
|
||||
return hours * 60 + minutes;
|
||||
};
|
||||
|
||||
timeEntries.forEach((entry) => {
|
||||
if (!entry.start_time && entry.end_time) return;
|
||||
|
||||
if (entry.start_time && !entry.end_time) {
|
||||
const dateKey = String(entry.date).slice(0, 10);
|
||||
const matchingEnd = timeEntries.find((candidate) => (
|
||||
candidate.id !== entry.id &&
|
||||
!candidate.start_time &&
|
||||
candidate.end_time &&
|
||||
String(candidate.date).slice(0, 10) === getNextDateKey(dateKey) &&
|
||||
(candidate.user === entry.user || candidate.username === entry.username)
|
||||
));
|
||||
|
||||
if (matchingEnd) {
|
||||
pairedEndIds.add(matchingEnd.id);
|
||||
expanded.push({
|
||||
...entry,
|
||||
end_time: '24:00:00',
|
||||
duration: (1440 - toMinutes(entry.start_time)) / 60,
|
||||
});
|
||||
expanded.push({
|
||||
...matchingEnd,
|
||||
start_time: '00:00:00',
|
||||
duration: toMinutes(matchingEnd.end_time) / 60,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
expanded.push(entry);
|
||||
});
|
||||
|
||||
return expanded.filter((entry) => !pairedEndIds.has(entry.id));
|
||||
};
|
||||
|
||||
const formatDate = (dateString) => {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString('fr-FR');
|
||||
@ -446,7 +496,7 @@ const TimeClockPage = () => {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{timeEntries.map((entry) => (
|
||||
{getDisplayTimeEntries().map((entry) => (
|
||||
<tr key={entry.id}>
|
||||
{isAdmin &&
|
||||
<td>{entry.user}</td>
|
||||
|
||||
@ -8,6 +8,46 @@ const DEFAULT_END_HOUR = 18;
|
||||
const HOUR_HEIGHT = 64;
|
||||
const USER_COLORS = ['#c56a3d', '#3d7c8c', '#8a5a9e', '#5d8b55', '#c08a32', '#b04f66', '#4772a8'];
|
||||
|
||||
const getNextDateKey = (dateKey) => {
|
||||
const nextDate = new Date(`${dateKey}T12:00:00`);
|
||||
nextDate.setDate(nextDate.getDate() + 1);
|
||||
return nextDate.toISOString().slice(0, 10);
|
||||
};
|
||||
|
||||
const expandOvernightAttendances = (entries) => {
|
||||
const pairedEndIds = new Set();
|
||||
const expanded = [];
|
||||
|
||||
entries.forEach((entry) => {
|
||||
if (!entry.start_time && entry.end_time) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.start_time && !entry.end_time) {
|
||||
const dateKey = String(entry.date).slice(0, 10);
|
||||
const nextDateKey = getNextDateKey(dateKey);
|
||||
const matchingEnd = entries.find((candidate) => (
|
||||
candidate.id !== entry.id &&
|
||||
!candidate.start_time &&
|
||||
candidate.end_time &&
|
||||
String(candidate.date).slice(0, 10) === nextDateKey &&
|
||||
(candidate.user === entry.user || candidate.username === entry.username)
|
||||
));
|
||||
|
||||
if (matchingEnd) {
|
||||
pairedEndIds.add(matchingEnd.id);
|
||||
expanded.push({ ...entry, end_time: '24:00:00' });
|
||||
expanded.push({ ...matchingEnd, start_time: '00:00:00' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
expanded.push(entry);
|
||||
});
|
||||
|
||||
return expanded.filter((entry) => !pairedEndIds.has(entry.id));
|
||||
};
|
||||
|
||||
const WeeklySummaryPage = ({ userId }) => {
|
||||
const { isAdmin } = useAuth();
|
||||
const [attendances, setAttendances] = useState([]);
|
||||
@ -98,6 +138,11 @@ const WeeklySummaryPage = ({ userId }) => {
|
||||
return (hours * 60) + minutes;
|
||||
};
|
||||
|
||||
const formatSegmentTime = (minutes) => {
|
||||
if (minutes === 1440) return '23h59';
|
||||
return `${String(Math.floor(minutes / 60)).padStart(2, '0')}h${String(minutes % 60).padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const getUserColor = (username) => {
|
||||
const hash = [...username].reduce((total, character) => total + character.charCodeAt(0), 0);
|
||||
return USER_COLORS[hash % USER_COLORS.length];
|
||||
@ -105,7 +150,7 @@ const WeeklySummaryPage = ({ userId }) => {
|
||||
|
||||
const getAttendancesForDay = (date) => {
|
||||
const dateKey = formatDateKey(date);
|
||||
return attendances.filter((attendance) => String(attendance.date).slice(0, 10) === dateKey);
|
||||
return expandOvernightAttendances(attendances).filter((attendance) => String(attendance.date).slice(0, 10) === dateKey);
|
||||
};
|
||||
|
||||
const getAttendanceSegments = (dayAttendances) => {
|
||||
@ -144,7 +189,7 @@ const WeeklySummaryPage = ({ userId }) => {
|
||||
|
||||
const getScheduleBounds = (weekDays) => {
|
||||
const weekDateKeys = new Set(weekDays.map(formatDateKey));
|
||||
const weekAttendances = attendances.filter((attendance) => (
|
||||
const weekAttendances = expandOvernightAttendances(attendances).filter((attendance) => (
|
||||
weekDateKeys.has(String(attendance.date).slice(0, 10))
|
||||
));
|
||||
const times = weekAttendances.flatMap((attendance) => [
|
||||
@ -246,8 +291,8 @@ const WeeklySummaryPage = ({ userId }) => {
|
||||
<div className="schedule-day-column" key={formatDateKey(day)}>
|
||||
{hours.map((hour) => <span className="schedule-hour-line" key={hour} />)}
|
||||
{getAttendanceSegments(getAttendancesForDay(day)).map(({ start, end, users }) => {
|
||||
const startTime = `${String(Math.floor(start / 60)).padStart(2, '0')}:${String(start % 60).padStart(2, '0')}`;
|
||||
const endTime = `${String(Math.floor(end / 60)).padStart(2, '0')}:${String(end % 60).padStart(2, '0')}`;
|
||||
const startTime = formatSegmentTime(start);
|
||||
const endTime = formatSegmentTime(end);
|
||||
const segmentLabel = users.map(({ username }) => username).join(', ');
|
||||
return (
|
||||
isAdmin ? (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user