pixelon 0.3.27 → 0.3.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/atoms/chat/CurrencyDisplay/ChatCurrencyDisplay.d.ts +18 -0
- package/dist/components/atoms/chat/CurrencyDisplay/index.d.ts +2 -0
- package/dist/components/atoms/chat/index.d.ts +2 -0
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/CostSummaryField.d.ts +13 -0
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/ReactiveFormView.d.ts +2 -0
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/types.d.ts +19 -1
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/useReactiveForm.d.ts +1 -0
- package/dist/components/molecules/chat/StructuredContent/components/SelectWithConfirm/types.d.ts +11 -0
- package/dist/components/molecules/chat/StructuredContent/components/SelectWithConfirm/useSelectEndpoint.d.ts +11 -0
- package/dist/components/molecules/chat/StructuredContent/components/index.d.ts +1 -0
- package/dist/components/molecules/chat/StructuredContent/helpers/AnsweredSummary.d.ts +5 -0
- package/dist/components/molecules/chat/StructuredContent/helpers/types.d.ts +18 -0
- package/dist/components/molecules/chat/StructuredContent/helpers/useComponentInteraction.d.ts +1 -1
- package/dist/core/chat/ChatConfigContext.d.ts +8 -0
- package/dist/core/eventBus/chatEventBus.d.ts +8 -1
- package/dist/index.esm.js +443 -99
- package/dist/index.js +443 -99
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +3 -1
package/dist/index.esm.js
CHANGED
|
@@ -1618,8 +1618,47 @@ function parseContent(content) {
|
|
|
1618
1618
|
return null;
|
|
1619
1619
|
}
|
|
1620
1620
|
|
|
1621
|
+
const TERMINAL_STATUS = /* @__PURE__ */ new Set(["answered", "cancelled", "expired"]);
|
|
1621
1622
|
const DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge", "reactive_form", "carousel"]);
|
|
1622
1623
|
|
|
1624
|
+
const AnsweredSummary = ({ component }) => {
|
|
1625
|
+
const status = component.status;
|
|
1626
|
+
const values = component.selected_values ?? [];
|
|
1627
|
+
const labels = values.map((v) => v.label).filter(Boolean).join(", ");
|
|
1628
|
+
let icon = "\u2713";
|
|
1629
|
+
let text = labels || "Respondido";
|
|
1630
|
+
let color = "#3a8a3a";
|
|
1631
|
+
if (status === "cancelled") {
|
|
1632
|
+
icon = "\u2715";
|
|
1633
|
+
text = "Cancelado";
|
|
1634
|
+
color = "#999";
|
|
1635
|
+
} else if (status === "expired") {
|
|
1636
|
+
icon = "\u231B";
|
|
1637
|
+
text = "Expir\xF3";
|
|
1638
|
+
color = "#b58a00";
|
|
1639
|
+
}
|
|
1640
|
+
return /* @__PURE__ */ jsxs(
|
|
1641
|
+
"div",
|
|
1642
|
+
{
|
|
1643
|
+
style: {
|
|
1644
|
+
display: "inline-flex",
|
|
1645
|
+
alignItems: "center",
|
|
1646
|
+
gap: "6px",
|
|
1647
|
+
padding: "6px 12px",
|
|
1648
|
+
borderRadius: "999px",
|
|
1649
|
+
background: "rgba(0,0,0,0.04)",
|
|
1650
|
+
color,
|
|
1651
|
+
fontSize: "0.875rem",
|
|
1652
|
+
fontWeight: 500
|
|
1653
|
+
},
|
|
1654
|
+
children: [
|
|
1655
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, children: icon }),
|
|
1656
|
+
/* @__PURE__ */ jsx("span", { children: text })
|
|
1657
|
+
]
|
|
1658
|
+
}
|
|
1659
|
+
);
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1623
1662
|
const useAppHeight$5 = () => {
|
|
1624
1663
|
useEffect(() => {
|
|
1625
1664
|
const setDrawerHeight = () => {
|
|
@@ -1796,13 +1835,14 @@ function useComponentInteraction({
|
|
|
1796
1835
|
}) {
|
|
1797
1836
|
const [isConfirmed, setIsConfirmed] = useState(false);
|
|
1798
1837
|
const emitInteraction = useCallback(
|
|
1799
|
-
(value, label) => {
|
|
1838
|
+
(value, label, actionId) => {
|
|
1800
1839
|
eventBus?.emit(CHAT_EVENT.COMPONENT_INTERACTION, {
|
|
1801
1840
|
fieldName,
|
|
1802
1841
|
value,
|
|
1803
1842
|
label,
|
|
1804
1843
|
componentType,
|
|
1805
|
-
assistantMessageId
|
|
1844
|
+
assistantMessageId,
|
|
1845
|
+
actionId
|
|
1806
1846
|
});
|
|
1807
1847
|
setIsConfirmed(true);
|
|
1808
1848
|
},
|
|
@@ -1811,6 +1851,114 @@ function useComponentInteraction({
|
|
|
1811
1851
|
return { emitInteraction, isConfirmed };
|
|
1812
1852
|
}
|
|
1813
1853
|
|
|
1854
|
+
const FETCH_TIMEOUT_MS = 12e4;
|
|
1855
|
+
function fetchViaEventBus(eventBus, service, url, method, body) {
|
|
1856
|
+
const requestId = globalThis.crypto?.randomUUID?.() ?? "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
1857
|
+
const r = Math.random() * 16 | 0;
|
|
1858
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
1859
|
+
});
|
|
1860
|
+
return new Promise((resolve, reject) => {
|
|
1861
|
+
const timeoutId = setTimeout(() => {
|
|
1862
|
+
unsubscribe();
|
|
1863
|
+
reject(new Error(`Timeout: no response for ${url} after ${FETCH_TIMEOUT_MS}ms`));
|
|
1864
|
+
}, FETCH_TIMEOUT_MS);
|
|
1865
|
+
const unsubscribe = eventBus.on(CHAT_EVENT.FETCH_RESPONSE, (response) => {
|
|
1866
|
+
if (response.requestId !== requestId) return;
|
|
1867
|
+
clearTimeout(timeoutId);
|
|
1868
|
+
unsubscribe();
|
|
1869
|
+
if (response.httpError) {
|
|
1870
|
+
reject(new Error(response.httpError));
|
|
1871
|
+
} else {
|
|
1872
|
+
resolve(response.data);
|
|
1873
|
+
}
|
|
1874
|
+
});
|
|
1875
|
+
eventBus.emit(CHAT_EVENT.FETCH_REQUEST, {
|
|
1876
|
+
requestId,
|
|
1877
|
+
service,
|
|
1878
|
+
url,
|
|
1879
|
+
method,
|
|
1880
|
+
...body ? { body } : {}
|
|
1881
|
+
});
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
function mapResponseToOptions(data, endpoint) {
|
|
1886
|
+
let items = [];
|
|
1887
|
+
if (endpoint.response_path) {
|
|
1888
|
+
const parts = endpoint.response_path.split(".");
|
|
1889
|
+
let current = data;
|
|
1890
|
+
for (const part of parts) {
|
|
1891
|
+
if (current != null && typeof current === "object") {
|
|
1892
|
+
current = current[part];
|
|
1893
|
+
} else {
|
|
1894
|
+
return [];
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
items = Array.isArray(current) ? current : [];
|
|
1898
|
+
} else if (Array.isArray(data)) {
|
|
1899
|
+
items = data;
|
|
1900
|
+
} else {
|
|
1901
|
+
return [];
|
|
1902
|
+
}
|
|
1903
|
+
return items.filter((item) => item != null && typeof item === "object").map((item) => ({
|
|
1904
|
+
value: String(item[endpoint.value_field] ?? ""),
|
|
1905
|
+
label: String(item[endpoint.label_field] ?? "")
|
|
1906
|
+
}));
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
function normalizeBody(body) {
|
|
1910
|
+
if (!body) return void 0;
|
|
1911
|
+
const normalized = { ...body };
|
|
1912
|
+
for (const [key, val] of Object.entries(normalized)) {
|
|
1913
|
+
if (/s_id$/.test(key) && typeof val === "string") {
|
|
1914
|
+
normalized[key] = [val];
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
return normalized;
|
|
1918
|
+
}
|
|
1919
|
+
function useSelectEndpoint(endpoint, eventBus) {
|
|
1920
|
+
const [options, setOptions] = useState([]);
|
|
1921
|
+
const [status, setStatus] = useState(endpoint ? "loading" : "idle");
|
|
1922
|
+
const [errorMessage, setErrorMessage] = useState("");
|
|
1923
|
+
const fetchedRef = useRef(false);
|
|
1924
|
+
const endpointRef = useRef(endpoint);
|
|
1925
|
+
endpointRef.current = endpoint;
|
|
1926
|
+
const doFetch = useCallback(async () => {
|
|
1927
|
+
const ep = endpointRef.current;
|
|
1928
|
+
if (!ep || fetchedRef.current) return;
|
|
1929
|
+
fetchedRef.current = true;
|
|
1930
|
+
if (!eventBus) {
|
|
1931
|
+
setOptions([
|
|
1932
|
+
{ value: "mock-1", label: "Mock Option 1" },
|
|
1933
|
+
{ value: "mock-2", label: "Mock Option 2" }
|
|
1934
|
+
]);
|
|
1935
|
+
setStatus("idle");
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
try {
|
|
1939
|
+
const body = normalizeBody(ep.body);
|
|
1940
|
+
if (ep.method.toUpperCase() === "POST" && !body) {
|
|
1941
|
+
setErrorMessage("Faltan par\xE1metros para cargar opciones");
|
|
1942
|
+
setStatus("error");
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
const data = await fetchViaEventBus(eventBus, ep.service, ep.url, ep.method, body);
|
|
1946
|
+
const mapped = mapResponseToOptions(data, ep);
|
|
1947
|
+
setOptions(mapped);
|
|
1948
|
+
setStatus("idle");
|
|
1949
|
+
} catch (err) {
|
|
1950
|
+
setErrorMessage(err instanceof Error ? err.message : "Error al cargar opciones");
|
|
1951
|
+
setStatus("error");
|
|
1952
|
+
}
|
|
1953
|
+
}, [eventBus]);
|
|
1954
|
+
useEffect(() => {
|
|
1955
|
+
if (endpoint && !fetchedRef.current) {
|
|
1956
|
+
doFetch();
|
|
1957
|
+
}
|
|
1958
|
+
}, [endpoint, doFetch]);
|
|
1959
|
+
return { options, status, errorMessage };
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1814
1962
|
const MOBILE_BREAKPOINT$4 = 640;
|
|
1815
1963
|
const useIsMobile$5 = () => {
|
|
1816
1964
|
const [isMobile, setIsMobile] = useState(
|
|
@@ -1834,10 +1982,15 @@ const SelectWithConfirm = ({
|
|
|
1834
1982
|
const [searchValue, setSearchValue] = useState("");
|
|
1835
1983
|
const searchInputRef = useRef(null);
|
|
1836
1984
|
const isMobile = useIsMobile$5();
|
|
1837
|
-
const { field_name, value, ...componentProps } = component.props;
|
|
1838
|
-
const
|
|
1985
|
+
const { field_name, value, endpoint: endpointProp, ...componentProps } = component.props;
|
|
1986
|
+
const endpoint = endpointProp;
|
|
1987
|
+
const { options: endpointOptions, status: endpointStatus, errorMessage } = useSelectEndpoint(endpoint, eventBus);
|
|
1988
|
+
const staticOptions = componentProps.options || [];
|
|
1989
|
+
const options = endpoint ? endpointOptions : staticOptions;
|
|
1839
1990
|
const placeholder = componentProps.placeholder || "Seleccionar...";
|
|
1840
1991
|
const label = componentProps.label || "";
|
|
1992
|
+
const isLoading = endpointStatus === "loading";
|
|
1993
|
+
const isError = endpointStatus === "error";
|
|
1841
1994
|
const { emitInteraction, isConfirmed } = useComponentInteraction({
|
|
1842
1995
|
eventBus,
|
|
1843
1996
|
fieldName: component.props.field_name,
|
|
@@ -1857,6 +2010,18 @@ const SelectWithConfirm = ({
|
|
|
1857
2010
|
}
|
|
1858
2011
|
}, [isDrawerOpen]);
|
|
1859
2012
|
if (isConfirmed) return null;
|
|
2013
|
+
if (isLoading) {
|
|
2014
|
+
return /* @__PURE__ */ jsxs("div", { className: "px-chat-select-with-confirm", children: [
|
|
2015
|
+
label && /* @__PURE__ */ jsx("label", { className: "px-chat-select-with-confirm__label", children: label }),
|
|
2016
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-select-with-confirm__loading", children: "Cargando opciones..." })
|
|
2017
|
+
] });
|
|
2018
|
+
}
|
|
2019
|
+
if (isError) {
|
|
2020
|
+
return /* @__PURE__ */ jsxs("div", { className: "px-chat-select-with-confirm", children: [
|
|
2021
|
+
label && /* @__PURE__ */ jsx("label", { className: "px-chat-select-with-confirm__label", children: label }),
|
|
2022
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-select-with-confirm__error", children: errorMessage })
|
|
2023
|
+
] });
|
|
2024
|
+
}
|
|
1860
2025
|
if (isMobile) {
|
|
1861
2026
|
return /* @__PURE__ */ jsxs("div", { className: "px-chat-select-with-confirm", children: [
|
|
1862
2027
|
label && /* @__PURE__ */ jsx("label", { className: "px-chat-select-with-confirm__label", children: label }),
|
|
@@ -1976,8 +2141,8 @@ const SelectWithConfirm = ({
|
|
|
1976
2141
|
/* @__PURE__ */ jsx(
|
|
1977
2142
|
Select$2,
|
|
1978
2143
|
{
|
|
1979
|
-
options: [],
|
|
1980
2144
|
...componentProps,
|
|
2145
|
+
options,
|
|
1981
2146
|
variant: "chat",
|
|
1982
2147
|
mode: "single",
|
|
1983
2148
|
showSearch: true,
|
|
@@ -2514,6 +2679,22 @@ const ConfirmButton = ({
|
|
|
2514
2679
|
assistantMessageId
|
|
2515
2680
|
});
|
|
2516
2681
|
if (isConfirmed) return null;
|
|
2682
|
+
const actions = component.actions;
|
|
2683
|
+
if (actions && actions.length > 0) {
|
|
2684
|
+
return /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: actions.map((a) => /* @__PURE__ */ jsx(
|
|
2685
|
+
Button$1,
|
|
2686
|
+
{
|
|
2687
|
+
variant: a.intent === "primary" ? "primary" : "secondary",
|
|
2688
|
+
onClick: () => emitInteraction(
|
|
2689
|
+
a.emits_value ? component.props.value : a.value,
|
|
2690
|
+
a.label,
|
|
2691
|
+
a.id
|
|
2692
|
+
),
|
|
2693
|
+
children: a.label
|
|
2694
|
+
},
|
|
2695
|
+
a.id
|
|
2696
|
+
)) });
|
|
2697
|
+
}
|
|
2517
2698
|
return /* @__PURE__ */ jsx(
|
|
2518
2699
|
Button$1,
|
|
2519
2700
|
{
|
|
@@ -3137,7 +3318,7 @@ const SelectField$1 = ({ field, value, disabled, loading, options, onChange, dra
|
|
|
3137
3318
|
),
|
|
3138
3319
|
searchValue && /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-select-drawer__search-clear", onClick: () => setSearchValue(""), children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" }) })
|
|
3139
3320
|
] }),
|
|
3140
|
-
/* @__PURE__ */ jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "px-chat-select-drawer__empty", children: "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
|
|
3321
|
+
/* @__PURE__ */ jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "px-chat-select-drawer__empty", children: field.empty_message || "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
|
|
3141
3322
|
const isSelected = opt.value === value;
|
|
3142
3323
|
return /* @__PURE__ */ jsxs(
|
|
3143
3324
|
"li",
|
|
@@ -3258,7 +3439,7 @@ const SelectMultipleField = ({ field, value, disabled, loading, options, onChang
|
|
|
3258
3439
|
),
|
|
3259
3440
|
searchValue && /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-select-drawer__search-clear", onClick: () => setSearchValue(""), children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" }) })
|
|
3260
3441
|
] }),
|
|
3261
|
-
/* @__PURE__ */ jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", "aria-multiselectable": "true", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "px-chat-select-drawer__empty", children: "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
|
|
3442
|
+
/* @__PURE__ */ jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", "aria-multiselectable": "true", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "px-chat-select-drawer__empty", children: field.empty_message || "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
|
|
3262
3443
|
const isChecked = selected.includes(opt.value);
|
|
3263
3444
|
return /* @__PURE__ */ jsxs(
|
|
3264
3445
|
"li",
|
|
@@ -3356,6 +3537,200 @@ const DateField = ({ field, value, disabled, onChange, drawerPlacement }) => {
|
|
|
3356
3537
|
] });
|
|
3357
3538
|
};
|
|
3358
3539
|
|
|
3540
|
+
const PREFIX$3 = "px-chat-currency";
|
|
3541
|
+
const ChatCurrencyDisplay = ({
|
|
3542
|
+
value,
|
|
3543
|
+
currencyCode,
|
|
3544
|
+
currencySymbol,
|
|
3545
|
+
showCode = true,
|
|
3546
|
+
size = "md",
|
|
3547
|
+
className
|
|
3548
|
+
}) => {
|
|
3549
|
+
const { locale, currency: configCurrency } = useChatConfig();
|
|
3550
|
+
const code = currencyCode || configCurrency?.code || "COP";
|
|
3551
|
+
const symbol = currencySymbol || configCurrency?.symbol || "$";
|
|
3552
|
+
const formatted = useMemo(() => {
|
|
3553
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
3554
|
+
const num = typeof value === "string" ? parseFloat(value) : value;
|
|
3555
|
+
if (isNaN(num)) return null;
|
|
3556
|
+
try {
|
|
3557
|
+
return new Intl.NumberFormat(locale || "es-CO", {
|
|
3558
|
+
minimumFractionDigits: 2,
|
|
3559
|
+
maximumFractionDigits: 2
|
|
3560
|
+
}).format(num);
|
|
3561
|
+
} catch {
|
|
3562
|
+
return num.toFixed(2);
|
|
3563
|
+
}
|
|
3564
|
+
}, [value, locale]);
|
|
3565
|
+
if (!formatted) return /* @__PURE__ */ jsx("span", { className: `${PREFIX$3} ${PREFIX$3}--empty`, children: "-" });
|
|
3566
|
+
const classes = [PREFIX$3, `${PREFIX$3}--${size}`, className].filter(Boolean).join(" ");
|
|
3567
|
+
return /* @__PURE__ */ jsxs("span", { className: classes, children: [
|
|
3568
|
+
/* @__PURE__ */ jsx("span", { className: `${PREFIX$3}__symbol`, children: symbol }),
|
|
3569
|
+
" ",
|
|
3570
|
+
/* @__PURE__ */ jsx("span", { className: `${PREFIX$3}__value`, children: formatted }),
|
|
3571
|
+
showCode && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3572
|
+
" ",
|
|
3573
|
+
/* @__PURE__ */ jsx("span", { className: `${PREFIX$3}__code`, children: code })
|
|
3574
|
+
] })
|
|
3575
|
+
] });
|
|
3576
|
+
};
|
|
3577
|
+
ChatCurrencyDisplay.displayName = "ChatCurrencyDisplay";
|
|
3578
|
+
|
|
3579
|
+
function resolveVariable(template, formValues, fieldStates) {
|
|
3580
|
+
if (!template.startsWith("$")) return template;
|
|
3581
|
+
const withoutDollar = template.slice(1);
|
|
3582
|
+
const dotIndex = withoutDollar.indexOf(".");
|
|
3583
|
+
const fieldName = dotIndex >= 0 ? withoutDollar.slice(0, dotIndex) : withoutDollar;
|
|
3584
|
+
const prop = dotIndex >= 0 ? withoutDollar.slice(dotIndex + 1) : null;
|
|
3585
|
+
const value = formValues[fieldName];
|
|
3586
|
+
const state = fieldStates[fieldName];
|
|
3587
|
+
if (!prop) return value;
|
|
3588
|
+
if (prop === "label" && state) {
|
|
3589
|
+
return state.label || "";
|
|
3590
|
+
}
|
|
3591
|
+
if (prop === "labels" && state && Array.isArray(value)) {
|
|
3592
|
+
return value.map((v) => {
|
|
3593
|
+
const opt = state.options.find((o) => o.value === v);
|
|
3594
|
+
return opt?.label || v;
|
|
3595
|
+
}).join(", ");
|
|
3596
|
+
}
|
|
3597
|
+
if (state) {
|
|
3598
|
+
const selectedOpt = state.options.find((o) => o.value === value);
|
|
3599
|
+
if (selectedOpt && prop in selectedOpt) {
|
|
3600
|
+
return selectedOpt[prop];
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
return "";
|
|
3604
|
+
}
|
|
3605
|
+
function resolveBody(obj, formValues, fieldStates) {
|
|
3606
|
+
if (typeof obj === "string") return resolveVariable(obj, formValues, fieldStates);
|
|
3607
|
+
if (Array.isArray(obj)) return obj.map((item) => resolveBody(item, formValues, fieldStates));
|
|
3608
|
+
if (obj !== null && typeof obj === "object") {
|
|
3609
|
+
const resolved = {};
|
|
3610
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
3611
|
+
resolved[key] = resolveBody(value, formValues, fieldStates);
|
|
3612
|
+
}
|
|
3613
|
+
return resolved;
|
|
3614
|
+
}
|
|
3615
|
+
return obj;
|
|
3616
|
+
}
|
|
3617
|
+
function resolveParams(params, formValues, fieldStates) {
|
|
3618
|
+
const resolved = {};
|
|
3619
|
+
for (const [key, template] of Object.entries(params)) {
|
|
3620
|
+
resolved[key] = resolveVariable(template, formValues, fieldStates);
|
|
3621
|
+
}
|
|
3622
|
+
return resolved;
|
|
3623
|
+
}
|
|
3624
|
+
function resolveSummaryRows(rows, formValues, fieldStates) {
|
|
3625
|
+
return rows.map((row) => ({
|
|
3626
|
+
label: row.label,
|
|
3627
|
+
value: String(resolveVariable(row.value, formValues, fieldStates) ?? "")
|
|
3628
|
+
}));
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
const CostSummaryField = ({
|
|
3632
|
+
field,
|
|
3633
|
+
values,
|
|
3634
|
+
fieldStates,
|
|
3635
|
+
onCostResolved,
|
|
3636
|
+
eventBus,
|
|
3637
|
+
onCancel
|
|
3638
|
+
}) => {
|
|
3639
|
+
const [totalCost, setTotalCost] = useState(null);
|
|
3640
|
+
const [loading, setLoading] = useState(true);
|
|
3641
|
+
const [error, setError] = useState("");
|
|
3642
|
+
const selectedItems = useMemo(() => {
|
|
3643
|
+
if (!field.items_from) return [];
|
|
3644
|
+
const { source_field, label_key, value_key } = field.items_from;
|
|
3645
|
+
const sourceState = fieldStates[source_field];
|
|
3646
|
+
const selectedValues = values[source_field];
|
|
3647
|
+
if (!sourceState?.options || !selectedValues) return [];
|
|
3648
|
+
const selectedArr = Array.isArray(selectedValues) ? selectedValues : [selectedValues];
|
|
3649
|
+
return sourceState.options.filter((opt) => selectedArr.includes(opt.value)).map((opt) => ({
|
|
3650
|
+
label: String(opt[label_key] || opt.label || ""),
|
|
3651
|
+
value: Number(opt[value_key] || 0)
|
|
3652
|
+
}));
|
|
3653
|
+
}, [field.items_from, fieldStates, values]);
|
|
3654
|
+
const fetchedRef = useRef(false);
|
|
3655
|
+
useEffect(() => {
|
|
3656
|
+
if (!field.endpoint || !eventBus || fetchedRef.current) {
|
|
3657
|
+
if (!field.endpoint || !eventBus) setLoading(false);
|
|
3658
|
+
return;
|
|
3659
|
+
}
|
|
3660
|
+
fetchedRef.current = true;
|
|
3661
|
+
const body = resolveBody(field.endpoint.body || {}, values, fieldStates);
|
|
3662
|
+
setLoading(true);
|
|
3663
|
+
setError("");
|
|
3664
|
+
fetchViaEventBus(eventBus, field.endpoint.service, field.endpoint.url, field.endpoint.method, body).then((data) => {
|
|
3665
|
+
const resp = data;
|
|
3666
|
+
if (resp?.notification_type && String(resp.notification_type).toUpperCase() !== "SUCCESS") {
|
|
3667
|
+
setError(String(resp.message || "Error al calcular costo"));
|
|
3668
|
+
return;
|
|
3669
|
+
}
|
|
3670
|
+
const responseData = resp?.response;
|
|
3671
|
+
const totalField = field.endpoint.total_field || "total_cost";
|
|
3672
|
+
const cost = Number(responseData?.[totalField] ?? resp?.[totalField] ?? 0);
|
|
3673
|
+
setTotalCost(cost);
|
|
3674
|
+
if (onCostResolved) {
|
|
3675
|
+
try {
|
|
3676
|
+
const formatted = new Intl.NumberFormat("es-CO", { style: "currency", currency: "COP" }).format(cost);
|
|
3677
|
+
onCostResolved(field.name, formatted);
|
|
3678
|
+
} catch {
|
|
3679
|
+
onCostResolved(field.name, `$${cost}`);
|
|
3680
|
+
}
|
|
3681
|
+
}
|
|
3682
|
+
}).catch((err) => {
|
|
3683
|
+
setError(err instanceof Error ? err.message : "Error al calcular costo");
|
|
3684
|
+
}).finally(() => setLoading(false));
|
|
3685
|
+
}, [field.endpoint, eventBus]);
|
|
3686
|
+
const handleCancel = () => {
|
|
3687
|
+
if (field.on_cancel && eventBus) {
|
|
3688
|
+
if (field.on_cancel.type === "system_message") {
|
|
3689
|
+
eventBus.emit(CHAT_EVENT.FORM_TRACE, {
|
|
3690
|
+
chatId: "",
|
|
3691
|
+
formTitle: "",
|
|
3692
|
+
source: "reactive_form",
|
|
3693
|
+
phase: "cancel",
|
|
3694
|
+
data: { message: field.on_cancel.message },
|
|
3695
|
+
service: "",
|
|
3696
|
+
url: "",
|
|
3697
|
+
method: ""
|
|
3698
|
+
});
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
onCancel();
|
|
3702
|
+
};
|
|
3703
|
+
if (loading) {
|
|
3704
|
+
return /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__cost-summary px-chat-rf__cost-summary--loading", children: [
|
|
3705
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__cost-summary__title", children: field.label || "Resumen de costos" }),
|
|
3706
|
+
/* @__PURE__ */ jsxs("div", { className: "px-chat-rf__cost-summary__loader", children: [
|
|
3707
|
+
/* @__PURE__ */ jsx("span", { className: "px-chat-rf__spinner" }),
|
|
3708
|
+
/* @__PURE__ */ jsx("span", { children: "Calculando costo..." })
|
|
3709
|
+
] })
|
|
3710
|
+
] });
|
|
3711
|
+
}
|
|
3712
|
+
if (error) {
|
|
3713
|
+
return /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__cost-summary px-chat-rf__cost-summary--error", children: [
|
|
3714
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__cost-summary__title", children: field.label || "Resumen de costos" }),
|
|
3715
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__cost-summary__error", children: error }),
|
|
3716
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--secondary", onClick: handleCancel, children: "Cancelar" })
|
|
3717
|
+
] });
|
|
3718
|
+
}
|
|
3719
|
+
return /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__cost-summary", children: [
|
|
3720
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__cost-summary__title", children: field.label || "Resumen de costos" }),
|
|
3721
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__cost-summary__items", children: selectedItems.map((item, i) => /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__cost-summary__item", children: [
|
|
3722
|
+
/* @__PURE__ */ jsx("span", { className: "px-chat-rf__cost-summary__item-label", children: item.label }),
|
|
3723
|
+
/* @__PURE__ */ jsx(ChatCurrencyDisplay, { value: item.value, size: "sm" })
|
|
3724
|
+
] }, i)) }),
|
|
3725
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__cost-summary__divider" }),
|
|
3726
|
+
/* @__PURE__ */ jsxs("div", { className: "px-chat-rf__cost-summary__total", children: [
|
|
3727
|
+
/* @__PURE__ */ jsx("span", { className: "px-chat-rf__cost-summary__total-label", children: "Total" }),
|
|
3728
|
+
/* @__PURE__ */ jsx(ChatCurrencyDisplay, { value: totalCost, size: "lg" })
|
|
3729
|
+
] }),
|
|
3730
|
+
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__cost-summary__actions", children: /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--secondary", onClick: handleCancel, children: "Cancelar" }) })
|
|
3731
|
+
] });
|
|
3732
|
+
};
|
|
3733
|
+
|
|
3359
3734
|
const checkIcon = /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
3360
3735
|
const calendarIcon = /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
3361
3736
|
/* @__PURE__ */ jsx("rect", { x: "2", y: "3", width: "12", height: "11", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
@@ -3371,7 +3746,7 @@ const formIcon = /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBo
|
|
|
3371
3746
|
] });
|
|
3372
3747
|
const chevronDown = /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
3373
3748
|
const chevronRight = /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M4.5 3L7.5 6L4.5 9", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
3374
|
-
const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form, drawerPlacement = "bottom" }) => {
|
|
3749
|
+
const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form, drawerPlacement = "bottom", eventBus }) => {
|
|
3375
3750
|
const {
|
|
3376
3751
|
formStatus,
|
|
3377
3752
|
setFormStatus,
|
|
@@ -3387,6 +3762,7 @@ const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form
|
|
|
3387
3762
|
handleNext,
|
|
3388
3763
|
handleBack,
|
|
3389
3764
|
handleSubmit,
|
|
3765
|
+
isSubmitting,
|
|
3390
3766
|
getDependencies,
|
|
3391
3767
|
allDepsResolved,
|
|
3392
3768
|
resolveSummaryRows
|
|
@@ -3446,11 +3822,25 @@ const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form
|
|
|
3446
3822
|
const renderSummaryActions = () => {
|
|
3447
3823
|
const actions = summary.actions;
|
|
3448
3824
|
if (!actions || actions.length === 0) {
|
|
3449
|
-
return /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--primary px-chat-rf__btn--full", onClick: handleSubmit, children: submit.label });
|
|
3825
|
+
return /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--primary px-chat-rf__btn--full", onClick: handleSubmit, disabled: isSubmitting, children: isSubmitting ? /* @__PURE__ */ jsx("span", { className: "px-chat-rf__spinner" }) : submit.label });
|
|
3450
3826
|
}
|
|
3451
3827
|
const actionHandlers = {
|
|
3452
3828
|
submit: handleSubmit,
|
|
3453
|
-
close: () =>
|
|
3829
|
+
close: () => {
|
|
3830
|
+
if (eventBus) {
|
|
3831
|
+
eventBus.emit(CHAT_EVENT.FORM_TRACE, {
|
|
3832
|
+
chatId: "",
|
|
3833
|
+
formTitle: "",
|
|
3834
|
+
source: "reactive_form",
|
|
3835
|
+
phase: "cancel",
|
|
3836
|
+
data: { message: "El usuario cancel\xF3 el agendamiento de la cita." },
|
|
3837
|
+
service: "",
|
|
3838
|
+
url: "",
|
|
3839
|
+
method: ""
|
|
3840
|
+
});
|
|
3841
|
+
}
|
|
3842
|
+
setFormStatus("closed");
|
|
3843
|
+
},
|
|
3454
3844
|
back: handleBack
|
|
3455
3845
|
};
|
|
3456
3846
|
return /* @__PURE__ */ jsx("div", { className: "px-chat-rf__nav", children: actions.map((act, i) => /* @__PURE__ */ jsx(
|
|
@@ -3460,7 +3850,8 @@ const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form
|
|
|
3460
3850
|
className: `px-chat-rf__btn px-chat-rf__btn--${act.variant || "primary"}`,
|
|
3461
3851
|
onClick: actionHandlers[act.action] || (() => {
|
|
3462
3852
|
}),
|
|
3463
|
-
|
|
3853
|
+
disabled: act.action === "submit" && isSubmitting,
|
|
3854
|
+
children: act.action === "submit" && isSubmitting ? /* @__PURE__ */ jsx("span", { className: "px-chat-rf__spinner" }) : act.label
|
|
3464
3855
|
},
|
|
3465
3856
|
i
|
|
3466
3857
|
)) });
|
|
@@ -3493,8 +3884,15 @@ const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form
|
|
|
3493
3884
|
)
|
|
3494
3885
|
] }),
|
|
3495
3886
|
prevStep.fields.map((fname) => {
|
|
3496
|
-
const fs = fieldStates[fname];
|
|
3497
3887
|
const fld = fields.find((f) => f.name === fname);
|
|
3888
|
+
if (fld?.type === "cost_summary") {
|
|
3889
|
+
const costLabel = fieldStates[fname]?.label;
|
|
3890
|
+
return costLabel ? /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__completed-field", children: [
|
|
3891
|
+
/* @__PURE__ */ jsx("span", { className: "px-chat-rf__completed-field-label", children: "Total:" }),
|
|
3892
|
+
/* @__PURE__ */ jsx("span", { className: "px-chat-rf__completed-field-value", children: costLabel })
|
|
3893
|
+
] }, fname) : null;
|
|
3894
|
+
}
|
|
3895
|
+
const fs = fieldStates[fname];
|
|
3498
3896
|
return /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__completed-field", children: [
|
|
3499
3897
|
/* @__PURE__ */ jsxs("span", { className: "px-chat-rf__completed-field-label", children: [
|
|
3500
3898
|
fld?.label,
|
|
@@ -3507,6 +3905,20 @@ const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form
|
|
|
3507
3905
|
/* @__PURE__ */ jsxs("div", { className: "px-chat-rf__active-step", children: [
|
|
3508
3906
|
/* @__PURE__ */ jsx("div", { className: "px-chat-rf__step-title", children: step.title }),
|
|
3509
3907
|
stepFields.map((field) => {
|
|
3908
|
+
if (field.type === "cost_summary") {
|
|
3909
|
+
return /* @__PURE__ */ jsx(
|
|
3910
|
+
CostSummaryField,
|
|
3911
|
+
{
|
|
3912
|
+
field,
|
|
3913
|
+
values,
|
|
3914
|
+
fieldStates,
|
|
3915
|
+
eventBus,
|
|
3916
|
+
onCancel: () => setFormStatus("closed"),
|
|
3917
|
+
onCostResolved: (name, label) => handleFieldChange(name, label, label)
|
|
3918
|
+
},
|
|
3919
|
+
field.name
|
|
3920
|
+
);
|
|
3921
|
+
}
|
|
3510
3922
|
const deps = getDependencies(field);
|
|
3511
3923
|
const isDisabled = !allDepsResolved(deps, values);
|
|
3512
3924
|
return /* @__PURE__ */ jsx(
|
|
@@ -3602,89 +4014,6 @@ function buildInitialValues(fields) {
|
|
|
3602
4014
|
return values;
|
|
3603
4015
|
}
|
|
3604
4016
|
|
|
3605
|
-
function resolveVariable(template, formValues, fieldStates) {
|
|
3606
|
-
if (!template.startsWith("$")) return template;
|
|
3607
|
-
const withoutDollar = template.slice(1);
|
|
3608
|
-
const dotIndex = withoutDollar.indexOf(".");
|
|
3609
|
-
const fieldName = dotIndex >= 0 ? withoutDollar.slice(0, dotIndex) : withoutDollar;
|
|
3610
|
-
const prop = dotIndex >= 0 ? withoutDollar.slice(dotIndex + 1) : null;
|
|
3611
|
-
const value = formValues[fieldName];
|
|
3612
|
-
const state = fieldStates[fieldName];
|
|
3613
|
-
if (!prop) return value;
|
|
3614
|
-
if (prop === "label" && state) {
|
|
3615
|
-
return state.label || "";
|
|
3616
|
-
}
|
|
3617
|
-
if (prop === "labels" && state && Array.isArray(value)) {
|
|
3618
|
-
return value.map((v) => {
|
|
3619
|
-
const opt = state.options.find((o) => o.value === v);
|
|
3620
|
-
return opt?.label || v;
|
|
3621
|
-
}).join(", ");
|
|
3622
|
-
}
|
|
3623
|
-
if (state) {
|
|
3624
|
-
const selectedOpt = state.options.find((o) => o.value === value);
|
|
3625
|
-
if (selectedOpt && prop in selectedOpt) {
|
|
3626
|
-
return selectedOpt[prop];
|
|
3627
|
-
}
|
|
3628
|
-
}
|
|
3629
|
-
return "";
|
|
3630
|
-
}
|
|
3631
|
-
function resolveBody(obj, formValues, fieldStates) {
|
|
3632
|
-
if (typeof obj === "string") return resolveVariable(obj, formValues, fieldStates);
|
|
3633
|
-
if (Array.isArray(obj)) return obj.map((item) => resolveBody(item, formValues, fieldStates));
|
|
3634
|
-
if (obj !== null && typeof obj === "object") {
|
|
3635
|
-
const resolved = {};
|
|
3636
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
3637
|
-
resolved[key] = resolveBody(value, formValues, fieldStates);
|
|
3638
|
-
}
|
|
3639
|
-
return resolved;
|
|
3640
|
-
}
|
|
3641
|
-
return obj;
|
|
3642
|
-
}
|
|
3643
|
-
function resolveParams(params, formValues, fieldStates) {
|
|
3644
|
-
const resolved = {};
|
|
3645
|
-
for (const [key, template] of Object.entries(params)) {
|
|
3646
|
-
resolved[key] = resolveVariable(template, formValues, fieldStates);
|
|
3647
|
-
}
|
|
3648
|
-
return resolved;
|
|
3649
|
-
}
|
|
3650
|
-
function resolveSummaryRows(rows, formValues, fieldStates) {
|
|
3651
|
-
return rows.map((row) => ({
|
|
3652
|
-
label: row.label,
|
|
3653
|
-
value: String(resolveVariable(row.value, formValues, fieldStates) ?? "")
|
|
3654
|
-
}));
|
|
3655
|
-
}
|
|
3656
|
-
|
|
3657
|
-
const FETCH_TIMEOUT_MS = 12e4;
|
|
3658
|
-
function fetchViaEventBus(eventBus, service, url, method, body) {
|
|
3659
|
-
const requestId = globalThis.crypto?.randomUUID?.() ?? "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
3660
|
-
const r = Math.random() * 16 | 0;
|
|
3661
|
-
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
3662
|
-
});
|
|
3663
|
-
return new Promise((resolve, reject) => {
|
|
3664
|
-
const timeoutId = setTimeout(() => {
|
|
3665
|
-
unsubscribe();
|
|
3666
|
-
reject(new Error(`Timeout: no response for ${url} after ${FETCH_TIMEOUT_MS}ms`));
|
|
3667
|
-
}, FETCH_TIMEOUT_MS);
|
|
3668
|
-
const unsubscribe = eventBus.on(CHAT_EVENT.FETCH_RESPONSE, (response) => {
|
|
3669
|
-
if (response.requestId !== requestId) return;
|
|
3670
|
-
clearTimeout(timeoutId);
|
|
3671
|
-
unsubscribe();
|
|
3672
|
-
if (response.httpError) {
|
|
3673
|
-
reject(new Error(response.httpError));
|
|
3674
|
-
} else {
|
|
3675
|
-
resolve(response.data);
|
|
3676
|
-
}
|
|
3677
|
-
});
|
|
3678
|
-
eventBus.emit(CHAT_EVENT.FETCH_REQUEST, {
|
|
3679
|
-
requestId,
|
|
3680
|
-
service,
|
|
3681
|
-
url,
|
|
3682
|
-
method,
|
|
3683
|
-
...body ? { body } : {}
|
|
3684
|
-
});
|
|
3685
|
-
});
|
|
3686
|
-
}
|
|
3687
|
-
|
|
3688
4017
|
function formatTime$1(value, timezone) {
|
|
3689
4018
|
try {
|
|
3690
4019
|
const d = new Date(value);
|
|
@@ -3692,7 +4021,7 @@ function formatTime$1(value, timezone) {
|
|
|
3692
4021
|
return d.toLocaleTimeString([], {
|
|
3693
4022
|
hour: "2-digit",
|
|
3694
4023
|
minute: "2-digit",
|
|
3695
|
-
hour12:
|
|
4024
|
+
hour12: true,
|
|
3696
4025
|
...timezone ? { timeZone: timezone } : {}
|
|
3697
4026
|
});
|
|
3698
4027
|
} catch {
|
|
@@ -4054,7 +4383,10 @@ function useReactiveForm(props) {
|
|
|
4054
4383
|
};
|
|
4055
4384
|
const handleBack = () => setCurrentStep((s) => s - 1);
|
|
4056
4385
|
const [submitMessage, setSubmitMessage] = useState("");
|
|
4386
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
4057
4387
|
const handleSubmit = async () => {
|
|
4388
|
+
if (isSubmitting) return;
|
|
4389
|
+
setIsSubmitting(true);
|
|
4058
4390
|
const resolvedPayload = resolveBody(submit.payload_map, values, fieldStates);
|
|
4059
4391
|
if (eventBus) {
|
|
4060
4392
|
try {
|
|
@@ -4077,7 +4409,8 @@ function useReactiveForm(props) {
|
|
|
4077
4409
|
submitUrl: submit.url,
|
|
4078
4410
|
result: data,
|
|
4079
4411
|
formValues: values,
|
|
4080
|
-
formLabels
|
|
4412
|
+
formLabels,
|
|
4413
|
+
onSuccess: submit.on_success
|
|
4081
4414
|
});
|
|
4082
4415
|
if (notificationType === "SUCCESS") {
|
|
4083
4416
|
setSubmitMessage(message || "Completado");
|
|
@@ -4093,6 +4426,7 @@ function useReactiveForm(props) {
|
|
|
4093
4426
|
const message = err instanceof Error ? err.message : "Error al enviar formulario";
|
|
4094
4427
|
setSubmitMessage(message);
|
|
4095
4428
|
setFormStatus("error");
|
|
4429
|
+
setIsSubmitting(false);
|
|
4096
4430
|
}
|
|
4097
4431
|
} else {
|
|
4098
4432
|
console.log("[ReactiveForm] Submit:", values);
|
|
@@ -4121,6 +4455,7 @@ function useReactiveForm(props) {
|
|
|
4121
4455
|
handleNext,
|
|
4122
4456
|
handleBack,
|
|
4123
4457
|
handleSubmit,
|
|
4458
|
+
isSubmitting,
|
|
4124
4459
|
getDependencies,
|
|
4125
4460
|
allDepsResolved,
|
|
4126
4461
|
resolveSummaryRows: resolveRows
|
|
@@ -4152,7 +4487,8 @@ const ReactiveForm = ({ component, eventBus }) => {
|
|
|
4152
4487
|
{
|
|
4153
4488
|
...props,
|
|
4154
4489
|
form,
|
|
4155
|
-
drawerPlacement: isMobile ? "bottom" : "right"
|
|
4490
|
+
drawerPlacement: isMobile ? "bottom" : "right",
|
|
4491
|
+
eventBus
|
|
4156
4492
|
}
|
|
4157
4493
|
);
|
|
4158
4494
|
};
|
|
@@ -4818,7 +5154,15 @@ const COMPONENT_MAP = {
|
|
|
4818
5154
|
};
|
|
4819
5155
|
function renderComponent(props) {
|
|
4820
5156
|
const { component } = props;
|
|
4821
|
-
if (component.
|
|
5157
|
+
if (component.status) {
|
|
5158
|
+
if (TERMINAL_STATUS.has(component.status)) {
|
|
5159
|
+
const policy = component.visibility_policy ?? "hide_on_terminal";
|
|
5160
|
+
if (policy === "hide_on_terminal") return null;
|
|
5161
|
+
if (component.selected_values && component.selected_values.length > 0) {
|
|
5162
|
+
return /* @__PURE__ */ jsx(AnsweredSummary, { component });
|
|
5163
|
+
}
|
|
5164
|
+
}
|
|
5165
|
+
} else if (component.answered && !DISPLAY_COMPONENTS.has(component.type)) {
|
|
4822
5166
|
return null;
|
|
4823
5167
|
}
|
|
4824
5168
|
const Component = COMPONENT_MAP[component.type];
|