@softdin/portal-admin 0.0.0-stage → 0.2.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.
Files changed (96) hide show
  1. package/README.md +95 -2
  2. package/dist-lib/chunks/AppLayout-COCPfLWo.js +303 -0
  3. package/dist-lib/chunks/AuditoriaView-Bcf_kOqI.js +643 -0
  4. package/dist-lib/chunks/CarnetView-BsdUtYeu.js +450 -0
  5. package/dist-lib/chunks/CarteleraView-CRnVjt-S.js +996 -0
  6. package/dist-lib/chunks/CertificadosView-DvHDflcN.js +549 -0
  7. package/dist-lib/chunks/ChatBandejaView-HqhdSw7G.js +274 -0
  8. package/dist-lib/chunks/ChatConfiguracionView-BdH5gDdR.js +716 -0
  9. package/dist-lib/chunks/ChatConocimientoView-nKTAKxFa.js +263 -0
  10. package/dist-lib/chunks/ChatConversacionView-Do74V09l.js +477 -0
  11. package/dist-lib/chunks/ChatInformeView-BIiAH9L_.js +280 -0
  12. package/dist-lib/chunks/ChatRespuestasView-QFXbyg8U.js +183 -0
  13. package/dist-lib/chunks/EmpleadosView-BtqrO5-8.js +311 -0
  14. package/dist-lib/chunks/HomologacionView-UCZk4u6R.js +949 -0
  15. package/dist-lib/chunks/IngresoSsoView-BKkcnrYO.js +98 -0
  16. package/dist-lib/chunks/SolicitudesView-CYPD2A1s.js +900 -0
  17. package/dist-lib/chunks/TiposSolicitudView-CrWTVizl.js +168 -0
  18. package/dist-lib/chunks/ToggleSwitch-BYrIyheq.js +55 -0
  19. package/dist-lib/chunks/_plugin-vue_export-helper-BOaGB7Aw.js +8 -0
  20. package/dist-lib/chunks/api-M7D1c3IT.js +97 -0
  21. package/dist-lib/chunks/apiError-BHGbwz97.js +15 -0
  22. package/dist-lib/chunks/auth.store-BrGKZg-7.js +220 -0
  23. package/dist-lib/chunks/chat.service-C7ZQf4w3.js +241 -0
  24. package/dist-lib/chunks/cliente-interno.store-De39VsEE.js +203 -0
  25. package/dist-lib/chunks/homologacion-CoeHD7cB.js +131 -0
  26. package/dist-lib/chunks/portal-empleado-6KQrnsQJ.js +120 -0
  27. package/dist-lib/chunks/tipos-D93bLfFC.js +22 -0
  28. package/dist-lib/portal-admin.js +196 -0
  29. package/dist-lib/style.css +4813 -0
  30. package/dist-lib/types/App.vue.d.ts +3 -0
  31. package/dist-lib/types/components/AppLayout.vue.d.ts +3 -0
  32. package/dist-lib/types/components/CarnetClientesInternos.vue.d.ts +11 -0
  33. package/dist-lib/types/components/InvitacionPortalModal.vue.d.ts +20 -0
  34. package/dist-lib/types/components/MenuUsuario.vue.d.ts +3 -0
  35. package/dist-lib/types/components/VistoBuenoPortalModal.vue.d.ts +23 -0
  36. package/dist-lib/types/components/auditoria/AuditoriaFila.vue.d.ts +16 -0
  37. package/dist-lib/types/components/auditoria/AuditoriaFiltros.vue.d.ts +30 -0
  38. package/dist-lib/types/components/auditoria/AuditoriaPaginador.vue.d.ts +14 -0
  39. package/dist-lib/types/components/cartelera/PaginaCarteleraImagen.vue.d.ts +14 -0
  40. package/dist-lib/types/components/cartelera/PublicacionFormModal.vue.d.ts +27 -0
  41. package/dist-lib/types/components/cartelera/VistaCelularCartelera.vue.d.ts +34 -0
  42. package/dist-lib/types/components/certificados/AtenderCertificadoModal.vue.d.ts +22 -0
  43. package/dist-lib/types/components/certificados/RechazarCertificadoModal.vue.d.ts +18 -0
  44. package/dist-lib/types/components/certificados/ResumenSolicitudCertificado.vue.d.ts +8 -0
  45. package/dist-lib/types/components/chat/ChatClientesInternos.vue.d.ts +21 -0
  46. package/dist-lib/types/components/chat/ChatHorarioCampos.vue.d.ts +21 -0
  47. package/dist-lib/types/components/forms/ExportExcelButton.vue.d.ts +30 -0
  48. package/dist-lib/types/components/forms/ToggleSwitch.vue.d.ts +17 -0
  49. package/dist-lib/types/components/homologacion/HomologacionFila.vue.d.ts +30 -0
  50. package/dist-lib/types/components/homologacion/TipoPermisoFormModal.vue.d.ts +26 -0
  51. package/dist-lib/types/components/homologacion/TipoSolicitudFormModal.vue.d.ts +27 -0
  52. package/dist-lib/types/lib/auditoria.d.ts +25 -0
  53. package/dist-lib/types/lib/cartelera-paginas.d.ts +26 -0
  54. package/dist-lib/types/lib/cartelera-vigencia.d.ts +3 -0
  55. package/dist-lib/types/lib/export-excel-csv.d.ts +4 -0
  56. package/dist-lib/types/lib/export-excel.d.ts +9 -0
  57. package/dist-lib/types/lib/exportar-listado.d.ts +68 -0
  58. package/dist-lib/types/lib/homologacion.d.ts +41 -0
  59. package/dist-lib/types/lib/portal-empleado.d.ts +32 -0
  60. package/dist-lib/types/modulo.d.ts +31 -0
  61. package/dist-lib/types/portal-admin/config.d.ts +17 -0
  62. package/dist-lib/types/portal-admin/rutas.d.ts +17 -0
  63. package/dist-lib/types/portal-admin/tipos.d.ts +68 -0
  64. package/dist-lib/types/router/index.d.ts +7 -0
  65. package/dist-lib/types/services/api.d.ts +29 -0
  66. package/dist-lib/types/services/auditoria.service.d.ts +63 -0
  67. package/dist-lib/types/services/auth.service.d.ts +61 -0
  68. package/dist-lib/types/services/carnet.service.d.ts +56 -0
  69. package/dist-lib/types/services/cartelera.service.d.ts +69 -0
  70. package/dist-lib/types/services/chat.service.d.ts +279 -0
  71. package/dist-lib/types/services/configuracion-cliente-interno.service.d.ts +23 -0
  72. package/dist-lib/types/services/homologacion.service.d.ts +105 -0
  73. package/dist-lib/types/services/portal-empleado.service.d.ts +112 -0
  74. package/dist-lib/types/services/solicitudes-certificado.service.d.ts +59 -0
  75. package/dist-lib/types/stores/auth.store.d.ts +125 -0
  76. package/dist-lib/types/stores/cliente-interno.store.d.ts +65 -0
  77. package/dist-lib/types/utils/apiError.d.ts +4 -0
  78. package/dist-lib/types/views/AuditoriaView.vue.d.ts +3 -0
  79. package/dist-lib/types/views/CarnetView.vue.d.ts +3 -0
  80. package/dist-lib/types/views/CarteleraView.vue.d.ts +3 -0
  81. package/dist-lib/types/views/CertificadosView.vue.d.ts +3 -0
  82. package/dist-lib/types/views/EmpleadosView.vue.d.ts +3 -0
  83. package/dist-lib/types/views/HomologacionView.vue.d.ts +4 -0
  84. package/dist-lib/types/views/IngresoSsoView.vue.d.ts +3 -0
  85. package/dist-lib/types/views/LoginView.vue.d.ts +3 -0
  86. package/dist-lib/types/views/OlvideView.vue.d.ts +3 -0
  87. package/dist-lib/types/views/RestablecerView.vue.d.ts +3 -0
  88. package/dist-lib/types/views/SolicitudesView.vue.d.ts +3 -0
  89. package/dist-lib/types/views/TiposSolicitudView.vue.d.ts +3 -0
  90. package/dist-lib/types/views/chat/ChatBandejaView.vue.d.ts +3 -0
  91. package/dist-lib/types/views/chat/ChatConfiguracionView.vue.d.ts +3 -0
  92. package/dist-lib/types/views/chat/ChatConocimientoView.vue.d.ts +3 -0
  93. package/dist-lib/types/views/chat/ChatConversacionView.vue.d.ts +11 -0
  94. package/dist-lib/types/views/chat/ChatInformeView.vue.d.ts +3 -0
  95. package/dist-lib/types/views/chat/ChatRespuestasView.vue.d.ts +3 -0
  96. package/package.json +66 -4
