clean up calendar display, added separated device runtime overrides

This commit is contained in:
2026-07-13 02:43:52 -04:00
parent 6bf6fa4867
commit 42f75fecef
8 changed files with 317 additions and 110 deletions
+80 -31
View File
@@ -1,3 +1,4 @@
import { useMemo } from 'react'
import DayColumn from './DayColumn'
import { getDeviceAccentClass } from './TestCard'
@@ -58,6 +59,11 @@ export default function Calendar({
windowLookup = new Map(),
onWindowSelect,
}) {
const SLOT_CHROME_PX = 10
const TEST_CARD_ROW_HEIGHT_PX = 22
const TEST_CARD_ROW_GAP_PX = 2
const DAY_HEADER_HEIGHT_PX = 48
const today = new Date()
today.setHours(0, 0, 0, 0)
@@ -68,6 +74,36 @@ export default function Calendar({
// Reorder columns: Sun Mon Tue Wed Thu Fri Sat
// weekStart is Monday, so days[0]=Mon ... days[6]=Sun → put Sunday first
const orderedDays = [ ...days.slice(0, 7)]
const shiftMinRows = useMemo(() => {
const minima = { shift2: 1, shift3: 1, nextDayShift1: 1 }
for (const date of orderedDays) {
const key = toDateKey(date)
const shifts = scheduleData[key] ?? { shift1: [], shift2: [], shift3: [] }
const nextKey = toDateKey(addDays(date, 1))
const nextDayShift1 = scheduleData[nextKey]?.shift1 ?? []
minima.shift2 = Math.max(minima.shift2, shifts.shift2.length || 1)
minima.shift3 = Math.max(minima.shift3, shifts.shift3.length || 1)
minima.nextDayShift1 = Math.max(minima.nextDayShift1, nextDayShift1.length || 1)
}
return minima
}, [orderedDays, scheduleData])
const slotHeights = useMemo(() => {
const calcSlotHeight = (rows) => {
const safeRows = Math.max(1, rows || 1)
const contentHeight = (safeRows * TEST_CARD_ROW_HEIGHT_PX) + ((safeRows - 1) * TEST_CARD_ROW_GAP_PX)
return contentHeight + SLOT_CHROME_PX
}
return {
shift2: calcSlotHeight(shiftMinRows.shift2),
shift3: calcSlotHeight(shiftMinRows.shift3),
nextDayShift1: calcSlotHeight(shiftMinRows.nextDayShift1),
}
}, [shiftMinRows])
const totalShiftHeightPx = slotHeights.shift2 + slotHeights.shift3 + slotHeights.nextDayShift1
const deviceLegendItems = Array.from(
new Set(
Object.values(scheduleData)
@@ -135,37 +171,50 @@ export default function Calendar({
</div>
{/* 7-day grid */}
<div className="flex gap-1.5 flex-1 overflow-x-auto">
{orderedDays.map((date) => {
const key = toDateKey(date)
const shifts = scheduleData[key] ?? { shift1: [], shift2: [], shift3: [] }
const isToday = date.getTime() === today.getTime()
const isWeekend = date.getDay() === 0 || date.getDay() === 6
// Get next day's shift1 for display
const nextDate = addDays(date, 1)
const nextKey = toDateKey(nextDate)
const nextDayShift1 = scheduleData[nextKey]?.shift1 ?? []
// Which shifts on this date are part of the active test window?
const activeShifts = new Set()
if (key === activeWindow.shift3Date) activeShifts.add(3)
if (key === activeWindow.shift1Date) activeShifts.add(1)
// Check if next day's shift1 is active
const nextDayShift1Active = nextKey === activeWindow.shift1Date
return (
<DayColumn
key={key}
date={date}
isToday={isToday}
activeShifts={activeShifts}
shifts={shifts}
nextDayShift1={nextDayShift1}
nextDayShift1Active={nextDayShift1Active}
showShift2={isWeekend || (daytimeDateKey !== null && key === daytimeDateKey)}
windowLookup={windowLookup}
onWindowSelect={onWindowSelect}
/>
)
})}
<div className="flex gap-2 flex-1 min-h-0 overflow-hidden">
<div className="w-10 shrink-0 text-[10px] font-semibold uppercase tracking-wider text-gray-500">
<div style={{ height: `${DAY_HEADER_HEIGHT_PX}px` }} />
<div className="relative" style={{ height: `${totalShiftHeightPx}px` }}>
<span className="absolute left-0 top-0">9AM</span>
<span className="absolute left-0" style={{ top: `${slotHeights.shift2}px` }}>5PM</span>
<span className="absolute left-0" style={{ top: `${slotHeights.shift2 + slotHeights.shift3}px` }}>12AM</span>
</div>
</div>
<div className="flex gap-1.5 flex-1 overflow-x-auto">
{orderedDays.map((date) => {
const key = toDateKey(date)
const shifts = scheduleData[key] ?? { shift1: [], shift2: [], shift3: [] }
const isToday = date.getTime() === today.getTime()
const isWeekend = date.getDay() === 0 || date.getDay() === 6
// Get next day's shift1 for display
const nextDate = addDays(date, 1)
const nextKey = toDateKey(nextDate)
const nextDayShift1 = scheduleData[nextKey]?.shift1 ?? []
// Which shifts on this date are part of the active test window?
const activeShifts = new Set()
if (key === activeWindow.shift3Date) activeShifts.add(3)
if (key === activeWindow.shift1Date) activeShifts.add(1)
// Check if next day's shift1 is active
const nextDayShift1Active = nextKey === activeWindow.shift1Date
return (
<DayColumn
key={key}
date={date}
isToday={isToday}
activeShifts={activeShifts}
shifts={shifts}
nextDayShift1={nextDayShift1}
nextDayShift1Active={nextDayShift1Active}
shiftMinRows={shiftMinRows}
slotHeights={slotHeights}
showShift2={isWeekend || (daytimeDateKey !== null && key === daytimeDateKey)}
windowLookup={windowLookup}
onWindowSelect={onWindowSelect}
/>
)
})}
</div>
</div>
{/* Legend */}