refactor: full UI/UX cleanup — expandable edit rows, better controls, cleaner UX

Admin tables (same pattern as OutputTypeTable):
- RenderTemplateTable: 11 cramped columns → expandable form row with grouped fields,
  boolean flags consolidated into compact badges, .blend upload in proper section
- PricingTierTable: inline cell editing → expandable form with labeled fields,
  shared renderEditFormGrid() for add/edit modes
- GlobalRenderPositionsPanel: tiny rotation inputs → expandable form with w-24 inputs,
  proper labels, sensor_width_mm added to edit form

Page polish:
- WorkerManagement: larger scale controls (p-2 rounded-lg), wider number displays (w-12),
  proper labels, more prominent Save button
- Billing: status select gets visible dropdown indicator (ChevronDown icon),
  hover border to signal interactivity, larger action buttons with borders
- OrderDetail: batch override in proper card with title/description,
  per-line override shows compact "+ override" link (expands on click),
  active overrides show as amber badge with X to clear

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 09:20:45 +01:00
parent 5b92375d86
commit 9a794ff2da
7 changed files with 1013 additions and 784 deletions
+98 -61
View File
@@ -1,86 +1,123 @@
# Plan: Duplicate Product Detection
# Plan: Full UI/UX Cleanup & Simplification
## Context
When importing products via Excel or STEP upload, there's no warning when a product already exists with a different STEP file. This can lead to accidental overwrites or confusion. The feature adds non-blocking warnings (yellow badges, toasts) at import time.
The OutputTypeTable was refactored from cramped 18-column inline editing to an expandable form row — a dramatic UX improvement. The same pattern should be applied to all other admin tables that suffer from the same problem. Additionally, several pages have UX inconsistencies (mixed editing patterns, tiny inputs, confusing controls) that need cleanup.
## Detection Scenarios
1. **Excel preview**: Product exists in DB with a different STEP file linked → warning icon
2. **Excel preview**: Same product in two rows with different `name_cad_modell` → conflict badge
3. **STEP upload on product**: Replacing an existing STEP file on a product that has renders → toast warning
4. **All warnings are non-blocking** — user can still proceed
**Principle**: Tables are for **viewing** data. Editing happens in **expandable rows** or **modals** — never in cramped inline cells.
## Affected Files
| File | Change |
|------|--------|
| `backend/app/services/excel_import.py` | Add STEP conflict detection in `preview_excel_rows()` |
| `backend/app/api/routers/uploads.py` | Extend preview response with conflict fields |
| `backend/app/api/routers/products.py` | Add render-count warning to CAD upload response |
| `frontend/src/api/uploads.ts` | Update TypeScript interfaces |
| `frontend/src/pages/Upload.tsx` | Display conflict warnings in preview table |
| `frontend/src/api/products.ts` | Add warning fields to CAD upload response type |
| `frontend/src/pages/ProductDetail.tsx` | Show toast warnings on STEP replacement |
| File | Change | Priority |
|------|--------|----------|
| `frontend/src/components/admin/RenderTemplateTable.tsx` | Expandable edit row (11 cramped columns) | HIGH |
| `frontend/src/components/admin/PricingTierTable.tsx` | Expandable edit row (6 columns, mixed add/edit) | HIGH |
| `frontend/src/components/admin/GlobalRenderPositionsPanel.tsx` | Expandable edit row (8 columns, tiny inputs) | MEDIUM |
| `frontend/src/pages/WorkerManagement.tsx` | Larger touch targets, better scale controls | MEDIUM |
| `frontend/src/pages/Billing.tsx` | Fix status dropdown disguised as badge | MEDIUM |
| `frontend/src/pages/OrderDetail.tsx` | Cleaner line table, material override UX | LOW |
## Tasks
## Tasks (in order)
### [ ] Task 1: Backend — STEP conflict detection in Excel preview
### [x] Task 1: RenderTemplateTable — expandable edit row
- **File**: `backend/app/services/excel_import.py`
- **What**: In `preview_excel_rows()`, after the product lookup:
1. If product exists and has `cad_file_id`, load the CadFile and compare `original_name` (stem) with the Excel row's `name_cad_modell`
2. If they differ → set `step_conflict=True` with details
3. Track `name_cad_modell` per product key in the `seen` dict
4. If same product appears again with different `name_cad_modell` → set `cad_name_conflict=True`
- **Also**: Add `selectinload(Product.cad_file)` to `lookup_product()` in `backend/app/domains/products/service.py`
- **File**: `frontend/src/components/admin/RenderTemplateTable.tsx`
- **What**: Same pattern as OutputTypeTable refactor:
1. Display row ALWAYS shows (no conditional switching)
2. Edit form opens as a new `<tr>` below with `colSpan` spanning all columns
3. Grid form inside with labeled fields, grouped logically:
- Row 1: Name, Category, Output Types (multi-select)
- Row 2: Collection name, Material Replace, Lighting Only, Shadow Catcher, Camera Orbit
- Row 3: .blend File (upload/download/re-upload with proper spacing)
- Row 4: Active toggle + Save/Cancel buttons
4. "Add new" form also uses the expandable pattern (button at top opens a full-width form row)
5. Use `React.Fragment` for dual-row rendering
- **Acceptance gate**: Edit mode shows a well-organized form below the display row; .blend file upload has proper spacing; no horizontal overflow
- **Dependencies**: None
- **Risk**: The .blend file upload flow (upload vs clone) is complex — needs careful preservation
### [ ] Task 2: Backend — Extend preview response models
### [x] Task 2: PricingTierTable — expandable edit row
- **File**: `backend/app/api/routers/uploads.py`
- **What**: Add to the preview row dict and response:
- `step_conflict: bool`, `step_conflict_existing_name: str | None`, `step_conflict_excel_name: str | None`
- `cad_name_conflict: bool`, `cad_name_conflict_other_name: str | None`, `cad_name_conflict_row: int | None`
- Response-level: `step_conflict_count: int`, `cad_name_conflict_count: int`
- **Dependencies**: Task 1
### [ ] Task 3: Backend — Render warning on product STEP replacement
- **File**: `backend/app/api/routers/products.py`
- **What**: In `upload_product_cad()`, before replacing cad_file_id:
1. Check if product already has a different `cad_file_id`
2. Count existing MediaAssets (renders) for this product
3. Add `warnings: list[str]` and `existing_render_count: int` to response
- **File**: `frontend/src/components/admin/PricingTierTable.tsx`
- **What**: Replace inline cell editing with expandable form row:
1. Display row always visible with read-only values
2. Edit form as expandable row below with grid layout:
- Row 1: Category Key (select), Quality Level (input), Price per Item (number input)
- Row 2: Description (textarea, full width)
- Row 3: Active toggle + Save/Cancel
3. "Add Tier" button opens the same expandable form at the top
4. Consistent visual: accent left border on edit row
- **Acceptance gate**: No inline cell editing; form has proper labels; description gets full width
- **Dependencies**: None
- **Risk**: Low — simple table with few fields
### [ ] Task 4: Frontend — Update API types
### [x] Task 3: GlobalRenderPositionsPanel — expandable edit row
- **File**: `frontend/src/api/uploads.ts`
- **What**: Add conflict fields to `ExcelPreviewRow` and `ExcelPreviewResult` interfaces
- **Also**: `frontend/src/api/products.ts` — add `warnings?: string[]` and `existing_render_count?: number` to `ProductCadUploadResponse`
- **Dependencies**: Tasks 2, 3
- **File**: `frontend/src/components/admin/GlobalRenderPositionsPanel.tsx`
- **What**: Replace inline cell editing with expandable form row:
1. Display row keeps compact view (Name, X°, Y°, Z°, Focal, Default, Order)
2. Edit form as expandable row:
- Row 1: Name (wide), Is Default (checkbox with label)
- Row 2: Rotation X°, Rotation Y°, Rotation Z° (number inputs with proper width)
- Row 3: Focal Length mm, Sensor Width mm, Sort Order
- Row 4: Save/Cancel buttons
3. "Add Position" opens same expandable form
4. Wider number inputs (`w-24` instead of `w-16`) for comfortable editing
- **Acceptance gate**: Rotation inputs are comfortable to edit; no cramped cells; proper labels
- **Dependencies**: None
- **Risk**: Low — straightforward table
### [ ] Task 5: FrontendShow conflict warnings in Upload preview
### [x] Task 4: WorkerManagementbetter scale controls
- **File**: `frontend/src/pages/Upload.tsx`
- **What**:
1. Add StatCards for `step_conflict_count` and `cad_name_conflict_count` (amber color, AlertTriangle icon)
2. In the preview table rows: yellow warning icon with tooltip for `step_conflict` and `cad_name_conflict`
- **Dependencies**: Task 4
- **File**: `frontend/src/pages/WorkerManagement.tsx`
- **What**: Improve the concurrency/scale controls:
1. Replace tiny `w-6` number displays with `w-12` minimum
2. Make up/down buttons larger (`p-2` instead of default, `rounded-lg`)
3. Add proper labels above each control ("Min Concurrency", "Max Concurrency")
4. Group the scale controls in a card with clear section header
5. Make the "Save" button more prominent (full-width at bottom of card)
- **Acceptance gate**: Controls are easy to click; labels are clear; no overflow on mobile
- **Dependencies**: None
- **Risk**: Low — cosmetic changes only
### [ ] Task 6: Frontend — Show warnings on STEP replacement
### [x] Task 5: Billing — fix status dropdown UX
- **File**: `frontend/src/pages/ProductDetail.tsx`
- **What**: In `cadUploadMut.onSuccess`, check response for `warnings` and show `toast.warning()` for each
- **Dependencies**: Task 4
- **File**: `frontend/src/pages/Billing.tsx`
- **What**: Fix the status dropdown that looks like a badge:
1. Replace the `<select>` styled as a badge with an explicit dropdown button that opens a small popover/menu
2. OR: keep the select but add a visible dropdown arrow indicator and border on hover to signal interactivity
3. Make action buttons (download, delete) slightly larger with visible borders
4. Add tooltips to icon-only action buttons
- **Acceptance gate**: Users can tell the status is interactive (not just a badge); action buttons are easy to click
- **Dependencies**: None
- **Risk**: Low — UI-only changes
### [x] Task 6: OrderDetail — cleaner material override UX
- **File**: `frontend/src/pages/OrderDetail.tsx`
- **What**: Polish the per-line material override dropdown:
1. Move the material override dropdown from inside the "Output Type" column to its own column or a cleaner inline position
2. Only show the dropdown on hover or when the line has an override set (reduce visual noise)
3. The batch override dropdown above the table should be more visually prominent — card-style with label, not just inline text + select
- **Acceptance gate**: Material override is discoverable but not visually noisy; batch override is clearly labeled
- **Dependencies**: None
- **Risk**: Low — visual adjustment
## Migration Check
**No** — all detection is computed from existing data.
**No** — all changes are frontend-only.
## Order
## Order Recommendation
1. Backend Tasks 1+2 (Excel preview conflicts)
2. Backend Task 3 (STEP replacement warning)
3. Frontend Tasks 4+5+6 (types + UI)
Tasks 1-3 can be done in parallel (independent admin components).
Tasks 4-6 can be done in parallel (independent pages).
Recommended execution: Tasks 1-3 first (highest impact), then 4-6.
## Risks / Open Questions
1. **RenderTemplateTable .blend upload**: The file upload flow (choose file → upload → or clone from existing) is complex. The expandable form needs to preserve this exact functionality without breaking the upload mutation.
2. **Consistency with OutputTypeTable**: The expandable form pattern should look identical across all admin tables — same grid spacing, same accent border, same Save/Cancel button placement. Consider extracting a shared `ExpandableEditRow` wrapper if patterns diverge.
3. **Add-new forms**: Some tables have "Add" as a button that opens a modal-like form at the top, others have an inline row. Standardize: "Add" button at the top → opens expandable form row at the top of the table body (same pattern as edit).