import { AmountComparator, AmountCriteria, ApprovalUpdateActionType, ID, RemiApprovalRuleWithUser, RemiSetupApproverUpdateDataView } from '@zeniai/client-epic-state'; import { ResponsiveSized } from '../../../../context/windowSizeProvider'; import { ApprovalStageData } from '../../../commonSetUp/approval/ApprovalStageRow'; import { IsOrIsNotOperator } from '../../../commonSetUp/approval/OperatorIsOrIsNotPicker'; declare const name = "name"; declare const description = "description"; declare const amountCriteria = "amountCriteria"; declare const vendorCriteria = "vendorCriteria"; declare const departmentCriteria = "departmentCriteria"; declare const steps = "steps"; declare const separationOfDuties = "separationOfDuties"; declare const isFallback = "isFallback"; declare const applyToExistingReimbursements = "applyToExistingReimbursements"; /** * Form-side shape for vendor / department conditions. * * The widget primitive (`LabeledMultiSelectField`) stores its value as * `{allOptions, selectedOptions}`, which doesn't match the wire shape * `{type, operator, vendorIds | departmentIds}`. The form stores the * widget-native shape under each slot and the screen connector * translates to the canonical `VendorCriteria` / `DepartmentCriteria` * at save time. */ export interface MultiSelectFormValue { allOptions: string[]; selectedOptions: string[]; } export interface VendorConditionFormValue { operator: { allOptions: IsOrIsNotOperator[]; selectedOption?: IsOrIsNotOperator; }; selection: MultiSelectFormValue; } export interface DepartmentConditionFormValue { operator: { allOptions: IsOrIsNotOperator[]; selectedOption?: IsOrIsNotOperator; }; selection: MultiSelectFormValue; } /** * Form-side amount shape. See the BillPay equivalent for the fuller * rationale — comparator is wrapped because the dropdown is * SingleSelectField-driven, min / max remain canonical because they * are driven by TextField. */ export interface AmountConditionFormValue { comparator: { allOptions: AmountComparator[]; selectedOption?: AmountComparator; }; type: "amount"; max?: AmountCriteria["max"]; min?: AmountCriteria["min"]; } /** * Full Approval Rules 3.0 form data shape. * * Each top-level slot corresponds to one section of the form. Bindings * land incrementally — the slots are declared up front so the contract is * stable across tasks: * - amountCriteria — task #8 * - vendorCriteria / departmentCriteria — tasks #9–#10 (this change) * - separationOfDuties — task #14 * - isFallback — task #15 */ export interface FormData { [applyToExistingReimbursements]: string[]; [steps]: ApprovalStageData[]; [amountCriteria]?: AmountConditionFormValue; [departmentCriteria]?: DepartmentConditionFormValue; [description]?: string; [isFallback]?: boolean; [name]?: string; [separationOfDuties]?: boolean; [vendorCriteria]?: VendorConditionFormValue; } export interface ReimbursementApprovalRuleDetailPageProps { /** * User-resolved approval rules used by RuleOverlapBanner. See the * BillPay equivalent for the rationale — the update-data view only * exposes the raw `ApprovalRule[]`, but the banner needs resolved * actor names to render the 'Then:' section. */ allApprovalRulesWithUser: RemiApprovalRuleWithUser[]; /** * Vendor list available to the rule. Threaded from `state.contactState` * by the screen connector. Empty when the contact slice hasn't loaded * yet — the multi-select renders no options in that case. */ allVendorIds: string[]; approvalUpdateActionType: ApprovalUpdateActionType; localData: RemiSetupApproverUpdateDataView; vendorNamesById: Record; /** * When editing an existing rule, the rule being edited. Used to * exclude it from the overlap check (a rule should not flag itself * as conflicting). Undefined for create flows. */ editingRuleId?: ID; onApprovalRuleDataUpdated: (formData: FormData) => void; onBackClick: () => void; /** * Approval Rules 3.0 — invoked from RuleOverlapBanner when the user * clicks Edit on one of the conflicting rules. The screen connector * wires this to a same-tab navigation to that rule's detail page. */ onEditExistingRule: (ruleId: string) => void; onResetClick: () => void; onSaveRuleClick: () => void; onSaveRuleSuccess: () => void; } /** * Dimensions */ export declare const D: { footerPadding: ResponsiveSized; }; declare function ReimbursementApprovalRuleDetailPage({ localData, approvalUpdateActionType, allApprovalRulesWithUser, allVendorIds, editingRuleId, vendorNamesById, onBackClick, onApprovalRuleDataUpdated, onEditExistingRule, onResetClick, onSaveRuleClick, onSaveRuleSuccess, }: ReimbursementApprovalRuleDetailPageProps): import("react/jsx-runtime").JSX.Element; export default ReimbursementApprovalRuleDetailPage; export declare const uniqueFormName: (sectionId: ID) => `${string}_form`; type FormDataKeys = keyof FormData; export declare const uniqueName: (key: FormDataKeys) => "description" | "name" | "steps" | "isFallback" | "separationOfDuties" | "amountCriteria" | "departmentCriteria" | "vendorCriteria" | "applyToExistingReimbursements"; export type FormDataKeyUniqueNames = ReturnType;