It's a todo list.
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

show lists on homepage

zeudev b41d70a0 77732318

+65 -21
+27
src/lib/ListItem.svelte
··· 1 + <script lang="ts"> 2 + import { pinned_list, type List } from "$lib/stores.svelte"; 3 + 4 + const { list = $bindable() }: { list: List } = $props(); 5 + 6 + let completed = $derived(list.tasks.filter((t) => t.completed).length); 7 + 8 + function pinList() { 9 + pinned_list.current = list.id; 10 + } 11 + </script> 12 + 13 + <div class="border p-4 flex justify-between"> 14 + <div class="flex flex-col"> 15 + <a href={`/${list.id}`} class="text-xl hover:underline">{list.title}</a> 16 + <p class="text-base">{completed}/{list.tasks.length}</p> 17 + </div> 18 + 19 + 20 + <button onclick={pinList} class="bg-white rounded-xl"> 21 + <img 22 + src={pinned_list.current === list.id ? "/pin.svg" : "/pin-line.svg"} 23 + alt="Pin list button" 24 + class="w-12 h-12 hover:bg-slate-500/10 rounded-full" 25 + /> 26 + </button> 27 + </div>
+13
src/lib/utils.ts
··· 1 1 import { alphabet, generateRandomString } from "oslo/crypto"; 2 + import { local_lists } from "./stores.svelte"; 3 + import { goto } from "$app/navigation"; 2 4 3 5 export function generateId() { 4 6 return generateRandomString(10, alphabet("a-z", "0-9")); ··· 18 20 19 21 return hrs + ':' + mins + ':' + secs ; 20 22 } 23 + 24 + export function createList() { 25 + const new_list = { 26 + id: generateId(), 27 + title: "", 28 + tasks: [] 29 + }; 30 + 31 + local_lists.current!.push(new_list); 32 + goto(`/${new_list.id}`); 33 + }
+24 -5
src/routes/+page.svelte
··· 1 1 <script lang="ts"> 2 - import { user_preferences } from "$lib/stores.svelte"; 2 + import ListItem from "$lib/ListItem.svelte"; 3 + import { createList } from "$lib/utils"; 4 + import { user_preferences, local_lists } from "$lib/stores.svelte"; 3 5 </script> 4 6 5 - <label for="openPinOnLoad"> 6 - <input id="openPinOnLoad" type="checkbox" bind:checked={user_preferences.current.openPinOnLoad} /> 7 - Open pinned list on load 8 - </label> 7 + <main class="flex flex-col w-full px-2 pt-8 pb-28 lg:px-4 lg:pt-4 gap-8 text-xl lg:text-3xl"> 8 + <section class="flex flex-col gap-4"> 9 + <h2 class="font-bold">Your Lists</h2> 10 + <div class="grid grid-cols-1 lg:grid-cols-3 gap-4"> 11 + {#each local_lists.current as list} 12 + <ListItem {list} /> 13 + {/each} 14 + <button onclick={createList} aria-label="Create New List" class="flex justify-center items-center border bg-white"> 15 + <img src="/basil--plus-solid.svg" alt="Plus" class="size-8 text-white" /> 16 + </button> 17 + </div> 18 + </section> 19 + <hr /> 20 + <section class="flex flex-col gap-4"> 21 + <h2 class="font-bold">Settings</h2> 22 + <label for="openPinOnLoad" class="flex gap-2 text-base"> 23 + <input id="openPinOnLoad" type="checkbox" bind:checked={user_preferences.current.openPinOnLoad} /> 24 + Open pinned list on load 25 + </label> 26 + </section> 27 + </main>
+1 -16
src/routes/[id]/+page.svelte
··· 2 2 import { page } from "$app/state"; 3 3 import { goto } from "$app/navigation"; 4 4 import toast from "svelte-french-toast"; 5 - import { generateId } from "$lib/utils"; 5 + import { createList, generateId } from "$lib/utils"; 6 6 import { local_lists, pinned_list, type List } from "$lib/stores.svelte"; 7 7 import TaskItem from "$lib/TaskItem.svelte"; 8 8 ··· 10 10 let list : List | undefined = $derived(local_lists.current!.find((l) => l.id === page.params.id)); 11 11 let task_input = $state(""); 12 12 let user_lists = $derived(local_lists.current) as List[]; 13 - 14 - // since list points to something inside local_lists, 15 - // it will run when list state changes 16 13 17 14 function addTask() { 18 15 if (task_input.length === 0) { ··· 34 31 if (list) { 35 32 list.tasks = list.tasks.filter((t) => t.id !== id); 36 33 } 37 - } 38 - 39 - function createList() { 40 - const new_list = { 41 - id: generateId(), 42 - title: "", 43 - tasks: [] 44 - }; 45 - 46 - local_lists.current!.push(new_list); 47 - list = local_lists.current!.find((l) => l.id === new_list.id); 48 - goto(`/${list!.id}`); 49 34 } 50 35 51 36 function switchToList(id: string) {