diff --git a/components/Button.tsx b/components/Button.tsx index a07f8a8..9ee4a48 100644 --- a/components/Button.tsx +++ b/components/Button.tsx @@ -6,7 +6,7 @@ export function Button(props: JSX.HTMLAttributes) { + + Flanagan Family + + + + ) +} diff --git a/components/TodoList.tsx b/components/TodoList.tsx index 37d548b..b41f83d 100644 --- a/components/TodoList.tsx +++ b/components/TodoList.tsx @@ -1,13 +1,39 @@ -import { Todo, User } from '$models' +import { Todo, UserWithTodos } from '@homeman/models.ts' export interface Props { - user: User + user: UserWithTodos } -export function TodoList({ user }: Props) { +export function TodoList({ user: { avatarUrl, assignedTodos, name } }: Props) { + const todoItem = ({ description }: Todo) => ( +
  • {description}
  • + ) return ( -
    -

    Todo List for {user}

    +
    + {avatarUrl != null + ? ( + + ) + : null} + + {name} + + +
      + {assignedTodos.length < 1 + ? ( +
    • + All clear! 🎉 +
    • + ) + : assignedTodos.map(todoItem)} +
    ) } diff --git a/deno.json b/deno.json index acc90d9..86cfead 100644 --- a/deno.json +++ b/deno.json @@ -29,8 +29,8 @@ "tailwindcss": "npm:tailwindcss@3.3.5", "tailwindcss/": "npm:/tailwindcss@3.3.5/", "tailwindcss/plugin": "npm:/tailwindcss@3.3.5/plugin.js", - "$models": "./models.ts", - "$std/": "https://deno.land/std@0.208.0/" + "$std/": "https://deno.land/std@0.208.0/", + "@homeman/": "./" }, "compilerOptions": { "jsx": "react-jsx", diff --git a/fresh.gen.ts b/fresh.gen.ts index 0a3a05f..d2b991f 100644 --- a/fresh.gen.ts +++ b/fresh.gen.ts @@ -4,9 +4,12 @@ import * as $_404 from './routes/_404.tsx' import * as $_app from './routes/_app.tsx' +import * as $admin from './routes/admin.tsx' import * as $api_joke from './routes/api/joke.ts' import * as $greet_name_ from './routes/greet/[name].tsx' import * as $index from './routes/index.tsx' +import * as $Admin from './islands/Admin.tsx' +import * as $Clock from './islands/Clock.tsx' import * as $Counter from './islands/Counter.tsx' import { type Manifest } from '$fresh/server.ts' @@ -14,11 +17,14 @@ const manifest = { routes: { './routes/_404.tsx': $_404, './routes/_app.tsx': $_app, + './routes/admin.tsx': $admin, './routes/api/joke.ts': $api_joke, './routes/greet/[name].tsx': $greet_name_, './routes/index.tsx': $index, }, islands: { + './islands/Admin.tsx': $Admin, + './islands/Clock.tsx': $Clock, './islands/Counter.tsx': $Counter, }, baseUrl: import.meta.url, diff --git a/islands/Admin.tsx b/islands/Admin.tsx new file mode 100644 index 0000000..436a34e --- /dev/null +++ b/islands/Admin.tsx @@ -0,0 +1,77 @@ +import { createRef } from 'preact' +import { Todo, User } from '@homeman/models.ts' +import { Button } from '@homeman/components/Button.tsx' + +export interface Props { + users: User[] + todos: Todo[] +} + +export function Admin({ users, todos }: Props) { + const addUserDialog = createRef() + const usersById: Record = {} + for (const u of users) { + usersById[u.id] = u + } + return ( +
    + sup +
    +

    + Users ({users.length}) +

    + +
    + + + + + + + + + + {users.map(({ name, avatarUrl, color }) => ( + + + + + + ))} + +
    NameAvatarColor
    {name} + {avatarUrl == null ? 'None' : } + + #{color} +
    +
    +

    + Todos ({users.length}) +

    + +
    + + + + + + + + + {todos.map(({ description, assigneeUserId }) => ( + + + + + ))} + +
    DescriptionAssignee
    {description} + {assigneeUserId == null + ? 'Unassigned' + : usersById[assigneeUserId]?.name} +
    +
    + ) +} diff --git a/islands/Clock.tsx b/islands/Clock.tsx new file mode 100644 index 0000000..447a165 --- /dev/null +++ b/islands/Clock.tsx @@ -0,0 +1,24 @@ +import { JSX } from 'preact' +import { signal } from '@preact/signals' +import { IS_BROWSER } from '$fresh/runtime.ts' + +const count = signal(new Date()) + +if (IS_BROWSER) { + setInterval(() => count.value = new Date(), 1000) +} + +export function Clock(props: JSX.HTMLAttributes) { + const dt = count.value + + return ( + + {dt.toLocaleTimeString([], { + hour: 'numeric', + minute: '2-digit', + // second: '2-digit', + }) + .toLowerCase().replaceAll(' ', '')} + + ) +} diff --git a/models.ts b/models.ts index 57e3839..07e3c70 100644 --- a/models.ts +++ b/models.ts @@ -1,17 +1,31 @@ import { z } from 'https://deno.land/x/zod@v3.21.4/mod.ts' import { createPentagon } from 'https://deno.land/x/pentagon@v0.1.5/mod.ts' -import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' +// import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' const kv = await Deno.openKv() +// const todos = kv.list({ prefix: ['todos'] }) +// const deleteme = [] +// for await (const u of todos) { +// deleteme.push(u.key) +// console.log(u) +// } +// for (const d of deleteme) { +// await kv.delete(d) +// } + const User = z.object({ id: z.string().ulid().describe('primary'), createdAt: z.date(), name: z.string(), avatarUrl: z.string().nullable(), + color: z.string().nullable(), }) export type User = z.infer +export type UserWithTodos = User & { + assignedTodos: Todo[] +} const Todo = z.object({ id: z.string().ulid().describe('primary'), @@ -40,20 +54,20 @@ export const db = createPentagon(kv, { }, }) -const daddy: User = { - id: ulid(), - createdAt: new Date(), - name: 'Daddy', - avatarUrl: null, -} -const todo: Todo = { - emoji: null, - id: ulid(), - createdAt: new Date(), - description: 'Test Todo', - doneAt: null, - assigneeUserId: daddy.id, -} +// const daddy: User = { +// id: ulid(), +// createdAt: new Date(), +// name: 'Daddy', +// avatarUrl: null, +// } +// const todo: Todo = { +// emoji: null, +// id: ulid(), +// createdAt: new Date(), +// description: 'Test Todo', +// doneAt: null, +// assigneeUserId: daddy.id, +// } -db.todos.create({ data: todo }) -db.users.create({ data: daddy }) +// db.todos.create({ data: todo }) +// db.users.create({ data: daddy }) diff --git a/routes/_app.tsx b/routes/_app.tsx index 9f87bdf..b41a3ec 100644 --- a/routes/_app.tsx +++ b/routes/_app.tsx @@ -1,4 +1,6 @@ import { type PageProps } from '$fresh/server.ts' +import { Nav } from '@homeman/components/Nav.tsx' + export default function App({ Component }: PageProps) { return ( @@ -8,8 +10,8 @@ export default function App({ Component }: PageProps) { homeman-deno - - meow + +