Skip to main content

[PRD] Revamp Add Single Customer in Right-Side Drawer

HEADER BLOCK

FieldValue
PMZhelia Alifa
PRD Version1.2
StatusDRAFT
PRD TypeADJUSTMENT (Frontend)
EpicTBD
SquadCDP Squad
RFC LinkTBD
Repoqontak-customer-fe (Nuxt 4 / Vue 3 / Mekari Pixel 3)
PlatformWebsite only
FigmaAdd customer — right-side drawer
ParentPRD CDP Q4 2026
Labelsepic:qontak-cdp | module:customers | feature:add-customer-drawer
Last Updated2026-07-25

0. Adjustment Context (Conditional Block)

Parent / current behavior: adding a single customer today is a full-page flow at route /customers/add (pages/customers/add.vuefeatures/customers/create/views/Index.vue). This PRD adjusts only the surface that hosts the create form — from a full page to a right-side drawer. It does not change what the form collects or how it saves.

Adjustment scope: move the existing create-customer form into a Mekari Pixel 3 right-side drawer opened from the customer list, and change the save/cancel flow to close-and-refresh in place instead of navigating away. Website only.

Parent scope preserved: all current create behavior is retained — the same dynamic, layout-driven fields (GET /v1/contacts/field_properties?layout_id=default), the same validation, the same POST /v1/contacts save, the same permission gate (customers_customers_add), and the same Mixpanel events. No new fields; no CRM-module association added.

Reason for the adjustment (grounded): the full-page layout is a 3-column grid gridTemplateColumns: '1fr 2fr 1fr' (features/customers/create/views/Index.vue:44-49) where the form occupies only the first 1fr column and the middle "Customer Activity" (2fr) and right "Customer Association" (1fr) columns are rendered as empty placeholders (Index.vue:25-29). So ~⅔ of the page is intentional blank space — scaffolding for activity/association panels that were never built, because create is a create-only action (association only exists later, on the detail page). A focused drawer removes the blank space and keeps the user in context on the customer list.

User-facing UI changes: Yes — the create-customer surface changes from a full page to a right-side drawer (this is the point of the adjustment). No other screen changes.


1. One-liner + Problem

One-liner: Move the add single customer create form from a full page into a right-side drawer on the CDP customer list — website only.

Problem: Creating a single customer opens a full page (/customers/add) whose layout was built for activity + association panels that don't exist at create time — so two of its three columns render empty (Index.vue:25-29, :44-49) and ~⅔ of the screen is blank. Because create is a create-only action (a user cannot and should not associate the customer with other CRM modules — deal / ticket / task / company — during creation; association only exists later on the detail page), the full page is oversized for the job, adds an unnecessary navigation away from the list, and reads poorly. Users just need a focused field-entry form.


2. Target Users + Persona Context

PersonaRoleGoalPainWorkaround
Primary — CRM/CDP agent or adminAdds customers to CDP one at a timeAdd a customer quickly without losing the list contextFull-page create navigates away, is oversized, and shows large blank spaceFills the sparse full page, then navigates back to the list
Secondary — Team lead / opsReviews the customer list, adds ad-hoc customersStay on the list while addingContext switch to a full page for a simple form

3. Non-Goals

  1. Not adding CRM-module association during create — deal / ticket / task / company association stays a detail-page capability (features/customers/detail/.../Associated*.vue); create remains create-only.
  2. Not changing the fields or the field source — fields still come from the backend layout (GET /v1/contacts/field_properties?layout_id=default); no fields added/removed by this PRD.
  3. Not changing the save contract — still POST /v1/contacts; no backend change.
  4. Not the bulk / multiple-customers flow/customers/bulk-upload is unchanged.
  5. Not mobile — website only.
  6. Not a redesign of the customer list page — only the add-customer entry point behavior changes.

4. Constraints

