homeman-deno/islands/Dashboard.tsx

156 lines
3.6 KiB
TypeScript
Raw Normal View History

2024-01-11 16:23:09 -06:00
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'
interface Props {
users: Record<string, UserWithTodos>
unassignedTodos: Todo[]
}
const unassignedUserPlaceholder: User = {
id: '',
createdAt: new Date(),
name: 'Shared',
avatarUrl: 'http://placekitten.com/512/512',
color: '888888',
}
2024-01-11 18:57:29 -06:00
interface UserSelectButtonProps extends JSX.HTMLAttributes<HTMLInputElement> {
2024-01-11 16:23:09 -06:00
user: User
}
function UserSelectButton(
2024-01-11 18:57:29 -06:00
{ user: { id, name, avatarUrl, color }, tabindex, ...props }:
UserSelectButtonProps,
2024-01-11 16:23:09 -06:00
) {
const eid = `assigneeUserId_${id}`
return (
<>
<input
aria-hidden='true'
type='radio'
2024-01-11 18:57:29 -06:00
class='peer sr-only'
2024-01-11 16:23:09 -06:00
id={eid}
name='assigneeUserId'
value={id}
2024-01-11 18:57:29 -06:00
{...props}
2024-01-11 16:23:09 -06:00
/>
<Label
for={eid}
2024-01-11 18:57:29 -06:00
style={`border-color: #${color};`}
tabindex={tabindex}
className='cursor-pointer peer-checked:border-t-2 peer-checked:bg-gray-500/20 hover:bg-gray-500/25 rounded p-2'
2024-01-11 16:23:09 -06:00
role='button'
>
<Avatar
className='mb-2'
src={avatarUrl}
/>
<span
style={`color: #${color};`}
class='font-semibold text-center'
>
2024-01-11 18:57:29 -06:00
{name}
2024-01-11 16:23:09 -06:00
</span>
</Label>
</>
)
}
export default function Dashboard({ users, unassignedTodos }: Props) {
const todoAssignUserId: Signal<string | null> = useSignal(null)
const showAddTodoDialog = useSignal(false)
const unassignedUser: UserWithTodos = {
...unassignedUserPlaceholder,
assignedTodos: unassignedTodos,
}
return (
<main class='flex flex-col'>
<Dialog
headerTitle='Add todo'
show={showAddTodoDialog.value}
onClose={() => showAddTodoDialog.value = false}
>
<form
class='p-4 gap-4 flex flex-col'
action='/api/todo'
method='post'
encType='multipart/form-data'
>
<Label for='description'>
Description
<Input autofocus name='description' />
</Label>
<span>
Assignee
<ul class='flex gap-2'>
<li>
2024-01-11 18:57:29 -06:00
<UserSelectButton
checked={todoAssignUserId.value == null}
tabindex={0}
user={unassignedUser}
/>
2024-01-11 16:23:09 -06:00
</li>
{Object.values(users).map(
2024-01-11 18:57:29 -06:00
(user) => {
2024-01-11 16:23:09 -06:00
return (
<li>
2024-01-11 18:57:29 -06:00
<UserSelectButton
checked={todoAssignUserId.value == user.id}
user={user}
/>
2024-01-11 16:23:09 -06:00
</li>
)
},
)}
</ul>
</span>
<footer class='flex justify-end gap-2'>
<Button
type='button'
onClick={() => showAddTodoDialog.value = false}
>
Cancel
</Button>
<Input type='submit' value='Save' />
</footer>
</form>
</Dialog>
<h1 class='p-5 border-b-2 border-stone-500/20 text-2xl'>
Todos
</h1>
<ul class='p-4 relative flex overflow-x-scroll max-w-screen'>
<li>
<TodoList
onNewButtonClicked={() => {
console.log('shared new')
showAddTodoDialog.value = true
todoAssignUserId.value = null
}}
user={unassignedUser}
/>
</li>
{Object.values(users).map((u) => (
<li>
<TodoList
onNewButtonClicked={() => {
showAddTodoDialog.value = true
todoAssignUserId.value = u.id
}}
user={u}
/>
</li>
))}
</ul>
</main>
)
}