# TechTitans — Product UX Corrections & Product Details Redesign

**Scope:** fix three product-editor issues reported in user testing (brand add, AI image, AI content
accuracy) and redesign the product details page as an electronics-retail product-management page.
**Branch:** `techtitans/product-editor-redesign`
**Commits:** frontend `b92bbb1`, backend `17546d2` (code). Not pushed or deployed.

---

## 1. Root causes

| Issue | Root cause |
|---|---|
| **Add New Brand missing/not discoverable** | `BrandField` only rendered the add row when the user had typed a non-empty, non-matching value **and** `showList` required `rowCount > 0`. With an empty field or no matches the dropdown (and the add action) never appeared. There was also no loading/error state for the create call, and the create handler swallowed failures silently. |
| **AI image "not working as expected"** | The feature was an inline panel with no prompt control, no "lifestyle" style, and no modal workflow; "Use this image" in create mode set the deferred blob but gave no clear review step. The backend `ProductImageGenerator` had no prompt parameter and only a mock driver (no real provider path). |
| **AI description used the wrong brand** (e.g. "Apple logitech key board…") | The backend mock faithfully composes `brand + name`; the fault was on the **frontend** — it sent whatever `brand` was in form state (a stale/incorrect selection) and **auto-applied** the result to the field with no mismatch check and no approval step. |
| **Product details looked like restaurant POS** | The page was the NH menu-item detail page: tabs for Modifiers / Sales Channels / Kitchen Routing / Availability windows, "Menu Management" breadcrumb, "Online menu details" copy, recipe/bottled-drinks inventory language. No retail header (brand/model/type), no KPI cards. |

## 2. Files changed

**Frontend (`b92bbb1`)**
- `components/menu/BrandField.tsx` — rewritten: always-visible add action, create loading/error, a11y.
- `components/menu/AiImageModal.tsx` *(new)* — prompt-editable image modal.
- `components/menu/ProductFormDrawer.tsx` — AI draft review + mismatch warning; modal wiring; async brand create.
- `lib/api/menu/productAi.ts` — `lifestyle` style, editable `prompt`, `prompt` in the result.
- `lib/api/menu/products.ts` — `productsApi.activity` + `ProductActivityEntry`.
- `lib/menu/productCapabilities.ts` *(new)* — retail/restaurant capability flags.
- `pages/menu/ProductDetailPage.tsx` + `product-detail.css` — retail header, KPI cards, six capability-gated tabs.
- `components/menu/product/ProductWebsiteSection.tsx`, `ProductHistorySection.tsx` *(new)*; `ProductOverviewSection.tsx`, `ProductInventorySection.tsx` — retail rewording.
- Tests: `ProductFormDrawer.aibrand.test.tsx`, `ProductDetailPage.test.tsx` updated/added; `product-form.css`.

**Backend (`17546d2`)**
- `AI/Product/Contracts/ProductImageGenerator.php` — `generateImage(context, style, ?prompt)`, returns `prompt`.
- `AI/Product/Mock/MockProductImageGenerator.php` — prompt echo + `lifestyle` style.
- `AI/Product/Openai/OpenAiProductImageGenerator.php` *(new)* — real OpenAI-compatible adapter.
- `AI/Product/Support/ProductImagePrompt.php` *(new)*; `AI/Product/Exceptions/AiProductGenerationFailedException.php` *(new)*; `AI/Product/Null/NullProductImageGenerator.php`.
- `Http/Requests/Api/V1/Menu/StoreAiImageRequest.php`, `Http/Controllers/Api/V1/Menu/AiProductController.php`, `Providers/ProductAiServiceProvider.php`, `config/ai_product.php`.
- `Menu/ProductService.php` + `Http/Controllers/Api/V1/Menu/ProductController.php` + `routes/api.php` — `GET menu/products/{product}/activity`.
- Tests: `AiProductContentTest.php`, `ProductActivityTest.php`.

## 3. Functional improvements