ConstraintValue
PlatformWebsite only (qontak-customer-fe, Nuxt 4 / Vue 3). No mobile.
Design systemMekari Pixel 3 MpDrawer family (MpDrawerOverlay/Content/Header/Body/Footer/CloseButton), placement="right" — reuse the established pattern (ExportCustomerDrawer.vue, DrawerSegment.vue).
No backend changeSame POST /v1/contacts + GET /v1/contacts/field_properties?layout_id=default contract, unchanged.
PermissionEntry gated by customers_customers_add (unchanged, Breadcrumb.vue:139-146).
Feature flagcdp_add_customer_drawer_enabled | default: OFF — flips the "Single customer" entry from the full-page route to the drawer, for safe rollback.
Layout / scrollThe form can be long (many layout fields + cascading address). The drawer body scrolls with a sticky footer (Cancel / Save) and a sticky header ("Add customer" + close ✕), per Figma.
No new fieldsThe drawer renders exactly the fields the current form renders (dynamic layout).
Performance (no regression)Create success rate ≥ current full-page baseline and create p95 latency ≤ baseline (same POST /v1/contacts); drawer open/render adds no perceptible delay vs the page. These are the §11 gate values.

Scope Changes

Engineering surfaces this PRD touches (controlled vocab: Backend · Frontend · Mobile · Infra · Data · Design · Docs · None).

  • Frontendqontak-customer-fe: host the existing create-customer Form.vue inside a Pixel 3 right-side MpDrawer opened from the customer list; change the list entry point (Breadcrumb.vue:68-70) to open the drawer instead of navigating to /customers/add; change the form's save/cancel from a hard router.push('/customers/all-customers') (Form.vue:86, :621-622) to emit close/saved and refresh the list in place; mount + toggle the drawer from the list page (mirroring ListPage.vue isExportDrawerOpen).
  • Design — new right-side "Add customer" drawer layout (Figma).

5. Feature Changes

5.1 Change block — Add-customer surface: full page → right-side drawer

FieldValue
Change IDACD-CH-01
Change TypeUX surface change (re-host existing form)
Page / URLCustomer list /customers/all-customers (entry) · current full page /customers/add (superseded as the primary surface)
Page intentCreate a single customer without leaving the list

Before → After (element-level):

ElementBefore (full page)After (drawer)
SurfaceFull page at /customers/add (pages/customers/add.vueIndex.vue)Right-side Pixel 3 MpDrawer (placement="right") mounted on the list page
Layout3-column grid 1fr 2fr 1fr (Index.vue:44-49); cols 2 & 3 empty placeholders (Index.vue:25-29) → ~⅔ blankSingle-column form in the drawer body; no blank columns
HeaderBreadcrumb "Customers / Add Customer" (Index.vue)Drawer header "Add customer" + close ✕ + "Select view: Default view" selector (Figma)
FormForm.vue in column 1Same Form.vue, rendered in MpDrawerBody
FooterSave / Cancel inline in the form column (Form.vue)Sticky Cancel / Save in MpDrawerFooter (Figma)
Entry point"Add customer" popover → "Single customer" = NuxtLink to="/customers/add" (Breadcrumb.vue:68-70)Same popover item → opens the drawer (sets isAddCustomerDrawerOpen = true); no route navigation
On Save successrouter.push('/customers/all-customers') + toast (Form.vue:621-627)Close the drawer, show the success toast, and refresh the list in place (no navigation)
On Cancel / closerouter.push('/customers/all-customers') (Form.vue:86)Close the drawer, stay on the list (unsaved input discarded; see OQ-3)

Fields (unchanged, from the default layout): Full name* (0/60), Username (@-source prefix), Phone number (multi, max 3), Email, Source, Owner*, Owner's team (flag cdp_team_permission_enabled), Assignee (+ "Assign to me"), Date of birth, Sex (None/Male/Female), Status, Job title, and cascading Province → City → District → Subdistrict → Zip code, plus any custom layout fields — all rendered by the existing dynamic dispatcher (Form.vue:66-72; source GET /v1/contacts/field_properties?layout_id=default, Form.vue:404-408). (The Figma frame shows the Default-view field set.)

Figma: Add customer — right-side drawer


7. API & Webhook Behavior

No API change. Create still calls POST /v1/contacts (Form.vue:611-616) and fields still load from GET /v1/contacts/field_properties?layout_id=default (Form.vue:404-408) — identical request and response. This PRD only changes the FE surface that hosts the form.


