This commit is contained in:
Louis Mazin 2026-09-20 00:38:55 +02:00
parent 17270122df
commit db61ec30e1

View File

@ -27,6 +27,10 @@ const DEFAULT_END_HOUR = 18;
const SCHEDULE_HEADER_HEIGHT = 58;
const MIN_SCHEDULE_HEIGHT = 180;
const MOBILE_TIME_COLUMN_WIDTH = 64;
const MOBILE_USER_COLUMN_WIDTH = 40;
const MOBILE_DEFAULT_CONTENT_WIDTH = 236;
const USER_COLORS = [
'#c56a3d',
'#3d7c8c',
@ -440,13 +444,6 @@ const WeeklySummaryPage = ({ userId }) => {
const tableTop =
scheduleTable.getBoundingClientRect().top;
/*
* Ici on calcule UNIQUEMENT la hauteur
* disponible pour les heures.
*
* Le header de 58px est ajouté séparément
* dans la hauteur totale du planning.
*/
const remainingHeight =
window.innerHeight -
tableTop -
@ -475,7 +472,13 @@ const WeeklySummaryPage = ({ userId }) => {
updateScheduleHeight,
);
};
}, [loading, error, showAllUsers, isMobile]);
}, [
loading,
error,
showAllUsers,
isMobile,
users.length,
]);
/*
* ------------------------------------------------------------
@ -898,7 +901,7 @@ const WeeklySummaryPage = ({ userId }) => {
/*
* ------------------------------------------------------------
* États du planning
* États
* ------------------------------------------------------------
*/
@ -941,13 +944,6 @@ const WeeklySummaryPage = ({ userId }) => {
const hourCount =
endHour - startHour;
/*
* Hauteur EXACTE de la zone horaire.
*
* Le header fait exactement 58px.
* La grille des heures utilise exactement
* availableScheduleHeight.
*/
const scheduleHeight = Math.max(
MIN_SCHEDULE_HEIGHT,
availableScheduleHeight,
@ -981,14 +977,25 @@ const WeeklySummaryPage = ({ userId }) => {
/*
* ------------------------------------------------------------
* Mobile
* Mobile : largeur des colonnes utilisateurs
* ------------------------------------------------------------
*/
const displayDay =
weekDays[
selectedDayIndex
];
const mobileUserCount =
Math.max(users.length, 1);
const mobileUsersWidth =
isAdmin && showAllUsers
? Math.max(
mobileUserCount *
MOBILE_USER_COLUMN_WIDTH,
MOBILE_DEFAULT_CONTENT_WIDTH,
)
: MOBILE_DEFAULT_CONTENT_WIDTH;
const mobilePlanningWidth =
MOBILE_TIME_COLUMN_WIDTH +
mobileUsersWidth;
/*
* ------------------------------------------------------------
@ -1111,7 +1118,9 @@ const WeeklySummaryPage = ({ userId }) => {
variant="secondary"
className="text-sm"
>
{displayDay.toLocaleDateString(
{weekDays[
selectedDayIndex
].toLocaleDateString(
'fr-FR',
{
weekday: 'long',
@ -1267,19 +1276,25 @@ const WeeklySummaryPage = ({ userId }) => {
{isMobile ? (
<div
className="grid min-w-[300px] grid-cols-1"
className="grid"
style={{
width: `${mobilePlanningWidth}px`,
minWidth: `${mobilePlanningWidth}px`,
height: `${totalPlanningHeight}px`,
gridTemplateRows: `${SCHEDULE_HEADER_HEIGHT}px ${scheduleHeight}px`,
}}
>
{/* Header */}
<div
className="sticky top-0 z-10 flex items-center justify-center border-b bg-background p-2 text-center font-medium"
className="flex items-center justify-center border-b bg-background p-2 text-center font-medium"
style={{
gridColumn: '1 / -1',
height: `${SCHEDULE_HEADER_HEIGHT}px`,
}}
>
{displayDay.toLocaleDateString(
{weekDays[
selectedDayIndex
].toLocaleDateString(
'fr-FR',
{
weekday: 'long',
@ -1289,9 +1304,12 @@ const WeeklySummaryPage = ({ userId }) => {
)}
</div>
{/* Corps */}
<div
className="grid grid-cols-[64px_1fr]"
className="grid"
style={{
gridColumn: '1 / -1',
gridTemplateColumns: `${MOBILE_TIME_COLUMN_WIDTH}px ${mobileUsersWidth}px`,
height: `${scheduleHeight}px`,
}}
>
@ -1319,34 +1337,53 @@ const WeeklySummaryPage = ({ userId }) => {
)}
</div>
{/* Planning */}
{/* Zone utilisateurs */}
<div
className="relative"
style={{
height: `${scheduleHeight}px`,
width: `${mobileUsersWidth}px`,
}}
>
{/* Grille horaire */}
{hours.map(
(hour) => (
<div
key={hour}
className="border-b border-gray-200"
className="absolute left-0 right-0 border-b border-gray-200"
style={{
top: `${
(hour -
startHour) *
hourHeight
}px`,
height: `${hourHeight}px`,
}}
/>
),
)}
{/* ==================================================
ADMIN + TOUS LES UTILISATEURS
1 utilisateur = 1 colonne
================================================== */}
{isAdmin &&
showAllUsers ? (
<div className="absolute inset-0 flex">
<div
className="absolute inset-0 grid"
style={{
gridTemplateColumns: `repeat(${mobileUserCount}, minmax(${MOBILE_USER_COLUMN_WIDTH}px, 1fr))`,
}}
>
{users.map(
(user) => {
const bounds =
getUserDayBounds(
getAttendancesForDay(
displayDay,
weekDays[
selectedDayIndex
],
),
user,
);
@ -1356,57 +1393,57 @@ const WeeklySummaryPage = ({ userId }) => {
user,
);
if (!bounds) {
return (
<div
key={getUserId(
user,
)}
className="relative min-w-0 flex-1"
/>
);
}
const style =
getAttendanceStyle(
bounds.start,
bounds.end,
startHour,
endHour,
hourHeight,
);
return (
<div
key={getUserId(
user,
)}
className="relative min-w-0 flex-1"
title={`${getUserLabel(
className="relative border-r border-border/30 last:border-r-0"
title={
bounds
? `${getUserLabel(
user,
)} : ${formatSegmentTime(
bounds.start,
)} - ${formatSegmentTime(
bounds.end,
)}`}
)}`
: getUserLabel(
user,
)
}
>
{bounds && (
<div
className="absolute left-1/2 w-2 -translate-x-1/2 rounded-full"
style={{
...style,
...getAttendanceStyle(
bounds.start,
bounds.end,
startHour,
endHour,
hourHeight,
),
backgroundColor:
color,
}}
/>
)}
</div>
);
},
)}
</div>
) : (
/*
* Utilisateur sélectionné /
* utilisateur normal.
*/
getSelectedUserAttendances(
getAttendancesForDay(
displayDay,
weekDays[
selectedDayIndex
],
),
)
.map(
@ -1452,10 +1489,14 @@ const WeeklySummaryPage = ({ userId }) => {
return (
<div
key={`${formatDateKey(
displayDay,
weekDays[
selectedDayIndex
],
)}-${start}-${end}`}
className="absolute left-0 right-0 rounded-sm border border-blue-600/30 bg-blue-500/80"
style={style}
className="absolute left-0 right-0 overflow-hidden rounded-sm border border-blue-600/30 bg-blue-500/80"
style={
style
}
>
<div className="p-1 text-xs text-white">
{formatSegmentTime(
@ -1484,10 +1525,8 @@ const WeeklySummaryPage = ({ userId }) => {
style={{
gridTemplateColumns:
'64px repeat(7, minmax(120px, 1fr))',
gridTemplateRows:
`${SCHEDULE_HEADER_HEIGHT}px ${scheduleHeight}px`,
height: `${totalPlanningHeight}px`,
}}
>
@ -1597,13 +1636,12 @@ const WeeklySummaryPage = ({ userId }) => {
{/* ==================================================
ADMIN : TOUS LES UTILISATEURS
1 colonne = 1 utilisateur
1 barre = 1 utilisateur
1 utilisateur = 1 colonne
================================================== */}
{isAdmin &&
showAllUsers ? (
<div className="absolute inset-0 flex">
<div className="absolute inset-0 grid grid-cols-[repeat(auto-fit,minmax(0,1fr))]">
{users.map(
(user) => {
const bounds =
@ -1622,7 +1660,7 @@ const WeeklySummaryPage = ({ userId }) => {
key={getUserId(
user,
)}
className="relative min-w-0 flex-1 border-r border-border/30 last:border-r-0"
className="relative min-w-0 border-r border-border/30 last:border-r-0"
title={
bounds
? `${getUserLabel(
@ -1659,10 +1697,9 @@ const WeeklySummaryPage = ({ userId }) => {
)}
</div>
) : (
/* ==================================================
UTILISATEUR SÉLECTIONNÉ
================================================== */
/*
* Utilisateur sélectionné
*/
getSelectedUserAttendances(
dayAttendances,
)