v0.1.35 - Ingredient categories: created categories now available across all rows

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 12:28:23 +12:00
co-authored by Claude Opus 4.8
parent c9f233dc0e
commit dc50e0538e
6 changed files with 39 additions and 11 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "hunter-backend" name = "hunter-backend"
version = "0.1.34" version = "0.1.35"
description = "Costing platform MVP backend (API for Hunter)" description = "Costing platform MVP backend (API for Hunter)"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = [ dependencies = [
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "hunter-app", "name": "hunter-app",
"version": "0.1.34", "version": "0.1.35",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "hunter-app", "name": "hunter-app",
"version": "0.1.34", "version": "0.1.35",
"dependencies": { "dependencies": {
"@fontsource/inter": "^5.2.8", "@fontsource/inter": "^5.2.8",
"lucide-svelte": "^1.0.1" "lucide-svelte": "^1.0.1"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hunter-app", "name": "hunter-app",
"version": "0.1.34", "version": "0.1.35",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
+8
View File
@@ -17,6 +17,14 @@ export type ChangelogEntry = {
export const APP_VERSION: string = packageInfo.version; export const APP_VERSION: string = packageInfo.version;
export const changelog: ChangelogEntry[] = [ export const changelog: ChangelogEntry[] = [
{
version: '0.1.35',
date: '2026-06-21',
highlights: [
'App: Bug fixes & improvements.',
'App: General improvements.'
]
},
{ {
version: '0.1.34', version: '0.1.34',
date: '2026-06-21', date: '2026-06-21',
@@ -14,7 +14,8 @@
placeholder = 'Category', placeholder = 'Category',
inputId, inputId,
disabled = false, disabled = false,
ariaLabel = 'Category' ariaLabel = 'Category',
oncreate
}: { }: {
value?: string; value?: string;
options?: string[]; options?: string[];
@@ -22,6 +23,9 @@
inputId?: string; inputId?: string;
disabled?: boolean; disabled?: boolean;
ariaLabel?: string; ariaLabel?: string;
/** Fired when the user deliberately creates a brand-new category, so the
* parent can keep it available to every other row. */
oncreate?: (category: string) => void;
} = $props(); } = $props();
// `query` is the ephemeral search text; `value` is the committed category. // `query` is the ephemeral search text; `value` is the committed category.
@@ -80,7 +84,9 @@
} }
function createNew() { function createNew() {
value = trimmed; const created = trimmed;
value = created;
oncreate?.(created);
closeMenu(); closeMenu();
} }
+19 -5
View File
@@ -174,14 +174,28 @@
}) })
); );
// Categories the user has explicitly created via the combobox this session.
// Tracked separately from row values so a freshly-created category stays
// available to every row even before it's been saved to (or assigned on) any
// ingredient — otherwise it would vanish as soon as you moved off the row.
let createdCategories = $state<string[]>([]);
function registerCategory(category: string) {
const name = category.trim();
if (!name) return;
if (createdCategories.some((existing) => existing.toLowerCase() === name.toLowerCase())) return;
createdCategories = [...createdCategories, name];
}
// Existing categories, offered as autocomplete suggestions so spelling stays // Existing categories, offered as autocomplete suggestions so spelling stays
// consistent across ingredients. // consistent across ingredients.
const knownCategories = $derived( const knownCategories = $derived(
Array.from( Array.from(
new Set( new Set(
rows [
.map((row) => (row.draft_category || row.category || '').trim()) ...rows.map((row) => (row.draft_category || row.category || '').trim()),
.filter((value) => value.length > 0) ...createdCategories.map((value) => value.trim())
].filter((value) => value.length > 0)
) )
).sort((a, b) => a.localeCompare(b)) ).sort((a, b) => a.localeCompare(b))
); );
@@ -298,7 +312,7 @@
</label> </label>
<label> <label>
<span>Category</span> <span>Category</span>
<CategoryCombobox bind:value={newIngredient.category} options={knownCategories} placeholder="e.g. Grains" inputId="new-ingredient-category" /> <CategoryCombobox bind:value={newIngredient.category} options={knownCategories} placeholder="e.g. Grains" inputId="new-ingredient-category" oncreate={registerCategory} />
</label> </label>
<label> <label>
<span>Rounding</span> <span>Rounding</span>
@@ -368,7 +382,7 @@
<div class="cell"> <div class="cell">
<span class="cell-label">Category</span> <span class="cell-label">Category</span>
<CategoryCombobox bind:value={row.draft_category} options={knownCategories} placeholder="—" ariaLabel={`Category for ${row.name}`} /> <CategoryCombobox bind:value={row.draft_category} options={knownCategories} placeholder="—" ariaLabel={`Category for ${row.name}`} oncreate={registerCategory} />
</div> </div>
<div class="cell"> <div class="cell">