120 lines
3.7 KiB
TypeScript
120 lines
3.7 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect, useLayoutEffect } 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 { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
|
|
import { CreateFlowTwoColumnSelectShell } from "../../components/CreateFlowTwoColumnSelectShell";
|
|
|
|
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,
|
|
}));
|
|
}
|
|
|
|
/** The first saved id. A count belongs to one band, so later ids are dropped. */
|
|
function soleSizeId(ids: readonly string[] | undefined): string | null {
|
|
for (const id of ids ?? []) {
|
|
if (id.length > 0) return id;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
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),
|
|
},
|
|
);
|
|
}
|
|
|
|
/** Create Community — Figma `24715:26346`, chips size M (one question). */
|
|
export function CommunitySizeSelectScreen() {
|
|
const m = useMessages();
|
|
const cs = m.create.community.communitySize;
|
|
const { markCreateFlowInteraction, updateState, state } = useCreateFlow();
|
|
const { attempted } = useCreateFlowContinueAttempt();
|
|
|
|
const [communitySizeOptions, setCommunitySizeOptions] = useState<
|
|
ChipOption[]
|
|
>(() =>
|
|
withSoleSelection(
|
|
chipRowsFromLabels(cs.communitySizes),
|
|
soleSizeId(state.selectedCommunitySizeIds),
|
|
),
|
|
);
|
|
|
|
useLayoutEffect(() => {
|
|
const ids = state.selectedCommunitySizeIds;
|
|
if (!ids || ids.length === 0) return;
|
|
const first = soleSizeId(ids);
|
|
if (ids.length === 1 && ids[0] === first) return;
|
|
updateState({ selectedCommunitySizeIds: first ? [first] : [] });
|
|
}, [state.selectedCommunitySizeIds, updateState]);
|
|
|
|
useEffect(() => {
|
|
const selectedId = soleSizeId(state.selectedCommunitySizeIds);
|
|
setCommunitySizeOptions((prev) => withSoleSelection(prev, selectedId));
|
|
}, [state.selectedCommunitySizeIds]);
|
|
|
|
const persistSelection = (next: ChipOption[]) => {
|
|
markCreateFlowInteraction();
|
|
setCommunitySizeOptions(next);
|
|
updateState({
|
|
selectedCommunitySizeIds: next
|
|
.filter((o) => o.state === "selected")
|
|
.map((o) => o.id),
|
|
});
|
|
};
|
|
|
|
const handleCommunitySizeClick = (chipId: string) => {
|
|
const current = communitySizeOptions.find((opt) => opt.state === "selected");
|
|
const nextId = current?.id === chipId ? null : chipId;
|
|
persistSelection(withSoleSelection(communitySizeOptions, nextId));
|
|
};
|
|
|
|
const showSizeError =
|
|
attempted && soleSizeId(state.selectedCommunitySizeIds) == null;
|
|
|
|
const multiSelectBlock = (
|
|
<MultiSelect
|
|
formHeader={false}
|
|
size="m"
|
|
options={communitySizeOptions}
|
|
onChipClick={handleCommunitySizeClick}
|
|
addButton={false}
|
|
errorMessage={showSizeError ? cs.pickOneError : undefined}
|
|
/>
|
|
);
|
|
|
|
return (
|
|
<CreateFlowTwoColumnSelectShell
|
|
header={
|
|
<CreateFlowHeaderLockup
|
|
title={cs.header.title}
|
|
description={cs.header.description}
|
|
justification="left"
|
|
/>
|
|
}
|
|
>
|
|
{multiSelectBlock}
|
|
</CreateFlowTwoColumnSelectShell>
|
|
);
|
|
}
|