all repos — kōi @ main

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<div class="flex items-center gap-4 rounded border p-2" id={task.id}>
33  <input
34    type="checkbox"
35    class="checkbox mt-1"
36    checked={task.done}
37    onchange={onUpdateDone}
38  />
39  <div class="flex w-full justify-between">
40    <div contenteditable oninput={debounce(onUpdateName, 750)}>
41      {@html parseContent(task.name)}
42    </div>
43    <input
44      type="date"
45      value={task.dueDate?.toISOString().split("T")[0]}
46      onchange={onUpdateDueDate}
47      class:text-red-400={task.dueDate && task.dueDate < new Date()}
48      class:text-primary={task.dueDate && task.dueDate >= new Date()}
49    />
50  </div>
51</div>