Initial project scaffold

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>
This commit is contained in:
2026-02-27 22:56:31 -08:00
parent 93e0494864
commit 417b3adfe8
68 changed files with 3919 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import api from '@/composables/useApi'
export const useScheduleStore = defineStore('schedule', () => {
const session = ref(null)
const blocks = ref([])
const completedBlockIds = ref([])
const child = ref(null)
const currentBlock = computed(() =>
session.value?.current_block_id
? blocks.value.find((b) => b.id === session.value.current_block_id) || null
: null
)
const progressPercent = computed(() => {
if (!blocks.value.length) return 0
return Math.round((completedBlockIds.value.length / blocks.value.length) * 100)
})
function applySnapshot(snapshot) {
session.value = snapshot.session
blocks.value = snapshot.blocks || []
completedBlockIds.value = snapshot.completed_block_ids || []
if (snapshot.child) child.value = snapshot.child
}
function applyWsEvent(event) {
if (event.event === 'session_update') {
applySnapshot(event)
return
}
// Timer events update session state
if (event.current_block_id !== undefined && session.value) {
session.value.current_block_id = event.current_block_id
}
if (event.event === 'complete' && event.block_id) {
if (!completedBlockIds.value.includes(event.block_id)) {
completedBlockIds.value.push(event.block_id)
}
}
}
async function fetchDashboard(childId) {
const res = await api.get(`/api/dashboard/${childId}`)
applySnapshot(res.data)
}
async function startSession(childId, templateId) {
const res = await api.post('/api/sessions', {
child_id: childId,
template_id: templateId,
})
session.value = res.data
completedBlockIds.value = []
}
async function sendTimerAction(sessionId, eventType, blockId = null) {
await api.post(`/api/sessions/${sessionId}/timer`, {
event_type: eventType,
block_id: blockId,
})
}
return {
session,
blocks,
completedBlockIds,
child,
currentBlock,
progressPercent,
applySnapshot,
applyWsEvent,
fetchDashboard,
startSession,
sendTimerAction,
}
})