diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-07 11:32:41 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-07 11:32:41 +0200 |
| commit | 18a0f9c874aaa09c0f71252dad853c23f9511ed6 (patch) | |
| tree | 93103b83f6d0057c40f0bab9c9473bf04292e9c4 /src/routes/+page.svelte | |
| parent | 113415ce357a9cea1759d0452ebae6352f8fe36b (diff) | |
Add projects with routines, urgency tracking and health scores
Projects group recurring routines (chores included) with an append-only
snapshot table (id, version) so edits never rewrite history; completions
reference the exact snapshot. Pure metrics compute due dates, urgency
buckets (ok/due/late/veryLate) and 0-100 health scores per routine,
project, and globally. Home page lists projects; project dashboard sorts
routines most-urgent first with one-tap completion and interval parser
inputs (1d/2w/3m/1y).
Diffstat (limited to 'src/routes/+page.svelte')
| -rw-r--r-- | src/routes/+page.svelte | 144 |
1 files changed, 140 insertions, 4 deletions
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 5bdee46..4d4777a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,4 +1,140 @@ -<p>Accueil — à venir : projets et routines.</p> -<ul> - <li><a href="/groceries">Courses</a></li> -</ul> +<script lang="ts"> + import { enhance } from '$app/forms'; + + let { data, form } = $props(); + + let name = $state(''); + + function scoreClass(score: number): string { + if (score >= 80) return 'score score--good'; + if (score >= 50) return 'score score--mid'; + return 'score score--bad'; + } +</script> + +<main> + <header class="page-header"> + <h1>Projets</h1> + <span class={scoreClass(data.globalScore)}>{data.globalScore}</span> + </header> + + <form class="cat-add-bar" method="POST" action="?/addProject" use:enhance> + <input + class="form-input" + type="text" + name="name" + bind:value={name} + placeholder="Nouveau projet..." + autocomplete="off" + /> + <button class="btn-accent" type="submit" aria-label="Ajouter">+</button> + </form> + + {#if form?.error} + <p class="error">{form.error}</p> + {/if} + + <ul class="item-list"> + {#each data.projects as entry (entry.project.id)} + <li class="item-row item-row--card project-row"> + <a class="project-link" href="/projects/{entry.project.id}" + >{entry.project.name}</a + > + <span class={scoreClass(entry.healthScore)}>{entry.healthScore}</span> + </li> + {/each} + </ul> + + {#if data.projects.length === 0} + <p class="empty">Aucun projet</p> + {/if} +</main> + +<style> + .page-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.25rem 0; + } + + .project-row { + padding: 0.875rem 1rem; + } + + .project-link { + flex-grow: 1; + font-weight: 500; + color: var(--text); + text-decoration: none; + } + + .project-link:hover { + color: var(--accent); + } + + .score { + flex-shrink: 0; + min-width: 2.75rem; + padding: 0.25rem 0.5rem; + border-radius: 9999px; + text-align: center; + font-size: 0.875rem; + font-weight: 700; + color: var(--white); + } + + .score--good { + background: var(--success); + } + + .score--mid { + background: var(--accent); + } + + .score--bad { + background: var(--danger); + } + + .cat-add-bar { + display: flex; + gap: 0.5rem; + padding: 0.75rem 0; + } + + .cat-add-bar input { + flex: 1; + background: var(--surface); + } + + .btn-accent { + width: 3rem; + height: 3rem; + flex-shrink: 0; + padding: 0; + border: none; + border-radius: 0.75rem; + background: var(--accent); + color: var(--white); + font-size: 1.25rem; + font-weight: 500; + font-family: inherit; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + box-shadow: 0 1px 2px var(--shadow); + } + + .btn-accent:hover { + background: var(--accent-hover); + transform: translateY(-1px); + box-shadow: 0 4px 8px var(--shadow-accent-lg); + } + + .empty { + margin-top: 1rem; + padding: 2rem; + } +</style> |