8. System Flow + User Stories + ACs

8.1 System Flow

Flow type: User Journey (create-customer via drawer).

flowchart TD
A[Customer list /customers/all-customers] -->|Add customer → Single customer<br/>Breadcrumb.vue:69| B{cdp_add_customer_drawer_enabled?}
D[Deep-link /customers/add<br/>host router RemoteContactRouter.vue:50-51] -->|flag ON → redirect| B
B -->|OFF| P[Full page /customers/add<br/>legacy, safe rollback]
B -->|ON| C[Open right-side MpDrawer<br/>fire 'Open Add Customer Drawer']
C --> E[Load layout<br/>GET field_properties?layout_id=default]
E -->|load fails| E1[Inline error / retry in drawer]
E --> F[Render Form.vue + fill fields]
F --> G{Save or Cancel?}
G -->|Cancel / ✕| H[Close drawer, stay on list<br/>discard input]
G -->|Save| I[POST /v1/contacts]
I -->|success| J[Close drawer + toast +<br/>refresh list in place +<br/>fire 'Add Single Customer']
I -->|error| K[Keep drawer open,<br/>preserve values, error toast]
  1. On the customer list (/customers/all-customers), the user (with customers_customers_add) opens the "Add customer" popover and clicks Single customer.
  2. With the flag ON, this opens the right-side drawer (no navigation) instead of routing to /customers/add; the Mixpanel "Click Add Single Customer" event still fires.
  3. The drawer loads the field layout (field_properties?layout_id=default) and renders Form.vue.
  4. The user fills the form; validation is identical to today.
  5. SavePOST /v1/contacts → on success: close the drawer, show the success toast, refresh the list in place, fire "Add Single Customer". Cancel / ✕ → close the drawer, stay on the list.

8.2 User Stories

User StoryImportanceMockupTechnical NotesAcceptance Criteria
[ACD-S01] — Open the Add Customer drawer from the list

As an agent/admin, I want the "Single customer" action to open a right-side drawer, so that I can add a customer without leaving the list.
Must HaveFigma — Add customer drawerGrounded: entry point today is NuxtLink to="/customers/add" in the "Add customer" popover (Breadcrumb.vue:68-70), gated by customers_customers_add (:139-146). Change it to toggle an isAddCustomerDrawerOpen ref (mirror ListPage.vue isExportDrawerOpen, :246, :123-130); mount a new AddCustomerDrawer using Pixel 3 MpDrawer placement="right" (pattern: ExportCustomerDrawer.vue:2-8).
Before → After: Before — navigates to full page /customers/add. After — opens the drawer over the list.
• AC-1: Given a user with customers_customers_add on the customer list, when they click "Add customer" → "Single customer", then a right-side drawer titled "Add customer" opens over the list (no route navigation).
• AC-2: Given the drawer is open, when the user clicks the ✕ or the overlay, then the drawer closes and the list is unchanged.
• AC-3: Given a user without customers_customers_add, then the entry point is not shown (unchanged gate).
— Error —
• ERR-1: Given the field layout fails to load, then the drawer shows an inline error/retry state (form not left blank silently).
[ACD-S02] — Create a customer in the drawer (form + save parity)

As an agent/admin, I want the drawer form to create a customer exactly as the full page did, so that nothing about creating is lost.
Must HaveFigmaGrounded: reuse Form.vue's field/validation/save logic in MpDrawerBody — same dynamic fields (Form.vue:66-72), yup validation (:164-291), POST /v1/contacts (:611-616). Not fully unchanged (D-7): the Save/Cancel buttons currently live inside Form.vue (Form.vue:83-91), but the drawer needs them in a sticky MpDrawerFooter — so extract them, defineExpose submitForm + loadingSubmit for the footer's Save, and have Cancel emit close. Also point the scroll-to-error (document.querySelector('.q-form--error').scrollIntoView, Form.vue:643) at the drawer body's scroll container. Drop the Index.vue chrome (breadcrumb + empty grid).• AC-1: Given the drawer is open, then it renders the same fields as the current create form for the default layout (Full name*, Username, Phone, Email, Source, Owner*, Owner's team, Assignee, DOB, Sex, Status, Job title, Province→City→District→Subdistrict→Zip, + custom fields).
• AC-2: Given valid input, when the user clicks the Save button in the sticky drawer footer, then it triggers the form's exposed submitForm and POST /v1/contacts is called with the same payload shape as today.
• AC-3: Given invalid input (e.g. empty required Full name / Owner), then the same validation errors show inline, Save is blocked, and the drawer scrolls to the first error within the drawer body (not the window).
• AC-4: Given the cascading address fields, then City is disabled until Province is chosen, District until City, etc. (unchanged dependency behavior).
• AC-5: Given a long form, then Cancel/Save stay pinned in the sticky footer while the body scrolls, and the Save button reflects the form's loadingSubmit state.
[ACD-S03] — Save closes the drawer and refreshes the list in place

