Offer the engine's five size bands as exclusive ranges, so a count of 100 has one home and a group cannot continue without a size.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
821690201e
commit
db278ab67d
11 files changed
+184
-61
No files matched your search
@@ -85,7 +85,10 @@ import {
|
||||
methodCardFacetSectionForConfirmStep,
|
||||
type CustomRuleConfirmFooterStep,
|
||||
} from "./utils/customRuleConfirmFooterSteps";
|
||||
import { getDefaultFooterLabel } from "./utils/createFlowFooterLabels";
|
||||
import {
|
||||
getDefaultFooterLabel,
|
||||
isCommunitySizeStepBlocked,
|
||||
} from "./utils/createFlowFooterLabels";
|
||||
import { useAuthModal } from "../../contexts/AuthModalContext";
|
||||
import { useMessages, useTranslation } from "../../contexts/MessagesContext";
|
||||
import { PostLoginDraftTransfer } from "./PostLoginDraftTransfer";
|
||||
@@ -985,7 +988,12 @@ function CreateFlowLayoutContent({
|
||||
palette="default"
|
||||
size="xsmall"
|
||||
disabled={
|
||||
isPublishing || (isFinalReviewLike && !sessionResolved)
|
||||
isPublishing ||
|
||||
(isFinalReviewLike && !sessionResolved) ||
|
||||
isCommunitySizeStepBlocked(
|
||||
currentStep,
|
||||
state.selectedCommunitySizeIds,
|
||||
)
|
||||
}
|
||||
className={CREATE_FLOW_FOOTER_BUTTON_CLASS}
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
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";
|
||||
@@ -18,13 +18,32 @@ function chipRowsFromLabels(
|
||||
}));
|
||||
}
|
||||
|
||||
function selectedIdsFromOptions(options: ChipOption[]): string[] {
|
||||
return options
|
||||
.filter((o) => o.state === "selected")
|
||||
.map((o) => o.id);
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/** Create Community — Figma `20094:41317`, chips only (layout tokens shared with structure select). */
|
||||
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;
|
||||
@@ -32,52 +51,40 @@ export function CommunitySizeSelectScreen() {
|
||||
|
||||
const [communitySizeOptions, setCommunitySizeOptions] = useState<
|
||||
ChipOption[]
|
||||
>(() => {
|
||||
const base = chipRowsFromLabels(cs.communitySizes);
|
||||
const selected = new Set(state.selectedCommunitySizeIds ?? []);
|
||||
return base.map((opt) => ({
|
||||
...opt,
|
||||
state: selected.has(opt.id) ? ("selected" as const) : ("unselected" as const),
|
||||
}));
|
||||
});
|
||||
>(() =>
|
||||
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 selected = new Set(state.selectedCommunitySizeIds ?? []);
|
||||
setCommunitySizeOptions((prev) =>
|
||||
prev.map((opt) =>
|
||||
opt.state === "custom"
|
||||
? opt
|
||||
: {
|
||||
...opt,
|
||||
state: selected.has(opt.id)
|
||||
? ("selected" as const)
|
||||
: ("unselected" as const),
|
||||
},
|
||||
),
|
||||
);
|
||||
const selectedId = soleSizeId(state.selectedCommunitySizeIds);
|
||||
setCommunitySizeOptions((prev) => withSoleSelection(prev, selectedId));
|
||||
}, [state.selectedCommunitySizeIds]);
|
||||
|
||||
const persistSelection = (next: ChipOption[]) => {
|
||||
markCreateFlowInteraction();
|
||||
setCommunitySizeOptions(next);
|
||||
updateState({
|
||||
selectedCommunitySizeIds: selectedIdsFromOptions(next),
|
||||
selectedCommunitySizeIds: next
|
||||
.filter((o) => o.state === "selected")
|
||||
.map((o) => o.id),
|
||||
});
|
||||
};
|
||||
|
||||
const handleCommunitySizeClick = (chipId: string) => {
|
||||
const next: ChipOption[] = communitySizeOptions.map((opt) =>
|
||||
opt.id === chipId
|
||||
? {
|
||||
...opt,
|
||||
state:
|
||||
opt.state === "selected"
|
||||
? ("unselected" as const)
|
||||
: ("selected" as const),
|
||||
}
|
||||
: opt,
|
||||
);
|
||||
persistSelection(next);
|
||||
const current = communitySizeOptions.find((opt) => opt.state === "selected");
|
||||
const nextId = current?.id === chipId ? null : chipId;
|
||||
persistSelection(withSoleSelection(communitySizeOptions, nextId));
|
||||
};
|
||||
|
||||
const multiSelectBlock = (
|
||||
|
||||
@@ -123,7 +123,7 @@ export interface CreateFlowState {
|
||||
* Picked once and kept on the draft so reload does not change it.
|
||||
*/
|
||||
previewSurfaceColor?: string;
|
||||
/** Selected chip ids from `community-size` (MultiSelect). */
|
||||
/** The size band from `community-size`. One id; 100 is `thirteenToOneHundred`. */
|
||||
selectedCommunitySizeIds?: string[];
|
||||
/** Selected chip ids from `community-structure` (organization types). */
|
||||
selectedOrganizationTypeIds?: string[];
|
||||
|
||||
@@ -20,9 +20,17 @@ const DEFAULT_FOOTER_LABEL_BY_STEP: ReadonlyMap<
|
||||
["confirm-stakeholders", "confirmStakeholders"],
|
||||
["community-context", "confirmDescription"],
|
||||
["community-structure", "confirmDetails"],
|
||||
["community-size", "confirmMembers"],
|
||||
["community-size", "confirmSize"],
|
||||
]);
|
||||
|
||||
export function isCommunitySizeStepBlocked(
|
||||
step: CreateFlowStep | null | undefined,
|
||||
selectedCommunitySizeIds: readonly string[] | undefined,
|
||||
): boolean {
|
||||
if (step !== "community-size") return false;
|
||||
return !(selectedCommunitySizeIds ?? []).some((id) => id.length > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the localized label for the default "next-step" footer button.
|
||||
* Returns the per-step override when one is registered, otherwise
|
||||
|
||||
@@ -53,7 +53,7 @@ export const CREATE_FLOW_SCREEN_REGISTRY: Record<
|
||||
},
|
||||
"community-size": {
|
||||
layoutKind: "select",
|
||||
figmaNodeId: "20094-41317",
|
||||
figmaNodeId: "24715-26346",
|
||||
messageNamespace: "create.community.communitySize",
|
||||
centeredBodyBelowMd: false,
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user