/* eslint-disable @typescript-eslint/no-explicit-any */ import { useEffect, useState } from "react"; import { BaseProps } from "../../Factory/BaseType"; import ConfirmationAlertView from "./ConfirmationAlertView"; import { useEffectiveStyle } from "../../utils/useEffectiveStyle"; export type ConfirmationAlertProps = BaseProps & { value: any; title: string; messageHeader?: string; messageBody?: string; iconUrl?: string; iconName?: string; confirmText?: string; cancelText?: string; onConfirm?: () => void; onCancel?: () => void; onModelUpdate?: ( callBack: ((args: any) => void) | null, fieldName: string, value: any, ) => void; handleHeader?: ( callback: (header: string) => void, header: string, viewModel?: Record, ) => void; handleBody?: ( callback: (body: string) => void, body: string, value?: any, ) => void; }; const ConfirmationAlert = (props: ConfirmationAlertProps) => { useEffectiveStyle(props.widgetStyle); const [header, setHeader] = useState(props.messageHeader); const [body, setBody] = useState(props.messageBody); useEffect(() => { if (props.handleHeader) { props.handleHeader(setHeader, props.messageHeader ?? "", props.viewModel); } else { setHeader(props.messageHeader); } }, [props.messageHeader, props.viewModel, props.handleHeader]); useEffect(() => { if (props.handleBody) { props.handleBody(setBody, props.messageBody ?? "", props.value); } else { setBody(props.messageBody); } }, [props.messageBody, props.value, props.handleBody]); // Clicking either button closes the dialog immediately. Previously the // confirm path awaited the action before closing, so a slow request left the // popup on screen for the whole round trip (and, from core 2.2.0, under the // global loader) - it looked stuck. Cancel had the same shape. // // Order matters. The schema-declared handlers arrive as props, but the // fallbacks live at value.onConfirm / value.onCancel - i.e. INSIDE the very // screenData field the close nulls out (the Grid writes them there in // handleHeaderAction). Resolve the handler to a local first, then close, // then invoke; closing first would drop the reference. const closeAlert = () => { props.onModelUpdate?.(null, props.screenDataField ?? "", null); }; // Not awaited: the dialog is already gone, so nothing is waiting on the // result. Actions log their own failures through ActionInvoker; this only // stops a rejected host-supplied closure from surfacing as an unhandled // rejection. const runDetached = (handler?: () => unknown) => { if (!handler) return; try { Promise.resolve(handler()).catch((error) => console.error("[vs-template] ConfirmationAlert action failed", error), ); } catch (error) { console.error("[vs-template] ConfirmationAlert action failed", error); } }; const handleCancel = () => { const onCancel = props.onCancel ?? props?.value?.onCancel; closeAlert(); runDetached(onCancel); }; const handleConfirm = () => { const onConfirm = props.onConfirm ?? props?.value?.onConfirm; closeAlert(); runDetached(onConfirm); }; return ( ); }; export default ConfirmationAlert;