"use client"; import IncrementerBlock from "../../../components/controls/IncrementerBlock"; import { useMessages } from "../../../contexts/MessagesContext"; import { formatConflictApplicableScopeForTextarea } from "../../../../lib/create/ruleSectionsFromMethodSelections"; import { withDecisionApproachKeyResourceScopes } from "../../../../lib/create/decisionApproachKeyResources"; import type { CommunicationMethodDetailEntry, ConflictManagementDetailEntry, DecisionApproachDetailEntry, MembershipMethodDetailEntry, } from "../types"; import ApplicableScopeField from "./ApplicableScopeField"; import type { MethodCardPolicyStep } from "./MethodCardPolicyDialog"; import ModalTextAreaField from "./ModalTextAreaField"; const CONSENSUS_LEVEL_MIN = 0; const CONSENSUS_LEVEL_MAX = 100; const CONSENSUS_LEVEL_STEP = 5; function textStep(args: { id: string; title: string; emptyDescription: string; value: string; onChange: (next: string) => void; generateDraftText?: string; generateDraftLabel: string; generateDraftHint: string; filledHint: string; placeholder: string; }): MethodCardPolicyStep { const done = args.value.trim().length > 0; return { id: args.id, title: args.title, emptyDescription: args.emptyDescription, done, summary: args.value, renderEditor: () => ( ), }; } function usePolicyFieldCopy() { const m = useMessages(); return { dialog: m.create.customRule.cardDialog, draftField: m.create.draftField, }; } export function useCommunicationPolicySteps( value: CommunicationMethodDetailEntry, onChange: (next: CommunicationMethodDetailEntry) => void, generateDraft?: CommunicationMethodDetailEntry, ): MethodCardPolicyStep[] { const { dialog, draftField } = usePolicyFieldCopy(); const headings = useMessages().create.customRule.communication.sectionHeadings; const fields: Array = [ "corePrinciple", "logisticsAdmin", "codeOfConduct", ]; return fields.map((field) => textStep({ id: field, title: headings[field], emptyDescription: dialog.emptyStepDescription, value: value[field], onChange: (next) => onChange({ ...value, [field]: next }), generateDraftText: generateDraft?.[field], generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), ); } export function useMembershipPolicySteps( value: MembershipMethodDetailEntry, onChange: (next: MembershipMethodDetailEntry) => void, generateDraft?: MembershipMethodDetailEntry, ): MethodCardPolicyStep[] { const { dialog, draftField } = usePolicyFieldCopy(); const headings = useMessages().create.customRule.membership.sectionHeadings; const fields: Array = [ "eligibility", "joiningProcess", "expectations", ]; return fields.map((field) => textStep({ id: field, title: headings[field], emptyDescription: dialog.emptyStepDescription, value: value[field], onChange: (next) => onChange({ ...value, [field]: next }), generateDraftText: generateDraft?.[field], generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), ); } export function useConflictPolicySteps( value: ConflictManagementDetailEntry, onChange: (next: ConflictManagementDetailEntry) => void, generateDraft?: ConflictManagementDetailEntry, ): MethodCardPolicyStep[] { const { dialog, draftField } = usePolicyFieldCopy(); const t = useMessages().create.customRule.conflictManagement; const scopeText = formatConflictApplicableScopeForTextarea( value.selectedApplicableScope, value.applicableScope, ); const generateScope = generateDraft && generateDraft.applicableScope.length > 0 ? generateDraft.applicableScope.join("\n") : generateDraft ? formatConflictApplicableScopeForTextarea( generateDraft.selectedApplicableScope, generateDraft.applicableScope, ) : undefined; return [ textStep({ id: "corePrinciple", title: t.sectionHeadings.corePrinciple, emptyDescription: dialog.emptyStepDescription, value: value.corePrinciple, onChange: (next) => onChange({ ...value, corePrinciple: next }), generateDraftText: generateDraft?.corePrinciple, generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), textStep({ id: "applicableScope", title: t.sectionHeadings.applicableScope, emptyDescription: t.applicableScopePlaceholder, value: scopeText, onChange: (next) => { const lines = next .split("\n") .map((line) => line.trim()) .filter((line) => line.length > 0); onChange({ ...value, applicableScope: lines, selectedApplicableScope: [...lines], }); }, generateDraftText: generateScope, generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: t.applicableScopePlaceholder, }), textStep({ id: "processProtocol", title: t.sectionHeadings.processProtocol, emptyDescription: dialog.emptyStepDescription, value: value.processProtocol, onChange: (next) => onChange({ ...value, processProtocol: next }), generateDraftText: generateDraft?.processProtocol, generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), textStep({ id: "restorationFallbacks", title: t.sectionHeadings.restorationFallbacks, emptyDescription: dialog.emptyStepDescription, value: value.restorationFallbacks, onChange: (next) => onChange({ ...value, restorationFallbacks: next }), generateDraftText: generateDraft?.restorationFallbacks, generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), ]; } export function useDecisionApproachPolicySteps( value: DecisionApproachDetailEntry, onChange: (next: DecisionApproachDetailEntry) => void, generateDraft?: DecisionApproachDetailEntry, ): MethodCardPolicyStep[] { const { dialog, draftField } = usePolicyFieldCopy(); const t = useMessages().create.customRule.decisionApproaches; const scopes = withDecisionApproachKeyResourceScopes(value.applicableScope); const selectedSummary = value.selectedApplicableScope.join(", "); const consensusStep: MethodCardPolicyStep = { id: "consensusLevel", title: t.sectionHeadings.consensusLevel, emptyDescription: t.consensusLevelDisplay.supermajorityShare, done: true, summary: value.consensusLevel === undefined ? t.consensusLevelDisplay.supermajorityShare : value.consensusLevel === 0 ? t.consensusLevelDisplay.noSetShare : `${value.consensusLevel}%`, renderEditor: () => value.consensusLevel === undefined ? ( {}} disabled rows={1} /> ) : ( onChange({ ...value, consensusLevel: next })} formatValue={(v) => v === 0 ? t.consensusLevelDisplay.noSetShare : `${v}%` } decrementAriaLabel={dialog.decreaseConsensusLevel} incrementAriaLabel={dialog.increaseConsensusLevel} /> ), }; const scopeStep: MethodCardPolicyStep = { id: "applicableScope", title: t.sectionHeadings.applicableScope, emptyDescription: dialog.scopeEmptyDescription, done: value.selectedApplicableScope.length > 0, summary: selectedSummary, renderEditor: () => ( onChange({ ...value, selectedApplicableScope: value.selectedApplicableScope.includes( scope, ) ? value.selectedApplicableScope.filter((item) => item !== scope) : [...value.selectedApplicableScope, scope], }) } onAddScope={(scope) => onChange({ ...value, applicableScope: [...value.applicableScope, scope], }) } /> ), }; return [ textStep({ id: "corePrinciple", title: t.sectionHeadings.corePrinciple, emptyDescription: dialog.emptyStepDescription, value: value.corePrinciple, onChange: (next) => onChange({ ...value, corePrinciple: next }), generateDraftText: generateDraft?.corePrinciple, generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), scopeStep, textStep({ id: "stepByStepInstructions", title: t.sectionHeadings.stepByStepInstructions, emptyDescription: dialog.emptyStepDescription, value: value.stepByStepInstructions, onChange: (next) => onChange({ ...value, stepByStepInstructions: next }), generateDraftText: generateDraft?.stepByStepInstructions, generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), consensusStep, textStep({ id: "objectionsDeadlocks", title: t.sectionHeadings.objectionsDeadlocks, emptyDescription: dialog.emptyStepDescription, value: value.objectionsDeadlocks, onChange: (next) => onChange({ ...value, objectionsDeadlocks: next }), generateDraftText: generateDraft?.objectionsDeadlocks, generateDraftLabel: draftField.generateDraft, generateDraftHint: draftField.generateDraftHint, filledHint: dialog.filledHint, placeholder: draftField.placeholder, }), ]; }