- Add 12-05-SUMMARY.md documenting OfferEditorClient + edit route
7.1 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12-offer-composition-drag-drop-csv-import | 05 | ui |
|
|
|
|
|
|
|
|
18min | 2026-06-15 |
Phase 12 Plan 05: Offer Editor Detail Page Summary
Full-page Offer Editor at /admin/offers/[id]/edit: 4-dimension tags, category-filtered A/B/C services checkbox matrix with live "Totale Servizi", independent "Prezzo Pubblico" per tier, 5-field transformation promise, and Salva/Annulla/Archivia actions.
Performance
- Duration: 18 min
- Started: 2026-06-15T08:07:00Z (approx)
- Completed: 2026-06-15T08:25:22Z
- Tasks: 2 completed
- Files modified: 2 (both new)
Accomplishments
- Created
src/app/admin/offers/[id]/edit/page.tsx: async server component using Next.js 16'sPromise<{ id: string }>params pattern, fetchesgetOfferEditorData(id)+getOfferFieldOptions()viaPromise.all, callsnotFound()for unknown ids, delegates toOfferEditorClient - Created
src/components/admin/offers/OfferEditorClient.tsx: client component covering the full UI-SPEC section 2 contract:- Header with "← Indietro" link, "Modifica Offerta" heading, editable offer name via
EditableCell - "Tag" section: Categoria/Ticket via
OptionSelect(single-select, with rename), Tipo/Obiettivo viaOptionMultiSelect(multi-select, creatable on the fly via "+ Crea Tipo"/"+ Crea Obiettivo") - "Servizi Inclusi" matrix: services filtered by
macro.category(live-recomputed viauseMemowhen Categoria changes), one checkbox column per tier (A/B/C), "Totale Servizi" row recalculated instantly client-side on every toggle (OFFER-11), independent "Prezzo Pubblico" numeric input per tier (OFFER-16, D-5) - "Promessa di Trasformazione" block: 5
EditableCellfields (Aiuto/A ottenere/In/Senza/Grazie a) mapped tocliente_ideale/risultato/tempo/pain/metodo(OFFER-17) - "Salva Offerta" (disabled with tooltip unless at least one tier has an assigned service) →
saveOfferEditor→ redirect to/admin/offers; "Annulla" → plain link back; "Archivia" (visible only when not already archived) → confirm dialog →toggleOfferArchived(id, true)→ redirect
- Header with "← Indietro" link, "Modifica Offerta" heading, editable offer name via
- All literal Italian copy strings from the UI-SPEC copywriting contract table implemented verbatim
Task Commits
Each task was committed atomically:
- Task 1: Create editor route + page.tsx server component -
8e0e4b9(feat) - Task 2: Build OfferEditorClient — tags, services matrix with live totals, promise block, actions -
8c5c918(feat)
Plan metadata: (this commit, follows)
Files Created/Modified
src/app/admin/offers/[id]/edit/page.tsx- New server component: fetches editor data + field options, 404s on missing offer, rendersOfferEditorClientsrc/components/admin/offers/OfferEditorClient.tsx- New client component: the entire offer editor UI and its Salva/Annulla/Archivia/rename interactions
Decisions Made
EditableCell.onSavein this codebase is(value: string) => void(synchronous), not(value: string) => void | Promise<void>as the plan's interface sketch suggested — implemented all macro-field handlers as synchronoussetMacroupdates, matching the real signature (verified vianpx tsc --noEmit)- Tier padding:
padTiers()always produces exactly 3 entries (A, B, C), filling missing tiers with empty placeholders (id: "",assignedServiceIds: [],servicesTotal: "0") so the matrix always renders 3 columns regardless of how many tiers exist in the DB - Tag rename (Categoria/Ticket/Tipo/Obiettivo) follows the existing
ServiceTable/renameServiceOptionoptimistic-update pattern: local state updates immediately,renameOfferOptionserver action fires viastartTransition
Deviations from Plan
None - plan executed exactly as written. The only adjustment was using the actual (synchronous) EditableCell.onSave signature instead of the plan's sketch signature, which is a same-behavior implementation detail (Rule 1 — code correctness), not a scope change.
Issues Encountered
None.
User Setup Required
None - no external service configuration required. This plan is pure UI (server + client components) consuming the already-deployed Plan 03 query layer and server actions against the live production schema (migration 0008).
Next Phase Readiness
/admin/offers/[id]/editis fully functional and type-checks/lints clean across the whole project (npx tsc --noEmitandnpx eslintboth pass with zero errors)- Plan 04's list page (
/admin/offers+OfferListClient.tsx, built in parallel in a separate worktree) can link directly to/admin/offers/[id]/edit— no shared files were touched, no merge conflicts expected - All four target requirements (OFFER-11, OFFER-15, OFFER-16, OFFER-17) are implemented end-to-end: UI ->
saveOfferEditor/toggleOfferArchived/renameOfferOption(Plan 03) ->offer_macros/offer_micros/offer_tier_services/tags(Plan 01/02, live on prod)
Phase: 12-offer-composition-drag-drop-csv-import Completed: 2026-06-15
Self-Check: PASSED
All created files verified present on disk:
- FOUND: src/app/admin/offers/[id]/edit/page.tsx
- FOUND: src/components/admin/offers/OfferEditorClient.tsx
- FOUND: .planning/phases/12-offer-composition-drag-drop-csv-import/12-05-SUMMARY.md
All task commits verified present in git log: