Implement create custom recommendations

This commit is contained in:
adilallo
2026-04-20 12:41:10 -06:00
parent e9dab04b34
commit 45bbbb8a35
75 changed files with 6403 additions and 1452 deletions
@@ -35,7 +35,7 @@ export function CreateFlowScreenView({
case "community-name":
return (
<CreateFlowTextFieldScreen
messageNamespace="create.communityName"
messageNamespace="create.community.communityName"
stateField="title"
maxLength={48}
/>
@@ -45,7 +45,7 @@ export function CreateFlowScreenView({
case "community-context":
return (
<CreateFlowTextFieldScreen
messageNamespace="create.communityContext"
messageNamespace="create.community.communityContext"
stateField="communityContext"
maxLength={48}
mainAlign="center"
@@ -58,7 +58,7 @@ export function CreateFlowScreenView({
case "community-save":
return (
<CreateFlowTextFieldScreen
messageNamespace="create.communitySave"
messageNamespace="create.community.communitySave"
stateField="communitySaveEmail"
maxLength={254}
mainAlign="center"
@@ -13,6 +13,11 @@ import { useState, useCallback, useMemo } from "react";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import {
deriveCompactCards,
rankMethodsByScore,
useFacetRecommendations,
} from "../../hooks/useFacetRecommendations";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import CardStack from "../../../../components/utility/CardStack";
import Create from "../../../../components/modals/Create";
@@ -24,10 +29,6 @@ import {
} from "../../components/createFlowLayoutTokens";
import ModalTextAreaField from "../../components/ModalTextAreaField";
const IN_PERSON_CARD_ID = "in-person-meetings";
const SIGNAL_CARD_ID = "signal";
const VIDEO_MEETINGS_CARD_ID = "video-meetings";
const SECTION_FIELDS = [
"corePrinciple",
"logisticsAdmin",
@@ -35,16 +36,6 @@ const SECTION_FIELDS = [
] as const;
type SectionField = (typeof SECTION_FIELDS)[number];
const COMMUNICATION_CARD_ORDER = [
IN_PERSON_CARD_ID,
SIGNAL_CARD_ID,
VIDEO_MEETINGS_CARD_ID,
"4",
"5",
"6",
"7",
] as const;
function AddPlatformModalContent({
platformCardId,
}: {
@@ -52,15 +43,13 @@ function AddPlatformModalContent({
}) {
const { markCreateFlowInteraction } = useCreateFlow();
const m = useMessages();
const comm = m.create.communication;
const modal =
platformCardId in comm.modals
? comm.modals[platformCardId as keyof typeof comm.modals]
: null;
const defaults = modal?.sections ?? {
corePrinciple: "",
logisticsAdmin: "",
codeOfConduct: "",
const comm = m.create.customRule.communication;
const method = comm.methods.find((entry) => entry.id === platformCardId);
const sections = method?.sections;
const defaults: Record<SectionField, string> = {
corePrinciple: sections?.corePrinciple ?? "",
logisticsAdmin: sections?.logisticsAdmin ?? "",
codeOfConduct: sections?.codeOfConduct ?? "",
};
const [sectionValues, setSectionValues] = useState<
@@ -96,7 +85,7 @@ function AddPlatformModalContent({
export function CommunicationMethodsScreen() {
const m = useMessages();
const comm = m.create.communication;
const comm = m.create.customRule.communication;
const mdUp = useCreateFlowMdUp();
const { state, updateState, markCreateFlowInteraction } = useCreateFlow();
const [expanded, setExpanded] = useState(false);
@@ -112,18 +101,32 @@ export function CommunicationMethodsScreen() {
[updateState],
);
const { scoresBySlug, hasAnyFacets } =
useFacetRecommendations("communication");
const rankedMethods = useMemo(
() => rankMethodsByScore(comm.methods, scoresBySlug),
[comm.methods, scoresBySlug],
);
const { compactCardIds, recommendedIds } = useMemo(
() => deriveCompactCards(rankedMethods, scoresBySlug, hasAnyFacets, 5),
[rankedMethods, scoresBySlug, hasAnyFacets],
);
const sampleCards = useMemo(
() =>
COMMUNICATION_CARD_ORDER.map((id) => {
const row = comm.cards[id as keyof typeof comm.cards];
return {
id,
label: row.label,
supportText: row.supportText,
recommended: true,
};
}),
[comm],
rankedMethods.map((entry) => ({
id: entry.id,
label: entry.label,
supportText: entry.supportText,
recommended: recommendedIds.has(entry.id),
})),
[rankedMethods, recommendedIds],
);
const methodById = useMemo(
() => new Map(rankedMethods.map((entry) => [entry.id, entry])),
[rankedMethods],
);
const title = expanded ? comm.page.expandedTitle : comm.page.compactTitle;
@@ -157,25 +160,10 @@ export function CommunicationMethodsScreen() {
};
}
if (pendingCardId in comm.modals) {
const modal = comm.modals[pendingCardId as keyof typeof comm.modals];
return {
title: modal.title,
description: modal.description,
nextButtonText: comm.addPlatform.nextButtonText,
showBackButton: false as const,
currentStep: undefined,
totalSteps: undefined,
};
}
const cardRow =
pendingCardId in comm.cards
? comm.cards[pendingCardId as keyof typeof comm.cards]
: null;
const method = methodById.get(pendingCardId);
return {
title: cardRow?.label ?? comm.confirmModal.title,
description: cardRow?.supportText ?? comm.confirmModal.description,
title: method?.label ?? comm.confirmModal.title,
description: method?.supportText ?? comm.confirmModal.description,
nextButtonText: comm.addPlatform.nextButtonText,
showBackButton: false as const,
currentStep: undefined,
@@ -235,7 +223,8 @@ export function CommunicationMethodsScreen() {
}}
hasMore={true}
toggleLabel={comm.page.seeAllLink}
compactRecommendedLimit={3}
compactRecommendedLimit={5}
compactCardIds={compactCardIds}
compactDesktopLayout="flexWrap"
headerLockupSize={mdUp ? "L" : "M"}
/>
@@ -7,7 +7,7 @@
* Card click opens the Figma "Add Approach" create modal (node `20874-172292`) with four
* controls: Core Principle, Applicable Scope (capsules), Process Protocol, and Restoration
* & Fallbacks. Section defaults are sourced from
* `messages/en/create/conflictManagement.json` and will be replaced with DB-driven
* `messages/en/create/customRule/conflictManagement.json` and will be replaced with DB-driven
* content; labels are hard-coded per the Figma design.
*/
@@ -15,6 +15,11 @@ import { useState, useCallback, useMemo } from "react";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import {
deriveCompactCards,
rankMethodsByScore,
useFacetRecommendations,
} from "../../hooks/useFacetRecommendations";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import CardStack from "../../../../components/utility/CardStack";
import Create from "../../../../components/modals/Create";
@@ -27,17 +32,6 @@ import {
import ModalTextAreaField from "../../components/ModalTextAreaField";
import ApplicableScopeField from "../../components/ApplicableScopeField";
const CONFLICT_CARD_ORDER = [
"peer-mediation",
"conflict-resolution-council",
"facilitated-negotiation",
"ad-hoc-arbitration",
"conflict-workshops",
"6",
"7",
"8",
] as const;
type ConflictModalSections = {
corePrinciple: string;
applicableScope: string[];
@@ -53,12 +47,9 @@ function AddConflictApproachModalContent({
}) {
const { markCreateFlowInteraction } = useCreateFlow();
const m = useMessages();
const cm = m.create.conflictManagement;
const modal =
approachCardId in cm.modals
? cm.modals[approachCardId as keyof typeof cm.modals]
: null;
const modalSections = modal?.sections;
const cm = m.create.customRule.conflictManagement;
const method = cm.methods.find((entry) => entry.id === approachCardId);
const modalSections = method?.sections;
const defaults: ConflictModalSections = {
corePrinciple: modalSections?.corePrinciple ?? "",
applicableScope: modalSections?.applicableScope ?? [],
@@ -126,7 +117,7 @@ function AddConflictApproachModalContent({
export function ConflictManagementScreen() {
const m = useMessages();
const cm = m.create.conflictManagement;
const cm = m.create.customRule.conflictManagement;
const mdUp = useCreateFlowMdUp();
const { state, updateState, markCreateFlowInteraction } = useCreateFlow();
const [expanded, setExpanded] = useState(false);
@@ -142,18 +133,32 @@ export function ConflictManagementScreen() {
[updateState],
);
const { scoresBySlug, hasAnyFacets } =
useFacetRecommendations("conflictManagement");
const rankedMethods = useMemo(
() => rankMethodsByScore(cm.methods, scoresBySlug),
[cm.methods, scoresBySlug],
);
const { compactCardIds, recommendedIds } = useMemo(
() => deriveCompactCards(rankedMethods, scoresBySlug, hasAnyFacets, 5),
[rankedMethods, scoresBySlug, hasAnyFacets],
);
const sampleCards = useMemo(
() =>
CONFLICT_CARD_ORDER.map((id) => {
const row = cm.cards[id as keyof typeof cm.cards];
return {
id,
label: row.label,
supportText: row.supportText,
recommended: true,
};
}),
[cm],
rankedMethods.map((entry) => ({
id: entry.id,
label: entry.label,
supportText: entry.supportText,
recommended: recommendedIds.has(entry.id),
})),
[rankedMethods, recommendedIds],
);
const methodById = useMemo(
() => new Map(rankedMethods.map((entry) => [entry.id, entry])),
[rankedMethods],
);
const title = expanded ? cm.page.expandedTitle : cm.page.compactTitle;
@@ -187,25 +192,10 @@ export function ConflictManagementScreen() {
};
}
if (pendingCardId in cm.modals) {
const modal = cm.modals[pendingCardId as keyof typeof cm.modals];
return {
title: modal.title,
description: modal.description,
nextButtonText: cm.addApproach.nextButtonText,
showBackButton: false as const,
currentStep: undefined,
totalSteps: undefined,
};
}
const cardRow =
pendingCardId in cm.cards
? cm.cards[pendingCardId as keyof typeof cm.cards]
: null;
const method = methodById.get(pendingCardId);
return {
title: cardRow?.label ?? cm.confirmModal.title,
description: cardRow?.supportText ?? cm.confirmModal.description,
title: method?.label ?? cm.confirmModal.title,
description: method?.supportText ?? cm.confirmModal.description,
nextButtonText: cm.addApproach.nextButtonText,
showBackButton: false as const,
currentStep: undefined,
@@ -266,6 +256,7 @@ export function ConflictManagementScreen() {
hasMore={true}
toggleLabel={cm.page.seeAllLink}
compactRecommendedLimit={5}
compactCardIds={compactCardIds}
compactDesktopLayout="pyramidFive"
headerLockupSize={mdUp ? "L" : "M"}
/>
@@ -7,7 +7,7 @@
* Card click opens the Figma create modal (node `20858-13948`) with three
* editable sections — Eligibility & Philosophy, Joining Process, and
* Expectations & Removal. Section defaults come from
* `messages/en/create/membership.json` and will be replaced with DB-driven
* `messages/en/create/customRule/membership.json` and will be replaced with DB-driven
* content.
*/
@@ -15,6 +15,11 @@ import { useState, useCallback, useMemo } from "react";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import {
deriveCompactCards,
rankMethodsByScore,
useFacetRecommendations,
} from "../../hooks/useFacetRecommendations";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import CardStack from "../../../../components/utility/CardStack";
import Create from "../../../../components/modals/Create";
@@ -33,17 +38,6 @@ const SECTION_FIELDS = [
] as const;
type SectionField = (typeof SECTION_FIELDS)[number];
const MEMBERSHIP_CARD_ORDER = [
"open-access",
"orientation-required",
"invitation-only",
"contribution-based",
"mentorship",
"6",
"7",
"8",
] as const;
function AddMembershipModalContent({
membershipCardId,
}: {
@@ -51,15 +45,13 @@ function AddMembershipModalContent({
}) {
const { markCreateFlowInteraction } = useCreateFlow();
const m = useMessages();
const mem = m.create.membership;
const modal =
membershipCardId in mem.modals
? mem.modals[membershipCardId as keyof typeof mem.modals]
: null;
const defaults = modal?.sections ?? {
eligibility: "",
joiningProcess: "",
expectations: "",
const mem = m.create.customRule.membership;
const method = mem.methods.find((entry) => entry.id === membershipCardId);
const sections = method?.sections;
const defaults: Record<SectionField, string> = {
eligibility: sections?.eligibility ?? "",
joiningProcess: sections?.joiningProcess ?? "",
expectations: sections?.expectations ?? "",
};
const [sectionValues, setSectionValues] = useState<
@@ -95,7 +87,7 @@ function AddMembershipModalContent({
export function MembershipMethodsScreen() {
const m = useMessages();
const mem = m.create.membership;
const mem = m.create.customRule.membership;
const mdUp = useCreateFlowMdUp();
const { state, updateState, markCreateFlowInteraction } = useCreateFlow();
const [expanded, setExpanded] = useState(false);
@@ -111,18 +103,32 @@ export function MembershipMethodsScreen() {
[updateState],
);
const { scoresBySlug, hasAnyFacets } =
useFacetRecommendations("membership");
const rankedMethods = useMemo(
() => rankMethodsByScore(mem.methods, scoresBySlug),
[mem.methods, scoresBySlug],
);
const { compactCardIds, recommendedIds } = useMemo(
() => deriveCompactCards(rankedMethods, scoresBySlug, hasAnyFacets, 5),
[rankedMethods, scoresBySlug, hasAnyFacets],
);
const sampleCards = useMemo(
() =>
MEMBERSHIP_CARD_ORDER.map((id) => {
const row = mem.cards[id as keyof typeof mem.cards];
return {
id,
label: row.label,
supportText: row.supportText,
recommended: true,
};
}),
[mem],
rankedMethods.map((entry) => ({
id: entry.id,
label: entry.label,
supportText: entry.supportText,
recommended: recommendedIds.has(entry.id),
})),
[rankedMethods, recommendedIds],
);
const methodById = useMemo(
() => new Map(rankedMethods.map((entry) => [entry.id, entry])),
[rankedMethods],
);
const title = expanded ? mem.page.expandedTitle : mem.page.compactTitle;
@@ -156,25 +162,10 @@ export function MembershipMethodsScreen() {
};
}
if (pendingCardId in mem.modals) {
const modal = mem.modals[pendingCardId as keyof typeof mem.modals];
return {
title: modal.title,
description: modal.description,
nextButtonText: mem.addPlatform.nextButtonText,
showBackButton: false as const,
currentStep: undefined,
totalSteps: undefined,
};
}
const cardRow =
pendingCardId in mem.cards
? mem.cards[pendingCardId as keyof typeof mem.cards]
: null;
const method = methodById.get(pendingCardId);
return {
title: cardRow?.label ?? mem.confirmModal.title,
description: cardRow?.supportText ?? mem.confirmModal.description,
title: method?.label ?? mem.confirmModal.title,
description: method?.supportText ?? mem.confirmModal.description,
nextButtonText: mem.addPlatform.nextButtonText,
showBackButton: false as const,
currentStep: undefined,
@@ -235,6 +226,7 @@ export function MembershipMethodsScreen() {
hasMore={true}
toggleLabel={mem.page.seeAllLink}
compactRecommendedLimit={5}
compactCardIds={compactCardIds}
compactDesktopLayout="pyramidFive"
headerLockupSize={mdUp ? "L" : "M"}
/>
@@ -17,7 +17,7 @@ import {
export function CompletedScreen() {
const mdUp = useCreateFlowMdUp();
const m = useMessages();
const completed = m.create.completed;
const completed = m.create.reviewAndComplete.completed;
const fallbackSections = useMemo(
() =>
@@ -14,7 +14,7 @@ import { CREATE_FLOW_MD_UP_COLUMN_MAX_CLASS } from "../../components/createFlowL
*/
export function InformationalScreen() {
const mdUp = useCreateFlowMdUp();
const copy = useMessages().create.informational;
const copy = useMessages().create.community.informational;
const items = [
{
@@ -14,7 +14,7 @@ import {
/** Create Community review — Figma `19706:12135` (`/create/review`; two columns from `lg:`; column caps in `createFlowLayoutTokens`). */
export function CommunityReviewScreen() {
const lgUp = useCreateFlowLgUp();
const t = useTranslation("create.review");
const t = useTranslation("create.community.review");
const { state } = useCreateFlow();
const cardTitle =
@@ -27,12 +27,12 @@ function buildFinalReviewCategories(
export function FinalReviewScreen() {
const { state } = useCreateFlow();
const mdUp = useCreateFlowMdUp();
const t = useTranslation("create.finalReview");
const t = useTranslation("create.reviewAndComplete.finalReview");
const m = useMessages();
const finalReviewCategories = useMemo(
() => buildFinalReviewCategories(m.create.finalReview.categories),
[m.create.finalReview.categories],
() => buildFinalReviewCategories(m.create.reviewAndComplete.finalReview.categories),
[m.create.reviewAndComplete.finalReview.categories],
);
const ruleCardTitle = useMemo(() => {
@@ -9,8 +9,9 @@
*
* Card click opens the Figma "Add Approach" create modal (node `20870-72155`) with five controls:
* Core Principle, Applicable Scope, Step-by-Step Instructions, Consensus Level, and Objections &
* Deadlocks. Section defaults are sourced from `messages/en/create/rightRail.json` and will be
* replaced with DB-driven content; labels are hard-coded per the Figma design.
* Deadlocks. Section defaults are sourced from `messages/en/create/customRule/decisionApproaches.json` (read
* via `m.create.customRule.decisionApproaches`) and will be replaced with DB-driven content; labels are
* hard-coded per the Figma design.
*/
import { useState, useCallback, useMemo } from "react";
@@ -24,6 +25,11 @@ import type { CardStackItem } from "../../../../components/utility/CardStack/Car
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { useCreateFlowMdUp } from "../../hooks/useCreateFlowMdUp";
import {
deriveCompactCards,
rankMethodsByScore,
useFacetRecommendations,
} from "../../hooks/useFacetRecommendations";
import { CreateFlowTwoColumnSelectShell } from "../../components/CreateFlowTwoColumnSelectShell";
import ModalTextAreaField from "../../components/ModalTextAreaField";
import ApplicableScopeField from "../../components/ApplicableScopeField";
@@ -49,12 +55,9 @@ function AddDecisionApproachModalContent({
}) {
const { markCreateFlowInteraction } = useCreateFlow();
const m = useMessages();
const rr = m.create.rightRail;
const modal =
approachCardId in rr.modals
? rr.modals[approachCardId as keyof typeof rr.modals]
: null;
const modalSections = modal?.sections;
const da = m.create.customRule.decisionApproaches;
const method = da.methods.find((entry) => entry.id === approachCardId);
const modalSections = method?.sections;
const defaults: RightRailModalSections = {
corePrinciple: modalSections?.corePrinciple ?? "",
applicableScope: modalSections?.applicableScope ?? [],
@@ -87,13 +90,13 @@ function AddDecisionApproachModalContent({
return (
<div className="flex flex-col gap-6">
<ModalTextAreaField
label={rr.sectionHeadings.corePrinciple}
label={da.sectionHeadings.corePrinciple}
value={sections.corePrinciple}
onChange={(v) => patch("corePrinciple", v)}
/>
<ApplicableScopeField
label={rr.sectionHeadings.applicableScope}
addLabel={rr.scopeAddButtonLabel}
label={da.sectionHeadings.applicableScope}
addLabel={da.scopeAddButtonLabel}
scopes={sections.applicableScope}
selectedScopes={sections.selectedApplicableScope}
onToggleScope={(scope) =>
@@ -109,12 +112,12 @@ function AddDecisionApproachModalContent({
}
/>
<ModalTextAreaField
label={rr.sectionHeadings.stepByStepInstructions}
label={da.sectionHeadings.stepByStepInstructions}
value={sections.stepByStepInstructions}
onChange={(v) => patch("stepByStepInstructions", v)}
/>
<IncrementerBlock
label={rr.sectionHeadings.consensusLevel}
label={da.sectionHeadings.consensusLevel}
value={sections.consensusLevel}
min={CONSENSUS_LEVEL_MIN}
max={CONSENSUS_LEVEL_MAX}
@@ -125,7 +128,7 @@ function AddDecisionApproachModalContent({
incrementAriaLabel="Increase consensus level"
/>
<ModalTextAreaField
label={rr.sectionHeadings.objectionsDeadlocks}
label={da.sectionHeadings.objectionsDeadlocks}
value={sections.objectionsDeadlocks}
onChange={(v) => patch("objectionsDeadlocks", v)}
/>
@@ -135,7 +138,7 @@ function AddDecisionApproachModalContent({
export function DecisionApproachesScreen() {
const m = useMessages();
const rr = m.create.rightRail;
const da = m.create.customRule.decisionApproaches;
const mdUp = useCreateFlowMdUp();
const { state, updateState, markCreateFlowInteraction } = useCreateFlow();
const [messageBoxCheckedIds, setMessageBoxCheckedIds] = useState<string[]>(
@@ -156,41 +159,53 @@ export function DecisionApproachesScreen() {
const messageBoxItems: InfoMessageBoxItem[] = useMemo(
() =>
rr.messageBox.items.map((item) => ({
da.messageBox.items.map((item) => ({
id: item.id,
label: item.label,
})),
[rr.messageBox.items],
[da.messageBox.items],
);
const { scoresBySlug, hasAnyFacets } =
useFacetRecommendations("decisionApproaches");
const rankedMethods = useMemo(
() => rankMethodsByScore(da.methods, scoresBySlug),
[da.methods, scoresBySlug],
);
const { compactCardIds, recommendedIds } = useMemo(
() => deriveCompactCards(rankedMethods, scoresBySlug, hasAnyFacets, 5),
[rankedMethods, scoresBySlug, hasAnyFacets],
);
const sampleCards: CardStackItem[] = useMemo(
() =>
rr.cards.map((c) => ({
id: c.id,
label: c.label,
supportText: c.supportText,
recommended: c.recommended,
rankedMethods.map((entry) => ({
id: entry.id,
label: entry.label,
supportText: entry.supportText,
recommended: recommendedIds.has(entry.id),
})),
[rr.cards],
[rankedMethods, recommendedIds],
);
const cardById = useMemo(
() => new Map(rr.cards.map((c) => [c.id, c])),
[rr.cards],
const methodById = useMemo(
() => new Map(rankedMethods.map((entry) => [entry.id, entry])),
[rankedMethods],
);
const sidebarDescription = (
<>
{rr.sidebar.descriptionBefore}
{da.sidebar.descriptionBefore}
<InlineTextButton
onClick={() => {
markCreateFlowInteraction();
setExpanded(true);
}}
>
{rr.sidebar.descriptionLinkLabel}
{da.sidebar.descriptionLinkLabel}
</InlineTextButton>
{rr.sidebar.descriptionAfter}
{da.sidebar.descriptionAfter}
</>
);
@@ -239,26 +254,17 @@ export function DecisionApproachesScreen() {
const modalConfig = (() => {
if (!pendingCardId) {
return {
title: rr.confirmModal.title,
description: rr.confirmModal.description,
nextButtonText: rr.confirmModal.nextButtonText,
title: da.confirmModal.title,
description: da.confirmModal.description,
nextButtonText: da.confirmModal.nextButtonText,
};
}
if (pendingCardId in rr.modals) {
const modal = rr.modals[pendingCardId as keyof typeof rr.modals];
return {
title: modal.title,
description: modal.description,
nextButtonText: rr.addApproach.nextButtonText,
};
}
const card = cardById.get(pendingCardId);
const method = methodById.get(pendingCardId);
return {
title: card?.label ?? rr.confirmModal.title,
description: card?.supportText ?? rr.confirmModal.description,
nextButtonText: rr.addApproach.nextButtonText,
title: method?.label ?? da.confirmModal.title,
description: method?.supportText ?? da.confirmModal.description,
nextButtonText: da.addApproach.nextButtonText,
};
})();
@@ -268,9 +274,9 @@ export function DecisionApproachesScreen() {
lgVerticalAlign="start"
header={
<DecisionMakingSidebar
title={rr.sidebar.title}
title={da.sidebar.title}
description={sidebarDescription}
messageBoxTitle={rr.messageBox.title}
messageBoxTitle={da.messageBox.title}
messageBoxItems={messageBoxItems}
messageBoxCheckedIds={messageBoxCheckedIds}
onMessageBoxCheckboxChange={handleMessageBoxCheckboxChange}
@@ -287,12 +293,13 @@ export function DecisionApproachesScreen() {
expanded={expanded}
onToggleExpand={handleToggleExpand}
hasMore={true}
toggleLabel={rr.cardStack.toggleSeeAll}
showLessLabel={rr.cardStack.toggleShowLess}
toggleLabel={da.cardStack.toggleSeeAll}
showLessLabel={da.cardStack.toggleShowLess}
title=""
description=""
layout="singleStack"
compactRecommendedLimit={5}
compactCardIds={compactCardIds}
className="w-full"
headerLockupSize={mdUp ? "L" : "M"}
/>
@@ -27,7 +27,7 @@ function selectedIdsFromOptions(options: ChipOption[]): string[] {
/** Create Community — Figma `20094:41317`, chips only (layout tokens shared with structure select). */
export function CommunitySizeSelectScreen() {
const m = useMessages();
const cs = m.create.communitySize;
const cs = m.create.community.communitySize;
const { markCreateFlowInteraction, updateState, state } = useCreateFlow();
const [communitySizeOptions, setCommunitySizeOptions] = useState<
@@ -106,7 +106,7 @@ function snapshotRowsToChipOptions(
/** Create Community step 3 — Figma `20094:18244` (responsive grid + column caps via `createFlowLayoutTokens`). */
export function CommunityStructureSelectScreen() {
const m = useMessages();
const cs = m.create.communityStructure;
const cs = m.create.community.communityStructure;
const { markCreateFlowInteraction, updateState, state } = useCreateFlow();
const [organizationTypeOptions, setOrganizationTypeOptions] = useState<
@@ -12,7 +12,7 @@ import { CREATE_FLOW_MD_UP_COLUMN_MAX_CLASS } from "../../components/createFlowL
export function ConfirmStakeholdersScreen() {
const { markCreateFlowInteraction } = useCreateFlow();
const t = useTranslation("create.confirmStakeholders");
const t = useTranslation("create.reviewAndComplete.confirmStakeholders");
const [toastDismissed, setToastDismissed] = useState(false);
const [stakeholderOptions, setStakeholderOptions] = useState<ChipOption[]>(
[],
@@ -99,7 +99,7 @@ function snapshotRowsToChipOptions(
/** Create Custom — Core Values (Figma `20264:68378`). Up to five selections; preset list + custom chips. */
export function CoreValuesSelectScreen() {
const m = useMessages();
const cv = m.create.coreValues;
const cv = m.create.customRule.coreValues;
const presets = useMemo(
() => normalizeCoreValuePresets(cv.values as CoreValuePresetJson[]),
[cv.values],
@@ -10,7 +10,7 @@ import { CREATE_FLOW_MD_UP_COLUMN_MAX_CLASS } from "../../components/createFlowL
/** Create Community — Figma Flow — Upload `20094:41524`. */
export function CommunityUploadScreen() {
const m = useMessages();
const u = m.create.communityUpload;
const u = m.create.community.communityUpload;
const { markCreateFlowInteraction } = useCreateFlow();
const handleUploadClick = () => {