- **Brand:** searchable dropdown with a persistent inline add (`+ Add new brand` / `+ Create "X"`), create loading + inline error, keyboard navigation; free-typed brands still submit (backend-compatible); brand persists on reopen. Dedup is server-side on a normalized slug.
- **AI description:** Generate / Rewrite / Regenerate stage a **review draft** — nothing is written to the field until the manager clicks **Apply** (Discard leaves existing text untouched). A **brand/name mismatch** warning appears when the name mentions a different known brand than the one selected.
- **AI image:** modal showing the product subject + specs used, an **editable prompt**, five styles (ecommerce, white background, transparent, studio, **lifestyle**), **Generate / Regenerate / Cancel / Use this image**; the chosen image flows through the existing pending-media (create) / upload (edit) pipeline.
- **Product details:** retail header (thumbnail, name, status, product-type badge, brand·model, category, SKU, Edit Product), **KPI cards** (selling price, purchase cost, available stock, variants, online status), and six tabs — **Overview, Variants & Pricing, Inventory, Images & Media, Website, History**. Restaurant-only surfaces (Modifiers, Kitchen Routing, Availability windows, Sales-channel jargon) are hidden via `productCapabilities`; the section components and their backend remain intact for re-enabling.

## 4. Real AI vs mock

- **Content (description):** deterministic **mock** driver (`AI_PRODUCT_DRIVER`, default `mock`). It composes copy from the real product context and is honest about being AI — it is the integration point for a real text provider later.
- **Image:** a **real OpenAI-compatible adapter** now exists and is selected by `AI_PRODUCT_IMAGE_DRIVER=openai` with `AI_PRODUCT_IMAGE_API_KEY` (plus optional `_MODEL`, `_BASE_URL`, `_SIZE`, `_TIMEOUT`). **Default stays the deterministic mock**; an `openai` driver with no key **fails closed at 503**, and provider/HTTP/timeout errors surface as **502** — no mock image is ever presented as a real AI/provider result. Credentials are backend-only; none are embedded.
- **No fabrication:** the details page shows purchase cost and store-sync as "Not tracked yet" / "Not connected" because the backend has no such data — these are never invented.

## 5. Screenshots

Captured from the running app (techtitans workspace, seeded `iPhone 15`).

- **Redesigned product editor** (six sections, brand field, AI image + description actions, completion sidebar): `images/product-editor.png`
- **Redesigned product details** (retail header, KPI cards, six tabs, Overview): `images/product-detail.png`

## 6. Tests & results

- **Frontend** — `npx tsc -p tsconfig.app.json --noEmit` ✓, `npx eslint <changed>` ✓.
  `vitest run` over product-editor + product-detail suites: **149 passed** (incl. 9 brand/AI tests and the updated 59 product-detail tests).
- **Backend** — `php artisan test` for `BrandEndpointTest`, `AiProductContentTest`, `ProductActivityTest`, `ProductRetailTemplateTest`, `MenuAuthorization`: **40 passed (162 assertions)**.
- **Live smoke** — brand create/list, AI description, AI image (prompt + lifestyle, 200/mock), product detail render (screenshots above) verified against the `techpos` database.

## 7. Known limitations

- **Real image generation is unverified** — it requires `AI_PRODUCT_IMAGE_DRIVER=openai` + a valid `AI_PRODUCT_IMAGE_API_KEY`. The adapter, config, and error handling are in place and unit-covered with the mock; the real call path has not been exercised (no credentials). Set the env vars to enable it.
- **Real text (description) provider** is not yet implemented — only the mock. The abstraction is ready for one.
- **Purchase cost / margin** has no backend field, so the KPI is intentionally blank ("Not tracked yet").
- **Store sync status** shows "Not connected" until a website connection confirms sync — never a false success.
- The global **app shell** left-nav still uses the shared Cacart navigation (POS/Tables/Kitchen) — out of scope for the product-details redesign; the product pages themselves are fully retail.

## 8. Commit hashes

- Frontend: **`b92bbb1`** (branch `techtitans/product-editor-redesign`)
- Backend: **`17546d2`** (branch `techtitans/product-editor-redesign`)

Committed locally only — not pushed or deployed.