@@ -0,0 +1,477 @@
1
+ import { t as useAuthStore } from "./auth.store-BrGKZg-7.js";
2
+ import { t as RUTAS_PORTAL } from "./tipos-D93bLfFC.js";
3
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BOaGB7Aw.js";
4
+ import { i as chatService, n as ESTADOS_CONVERSACION, o as fechaHora, r as MOTIVOS_ESCALAMIENTO, s as relativo } from "./chat.service-C7ZQf4w3.js";
5
+ import { t as mensajeError } from "./apiError-BHGbwz97.js";
6
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderList, toDisplayString, unref, vModelCheckbox, vModelSelect, vModelText, withCtx, withDirectives, withModifiers } from "vue";
7
+ import { RouterLink, useRouter } from "vue-router";
8
+ //#region src/views/chat/ChatConversacionView.vue?vue&type=script&setup=true&lang.ts
9
+ var _hoisted_1 = { class: "page-shell" };
10
+ var _hoisted_2 = {
11
+ key: 0,
12
+ class: "panel-muted"
13
+ };
14
+ var _hoisted_3 = {
15
+ key: 1,
16
+ class: "panel-error",
17
+ role: "alert"
18
+ };
19
+ var _hoisted_4 = { class: "page-header" };
20
+ var _hoisted_5 = { class: "page-title" };
21
+ var _hoisted_6 = { class: "page-subtitle" };
22
+ var _hoisted_7 = {
23
+ key: 0,
24
+ class: "page-subtitle"
25
+ };
26
+ var _hoisted_8 = { class: "toolbar" };
27
+ var _hoisted_9 = {
28
+ key: 0,
29
+ class: "panel-muted"
30
+ };
31
+ var _hoisted_10 = {
32
+ key: 0,
33
+ class: "panel-error",
34
+ role: "alert"
35
+ };
36
+ var _hoisted_11 = { class: "columnas" };
37
+ var _hoisted_12 = { class: "panel hilo" };
38
+ var _hoisted_13 = {
39
+ class: "mensajes",
40
+ "aria-label": "Mensajes"
41
+ };
42
+ var _hoisted_14 = { class: "mensaje-autor" };
43
+ var _hoisted_15 = { class: "mensaje-hora" };
44
+ var _hoisted_16 = { class: "mensaje-cuerpo" };
45
+ var _hoisted_17 = { scope: "row" };
46
+ var _hoisted_18 = {
47
+ key: 0,
48
+ class: "mensaje-hora"
49
+ };
50
+ var _hoisted_19 = ["placeholder"];
51
+ var _hoisted_20 = { class: "toolbar" };
52
+ var _hoisted_21 = { class: "label" };
53
+ var _hoisted_22 = ["value"];
54
+ var _hoisted_23 = {
55
+ key: 1,
56
+ class: "panel-muted"
57
+ };
58
+ var _hoisted_24 = ["disabled"];
59
+ var _hoisted_25 = {
60
+ key: 1,
61
+ class: "panel-muted"
62
+ };
63
+ var _hoisted_26 = { class: "lateral" };
64
+ var _hoisted_27 = { class: "panel" };
65
+ var _hoisted_28 = {
66
+ key: 0,
67
+ class: "acciones"
68
+ };
69
+ var _hoisted_29 = ["disabled"];
70
+ var _hoisted_30 = ["disabled"];
71
+ var _hoisted_31 = ["disabled"];
72
+ var _hoisted_32 = ["disabled"];
73
+ var _hoisted_33 = {
74
+ key: 1,
75
+ class: "panel-muted"
76
+ };
77
+ var _hoisted_34 = {
78
+ key: 2,
79
+ class: "campo"
80
+ };
81
+ var _hoisted_35 = ["disabled"];
82
+ var _hoisted_36 = ["value"];
83
+ var _hoisted_37 = { class: "campo" };
84
+ var _hoisted_38 = ["value"];
85
+ var _hoisted_39 = { class: "campo" };
86
+ var _hoisted_40 = ["value"];
87
+ var _hoisted_41 = { class: "campo" };
88
+ var _hoisted_42 = ["disabled"];
89
+ var _hoisted_43 = { class: "panel" };
90
+ var _hoisted_44 = { class: "panel-muted" };
91
+ var _hoisted_45 = {
92
+ key: 0,
93
+ class: "panel-muted"
94
+ };
95
+ var _hoisted_46 = {
96
+ key: 2,
97
+ class: "panel-muted"
98
+ };
99
+ var _hoisted_47 = {
100
+ key: 3,
101
+ class: "panel-muted"
102
+ };
103
+ var _hoisted_48 = { class: "panel" };
104
+ var _hoisted_49 = { class: "ficha" };
105
+ var _hoisted_50 = { key: 0 };
106
+ var _hoisted_51 = { key: 1 };
107
+ var _hoisted_52 = { key: 2 };
108
+ var _hoisted_53 = { key: 3 };
109
+ var _hoisted_54 = { class: "panel" };
110
+ var _hoisted_55 = { class: "eventos" };
111
+ var _hoisted_56 = { class: "sub" };
112
+ /**
113
+ * Una conversación del chat: el hilo completo (con las notas internas, que el empleado no
114
+ * ve), la ficha del empleo (con el cliente interno desde el que escribe) y las acciones de la
115
+ * bandeja. Se actualiza sola cada 10 segundos.
116
+ */
117
+ var CADA_MS = 1e4;
118
+ //#endregion
119
+ //#region src/views/chat/ChatConversacionView.vue
120
+ var ChatConversacionView_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
121
+ __name: "ChatConversacionView",
122
+ props: { id: {} },
123
+ setup(__props) {
124
+ const props = __props;
125
+ const router = useRouter();
126
+ const auth = useAuthStore();
127
+ const c = ref(null);
128
+ const resumen = ref(null);
129
+ const personas = ref([]);
130
+ const temas = ref([]);
131
+ const respuestas = ref([]);
132
+ /** Las del tema de la conversación y las generales. */
133
+ const respuestasDelTema = computed(() => respuestas.value.filter((r) => r.tema_id === null || r.tema_id === c.value?.tema?.id));
134
+ /** Inserta una respuesta guardada en el cuadro de texto, con el primer nombre del empleado. */
135
+ function insertarRespuesta(e) {
136
+ const select = e.target;
137
+ const r = respuestas.value.find((x) => x.id === Number(select.value));
138
+ select.value = "";
139
+ if (!r) return;
140
+ const nombre = (c.value?.empleado ?? "").trim().split(/\s+/)[0] ?? "";
141
+ const texto = r.cuerpo.replaceAll("{nombre}", nombre);
142
+ cuerpo.value = cuerpo.value.trim() ? `${cuerpo.value.trimEnd()}\n${texto}` : texto;
143
+ }
144
+ const cargando = ref(true);
145
+ const ocupado = ref(false);
146
+ const error = ref(null);
147
+ const cuerpo = ref("");
148
+ const interno = ref(false);
149
+ const ahora = ref(Date.now());
150
+ const fin = ref(null);
151
+ const reasignando = ref(false);
152
+ const cambio = ref({
153
+ usuario_id: null,
154
+ tema_id: null,
155
+ comentario: ""
156
+ });
157
+ const miId = computed(() => auth.usuario?.id ?? null);
158
+ const esMia = computed(() => c.value?.asignada_a?.id === miId.value);
159
+ const abierta = computed(() => [
160
+ "sin_asignar",
161
+ "asignada",
162
+ "esperando_empleado"
163
+ ].includes(c.value?.estado ?? ""));
164
+ /** Responde quien la tiene asignada, un admin, o cualquiera si nadie la tiene (al responder la toma). */
165
+ const puedeResponder = computed(() => c.value !== null && c.value.estado !== "cerrada" && (!c.value.asignada_a || esMia.value || resumen.value?.es_admin === true));
166
+ const atienden = computed(() => personas.value.filter((p) => p.atiende_chat));
167
+ async function cargar(silencioso = false) {
168
+ if (!silencioso) cargando.value = true;
169
+ try {
170
+ const antes = c.value?.mensajes.length ?? 0;
171
+ c.value = await chatService.conversacion(props.id);
172
+ ahora.value = Date.now();
173
+ if (c.value.mensajes.length !== antes) await bajar();
174
+ if (!silencioso) error.value = null;
175
+ } catch (e) {
176
+ error.value = mensajeError(e, "No se pudo cargar la conversación.");
177
+ } finally {
178
+ cargando.value = false;
179
+ }
180
+ }
181
+ async function bajar() {
182
+ await nextTick();
183
+ fin.value?.scrollIntoView({ block: "end" });
184
+ }
185
+ async function accion(fn, falla) {
186
+ ocupado.value = true;
187
+ error.value = null;
188
+ try {
189
+ const r = await fn();
190
+ if (r === null) {
191
+ await router.replace({ name: RUTAS_PORTAL.chat });
192
+ return;
193
+ }
194
+ c.value = r;
195
+ await bajar();
196
+ } catch (e) {
197
+ error.value = mensajeError(e, falla);
198
+ } finally {
199
+ ocupado.value = false;
200
+ }
201
+ }
202
+ async function responder() {
203
+ const texto = cuerpo.value.trim();
204
+ if (!texto) return;
205
+ await accion(() => chatService.responder(props.id, texto, interno.value), "No se pudo enviar el mensaje.");
206
+ if (!error.value) {
207
+ cuerpo.value = "";
208
+ interno.value = false;
209
+ }
210
+ }
211
+ const tomar = () => accion(() => chatService.tomar(props.id), "No se pudo tomar la conversación.");
212
+ const esperando = () => accion(() => chatService.esperando(props.id), "No se pudo cambiar el estado.");
213
+ function resolver() {
214
+ const comentario = window.prompt("Comentario de cierre (opcional, no lo ve el empleado):", "");
215
+ if (comentario === null) return;
216
+ accion(() => chatService.resolver(props.id, comentario.trim() || null), "No se pudo resolver la conversación.");
217
+ }
218
+ function asignar(e) {
219
+ const usuarioId = Number(e.target.value);
220
+ if (!usuarioId) return;
221
+ accion(() => chatService.asignar(props.id, usuarioId), "No se pudo asignar la conversación.");
222
+ }
223
+ async function reasignar() {
224
+ await accion(() => chatService.reasignar(props.id, {
225
+ ...cambio.value,
226
+ comentario: cambio.value.comentario.trim()
227
+ }), "No se pudo reasignar.");
228
+ if (!error.value) {
229
+ reasignando.value = false;
230
+ cambio.value = {
231
+ usuario_id: null,
232
+ tema_id: null,
233
+ comentario: ""
234
+ };
235
+ }
236
+ }
237
+ function autor(m) {
238
+ if (m.autor === "empleado") return c.value?.empleado ?? "Empleado";
239
+ if (m.autor === "sistema") return "Sistema";
240
+ if (m.autor === "ia") return "Asistente";
241
+ return m.autor_nombre ?? "RRHH";
242
+ }
243
+ const textoEvento = {
244
+ escalada: "Llegó a RRHH",
245
+ tomada: "La tomó",
246
+ asignada: "Asignada",
247
+ reasignada: "Reasignada",
248
+ cambio_tema: "Cambio de tema",
249
+ esperando: "Esperando al empleado",
250
+ resuelta: "Resuelta",
251
+ reabierta: "Reabierta",
252
+ cerrada: "Cerrada",
253
+ abierta_por_rrhh: "La abrió"
254
+ };
255
+ let reloj = null;
256
+ onMounted(async () => {
257
+ await cargar();
258
+ [resumen.value, personas.value, temas.value, respuestas.value] = await Promise.all([
259
+ chatService.resumen().catch(() => null),
260
+ chatService.personas().catch(() => []),
261
+ chatService.temas().catch(() => []),
262
+ chatService.respuestas().catch(() => [])
263
+ ]);
264
+ reloj = setInterval(() => void cargar(true), CADA_MS);
265
+ });
266
+ onBeforeUnmount(() => {
267
+ if (reloj) clearInterval(reloj);
268
+ });
269
+ return (_ctx, _cache) => {
270
+ return openBlock(), createElementBlock("section", _hoisted_1, [createVNode(unref(RouterLink), {
271
+ to: { name: unref(RUTAS_PORTAL).chat },
272
+ class: "volver"
273
+ }, {
274
+ default: withCtx(() => [..._cache[6] || (_cache[6] = [createTextVNode("← Bandeja", -1)])]),
275
+ _: 1
276
+ }, 8, ["to"]), cargando.value ? (openBlock(), createElementBlock("p", _hoisted_2, "Cargando…")) : !c.value ? (openBlock(), createElementBlock("p", _hoisted_3, toDisplayString(error.value), 1)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
277
+ createElementVNode("header", _hoisted_4, [createElementVNode("div", null, [
278
+ createElementVNode("h1", _hoisted_5, toDisplayString(c.value.empleado ?? "Empleado"), 1),
279
+ createElementVNode("p", _hoisted_6, [createTextVNode(toDisplayString(c.value.identificacion) + " · " + toDisplayString(c.value.tema?.nombre ?? "Sin tema"), 1), c.value.tema?.confidencial ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" (confidencial)")], 64)) : createCommentVNode("", true)]),
280
+ c.value.cliente_interno ? (openBlock(), createElementBlock("p", _hoisted_7, [
281
+ _cache[7] || (_cache[7] = createTextVNode(" Escribe desde ", -1)),
282
+ createElementVNode("strong", null, toDisplayString(c.value.cliente_interno.nombre), 1),
283
+ c.value.cliente_interno.nit ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" · NIT " + toDisplayString(c.value.cliente_interno.nit), 1)], 64)) : createCommentVNode("", true)
284
+ ])) : createCommentVNode("", true)
285
+ ]), createElementVNode("div", _hoisted_8, [createElementVNode("span", { class: normalizeClass(["estado", unref(ESTADOS_CONVERSACION)[c.value.estado].clase]) }, toDisplayString(unref(ESTADOS_CONVERSACION)[c.value.estado].texto), 3), c.value.asignada_a ? (openBlock(), createElementBlock("span", _hoisted_9, "Atiende: " + toDisplayString(c.value.asignada_a.nombre), 1)) : createCommentVNode("", true)])]),
286
+ error.value ? (openBlock(), createElementBlock("p", _hoisted_10, toDisplayString(error.value), 1)) : createCommentVNode("", true),
287
+ createElementVNode("div", _hoisted_11, [createElementVNode("div", _hoisted_12, [
288
+ createElementVNode("ol", _hoisted_13, [(openBlock(true), createElementBlock(Fragment, null, renderList(c.value.mensajes, (m) => {
289
+ return openBlock(), createElementBlock("li", {
290
+ key: m.id,
291
+ class: normalizeClass(["mensaje", {
292
+ propio: m.autor === "rrhh" && !m.interno,
293
+ nota: m.interno,
294
+ sistema: m.autor === "sistema",
295
+ ia: m.autor === "ia"
296
+ }])
297
+ }, [
298
+ createElementVNode("p", _hoisted_14, [
299
+ createTextVNode(toDisplayString(autor(m)), 1),
300
+ m.interno ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" · nota interna")], 64)) : createCommentVNode("", true),
301
+ createElementVNode("span", _hoisted_15, toDisplayString(unref(fechaHora)(m.creado_en)), 1)
302
+ ]),
303
+ createElementVNode("p", _hoisted_16, toDisplayString(m.cuerpo), 1),
304
+ (openBlock(true), createElementBlock(Fragment, null, renderList(m.tarjetas ?? [], (t, i) => {
305
+ return openBlock(), createElementBlock("table", {
306
+ key: i,
307
+ class: "tarjeta-datos"
308
+ }, [createElementVNode("caption", null, toDisplayString(t.titulo), 1), createElementVNode("tbody", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(t.filas, (fila, j) => {
309
+ return openBlock(), createElementBlock("tr", { key: j }, [createElementVNode("th", _hoisted_17, toDisplayString(fila[0]), 1), createElementVNode("td", null, toDisplayString(fila[1]), 1)]);
310
+ }), 128))])]);
311
+ }), 128)),
312
+ m.util != null ? (openBlock(), createElementBlock("p", _hoisted_18, toDisplayString(m.util ? "Al empleado le sirvió" : "Al empleado no le sirvió"), 1)) : createCommentVNode("", true)
313
+ ], 2);
314
+ }), 128))]),
315
+ createElementVNode("div", {
316
+ ref_key: "fin",
317
+ ref: fin
318
+ }, null, 512),
319
+ puedeResponder.value ? (openBlock(), createElementBlock("form", {
320
+ key: 0,
321
+ class: "respuesta",
322
+ onSubmit: withModifiers(responder, ["prevent"])
323
+ }, [
324
+ _cache[10] || (_cache[10] = createElementVNode("label", {
325
+ for: "chat-respuesta",
326
+ class: "sr-only"
327
+ }, "Respuesta", -1)),
328
+ withDirectives(createElementVNode("textarea", {
329
+ id: "chat-respuesta",
330
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => cuerpo.value = $event),
331
+ class: "input",
332
+ rows: "3",
333
+ maxlength: "4000",
334
+ placeholder: interno.value ? "Nota para RRHH (el empleado no la ve)" : "Respuesta para el empleado"
335
+ }, null, 8, _hoisted_19), [[vModelText, cuerpo.value]]),
336
+ createElementVNode("div", _hoisted_20, [
337
+ createElementVNode("label", _hoisted_21, [withDirectives(createElementVNode("input", {
338
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => interno.value = $event),
339
+ type: "checkbox"
340
+ }, null, 512), [[vModelCheckbox, interno.value]]), _cache[8] || (_cache[8] = createTextVNode(" Nota interna", -1))]),
341
+ respuestas.value.length ? (openBlock(), createElementBlock("select", {
342
+ key: 0,
343
+ class: "input",
344
+ "aria-label": "Insertar una respuesta guardada",
345
+ onChange: insertarRespuesta
346
+ }, [_cache[9] || (_cache[9] = createElementVNode("option", { value: "" }, "Respuesta guardada…", -1)), (openBlock(true), createElementBlock(Fragment, null, renderList(respuestasDelTema.value, (r) => {
347
+ return openBlock(), createElementBlock("option", {
348
+ key: r.id,
349
+ value: r.id
350
+ }, toDisplayString(r.titulo), 9, _hoisted_22);
351
+ }), 128))], 32)) : createCommentVNode("", true),
352
+ !c.value.asignada_a && !interno.value ? (openBlock(), createElementBlock("span", _hoisted_23, "Al responder, la conversación queda asignada a usted.")) : createCommentVNode("", true),
353
+ createElementVNode("button", {
354
+ type: "submit",
355
+ class: "btn-primary",
356
+ style: { "margin-left": "auto" },
357
+ disabled: ocupado.value || !cuerpo.value.trim()
358
+ }, toDisplayString(interno.value ? "Guardar nota" : "Enviar"), 9, _hoisted_24)
359
+ ])
360
+ ], 32)) : c.value.estado !== "cerrada" ? (openBlock(), createElementBlock("p", _hoisted_25, "La atiende " + toDisplayString(c.value.asignada_a?.nombre) + ". Puede dejar una nota interna si se la reasignan.", 1)) : createCommentVNode("", true)
361
+ ]), createElementVNode("aside", _hoisted_26, [
362
+ createElementVNode("div", _hoisted_27, [
363
+ _cache[18] || (_cache[18] = createElementVNode("p", { class: "panel-title" }, "Acciones", -1)),
364
+ abierta.value ? (openBlock(), createElementBlock("div", _hoisted_28, [
365
+ c.value.estado === "sin_asignar" ? (openBlock(), createElementBlock("button", {
366
+ key: 0,
367
+ type: "button",
368
+ class: "btn-primary",
369
+ disabled: ocupado.value,
370
+ onClick: tomar
371
+ }, "Tomar", 8, _hoisted_29)) : createCommentVNode("", true),
372
+ c.value.estado === "asignada" ? (openBlock(), createElementBlock("button", {
373
+ key: 1,
374
+ type: "button",
375
+ class: "btn-secondary",
376
+ disabled: ocupado.value,
377
+ onClick: esperando
378
+ }, " Esperando al empleado ", 8, _hoisted_30)) : createCommentVNode("", true),
379
+ createElementVNode("button", {
380
+ type: "button",
381
+ class: "btn-secondary",
382
+ disabled: ocupado.value,
383
+ onClick: _cache[2] || (_cache[2] = ($event) => reasignando.value = !reasignando.value)
384
+ }, "Reasignar…", 8, _hoisted_31),
385
+ createElementVNode("button", {
386
+ type: "button",
387
+ class: "btn-primary",
388
+ disabled: ocupado.value,
389
+ onClick: resolver
390
+ }, "Resolver", 8, _hoisted_32)
391
+ ])) : (openBlock(), createElementBlock("p", _hoisted_33, "Conversación " + toDisplayString(unref(ESTADOS_CONVERSACION)[c.value.estado].texto.toLowerCase()) + ".", 1)),
392
+ abierta.value && resumen.value?.es_admin ? (openBlock(), createElementBlock("label", _hoisted_34, [_cache[12] || (_cache[12] = createElementVNode("span", { class: "label" }, "Asignar a", -1)), createElementVNode("select", {
393
+ class: "input",
394
+ disabled: ocupado.value,
395
+ onChange: asignar
396
+ }, [_cache[11] || (_cache[11] = createElementVNode("option", { value: "" }, "Elegir persona…", -1)), (openBlock(true), createElementBlock(Fragment, null, renderList(atienden.value, (p) => {
397
+ return openBlock(), createElementBlock("option", {
398
+ key: p.id,
399
+ value: p.id
400
+ }, toDisplayString(p.nombre), 9, _hoisted_36);
401
+ }), 128))], 40, _hoisted_35)])) : createCommentVNode("", true),
402
+ reasignando.value ? (openBlock(), createElementBlock("form", {
403
+ key: 3,
404
+ class: "reasignar",
405
+ onSubmit: withModifiers(reasignar, ["prevent"])
406
+ }, [
407
+ createElementVNode("label", _hoisted_37, [_cache[14] || (_cache[14] = createElementVNode("span", { class: "label" }, "Otra persona (opcional)", -1)), withDirectives(createElementVNode("select", {
408
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => cambio.value.usuario_id = $event),
409
+ class: "input"
410
+ }, [_cache[13] || (_cache[13] = createElementVNode("option", { value: null }, "Nadie: vuelve a «sin asignar»", -1)), (openBlock(true), createElementBlock(Fragment, null, renderList(atienden.value, (p) => {
411
+ return openBlock(), createElementBlock("option", {
412
+ key: p.id,
413
+ value: p.id
414
+ }, toDisplayString(p.nombre), 9, _hoisted_38);
415
+ }), 128))], 512), [[vModelSelect, cambio.value.usuario_id]])]),
416
+ createElementVNode("label", _hoisted_39, [_cache[16] || (_cache[16] = createElementVNode("span", { class: "label" }, "Otro tema (opcional)", -1)), withDirectives(createElementVNode("select", {
417
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => cambio.value.tema_id = $event),
418
+ class: "input"
419
+ }, [_cache[15] || (_cache[15] = createElementVNode("option", { value: null }, "El mismo", -1)), (openBlock(true), createElementBlock(Fragment, null, renderList(temas.value.filter((x) => x.activo), (t) => {
420
+ return openBlock(), createElementBlock("option", {
421
+ key: t.id,
422
+ value: t.id
423
+ }, toDisplayString(t.nombre), 9, _hoisted_40);
424
+ }), 128))], 512), [[vModelSelect, cambio.value.tema_id]])]),
425
+ createElementVNode("label", _hoisted_41, [_cache[17] || (_cache[17] = createElementVNode("span", { class: "label" }, "Motivo", -1)), withDirectives(createElementVNode("input", {
426
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => cambio.value.comentario = $event),
427
+ class: "input",
428
+ maxlength: "500",
429
+ required: ""
430
+ }, null, 512), [[vModelText, cambio.value.comentario]])]),
431
+ createElementVNode("button", {
432
+ type: "submit",
433
+ class: "btn-primary",
434
+ disabled: ocupado.value || !cambio.value.comentario.trim()
435
+ }, "Reasignar", 8, _hoisted_42)
436
+ ], 32)) : createCommentVNode("", true)
437
+ ]),
438
+ createElementVNode("div", _hoisted_43, [
439
+ _cache[19] || (_cache[19] = createElementVNode("p", { class: "panel-title" }, "Plazos", -1)),
440
+ createElementVNode("p", _hoisted_44, toDisplayString(unref(MOTIVOS_ESCALAMIENTO)[c.value.motivo_escalamiento ?? ""] ?? "—"), 1),
441
+ c.value.primera_respuesta_en ? (openBlock(), createElementBlock("p", _hoisted_45, "Primera respuesta: " + toDisplayString(unref(fechaHora)(c.value.primera_respuesta_en)), 1)) : c.value.vence_primera_respuesta_en ? (openBlock(), createElementBlock("p", {
442
+ key: 1,
443
+ class: normalizeClass(["panel-muted", { vencida: c.value.vencida }])
444
+ }, " Primera respuesta " + toDisplayString(unref(relativo)(c.value.vence_primera_respuesta_en, ahora.value)) + " (" + toDisplayString(unref(fechaHora)(c.value.vence_primera_respuesta_en)) + ") ", 3)) : createCommentVNode("", true),
445
+ c.value.vence_resolucion_en && abierta.value ? (openBlock(), createElementBlock("p", _hoisted_46, "Resolver antes de " + toDisplayString(unref(fechaHora)(c.value.vence_resolucion_en)), 1)) : createCommentVNode("", true),
446
+ c.value.calificacion ? (openBlock(), createElementBlock("p", _hoisted_47, "Calificación del empleado: " + toDisplayString(c.value.calificacion) + "/5", 1)) : createCommentVNode("", true)
447
+ ]),
448
+ createElementVNode("div", _hoisted_48, [_cache[25] || (_cache[25] = createElementVNode("p", { class: "panel-title" }, "Empleo", -1)), createElementVNode("dl", _hoisted_49, [
449
+ c.value.cliente_interno ? (openBlock(), createElementBlock("dt", _hoisted_50, "Cliente")) : createCommentVNode("", true),
450
+ c.value.cliente_interno ? (openBlock(), createElementBlock("dd", _hoisted_51, [createTextVNode(toDisplayString(c.value.cliente_interno.nombre), 1), c.value.cliente_interno.nit ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" · NIT " + toDisplayString(c.value.cliente_interno.nit), 1)], 64)) : createCommentVNode("", true)])) : createCommentVNode("", true),
451
+ _cache[20] || (_cache[20] = createElementVNode("dt", null, "Cargo", -1)),
452
+ createElementVNode("dd", null, toDisplayString(c.value.empleo.cargo ?? "—"), 1),
453
+ _cache[21] || (_cache[21] = createElementVNode("dt", null, "Contrato", -1)),
454
+ createElementVNode("dd", null, toDisplayString(c.value.empleo.tipo_contrato ?? "—"), 1),
455
+ _cache[22] || (_cache[22] = createElementVNode("dt", null, "Ingreso", -1)),
456
+ createElementVNode("dd", null, toDisplayString(c.value.empleo.fecha_ingreso ?? "—"), 1),
457
+ c.value.empleo.fecha_retiro ? (openBlock(), createElementBlock("dt", _hoisted_52, "Retiro")) : createCommentVNode("", true),
458
+ c.value.empleo.fecha_retiro ? (openBlock(), createElementBlock("dd", _hoisted_53, toDisplayString(c.value.empleo.fecha_retiro), 1)) : createCommentVNode("", true),
459
+ _cache[23] || (_cache[23] = createElementVNode("dt", null, "Vacaciones", -1)),
460
+ createElementVNode("dd", null, [createTextVNode(toDisplayString(c.value.empleo.dias_vacaciones ?? "—") + " días", 1), c.value.empleo.vacaciones_corte ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" al " + toDisplayString(c.value.empleo.vacaciones_corte), 1)], 64)) : createCommentVNode("", true)]),
461
+ _cache[24] || (_cache[24] = createElementVNode("dt", null, "Solicitudes abiertas", -1)),
462
+ createElementVNode("dd", null, toDisplayString(c.value.empleo.solicitudes_abiertas), 1)
463
+ ])]),
464
+ createElementVNode("div", _hoisted_54, [_cache[26] || (_cache[26] = createElementVNode("p", { class: "panel-title" }, "Historial", -1)), createElementVNode("ol", _hoisted_55, [(openBlock(true), createElementBlock(Fragment, null, renderList(c.value.eventos, (ev, i) => {
465
+ return openBlock(), createElementBlock("li", { key: i }, [
466
+ createElementVNode("strong", null, toDisplayString(textoEvento[ev.tipo] ?? ev.tipo), 1),
467
+ ev.usuario ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" · " + toDisplayString(ev.usuario), 1)], 64)) : createCommentVNode("", true),
468
+ createElementVNode("span", _hoisted_56, [createTextVNode(toDisplayString(unref(fechaHora)(ev.creado_en)), 1), ev.detalle ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" · " + toDisplayString(ev.detalle), 1)], 64)) : createCommentVNode("", true)])
469
+ ]);
470
+ }), 128))])])
471
+ ])])
472
+ ], 64))]);
473
+ };
474
+ }
475
+ }), [["__scopeId", "data-v-8a10d53d"]]);
476
+ //#endregion
477
+ export { ChatConversacionView_default as default };