Template flow cleaned up
This commit is contained in:
+21
-1
@@ -55,7 +55,27 @@ Active step for chrome and navigation is resolved from the pathname via [`parseC
|
||||
| --- | --- |
|
||||
| `/create/review-template/[slug]` | Template preview in the create shell; uses the same layout/footer chrome as other create pages but **is not** part of `FLOW_STEP_ORDER` **or** the three Figma stages above. |
|
||||
|
||||
From that page, **Customize** currently navigates to `/create/informational?template=<slug>`. The **`template` query parameter is reserved**; the informational step **does not** yet read it to prefill `CreateFlowState`. **Starting the wizard from a template at `final-review` or any mid-flow step** is **out of scope** until a dedicated product ticket ships. A **full create-from-template** experience will **likely use separate route(s)** when product and eng define it (may still align conceptually with the same three stages where behavior overlaps the custom path).
|
||||
From that page, **Customize** pre-fills the custom-rule selections on the current `CreateFlowState` (via [`buildTemplateCustomizePrefill`](../lib/create/applyTemplatePrefill.ts)) and routes to **`/create/core-values`** when the community name (`state.title`) is already set, otherwise to **`/create/informational`**. Name-only is the gate because other community-stage fields (e.g. `communityStructureChipSnapshots`) are sticky once the user lands on those screens; a non-empty title is also the minimum bar [`buildPublishPayload`](../lib/create/buildPublishPayload.ts) enforces, so the two checks stay aligned. No query-param plumbing: state persists via the usual anonymous/server-draft mirrors.
|
||||
|
||||
**Use without changes** writes the template's `body.sections` into `state.sections` (and its `description` into `state.summary` when present), resets any prior Customize chip selections so they don't bleed into `document.coreValues`, and routes to **`/create/confirm-stakeholders`**. The user then exits via the normal **`final-review → handleFinalize → publishRule`** pipeline, which gates unauthenticated publishes with a **401 → `openLogin`** redirect back to `/create/final-review?syncDraft=1`.
|
||||
|
||||
**Entering a template before community stage is done.** When `state.title` is empty, both handlers apply their side effects eagerly (prefill for Customize; `sections` + `summary` for Use without changes) *and* pin a `pendingTemplateAction: { slug, mode }` on `CreateFlowState` before routing to `/create/informational`. Once the user reaches `/create/review`, [`CommunityReviewScreen`](../app/(app)/create/screens/review/CommunityReviewScreen.tsx) reads the action on mount, clears it via `updateState`, and `router.replace`s past itself — to `/create/core-values` for `customize`, `/create/confirm-stakeholders` for `useWithoutChanges`. The user never sees the community-review page in that flow because their intent was already expressed at the template-review step. `replace` (not `push`) keeps `community-save` as the Back-button target from the destination. The action is cleared on the first fire so later direct visits to `/create/review` render normally.
|
||||
|
||||
**Direct entry vs in-flow template pick.** The same `/create/review-template/[slug]` URL is reached from two different origins. We disambiguate at the *click site*, not on the review-template page, using [`clearCreateFlowPersistedDrafts`](../app/(app)/create/utils/clearCreateFlowPersistedDrafts.ts) — a tiny helper that wipes the anonymous draft from `localStorage` (both `create-flow-anonymous` and the core-value-details key) **before** the navigation fires. Because `CreateFlowProvider` reads `localStorage` in its `useState` initializer, the provider mounts empty and `handleCustomizeTemplate` / `handleUseTemplateWithoutChanges` naturally take the no-community branch — no per-handler marker plumbing needed.
|
||||
|
||||
| Origin | Click-site behavior | URL the user lands on |
|
||||
| --- | --- | --- |
|
||||
| Home marketing "Popular templates" ([`RuleStack.container.tsx`](../app/components/sections/RuleStack/RuleStack.container.tsx)) | always calls `clearCreateFlowPersistedDrafts()` | `/create/review-template/[slug]` |
|
||||
| `/templates` index ([`TemplatesPageClient.tsx`](../app/(marketing)/templates/TemplatesPageClient.tsx)) visited directly / via pasted URL | `fromFlow` absent → calls `clearCreateFlowPersistedDrafts()` | `/create/review-template/[slug]` |
|
||||
| In-flow: `/create/review` footer "Create from template" → `/templates?fromFlow=1` → template click | `fromFlow=1` → skips the clear | `/create/review-template/[slug]` |
|
||||
|
||||
Only one `?fromFlow=1` marker exists, on one hop (`/create/review` → `/templates`). It is not forwarded onto the review-template URL. The review-template handlers branch solely on `state.title` — they don't need to know the origin.
|
||||
|
||||
Server drafts (`/api/drafts/me`) are **not** touched here. Per product plan they are not auto-hydrated into the create flow; users select and load a specific saved draft from the profile page. So wiping `localStorage` is sufficient for the "fresh slate" invariant.
|
||||
|
||||
**Final-review RuleCard category chips** are derived from `CreateFlowState` via [`buildFinalReviewCategoriesFromState`](../lib/create/buildFinalReviewCategories.ts): for the Customize / plain custom-rule path it resolves `selected{Communication,Membership,DecisionApproach,ConflictManagement}MethodIds` against the curated method presets in `messages/en/create/customRule/*.json`, and `buildCoreValuesForDocument` supplies the `Values` row from `coreValuesChipsSnapshot` + `selectedCoreValueIds`. For the Use-without-changes path the template body lives in `state.sections`; the helper renders `categoryName` + entry titles directly. The demo chips shipped in `finalReview.json` remain the fallback only when nothing in state resolves to any chip (e.g. direct navigation for development).
|
||||
|
||||
**Starting the wizard from a template at `final-review` directly** is out of scope until a dedicated product ticket ships. A **full create-from-template** experience will **likely use separate route(s)** when product and eng define it (may still align conceptually with the same three stages where behavior overlaps the custom path).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -311,7 +311,7 @@ Optional: **Docker image deploy** using the repo [Dockerfile](Dockerfile)—admi
|
||||
|
||||
**Goal:** Establish the **official custom** create-rule flow (ordered steps, URLs, persistence, entry points, **Figma three-stage framing**) in repo docs and close gaps between that spec and the implementation (routing clutter, progress UI, step source of truth, resume vs URL).
|
||||
|
||||
**Context:** Step order lives in [`app/(app)/create/utils/flowSteps.ts`](app/(app)/create/utils/flowSteps.ts). Wizard screens render from [`app/(app)/create/[screenId]/page.tsx`](app/(app)/create/[screenId]/page.tsx) plus [`CREATE_FLOW_SCREEN_REGISTRY`](app/(app)/create/utils/createFlowScreenRegistry.ts) (Figma node + layout family per slug). [`docs/create-flow.md`](create-flow.md) is the **canonical** URL/persistence summary: **Create Community** (eight semantic steps ending at `review`) → **Create Custom CommunityRule** → **Review and complete**. **Full create-from-template** will likely use **additional route(s)** when product defines it; **`/create/review-template/[slug]`** remains auxiliary preview only. **Template → `final-review` or mid-wizard prefill** is **out of scope** here (future ticket); `/create/informational?template=` is a **no-op** until then.
|
||||
**Context:** Step order lives in [`app/(app)/create/utils/flowSteps.ts`](app/(app)/create/utils/flowSteps.ts). Wizard screens render from [`app/(app)/create/[screenId]/page.tsx`](app/(app)/create/[screenId]/page.tsx) plus [`CREATE_FLOW_SCREEN_REGISTRY`](app/(app)/create/utils/createFlowScreenRegistry.ts) (Figma node + layout family per slug). [`docs/create-flow.md`](create-flow.md) is the **canonical** URL/persistence summary: **Create Community** (eight semantic steps ending at `review`) → **Create Custom CommunityRule** → **Review and complete**. **Full create-from-template** will likely use **additional route(s)** when product defines it; **`/create/review-template/[slug]`** remains auxiliary preview only. **Template → `final-review` prefill** (skipping straight to publish) is **out of scope** here (future ticket). The **Customize** button on `/create/review-template/[slug]` now prefills customize selections and routes to `core-values` (or `informational` when Community is empty) via [`buildTemplateCustomizePrefill`](../../lib/create/applyTemplatePrefill.ts). **Use without changes** writes `template.body.sections` into `state.sections` and routes to `confirm-stakeholders`, so the user exits through the normal `final-review → handleFinalize → publishRule` pipeline and inherits its 401 sign-in gate. When either button is clicked **before** the community stage is done, the handler still applies its side effects eagerly and pins a `pendingTemplateAction: { slug, mode }` on `CreateFlowState`; [`CommunityReviewScreen`](app/(app)/create/screens/review/CommunityReviewScreen.tsx) consumes the pin on mount and `router.replace`s past itself to the right downstream step (`core-values` for customize, `confirm-stakeholders` for useWithoutChanges), so users never see the community-review page after expressing template intent at the template-review step.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
@@ -328,7 +328,7 @@ Optional: **Docker image deploy** using the repo [Dockerfile](Dockerfile)—admi
|
||||
- [ ] No misleading dynamic step placeholder for valid wizard URLs.
|
||||
- [ ] Footer progress reflects step index **or** doc/issue records a deliberate deferral with design sign-off.
|
||||
- [ ] Hydration + `currentStep` behavior is verified (redirect vs stay).
|
||||
- [ ] `?template=` documented as deferred; no implied “template customize → full wizard” parity.
|
||||
- [ ] Template **Customize** prefill is documented (maps template body to `selected*Ids` + `coreValuesChipsSnapshot`, routes to `core-values` when Community has data else `informational`); full template-customize-from-mid-wizard entry beyond `core-values` stays deferred.
|
||||
|
||||
**Files:** [`docs/create-flow.md`](create-flow.md), [`app/(app)/create/`](app/(app)/create/), [`app/components/utility/CreateFlowFooter/`](app/components/utility/CreateFlowFooter/), optionally [`docs/backend-roadmap.md`](backend-roadmap.md) §12 cross-links.
|
||||
|
||||
|
||||
@@ -269,9 +269,27 @@ decision-approaches → conflict-management → confirm-stakeholders → final-r
|
||||
| API list | `app/api/templates/route.ts` (GET only, no params today) |
|
||||
|
||||
Template ranking adds optional facet query params to `/api/templates`;
|
||||
the no-facets path keeps today's curated ordering. The
|
||||
`/create/informational?template=<slug>` query-param prefill is a known
|
||||
no-op (`CreateFlowLayoutClient.tsx`); fixing it is **out of scope**.
|
||||
the no-facets path keeps today's curated ordering. Template **Customize**
|
||||
now prefills the custom-rule flow via
|
||||
[`buildTemplateCustomizePrefill`](../../lib/create/applyTemplatePrefill.ts)
|
||||
(applied in `CreateFlowLayoutClient.tsx`) and routes to `core-values`
|
||||
when Community already has input, else to `informational`. Template **Use
|
||||
without changes** writes `template.body.sections` into `state.sections`
|
||||
and routes to `confirm-stakeholders`, so the user exits via the normal
|
||||
`final-review → handleFinalize → publishRule` path and picks up the
|
||||
server-enforced 401 sign-in gate for free.
|
||||
|
||||
When the user picks a template **before** completing the community
|
||||
stage, both handlers still apply their side effects eagerly (prefill or
|
||||
`sections`/`summary`) and pin a
|
||||
`pendingTemplateAction: { slug, mode: "customize" | "useWithoutChanges" }`
|
||||
on `CreateFlowState`, then route to `informational`. Once the user
|
||||
reaches `/create/review`, `CommunityReviewScreen` consumes the pin and
|
||||
`router.replace`s past itself — to `core-values` for `customize`, to
|
||||
`confirm-stakeholders` for `useWithoutChanges`. The community-review
|
||||
screen is therefore only shown when the user came from "Create Custom"
|
||||
(no template), matching the intent already expressed at the
|
||||
template-review step.
|
||||
|
||||
---
|
||||
|
||||
@@ -660,10 +678,12 @@ Once the API exists:
|
||||
rendering.
|
||||
- API failure or empty facets → render the messages deck in its on-disk
|
||||
order. No regression from today.
|
||||
- Selecting a template on the marketing home or `templates/` page can
|
||||
prefill the create flow's `selected*MethodIds` from the template's
|
||||
composition (closes the `?template=` no-op gap noted in
|
||||
`CreateFlowLayoutClient.tsx`). Out of scope for CR-88.
|
||||
- Selecting a template on the template-review page via **Customize**
|
||||
prefills the create flow's `selected*MethodIds` and core-values chip
|
||||
snapshot from the template's composition — see
|
||||
[`buildTemplateCustomizePrefill`](../../lib/create/applyTemplatePrefill.ts)
|
||||
and the `handleCustomizeTemplate` handler in
|
||||
`CreateFlowLayoutClient.tsx`. Shipped outside CR-88.
|
||||
- Recommendations **never hide** options — ranking only. Authors expect
|
||||
to see "all 32 decision-making patterns" with the matching ones
|
||||
surfaced first.
|
||||
|
||||
Reference in New Issue
Block a user