fix(review): thickness band derived from thickness_in (#88); MultiSelect shows selected names + commits on toggle settle (#90)

#88 — thickness band is now display-only, derived deterministically from
thickness_in against the synced Woo thickness terms (TV-9 / QUALITY-95).
Replaces the <select> with a read-only div. New pure function
deriveThicknessTermId + 6 unit tests. Docs (UAT-PRACTICE, contracts/UX)
updated to reflect the band is not an owner control.

#90 — MultiSelect closed state now shows the selected option names
(truncated to 2 + +N) instead of just a count. onCommit prop wired so
multi-select changes persist + re-review immediately (250ms debounce,
flush on Done, cleanup on destroy). Single-select binds use string vars
(speciesSel/edgeSel/gradeSel) to fix the number/string mismatch with
<option value={id}>; a tick()-deferred syncSelects() keeps the DOM
option in sync after programmatic writes (AI prefill, reload hydrate)
that Svelte's own select_option would otherwise reset.
This commit is contained in:
Ty
2026-09-21 09:56:44 -07:00
parent 502314b338
commit bdd03afce4
6 changed files with 244 additions and 32 deletions
+5 -2
View File
@@ -55,8 +55,11 @@ Cites REVIEW-5, REVIEW-15, REVIEW-20, METADATA-45.
with an "AI" badge; below it the field starts empty. The badge is presentation only and clears
on edit.
- **Required set.** Exactly one species and at least one wood-category leaf; one Edge Type, at
least one Figure, exactly one Grade, one Thickness band, one Moisture; fig-* and feat-* tags
optional; price; title, short_description, and description.
least one Figure, exactly one Grade, one Moisture; fig-* and feat-* tags optional; price;
title, short_description, and description. The **Thickness band is not an owner control** — it
is derived deterministically from `thickness_in` (the value rounds up into the synced Woo band,
`TV-9` / `QUALITY-95`), displayed read-only, and satisfies the readiness requirement
(`REVIEW-5`) via that derived value.
- **Primary category.** The owner declares one primary wood category and any secondary ones; the
default is the first selected.
- **Inline nudges.** Every empty required field shows an inline nudge as the owner works; there is