71 lines
2.9 KiB
Markdown
71 lines
2.9 KiB
Markdown
# F-070 — Implementer evidence
|
|
|
|
## Problem
|
|
|
|
Product attributes (bio, vegano, sin-gluten, etc.) are returned by the backend
|
|
`serializeProduct` (already includes `attributes: product.attributes`) but the
|
|
frontend `Product` type omits the field and the product detail page never
|
|
renders them. Customers see no attribute badges on `/products/[slug]`.
|
|
|
|
## Root cause
|
|
|
|
1. `project/frontend/src/types/api.ts` — `Product` interface missing `attributes` field.
|
|
2. `project/frontend/src/app/products/[slug]/page.tsx` — no attributes rendering section.
|
|
|
|
Backend already ships `PRODUCT_ATTRIBUTES` enum (16 values) in
|
|
`project/src/modules/catalog/domain/product.ts` and `serializeProduct`
|
|
returns the array. No backend changes needed.
|
|
|
|
## Changes
|
|
|
|
### Type definition
|
|
`project/frontend/src/types/api.ts`
|
|
|
|
- Added `PRODUCT_ATTRIBUTES` const array (16 values matching backend).
|
|
- Added `ProductAttribute` type = `(typeof PRODUCT_ATTRIBUTES)[number]`.
|
|
- Added `attributes?: ProductAttribute[]` to the `Product` interface.
|
|
|
|
### Attribute labels
|
|
`project/frontend/src/lib/product-attributes.ts` (new)
|
|
|
|
- `ATTRIBUTE_LABELS: Record<ProductAttribute, string>` — Spanish human-readable
|
|
labels for each attribute slug (bio → "Eco", vegano → "Vegano", etc.).
|
|
- `getAttributeLabel(attr)` helper with fallback to raw slug.
|
|
|
|
### Badge component
|
|
`project/frontend/src/components/product/ProductAttributes.tsx` (new)
|
|
|
|
- Renders attributes as `inline-flex` rounded-full badges with emerald styling.
|
|
- Returns `null` when no attributes (no DOM noise).
|
|
- Accessible: `title` attribute on each badge = full label.
|
|
|
|
### Page integration
|
|
`project/frontend/src/app/products/[slug]/page.tsx`
|
|
|
|
- Import `ProductAttributes`.
|
|
- Render `<ProductAttributes attributes={product.attributes} />` right after
|
|
the product `<h1>` title, before the price section.
|
|
|
|
## Build verification
|
|
|
|
- `npx tsc --noEmit` (frontend) — exit 0
|
|
- `npx eslint` on all 4 changed files — exit 0
|
|
- `./scripts/verify.sh` — exit 0
|
|
|
|
## Files touched
|
|
|
|
```
|
|
project/frontend/src/types/api.ts (modified — added ProductAttribute type + attributes field)
|
|
project/frontend/src/lib/product-attributes.ts (new — attribute label map + helper)
|
|
project/frontend/src/components/product/ProductAttributes.tsx (new — badge component)
|
|
project/frontend/src/app/products/[slug]/page.tsx (modified — render badges after title)
|
|
```
|
|
|
|
## Acceptance traceability
|
|
|
|
| Acceptance criterion | How it is met |
|
|
| -------------------- | ------------- |
|
|
| Product detail page renders product attributes as badges | `ProductAttributes` component renders `ATTRIBUTE_LABELS[attr]` as emerald badges on `page.tsx` |
|
|
| No regression on existing product pages | `attributes` is optional (`?`); pages without attributes render `null` — no layout change |
|
|
| `verify.sh` is green | Exit 0 |
|