As an agent/admin, I want a successful save to return me to the updated list without a full-page reload, so that I keep my context.
Must HaveFigmaGrounded: today success does router.push('/customers/all-customers') + toast (Form.vue:621-627). In the drawer, replace the hard navigation with an emitted saved event; the list page closes the drawer, shows the toast, and refreshes the list data in place. Mixpanel [Qontak One] [Customer] Add Single Customer still fires (Form.vue:593-595).• AC-1: Given a successful create, when the drawer is used, then the drawer closes, the success toast "Customer successfully created" shows, and the newly created customer appears in the refreshed list — without a full-page navigation.
• AC-2: Given the save, then the "Add Single Customer" Mixpanel event fires exactly once (parity with today).
— Error —
• ERR-1: Given POST /v1/contacts fails, then the drawer stays open, the entered values are preserved, and the same error toast shows.
[ACD-S04] — Cancel / close discards and stays on the list

As an agent/admin, I want Cancel or ✕ to close the drawer and keep me on the list, so that abandoning is frictionless.
Must HaveFigmaGrounded: today Cancel does router.push('/customers/all-customers') (Form.vue:86). In the drawer, Cancel/✕ emits close; the list page hides the drawer with no navigation. Unsaved-changes confirmation = OQ-3.• AC-1: Given the drawer is open with entered values, when the user clicks Cancel or ✕, then the drawer closes, no customer is created, and the user remains on the list (no navigation).
• AC-2: Given the drawer was closed, when the user reopens it, then it opens with a fresh, empty form (no stale state).
[ACD-S05] — Layout/view selection in the drawer

As an admin, I want the drawer to respect the customer field layout (view), so that custom fields still appear.
Should HaveFigma — "Select view: Default view"Grounded: fields come from field_properties?layout_id=default (Form.vue:404-408); the Figma header shows a "Select view: Default view" control. Scope of switching views in the drawer = OQ-2 (default: render the Default view; a switcher is a follow-up if not already supported).• AC-1: Given a company with custom layout fields, when the drawer opens on the Default view, then those custom fields render and post under custom_fields[] (unchanged).
• AC-2: Given the "Select view" control (if in scope, OQ-2), when a different view is chosen, then the drawer re-renders that layout's fields.
[ACD-S06] — Handle the /customers/add deep-link (second entry point) so the full page actually retires

As a CDP engineer, I want every path to add-customer to reach the drawer (or redirect to it), so that we don't ship two divergent create experiences and the blank-space page is truly retired.
Must HaveN/A — routingGrounded — second entry point: the list breadcrumb (Breadcrumb.vue:69) is not the only way into create. The micro-frontend host router matches any /customers/add path and renders the full-page component (common/components/RemoteContactRouter.vue:50-51: else if (/^\/customers\/add/.test(pathName)) { asyncPageComponent = Add }, registered at :29). So an external shell / deep-link bypasses the list and lands on the full page. With the flag ON, /customers/add must redirect to the list + auto-open the drawer (default, OQ-1) — otherwise drawer-from-list and full-page-from-deep-link coexist and the page never retires.• AC-1: Given the flag is ON, when a user (or an external shell) navigates directly to /customers/add — including via the host router (RemoteContactRouter.vue:50-51) — then they land on the customer list with the Add Customer drawer auto-opened, never the standalone full page.
• AC-2: Given the flag is ON, then there is no path that still renders the full-page create surface (the empty-column page is fully retired for that scope).
• AC-3: Given the flag is OFF, then /customers/add and the host route render the full page exactly as today (safe rollback).
— Error —
• ERR-1: Given the host cannot open the drawer (e.g. list context unavailable), then it falls back to the full page rather than a broken screen, and the fallback is logged.

