- Extend start-time trigger window from 15s to 5 min so opening the
dashboard late still marks the meeting as started
- Only play chime and show TV overlay when within 30s of start time
- Skip switchBlock call when the session is already on that block
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 📝 Agenda button to each block in Today's Schedule on the Dashboard
- Dialog allows setting a free-text activity/note for that block for the current day
- Agenda replaces subject options in the TV center panel while set; clears on session end
- Backend: new SessionBlockAgenda model, PUT /api/sessions/{id}/blocks/{block_id}/agenda
- Agendas included in dashboard snapshot and session_update WS broadcast
- New agenda_update WS event keeps TV in sync live when agenda is saved or cleared
- Update README with feature description, project structure, and WS event table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each child is assigned a unique permanent tv_token on creation. The TV
dashboard URL (/tv/:tvToken) and WebSocket (/ws/:tvToken) now use this
token instead of the internal DB ID. Existing children are backfilled
on startup. README updated to reflect the change.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Done button snaps block to full duration, marks complete, logs "Marked Done by User"; Reset after Done fully un-completes the block
- Session action buttons stretch full-width and double height for tablet tapping
- Super admin: reset password, disable/enable accounts, delete user (with cascade), last active date per user's timezone
- Disabled account login returns specific error message instead of generic invalid credentials
- Users can change own password from Admin → Settings
- Strikes reset automatically at midnight in user's configured timezone (lazy reset on page load)
- Break timer state fully restored when navigating away and back to dashboard
- Timer no longer auto-starts on navigation if it wasn't running before
- Implicit pause guard: no duplicate pause events when switching already-paused blocks or starting a break
- Block selection events removed from activity log; all event types have human-readable labels
- House emoji favicon via inline SVG data URI
- README updated to reflect all changes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Auto-create a locked "Meeting" subject for every user on registration
and seed it for all existing users on startup
- Meeting subject cannot be deleted or renamed (is_system flag)
- 5-minute corner toast warning on Dashboard and TV with live countdown,
dismiss button, and 1-minute re-notify if dismissed
- At start time: full-screen TV overlay with 30-second auto-dismiss,
automatic pause of running block, switch to Meeting block, and
auto-start of Meeting timer
- Web Audio API chimes: rising on warnings, falling at meeting start
- Update README with Meeting subject and notification system docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Starting break now pauses the main block timer (frontend optimistic +
backend implicit pause event recorded before break_start)
- Resuming/starting the main block while break is active pauses the
break timer and exits break mode on all clients including TV
- Timer display counts negative past zero so overtime is visible while
label stays "Done!"
- Fixed WS start handler incorrectly skipping break-mode clear when
restarting the same block; resume handler now also clears break mode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both the TV and parent dashboard progress bars now calculate % complete
based on total scheduled block time vs. remaining block + break time,
so the bar only advances while blocks are actively being worked.
TV bar labels changed to "🟢 Start" and "Finish 🏁".
Parent dashboard shows first block's scheduled start time on the left
and a live estimated finish time (now + remaining block/break time) on
the right.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin: per-block "Break Time" checkbox + duration (min) setting; new
Break Activities section (global list, same pattern as Morning Routine)
- Dashboard: break timer section appears on blocks with break enabled;
Start/Pause/Resume/Reset controls work independently of the main timer
- TV: left column switches to amber break badge + countdown during break;
center column shows configurable Break Activities list
- Backend: break_time_enabled/break_time_minutes columns on schedule_blocks
(auto-migrated on startup); break_activity_items table + CRUD router;
break timer events (break_start/pause/resume/reset) stored as TimerEvents
and broadcast via WebSocket; break_activities included in dashboard
snapshot and session_update broadcast
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reset clears the current block's elapsed time to zero and immediately
starts the timer. A shared compute_block_elapsed() utility (utils/timer.py)
handles the elapsed calculation in both the sessions and dashboard routers,
and correctly treats "reset" events as zero-elapsed restart markers so
page reloads after a reset show accurate times.
Layout: Start/Pause/Resume/Reset are grouped on the left; End Day sits
on the right via justify-content: space-between.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Blocks are now selected without auto-starting the timer. Clicking a block
makes it current (highlighted) but leaves it in a ready state. A "Start"
button (indigo) triggers timing for a fresh block; "Resume" appears for
previously-worked blocks; "Pause" remains while running.
Also fixes the sidebar duration label to show "Done!" when elapsed ≥ total
and "< 1 min" for sub-minute remaining time instead of "0 min".
Backend adds a "select" event type that records an implicit pause for the
previous block, updates current_block_id, and broadcasts is_paused=true
with prev_block_elapsed_seconds so the TV sidebar stays accurate.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Block list on both dashboards now shows time remaining on each block's
timer (allocated duration minus elapsed) instead of total duration;
the active block counts down live every second
- Fix block switching requiring 2 clicks: replace separate pause+start
requests with a single start request; backend implicitly records a
pause event for the previous block atomically
- Export blockElapsedCache from store so views can compute per-block
elapsed for both running and paused blocks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Double-click fix:
- After awaiting the pause, optimistically set current_block_id and
isPaused on the store so the UI switches instantly. The subsequent
WS start event confirms the state without requiring a second click.
TV elapsed reset fix:
- The TV's local cache was empty for blocks paused before it connected,
so returning to those blocks showed 0 elapsed.
- Backend now computes the block's accumulated elapsed from previous
start/pause cycles and includes it as block_elapsed_seconds in the
'start' WS event payload.
- All clients (Dashboard and TV) now use this authoritative server value
instead of relying solely on the local cache.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, clicking a different block always fired 'start' which reset
elapsed to zero — returning to a block lost all accumulated time.
Store changes:
- Add blockElapsedCache (blockId → elapsed seconds) that persists across
block switches within a session
- On 'pause' WS event: write the block's total elapsed into the cache
- On 'start' WS event: restore elapsed from cache (0 if never worked)
- On applySnapshot: seed cache with server-computed elapsed for the
current block (so reloading preserves state correctly)
- Clear cache when the session ends
Dashboard selectBlock changes:
- Auto-pause the currently running block before switching to another
- Clicking the active block while paused now sends 'resume' instead of
doing nothing
- Clicking the already-running active block is a no-op
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Adds strikes (0-3) to Child model with migration
- New PATCH /api/children/{id}/strikes endpoint with WebSocket broadcast
- TV dashboard shows red ✕ marks next to child name when strikes > 0
- 3 Strikes card on Dashboard page (removed from Admin)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces block-count progress with a wall-clock progress bar driven by
configurable day start/end hours on each schedule template.
- ScheduleTemplate: add day_start_time / day_end_time (TIME, nullable)
- Startup migration: idempotent ALTER TABLE for existing DBs
- Dashboard snapshot: includes day_start_time / day_end_time from template
- Admin → Schedules: time pickers in block editor to set day hours
- Dashboard view: time-based progress bar with start/current/end labels
- TV view: full-width day progress strip between header and main content
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Backend computes block_elapsed_seconds server-side from timer_events
- Store tracks blockStartedAt (ms) + blockElapsedOffset (seconds) instead
of a client-side counter; updated correctly on start/pause/resume/end
- TimerDisplay derives elapsed from store props so both views always agree
- Add compact timer display to dashboard session card
- Add isPaused/pause-resume logic to dashboard Pause/Resume buttons
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full-stack homeschool web app with FastAPI backend, Vue 3 frontend,
MySQL database, and Docker Compose orchestration. Includes JWT auth,
WebSocket real-time TV dashboard, schedule builder, activity logging,
and multi-child support.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>