import { DailyPhase, DailyPhaseModel, Task, toPhase } from '@homeman/models.ts' import { signal, useSignal } from '@preact/signals' import { excitement } from '@homeman/common.ts' import { IS_BROWSER } from '$fresh/runtime.ts' import { useEffect } from 'preact/hooks' export interface Props { tasks: Task[] } interface TaskWithIndex extends Task { index: number } const phaseEmoji: Record = { Morning: '🌄', Midday: '🌞', Evening: '🌆', Bedtime: '🛌', Night: '🌙', } type TaskGroups = Record let lastPhaseSelection = new Date() export function Routine( props: Props, ) { const tasks = useSignal(props.tasks) const currentPhase = useSignal(toPhase()) const reload = async () => { console.log('reloading...') const newData = await (await fetch(location.href, { headers: { accept: 'application/json' }, })).json() tasks.value = newData console.log('new tasks:', newData) } useEffect(() => { let es = new EventSource('/api/tasks') console.log('Streaming task events...') es.addEventListener('message', (e) => { console.log('task event from server:', e) reload() }) es.addEventListener('error', async (e) => { // try and reconnect console.log('Streaming todo events error:', e) es.close() const backoff = 10000 + Math.random() * 5000 await new Promise((resolve) => setTimeout(resolve, backoff)) es = new EventSource('/api/tasks') }) }, []) useEffect(() => { if (IS_BROWSER) { setInterval(() => { const delta = (new Date()).getTime() - lastPhaseSelection.getTime() const nowPhase = toPhase() if (nowPhase != currentPhase.value && delta >= 1000 * 60 * 10) { currentPhase.value = nowPhase lastPhaseSelection = new Date() } }, 5_000) } }, []) const taskGroups: TaskGroups = { Morning: [], Midday: [], Evening: [], Bedtime: [], Night: [], } tasks.value.forEach((t, i) => taskGroups[t.phase].push({ ...t, index: i })) return ( <>
    {taskGroups[currentPhase.value].map(( task: TaskWithIndex, ) => { const { emoji, description, doneAt, index } = task return (
  • { tasks.value[index].doneAt = tasks.value[index].doneAt ? null : new Date() tasks.value = [...tasks.value] if (tasks.value[index].doneAt) { excitement() } await (await fetch('/api/tasks', { method: 'PUT', body: JSON.stringify({ ...task, done: !!tasks.value[index].doneAt, }), })).json() }} > {emoji ? `${emoji.trim()} ` : ''} {description.trim()}
  • ) })}
) }