From beb488b3d6da49e91b50be830c6d8c68b080f4e1 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Sun, 21 Jan 2024 14:23:45 -0600 Subject: [PATCH 1/5] WIP --- .gitignore | 2 + db.ts | 6 +- models.ts | 8 +-- playground.ts | 60 ++++++++++++++++++ routes/api/tasks.ts | 144 +++++++++++++++++++++++--------------------- routes/routine.tsx | 60 ++---------------- 6 files changed, 145 insertions(+), 135 deletions(-) create mode 100644 playground.ts diff --git a/.gitignore b/.gitignore index 38e2f67..7721393 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ node_modules/ *.db-shm /static/uploads + +/data diff --git a/db.ts b/db.ts index 2b02ada..58b2f3b 100644 --- a/db.ts +++ b/db.ts @@ -2,7 +2,7 @@ import { createPentagon, TableDefinition, } from 'https://deno.land/x/pentagon@v0.1.5/mod.ts' -import { DoneTaskModel, TodoModel, UserModel } from '@homeman/models.ts' +import { TaskModel, TodoModel, UserModel } from '@homeman/models.ts' export const kv = await Deno.openKv('homeman.db') @@ -19,8 +19,8 @@ export const schema: Record = { assignee: ['users', UserModel, 'assigneeUserId', 'id'], }, }, - doneTasks: { - schema: DoneTaskModel, + tasks: { + schema: TaskModel, }, } diff --git a/models.ts b/models.ts index 2a87408..34edf0b 100644 --- a/models.ts +++ b/models.ts @@ -58,16 +58,10 @@ export function toPhase(dt?: Date | null): z.infer { const Task = z.object({ id: z.string(), + description: z.string(), emoji: z.string().nullable(), doneAt: z.date().nullable(), phase: DailyPhase, }) export const TaskModel = Task export type Task = z.infer - -const DoneTask = Task.pick({ - id: true, - doneAt: true, -}) -export const DoneTaskModel = DoneTask -export type DoneTask = z.infer diff --git a/playground.ts b/playground.ts new file mode 100644 index 0000000..0d386a1 --- /dev/null +++ b/playground.ts @@ -0,0 +1,60 @@ +import { DailyPhase, TaskModel } from '@homeman/models.ts' +import { db } from '@homeman/db.ts' +import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' + +const hardcoded: Record = { + 'Morning': [ + ['🥣', 'Breakfast'], + ['🪥', 'Brush teeth'], + ['👕', 'Get dressed'], + ['🙏', 'Ask and thank Jesus'], + ['✝️', 'Bible story or devotional'], + ['📚', 'School: with Mrs. Emily or Mama'], + ['🎨', 'Create time: 🧶craft ✏️ draw 🧑🏼‍🎨 paint'], + ['🏗️', ' Build time: 🧱legos 🚂train tracks 🏎magna tiles'], + ['👯', 'Friend time: playdate or neighbor time'], + ['🚗', 'Outing: 📚library 🌳park 🥑groceries ☕ coffee shop'], + ], + 'Midday': [ + ['🥓', 'Lunch'], + ['🧹', 'Tidy time'], + ['🤫', 'Quiet time'], + ['🏃', 'BIG energy time: 🚲bike 🥁 drums 🤸 silly play'], + ['👯', 'Friend time: playdate or neighbor time'], + ['🚗', 'Outing: 📚library 🌳park 🥑groceries'], + ], + 'Evening': [ + ['🍽️', 'Dinner'], + ['🚗', 'Outing'], + ['👪', 'Family time: 🃏games 🕺dance party 🤸silly play 🏋️workout'], + ], + 'Bedtime': [ + ['🪥', 'Brush teeth'], + ['🛁', 'Take bath'], + ['👕', 'Put on pajamas'], + ['🙏', 'Ask and thank Jesus'], + ['✝️', 'Bible story or devotional'], + ['📕', 'Read a story'], + ['❤', 'Emotions check in: 😭 😡 😂 😟 😣 😀 ☹️ 😰 😁'], + ], + 'Night': [ + ['👨‍⚖️', 'Sleep!'], + ], +} +Object.entries(hardcoded).forEach(async ([tphase, phaseTasks]) => { + const phase = tphase as DailyPhase + for (const [emoji, description] of phaseTasks) { + const task = TaskModel.parse({ + phase, + emoji, + description, + id: ulid(), + doneAt: null, + }) + console.log(task) + const result = await db.tasks.create({ + data: task, + }) + console.log('after create:', result) + } +}) diff --git a/routes/api/tasks.ts b/routes/api/tasks.ts index a21e1fe..69fa4c7 100644 --- a/routes/api/tasks.ts +++ b/routes/api/tasks.ts @@ -1,81 +1,81 @@ import { Handlers } from '$fresh/server.ts' -import { DoneTask, DoneTaskModel } from '@homeman/models.ts' +import { Task, TaskModel } from '@homeman/models.ts' import { db, kv } from '@homeman/db.ts' +import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' import { z } from 'https://deno.land/x/zod@v3.21.4/mod.ts' -const DoneTaskPayload = DoneTaskModel.partial({ doneAt: true }) -type DoneTaskPayload = z.infer +const TaskPayload = TaskModel.partial({ id: true }) +type TaskPayload = z.infer -export const handler: Handlers = { +async function createOrUpdate(task: TaskPayload) { + if (!task.id || task.id === '') { + const newTask: Task = { + ...task, + id: ulid(), + } + const result = await db.tasks.create({ data: newTask }) + await kv.set(['last_task_updated'], newTask.id) + return result + } else { + const result = await db.tasks.update({ where: { id: task.id }, data: task }) + await kv.set(['last_task_updated'], task.id) + return result + } +} + +export const handler: Handlers = { async POST(req, _ctx) { - // a task is marked done - let id: string | undefined if (req.headers.get('content-type')?.includes('json')) { - id = DoneTaskPayload.parse(await req.json()).id - } else { - id = new URL(req.url).searchParams.get('id') || undefined - } - console.log('done task post:', id) - if (!id) { - return new Response( - JSON.stringify({ - message: "can't complete task with id empty string", - }), - { status: 400 }, + const result = await createOrUpdate( + TaskPayload.parse(await req.json()), ) + return new Response(JSON.stringify(result)) + } else { + const form = await req.formData() + const id = form.get('id')?.toString() || undefined + + const doneAt = form.get('doneAt') + console.log('task POST doneAt:', doneAt) + + const task = TaskPayload.parse({ + id: id, + emoji: form.get('emoji')?.toString() || null, + doneAt: form.get('doneAt')?.toString() || null, + description: form.get('description')?.toString(), + assigneeUserId: form.get('assigneeUserId')?.toString() || null, + }) + + if (!id) { + delete task.id + } + + if (!task.assigneeUserId) { + delete task.id + } + + await createOrUpdate(task) + + const url = new URL(req.url) + url.pathname = '/' + return Response.redirect(url, 303) } - - const newDoneTask: DoneTask = { - id, - doneAt: new Date(), - } - const res = await db.doneTasks.create({ - data: newDoneTask, - }) - console.log('done task create result:', res) - console.log(await db.doneTasks.findMany({})) - - await kv.set(['last_task_updated'], id) - - return new Response(JSON.stringify({ id })) }, async DELETE(req, _ctx) { - let id: string | undefined + // task: form or query params or json + let data if (req.headers.get('content-type')?.includes('json')) { - id = DoneTaskPayload.parse(await req.json()).id + data = await req.json() } else { - id = new URL(req.url).searchParams.get('id') || undefined + data = { id: new URL(req.url).searchParams.get('id') } } - console.log('done task delete:', id) - if (!id) { - return new Response( - JSON.stringify({ - message: "can't uncomplete task with id empty string", - }), - { status: 400 }, - ) - } - if (!id) { - return new Response( - JSON.stringify({ - message: "can't complete task with id empty string", - }), - { status: 400 }, - ) - } - - await db.doneTasks.deleteMany({ - where: { - id, - }, - }) - - await kv.set(['last_task_updated'], id) - - return new Response(JSON.stringify({ id })) + console.log('delete task data:', data) + const taskData = TaskModel.pick({ id: true }).parse(data) + const result = await db.tasks.delete({ where: taskData }) + await kv.set(['last_task_updated'], taskData.id) + return new Response(JSON.stringify(result)) }, async GET(req, ctx) { - // TODO: json or query params + // task: json or query params const accept = req.headers.get('accept') if (accept === 'text/event-stream') { console.log('Request for task event stream') @@ -98,7 +98,7 @@ export const handler: Handlers = { continue } - const task = await db.doneTask.findFirst({ + const task = await db.tasks.findFirst({ where: { id: entry.value }, }) const chunk = `data: ${ @@ -108,21 +108,21 @@ export const handler: Handlers = { value: task, }) }\n\n` - console.log('todo event chunk:', chunk) + console.log('task event chunk:', chunk) controller.enqueue(new TextEncoder().encode(chunk)) } if (entries.done) { return } } catch (e) { - console.error(`Error refreshing todo:`, e) + console.error(`Error refreshing task:`, e) } } }, cancel() { stream.cancel() console.log( - `Closed todo updates stream to ${JSON.stringify(ctx.remoteAddr)}`, + `Closed task updates stream to ${JSON.stringify(ctx.remoteAddr)}`, ) }, }) @@ -132,8 +132,14 @@ export const handler: Handlers = { }, }) } - return new Response( - JSON.stringify({ done: await db.doneTasks.findMany({}) }), - ) + const data = await req.json().catch(() => {}) + const taskData = TaskModel.pick({ id: true }).safeParse(data) + if (taskData.success) { + return new Response( + JSON.stringify(await db.tasks.findFirst({ where: taskData.data })), + ) + } else { + return new Response(JSON.stringify(await db.tasks.findMany({}))) + } }, } diff --git a/routes/routine.tsx b/routes/routine.tsx index 49ac3ef..be87cc5 100644 --- a/routes/routine.tsx +++ b/routes/routine.tsx @@ -1,72 +1,20 @@ import { Handlers, PageProps } from '$fresh/server.ts' -import { DailyPhase, DoneTask, Task } from '@homeman/models.ts' +import { Task } from '@homeman/models.ts' import { Routine } from '@homeman/islands/Routine.tsx' import { db } from '@homeman/db.ts' // import { db, kv, Todo, UserWithTodos } from '@homeman/models.ts' interface Data { tasks: Task[] - done: DoneTask[] } export const handler: Handlers = { async GET(_req, ctx) { - const tasks: Task[] = Array.from([]) - console.log(tasks) - - const hardcoded: Record = { - 'Morning': [ - ['🥣', 'Breakfast'], - ['🪥', 'Brush teeth'], - ['👕', 'Get dressed'], - ['🙏', 'Ask and thank Jesus'], - ['✝️', 'Bible story or devotional'], - ['📚', 'School: with Mrs. Emily or Mama'], - ['🎨', 'Create time: 🧶craft ✏️ draw 🧑🏼‍🎨 paint'], - ['🏗️', ' Build time: 🧱legos 🚂train tracks 🏎magna tiles'], - ['👯', 'Friend time: playdate or neighbor time'], - ['🚗', 'Outing: 📚library 🌳park 🥑groceries ☕ coffee shop'], - ], - 'Midday': [ - ['🥓', 'Lunch'], - ['🧹', 'Tidy time'], - ['🤫', 'Quiet time'], - ['🏃', 'BIG energy time: 🚲bike 🥁 drums 🤸 silly play'], - ['👯', 'Friend time: playdate or neighbor time'], - ['🚗', 'Outing: 📚library 🌳park 🥑groceries'], - ], - 'Evening': [ - ['🍽️', 'Dinner'], - ['🚗', 'Outing'], - ['👪', 'Family time: 🃏games 🕺dance party 🤸silly play 🏋️workout'], - ], - 'Bedtime': [ - ['🪥', 'Brush teeth'], - ['🛁', 'Take bath'], - ['👕', 'Put on pajamas'], - ['🙏', 'Ask and thank Jesus'], - ['✝️', 'Bible story or devotional'], - ['📕', 'Read a story'], - ['❤', 'Emotions check in: 😭 😡 😂 😟 😣 😀 ☹️ 😰 😁'], - ], - 'Night': [ - ['👨‍⚖️', 'Sleep!'], - ], - } - Object.entries(hardcoded).forEach(([tphase, phaseTasks]) => { - const phase = tphase as DailyPhase - for (const [emoji, id] of phaseTasks) { - tasks.push({ phase, emoji, id, doneAt: null }) - } - }) - - const done = await db.doneTasks.findMany({}) - console.log({ done }) - - return ctx.render({ tasks, done }) + const tasks = await db.tasks.findMany({}) + return ctx.render({ tasks }) }, } export default function Page(props: PageProps) { - return + return } From 4275d51fafe741c851e2d404ab8ae1bc261299b4 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Sun, 21 Jan 2024 15:52:46 -0600 Subject: [PATCH 2/5] WIP --- db.ts | 5 +---- islands/Routine.tsx | 9 +-------- playground.ts | 12 +++++++----- routes/api/tasks.ts | 19 ++++++++----------- 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/db.ts b/db.ts index 58b2f3b..a012630 100644 --- a/db.ts +++ b/db.ts @@ -2,7 +2,7 @@ import { createPentagon, TableDefinition, } from 'https://deno.land/x/pentagon@v0.1.5/mod.ts' -import { TaskModel, TodoModel, UserModel } from '@homeman/models.ts' +import { TodoModel, UserModel } from '@homeman/models.ts' export const kv = await Deno.openKv('homeman.db') @@ -19,9 +19,6 @@ export const schema: Record = { assignee: ['users', UserModel, 'assigneeUserId', 'id'], }, }, - tasks: { - schema: TaskModel, - }, } export const db = createPentagon(kv, schema) diff --git a/islands/Routine.tsx b/islands/Routine.tsx index 1f465f2..37821b5 100644 --- a/islands/Routine.tsx +++ b/islands/Routine.tsx @@ -1,16 +1,9 @@ -import { - DailyPhase, - DailyPhaseModel, - DoneTask, - Task, - toPhase, -} from '@homeman/models.ts' +import { DailyPhase, DailyPhaseModel, Task, toPhase } from '@homeman/models.ts' import { useSignal } from '@preact/signals' import { excitement } from '@homeman/common.ts' export interface Props { tasks: Task[] - done: DoneTask[] } interface TaskWithIndex extends Task { diff --git a/playground.ts b/playground.ts index 0d386a1..6877363 100644 --- a/playground.ts +++ b/playground.ts @@ -1,5 +1,5 @@ import { DailyPhase, TaskModel } from '@homeman/models.ts' -import { db } from '@homeman/db.ts' +import { kv } from '@homeman/db.ts' import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' const hardcoded: Record = { @@ -41,6 +41,7 @@ const hardcoded: Record = { ['👨‍⚖️', 'Sleep!'], ], } +console.log({ kv }) Object.entries(hardcoded).forEach(async ([tphase, phaseTasks]) => { const phase = tphase as DailyPhase for (const [emoji, description] of phaseTasks) { @@ -52,9 +53,10 @@ Object.entries(hardcoded).forEach(async ([tphase, phaseTasks]) => { doneAt: null, }) console.log(task) - const result = await db.tasks.create({ - data: task, - }) - console.log('after create:', result) + try { + await kv.set(['task', task.id], task) + } catch (e) { + console.error('error creating:', e) + } } }) diff --git a/routes/api/tasks.ts b/routes/api/tasks.ts index 69fa4c7..2c786a2 100644 --- a/routes/api/tasks.ts +++ b/routes/api/tasks.ts @@ -1,6 +1,6 @@ import { Handlers } from '$fresh/server.ts' import { Task, TaskModel } from '@homeman/models.ts' -import { db, kv } from '@homeman/db.ts' +import { kv } from '@homeman/db.ts' import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' import { z } from 'https://deno.land/x/zod@v3.21.4/mod.ts' @@ -9,16 +9,17 @@ type TaskPayload = z.infer async function createOrUpdate(task: TaskPayload) { if (!task.id || task.id === '') { - const newTask: Task = { + const newTask: Task = TaskModel.parse({ ...task, id: ulid(), - } - const result = await db.tasks.create({ data: newTask }) + }) + const result = await kv.set(['task', newTask.id], newTask) await kv.set(['last_task_updated'], newTask.id) return result } else { - const result = await db.tasks.update({ where: { id: task.id }, data: task }) - await kv.set(['last_task_updated'], task.id) + const newTask: Task = TaskModel.parse(task) + const result = await kv.set(['task', task.id], newTask) + await kv.set(['last_task_updated'], newTask.id) return result } } @@ -42,17 +43,13 @@ export const handler: Handlers = { emoji: form.get('emoji')?.toString() || null, doneAt: form.get('doneAt')?.toString() || null, description: form.get('description')?.toString(), - assigneeUserId: form.get('assigneeUserId')?.toString() || null, + phase: form.get('phase')?.toString() || null, }) if (!id) { delete task.id } - if (!task.assigneeUserId) { - delete task.id - } - await createOrUpdate(task) const url = new URL(req.url) From 6529cb3810b4a6b7c3f984e11534c9fd0b6deeb0 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Sun, 21 Jan 2024 18:11:25 -0600 Subject: [PATCH 3/5] Unborked? --- islands/Routine.tsx | 4 ++-- routes/api/tasks.ts | 20 ++++++++++++++------ routes/routine.tsx | 7 +++++-- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/islands/Routine.tsx b/islands/Routine.tsx index 37821b5..b831018 100644 --- a/islands/Routine.tsx +++ b/islands/Routine.tsx @@ -55,7 +55,7 @@ export function Routine(
    {taskGroups[currentPhase.value].map(( - { emoji, id, doneAt, index }: TaskWithIndex, + { emoji, id, description, doneAt, index }: TaskWithIndex, ) => (
  • {emoji ? `${emoji.trim()} ` : ''} - {id.trim()} + {description.trim()}
  • ))}
diff --git a/routes/api/tasks.ts b/routes/api/tasks.ts index 2c786a2..7f0f9e3 100644 --- a/routes/api/tasks.ts +++ b/routes/api/tasks.ts @@ -57,6 +57,14 @@ export const handler: Handlers = { return Response.redirect(url, 303) } }, + async PUT(req, _ctx) { + if (req.headers.get('content-type')?.includes('json')) { + const result = await createOrUpdate( + TaskPayload.parse(await req.json()), + ) + return new Response(JSON.stringify(result)) + } + }, async DELETE(req, _ctx) { // task: form or query params or json let data @@ -67,7 +75,7 @@ export const handler: Handlers = { } console.log('delete task data:', data) const taskData = TaskModel.pick({ id: true }).parse(data) - const result = await db.tasks.delete({ where: taskData }) + const result = await kv.delete(['task', taskData.id]) await kv.set(['last_task_updated'], taskData.id) return new Response(JSON.stringify(result)) }, @@ -95,9 +103,7 @@ export const handler: Handlers = { continue } - const task = await db.tasks.findFirst({ - where: { id: entry.value }, - }) + const task = (await kv.get(['task', entry.value])).value const chunk = `data: ${ JSON.stringify({ id: entry.value, @@ -133,10 +139,12 @@ export const handler: Handlers = { const taskData = TaskModel.pick({ id: true }).safeParse(data) if (taskData.success) { return new Response( - JSON.stringify(await db.tasks.findFirst({ where: taskData.data })), + JSON.stringify((await kv.get(['task', taskData.data.id])).value), ) } else { - return new Response(JSON.stringify(await db.tasks.findMany({}))) + return new Response( + JSON.stringify(Array.fromAsync(kv.list({ prefix: ['task'] }))), + ) } }, } diff --git a/routes/routine.tsx b/routes/routine.tsx index be87cc5..4437056 100644 --- a/routes/routine.tsx +++ b/routes/routine.tsx @@ -1,7 +1,7 @@ import { Handlers, PageProps } from '$fresh/server.ts' import { Task } from '@homeman/models.ts' import { Routine } from '@homeman/islands/Routine.tsx' -import { db } from '@homeman/db.ts' +import { kv } from '@homeman/db.ts' // import { db, kv, Todo, UserWithTodos } from '@homeman/models.ts' interface Data { @@ -10,7 +10,10 @@ interface Data { export const handler: Handlers = { async GET(_req, ctx) { - const tasks = await db.tasks.findMany({}) + const tasks = (await Array.fromAsync(kv.list({ prefix: ['task'] }))).map( + (r) => r.value + ) + console.log({ tasks }) return ctx.render({ tasks }) }, } From 2aaeb1ac7f03f76550a797a6f245e5c881d9f5f6 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Sun, 21 Jan 2024 20:10:46 -0600 Subject: [PATCH 4/5] Tasks work --- islands/Routine.tsx | 63 ++++++++++++++++++++-------------------- routes/api/tasks.ts | 71 ++++++++++++++------------------------------- 2 files changed, 52 insertions(+), 82 deletions(-) diff --git a/islands/Routine.tsx b/islands/Routine.tsx index b831018..e3985b1 100644 --- a/islands/Routine.tsx +++ b/islands/Routine.tsx @@ -55,38 +55,37 @@ export function Routine(
    {taskGroups[currentPhase.value].map(( - { emoji, id, description, doneAt, index }: TaskWithIndex, - ) => ( -
  • { - tasks.value[index].doneAt = tasks.value[index].doneAt - ? null - : new Date() - tasks.value = [...tasks.value] - if (tasks.value[index].doneAt) { - fetch('/api/tasks', { - method: 'POST', - headers: { 'content-type': 'application/json' }, - body: JSON.stringify({ id: id }), - }) - excitement() - } else { - fetch('/api/tasks', { - method: 'DELETE', - headers: { 'content-type': 'application/json' }, - body: JSON.stringify({ id: id }), - }) - } - }} - > - {emoji ? `${emoji.trim()} ` : ''} - {description.trim()} -
  • - ))} + 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()} +
  • + ) + })}
