all repos — kōi @ 06d6c343bb7f758261d0ed471cf4711ef5310723

Minimalist task manager

src/routes/(auth)/Task.svelte (view raw)

 1<script lang="ts">
 2	import { db } from '$lib/db';
 3	import { debounce } from '$lib/utils';
 4	import type { FormEventHandler } from 'svelte/elements';
 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 onUpdateContent: FormEventHandler<HTMLDivElement> = (e) => {
12		const element = e.target as HTMLElement;
13		const content = element.innerText?.trim();
14		if (content) db.tasks.update(task.id, { content });
15		else db.tasks.delete(task.id);
16	};
17
18	const onUpdateDone: FormEventHandler<HTMLInputElement> = (e) => {
19		const element = e.target as HTMLInputElement;
20		const done = element.checked;
21		db.tasks.update(task.id, { done });
22	};
23
24	const onUpdateDueDate: FormEventHandler<HTMLInputElement> = (e) => {
25		const element = e.target as HTMLInputElement;
26		const rawDate = element.value;
27		let dueDate;
28		if (rawDate) dueDate = new Date(rawDate);
29		db.tasks.update(task.id, { dueDate });
30	};
31</script>
32
33<div class="flex items-center justify-between gap-2">
34	<div class="flex items-center gap-2">
35		<input
36			type="checkbox"
37			class="checkbox-primary checkbox checkbox-sm"
38			checked={task.done}
39			onchange={onUpdateDone}
40		/>
41		<div
42			contenteditable
43			oninput={debounce(onUpdateContent, 1000)}
44			class:opacity-50={task.done}
45			class:line-through={task.done}
46		>
47			{@html parseContent(task.content)}
48		</div>
49	</div>
50	<input
51		type="date"
52		value={task.dueDate?.toISOString().split('T')[0]}
53		onchange={onUpdateDueDate}
54		class:text-red-400={task.dueDate && task.dueDate < new Date()}
55		class:text-primary={task.dueDate && task.dueDate >= new Date()}
56	/>
57</div>