Dependencies: ACD-S02/S03/S04 reuse the existing Form.vue; ACD-S06 depends on the micro-frontend host routing decision (OQ-1).


9. Rollout

AspectDetail
Feature flagcdp_add_customer_drawer_enabled | default: OFF. ON = the "Single customer" entry opens the drawer; OFF = the current full-page route.
Rollout sequenceInternal / QA on staging → enable for a small % of companies → GA. Entry-point swap + drawer are entirely behind the flag.
Backward compatibilityYes. With the flag OFF, /customers/add and the full page are untouched. The POST /v1/contacts + field_properties contract is unchanged, so no data/behavior migration.
RollbackFlip the flag OFF → instantly reverts to the full-page flow; no redeploy.
Host compatibility (GA gate)The /customers/add deep-link handled by the micro-frontend host router (RemoteContactRouter.vue:50-51) must redirect to the list + auto-open the drawer under the flag (ACD-S06). GA is blocked until this is done — otherwise the full page is still reachable and never retires.

10. Observability

Events (Mixpanel — reuse existing, add surface context)

EventTriggerProperties
[Qontak One] [Customer] Click Add Single CustomerUser clicks "Single customer" (now opens the drawer)existing props + surface: drawer | page
[Qontak One] [Customer] Open Add Customer Drawer (new)The Add Customer drawer is opened (from the list or a /customers/add deep-link redirect)entry: list | deeplink, company_sso_id
[Qontak One] [Customer] Add Single CustomerSuccessful create (drawer save)existing props + surface: drawer | page
[Qontak One] [Customer] Close Add Customer Drawer (new)Drawer closed without saving (Cancel/✕/overlay)had_input: bool, company_sso_id

(The first two already exist — Breadcrumb.vue:157-159, Form.vue:593-595; adding a surface property lets us compare drawer vs the legacy page during rollout.)

Monitoring

SignalThresholdRouting
Create success rate (drawer vs page)drawer ≥ page baselineCDP FE — investigate a drop before widening rollout
POST /v1/contacts error rate from the drawerno increase vs baselineCDP FE
Drawer open → save conversiontracked for the funnelCDP PM dashboard

Dashboard owner: CDP squad. Cadence: review daily during staged rollout, then weekly post-GA.


11. Success Metrics

CategoryMetricDefinitionBaselineTarget
Quality⭐ Create-customer success rate (no regression)Successful POST /v1/contacts / create attempts, drawer vs current pageCurrent full-page success rate≥ baseline (no regression)
EfficiencyTime-to-create (open → save)Median seconds from opening the create surface to a successful saveCurrent full-page median≤ baseline (faster / same)
AdoptionDrawer usage share% of single-customer creates via the drawer once GA0% (new)≥ 95% of single-customer creates post-GA
EfficiencyContext retention% of creates that return to the list without a full-page navigation0% today (always navigates)100% via the drawer

Primary KPI = create success rate maintained (no regression) while moving 100% of single-customer creates off the full page — this is an ADJUSTMENT, so "don't break create" is the gate.


12. Launch Plan & Stage Gates

StageAudienceDurationSuccess gate
1 — Internal / QAStaging + internal companies (flag ON)until sign-offFull form parity vs the page (fields, validation, save); Figma match; /customers/add host case handled
2 — Canary %Small % of companies (flag ON)1 weekCreate success rate ≥ baseline; no POST /v1/contacts error spike from the drawer
3 — GAAll website companiesSustained ≥ baseline success rate; ≥ 95% of single-customer creates via the drawer

Each gate references §11 (success rate) + §10 (error/conversion). Failing a gate → hold; regression → flip the flag OFF (§9).


