homeman-deno/islands/Routine.tsx
2024-01-21 20:39:24 -06:00

111 lines
2.7 KiB
TypeScript

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<DailyPhase, string> = {
Morning: '🌄',
Midday: '🌞',
Evening: '🌆',
Bedtime: '🛌',
Night: '🌙',
}
type TaskGroups = Record<DailyPhase, TaskWithIndex[]>
let lastPhaseSelection = new Date()
export function Routine(
props: Props,
) {
const tasks = useSignal(props.tasks)
const currentPhase = useSignal(toPhase())
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 (
<>
<nav class='flex overflow-x-scroll'>
{DailyPhaseModel.options.map((phase) => (
<button
onClick={() => {
currentPhase.value = phase
lastPhaseSelection = new Date()
}}
class={`p-4 shrink-0 grow border-b-2 text-lg ${
currentPhase.value == phase
? 'border-purple-500'
: 'border-gray-500/20 hover:border-gray-500'
}`}
>
{phaseEmoji[phase]} {phase}
</button>
))}
</nav>
<main class='flex flex-col overflow-x-scroll'>
<ul>
{taskGroups[currentPhase.value].map((
task: TaskWithIndex,
) => {
const { emoji, description, doneAt, index } = task
return (
<li
role='button'
class={`text-lg cursor-pointer p-4 hover:bg-gray-500/20 ${
doneAt ? 'line-through opacity-30 hover:bg-gray-500' : ''
}`}
onClick={async () => {
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()}
</li>
)
})}
</ul>
</main>
</>
)
}