diff --git a/routes/api/tasks.ts b/routes/api/tasks.ts index 7f0f9e3..b7e73c0 100644 --- a/routes/api/tasks.ts +++ b/routes/api/tasks.ts @@ -4,66 +4,37 @@ import { kv } from '@homeman/db.ts' import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' import { z } from 'https://deno.land/x/zod@v3.21.4/mod.ts' -const TaskPayload = TaskModel.partial({ id: true }) +const TaskPayload = TaskModel.omit({ doneAt: true }).partial({ + id: true, +}).extend({ + done: z.boolean().optional(), +}) type TaskPayload = z.infer async function createOrUpdate(task: TaskPayload) { - if (!task.id || task.id === '') { - const newTask: Task = TaskModel.parse({ - ...task, - id: ulid(), - }) - const result = await kv.set(['task', newTask.id], newTask) - await kv.set(['last_task_updated'], newTask.id) - return result - } else { - const newTask: Task = TaskModel.parse(task) - const result = await kv.set(['task', task.id], newTask) - await kv.set(['last_task_updated'], newTask.id) - return result + const newTask: Task = TaskModel.parse({ + ...task, + doneAt: task.done ? new Date() : null, + }) + if (!newTask.id || newTask.id === '') { + newTask.id = ulid() } + const result = await kv.set(['task', newTask.id], newTask) + await kv.set(['last_task_updated'], newTask.id) + return result } export const handler: Handlers = { async POST(req, _ctx) { - if (req.headers.get('content-type')?.includes('json')) { - const result = await createOrUpdate( - TaskPayload.parse(await req.json()), - ) - return new Response(JSON.stringify(result)) - } else { - const form = await req.formData() - const id = form.get('id')?.toString() || undefined - - const doneAt = form.get('doneAt') - console.log('task POST doneAt:', doneAt) - - const task = TaskPayload.parse({ - id: id, - emoji: form.get('emoji')?.toString() || null, - doneAt: form.get('doneAt')?.toString() || null, - description: form.get('description')?.toString(), - phase: form.get('phase')?.toString() || null, - }) - - if (!id) { - delete task.id - } - - await createOrUpdate(task) - - const url = new URL(req.url) - url.pathname = '/' - return Response.redirect(url, 303) - } + const result = await createOrUpdate( + TaskPayload.parse(await req.json()), + ) + return new Response(JSON.stringify(result)) }, async PUT(req, _ctx) { - if (req.headers.get('content-type')?.includes('json')) { - const result = await createOrUpdate( - TaskPayload.parse(await req.json()), - ) - return new Response(JSON.stringify(result)) - } + const t = TaskPayload.parse(await req.json()) + const result = await createOrUpdate(t) + return new Response(JSON.stringify(result)) }, async DELETE(req, _ctx) { // task: form or query params or json From 53b36b1957c155dd1e3467c7d15aae7194edcbea Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Sun, 21 Jan 2024 20:15:43 -0600 Subject: [PATCH 5/5] Fixed --- main.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/main.ts b/main.ts index 11ebba6..bf7b415 100644 --- a/main.ts +++ b/main.ts @@ -10,5 +10,18 @@ import '$std/dotenv/load.ts' import { start } from '$fresh/server.ts' import manifest from './fresh.gen.ts' import config from './fresh.config.ts' +import { kv } from '@homeman/db.ts' +import { Task } from '@homeman/models.ts' + +Deno.cron('Reset daily tasks', '0 4 * * *', async () => { + console.log('4am daily tasks reset') + const tasks = await Array.fromAsync(kv.list({ prefix: ['task'] })) + tasks.forEach( + async (t) => { + const nv = { ...t.value, doneAt: null } + await kv.set(t.key, nv) + }, + ) +}) await start(manifest, config)