Final review edit modals created
This commit is contained in:
@@ -1,5 +1,19 @@
|
||||
import type { CoreValueDetailEntry, CreateFlowState } from "../../app/(app)/create/types";
|
||||
import type {
|
||||
CommunicationMethodDetailEntry,
|
||||
ConflictManagementDetailEntry,
|
||||
CoreValueDetailEntry,
|
||||
CreateFlowState,
|
||||
DecisionApproachDetailEntry,
|
||||
MembershipMethodDetailEntry,
|
||||
} from "../../app/(app)/create/types";
|
||||
import type { CommunityRuleDocumentSection } from "../../app/components/sections/CommunityRuleDocument/CommunityRuleDocument.types";
|
||||
import {
|
||||
communicationPresetFor,
|
||||
conflictManagementPresetFor,
|
||||
decisionApproachPresetFor,
|
||||
membershipPresetFor,
|
||||
methodLabelFor,
|
||||
} from "./finalReviewChipPresets";
|
||||
|
||||
function isDocumentEntry(x: unknown): x is { title: string; body: string } {
|
||||
if (!x || typeof x !== "object") return false;
|
||||
@@ -52,6 +66,36 @@ export function buildCoreValuesForDocument(state: CreateFlowState): Array<{
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Structured per-group method selections emitted into `document.methodSelections`
|
||||
* at publish time. Each entry carries the preset id (stable key), display
|
||||
* label, and the fully-resolved section payload (override on top of preset).
|
||||
* Empty groups are omitted so downstream readers can iterate just the set
|
||||
* the author actually picked.
|
||||
*/
|
||||
export type PublishedMethodSelections = {
|
||||
communication?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
sections: CommunicationMethodDetailEntry;
|
||||
}>;
|
||||
membership?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
sections: MembershipMethodDetailEntry;
|
||||
}>;
|
||||
decisionApproaches?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
sections: DecisionApproachDetailEntry;
|
||||
}>;
|
||||
conflictManagement?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
sections: ConflictManagementDetailEntry;
|
||||
}>;
|
||||
};
|
||||
|
||||
export type BuildPublishPayloadResult =
|
||||
| {
|
||||
ok: true;
|
||||
@@ -97,16 +141,93 @@ export function buildPublishPayload(
|
||||
}
|
||||
|
||||
const coreValues = buildCoreValuesForDocument(state);
|
||||
const methodSelections = buildMethodSelectionsForDocument(state);
|
||||
|
||||
const document: Record<string, unknown> = { sections, coreValues };
|
||||
if (hasAnyMethodSelection(methodSelections)) {
|
||||
document.methodSelections = methodSelections;
|
||||
}
|
||||
|
||||
if (summary !== undefined) {
|
||||
return {
|
||||
ok: true,
|
||||
title,
|
||||
summary,
|
||||
document: { sections, coreValues },
|
||||
};
|
||||
return { ok: true, title, summary, document };
|
||||
}
|
||||
return { ok: true, title, document: { sections, coreValues } };
|
||||
return { ok: true, title, document };
|
||||
}
|
||||
|
||||
function hasAnyMethodSelection(m: PublishedMethodSelections): boolean {
|
||||
return Boolean(
|
||||
m.communication?.length ||
|
||||
m.membership?.length ||
|
||||
m.decisionApproaches?.length ||
|
||||
m.conflictManagement?.length,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge `selected*MethodIds` with any saved `{group}MethodDetailsById`
|
||||
* overrides authored on the final-review screen. Preset defaults from the
|
||||
* shipped `messages/en/create/customRule/*.json` seed any sub-fields the
|
||||
* user didn't edit so consumers of `document.methodSelections` always see
|
||||
* a complete payload per method.
|
||||
*/
|
||||
export function buildMethodSelectionsForDocument(
|
||||
state: CreateFlowState,
|
||||
): PublishedMethodSelections {
|
||||
const out: PublishedMethodSelections = {};
|
||||
|
||||
const commIds = state.selectedCommunicationMethodIds ?? [];
|
||||
if (commIds.length > 0) {
|
||||
out.communication = commIds.map((id) => {
|
||||
const preset = communicationPresetFor(id);
|
||||
const override = state.communicationMethodDetailsById?.[id];
|
||||
return {
|
||||
id,
|
||||
label: methodLabelFor("communication", id),
|
||||
sections: override ? { ...preset, ...override } : preset,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const memIds = state.selectedMembershipMethodIds ?? [];
|
||||
if (memIds.length > 0) {
|
||||
out.membership = memIds.map((id) => {
|
||||
const preset = membershipPresetFor(id);
|
||||
const override = state.membershipMethodDetailsById?.[id];
|
||||
return {
|
||||
id,
|
||||
label: methodLabelFor("membership", id),
|
||||
sections: override ? { ...preset, ...override } : preset,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const daIds = state.selectedDecisionApproachIds ?? [];
|
||||
if (daIds.length > 0) {
|
||||
out.decisionApproaches = daIds.map((id) => {
|
||||
const preset = decisionApproachPresetFor(id);
|
||||
const override = state.decisionApproachDetailsById?.[id];
|
||||
return {
|
||||
id,
|
||||
label: methodLabelFor("decisionApproaches", id),
|
||||
sections: override ? { ...preset, ...override } : preset,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const cmIds = state.selectedConflictManagementIds ?? [];
|
||||
if (cmIds.length > 0) {
|
||||
out.conflictManagement = cmIds.map((id) => {
|
||||
const preset = conflictManagementPresetFor(id);
|
||||
const override = state.conflictManagementDetailsById?.[id];
|
||||
return {
|
||||
id,
|
||||
label: methodLabelFor("conflictManagement", id),
|
||||
sections: override ? { ...preset, ...override } : preset,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Read `document.sections` from a stored published payload for display. */
|
||||
|
||||
Reference in New Issue
Block a user