src/routes/(auth)/TaskItem.svelte (view raw)
1<script lang="ts">
2 import { debounce } from '$lib/utils';
3 import type { FormEventHandler } from 'svelte/elements';
4 import tasksStore from './tasksStore';
5
6 let { task }: { task: Task } = $props();
7
8 const parseContent = (content: string) =>
9 content.replace(/#((\w|-)+)/g, '<span class="hashtag">#$1</span>');
10
11 const onUpdateName: FormEventHandler<HTMLDivElement> = (event) => {
12 const element = event.target as HTMLElement;
13 const newValue = element.innerText?.trim();
14 tasksStore.updateTask(task.id, { name: newValue });
15 };
16
17 const onUpdateDone: FormEventHandler<HTMLInputElement> = (e) => {
18 const element = e.target as HTMLInputElement;
19 const done = element.checked;
20 tasksStore.updateTask(task.id, { done });
21 };
22
23 const onUpdateDueDate: FormEventHandler<HTMLInputElement> = (e) => {
24 const element = e.target as HTMLInputElement;
25 const rawDate = element.value;
26 let dueDate;
27 if (rawDate) dueDate = new Date(rawDate);
28 tasksStore.updateTask(task.id, { dueDate });
29 };
30</script>
31
32<div class="flex items-center gap-4 rounded border p-2" id={task.id}>
33 <input type="checkbox" class="checkbox mt-1" checked={task.done} onchange={onUpdateDone} />
34 <div class="flex w-full justify-between">
35 <div contenteditable oninput={debounce(onUpdateName, 750)}>
36 {@html parseContent(task.name)}
37 </div>
38 <input
39 type="date"
40 value={task.dueDate?.toISOString().split('T')[0]}
41 onchange={onUpdateDueDate}
42 class:text-red-400={task.dueDate && task.dueDate < new Date()}
43 class:text-primary={task.dueDate && task.dueDate >= new Date()}
44 />
45 </div>
46</div>