diff --git a/backend/app.py b/backend/app.py
index 4796422..54b258c 100644
--- a/backend/app.py
+++ b/backend/app.py
@@ -445,10 +445,12 @@ def get_schedule_week(start: str | None = None) -> dict[str, Any]:
week_start_date = datetime.strptime(week_start, "%Y-%m-%d").date()
rows = db.get_schedule_week(week_start, DB_PATH)
all_rows = db.get_schedule_rows_for_latest_version(DB_PATH)
+ completion_date = max((row.scheduled_date for row in all_rows), default=None)
holiday_dates = db.list_holidays(DB_PATH)
return {
"start_date": week_start,
"items": [_serialize_schedule_row(row) for row in rows],
+ "completion_date": completion_date,
"windows": _build_schedule_windows(week_start_date, all_rows, holiday_dates),
}
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index b28c188..9877bbc 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -206,6 +206,7 @@ export default function App() {
const data = await api.getScheduleWeek(toKey(start))
setScheduleData(groupScheduleItems(data.items))
setScheduleWindows(data.windows ?? [])
+ setCompletionDate(data.completion_date ?? null)
} catch (e) {
console.error('Failed to fetch schedule:', e)
}
diff --git a/frontend/src/components/Calendar.jsx b/frontend/src/components/Calendar.jsx
index 197e5d9..5ec8f3b 100644
--- a/frontend/src/components/Calendar.jsx
+++ b/frontend/src/components/Calendar.jsx
@@ -59,6 +59,7 @@ export default function Calendar({
windowLookup = new Map(),
onWindowSelect,
}) {
+ const DEFAULT_SHIFT_MIN_ROWS = 3
const SLOT_CHROME_PX = 10
const TEST_CARD_ROW_HEIGHT_PX = 22
const TEST_CARD_ROW_GAP_PX = 2
@@ -75,7 +76,11 @@ export default function Calendar({
// 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 }
+ const minima = {
+ shift2: DEFAULT_SHIFT_MIN_ROWS,
+ shift3: DEFAULT_SHIFT_MIN_ROWS,
+ nextDayShift1: DEFAULT_SHIFT_MIN_ROWS,
+ }
for (const date of orderedDays) {
const key = toDateKey(date)
@@ -83,16 +88,16 @@ export default function Calendar({
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)
+ minima.shift2 = Math.max(minima.shift2, shifts.shift2.length || DEFAULT_SHIFT_MIN_ROWS)
+ minima.shift3 = Math.max(minima.shift3, shifts.shift3.length || DEFAULT_SHIFT_MIN_ROWS)
+ minima.nextDayShift1 = Math.max(minima.nextDayShift1, nextDayShift1.length || DEFAULT_SHIFT_MIN_ROWS)
}
return minima
}, [orderedDays, scheduleData])
const slotHeights = useMemo(() => {
const calcSlotHeight = (rows) => {
- const safeRows = Math.max(1, rows || 1)
+ const safeRows = Math.max(DEFAULT_SHIFT_MIN_ROWS, rows || DEFAULT_SHIFT_MIN_ROWS)
const contentHeight = (safeRows * TEST_CARD_ROW_HEIGHT_PX) + ((safeRows - 1) * TEST_CARD_ROW_GAP_PX)
return contentHeight + SLOT_CHROME_PX
}
@@ -178,6 +183,17 @@ export default function Calendar({
9AM
5PM
12AM
+
+ Next Day
+
diff --git a/frontend/src/components/ShiftSlot.jsx b/frontend/src/components/ShiftSlot.jsx
index 3bc5756..7ece73e 100644
--- a/frontend/src/components/ShiftSlot.jsx
+++ b/frontend/src/components/ShiftSlot.jsx
@@ -8,7 +8,7 @@ export default function ShiftSlot({
visible = true,
active = false,
windowDetails = null,
- minContentRows = 1,
+ minContentRows = 3,
slotHeightPx = null,
onWindowSelect,
}) {