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

+54 -5
View File
@@ -50,6 +50,56 @@ export type FinalReviewCategoryNames = {
conflict: string;
};
const CANONICAL_FACET_ORDER: readonly TemplateFacetGroupKey[] = [
"coreValues",
"communication",
"membership",
"decisionApproaches",
"conflictManagement",
] as const;
function nameForGroup(
groupKey: TemplateFacetGroupKey,
names: FinalReviewCategoryNames,
): string {
switch (groupKey) {
case "coreValues":
return names.values;
case "communication":
return names.communication;
case "membership":
return names.membership;
case "decisionApproaches":
return names.decisions;
case "conflictManagement":
return names.conflict;
}
}
/** Always five section rows, in values-first order, including empty ones. */
export function ensureCanonicalFinalReviewRows(
rows: readonly FinalReviewCategoryRowDetailed[],
names: FinalReviewCategoryNames,
): FinalReviewCategoryRowDetailed[] {
const byGroup = new Map<TemplateFacetGroupKey, FinalReviewCategoryRowDetailed>();
for (const row of rows) {
if (row.groupKey == null) continue;
byGroup.set(row.groupKey, {
...row,
name: nameForGroup(row.groupKey, names),
});
}
return CANONICAL_FACET_ORDER.map((groupKey) => {
const existing = byGroup.get(groupKey);
if (existing) return existing;
return {
name: nameForGroup(groupKey, names),
groupKey,
entries: [],
};
});
}
type MethodPreset = { id: string; label: string };
/**
@@ -230,7 +280,7 @@ export function buildFinalReviewCategoryRowsDetailed(
if (entries.length === 0) continue;
rows.push({ name: s.categoryName, groupKey, entries });
}
return rows;
return ensureCanonicalFinalReviewRows(rows, names);
}
const rows: FinalReviewCategoryRowDetailed[] = [
@@ -276,7 +326,7 @@ export function buildFinalReviewCategoryRowsDetailed(
),
},
];
return rows.filter((r) => r.entries.length > 0);
return ensureCanonicalFinalReviewRows(rows, names);
}
/**
@@ -293,9 +343,8 @@ export function buildFinalReviewCategoryRowsDetailed(
* against the curated message `methods[]` list to get the display labels,
* matching what the user saw as chips in-flow.
*
* Empty categories are filtered out so the review card doesn't render headings
* with no chips. If nothing in state resolves to any chip, the caller should
* fall back to the demo categories shipped in `finalReview.json`.
* Empty categories stay on the card so add chips and flags can show. The five
* named rows always render, in values-first order.
*/
export function buildFinalReviewCategoriesFromState(
state: CreateFlowState,