97 lines
2.9 KiB
TypeScript
97 lines
2.9 KiB
TypeScript
import type { ChipOption } from "../../app/components/controls/MultiSelect/MultiSelect.types";
|
|
import type {
|
|
CreateFlowState,
|
|
} from "../../app/(app)/create/types";
|
|
|
|
type CoreValuePreset = { label: string; meaning: string; signals: string };
|
|
|
|
function chipRowsFromPresets(presets: readonly CoreValuePreset[]): ChipOption[] {
|
|
return presets.map((row, i) => ({
|
|
id: String(i + 1),
|
|
label: row.label,
|
|
state: "unselected" as const,
|
|
}));
|
|
}
|
|
|
|
function applySavedSelectionToPresetsOnly(
|
|
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),
|
|
},
|
|
);
|
|
}
|
|
|
|
/** Valid MultiSelect chip state from snapshot JSON. */
|
|
function normalizeChipState(s: unknown): ChipOption["state"] | undefined {
|
|
return s === "selected" ||
|
|
s === "unselected" ||
|
|
s === "custom" ||
|
|
s === "error"
|
|
? (s as ChipOption["state"])
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* Build the core-values MultiSelect chip list shown in-create.
|
|
*
|
|
* The published-rule hydration path writes only **selected** rows into
|
|
* `coreValuesChipsSnapshot`. Editing must still show every preset ("1"..N) plus
|
|
* custom ids from the snapshot. Card-deck pin / ordering features do not apply
|
|
* here.
|
|
*/
|
|
export function buildCoreValueChipOptionsFromDraft(
|
|
presets: readonly CoreValuePreset[],
|
|
snapshot: CreateFlowState["coreValuesChipsSnapshot"],
|
|
selectedCoreValueIds: CreateFlowState["selectedCoreValueIds"],
|
|
): ChipOption[] {
|
|
const presetBase = chipRowsFromPresets(presets);
|
|
const presetIdSet = new Set(presetBase.map((p) => p.id));
|
|
const selected = new Set(selectedCoreValueIds ?? []);
|
|
|
|
if (!snapshot?.length) {
|
|
return applySavedSelectionToPresetsOnly(presetBase, selectedCoreValueIds);
|
|
}
|
|
|
|
const snapById = new Map(snapshot.map((r) => [r.id, r] as const));
|
|
|
|
const presetRows: ChipOption[] = presetBase.map((opt) => {
|
|
const row = snapById.get(opt.id);
|
|
if (!row) {
|
|
return {
|
|
...opt,
|
|
state: selected.has(opt.id) ? ("selected" as const) : ("unselected" as const),
|
|
};
|
|
}
|
|
const normalized = normalizeChipState(row.state);
|
|
const effectiveState =
|
|
normalized ??
|
|
(selected.has(opt.id) ? ("selected" as const) : ("unselected" as const));
|
|
const label =
|
|
typeof row.label === "string" && row.label.trim().length > 0
|
|
? row.label
|
|
: opt.label;
|
|
return { ...opt, label, state: effectiveState };
|
|
});
|
|
|
|
const customRows: ChipOption[] = snapshot
|
|
.filter((r) => !presetIdSet.has(r.id))
|
|
.map((r) => ({
|
|
id: r.id,
|
|
label: r.label,
|
|
state:
|
|
normalizeChipState(r.state) ??
|
|
(selected.has(r.id) ? ("selected" as const) : ("unselected" as const)),
|
|
}));
|
|
|
|
return [...presetRows, ...customRows];
|
|
}
|