all repos — kōi @ aabc809544f1c5547b497e8f0e5dda482f6b25e1

Minimalist task manager

src/lib/components/TaskItem.svelte (view raw)

 1<script lang="ts">
 2  import type { FormEventHandler } from "svelte/elements";
 3  import tasksStore from "../store/tasksStore";
 4  import { debounce } from "../utils";
 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<li class="list-row flex items-center gap-4 p-2" id={task.id}>
33  <input
34    type="checkbox"
35    class="checkbox"
36    checked={task.done}
37    onchange={onUpdateDone}
38  />
39  <div class="flex w-full justify-between">
40    <div
41      contenteditable
42      autocorrect="off"
43      oninput={debounce(onUpdateName, 750)}
44      class:line-through={task.done}
45    >
46      {@html parseContent(task.name)}
47    </div>
48    <input
49      type="date"
50      value={task.dueDate?.toISOString().split("T")[0]}
51      onchange={onUpdateDueDate}
52      class:text-red-400={task.dueDate && task.dueDate < new Date()}
53      class:text-primary={task.dueDate && task.dueDate >= new Date()}
54      class="rounded px-1"
55    />
56  </div>
57</li>