aboutsummaryrefslogtreecommitdiff
path: root/src/routes/+page.svelte
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-07-27 18:31:26 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-07-27 18:31:26 +0200
commite14717b2e7853705469275d64023bb902b195ebb (patch)
tree2e450f7b4e864e232d06df43ad1aba1b62be4f4c /src/routes/+page.svelte
parent8224c7d6572db6ec76c4224eec1df8a538b47ad4 (diff)
feat: separate categories table + /categories management page
- Categories table (id, name unique) with FK from groceries.category_id - /categories page for add/delete categories - Main page uses native <select> dropdown for category - Categories grouped by name in list/catalog views - Regenerated drizzle migrations from scratch
Diffstat (limited to 'src/routes/+page.svelte')
-rw-r--r--src/routes/+page.svelte136
1 files changed, 94 insertions, 42 deletions
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index a3e6d23..9490a51 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -7,18 +7,39 @@
let listItems = $derived(data?.items?.filter((i) => !i.checked) ?? []);
let catalogItems = $derived(data?.items?.filter((i) => i.checked) ?? []);
+
+ function groupByCategory(items: typeof listItems) {
+ const groups: Record<string, typeof listItems> = {};
+ for (const item of items) {
+ const key = item.categoryName ?? 'Uncategorized';
+ (groups[key] ??= []).push(item);
+ }
+ return Object.entries(groups);
+ }
</script>
<h1>Groceries</h1>
<form class="add-form" method="POST" action="?/add" use:enhance>
- <input
- type="text"
- name="name"
- bind:value={name}
- placeholder="Add an item..."
- autocomplete="off"
- />
+ <label>
+ <span class="label">Item</span>
+ <input
+ type="text"
+ name="name"
+ bind:value={name}
+ placeholder="Add an item..."
+ autocomplete="off"
+ />
+ </label>
+ <label>
+ <span class="label">Category</span>
+ <select name="category_id">
+ <option value="">—</option>
+ {#each data?.categories ?? [] as cat (cat.id)}
+ <option value={cat.id}>{cat.name}</option>
+ {/each}
+ </select>
+ </label>
<button type="submit">Add</button>
</form>
@@ -28,64 +49,86 @@
<h2>List</h2>
-<form method="POST" action="?/toggle" use:enhance>
- <ul class="item-list">
- {#each listItems as item (item.id)}
- <li>
- <button name="id" value={item.id} type="submit">
- {item.name}
- </button>
- </li>
- {/each}
- </ul>
-</form>
-
{#if listItems.length === 0}
<p class="empty">Nothing to buy</p>
+{:else}
+ <form method="POST" action="?/toggle" use:enhance>
+ {#each groupByCategory(listItems) as [cat, items] (cat)}
+ <h3 class="category-name">{cat}</h3>
+ <ul class="item-list">
+ {#each items as item (item.id)}
+ <li>
+ <button name="id" value={item.id} type="submit">
+ {item.name}
+ </button>
+ </li>
+ {/each}
+ </ul>
+ {/each}
+ </form>
{/if}
<hr />
<h2>Catalog</h2>
-<form method="POST" action="?/toggle" use:enhance>
- <ul class="item-list">
- {#each catalogItems as item (item.id)}
- <li class="catalog-item">
- <button name="id" value={item.id} type="submit">
- {item.name}
- </button>
- <button
- class="delete-btn"
- name="id"
- value={item.id}
- type="submit"
- formaction="?/delete"
- >
- &times;
- </button>
- </li>
- {/each}
- </ul>
-</form>
-
{#if catalogItems.length === 0}
<p class="empty">No items yet</p>
+{:else}
+ <form method="POST" action="?/toggle" use:enhance>
+ {#each groupByCategory(catalogItems) as [cat, items] (cat)}
+ <h3 class="category-name">{cat}</h3>
+ <ul class="item-list">
+ {#each items as item (item.id)}
+ <li class="catalog-item">
+ <button name="id" value={item.id} type="submit">
+ {item.name}
+ </button>
+ <button
+ class="delete-btn"
+ name="id"
+ value={item.id}
+ type="submit"
+ formaction="?/delete"
+ >
+ &times;
+ </button>
+ </li>
+ {/each}
+ </ul>
+ {/each}
+ </form>
{/if}
<style>
.add-form {
display: flex;
+ flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
- input {
- flex: 1;
+ .add-form label {
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+ }
+
+ .label {
+ font-size: 0.75rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ color: #999;
+ }
+
+ input,
+ select {
padding: 0.75rem;
border: 1px solid #ccc;
border-radius: 0.5rem;
font-size: 1rem;
+ font-family: inherit;
+ background: #fff;
}
.add-form button[type='submit'] {
@@ -95,6 +138,7 @@
background: #333;
color: #fff;
font-size: 1rem;
+ align-self: flex-start;
}
.error {
@@ -168,4 +212,12 @@
font-size: 0.875rem;
margin-top: 0.5rem;
}
+
+ .category-name {
+ font-size: 0.75rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ color: #999;
+ margin: 1rem 0 0.25rem;
+ }
</style>