@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,549 @@
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 { o as fechaCorta } from "./portal-empleado-6KQrnsQJ.js";
6
+ import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, normalizeClass, onMounted, openBlock, ref, renderList, toDisplayString, unref, useModel, vModelSelect, vModelText, watch, withDirectives, withModifiers } from "vue";
7
+ import FormCloseButton from "@softdin/shared/components/forms/FormCloseButton.vue";
8
+ //#region src/services/solicitudes-certificado.service.ts
9
+ var TIPOS_CERTIFICADO = {
10
+ laboral: "Laboral",
11
+ ingresos_retenciones: "Ingresos y retenciones",
12
+ otro: "Otro"
13
+ };
14
+ var ESTADOS_SOLICITUD_CERTIFICADO = {
15
+ pendiente: {
16
+ texto: "Pendiente",
17
+ clase: "estado-espera"
18
+ },
19
+ atendida: {
20
+ texto: "Atendida",
21
+ clase: "estado-ok"
22
+ },
23
+ rechazada: {
24
+ texto: "Rechazada",
25
+ clase: "estado-error"
26
+ }
27
+ };
28
+ var MULTIPART = { headers: { "Content-Type": "multipart/form-data" } };
29
+ var solicitudesCertificadoService = {
30
+ async listar(filtros = {}) {
31
+ const params = {};
32
+ if (filtros.estado) params.estado = filtros.estado;
33
+ if (filtros.cliente_interno_id !== void 0 && filtros.cliente_interno_id !== null) params.cliente_interno_id = filtros.cliente_interno_id;
34
+ const { data } = await api.get("/solicitudes-certificado", { params });
35
+ return data.data;
36
+ },
37
+ /**
38
+ * Guarda el PDF en SoftDIN y marca la solicitud atendida. Si SoftDIN no responde, el
39
+ * portal contesta 503 con el mensaje y la solicitud sigue pendiente.
40
+ */
41
+ async atender(id, datos) {
42
+ const f = new FormData();
43
+ f.append("pdf", datos.pdf);
44
+ const titulo = datos.titulo?.trim();
45
+ if (titulo) f.append("titulo", titulo);
46
+ const respuesta = datos.respuesta?.trim();
47
+ if (respuesta) f.append("respuesta", respuesta);
48
+ await api.post(`/solicitudes-certificado/${id}/atender`, f, MULTIPART);
49
+ },
50
+ /** `respuesta` es el motivo que verá el empleado (5 a 1000 caracteres). */
51
+ async rechazar(id, respuesta) {
52
+ await api.post(`/solicitudes-certificado/${id}/rechazar`, { respuesta: respuesta.trim() });
53
+ }
54
+ };
55
+ //#endregion
56
+ //#region src/components/certificados/ResumenSolicitudCertificado.vue?vue&type=script&setup=true&lang.ts
57
+ var _hoisted_1$3 = { class: "resumen" };
58
+ var _hoisted_2$3 = { key: 0 };
59
+ var _hoisted_3$3 = { class: "informacion" };
60
+ //#endregion
61
+ //#region src/components/certificados/ResumenSolicitudCertificado.vue
62
+ var ResumenSolicitudCertificado_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
63
+ __name: "ResumenSolicitudCertificado",
64
+ props: { solicitud: {} },
65
+ setup(__props) {
66
+ return (_ctx, _cache) => {
67
+ return openBlock(), createElementBlock("dl", _hoisted_1$3, [
68
+ createElementVNode("div", null, [_cache[0] || (_cache[0] = createElementVNode("dt", null, "Empleado", -1)), createElementVNode("dd", null, [createTextVNode(toDisplayString(__props.solicitud.empleado.nombre ?? "—"), 1), __props.solicitud.empleado.documento ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" · " + toDisplayString(__props.solicitud.empleado.documento), 1)], 64)) : createCommentVNode("", true)])]),
69
+ __props.solicitud.cliente_interno ? (openBlock(), createElementBlock("div", _hoisted_2$3, [_cache[1] || (_cache[1] = createElementVNode("dt", null, "Cliente", -1)), createElementVNode("dd", null, toDisplayString(__props.solicitud.cliente_interno.nombre), 1)])) : createCommentVNode("", true),
70
+ createElementVNode("div", null, [_cache[2] || (_cache[2] = createElementVNode("dt", null, "Certificado", -1)), createElementVNode("dd", null, [createTextVNode(toDisplayString(unref(TIPOS_CERTIFICADO)[__props.solicitud.tipo] ?? __props.solicitud.tipo), 1), __props.solicitud.anio ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" · año " + toDisplayString(__props.solicitud.anio), 1)], 64)) : createCommentVNode("", true)])]),
71
+ createElementVNode("div", null, [_cache[3] || (_cache[3] = createElementVNode("dt", null, "Solicitada", -1)), createElementVNode("dd", null, toDisplayString(unref(fechaCorta)(__props.solicitud.creada_en)), 1)]),
72
+ createElementVNode("div", null, [_cache[4] || (_cache[4] = createElementVNode("dt", null, "Información", -1)), createElementVNode("dd", _hoisted_3$3, toDisplayString(__props.solicitud.informacion), 1)])
73
+ ]);
74
+ };
75
+ }
76
+ }), [["__scopeId", "data-v-ce40d24f"]]);
77
+ //#endregion
78
+ //#region src/components/certificados/AtenderCertificadoModal.vue?vue&type=script&setup=true&lang.ts
79
+ var _hoisted_1$2 = {
80
+ key: 0,
81
+ class: "modal-backdrop"
82
+ };
83
+ var _hoisted_2$2 = {
84
+ class: "modal-panel",
85
+ role: "dialog",
86
+ "aria-modal": "true",
87
+ "aria-labelledby": "atender-certificado-titulo"
88
+ };
89
+ var _hoisted_3$2 = { class: "modal-header" };
90
+ var _hoisted_4$2 = ["disabled"];
91
+ var _hoisted_5$2 = ["disabled"];
92
+ var _hoisted_6$2 = ["disabled"];
93
+ var _hoisted_7$2 = {
94
+ key: 0,
95
+ class: "alert-error",
96
+ role: "alert"
97
+ };
98
+ var _hoisted_8$2 = { class: "modal-footer" };
99
+ var _hoisted_9$1 = ["disabled"];
100
+ var _hoisted_10$1 = ["disabled"];
101
+ //#endregion
102
+ //#region src/components/certificados/AtenderCertificadoModal.vue
103
+ var AtenderCertificadoModal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
104
+ __name: "AtenderCertificadoModal",
105
+ props: /*@__PURE__*/ mergeModels({ solicitud: {} }, {
106
+ "open": {
107
+ type: Boolean,
108
+ required: true
109
+ },
110
+ "openModifiers": {}
111
+ }),
112
+ emits: /*@__PURE__*/ mergeModels(["atendida"], ["update:open"]),
113
+ setup(__props, { emit: __emit }) {
114
+ const props = __props;
115
+ const open = useModel(__props, "open");
116
+ const emit = __emit;
117
+ const archivo = ref(null);
118
+ const titulo = ref("");
119
+ const respuesta = ref("");
120
+ const enviando = ref(false);
121
+ const error = ref(null);
122
+ const entrada = ref(null);
123
+ watch(open, (abierto) => {
124
+ if (abierto) {
125
+ archivo.value = null;
126
+ titulo.value = "";
127
+ respuesta.value = "";
128
+ error.value = null;
129
+ if (entrada.value) entrada.value.value = "";
130
+ }
131
+ });
132
+ function elegir(e) {
133
+ const f = e.target.files?.[0] ?? null;
134
+ archivo.value = f;
135
+ error.value = null;
136
+ }
137
+ function validar() {
138
+ const f = archivo.value;
139
+ if (!f) return "Adjunte el certificado en PDF.";
140
+ if (!(f.type === "application/pdf" || f.name.toLowerCase().endsWith(".pdf"))) return "El archivo debe ser un PDF.";
141
+ if (f.size > 5242880) return "El PDF no puede pasar de 5 MB.";
142
+ return null;
143
+ }
144
+ async function atender() {
145
+ if (!props.solicitud || enviando.value) return;
146
+ error.value = validar();
147
+ if (error.value || !archivo.value) return;
148
+ enviando.value = true;
149
+ try {
150
+ await solicitudesCertificadoService.atender(props.solicitud.id, {
151
+ pdf: archivo.value,
152
+ titulo: titulo.value,
153
+ respuesta: respuesta.value
154
+ });
155
+ emit("atendida");
156
+ open.value = false;
157
+ } catch (e) {
158
+ error.value = mensajeError(e, "No se pudo atender la solicitud.");
159
+ } finally {
160
+ enviando.value = false;
161
+ }
162
+ }
163
+ return (_ctx, _cache) => {
164
+ return openBlock(), createBlock(Teleport, { to: "body" }, [open.value && __props.solicitud ? (openBlock(), createElementBlock("div", _hoisted_1$2, [createElementVNode("div", _hoisted_2$2, [createElementVNode("header", _hoisted_3$2, [_cache[4] || (_cache[4] = createElementVNode("h2", {
165
+ id: "atender-certificado-titulo",
166
+ class: "modal-title"
167
+ }, "Atender solicitud de certificado", -1)), createVNode(FormCloseButton, {
168
+ disabled: enviando.value,
169
+ onClick: _cache[0] || (_cache[0] = ($event) => open.value = false)
170
+ }, null, 8, ["disabled"])]), createElementVNode("form", {
171
+ class: "modal-body",
172
+ novalidate: "",
173
+ onSubmit: withModifiers(atender, ["prevent"])
174
+ }, [
175
+ createVNode(ResumenSolicitudCertificado_default, { solicitud: __props.solicitud }, null, 8, ["solicitud"]),
176
+ createElementVNode("div", null, [
177
+ _cache[5] || (_cache[5] = createElementVNode("label", {
178
+ for: "atender-certificado-pdf",
179
+ class: "label"
180
+ }, "Certificado en PDF", -1)),
181
+ createElementVNode("input", {
182
+ id: "atender-certificado-pdf",
183
+ ref_key: "entrada",
184
+ ref: entrada,
185
+ type: "file",
186
+ accept: "application/pdf,.pdf",
187
+ class: "input",
188
+ required: "",
189
+ "aria-describedby": "atender-certificado-pdf-ayuda",
190
+ disabled: enviando.value,
191
+ onChange: elegir
192
+ }, null, 40, _hoisted_4$2),
193
+ _cache[6] || (_cache[6] = createElementVNode("p", {
194
+ id: "atender-certificado-pdf-ayuda",
195
+ class: "ayuda"
196
+ }, "Máximo 5 MB. El empleado lo verá en «Documentos» de su app.", -1))
197
+ ]),
198
+ createElementVNode("div", null, [_cache[7] || (_cache[7] = createElementVNode("label", {
199
+ for: "atender-certificado-nombre",
200
+ class: "label"
201
+ }, "Título (opcional)", -1)), withDirectives(createElementVNode("input", {
202
+ id: "atender-certificado-nombre",
203
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => titulo.value = $event),
204
+ type: "text",
205
+ class: "input",
206
+ maxlength: "150",
207
+ placeholder: "Ej.: Certificado laboral con salario",
208
+ disabled: enviando.value
209
+ }, null, 8, _hoisted_5$2), [[vModelText, titulo.value]])]),
210
+ createElementVNode("div", null, [_cache[8] || (_cache[8] = createElementVNode("label", {
211
+ for: "atender-certificado-respuesta",
212
+ class: "label"
213
+ }, "Respuesta para el empleado (opcional)", -1)), withDirectives(createElementVNode("textarea", {
214
+ id: "atender-certificado-respuesta",
215
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => respuesta.value = $event),
216
+ class: "input",
217
+ rows: "3",
218
+ maxlength: "1000",
219
+ disabled: enviando.value
220
+ }, null, 8, _hoisted_6$2), [[vModelText, respuesta.value]])]),
221
+ error.value ? (openBlock(), createElementBlock("p", _hoisted_7$2, toDisplayString(error.value), 1)) : createCommentVNode("", true),
222
+ createElementVNode("footer", _hoisted_8$2, [createElementVNode("button", {
223
+ type: "button",
224
+ class: "btn-secondary",
225
+ disabled: enviando.value,
226
+ onClick: _cache[3] || (_cache[3] = ($event) => open.value = false)
227
+ }, "Cancelar", 8, _hoisted_9$1), createElementVNode("button", {
228
+ type: "submit",
229
+ class: "btn-primary",
230
+ disabled: enviando.value
231
+ }, toDisplayString(enviando.value ? "Enviando…" : "Entregar certificado"), 9, _hoisted_10$1)])
232
+ ], 32)])])) : createCommentVNode("", true)]);
233
+ };
234
+ }
235
+ }), [["__scopeId", "data-v-96ef0086"]]);
236
+ //#endregion
237
+ //#region src/components/certificados/RechazarCertificadoModal.vue?vue&type=script&setup=true&lang.ts
238
+ var _hoisted_1$1 = {
239
+ key: 0,
240
+ class: "modal-backdrop"
241
+ };
242
+ var _hoisted_2$1 = {
243
+ class: "modal-panel",
244
+ role: "dialog",
245
+ "aria-modal": "true",
246
+ "aria-labelledby": "rechazar-certificado-titulo"
247
+ };
248
+ var _hoisted_3$1 = { class: "modal-header" };
249
+ var _hoisted_4$1 = ["disabled"];
250
+ var _hoisted_5$1 = {
251
+ key: 0,
252
+ class: "alert-error",
253
+ role: "alert"
254
+ };
255
+ var _hoisted_6$1 = { class: "modal-footer" };
256
+ var _hoisted_7$1 = ["disabled"];
257
+ var _hoisted_8$1 = ["disabled"];
258
+ //#endregion
259
+ //#region src/components/certificados/RechazarCertificadoModal.vue
260
+ var RechazarCertificadoModal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
261
+ __name: "RechazarCertificadoModal",
262
+ props: /*@__PURE__*/ mergeModels({ solicitud: {} }, {
263
+ "open": {
264
+ type: Boolean,
265
+ required: true
266
+ },
267
+ "openModifiers": {}
268
+ }),
269
+ emits: /*@__PURE__*/ mergeModels(["rechazada"], ["update:open"]),
270
+ setup(__props, { emit: __emit }) {
271
+ const props = __props;
272
+ const open = useModel(__props, "open");
273
+ const emit = __emit;
274
+ const motivo = ref("");
275
+ const enviando = ref(false);
276
+ const error = ref(null);
277
+ watch(open, (abierto) => {
278
+ if (abierto) {
279
+ motivo.value = "";
280
+ error.value = null;
281
+ }
282
+ });
283
+ async function rechazar() {
284
+ if (!props.solicitud || enviando.value) return;
285
+ error.value = null;
286
+ if (motivo.value.trim().length < 5) {
287
+ error.value = "Escriba el motivo (mínimo 5 caracteres): el empleado lo verá en su app.";
288
+ return;
289
+ }
290
+ enviando.value = true;
291
+ try {
292
+ await solicitudesCertificadoService.rechazar(props.solicitud.id, motivo.value);
293
+ emit("rechazada");
294
+ open.value = false;
295
+ } catch (e) {
296
+ error.value = mensajeError(e, "No se pudo rechazar la solicitud.");
297
+ } finally {
298
+ enviando.value = false;
299
+ }
300
+ }
301
+ return (_ctx, _cache) => {
302
+ return openBlock(), createBlock(Teleport, { to: "body" }, [open.value && __props.solicitud ? (openBlock(), createElementBlock("div", _hoisted_1$1, [createElementVNode("div", _hoisted_2$1, [createElementVNode("header", _hoisted_3$1, [_cache[3] || (_cache[3] = createElementVNode("h2", {
303
+ id: "rechazar-certificado-titulo",
304
+ class: "modal-title"
305
+ }, "Rechazar solicitud de certificado", -1)), createVNode(FormCloseButton, {
306
+ disabled: enviando.value,
307
+ onClick: _cache[0] || (_cache[0] = ($event) => open.value = false)
308
+ }, null, 8, ["disabled"])]), createElementVNode("form", {
309
+ class: "modal-body",
310
+ novalidate: "",
311
+ onSubmit: withModifiers(rechazar, ["prevent"])
312
+ }, [
313
+ createVNode(ResumenSolicitudCertificado_default, { solicitud: __props.solicitud }, null, 8, ["solicitud"]),
314
+ createElementVNode("div", null, [
315
+ _cache[4] || (_cache[4] = createElementVNode("label", {
316
+ for: "rechazar-certificado-motivo",
317
+ class: "label"
318
+ }, "Motivo", -1)),
319
+ withDirectives(createElementVNode("textarea", {
320
+ id: "rechazar-certificado-motivo",
321
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => motivo.value = $event),
322
+ class: "input",
323
+ rows: "3",
324
+ minlength: "5",
325
+ maxlength: "1000",
326
+ required: "",
327
+ "aria-describedby": "rechazar-certificado-ayuda",
328
+ disabled: enviando.value
329
+ }, null, 8, _hoisted_4$1), [[vModelText, motivo.value]]),
330
+ _cache[5] || (_cache[5] = createElementVNode("p", {
331
+ id: "rechazar-certificado-ayuda",
332
+ class: "ayuda"
333
+ }, "Obligatorio: el empleado lo verá como respuesta.", -1))
334
+ ]),
335
+ error.value ? (openBlock(), createElementBlock("p", _hoisted_5$1, toDisplayString(error.value), 1)) : createCommentVNode("", true),
336
+ createElementVNode("footer", _hoisted_6$1, [createElementVNode("button", {
337
+ type: "button",
338
+ class: "btn-secondary",
339
+ disabled: enviando.value,
340
+ onClick: _cache[2] || (_cache[2] = ($event) => open.value = false)
341
+ }, "Cancelar", 8, _hoisted_7$1), createElementVNode("button", {
342
+ type: "submit",
343
+ class: "btn-danger",
344
+ disabled: enviando.value
345
+ }, toDisplayString(enviando.value ? "Guardando…" : "Rechazar"), 9, _hoisted_8$1)])
346
+ ], 32)])])) : createCommentVNode("", true)]);
347
+ };
348
+ }
349
+ }), [["__scopeId", "data-v-bf8d5555"]]);
350
+ //#endregion
351
+ //#region src/views/CertificadosView.vue?vue&type=script&setup=true&lang.ts
352
+ var _hoisted_1 = { class: "page-shell" };
353
+ var _hoisted_2 = { class: "toolbar" };
354
+ var _hoisted_3 = ["disabled"];
355
+ var _hoisted_4 = ["value"];
356
+ var _hoisted_5 = ["disabled"];
357
+ var _hoisted_6 = {
358
+ key: 0,
359
+ class: "panel-error",
360
+ role: "alert"
361
+ };
362
+ var _hoisted_7 = {
363
+ key: 1,
364
+ class: "panel-muted",
365
+ role: "status"
366
+ };
367
+ var _hoisted_8 = {
368
+ key: 2,
369
+ class: "panel-muted"
370
+ };
371
+ var _hoisted_9 = {
372
+ key: 3,
373
+ class: "table-wrap"
374
+ };
375
+ var _hoisted_10 = { class: "data-table table-cards" };
376
+ var _hoisted_11 = {
377
+ class: "cell-primary",
378
+ "data-label": "Empleado"
379
+ };
380
+ var _hoisted_12 = {
381
+ key: 0,
382
+ class: "sub"
383
+ };
384
+ var _hoisted_13 = { "data-label": "Cliente" };
385
+ var _hoisted_14 = { "data-label": "Certificado" };
386
+ var _hoisted_15 = { "data-label": "Año" };
387
+ var _hoisted_16 = {
388
+ class: "informacion",
389
+ "data-label": "Información"
390
+ };
391
+ var _hoisted_17 = { "data-label": "Solicitada" };
392
+ var _hoisted_18 = { "data-label": "Estado" };
393
+ var _hoisted_19 = {
394
+ key: 0,
395
+ class: "sub"
396
+ };
397
+ var _hoisted_20 = {
398
+ key: 1,
399
+ class: "sub"
400
+ };
401
+ var _hoisted_21 = {
402
+ class: "actions-cell",
403
+ "data-label": "Acciones"
404
+ };
405
+ var _hoisted_22 = {
406
+ key: 0,
407
+ class: "acciones"
408
+ };
409
+ var _hoisted_23 = ["aria-label", "onClick"];
410
+ var _hoisted_24 = ["aria-label", "onClick"];
411
+ //#endregion
412
+ //#region src/views/CertificadosView.vue
413
+ var CertificadosView_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
414
+ __name: "CertificadosView",
415
+ setup(__props) {
416
+ const clientesInternos = useClienteInternoStore();
417
+ const estado = ref("pendiente");
418
+ const items = ref([]);
419
+ const loading = ref(false);
420
+ const error = ref(null);
421
+ const seleccionada = ref(null);
422
+ const atenderOpen = ref(false);
423
+ const rechazarOpen = ref(false);
424
+ const filtros = [
425
+ {
426
+ valor: "pendiente",
427
+ texto: "Pendientes"
428
+ },
429
+ {
430
+ valor: "atendida",
431
+ texto: "Atendidas"
432
+ },
433
+ {
434
+ valor: "rechazada",
435
+ texto: "Rechazadas"
436
+ },
437
+ {
438
+ valor: "",
439
+ texto: "Todas"
440
+ }
441
+ ];
442
+ const textoVacio = computed(() => estado.value === "pendiente" ? "No hay solicitudes de certificado por atender." : "No hay solicitudes de certificado con este estado.");
443
+ async function cargar() {
444
+ loading.value = true;
445
+ error.value = null;
446
+ try {
447
+ items.value = await solicitudesCertificadoService.listar({
448
+ estado: estado.value || void 0,
449
+ cliente_interno_id: clientesInternos.seleccionado
450
+ });
451
+ } catch (e) {
452
+ error.value = mensajeError(e, "No se pudieron cargar las solicitudes de certificado.");
453
+ } finally {
454
+ loading.value = false;
455
+ }
456
+ }
457
+ function abrirAtender(s) {
458
+ seleccionada.value = s;
459
+ atenderOpen.value = true;
460
+ }
461
+ function abrirRechazar(s) {
462
+ seleccionada.value = s;
463
+ rechazarOpen.value = true;
464
+ }
465
+ watch([estado, () => clientesInternos.seleccionado], () => void cargar());
466
+ onMounted(() => void cargar());
467
+ return (_ctx, _cache) => {
468
+ return openBlock(), createElementBlock("section", _hoisted_1, [
469
+ _cache[6] || (_cache[6] = createElementVNode("header", { class: "page-header" }, [createElementVNode("div", null, [createElementVNode("h1", { class: "page-title" }, "Solicitudes de certificado"), createElementVNode("p", { class: "page-subtitle descripcion-en-ayuda" }, " Certificados que los empleados pidieron desde su Portal de autogestión porque no se pudieron generar solos o necesitan uno distinto. Atiéndalos adjuntando el PDF (el empleado lo verá en «Documentos» de su app) o rechácelos indicando el motivo. ")])], -1)),
470
+ createElementVNode("div", _hoisted_2, [
471
+ _cache[3] || (_cache[3] = createElementVNode("label", {
472
+ for: "certificados-estado",
473
+ class: "label"
474
+ }, "Estado", -1)),
475
+ withDirectives(createElementVNode("select", {
476
+ id: "certificados-estado",
477
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => estado.value = $event),
478
+ class: "input",
479
+ disabled: loading.value
480
+ }, [(openBlock(), createElementBlock(Fragment, null, renderList(filtros, (f) => {
481
+ return createElementVNode("option", {
482
+ key: f.valor,
483
+ value: f.valor
484
+ }, toDisplayString(f.texto), 9, _hoisted_4);
485
+ }), 64))], 8, _hoisted_3), [[vModelSelect, estado.value]]),
486
+ createElementVNode("button", {
487
+ type: "button",
488
+ class: "btn-secondary",
489
+ disabled: loading.value,
490
+ onClick: cargar
491
+ }, "Actualizar", 8, _hoisted_5)
492
+ ]),
493
+ error.value ? (openBlock(), createElementBlock("p", _hoisted_6, toDisplayString(error.value), 1)) : loading.value ? (openBlock(), createElementBlock("p", _hoisted_7, "Cargando…")) : items.value.length === 0 ? (openBlock(), createElementBlock("p", _hoisted_8, toDisplayString(textoVacio.value), 1)) : (openBlock(), createElementBlock("div", _hoisted_9, [createElementVNode("table", _hoisted_10, [
494
+ _cache[4] || (_cache[4] = createElementVNode("caption", { class: "sr-only" }, "Solicitudes de certificado", -1)),
495
+ _cache[5] || (_cache[5] = createElementVNode("thead", null, [createElementVNode("tr", null, [
496
+ createElementVNode("th", { scope: "col" }, "Empleado"),
497
+ createElementVNode("th", { scope: "col" }, "Cliente"),
498
+ createElementVNode("th", { scope: "col" }, "Certificado"),
499
+ createElementVNode("th", { scope: "col" }, "Año"),
500
+ createElementVNode("th", { scope: "col" }, "Información"),
501
+ createElementVNode("th", { scope: "col" }, "Solicitada"),
502
+ createElementVNode("th", { scope: "col" }, "Estado"),
503
+ createElementVNode("th", { scope: "col" }, [createElementVNode("span", { class: "sr-only" }, "Acciones")])
504
+ ])], -1)),
505
+ createElementVNode("tbody", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (s) => {
506
+ return openBlock(), createElementBlock("tr", { key: s.id }, [
507
+ createElementVNode("td", _hoisted_11, [createTextVNode(toDisplayString(s.empleado.nombre ?? "—") + " ", 1), s.empleado.documento ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(s.empleado.documento), 1)) : createCommentVNode("", true)]),
508
+ createElementVNode("td", _hoisted_13, toDisplayString(s.cliente_interno?.nombre ?? "—"), 1),
509
+ createElementVNode("td", _hoisted_14, toDisplayString(unref(TIPOS_CERTIFICADO)[s.tipo] ?? s.tipo), 1),
510
+ createElementVNode("td", _hoisted_15, toDisplayString(s.anio ?? "—"), 1),
511
+ createElementVNode("td", _hoisted_16, toDisplayString(s.informacion), 1),
512
+ createElementVNode("td", _hoisted_17, toDisplayString(unref(fechaCorta)(s.creada_en)), 1),
513
+ createElementVNode("td", _hoisted_18, [
514
+ createElementVNode("span", { class: normalizeClass(["estado", unref(ESTADOS_SOLICITUD_CERTIFICADO)[s.estado]?.clase]) }, toDisplayString(unref(ESTADOS_SOLICITUD_CERTIFICADO)[s.estado]?.texto ?? s.estado), 3),
515
+ s.atendida_en ? (openBlock(), createElementBlock("span", _hoisted_19, toDisplayString(unref(fechaCorta)(s.atendida_en)), 1)) : createCommentVNode("", true),
516
+ s.respuesta ? (openBlock(), createElementBlock("span", _hoisted_20, "«" + toDisplayString(s.respuesta) + "»", 1)) : createCommentVNode("", true)
517
+ ]),
518
+ createElementVNode("td", _hoisted_21, [s.estado === "pendiente" ? (openBlock(), createElementBlock("div", _hoisted_22, [createElementVNode("button", {
519
+ type: "button",
520
+ class: "btn-primary",
521
+ "aria-label": `Atender la solicitud de ${s.empleado.nombre ?? "el empleado"}`,
522
+ onClick: ($event) => abrirAtender(s)
523
+ }, " Atender ", 8, _hoisted_23), createElementVNode("button", {
524
+ type: "button",
525
+ class: "btn-danger-outline",
526
+ "aria-label": `Rechazar la solicitud de ${s.empleado.nombre ?? "el empleado"}`,
527
+ onClick: ($event) => abrirRechazar(s)
528
+ }, " Rechazar ", 8, _hoisted_24)])) : createCommentVNode("", true)])
529
+ ]);
530
+ }), 128))])
531
+ ])])),
532
+ createVNode(AtenderCertificadoModal_default, {
533
+ open: atenderOpen.value,
534
+ "onUpdate:open": _cache[1] || (_cache[1] = ($event) => atenderOpen.value = $event),
535
+ solicitud: seleccionada.value,
536
+ onAtendida: cargar
537
+ }, null, 8, ["open", "solicitud"]),
538
+ createVNode(RechazarCertificadoModal_default, {
539
+ open: rechazarOpen.value,
540
+ "onUpdate:open": _cache[2] || (_cache[2] = ($event) => rechazarOpen.value = $event),
541
+ solicitud: seleccionada.value,
542
+ onRechazada: cargar
543
+ }, null, 8, ["open", "solicitud"])
544
+ ]);
545
+ };
546
+ }
547
+ }), [["__scopeId", "data-v-89abf74f"]]);
548
+ //#endregion
549
+ export { CertificadosView_default as default };