"use client"; import { useState, useMemo, useEffect, type Dispatch, type SetStateAction, } from "react"; import MultiSelect from "../../../../components/controls/MultiSelect"; import type { ChipOption } from "../../../../components/controls/MultiSelect/MultiSelect.types"; import { useMessages } from "../../../../contexts/MessagesContext"; import { useCreateFlow } from "../../context/CreateFlowContext"; import { useCreateFlowContinueAttempt } from "../../context/CreateFlowContinueAttemptContext"; import type { CommunityStructureChipSnapshotRow } from "../../types"; import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup"; import { CreateFlowTwoColumnSelectShell } from "../../components/CreateFlowTwoColumnSelectShell"; function createListCustomHandlers( setList: Dispatch>, confirmState: "unselected" | "selected", onInteraction?: () => void, ) { const touch = () => onInteraction?.(); return { onAddClick: () => { touch(); setList((prev) => [ ...prev, { id: crypto.randomUUID(), label: "", state: "custom" }, ]); }, onCustomChipConfirm: (chipId: string, value: string) => { touch(); setList((prev) => prev.map((opt) => opt.id === chipId ? { ...opt, label: value, state: confirmState } : opt, ), ); }, onCustomChipClose: (chipId: string) => { touch(); setList((prev) => prev.filter((o) => o.id !== chipId)); }, }; } function chipRowsFromLabels( rows: readonly { id?: string; label: string }[], ): ChipOption[] { return rows.map((row, i) => ({ id: row.id ?? String(i + 1), label: row.label, state: "unselected" as const, })); } function applySavedSelection( options: ChipOption[], saved: string[] | undefined, ): ChipOption[] { const selected = new Set(saved ?? []); return options.map((opt) => opt.state === "custom" ? opt : { ...opt, state: selected.has(opt.id) ? ("selected" as const) : ("unselected" as const), }, ); } function withSoleSelection( options: ChipOption[], selectedId: string | null, ): ChipOption[] { return options.map((opt) => opt.state === "custom" ? opt : { ...opt, state: opt.id === selectedId ? ("selected" as const) : ("unselected" as const), }, ); } function selectedIdsFromOptions(options: ChipOption[]): string[] { return options.filter((o) => o.state === "selected").map((o) => o.id); } function firstSelectedId(options: ChipOption[]): string | null { return selectedIdsFromOptions(options)[0] ?? null; } function chipOptionsToSnapshotRows( options: ChipOption[], ): CommunityStructureChipSnapshotRow[] { return options.map((o) => ({ id: o.id, label: o.label, ...(o.state !== undefined ? { state: o.state } : {}), })); } /** Returns chips when a draft snapshot exists; otherwise null (use preset rows + selected ids). */ function snapshotRowsToChipOptions( rows: CommunityStructureChipSnapshotRow[] | undefined, ): ChipOption[] | null { if (!Array.isArray(rows) || rows.length === 0) return null; return rows.map((r) => ({ id: r.id, label: r.label, ...(r.state !== undefined ? { state: r.state as ChipOption["state"] } : {}), })); } function organizationIdsForPersist( mainId: string | null, otherIds: readonly string[], ): string[] { if (!mainId) return []; return [mainId, ...otherIds.filter((id) => id !== mainId)]; } /** Create Community type step — Figma `25224:105767`. */ export function CommunityStructureSelectScreen() { const m = useMessages(); const cs = m.create.community.communityStructure; const { markCreateFlowInteraction, updateState, state } = useCreateFlow(); const { attempted } = useCreateFlowContinueAttempt(); const savedKindIds = state.selectedOrganizationTypeIds ?? []; const savedMainIndex = savedKindIds.findIndex((id) => id.length > 0); const savedMainId = savedMainIndex >= 0 ? savedKindIds[savedMainIndex]! : null; const savedOtherIds = savedMainIndex >= 0 ? savedKindIds.slice(savedMainIndex + 1) : []; const [mainKindOptions, setMainKindOptions] = useState(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.organizationTypes, ); return withSoleSelection( fromSnap ?? chipRowsFromLabels(cs.organizationTypes), savedMainId, ); }); const [otherKindOptions, setOtherKindOptions] = useState(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.otherOrganizationTypes, ); if (fromSnap) return fromSnap; return applySavedSelection( chipRowsFromLabels(cs.organizationTypes), savedOtherIds, ); }); const [scaleOptions, setScaleOptions] = useState(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.scale, ); if (fromSnap) return fromSnap; return applySavedSelection( chipRowsFromLabels(cs.scaleOptions), state.selectedScaleIds, ); }); const [maturityOptions, setMaturityOptions] = useState(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.maturity, ); const base = fromSnap ?? chipRowsFromLabels(cs.maturityOptions); const maturityId = (state.selectedMaturityIds ?? []).find((id) => id.length > 0) ?? null; return withSoleSelection(base, maturityId); }); useEffect(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.organizationTypes, ); const mainId = (state.selectedOrganizationTypeIds ?? []).find((id) => id.length > 0) ?? null; setMainKindOptions( withSoleSelection( fromSnap ?? chipRowsFromLabels(cs.organizationTypes), mainId, ), ); }, [ cs.organizationTypes, state.communityStructureChipSnapshots?.organizationTypes, state.selectedOrganizationTypeIds, ]); useEffect(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.otherOrganizationTypes, ); const ids = state.selectedOrganizationTypeIds ?? []; const mainId = ids.find((id) => id.length > 0); const otherIds = mainId ? ids.slice(ids.indexOf(mainId) + 1) : []; if (fromSnap) { setOtherKindOptions(fromSnap); return; } setOtherKindOptions((prev) => applySavedSelection(prev, otherIds)); }, [ state.communityStructureChipSnapshots?.otherOrganizationTypes, state.selectedOrganizationTypeIds, ]); useEffect(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.scale, ); if (fromSnap) { setScaleOptions(fromSnap); return; } setScaleOptions((prev) => applySavedSelection(prev, state.selectedScaleIds)); }, [ state.communityStructureChipSnapshots?.scale, state.selectedScaleIds, ]); useEffect(() => { const fromSnap = snapshotRowsToChipOptions( state.communityStructureChipSnapshots?.maturity, ); const maturityId = (state.selectedMaturityIds ?? []).find((id) => id.length > 0) ?? null; if (fromSnap) { setMaturityOptions(withSoleSelection(fromSnap, maturityId)); return; } setMaturityOptions((prev) => withSoleSelection(prev, maturityId)); }, [ state.communityStructureChipSnapshots?.maturity, state.selectedMaturityIds, ]); const mainKindCustomHandlers = useMemo( () => createListCustomHandlers( setMainKindOptions, "unselected", markCreateFlowInteraction, ), [markCreateFlowInteraction], ); const otherKindCustomHandlers = useMemo( () => createListCustomHandlers( setOtherKindOptions, "unselected", markCreateFlowInteraction, ), [markCreateFlowInteraction], ); const persistKinds = (main: ChipOption[], others: ChipOption[]) => { markCreateFlowInteraction(); setMainKindOptions(main); setOtherKindOptions(others); const mainId = firstSelectedId(main); updateState({ selectedOrganizationTypeIds: organizationIdsForPersist( mainId, selectedIdsFromOptions(others), ), communityStructureChipSnapshots: { organizationTypes: chipOptionsToSnapshotRows(main), otherOrganizationTypes: chipOptionsToSnapshotRows(others), }, }); }; const persistScale = (next: ChipOption[]) => { markCreateFlowInteraction(); setScaleOptions(next); updateState({ selectedScaleIds: selectedIdsFromOptions(next), communityStructureChipSnapshots: { scale: chipOptionsToSnapshotRows(next), }, }); }; const persistMaturity = (next: ChipOption[]) => { markCreateFlowInteraction(); setMaturityOptions(next); updateState({ selectedMaturityIds: selectedIdsFromOptions(next), communityStructureChipSnapshots: { maturity: chipOptionsToSnapshotRows(next), }, }); }; const handleMainKindClick = (chipId: string) => { const current = firstSelectedId(mainKindOptions); const nextId = current === chipId ? null : chipId; persistKinds(withSoleSelection(mainKindOptions, nextId), otherKindOptions); }; const handleOtherKindClick = (chipId: string) => { persistKinds( mainKindOptions, otherKindOptions.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? ("unselected" as const) : ("selected" as const), } : opt, ), ); }; const handleScaleClick = (chipId: string) => { persistScale( scaleOptions.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? ("unselected" as const) : ("selected" as const), } : opt, ), ); }; const handleMaturityClick = (chipId: string) => { const current = firstSelectedId(maturityOptions); const nextId = current === chipId ? null : chipId; persistMaturity(withSoleSelection(maturityOptions, nextId)); }; const showMainError = attempted && firstSelectedId(mainKindOptions) == null; const showMaturityError = attempted && firstSelectedId(maturityOptions) == null; const multiSelectBlock = ( <> ); return ( } > {multiSelectBlock} ); }