pixelon 0.4.2 → 0.5.0
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/molecules/chat/StructuredContent/components/ReactiveCrud/ReactiveCrud.d.ts +1 -0
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveCrud/TranscriptSection.d.ts +10 -0
- package/dist/components/molecules/chat/StructuredContent/components/ReactiveCrud/types.d.ts +47 -1
- package/dist/components/molecules/chat/StructuredContent/components/ServicesMap/types.d.ts +3 -0
- package/dist/components/molecules/chat/StructuredContent/components/index.d.ts +0 -1
- package/dist/core/chat/ChatConfigContext.d.ts +25 -0
- package/dist/core/i18n/separadores.d.ts +12 -0
- package/dist/index.esm.js +173 -33
- package/dist/index.js +173 -33
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
- package/src/styles/index.scss +1 -0
package/dist/index.js
CHANGED
|
@@ -12838,29 +12838,22 @@ const FormDrawer = ({
|
|
|
12838
12838
|
onClose();
|
|
12839
12839
|
methods.reset();
|
|
12840
12840
|
}, [onClose, onBeforeClose, methods]);
|
|
12841
|
-
const [invalidMsg, setInvalidMsg] = React.useState(null);
|
|
12842
|
-
React.useEffect(() => {
|
|
12843
|
-
if (!isOpen) setInvalidMsg(null);
|
|
12844
|
-
}, [isOpen]);
|
|
12845
|
-
React.useEffect(() => {
|
|
12846
|
-
const sub = methods.watch(() => setInvalidMsg(null));
|
|
12847
|
-
return () => sub.unsubscribe();
|
|
12848
|
-
}, [methods.watch]);
|
|
12849
12841
|
const handleFormSubmit = React.useCallback(
|
|
12850
12842
|
async (data) => {
|
|
12851
|
-
setInvalidMsg(null);
|
|
12852
12843
|
await onSubmit(data);
|
|
12853
12844
|
},
|
|
12854
12845
|
[onSubmit]
|
|
12855
12846
|
);
|
|
12856
12847
|
const handleInvalid = React.useCallback(
|
|
12857
12848
|
(formErrors) => {
|
|
12858
|
-
const
|
|
12859
|
-
|
|
12860
|
-
|
|
12861
|
-
);
|
|
12849
|
+
const primero = Object.keys(formErrors)[0];
|
|
12850
|
+
if (!primero) return;
|
|
12851
|
+
const nodo = document.querySelector(`[name="${CSS.escape(primero)}"]`);
|
|
12852
|
+
if (!nodo) return;
|
|
12853
|
+
nodo.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
12854
|
+
window.setTimeout(() => nodo.focus({ preventScroll: true }), 300);
|
|
12862
12855
|
},
|
|
12863
|
-
[
|
|
12856
|
+
[]
|
|
12864
12857
|
);
|
|
12865
12858
|
const handleSubmitClick = methods.handleSubmit(handleFormSubmit, handleInvalid);
|
|
12866
12859
|
const drawerTitle = title || DEFAULT_TITLES[mode];
|
|
@@ -12918,7 +12911,6 @@ const FormDrawer = ({
|
|
|
12918
12911
|
) }) }),
|
|
12919
12912
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${baseClass}__footer`, children: [
|
|
12920
12913
|
footerExtra && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${baseClass}__footer-extra`, children: footerExtra }),
|
|
12921
|
-
invalidMsg && mode !== "view" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${baseClass}__invalid`, role: "alert", children: invalidMsg }),
|
|
12922
12914
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${baseClass}__actions`, children: [
|
|
12923
12915
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12924
12916
|
Button,
|
|
@@ -14133,7 +14125,7 @@ function getFormatter(key) {
|
|
|
14133
14125
|
}
|
|
14134
14126
|
|
|
14135
14127
|
const OPTIONS_LOAD_ERROR = "No se pudieron cargar las opciones. Int\xE9ntalo de nuevo.";
|
|
14136
|
-
function unwrap$
|
|
14128
|
+
function unwrap$4(raw) {
|
|
14137
14129
|
if (raw && typeof raw === "object" && "response" in raw) {
|
|
14138
14130
|
return raw.response;
|
|
14139
14131
|
}
|
|
@@ -14154,7 +14146,7 @@ function resolveBody(body, ctx) {
|
|
|
14154
14146
|
}
|
|
14155
14147
|
async function loadOptions(eventBus, ep, ctx) {
|
|
14156
14148
|
const raw = await fetchViaEventBus(eventBus, ep.service, ep.url, ep.method, resolveBody(ep.body, ctx));
|
|
14157
|
-
let data = unwrap$
|
|
14149
|
+
let data = unwrap$4(raw);
|
|
14158
14150
|
if (ep.response_path && data && typeof data === "object" && !Array.isArray(data)) {
|
|
14159
14151
|
data = data[ep.response_path];
|
|
14160
14152
|
}
|
|
@@ -14192,7 +14184,7 @@ const mensajeDeError = (e, respaldo) => {
|
|
|
14192
14184
|
};
|
|
14193
14185
|
|
|
14194
14186
|
const REFRESH_INTERVAL_MS = 2e4;
|
|
14195
|
-
function unwrap$
|
|
14187
|
+
function unwrap$3(raw) {
|
|
14196
14188
|
if (raw && typeof raw === "object" && "response" in raw) {
|
|
14197
14189
|
return raw.response;
|
|
14198
14190
|
}
|
|
@@ -14224,7 +14216,7 @@ function resolvePayload(map, ctx) {
|
|
|
14224
14216
|
function useReactiveCrud(config, eventBus) {
|
|
14225
14217
|
const pageSize = config.pageSize ?? 10;
|
|
14226
14218
|
const [skip, setSkip] = React.useState(0);
|
|
14227
|
-
const [filters, setFilters] = React.useState([]);
|
|
14219
|
+
const [filters, setFilters] = React.useState(config.initialFilters ?? []);
|
|
14228
14220
|
const [state, setState] = React.useState({ rows: [], total: 0, loading: false, error: null });
|
|
14229
14221
|
const [actionError, setActionError] = React.useState(null);
|
|
14230
14222
|
const reqIdRef = React.useRef(0);
|
|
@@ -14241,7 +14233,7 @@ function useReactiveCrud(config, eventBus) {
|
|
|
14241
14233
|
filters
|
|
14242
14234
|
});
|
|
14243
14235
|
assertOk(raw);
|
|
14244
|
-
const data = unwrap$
|
|
14236
|
+
const data = unwrap$3(raw);
|
|
14245
14237
|
let rows = [];
|
|
14246
14238
|
let total = 0;
|
|
14247
14239
|
if (Array.isArray(data)) {
|
|
@@ -14445,6 +14437,20 @@ const FileField = ({
|
|
|
14445
14437
|
] });
|
|
14446
14438
|
};
|
|
14447
14439
|
|
|
14440
|
+
const RESPALDO = { miles: ".", decimal: "," };
|
|
14441
|
+
function separadoresDelLocale(locale) {
|
|
14442
|
+
if (!locale) return RESPALDO;
|
|
14443
|
+
try {
|
|
14444
|
+
const partes = new Intl.NumberFormat(locale).formatToParts(123456789e-2);
|
|
14445
|
+
const miles = partes.find((p) => p.type === "group")?.value;
|
|
14446
|
+
const decimal = partes.find((p) => p.type === "decimal")?.value;
|
|
14447
|
+
if (!miles || !decimal) return RESPALDO;
|
|
14448
|
+
return { miles, decimal };
|
|
14449
|
+
} catch {
|
|
14450
|
+
return RESPALDO;
|
|
14451
|
+
}
|
|
14452
|
+
}
|
|
14453
|
+
|
|
14448
14454
|
const CRUD_TO_FORM_MOLECULE = {
|
|
14449
14455
|
INPUT: "INPUT",
|
|
14450
14456
|
INPUT_NUMBER: "INPUT_NUMBER",
|
|
@@ -14501,6 +14507,8 @@ function ActionFormDrawer({ action, row, idField, eventBus, onExecute, onClose }
|
|
|
14501
14507
|
alive = false;
|
|
14502
14508
|
};
|
|
14503
14509
|
}, [eventBus, action.key, normalFields]);
|
|
14510
|
+
const { locale } = useChatConfig();
|
|
14511
|
+
const separadores = React.useMemo(() => separadoresDelLocale(locale), [locale]);
|
|
14504
14512
|
const fields = React.useMemo(
|
|
14505
14513
|
() => normalFields.map((f) => ({
|
|
14506
14514
|
name: f.name,
|
|
@@ -14511,9 +14519,19 @@ function ActionFormDrawer({ action, row, idField, eventBus, onExecute, onClose }
|
|
|
14511
14519
|
options: f.options ?? optionsByField[f.name],
|
|
14512
14520
|
// SPEC-106 T8 — `uiProps` llega tal cual a la molécula, así que el desplegable dice lo
|
|
14513
14521
|
// que pasó de verdad en vez del «no hay» de siempre. Sin error, se queda el de siempre.
|
|
14514
|
-
...optionsErrorByField[f.name] ? { uiProps: { notFoundContent: optionsErrorByField[f.name] } } : {}
|
|
14522
|
+
...optionsErrorByField[f.name] ? { uiProps: { notFoundContent: optionsErrorByField[f.name] } } : {},
|
|
14523
|
+
// SPEC-128 — el dinero se escribe como se escribe AQUÍ.
|
|
14524
|
+
//
|
|
14525
|
+
// Los campos de moneda caían a `thousandSeparator ?? ','`, un valor por defecto en formato
|
|
14526
|
+
// inglés: al teclear 180000 el campo mostraba «180,000» mientras la tarjeta que recibe el
|
|
14527
|
+
// cliente decía «$ 180.000,00 COP». El mismo importe escrito de una manera y leído de otra.
|
|
14528
|
+
//
|
|
14529
|
+
// Se deriva del locale que el host ya declara en la config del chat, no de un valor fijo ni
|
|
14530
|
+
// del navegador: `navigator.language` puede ser `es-419` —español, pero con coma para los
|
|
14531
|
+
// miles— y entonces el resultado dependería del portátil de cada quien.
|
|
14532
|
+
...f.moleculeType === "INPUT_CURRENCY" ? { uiProps: { thousandSeparator: separadores.miles, decimalSeparator: separadores.decimal } } : {}
|
|
14515
14533
|
})),
|
|
14516
|
-
[normalFields, optionsByField, optionsErrorByField]
|
|
14534
|
+
[normalFields, optionsByField, optionsErrorByField, separadores]
|
|
14517
14535
|
);
|
|
14518
14536
|
const validationSchema = React.useMemo(() => buildCrudYupSchema(normalFields), [normalFields]);
|
|
14519
14537
|
const uploadOne = async (f, file, idx) => {
|
|
@@ -15172,6 +15190,95 @@ const FileViewer = ({
|
|
|
15172
15190
|
] });
|
|
15173
15191
|
};
|
|
15174
15192
|
|
|
15193
|
+
function unwrap$2(raw) {
|
|
15194
|
+
if (raw && typeof raw === "object" && "response" in raw) {
|
|
15195
|
+
return raw.response;
|
|
15196
|
+
}
|
|
15197
|
+
return raw;
|
|
15198
|
+
}
|
|
15199
|
+
function hora(iso) {
|
|
15200
|
+
if (!iso) return "";
|
|
15201
|
+
const d = new Date(iso);
|
|
15202
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
15203
|
+
return d.toLocaleString(void 0, { day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" });
|
|
15204
|
+
}
|
|
15205
|
+
function TranscriptSection({ transcript, values, eventBus }) {
|
|
15206
|
+
const chatId = values[transcript.chatIdField];
|
|
15207
|
+
const id = chatId == null || chatId === "" ? "" : String(chatId);
|
|
15208
|
+
const [datos, setDatos] = React.useState(null);
|
|
15209
|
+
const [cargando, setCargando] = React.useState(true);
|
|
15210
|
+
const [fallo, setFallo] = React.useState(false);
|
|
15211
|
+
React.useEffect(() => {
|
|
15212
|
+
if (!eventBus || !id) {
|
|
15213
|
+
setCargando(false);
|
|
15214
|
+
return;
|
|
15215
|
+
}
|
|
15216
|
+
let vivo = true;
|
|
15217
|
+
setCargando(true);
|
|
15218
|
+
setFallo(false);
|
|
15219
|
+
void (async () => {
|
|
15220
|
+
try {
|
|
15221
|
+
const raw = await fetchViaEventBus(
|
|
15222
|
+
eventBus,
|
|
15223
|
+
transcript.get.service,
|
|
15224
|
+
transcript.get.url,
|
|
15225
|
+
transcript.get.method ?? "POST",
|
|
15226
|
+
{ [transcript.param ?? "chat_id"]: id }
|
|
15227
|
+
);
|
|
15228
|
+
if (vivo) {
|
|
15229
|
+
setDatos(unwrap$2(raw) ?? {});
|
|
15230
|
+
setCargando(false);
|
|
15231
|
+
}
|
|
15232
|
+
} catch {
|
|
15233
|
+
if (vivo) {
|
|
15234
|
+
setFallo(true);
|
|
15235
|
+
setCargando(false);
|
|
15236
|
+
}
|
|
15237
|
+
}
|
|
15238
|
+
})();
|
|
15239
|
+
return () => {
|
|
15240
|
+
vivo = false;
|
|
15241
|
+
};
|
|
15242
|
+
}, [eventBus, id, transcript]);
|
|
15243
|
+
if (!id) return null;
|
|
15244
|
+
const lineas = datos?.lines ?? [];
|
|
15245
|
+
const dijoAlgo = (datos?.from_user ?? 0) > 0;
|
|
15246
|
+
const nombres = {
|
|
15247
|
+
user: transcript.labels?.user ?? "Cliente",
|
|
15248
|
+
assistant: transcript.labels?.assistant ?? "Asistente"
|
|
15249
|
+
};
|
|
15250
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-crud-transcript", children: [
|
|
15251
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "px-chat-crud-transcript__title", children: transcript.title ?? "Conversaci\xF3n" }),
|
|
15252
|
+
cargando && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-transcript__note", children: "Cargando\u2026" }),
|
|
15253
|
+
!cargando && fallo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-transcript__note", children: "No se pudo cargar la conversaci\xF3n." }),
|
|
15254
|
+
!cargando && !fallo && !dijoAlgo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-transcript__note", children: transcript.silentText ?? "Todav\xEDa no ha escrito nada." }),
|
|
15255
|
+
!cargando && !fallo && lineas.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "px-chat-crud-transcript__lines", children: lineas.map((l, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15256
|
+
"li",
|
|
15257
|
+
{
|
|
15258
|
+
className: [
|
|
15259
|
+
"px-chat-crud-transcript__line",
|
|
15260
|
+
l.rol === "user" ? "is-user" : "is-assistant"
|
|
15261
|
+
].join(" "),
|
|
15262
|
+
children: [
|
|
15263
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-crud-transcript__who", children: [
|
|
15264
|
+
l.rol === "user" ? nombres.user : nombres.assistant,
|
|
15265
|
+
hora(l.created_date) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-crud-transcript__when", children: hora(l.created_date) })
|
|
15266
|
+
] }),
|
|
15267
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-crud-transcript__text", children: l.text })
|
|
15268
|
+
]
|
|
15269
|
+
},
|
|
15270
|
+
`${i}-${l.created_date ?? ""}`
|
|
15271
|
+
)) }),
|
|
15272
|
+
!cargando && !fallo && (datos?.total ?? 0) > lineas.length && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-crud-transcript__note", children: [
|
|
15273
|
+
"Se muestran los \xFAltimos ",
|
|
15274
|
+
lineas.length,
|
|
15275
|
+
" de ",
|
|
15276
|
+
datos?.total,
|
|
15277
|
+
" mensajes."
|
|
15278
|
+
] })
|
|
15279
|
+
] });
|
|
15280
|
+
}
|
|
15281
|
+
|
|
15175
15282
|
function unwrap$1(raw) {
|
|
15176
15283
|
if (raw && typeof raw === "object" && "response" in raw) {
|
|
15177
15284
|
return raw.response;
|
|
@@ -15300,6 +15407,7 @@ function DetailDrawer({ row, config, eventBus, onClose, loadedOptions }) {
|
|
|
15300
15407
|
] })
|
|
15301
15408
|
] }, f.name);
|
|
15302
15409
|
}) }),
|
|
15410
|
+
config.transcript && /* @__PURE__ */ jsxRuntime.jsx(TranscriptSection, { transcript: config.transcript, values, eventBus }),
|
|
15303
15411
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-reactive-crud-detail__photos", children: [
|
|
15304
15412
|
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "px-chat-reactive-crud-detail__photos-title", children: "Fotos y documentos" }),
|
|
15305
15413
|
loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-reactive-crud-detail__empty", children: "Cargando\u2026" }) : files.length ? /* @__PURE__ */ jsxRuntime.jsx(FileViewer, { files }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-reactive-crud-detail__empty", children: "Este servicio no tiene archivos." })
|
|
@@ -16006,6 +16114,10 @@ function matchesVisibleWhen(a, row) {
|
|
|
16006
16114
|
if (!a.visibleWhen) return true;
|
|
16007
16115
|
return cumplenTodas(a.visibleWhen, row);
|
|
16008
16116
|
}
|
|
16117
|
+
function laQueTocaAhora(actions, row) {
|
|
16118
|
+
const candidatas = actions.filter((a) => a.ahoraToca && cumplenTodas(a.ahoraToca, row));
|
|
16119
|
+
return candidatas.length === 1 ? candidatas[0] : void 0;
|
|
16120
|
+
}
|
|
16009
16121
|
function condicionesDeshabilitado(a) {
|
|
16010
16122
|
if (!a.disabledWhen) return [];
|
|
16011
16123
|
return Array.isArray(a.disabledWhen) ? a.disabledWhen : [a.disabledWhen];
|
|
@@ -16136,6 +16248,7 @@ function ReactiveCrud({ config, eventBus, autoOpenCreate, prefill, onCreated, on
|
|
|
16136
16248
|
total: crud.total,
|
|
16137
16249
|
loading: crud.loading,
|
|
16138
16250
|
filters: { skip: crud.skip, limit: crud.pageSize, all_data: false, filters: crud.filters },
|
|
16251
|
+
defaultFilters: config.initialFilters,
|
|
16139
16252
|
tableScroll: config.tableScroll,
|
|
16140
16253
|
layout: config.layout,
|
|
16141
16254
|
cardsBelow: config.cardsBelow,
|
|
@@ -16325,7 +16438,7 @@ function DeadlineCountdown({ deadline, label, expiredLabel }) {
|
|
|
16325
16438
|
}
|
|
16326
16439
|
|
|
16327
16440
|
function ReactiveCrudItemChat({ component, eventBus }) {
|
|
16328
|
-
const { resolveModuleConfig } = useChatConfig();
|
|
16441
|
+
const { resolveModuleConfig, resolveMomento } = useChatConfig();
|
|
16329
16442
|
const props = component.props ?? {};
|
|
16330
16443
|
const top = component;
|
|
16331
16444
|
const pick = (key) => props[key] !== void 0 ? props[key] : top[key];
|
|
@@ -16333,7 +16446,11 @@ function ReactiveCrudItemChat({ component, eventBus }) {
|
|
|
16333
16446
|
const recordId = pick("record_id") ?? pick("recordId") ?? pick("id") ?? pick("service_id");
|
|
16334
16447
|
const recordLabel = pick("record_label") ?? pick("label");
|
|
16335
16448
|
const allowedRaw = pick("actions");
|
|
16336
|
-
const
|
|
16449
|
+
const allowedLegacy = Array.isArray(allowedRaw) && allowedRaw.length > 0 ? allowedRaw : void 0;
|
|
16450
|
+
const momento = pick("momento");
|
|
16451
|
+
const delMomento = momento && resolveMomento ? resolveMomento(momento) : void 0;
|
|
16452
|
+
const allowed = delMomento ?? allowedLegacy;
|
|
16453
|
+
const sinAcciones = delMomento?.length === 0;
|
|
16337
16454
|
const config = typeof moduleKey === "string" && resolveModuleConfig ? resolveModuleConfig(moduleKey) : void 0;
|
|
16338
16455
|
if (!config || recordId == null || recordId === "") return null;
|
|
16339
16456
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -16343,11 +16460,12 @@ function ReactiveCrudItemChat({ component, eventBus }) {
|
|
|
16343
16460
|
recordId: String(recordId),
|
|
16344
16461
|
recordLabel,
|
|
16345
16462
|
allowed: Array.isArray(allowed) ? allowed.map(String) : void 0,
|
|
16463
|
+
sinAcciones,
|
|
16346
16464
|
eventBus
|
|
16347
16465
|
}
|
|
16348
16466
|
);
|
|
16349
16467
|
}
|
|
16350
|
-
function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus }) {
|
|
16468
|
+
function ServiceActionsPanel({ config, recordId, recordLabel, allowed, sinAcciones, eventBus }) {
|
|
16351
16469
|
const { chatIsForeign } = useChatConfig();
|
|
16352
16470
|
const crud = useReactiveCrud(config, eventBus);
|
|
16353
16471
|
const [activeAction, setActiveAction] = React.useState(null);
|
|
@@ -16396,9 +16514,26 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16396
16514
|
}, [recordId]);
|
|
16397
16515
|
const gastada = !esUltima;
|
|
16398
16516
|
const actions = React.useMemo(() => {
|
|
16399
|
-
if (!row
|
|
16400
|
-
|
|
16517
|
+
if (!row) return [];
|
|
16518
|
+
if (gastada) {
|
|
16519
|
+
const hechas = (config.rowActions ?? []).filter((a) => !allowed || allowed.includes(a.key)).filter((a) => matchesDoneWhen(a, row));
|
|
16520
|
+
const vistas = /* @__PURE__ */ new Set();
|
|
16521
|
+
return hechas.filter((a) => {
|
|
16522
|
+
const linea = a.doneLabel ?? a.label;
|
|
16523
|
+
if (vistas.has(linea)) return false;
|
|
16524
|
+
vistas.add(linea);
|
|
16525
|
+
return true;
|
|
16526
|
+
});
|
|
16527
|
+
}
|
|
16528
|
+
const visibles = (config.rowActions ?? []).filter((a) => !allowed || allowed.includes(a.key)).filter((a) => matchesVisibleWhen(a, row));
|
|
16529
|
+
const toca = laQueTocaAhora(visibles, row);
|
|
16530
|
+
if (!toca) return visibles;
|
|
16531
|
+
return [toca, ...visibles.filter((a) => a.key !== toca.key)];
|
|
16401
16532
|
}, [config.rowActions, row, allowed, gastada]);
|
|
16533
|
+
const claveQueToca = React.useMemo(
|
|
16534
|
+
() => row && !gastada ? laQueTocaAhora(actions, row)?.key : void 0,
|
|
16535
|
+
[actions, row, gastada]
|
|
16536
|
+
);
|
|
16402
16537
|
const title = recordLabel ?? config.title ?? "Servicio";
|
|
16403
16538
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-crud-item", ref: raiz, "data-panel-record": recordId, children: [
|
|
16404
16539
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__header", children: title }),
|
|
@@ -16409,7 +16544,7 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16409
16544
|
crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "Cargando\u2026" }),
|
|
16410
16545
|
!crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "No se encontr\xF3 el servicio." }),
|
|
16411
16546
|
gastada && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "Este paso ya se gestion\xF3. Contin\xFAa en el mensaje m\xE1s reciente." }),
|
|
16412
|
-
row && config.deadline && typeof row[config.deadline.field] === "string" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16547
|
+
row && !gastada && config.deadline && typeof row[config.deadline.field] === "string" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16413
16548
|
DeadlineCountdown,
|
|
16414
16549
|
{
|
|
16415
16550
|
deadline: row[config.deadline.field],
|
|
@@ -16420,7 +16555,7 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16420
16555
|
row && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-crud-item__actions", children: [
|
|
16421
16556
|
config.detail && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-crud-item__action", onClick: () => setDetailRow(row), children: "Ver" }),
|
|
16422
16557
|
actions.map((a) => {
|
|
16423
|
-
const disabled = Boolean(chatIsForeign) || matchesDisabledWhen(a, row);
|
|
16558
|
+
const disabled = gastada || Boolean(chatIsForeign) || matchesDisabledWhen(a, row);
|
|
16424
16559
|
const motivo = chatIsForeign ? "Esta conversaci\xF3n es de otra persona" : disabledReasonFor(a, row);
|
|
16425
16560
|
const done = matchesDoneWhen(a, row);
|
|
16426
16561
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -16430,13 +16565,18 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16430
16565
|
className: [
|
|
16431
16566
|
"px-chat-crud-item__action",
|
|
16432
16567
|
a.intent === "danger" ? "is-danger" : "",
|
|
16433
|
-
disabled && motivo ? "is-con-motivo" : ""
|
|
16568
|
+
disabled && motivo ? "is-con-motivo" : "",
|
|
16569
|
+
// SPEC-129 T6 — lo hecho se pinta como un acta, no como un botón apagado.
|
|
16570
|
+
gastada ? "is-hecho" : "",
|
|
16571
|
+
// SPEC-127 T4 — señalada, pero solo si de verdad se puede pulsar: destacar una
|
|
16572
|
+
// acción apagada sería dirigir a alguien a una puerta cerrada.
|
|
16573
|
+
a.key === claveQueToca && !disabled ? "is-ahora" : ""
|
|
16434
16574
|
].filter(Boolean).join(" "),
|
|
16435
16575
|
disabled,
|
|
16436
16576
|
onClick: () => a.form ? setActiveAction({ action: a, row }) : crud.runEndpoints(a.endpoints ?? [a.endpoint], { ...row, id: row[config.idField] }),
|
|
16437
16577
|
children: [
|
|
16438
16578
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-crud-item__action-texts", children: [
|
|
16439
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: a.label }),
|
|
16579
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: gastada && a.doneLabel ? a.doneLabel : a.label }),
|
|
16440
16580
|
disabled && motivo && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-crud-item__action-reason", children: motivo })
|
|
16441
16581
|
] }),
|
|
16442
16582
|
done && /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: "check-circle", width: 18, height: 18, className: "px-chat-crud-item__done", "aria-label": "Hecho" })
|
|
@@ -16445,7 +16585,7 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16445
16585
|
a.key
|
|
16446
16586
|
);
|
|
16447
16587
|
}),
|
|
16448
|
-
actions.length === 0 && !config.detail && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "Sin acciones disponibles." })
|
|
16588
|
+
actions.length === 0 && !config.detail && !sinAcciones && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "Sin acciones disponibles." })
|
|
16449
16589
|
] }),
|
|
16450
16590
|
activeAction && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16451
16591
|
ActionFormDrawer,
|
|
@@ -16665,7 +16805,7 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
|
|
|
16665
16805
|
),
|
|
16666
16806
|
simulated > 0 && ` \xB7 ${config.live?.labels?.simulatedText ?? "incluye posiciones simuladas"}`
|
|
16667
16807
|
] }),
|
|
16668
|
-
missing > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$6}__note`, children: (labels.missingText ?? "{n} sin ubicaci\xF3n registrada").replace("{n}", String(missing)) }),
|
|
16808
|
+
missing > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$6}__note`, children: ((missing === 1 ? labels.missingTextOne : void 0) ?? labels.missingText ?? "{n} sin ubicaci\xF3n registrada").replace("{n}", String(missing)) }),
|
|
16669
16809
|
outside > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$6}__note`, children: (labels.outsideText ?? "{n} fuera de la zona (aleja el mapa para verlos)").replace(
|
|
16670
16810
|
"{n}",
|
|
16671
16811
|
String(outside)
|