13. Dependencies

DependencyOwnerDeliverableBlocking?
Design — Add customer drawerDesign (CDP)Final Figma for the right-side drawer (link)YES
Pixel 3 MpDrawerMekari PixelRight-placement drawer components (already used in-repo)NO (available)
Micro-frontend host routing — the /customers/add deep-link (second entry point)CDP FE / host ownerWith the flag ON, redirect the host-matched /customers/add path (RemoteContactRouter.vue:50-51, registered :29) to the list + auto-open the drawer, so no path still renders the full page (ACD-S06)YES (blocking for GA) — without it the full page never retires and two create experiences coexist
Form.vue refactor (D-7)CDP FEExtract Save/Cancel from Form.vue (Form.vue:83-91) into the sticky MpDrawerFooter; defineExpose submitForm + loadingSubmit; Cancel emits close; save emits saved instead of router.push (Form.vue:86, :621-622); scroll-to-error targets the drawer body (Form.vue:643)YES

14. Key Decisions + Alternatives Rejected

14a — Decisions Made

IDDateDecisionRationale
D-12026-07-25Reuse the existing Form.vue's field/validation/save logic inside a Pixel 3 MpDrawer; don't rebuild the form — but with a targeted refactor (D-7), not "unchanged".The dynamic fields + yup validation + POST /v1/contacts are reused as-is; the page chrome, the navigation, and the Save/Cancel button placement are what change (see D-7).
D-22026-07-25No backend change — keep POST /v1/contacts + field_properties.The adjustment is UI-surface only; the create contract is correct as-is.
D-32026-07-25Save/Cancel emit saved/close and refresh the list in place, instead of router.push.Keeping the user on the list is the whole point of the drawer.
D-42026-07-25Gate the swap behind cdp_add_customer_drawer_enabled (OFF).Safe, instant rollback to the full page if create regresses.
D-52026-07-25Create stays create-only — no CRM-module association in the drawer.Association is a detail-page capability; adding it here is out of scope and defeats the "focused" intent.
D-62026-07-25Retire the full page for real: the /customers/add deep-link (host router) redirects to the drawer under the flag.The list breadcrumb isn't the only entry point (RemoteContactRouter.vue:50-51); without redirecting the deep-link, two create experiences coexist and the blank-space page never retires.
D-72026-07-25Lift the Save/Cancel buttons out of Form.vue into the sticky MpDrawerFooter; expose submitForm + loadingSubmit from Form.vue (defineExpose) and have Cancel emit close.The Figma footer is sticky, but today the buttons live inside Form.vue (Form.vue:83-91; Cancel $router.push :86, Save submitForm :91). A sticky drawer footer can't wrap the form's own buttons — the submit trigger must be decoupled so the footer owns Cancel/Save. This is the one real Form.vue change (beyond navigation).

14b — Alternatives Rejected

AlternativeDateWhy rejected
Keep the full page but delete the two empty columns2026-07-25Removes blank space but still navigates the user away from the list and keeps a heavyweight page for a light task.
Use a centered modal dialog instead of a drawer2026-07-25The form is long (many layout fields + cascading address); a right-side drawer scrolls better and matches the Pixel pattern already used for export/segment.
Rebuild the create form as a new drawer component2026-07-25Unnecessary — Form.vue already works standalone; rebuilding risks validation/field-parity regressions.

15. Open Questions

