"use client"; import { useEffect, useRef, useState } from "react"; import { useRouter } from "next/navigation"; import Rule from "../../../../components/cards/Rule"; import Button from "../../../../components/buttons/Button"; import InlineTextButton from "../../../../components/buttons/InlineTextButton"; import { useMessages, useTranslation } from "../../../../contexts/MessagesContext"; import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup"; import { useCreateFlow } from "../../context/CreateFlowContext"; import { useCommunityAvatarDisplayUrl } from "../../hooks/useCommunityAvatarDisplayUrl"; import { useCreateFlowLgUp } from "../../hooks/useCreateFlowLgUp"; import { CreateFlowStepShell } from "../../components/CreateFlowStepShell"; import { CREATE_FLOW_MD_UP_GRID_CELL_CLASS, CREATE_FLOW_TWO_COLUMN_MAX_WIDTH_CLASS, } from "../../components/createFlowLayoutTokens"; import { getAssetPath, vectorMarkPath, } from "../../../../../lib/assetUtils"; import { methodSectionsPinsForHydratedSelections } from "../../../../../lib/create/publishedDocumentToCreateFlowState"; import { CREATE_ROUTES, createFlowStepPath } from "../../utils/createFlowPaths"; import { CREATE_FLOW_REVIEW_RETURN_QUERY_KEY } from "../../utils/flowSteps"; import type { CreateFlowStep } from "../../types"; function firstId(ids: readonly string[] | undefined): string | undefined { return ids?.find((id) => id.length > 0); } function chipLabel( id: string | undefined, rows: readonly { id: string; label: string }[] | undefined, snapshots: readonly { id: string; label: string }[] | undefined, ): string | undefined { if (!id) return undefined; const fromSnap = snapshots?.find((row) => row.id === id)?.label.trim(); if (fromSnap) return fromSnap; return rows?.find((row) => row.id === id)?.label; } function reviewSizeValue( id: string | undefined, sizes: readonly { id: string; label: string }[], peopleTemplate: string, ): string | undefined { if (!id) return undefined; const row = sizes.find((item) => item.id === id); if (!row) return undefined; if (id === "oneMember") return row.label; return peopleTemplate.replace("{label}", row.label); } function CommunityReviewAnswerRow({ label, value, editLabel, onEdit, }: { label: string; value: string; editLabel: string; onEdit: () => void; }) { return (

{label}

{value}

{editLabel}
); } /** Create Community review — Figma `19706:12135` (`/create/review`; two columns from `lg:`; column caps in `createFlowLayoutTokens`). */ export function CommunityReviewScreen() { const router = useRouter(); const lgUp = useCreateFlowLgUp(); const messages = useMessages(); const t = useTranslation("create.community.review"); const { state, updateState } = useCreateFlow(); /** * Server layout has an empty context; the client layout may already hold a * named draft. Defer empty-vs-congrats until after mount so the first paint * matches SSR (`null`) instead of swapping HeaderLockup titles. */ const [reviewReady, setReviewReady] = useState(false); useEffect(() => { setReviewReady(true); }, []); /** * If the user picked **Customize** from a template before finishing community * stage, we pinned `pendingTemplateAction` so this screen can skip itself * and `replace` to `core-values`. **Use without changes** does not skip * identity: if they land here with that pin, send them to `community-name` * and leave the pin so name → description → photo stay in the skip list. * * Ref guard covers React 18 StrictMode's double-mount in dev so we don't * fire `router.replace` twice on the same transition. */ const firedRedirectRef = useRef(false); useEffect(() => { if (firedRedirectRef.current) return; const pending = state.pendingTemplateAction; if (!pending) return; if (pending.mode !== "customize") { firedRedirectRef.current = true; router.replace(createFlowStepPath("community-name")); return; } const target = createFlowStepPath("core-values"); firedRedirectRef.current = true; const pinMerge = { methodSectionsPinCommitted: { ...state.methodSectionsPinCommitted, ...methodSectionsPinsForHydratedSelections(state), }, }; updateState({ pendingTemplateAction: undefined, ...pinMerge }); router.replace(target); }, [ router, state.pendingTemplateAction, state.methodSectionsPinCommitted, state.selectedCommunicationMethodIds, state.selectedMembershipMethodIds, state.selectedDecisionApproachIds, state.selectedConflictManagementIds, updateState, ]); const cardTitle = typeof state.title === "string" && state.title.trim().length > 0 ? state.title.trim() : ""; /** * No placeholder fallback: if the user skipped `community-context`, leave * the card description off rather than render sample copy as real user data. */ const cardDescription = typeof state.communityContext === "string" && state.communityContext.trim().length > 0 ? state.communityContext.trim() : undefined; const avatarUrl = useCommunityAvatarDisplayUrl(state.communityAvatarUrl); const structure = messages.create.community.communityStructure; const sizes = messages.create.community.communitySize.communitySizes; const kindValue = chipLabel( firstId(state.selectedOrganizationTypeIds), structure.organizationTypes, state.communityStructureChipSnapshots?.organizationTypes, ); const sizeValue = reviewSizeValue( firstId(state.selectedCommunitySizeIds), sizes, t("rows.sizePeople"), ); const maturityValue = chipLabel( firstId(state.selectedMaturityIds), structure.maturityOptions, state.communityStructureChipSnapshots?.maturity, ); const goEdit = (step: CreateFlowStep) => { router.push( createFlowStepPath(step, { [CREATE_FLOW_REVIEW_RETURN_QUERY_KEY]: "review", }), ); }; if (state.pendingTemplateAction || !reviewReady) { return null; } if (!cardTitle) { return (
); } return (
{kindValue ? ( goEdit("community-structure")} /> ) : null} {sizeValue ? ( goEdit("community-size")} /> ) : null} {maturityValue ? ( goEdit("community-structure")} /> ) : null}
); }