feat: per-group sort order (defined/alpha) in group form and converter

This commit is contained in:
Falkan
2026-03-17 19:59:02 -04:00
parent 6d72242aaa
commit 1317f5e8fb
3 changed files with 18 additions and 2 deletions

View File

@@ -37,6 +37,8 @@ export interface Group {
baseUnitId: string; baseUnitId: string;
/** Relative scale for cross-group YOLO conversions. */ /** Relative scale for cross-group YOLO conversions. */
toUniversal: number; toUniversal: number;
/** Display order for units in the converter. Defaults to 'defined'. */
sortOrder?: 'defined' | 'alpha';
} }
/** Full data payload for units and groups. */ /** Full data payload for units and groups. */

View File

@@ -133,7 +133,7 @@
fromUnitId = id; fromUnitId = id;
} }
// ── Group units for display — single O(n) pass ────────────────────────────── // ── Derived: results per group for display — single O(n) pass ──────────────
let orderedResults: { groupLabel: string | null; items: ResultItem[] }[] = $derived.by(() => { let orderedResults: { groupLabel: string | null; items: ResultItem[] }[] = $derived.by(() => {
// Build a Map of groupId → items in a single pass over results // Build a Map of groupId → items in a single pass over results
const byGroup = new Map<string | null, ResultItem[]>(); const byGroup = new Map<string | null, ResultItem[]>();
@@ -147,7 +147,12 @@
const sections: { groupLabel: string | null; items: ResultItem[] }[] = []; const sections: { groupLabel: string | null; items: ResultItem[] }[] = [];
for (const group of groups) { for (const group of groups) {
const items = byGroup.get(group.id); const items = byGroup.get(group.id);
if (items?.length) sections.push({ groupLabel: group.label, items }); if (items?.length) {
const sorted = group.sortOrder === 'alpha'
? [...items].sort((a, b) => a.unit.label.localeCompare(b.unit.label))
: items;
sections.push({ groupLabel: group.label, items: sorted });
}
} }
const orphaned = byGroup.get(null); const orphaned = byGroup.get(null);
if (orphaned?.length) sections.push({ groupLabel: 'Ungrouped', items: orphaned }); if (orphaned?.length) sections.push({ groupLabel: 'Ungrouped', items: orphaned });

View File

@@ -803,6 +803,15 @@
<small class="muted">Relative scale for cross-group (YOLO) conversions. Arbitrary.</small> <small class="muted">Relative scale for cross-group (YOLO) conversions. Arbitrary.</small>
<input type="number" bind:value={groupForm.toUniversal} min="0.000001" step="any" /> <input type="number" bind:value={groupForm.toUniversal} min="0.000001" step="any" />
</label> </label>
<label>
Display order
<small class="muted">How units in this group are sorted in the converter.</small>
<select bind:value={groupForm.sortOrder}>
<option value={undefined}>Defined order (default)</option>
<option value="defined">Defined order</option>
<option value="alpha">Alphabetical</option>
</select>
</label>
<div class="form-actions"> <div class="form-actions">
<button onclick={saveGroup}>{groupFormNew ? 'Create' : 'Save'}</button> <button onclick={saveGroup}>{groupFormNew ? 'Create' : 'Save'}</button>
{#if !groupFormNew} {#if !groupFormNew}