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>
80 lines
2.1 KiB
JavaScript
80 lines
2.1 KiB
JavaScript
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,
|
|
}
|
|
})
|