Superpowered to do lists. No signup required.
1import { generateId } from "./utils";
2
3// Browser + Local Storage
4const browser_exists = (typeof window !== "undefined") && (typeof (document) !== "undefined");
5const storage = browser_exists ? localStorage : null;
6
7// Generalized Local Storage
8export function persisted<T>(key: string, default_value: T) {
9 let value : T | undefined = $state();
10
11 const initial_local = storage?.getItem(key);
12 if (initial_local) {
13 value = JSON.parse(initial_local).value as T;
14 if (!value) { update(); }
15 }
16 else {
17 value = default_value;
18 update();
19 }
20
21 function update() {
22 if (browser_exists) {
23 storage?.setItem(key, JSON.stringify({ value: value }));
24 }
25 }
26
27 return {
28 get value() { return value; },
29 set value(new_value) { value = new_value; update(); },
30 update
31 }
32}
33
34export type Task = {
35 id: string;
36 description: string;
37 is_completed: boolean;
38 // optional
39 duration?: number;
40 stopwatchInterval?: number;
41}
42
43export type List = {
44 id: string;
45 title: string;
46 tasks: Task[];
47}
48
49export const local_lists = persisted<List[]>("local_lists", [
50 {
51 id: generateId(),
52 title: "Take a Break",
53 tasks: [
54 { id: generateId(), description: "Drink water", is_completed: false },
55 { id: generateId(), description: "Stand up and stretch", is_completed: false },
56 { id: generateId(), description: "Go outside for 10 seconds", is_completed: false }, ]
57 }
58]);
59
60export const pinned_list = persisted<string>("pinned_list", local_lists.value![0].id);