clean up calendar display, added separated device runtime overrides
This commit is contained in:
@@ -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 */}
|
||||
|
||||
Reference in New Issue
Block a user