From 3a9727bceb51967b4abd30ab4eecb2264546b8c7 Mon Sep 17 00:00:00 2001 From: adilallo <39313955+adilallo@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:05:37 -0600 Subject: [PATCH] New edit-rule page created --- app/(app)/create/CreateFlowLayoutClient.tsx | 69 +++++++++-- .../FinalReviewCommunityContextEditModal.tsx | 111 ++++++++++++++++++ app/(app)/create/hooks/useCreateFlowExit.ts | 62 ++++++++-- .../create/hooks/useCreateFlowFinalize.ts | 59 ++++++++-- .../create/screens/CreateFlowScreenView.tsx | 2 + .../screens/review/FinalReviewScreen.tsx | 47 +++++++- app/(app)/create/types.ts | 7 ++ .../utils/createFlowProportionProgress.ts | 3 + .../create/utils/createFlowScreenRegistry.ts | 6 + app/(app)/create/utils/flowSteps.ts | 8 +- app/api/rules/[id]/route.ts | 56 ++++++++- .../InlineTextButton/InlineTextButton.tsx | 15 ++- app/components/cards/Rule/Rule.container.tsx | 6 + app/components/cards/Rule/Rule.types.ts | 15 +++ app/components/cards/Rule/Rule.view.tsx | 49 ++++++-- lib/create/api.ts | 42 +++++++ .../publishedDocumentToCreateFlowState.ts | 100 ++++++++++++++++ lib/server/validation/createFlowSchemas.ts | 1 + .../create/reviewAndComplete/finalReview.json | 8 ++ tests/components/FinalReviewPage.test.tsx | 64 ++++++++++ tests/unit/Rule.test.jsx | 17 +++ .../unit/createFlowProportionProgress.test.ts | 4 + tests/unit/flowSteps.test.ts | 13 +- ...publishedDocumentToCreateFlowState.test.ts | 52 ++++++++ tests/unit/rulesByIdPatchRoute.test.ts | 111 ++++++++++++++++++ 25 files changed, 875 insertions(+), 52 deletions(-) create mode 100644 app/(app)/create/components/FinalReviewCommunityContextEditModal.tsx create mode 100644 lib/create/publishedDocumentToCreateFlowState.ts create mode 100644 tests/unit/publishedDocumentToCreateFlowState.test.ts create mode 100644 tests/unit/rulesByIdPatchRoute.test.ts diff --git a/app/(app)/create/CreateFlowLayoutClient.tsx b/app/(app)/create/CreateFlowLayoutClient.tsx index 60a816b..ad67618 100644 --- a/app/(app)/create/CreateFlowLayoutClient.tsx +++ b/app/(app)/create/CreateFlowLayoutClient.tsx @@ -32,6 +32,8 @@ import { clearAnonymousCreateFlowStorage, setTransferPendingFlag, } from "./utils/anonymousDraftStorage"; +import { createFlowStateFromPublishedRule } from "../../../lib/create/publishedDocumentToCreateFlowState"; +import { readLastPublishedRule } from "../../../lib/create/lastPublishedRule"; import { deleteServerDraft } from "../../../lib/create/api"; import messages from "../../../messages/en/index"; import { @@ -133,12 +135,23 @@ function CreateFlowLayoutContent({ const [communitySaveMagicLinkSuccess, setCommunitySaveMagicLinkSuccess] = useState(false); + const loginReturnPath = + currentStep === "edit-rule" + ? "/create/edit-rule?syncDraft=1" + : "/create/final-review?syncDraft=1"; + const { publishBannerMessage, setPublishBannerMessage, isPublishing, finalize: handleFinalize, - } = useCreateFlowFinalize({ state, router, openLogin }); + } = useCreateFlowFinalize({ + state, + router, + openLogin, + updateState, + loginReturnPath, + }); const { isTemplateReviewRoute, @@ -221,6 +234,34 @@ function CreateFlowLayoutContent({ } }, [currentStep]); + useEffect(() => { + if (currentStep !== "edit-rule") return; + const last = readLastPublishedRule(); + if (!last) { + router.replace("/create/completed"); + return; + } + const editingId = state.editingPublishedRuleId?.trim() ?? ""; + if (editingId.length > 0 && editingId !== last.id) { + router.replace("/create/completed"); + return; + } + const titleOk = + typeof state.title === "string" && state.title.trim().length > 0; + const sectionsClear = (state.sections?.length ?? 0) === 0; + /** Stale template `sections` (e.g. Values-only) makes final-review rows wrong; re-hydrate until cleared. */ + if (titleOk && editingId === last.id && sectionsClear) { + return; + } + updateState(createFlowStateFromPublishedRule(last)); + }, [ + currentStep, + router, + updateState, + state.editingPublishedRuleId, + state.title, + ]); + const handleCommunitySaveMagicLinkSubmit = useCallback(async () => { setCommunitySaveMagicLinkError(null); setCommunitySaveMagicLinkSuccess(false); @@ -260,7 +301,8 @@ function CreateFlowLayoutContent({ const isCompletedStep = currentStep === "completed"; const isRightRailStep = currentStep === "decision-approaches"; - const isFinalReviewStep = currentStep === "final-review"; + const isFinalReviewLike = + currentStep === "final-review" || currentStep === "edit-rule"; const isCardLayoutStep = createFlowStepUsesCardLayout(currentStep); /** Two-column select / right-rail: below `lg` main scrolls; at `lg+` only the right column scrolls. */ const isSelectSplitScrollStep = @@ -275,7 +317,7 @@ function CreateFlowLayoutContent({ ? "items-stretch overflow-y-auto md:overflow-hidden" : isSelectSplitScrollStep ? "items-start justify-start overflow-y-auto max-lg:overflow-y-auto lg:min-h-0 lg:items-stretch lg:overflow-hidden" - : isFinalReviewStep || isCardLayoutStep || isTemplateReviewRoute + : isFinalReviewLike || isCardLayoutStep || isTemplateReviewRoute ? "items-start justify-center overflow-y-auto" : "items-start justify-center overflow-y-auto md:items-center"; @@ -289,7 +331,8 @@ function CreateFlowLayoutContent({ : "max-md:flex-col max-md:items-center"; const mainResponsiveLayout = `${mainMaxMdCross} ${mainMaxMdJustify} md:flex-row md:justify-center`; const saveDraftOnExit = - Boolean(sessionUser) && stepIdx >= SAVE_EXIT_FROM_STEP_INDEX; + Boolean(sessionUser) && + (stepIdx >= SAVE_EXIT_FROM_STEP_INDEX || currentStep === "edit-rule"); const proportionBarProgress = getProportionBarProgressForCreateFlowStep( currentStep, @@ -408,7 +451,15 @@ function CreateFlowLayoutContent({ saveDraftOnExit={saveDraftOnExit} onEdit={ isCompletedStep - ? () => router.push("/create/final-review") + ? () => { + const last = readLastPublishedRule(); + if (!last) return; + updateState({ + editingPublishedRuleId: last.id, + sections: [], + }); + router.push("/create/edit-rule"); + } : undefined } onExit={(opts) => void handleExit(opts)} @@ -425,7 +476,7 @@ function CreateFlowLayoutContent({ {!isCompletedStep && ( {footer[customRuleConfirmFooter.footerMessageKey]} - ) : nextStep ? ( + ) : nextStep || isFinalReviewLike ? (