From b1c0d3f3dab3888e96eabc3a1de0a994320975c4 Mon Sep 17 00:00:00 2001 From: ponzischeme89 Date: Sat, 13 Jun 2026 10:25:52 +1200 Subject: [PATCH] v0.1.20 - Even composer fields on laptops & add-success modal - Throughput: even three-across layout for the "Add a packing run" fields on laptop widths so placeholders stay readable in the narrow content band - Throughput: centred "Added" confirmation modal with in-card confetti on save (3s), composer clears for the next entry - Fix stray character in changelog.ts type comment Co-Authored-By: Claude Opus 4.8 --- frontend/package.json | 2 +- frontend/src/lib/changelog.ts | 10 +- frontend/src/routes/throughput/+page.svelte | 157 +++++++++++++++++++- 3 files changed, 165 insertions(+), 4 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index f6e9421..d94d562 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "hunter-app", - "version": "0.1.19", + "version": "0.1.20", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/lib/changelog.ts b/frontend/src/lib/changelog.ts index 15eba86..344c0b5 100644 --- a/frontend/src/lib/changelog.ts +++ b/frontend/src/lib/changelog.ts @@ -8,7 +8,7 @@ import packageInfo from '../../package.json'; */ export type ChangelogEntry = { version: string; - /** ISO date (YYYY-MM-DD) the version shipped. */a + /** ISO date (YYYY-MM-DD) the version shipped. */ date: string; highlights: string[]; }; @@ -17,6 +17,14 @@ export type ChangelogEntry = { export const APP_VERSION: string = packageInfo.version; export const changelog: ChangelogEntry[] = [ + { + version: '0.1.20', + date: '2026-06-13', + highlights: [ + 'App - Improvements', + 'App - Bug fixes' + ] + }, { version: '0.1.18', date: '2026-06-12', diff --git a/frontend/src/routes/throughput/+page.svelte b/frontend/src/routes/throughput/+page.svelte index 505c408..84d5155 100644 --- a/frontend/src/routes/throughput/+page.svelte +++ b/frontend/src/routes/throughput/+page.svelte @@ -6,7 +6,7 @@ ThroughputProduct, ThroughputQuantityType } from '$lib/types'; - import { ArrowUpDown, CalendarDays, CalendarRange, Carrot, ChevronLeft, ChevronRight, Gauge, History, Pencil, Plus, TrendingUp, Trash2, TriangleAlert, Search, Wheat, X } from 'lucide-svelte'; + import { ArrowUpDown, CalendarDays, CalendarRange, Carrot, CheckCircle2, ChevronLeft, ChevronRight, Gauge, History, Pencil, Plus, TrendingUp, Trash2, TriangleAlert, Search, Wheat, X } from 'lucide-svelte'; import { fade } from 'svelte/transition'; import ThroughputProductPicker from '$lib/components/throughput/ThroughputProductPicker.svelte'; import { formatDate as formatDisplayDate, formatLocaleNumber, toNum } from '$lib/format'; @@ -105,6 +105,41 @@ let composer = $state(null); let deletingId = $state(null); + // A brief centred "Added" confirmation with a confetti burst after a run is + // logged, so a fast operator gets unmistakable feedback even with their eyes + // on the keyboard. Auto-dismisses; pointer-events stay off so it never blocks + // the next entry. + type ConfettiPiece = { + left: number; + delay: number; + duration: number; + color: string; + rotate: number; + drift: number; + size: number; + }; + const CONFETTI_COLORS = ['#16a34a', '#f59e0b', '#3b82f6', '#ec4899', '#8b5cf6', '#ef4444']; + let showSuccess = $state(false); + let confetti = $state([]); + let successTimer: ReturnType | null = null; + + function flashSuccess() { + confetti = Array.from({ length: 42 }, (_, i) => ({ + left: Math.random() * 100, + delay: Math.random() * 1.2, + duration: 1 + Math.random() * 0.8, + color: CONFETTI_COLORS[i % CONFETTI_COLORS.length], + rotate: 220 + Math.random() * 360, + drift: (Math.random() - 0.5) * 60, + size: 6 + Math.random() * 6 + })); + showSuccess = true; + if (successTimer) clearTimeout(successTimer); + successTimer = setTimeout(() => { + showSuccess = false; + }, 3000); + } + // When both checkpoints are ticked the run is split, so we need to know how // much goes to stock (the rest belongs to the order). const isSplit = $derived(nForOrder && nForStock); @@ -287,6 +322,7 @@ upsertStatsEntry(created); page = 1; highlightId = created.id; + flashSuccess(); } const flashed = highlightId; setTimeout(() => { @@ -982,6 +1018,24 @@ {/if} +{#if showSuccess} + +{/if} +