Show the whole Rule on one review card, with quiet flags for missing cards and Continue once each question has one.

This commit is contained in:
adilallo committed 2026-11-06 08:36:34 -07:00
1 parent cc878e3c19
commit 6e2e1915ae
30 files changed
+571 -218

No files matched your search

@@ -1,5 +1,10 @@
import type footerMessages from "../../../../messages/en/create/footer.json";
import type { CreateFlowStep } from "../types";
import {
buildFinalReviewCategoryRowsDetailed,
type FinalReviewCategoryNames,
} from "../../../../lib/create/buildFinalReviewCategories";
import type { TemplateFacetGroupKey } from "../../../../lib/create/templateReviewMapping";
import type { CreateFlowState, CreateFlowStep } from "../types";
type FooterMessages = typeof footerMessages;
@@ -9,9 +14,10 @@ type FooterMessages = typeof footerMessages;
* fires `goToNextStep` for steps without a bespoke footer). Steps absent
* from this map fall back to `footer.next`.
*
* `final-review` is handled separately by the caller because its label
* also depends on the in-flight publish flag (`publishButtonPublishing`
* vs `publishCommunityRule`).
* `final-review` uses Continue (gated by {@link isFinalReviewContinueBlocked}).
* `edit-rule` is handled separately by the caller because its label also
* depends on the in-flight publish flag (`publishButtonPublishing` vs
* `publishCommunityRule`).
*/
const DEFAULT_FOOTER_LABEL_BY_STEP: ReadonlyMap<
CreateFlowStep,
@@ -53,10 +59,42 @@ export function isCommunitySizeStepBlocked(
return !hasNonEmptyId(selectedCommunitySizeIds);
}
const FINAL_REVIEW_BLOCK_NAMES: FinalReviewCategoryNames = {
values: "values",
communication: "communication",
membership: "membership",
decisions: "decisions",
conflict: "conflict",
};
const FINAL_REVIEW_REQUIRED_GROUPS: readonly TemplateFacetGroupKey[] = [
"communication",
"membership",
"decisionApproaches",
"conflictManagement",
] as const;
/**
* Continue on final review waits for a community name and at least one card
* on each of the four questions. Skipped values do not block.
*/
export function isFinalReviewContinueBlocked(state: CreateFlowState): boolean {
const title = typeof state.title === "string" ? state.title.trim() : "";
if (title.length === 0) return true;
const rows = buildFinalReviewCategoryRowsDetailed(
state,
FINAL_REVIEW_BLOCK_NAMES,
);
return FINAL_REVIEW_REQUIRED_GROUPS.some((groupKey) => {
const row = rows.find((candidate) => candidate.groupKey === groupKey);
return !row || row.entries.length === 0;
});
}
/**
* Resolve the localized label for the default "next-step" footer button.
* Returns the per-step override when one is registered, otherwise
* `footer.next`. Caller still owns the `final-review` special case.
* `footer.next`. Caller still owns the `final-review` / `edit-rule` special case.
*/
export function getDefaultFooterLabel(
step: CreateFlowStep | null | undefined,