#TypeQuestionMitigation / DefaultOwnerDeadline
OQ-1Decision (blocking for GA — ACD-S06)With the flag ON, how is the /customers/add deep-link handled by the host router (RemoteContactRouter.vue:50-51) — redirect to list + auto-open drawer, or render the drawer standalone at that path?Default: redirect /customers/add → list with the drawer auto-opened; keep the route resolvable so the host doesn't 404. Must be resolved before GA (else the full page never retires).CDP FE + host owner2026-10-09 (RFC)
OQ-2ScopeDoes the "Select view: Default view" control in the drawer let the user switch layouts, or is it display-only (Default view)?Default v1: render the Default view; a view switcher is a follow-up unless already supported by field_properties?layout_id=.PM + CDP FE2026-10-09
OQ-3DecisionOn Cancel/✕ with unsaved input — discard silently or show an "unsaved changes" confirm?Default: show a lightweight confirm if the form is dirty; otherwise close immediately.PM + CDP FE2026-10-16
OQ-4DesignDrawer width + long-form scroll behavior (sticky header/footer) on smaller desktop widths.Follow Figma; sticky header (title + ✕) and footer (Cancel/Save), body scrolls.Design + FE2026-10-16
OQ-5RiskOverlay stacking inside the drawer — the form's dropdowns (Source/Owner/Status/address selects), the @-username dropdown, and the date picker open floating layers; inside an MpDrawer these can clip or render behind the drawer if not portalled with the right z-index (cf. use-portal / zIndex: modal+n patterns at properties/.../ListTable.vue:55, UserSelectionDrawer.vue:7).Verify each field overlay renders above the drawer (use Pixel use-portal / correct z-index); QA every dropdown + date picker inside the drawer before GA.CDP FE + QA2026-10-16

PRD CHANGELOG

VersionDateBySectionTypeSummary
1.22026-07-25Zhelia Alifa (drafted w/ AI, grounded)§14 (D-1/D-7), §8.2 (ACD-S02), §13, §15 (OQ-5)UPDATEDClosed a second grounded gap: Form.vue is not reusable "unchanged". The Figma drawer has a sticky footer for Cancel/Save, but those buttons live inside Form.vue (Form.vue:83-91; Cancel $router.push :86, Save submitForm :91). So the footer must own the buttons: extract them into MpDrawerFooter, defineExpose submitForm + loadingSubmit, Cancel emits close, and point scroll-to-error (Form.vue:643) at the drawer body. Corrected D-1 ("not unchanged"), added D-7, rewrote ACD-S02 tech notes + added AC-5 (sticky footer / loading state) and tightened AC-2/AC-3; made the §13 Form.vue dependency the button-extraction refactor; added OQ-5 (overlay/dropdown/date-picker z-index inside the drawer — verify portalling). No change to fields or the create contract.
1.12026-07-25Zhelia Alifa (drafted w/ AI, grounded)§8.2 (ACD-S06), §9, §13, §15, §10, §14, §4, §8.1UPDATEDClosed the grounded gap + score-prd polish. Gap: the list breadcrumb (Breadcrumb.vue:69) is not the only entry point — the micro-frontend host router matches /customers/add and renders the full page (RemoteContactRouter.vue:50-51), a second (deep-link) entry point. Promoted ACD-S06 Should → Must (redirect the deep-link to the list + auto-open the drawer so the full page truly retires; +ERR fallback), made host-route handling a blocking §13 dependency + §9 GA gate, sharpened OQ-1. Polish: added a 4th Mixpanel event (Open Add Customer Drawer) to §10; dated all §14 decisions + rejected alternatives; added a system-flow mermaid to §8.1; added a no-regression Performance constraint to §4. No change to the create contract or fields.
1.02026-07-25Zhelia Alifa (drafted w/ AI, grounded)AllCREATEDFirst PRD to revamp add single customer into a right-side drawer (ADJUSTMENT, website only). Grounded against qontak-customer-fe: current full page is /customers/add (pages/customers/add.vueIndex.vue) with a 3-column grid 1fr 2fr 1fr (Index.vue:44-49) whose "Customer Activity"/"Customer Association" columns are empty placeholders (Index.vue:25-29) → ~⅔ blank; create is create-only (association only on the detail page, Associated*.vue). Solution: host the existing dynamic Form.vue (fields from field_properties?layout_id=default, save POST /v1/contacts) inside a Pixel 3 right-side MpDrawer (pattern: ExportCustomerDrawer.vue/DrawerSegment.vue), opened from Breadcrumb.vue:68-70, with save/cancel emitting saved/close + refresh-in-place instead of router.push (Form.vue:86, :621-622), behind flag cdp_add_customer_drawer_enabled. Stories ACD-S01..S06; §5 Feature Changes before/after; rollout/observability/metrics/launch; decisions + OQs (route handling, view switch, unsaved-changes, drawer width).