@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,450 @@
1
+ import { t as api } from "./api-M7D1c3IT.js";
2
+ import { t as useClienteInternoStore } from "./cliente-interno.store-De39VsEE.js";
3
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BOaGB7Aw.js";
4
+ import { t as mensajeError } from "./apiError-BHGbwz97.js";
5
+ import { t as ToggleSwitch_default } from "./ToggleSwitch-BYrIyheq.js";
6
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderList, toDisplayString, unref, vModelText, watch, withDirectives } from "vue";
7
+ //#region src/services/configuracion-cliente-interno.service.ts
8
+ var carnetClientesInternosService = {
9
+ async config() {
10
+ const { data } = await api.get("/carnet/config");
11
+ return data.data;
12
+ },
13
+ /** Valor propio de un cliente interno. */
14
+ async fijar(clienteInternoId, activo) {
15
+ const { data } = await api.patch("/carnet/config", {
16
+ carnet_activo: activo,
17
+ cliente_interno_id: clienteInternoId
18
+ });
19
+ return data.data;
20
+ },
21
+ /** Quita el valor propio: vuelve a heredar el del tenant. */
22
+ async heredar(clienteInternoId) {
23
+ const { data } = await api.delete(`/carnet/config/clientes-internos/${clienteInternoId}`);
24
+ return data.data;
25
+ }
26
+ };
27
+ //#endregion
28
+ //#region src/components/CarnetClientesInternos.vue?vue&type=script&setup=true&lang.ts
29
+ var _hoisted_1$1 = { class: "panel" };
30
+ var _hoisted_2$1 = { class: "fila" };
31
+ var _hoisted_3$1 = { class: "panel-title" };
32
+ var _hoisted_4$1 = { class: "panel-muted" };
33
+ var _hoisted_5$1 = { class: "control" };
34
+ var _hoisted_6$1 = [
35
+ "aria-label",
36
+ "value",
37
+ "disabled"
38
+ ];
39
+ var _hoisted_7$1 = {
40
+ key: 0,
41
+ class: "panel-error",
42
+ role: "alert"
43
+ };
44
+ //#endregion
45
+ //#region src/components/CarnetClientesInternos.vue
46
+ var CarnetClientesInternos_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
47
+ __name: "CarnetClientesInternos",
48
+ props: {
49
+ clienteId: {},
50
+ tenantActivo: { type: Boolean }
51
+ },
52
+ setup(__props) {
53
+ const props = __props;
54
+ const clientesInternos = useClienteInternoStore();
55
+ const propios = ref([]);
56
+ const ocupado = ref(false);
57
+ const error = ref(null);
58
+ const nombre = computed(() => clientesInternos.nombre(props.clienteId));
59
+ const propio = computed(() => propios.value.find((p) => p.cliente_interno_id === props.clienteId)?.activo);
60
+ const opcion = computed(() => propio.value === void 0 ? "heredar" : propio.value ? "si" : "no");
61
+ const efectivo = computed(() => propio.value ?? props.tenantActivo);
62
+ async function cargar() {
63
+ error.value = null;
64
+ try {
65
+ propios.value = (await carnetClientesInternosService.config()).clientes_internos;
66
+ } catch (e) {
67
+ error.value = mensajeError(e, "No se pudo cargar el carnet del cliente.");
68
+ }
69
+ }
70
+ async function cambiar(valor) {
71
+ ocupado.value = true;
72
+ error.value = null;
73
+ try {
74
+ const config = valor === "heredar" ? await carnetClientesInternosService.heredar(props.clienteId) : await carnetClientesInternosService.fijar(props.clienteId, valor === "si");
75
+ propios.value = config.clientes_internos;
76
+ } catch (e) {
77
+ error.value = mensajeError(e, "No se pudo guardar el cambio.");
78
+ } finally {
79
+ ocupado.value = false;
80
+ }
81
+ }
82
+ watch(() => props.clienteId, () => void cargar());
83
+ onMounted(() => void cargar());
84
+ return (_ctx, _cache) => {
85
+ return openBlock(), createElementBlock("div", _hoisted_1$1, [createElementVNode("div", _hoisted_2$1, [createElementVNode("div", null, [createElementVNode("p", _hoisted_3$1, "Carnet digital para los empleados de " + toDisplayString(nombre.value), 1), createElementVNode("p", _hoisted_4$1, " Usa lo de todo el tenant (hoy " + toDisplayString(__props.tenantActivo ? "encendido" : "apagado") + "), salvo que le fije su propio valor: ese prevalece para sus empleados. ", 1)]), createElementVNode("div", _hoisted_5$1, [createElementVNode("select", {
86
+ id: "carnet-cliente-interno",
87
+ class: "campo",
88
+ "aria-label": `Carnet para ${nombre.value}`,
89
+ value: opcion.value,
90
+ disabled: ocupado.value,
91
+ onChange: _cache[0] || (_cache[0] = ($event) => cambiar($event.target.value))
92
+ }, [..._cache[1] || (_cache[1] = [
93
+ createElementVNode("option", { value: "heredar" }, "Como todo el tenant", -1),
94
+ createElementVNode("option", { value: "si" }, "Encendido", -1),
95
+ createElementVNode("option", { value: "no" }, "Apagado", -1)
96
+ ])], 40, _hoisted_6$1), createElementVNode("span", { class: normalizeClass(["estado", efectivo.value ? "estado-si" : "estado-no"]) }, toDisplayString(efectivo.value ? "Encendido" : "Apagado"), 3)])]), error.value ? (openBlock(), createElementBlock("p", _hoisted_7$1, toDisplayString(error.value), 1)) : createCommentVNode("", true)]);
97
+ };
98
+ }
99
+ }), [["__scopeId", "data-v-1a4f4dcb"]]);
100
+ //#endregion
101
+ //#region src/services/carnet.service.ts
102
+ var carnetService = {
103
+ async config() {
104
+ const { data } = await api.get("/carnet/config");
105
+ return data.data.carnet_activo;
106
+ },
107
+ async activar(activo) {
108
+ const { data } = await api.patch("/carnet/config", { carnet_activo: activo });
109
+ return data.data.carnet_activo;
110
+ },
111
+ /** Con `clienteInterno`, solo las de los empleados de ese cliente interno. */
112
+ async fotos(estado = "pendiente", clienteInterno = null) {
113
+ const params = { estado };
114
+ if (clienteInterno !== null) params.cliente_interno_id = clienteInterno;
115
+ const { data } = await api.get("/carnet/fotos", { params });
116
+ return data.data;
117
+ },
118
+ /** La imagen va con el token de la sesión: se pide como blob y se muestra con una URL local. */
119
+ async imagen(id) {
120
+ const { data } = await api.get(`/carnet/fotos/${id}/imagen`, { responseType: "blob" });
121
+ return data;
122
+ },
123
+ /** Aprueba la foto y la envía a SoftDIN; responde cómo quedó ese envío. */
124
+ async aprobar(id) {
125
+ const { data } = await api.post(`/carnet/fotos/${id}/aprobar`);
126
+ return data.data;
127
+ },
128
+ /** Reintenta a mano el envío a SoftDIN de una foto aprobada. */
129
+ async sincronizar(id) {
130
+ const { data } = await api.post(`/carnet/fotos/${id}/sincronizar`);
131
+ return data.data;
132
+ },
133
+ async rechazar(id, motivo) {
134
+ await api.post(`/carnet/fotos/${id}/rechazar`, { motivo });
135
+ },
136
+ /** Con `clienteInterno`, solo los de los empleados de ese cliente interno. */
137
+ async carnets(clienteInterno = null) {
138
+ const params = clienteInterno === null ? {} : { cliente_interno_id: clienteInterno };
139
+ const { data } = await api.get("/carnet/carnets", { params });
140
+ return data.data;
141
+ },
142
+ async revocar(id) {
143
+ await api.post(`/carnet/carnets/${id}/revocar`);
144
+ }
145
+ };
146
+ //#endregion
147
+ //#region src/views/CarnetView.vue?vue&type=script&setup=true&lang.ts
148
+ var _hoisted_1 = { class: "page-shell" };
149
+ var _hoisted_2 = {
150
+ key: 0,
151
+ class: "panel-error",
152
+ role: "alert"
153
+ };
154
+ var _hoisted_3 = {
155
+ key: 1,
156
+ class: "panel-aviso",
157
+ role: "status"
158
+ };
159
+ var _hoisted_4 = {
160
+ key: 2,
161
+ class: "panel-muted"
162
+ };
163
+ var _hoisted_5 = {
164
+ key: 0,
165
+ class: "panel flex-row"
166
+ };
167
+ var _hoisted_6 = { class: "panel" };
168
+ var _hoisted_7 = { class: "panel-title" };
169
+ var _hoisted_8 = {
170
+ key: 0,
171
+ class: "panel-muted"
172
+ };
173
+ var _hoisted_9 = {
174
+ key: 1,
175
+ class: "fotos"
176
+ };
177
+ var _hoisted_10 = ["src", "alt"];
178
+ var _hoisted_11 = {
179
+ key: 1,
180
+ class: "foto-vacia"
181
+ };
182
+ var _hoisted_12 = { class: "foto-nombre" };
183
+ var _hoisted_13 = { class: "panel-muted" };
184
+ var _hoisted_14 = {
185
+ key: 2,
186
+ class: "panel-muted"
187
+ };
188
+ var _hoisted_15 = ["onUpdate:modelValue"];
189
+ var _hoisted_16 = { class: "acciones" };
190
+ var _hoisted_17 = ["disabled", "onClick"];
191
+ var _hoisted_18 = ["disabled"];
192
+ var _hoisted_19 = {
193
+ key: 4,
194
+ class: "acciones"
195
+ };
196
+ var _hoisted_20 = ["disabled", "onClick"];
197
+ var _hoisted_21 = ["disabled", "onClick"];
198
+ var _hoisted_22 = { class: "panel" };
199
+ var _hoisted_23 = { class: "panel-title" };
200
+ var _hoisted_24 = {
201
+ key: 0,
202
+ class: "panel-muted"
203
+ };
204
+ var _hoisted_25 = {
205
+ key: 1,
206
+ class: "table-wrap"
207
+ };
208
+ var _hoisted_26 = { class: "data-table" };
209
+ var _hoisted_27 = {
210
+ key: 0,
211
+ class: "insignia insignia-ok"
212
+ };
213
+ var _hoisted_28 = {
214
+ key: 0,
215
+ class: "panel-muted"
216
+ };
217
+ var _hoisted_29 = {
218
+ key: 1,
219
+ class: "panel-muted"
220
+ };
221
+ var _hoisted_30 = {
222
+ key: 2,
223
+ class: "panel-muted"
224
+ };
225
+ var _hoisted_31 = ["disabled", "onClick"];
226
+ var _hoisted_32 = { class: "panel" };
227
+ var _hoisted_33 = { class: "panel-title" };
228
+ var _hoisted_34 = {
229
+ key: 0,
230
+ class: "panel-muted"
231
+ };
232
+ var _hoisted_35 = {
233
+ key: 1,
234
+ class: "table-wrap"
235
+ };
236
+ var _hoisted_36 = { class: "data-table" };
237
+ var _hoisted_37 = ["disabled", "onClick"];
238
+ //#endregion
239
+ //#region src/views/CarnetView.vue
240
+ var CarnetView_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
241
+ __name: "CarnetView",
242
+ setup(__props) {
243
+ const clientesInternos = useClienteInternoStore();
244
+ const activo = ref(false);
245
+ const fotos = ref([]);
246
+ const aprobadas = ref([]);
247
+ const aviso = ref(null);
248
+ const carnets = ref([]);
249
+ const imagenes = ref({});
250
+ const motivos = ref({});
251
+ const rechazando = ref(null);
252
+ const cargando = ref(true);
253
+ const ocupado = ref(false);
254
+ const error = ref(null);
255
+ function soltarImagenes() {
256
+ Object.values(imagenes.value).forEach((u) => URL.revokeObjectURL(u));
257
+ imagenes.value = {};
258
+ }
259
+ async function cargar() {
260
+ cargando.value = true;
261
+ error.value = null;
262
+ try {
263
+ activo.value = await carnetService.config();
264
+ [fotos.value, aprobadas.value, carnets.value] = await Promise.all([
265
+ carnetService.fotos("pendiente", clientesInternos.seleccionado),
266
+ carnetService.fotos("aprobada", clientesInternos.seleccionado),
267
+ carnetService.carnets(clientesInternos.seleccionado)
268
+ ]);
269
+ soltarImagenes();
270
+ for (const f of fotos.value) carnetService.imagen(f.id).then((b) => imagenes.value = {
271
+ ...imagenes.value,
272
+ [f.id]: URL.createObjectURL(b)
273
+ }).catch(() => void 0);
274
+ } catch (e) {
275
+ error.value = mensajeError(e, "No se pudo cargar el carnet digital.");
276
+ } finally {
277
+ cargando.value = false;
278
+ }
279
+ }
280
+ async function cambiarActivo(valor) {
281
+ ocupado.value = true;
282
+ error.value = null;
283
+ try {
284
+ activo.value = await carnetService.activar(valor);
285
+ } catch (e) {
286
+ error.value = mensajeError(e, "No se pudo guardar el cambio.");
287
+ } finally {
288
+ ocupado.value = false;
289
+ }
290
+ }
291
+ async function accion(fn, falla) {
292
+ ocupado.value = true;
293
+ error.value = null;
294
+ aviso.value = null;
295
+ try {
296
+ await fn();
297
+ rechazando.value = null;
298
+ await cargar();
299
+ } catch (e) {
300
+ error.value = mensajeError(e, falla);
301
+ } finally {
302
+ ocupado.value = false;
303
+ }
304
+ }
305
+ /** Cómo quedó el envío a SoftDIN, en palabras para RRHH. */
306
+ function contarEnvio(nombre, r, aprobada) {
307
+ const inicio = aprobada ? `Foto de ${nombre} aprobada` : `Foto de ${nombre}`;
308
+ aviso.value = r.sincronizacion === "sincronizada" ? `${inicio} y guardada en SoftDIN.` : r.sincronizacion === "pendiente" ? `${inicio}${aprobada ? "" : ":"} SoftDIN no respondió; se reintentará sola. Ya sale en el carnet.` : `${inicio}${aprobada ? "" : ":"} no se pudo guardar en SoftDIN${r.sincronizacion_error ? ` (${r.sincronizacion_error})` : ""}. Ya sale en el carnet; reinténtalo abajo.`;
309
+ }
310
+ const aprobar = (f) => accion(async () => contarEnvio(f.empleado, await carnetService.aprobar(f.id), true), "No se pudo aprobar la foto.");
311
+ const reintentar = (f) => accion(async () => contarEnvio(f.empleado, await carnetService.sincronizar(f.id), false), "No se pudo reintentar el envío.");
312
+ const estadoEnvio = {
313
+ sincronizada: {
314
+ texto: "Guardada en SoftDIN",
315
+ clase: "insignia-ok"
316
+ },
317
+ pendiente: {
318
+ texto: "Pendiente de enviar a SoftDIN (se reintenta sola)",
319
+ clase: "insignia-espera"
320
+ },
321
+ fallida: {
322
+ texto: "No se pudo guardar en SoftDIN",
323
+ clase: "insignia-error"
324
+ }
325
+ };
326
+ const rechazar = (f) => accion(() => carnetService.rechazar(f.id, (motivos.value[f.id] ?? "").trim()), "No se pudo rechazar la foto.");
327
+ function revocar(c) {
328
+ if (!window.confirm(`¿Revocar el carnet de ${c.empleado}? Deja de validar desde el siguiente escaneo.`)) return;
329
+ accion(() => carnetService.revocar(c.id), "No se pudo revocar el carnet.");
330
+ }
331
+ const fecha = (iso) => iso ? new Date(iso).toLocaleDateString("es-CO", {
332
+ day: "numeric",
333
+ month: "short",
334
+ year: "numeric"
335
+ }) : "—";
336
+ watch(() => clientesInternos.seleccionado, () => void cargar());
337
+ onMounted(() => void cargar());
338
+ onBeforeUnmount(soltarImagenes);
339
+ return (_ctx, _cache) => {
340
+ return openBlock(), createElementBlock("section", _hoisted_1, [
341
+ _cache[6] || (_cache[6] = createElementVNode("header", null, [createElementVNode("h1", { class: "page-title" }, "Carnet digital"), createElementVNode("p", { class: "page-subtitle" }, " El empleado muestra en su Portal de autogestión un carnet con su foto y un código QR que cambia cada 30 segundos. Quien lo escanea ve si es válido y la foto aprobada aquí. El retiro en SoftDIN lo invalida solo. ")], -1)),
342
+ error.value ? (openBlock(), createElementBlock("p", _hoisted_2, toDisplayString(error.value), 1)) : createCommentVNode("", true),
343
+ aviso.value ? (openBlock(), createElementBlock("p", _hoisted_3, toDisplayString(aviso.value), 1)) : createCommentVNode("", true),
344
+ cargando.value ? (openBlock(), createElementBlock("p", _hoisted_4, "Cargando…")) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
345
+ unref(clientesInternos).seleccionado === null ? (openBlock(), createElementBlock("div", _hoisted_5, [_cache[1] || (_cache[1] = createElementVNode("div", null, [createElementVNode("p", { class: "panel-title" }, "Carnet digital para los empleados de todo el tenant"), createElementVNode("p", { class: "panel-muted" }, "Apagado, los empleados no pueden enviar foto ni activar el carnet, y los ya activos no validan.")], -1)), createVNode(ToggleSwitch_default, {
346
+ "model-value": activo.value,
347
+ disabled: ocupado.value,
348
+ "onUpdate:modelValue": cambiarActivo
349
+ }, null, 8, ["model-value", "disabled"])])) : (openBlock(), createBlock(CarnetClientesInternos_default, {
350
+ key: 1,
351
+ "cliente-id": unref(clientesInternos).seleccionado,
352
+ "tenant-activo": activo.value
353
+ }, null, 8, ["cliente-id", "tenant-activo"])),
354
+ createElementVNode("div", _hoisted_6, [
355
+ createElementVNode("p", _hoisted_7, "Fotos por revisar (" + toDisplayString(fotos.value.length) + ")", 1),
356
+ _cache[3] || (_cache[3] = createElementVNode("p", { class: "nota" }, [
357
+ createTextVNode(" Aprobar una foto la deja también como la foto del empleado en SoftDIN: "),
358
+ createElementVNode("strong", null, "reemplaza la que tenga su tercero"),
359
+ createTextVNode(". Si el tercero ya tenía foto en SoftDIN, esa se usa en el carnet sin pedirle otra. ")
360
+ ], -1)),
361
+ !fotos.value.length ? (openBlock(), createElementBlock("p", _hoisted_8, "No hay fotos pendientes.")) : (openBlock(), createElementBlock("div", _hoisted_9, [(openBlock(true), createElementBlock(Fragment, null, renderList(fotos.value, (f) => {
362
+ return openBlock(), createElementBlock("article", {
363
+ key: f.id,
364
+ class: "foto"
365
+ }, [
366
+ imagenes.value[f.id] ? (openBlock(), createElementBlock("img", {
367
+ key: 0,
368
+ src: imagenes.value[f.id],
369
+ alt: `Foto de ${f.empleado}`
370
+ }, null, 8, _hoisted_10)) : (openBlock(), createElementBlock("div", _hoisted_11)),
371
+ createElementVNode("p", _hoisted_12, toDisplayString(f.empleado), 1),
372
+ createElementVNode("p", _hoisted_13, toDisplayString(f.cargo ?? "") + " · " + toDisplayString(fecha(f.enviada_en)), 1),
373
+ f.tiene_aprobada ? (openBlock(), createElementBlock("p", _hoisted_14, "Reemplaza la foto actual del carnet.")) : createCommentVNode("", true),
374
+ _cache[2] || (_cache[2] = createElementVNode("p", { class: "panel-muted" }, "Al aprobarla reemplaza la foto del tercero en SoftDIN.", -1)),
375
+ rechazando.value === f.id ? (openBlock(), createElementBlock(Fragment, { key: 3 }, [withDirectives(createElementVNode("input", {
376
+ "onUpdate:modelValue": ($event) => motivos.value[f.id] = $event,
377
+ class: "campo",
378
+ maxlength: "300",
379
+ placeholder: "Motivo (lo verá el empleado)",
380
+ "aria-label": "Motivo del rechazo"
381
+ }, null, 8, _hoisted_15), [[vModelText, motivos.value[f.id]]]), createElementVNode("div", _hoisted_16, [createElementVNode("button", {
382
+ type: "button",
383
+ class: "btn btn-peligro",
384
+ disabled: ocupado.value || !(motivos.value[f.id] ?? "").trim(),
385
+ onClick: ($event) => rechazar(f)
386
+ }, " Rechazar ", 8, _hoisted_17), createElementVNode("button", {
387
+ type: "button",
388
+ class: "btn",
389
+ disabled: ocupado.value,
390
+ onClick: _cache[0] || (_cache[0] = ($event) => rechazando.value = null)
391
+ }, "Cancelar", 8, _hoisted_18)])], 64)) : (openBlock(), createElementBlock("div", _hoisted_19, [createElementVNode("button", {
392
+ type: "button",
393
+ class: "btn btn-primario",
394
+ disabled: ocupado.value,
395
+ onClick: ($event) => aprobar(f)
396
+ }, "Aprobar", 8, _hoisted_20), createElementVNode("button", {
397
+ type: "button",
398
+ class: "btn",
399
+ disabled: ocupado.value,
400
+ onClick: ($event) => rechazando.value = f.id
401
+ }, "Rechazar…", 8, _hoisted_21)]))
402
+ ]);
403
+ }), 128))]))
404
+ ]),
405
+ createElementVNode("div", _hoisted_22, [createElementVNode("p", _hoisted_23, "Fotos aprobadas y su envío a SoftDIN (" + toDisplayString(aprobadas.value.length) + ")", 1), !aprobadas.value.length ? (openBlock(), createElementBlock("p", _hoisted_24, "Todavía no hay fotos aprobadas.")) : (openBlock(), createElementBlock("div", _hoisted_25, [createElementVNode("table", _hoisted_26, [_cache[4] || (_cache[4] = createElementVNode("thead", null, [createElementVNode("tr", null, [
406
+ createElementVNode("th", null, "Empleado"),
407
+ createElementVNode("th", null, "Cargo"),
408
+ createElementVNode("th", null, "En SoftDIN"),
409
+ createElementVNode("th")
410
+ ])], -1)), createElementVNode("tbody", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(aprobadas.value, (f) => {
411
+ return openBlock(), createElementBlock("tr", { key: f.id }, [
412
+ createElementVNode("td", null, toDisplayString(f.empleado), 1),
413
+ createElementVNode("td", null, toDisplayString(f.cargo ?? "—"), 1),
414
+ createElementVNode("td", null, [f.origen === "softdin" ? (openBlock(), createElementBlock("span", _hoisted_27, "Tomada de SoftDIN")) : f.sincronizacion && estadoEnvio[f.sincronizacion] ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createElementVNode("span", { class: normalizeClass(["insignia", estadoEnvio[f.sincronizacion].clase]) }, toDisplayString(estadoEnvio[f.sincronizacion].texto), 3), f.sincronizacion === "sincronizada" ? (openBlock(), createElementBlock("span", _hoisted_28, " · " + toDisplayString(fecha(f.sincronizada_en)), 1)) : f.sincronizacion_error ? (openBlock(), createElementBlock("p", _hoisted_29, toDisplayString(f.sincronizacion_intentos) + " intento(s). Último error: " + toDisplayString(f.sincronizacion_error), 1)) : createCommentVNode("", true)], 64)) : (openBlock(), createElementBlock("span", _hoisted_30, "—"))]),
415
+ createElementVNode("td", null, [f.origen === "portal" && (f.sincronizacion === "fallida" || f.sincronizacion === "pendiente") ? (openBlock(), createElementBlock("button", {
416
+ key: 0,
417
+ type: "button",
418
+ class: "btn",
419
+ disabled: ocupado.value,
420
+ onClick: ($event) => reintentar(f)
421
+ }, " Reintentar ahora ", 8, _hoisted_31)) : createCommentVNode("", true)])
422
+ ]);
423
+ }), 128))])])]))]),
424
+ createElementVNode("div", _hoisted_32, [createElementVNode("p", _hoisted_33, "Carnets activos (" + toDisplayString(carnets.value.length) + ")", 1), !carnets.value.length ? (openBlock(), createElementBlock("p", _hoisted_34, "Ningún empleado ha activado el carnet todavía.")) : (openBlock(), createElementBlock("div", _hoisted_35, [createElementVNode("table", _hoisted_36, [_cache[5] || (_cache[5] = createElementVNode("thead", null, [createElementVNode("tr", null, [
425
+ createElementVNode("th", null, "Empleado"),
426
+ createElementVNode("th", null, "Cargo"),
427
+ createElementVNode("th", null, "Activado"),
428
+ createElementVNode("th", null, "Vence"),
429
+ createElementVNode("th")
430
+ ])], -1)), createElementVNode("tbody", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(carnets.value, (c) => {
431
+ return openBlock(), createElementBlock("tr", { key: c.id }, [
432
+ createElementVNode("td", null, toDisplayString(c.empleado), 1),
433
+ createElementVNode("td", null, toDisplayString(c.cargo ?? "—"), 1),
434
+ createElementVNode("td", null, toDisplayString(fecha(c.emitido_en)), 1),
435
+ createElementVNode("td", null, toDisplayString(fecha(c.vence_en)), 1),
436
+ createElementVNode("td", null, [createElementVNode("button", {
437
+ type: "button",
438
+ class: "btn btn-peligro",
439
+ disabled: ocupado.value,
440
+ onClick: ($event) => revocar(c)
441
+ }, "Revocar", 8, _hoisted_37)])
442
+ ]);
443
+ }), 128))])])]))])
444
+ ], 64))
445
+ ]);
446
+ };
447
+ }
448
+ }), [["__scopeId", "data-v-4e70ef58"]]);
449
+ //#endregion
450
+ export { CarnetView_default as default };