import { fail, redirect } from '@sveltejs/kit'; import { hono } from '$lib/server/hono'; import { PROXY_URL } from '$app/env/public'; const HONO_URL = PROXY_URL; export async function load(event) { const session = event.locals.session; // Parent (session auth) → admin overview if (session) { const famId = session.famId; const famSlug = event.params.fam; const username = event.params.username; if (session.memberName && session.memberName !== username) { throw redirect(303, `/${famSlug}/${session.memberName}`); } const [ members, templates, assigned, summary, fam, rewards, bonusConfigs, completions, settings ] = await Promise.all([ hono.admin.list(event, 'members', famId), hono.admin.list(event, 'chore-templates', famId), hono.admin.list(event, 'assigned-chores', famId), hono.admin.weeklySummary(event, famId), hono.admin.fam(event, famId), hono.admin.rewards(event, famId), hono.admin.bonusConfigs(event, famId), hono.admin.completions(event, famId), hono.admin.settings(event, famId).catch(() => ({})) ]); return { role: 'parent', members, templates, assigned, summary, fam, famSlug, rewards, bonusConfigs, completions, settings }; } // Child (device token) → kanban const deviceToken = event.cookies.get('device_token') || event.url.searchParams.get('token') || ''; const famSlug = event.params.fam; const username = event.params.username; if (!deviceToken) { return { role: 'child', token: '', memberId: '', verified: false, famId: '', templates: [], assigned: [], completions: [], rewards: [], bonusConfigs: [], tallies: {} }; } try { const res = await fetch(`${HONO_URL}/api/members/verify-token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ deviceToken, famSlug }) }); const data = await res.json(); if (!res.ok || data.name !== username) { return { role: 'child', token: deviceToken, memberId: '', verified: false, famId: '', memberName: '', memberColor: '', templates: [], assigned: [], completions: [], rewards: [], bonusConfigs: [], tallies: {} }; } let chores: any = {}; try { const choresRes = await fetch(`${HONO_URL}/api/members/my-chores`, { method: 'POST', headers: { 'x-device-token': deviceToken, 'x-device-famid': data.famId } }); chores = await choresRes.json(); } catch {} return { role: 'child', token: deviceToken, memberId: data.memberId, famId: data.famId, verified: true, memberName: data.name, memberColor: data.color, templates: chores.templates || [], assigned: chores.assigned || [], completions: chores.completions || [], rewards: chores.rewards || [], bonusConfigs: chores.bonusConfigs || [], tallies: chores.tallies || {}, payday: chores.payday, paydayTime: chores.paydayTime || '18:00', timezone: chores.timezone || 'auto', simulateEow: !!chores.simulateEow }; } catch { return { role: 'child', token: deviceToken, memberId: '', verified: false, famId: '', templates: [], assigned: [], completions: [], rewards: [], bonusConfigs: [], tallies: {}, payday: 1, paydayTime: '18:00', timezone: 'auto' }; } } export const actions = { setEow: async (event) => { if (!event.locals.session) throw redirect(303, '/login'); const famId = event.locals.session.famId; const fd = await event.request.formData(); const on = fd.get('on') === 'true'; try { const result = await hono.admin.updateSettings(event, famId, { simulateEow: on }); return { simulateEow: result.simulateEow }; } catch (e) { return { error: e instanceof Error ? e.message : 'Failed to update settings' }; } }, previewEow: async (event) => { if (!event.locals.session) throw redirect(303, '/login'); const famId = event.locals.session.famId; try { const preview = await hono.admin.eowPreview(event, famId); await hono.admin.updateSettings(event, famId, { simulateEow: true }); return { preview, simulateEow: true }; } catch (e) { return { error: e instanceof Error ? e.message : 'Failed to preview payday' }; } }, claim: async (event) => { if (!event.locals.session) throw redirect(303, '/login'); const famId = event.locals.session.famId; const fd = await event.request.formData(); const rewardId = fd.get('id') as string; try { const record = await hono.admin.claimReward(event, famId, rewardId); return { record }; } catch (e) { return { error: e instanceof Error ? e.message : 'Failed to claim reward' }; } }, issueAll: async (event) => { if (!event.locals.session) throw redirect(303, '/login'); const famId = event.locals.session.famId; const fd = await event.request.formData(); const memberId = fd.get('memberId') as string; try { const result = await hono.admin.issueAllRewards(event, famId, memberId); return { count: result.count }; } catch (e) { return { error: e instanceof Error ? e.message : 'Failed to issue rewards' }; } }, revoke: async (event) => { if (!event.locals.session) throw redirect(303, '/login'); const famId = event.locals.session.famId; const fd = await event.request.formData(); const completionId = fd.get('id') as string; try { await hono.admin.revokeCompletion(event, famId, completionId); return { revoked: true, id: completionId }; } catch (e) { return { error: e instanceof Error ? e.message : 'Failed to revoke' }; } }, trigger: async (event) => { if (!event.locals.session) throw redirect(303, '/login'); const famId = event.locals.session.famId; const fd = await event.request.formData(); const configId = fd.get('configId') as string; const memberId = fd.get('memberId') as string; if (!configId) return { error: 'Config ID required' }; try { const result = await hono.admin.triggerBonusConfig( event, famId, configId, memberId || undefined ); return { records: result.records || [] }; } catch (e) { return { error: e instanceof Error ? e.message : 'Failed to trigger' }; } } };