diff --git a/.cursor/rules/create-flow.mdc b/.cursor/rules/create-flow.mdc index 9c9a417..fb76949 100644 --- a/.cursor/rules/create-flow.mdc +++ b/.cursor/rules/create-flow.mdc @@ -39,9 +39,16 @@ file are a smell once they're used more than once. ## Copy & data -- Step copy lives in `messages/en/create/.json`, wired into - `messages/en/index.ts` under the `create:` namespace (see - `localization.mdc` for the standard pattern). +- Step copy lives in `messages/en/create//.json` where + `` is one of `community`, `customRule`, `reviewAndComplete` + (matches Figma stages — see `docs/create-flow.md`). Cross-cutting chrome + (`footer.json`, `topNav.json`, `draftHydration.json`, + `templateReview.json`) and shared layout-shell strings (`select.json`, + `text.json`, `upload.json`) live at the `create/` root. Wire each new + JSON into `messages/en/index.ts` under the matching `create..*` + namespace (see `localization.mdc`). +- Modal `sections` defaults are DB-shaped seed placeholders, not UI + constants — expect replacement with live data. - Modal `sections` defaults are DB-shaped seed placeholders, not UI constants — expect replacement with live data. diff --git a/.cursor/rules/localization.mdc b/.cursor/rules/localization.mdc index 467d5bd..b141dd1 100644 --- a/.cursor/rules/localization.mdc +++ b/.cursor/rules/localization.mdc @@ -15,9 +15,13 @@ notation). Never hard-code user-facing strings in components. - `messages/en/.json` for single-file areas (`common.json`, `navigation.json`, `metadata.json`). - `messages/en//.json` for areas with multiple buckets: - `components/*.json`, `pages/*.json`, `create/*.json`. One JSON per - component / page / create-flow step — don't shoehorn unrelated copy into - a shared file. + `components/*.json`, `pages/*.json`. One JSON per component / page — + don't shoehorn unrelated copy into a shared file. +- `messages/en/create//.json` — wizard steps grouped by Figma + stage (`community`, `customRule`, `reviewAndComplete`). Cross-cutting + chrome (footer, top nav, draft hydration, template review) and shared + layout-shell strings (`select.json`, `text.json`, `upload.json`) live at + the `create/` root. - Optional `"_comment"` at the top of a JSON documents the bundle's purpose. ## Registration — required @@ -25,12 +29,14 @@ notation). Never hard-code user-facing strings in components. Every new JSON must be wired into `messages/en/index.ts`: ```typescript -import createConflictManagement from "./create/conflictManagement.json"; +import createConflictManagement from "./create/customRule/conflictManagement.json"; export default { // … create: { - conflictManagement: createConflictManagement, + customRule: { + conflictManagement: createConflictManagement, + }, }, }; ``` @@ -44,7 +50,7 @@ step means consumers can't read your strings and TypeScript won't flag the gap. import { useMessages } from "../contexts/MessagesContext"; const m = useMessages(); -const title = m.create.conflictManagement.page.compactTitle; // fully typed +const title = m.create.customRule.conflictManagement.page.compactTitle; // fully typed ``` Use `useTranslation(namespace)` only when you need dot-path lookup by dynamic diff --git a/app/(app)/create/CreateFlowLayoutClient.tsx b/app/(app)/create/CreateFlowLayoutClient.tsx index 6448898..36d6f24 100644 --- a/app/(app)/create/CreateFlowLayoutClient.tsx +++ b/app/(app)/create/CreateFlowLayoutClient.tsx @@ -28,7 +28,11 @@ import { requestMagicLink, } from "../../../lib/create/api"; import { safeInternalPath } from "../../../lib/safeInternalPath"; -import { setTransferPendingFlag } from "./utils/anonymousDraftStorage"; +import { + clearAnonymousCreateFlowStorage, + setTransferPendingFlag, +} from "./utils/anonymousDraftStorage"; +import { deleteServerDraft } from "../../../lib/create/api"; import { writeLastPublishedRule } from "../../../lib/create/lastPublishedRule"; import { fetchTemplateBySlug, @@ -64,10 +68,14 @@ function CreateFlowSessionShell({ children }: { children: ReactNode }) { }, []); const sessionResolved = sessionUser !== undefined; - const enableAnonymousPersistence = sessionResolved && sessionUser === null; + // Mirror in-progress draft to localStorage for ALL visitors once we know who + // they are. Refresh-survival is the same UX for guest and signed-in users; + // signed-in users additionally get an explicit "Save & Exit" that PUTs to + // the server (handled in `useCreateFlowExit`). + const enableLocalDraftMirroring = sessionResolved; return ( - + setPublishBannerMessage(null)} className="w-full" @@ -622,7 +644,7 @@ function CreateFlowLayoutContent({ goToNextStep(); }} > - {footer.confirmRightRail} + {footer.confirmDecisionApproaches} ) : currentStep === "conflict-management" && nextStep ? (