Clear leftover setup answers on template paths that skip those questions, and treat Continue as an edit so restored ticks are not overwritten.

This commit is contained in:
adilallo committed 2026-11-05 21:02:04 -07:00
1 parent bdaf1818d9
commit cec83eb27f
3 files changed
+43 -4

No files matched your search

@@ -999,6 +999,7 @@ function CreateFlowLayoutContent({
} }
className={CREATE_FLOW_FOOTER_BUTTON_CLASS} className={CREATE_FLOW_FOOTER_BUTTON_CLASS}
onClick={() => { onClick={() => {
markCreateFlowInteraction();
goToNextStep(); goToNextStep();
}} }}
> >
@@ -30,7 +30,9 @@ export type UseTemplateReviewActionsResult = {
* Customize: apply the template's selections onto state and route to * Customize: apply the template's selections onto state and route to
* `/create/core-values` (if community name is set) or `/create/informational` * `/create/core-values` (if community name is set) or `/create/informational`
* with a `pendingTemplateAction` pin so `/create/review` can later replace * with a `pendingTemplateAction` pin so `/create/review` can later replace
* itself with `/create/core-values`. * itself with `/create/core-values`. A named community skips setup
* questions, so leftover setup answers are dropped and cannot change
* suggested cards.
*/ */
handleCustomize: () => Promise<void>; handleCustomize: () => Promise<void>;
/** /**
@@ -39,8 +41,9 @@ export type UseTemplateReviewActionsResult = {
* Customize) so drilling from final-review via + shows selected cards, drop * Customize) so drilling from final-review via + shows selected cards, drop
* the Values row from `state.sections`. Direct template entry routes to * the Values row from `state.sections`. Direct template entry routes to
* `/create/community-name` with a pin so Next/Back collect only name → * `/create/community-name` with a pin so Next/Back collect only name →
* description → photo. In-flow (`?fromFlow=1`, community steps already done) * description → photo, and drops leftover setup answers along with the
* routes to `/create/confirm-stakeholders`. * other identity fields. In-flow (`?fromFlow=1`, community steps already
* done) routes to `/create/confirm-stakeholders` and keeps those answers.
*/ */
handleUseWithoutChanges: () => Promise<void>; handleUseWithoutChanges: () => Promise<void>;
}; };
@@ -128,7 +131,7 @@ export function useTemplateReviewActions({
}, },
templateReviewBackSlug: undefined, templateReviewBackSlug: undefined,
...(hasCommunityName ...(hasCommunityName
? { pendingTemplateAction: undefined } ? { pendingTemplateAction: undefined, setupTraits: undefined }
: { : {
pendingTemplateAction: { pendingTemplateAction: {
slug: templateReviewSlug, slug: templateReviewSlug,
@@ -256,6 +259,7 @@ export function useTemplateReviewActions({
communityAvatarUrl: undefined, communityAvatarUrl: undefined,
currentStep: undefined, currentStep: undefined,
templateReviewEntryFromCreateFlow: undefined, templateReviewEntryFromCreateFlow: undefined,
setupTraits: undefined,
pendingTemplateAction: { pendingTemplateAction: {
slug: templateReviewSlug, slug: templateReviewSlug,
mode: "useWithoutChanges", mode: "useWithoutChanges",
@@ -91,6 +91,7 @@ describe("useTemplateReviewActions", () => {
title: "Neighborhood", title: "Neighborhood",
communityContext: "Stale description", communityContext: "Stale description",
currentStep: "confirm-stakeholders", currentStep: "confirm-stakeholders",
setupTraits: { employer: true, network: false },
}); });
}, },
); );
@@ -104,6 +105,7 @@ describe("useTemplateReviewActions", () => {
expect(applied?.title).toBeUndefined(); expect(applied?.title).toBeUndefined();
expect(applied?.communityContext).toBeUndefined(); expect(applied?.communityContext).toBeUndefined();
expect(applied?.currentStep).toBeUndefined(); expect(applied?.currentStep).toBeUndefined();
expect(applied?.setupTraits).toBeUndefined();
expect(applied?.pendingTemplateAction?.mode).toBe("useWithoutChanges"); expect(applied?.pendingTemplateAction?.mode).toBe("useWithoutChanges");
}); });
@@ -114,6 +116,7 @@ describe("useTemplateReviewActions", () => {
title: "Neighborhood", title: "Neighborhood",
communityContext: "We meet weekly", communityContext: "We meet weekly",
templateReviewEntryFromCreateFlow: true, templateReviewEntryFromCreateFlow: true,
setupTraits: { employer: true },
}); });
}, },
); );
@@ -129,7 +132,38 @@ describe("useTemplateReviewActions", () => {
expect(router.push).toHaveBeenCalledWith("/create/confirm-stakeholders"); expect(router.push).toHaveBeenCalledWith("/create/confirm-stakeholders");
expect(applied?.title).toBe("Neighborhood"); expect(applied?.title).toBe("Neighborhood");
expect(applied?.communityContext).toBe("We meet weekly"); expect(applied?.communityContext).toBe("We meet weekly");
expect(applied?.setupTraits).toEqual({ employer: true });
expect(applied?.pendingTemplateAction).toBeUndefined(); expect(applied?.pendingTemplateAction).toBeUndefined();
expect(applied?.templateReviewBackSlug).toBe("mutual-aid-mondays"); expect(applied?.templateReviewBackSlug).toBe("mutual-aid-mondays");
}); });
it("customize with a community name drops leftover setup answers", async () => {
const { result } = renderActions({
title: "Neighborhood",
setupTraits: { employer: true },
});
await act(async () => {
await result.current.handleCustomize();
});
expect(router.push).toHaveBeenCalledWith("/create/core-values");
expect(updateState).toHaveBeenCalledWith(
expect.objectContaining({ setupTraits: undefined }),
);
});
it("customize without a community name leaves setup answers for the questionnaire", async () => {
const { result } = renderActions({
setupTraits: { employer: true },
});
await act(async () => {
await result.current.handleCustomize();
});
expect(router.push).toHaveBeenCalledWith("/create/informational");
const patch = updateState.mock.calls[0]?.[0] as CreateFlowState;
expect(patch).not.toHaveProperty("setupTraits");
});
}); });