From 08ded5fa1b4cf3ac11ac630e3da26a59028ba0d4 Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Thu, 11 Jun 2026 08:45:56 -0700 Subject: [PATCH] =?UTF-8?q?spec(SD-0002=20=C2=A75):=20UX=20layout=20?= =?UTF-8?q?=E2=80=94=204=20screens;=20design-tooling=20decision:=20Code=20?= =?UTF-8?q?directly=20(rubric=20=E2=88=921);=20reconcile=20PUC-7=20badges?= =?UTF-8?q?=20+=20PUC-10=20no-op=20confirm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- ...SD-0002-products-bulk-csv-import-export.md | 120 +++++++++++++++++- 1 file changed, 117 insertions(+), 3 deletions(-) diff --git a/specs/SD-0002-products-bulk-csv-import-export.md b/specs/SD-0002-products-bulk-csv-import-export.md index 73dc51f..87a7ca5 100644 --- a/specs/SD-0002-products-bulk-csv-import-export.md +++ b/specs/SD-0002-products-bulk-csv-import-export.md @@ -425,7 +425,9 @@ Scenario: PUC-7 — The image-fetch phase reports per image And when complete, each image's outcome: fetched, rejected (below the resolution bar / not an image), or failed (unreachable) And products whose images were rejected or failed show a placeholder and - carry a visible badge on the Products page + are surfaced on the Products page — pre-#14 as an aggregate notice + ("N products have image problems") linking to the run detail; per-product + badges arrive with #14's list view And the Merchant can re-import corrected URLs to retry (upsert, BUC-3) ``` @@ -462,7 +464,9 @@ Scenario: PUC-10 — Re-importing an export is a no-op, and says so unmodified Then the preview shows every product as "unchanged" — nothing to add, nothing to update, no errors - And confirming (or canceling) leaves the catalog identical + And the import action is unavailable, with the note "Nothing to change — + your catalog already matches this file" + And canceling leaves the catalog identical ``` **PUC-11 — Learning the format** *(realizes BUC-1 for the cold-start merchant)* @@ -479,7 +483,117 @@ Scenario: PUC-11 — The sample CSV and column reference teach the shape ## 5. UX Layout -*(not yet authored)* +Text is the source of truth; wireframes are generated from these descriptions +on demand and never committed. All surfaces live inside SD-0001's admin shell +(its header: storefront name left, signed-in email + sign out right). + +### 5.1 Design tooling decision + +- **Decision:** Code directly. +- **Rationale:** rubric score **−1** (claude-design-vs-code.md): Q1 **+1** + (net-new Products section, no data-surface precedent in the codebase), + Q2 **−1** (this section describes the UI to wireframe level — named + components, enumerated states), Q3 **0** (one admin section, multi-step but + utilitarian), Q4 **+1** (no design system in the ecomm app yet), Q5 **−1** + (solo build, operator is the only reviewer), Q6 **−1** (work is dominantly + logic: parsing, diffing, upsert, image pipeline). Default at −1 is Code; no + override fires — the import preview is novel but structural, and prose + specifies it adequately. + +### 5.2 Screen: Products (serves PUC-1, PUC-7, PUC-8, PUC-9, PUC-11) + +- **Purpose:** the catalog's home in the admin; where imports start, exports + download, and past imports are reviewed. Created by this design; #14 fills + in the browsable list. +- **Layout (top → bottom):** + - **Header row:** title "Products" + product count (e.g. "Products · 412"); + actions right-aligned: secondary **"Export"** (opens a small menu: status + filter All / Active / Draft / Archived, then downloads — PUC-9; disabled + with a note when the catalog is empty), primary **"Import products"** + (→ §5.3). + - **Notices band (conditional):** image-problems aggregate notice — "N + products have image problems" linking to the most recent run's detail + (PUC-7); shown while any product's image status is rejected/failed. + - **Primary content, empty catalog:** empty state — "No products yet. Bulk + import is how product data gets in." with the **"Import products"** + action repeated, plus links **"Download sample CSV"** and **"Column + reference"** (PUC-11). + - **Primary content, populated catalog:** the honest pre-#14 state — the + product count and one line: "Your catalog is loaded. The browsable + product list arrives with an upcoming release." (replaced by #14's list). + - **Import history (section):** table of runs, newest first — date · file + name · dialect · added / updated / errors · image outcomes (e.g. + "4,938 ✓ · 12 ✗") · status (Importing… / Fetching images… / Complete / + Complete with problems). Row click → run detail (§5.5). Empty state: "No + imports yet." +- **States:** loading: skeleton for count + history · error: honest failure + banner with retry (INV-9 spirit) · empty/populated per above. +- **Notifications:** none beyond the notices band (no toasts here; outcomes + live on durable surfaces). + +### 5.3 Screen: Import — upload (serves PUC-2, PUC-5a, PUC-11) + +- **Purpose:** choose and validate a file. +- **Layout:** + - **Header:** "Import products", back to Products. + - **Primary content:** drop zone / file picker ("CSV, up to 5,000 rows"); + beneath it the format help: "Works with the canonical format or a Shopify + product export." + links to sample CSV and column reference (PUC-11). + - **Actions:** none beyond the picker — selecting a file starts upload + + validation immediately (one fewer click; canceling is free, PUC-3a). +- **States:** idle · uploading/validating: progress ("Validating… 2,140 of + 4,950 rows") with cancel · file-level rejection (PUC-5a): error banner + naming the one problem ("This file is missing the required column + 'Title'"), picker remains for retry · success: → preview (§5.4). +- **Notifications:** none (errors render in place). + +### 5.4 Screen: Import — preview (serves PUC-3, PUC-3a, PUC-5, PUC-6, PUC-10) + +- **Purpose:** the consent gate — see exactly what will happen, then decide. +- **Layout:** + - **Header:** "Import preview — ⟨file name⟩"; dialect line: "Recognized: + Shopify product CSV — mapped to canonical" or "Canonical format" (PUC-6). + - **Warnings band (conditional):** columns not imported, listed by name + (unknown-column warning); collapsible when long. + - **Summary tiles:** **N to add · M to update · U unchanged · K errors** — + each tile filters the detail list below. + - **Detail list:** one row per product (grouped from its variant rows): + handle, title, change kind (add / update / unchanged / error), variant + count. Expanding a row drills in (PUC-3): adds show the fields to be + set; updates show a field-by-field **before → after** diff (only changed + fields, per variant where applicable); errors show the error detail. + - **Error table (under the errors filter):** line number · column · plain- + language problem ("row 214: 'Variant Price' — '12,50' is not a price"). + - **Actions (sticky footer):** primary **"Import N products"** (disabled + when nothing valid to apply — all-unchanged reads "Nothing to change — + your catalog already matches this file", PUC-10); secondary **"Cancel"** + (returns to Products, no trace, PUC-3a). +- **States:** the preview *is* a state machine of its content (mixes of + add/update/unchanged/error per above); plus stale-session expiry: a preview + left open past its validity window (§6) prompts re-validation rather than + applying stale diffs. +- **Notifications:** none. + +### 5.5 Screen: Import run detail (serves PUC-4, PUC-5, PUC-7, PUC-8) + +- **Purpose:** the durable record of one confirmed import — what applied, what + errored, how the image fetch went. The post-confirm landing page and the + import-history destination. +- **Layout:** + - **Header:** file name · imported ⟨relative time⟩ by ⟨email⟩ · dialect. + - **Result summary:** added / updated / errors counts (mirrors the preview's + final numbers). + - **Images section:** while fetching — progress "Fetching images: 312 of + 4,950" (updates live); when done — outcome summary ("4,938 fetched · + 9 rejected · 3 failed") and an outcomes table listing only problems: + product handle · variant · image URL · outcome (rejected: below the + resolution bar / not an image · failed: unreachable) · what to do + ("correct the URL and re-import"). All-clean collapses to one line. + - **Error table:** the run's unapplied rows (line · column · problem), + exactly as the preview showed them (PUC-5). +- **States:** applying ("Importing…") · fetching images · complete · complete + with problems (errors and/or image problems present). +- **Notifications:** in-app only (decided: no email summaries in the MVP). ## 6. Technical Design