import { Todo, User, UserWithTodos } from '@homeman/models.ts' import { Signal, useSignal } from '@preact/signals' import { TodoList } from '@homeman/islands/TodoList.tsx' import { Dialog } from '@homeman/components/Dialog.tsx' import { Label } from '@homeman/components/Label.tsx' import { Input } from '@homeman/components/Input.tsx' import { Avatar } from '@homeman/components/Avatar.tsx' import { Button } from '@homeman/components/Button.tsx' import { JSX } from 'preact' import * as confetti from 'https://esm.sh/tsparticles@3.1.0' import { useEffect } from 'preact/hooks' interface Props { users: Record todos: Record unassignedTodos: Todo[] lastUserIdUpdated: { value: string; versionstamp: string } lastTodoIdUpdated: { value: string; versionstamp: string } } const unassignedUserPlaceholder: User = { id: '', createdAt: new Date(), name: 'Shared', avatarUrl: 'http://placekitten.com/512/512', color: '888888', } interface UserSelectButtonProps extends JSX.HTMLAttributes { user: User } function UserSelectButton( { user: { id, name, avatarUrl, color }, tabindex, ...props }: UserSelectButtonProps, ) { const eid = `assigneeUserId_${id}` return ( <> ) } export default function Dashboard( { todos, users, unassignedTodos, lastTodoIdUpdated, lastUserIdUpdated }: Props, ) { console.log('lasttodo:', lastTodoIdUpdated) console.log('lastuser:', lastUserIdUpdated) const todoAssignUserId: Signal = useSignal(null) const showAddTodoDialog = useSignal(false) useEffect(() => { let es = new EventSource('/api/user') es.addEventListener('message', (e) => { console.log('user event from server:', e) }) es.addEventListener('error', async () => { es.close() const backoff = 10000 + Math.random() * 5000 await new Promise((resolve) => setTimeout(resolve, backoff)) es = new EventSource('/api/user') }) }, []) useEffect(() => { const count = 200, defaults = { origin: { y: 0.7 }, } function fire(particleRatio: number, opts: { spread?: number startVelocity?: number decay?: number scalar?: number }) { confetti( Object.assign({}, defaults, opts, { particleCount: Math.floor(count * particleRatio), }), ) } fire(0.25, { spread: 26, startVelocity: 55, }) fire(0.2, { spread: 60, }) fire(0.35, { spread: 100, decay: 0.91, scalar: 0.8, }) fire(0.1, { spread: 120, startVelocity: 25, decay: 0.92, scalar: 1.2, }) fire(0.1, { spread: 120, startVelocity: 45, }) }) useEffect(() => { let es = new EventSource('/api/todo') console.log('Streaming todo events...') es.addEventListener('message', (e) => { console.log('todo event from server:', e) const payload = JSON.parse(e.data) const { id: id } = payload if ( payload.versionstamp === lastTodoIdUpdated.versionstamp && payload.id === lastTodoIdUpdated.value ) { console.log('skipping...') // skip, we hydrated with it return } if (!payload.value) { // deleted, so reload location.reload() } else { const { description, doneAt, assigneeUserId, emoji } = payload.value const t = todos[id] if ( !t || id != t.id || description != t.description || doneAt != t.doneAt || assigneeUserId != t.assigneeUserId || emoji != t.emoji ) { console.log('Should reload!') location.reload() } } }) es.addEventListener('error', async (e) => { 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/todo') }) }, []) const unassignedUser: UserWithTodos = { ...unassignedUserPlaceholder, assignedTodos: unassignedTodos, } return (
showAddTodoDialog.value = false} >
Assignee
  • {Object.values(users).map( (user) => { return (
  • ) }, )}

Todos

  • { console.log('shared new') showAddTodoDialog.value = true todoAssignUserId.value = null }} user={unassignedUser} />
  • {Object.values(users).map((u) => (
  • { showAddTodoDialog.value = true todoAssignUserId.value = u.id }} user={u} />
  • ))}
) }