It's a todo list.
1import { alphabet, generateRandomString } from "oslo/crypto";
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}
39
40export type List = {
41 id: string;
42 title: string;
43 tasks: Task[];
44}
45
46export const local_lists = persisted<List[]>("local_lists", [
47 {
48 id: generateId(),
49 title: "Take a Break",
50 tasks: [
51 { id: generateId(), description: "Drink water", is_completed: false },
52 { id: generateId(), description: "Stand up and stretch", is_completed: false },
53 { id: generateId(), description: "Go outside for 10 seconds", is_completed: false }, ]
54 }
55]);
56
57export const pinned_list = persisted<string>("pinned_list", local_lists.value![0].id);
58
59export function generateId() {
60 return generateRandomString(10, alphabet("a-z", "0-9"));
61}