ultimo_cambio

main
Elmer Yujra Condori 2 months ago
parent eb62405353
commit f400639c86

@ -340,4 +340,78 @@ public function obtenerAvanceProcesoPostulante(Request $request, $idProceso)
} }
} }
public function miObservacion(Request $request)
{
$postulante = $request->user();
if (!$postulante) {
return response()->json([
'success' => false,
'message' => 'No autenticado'
], 401);
}
$dni = trim($postulante->dni);
if (!$dni) {
return response()->json([
'success' => false,
'message' => 'El postulante no tiene DNI registrado'
], 422);
}
$url = "https://test-admision.unap.edu.pe/service_observados/api/v1/observaciones/dni/{$dni}";
try {
$response = Http::timeout(15)->get($url);
if (!$response->successful()) {
return response()->json([
'success' => false,
'message' => 'No se pudo consultar observaciones',
'status_http' => $response->status(),
], 502);
}
$payload = $response->json();
// si no viene, asumimos false
$esObservado = (bool)($payload['es_observado'] ?? false);
// opcional: traer una observación "principal"
$detalle = null;
if (!empty($payload['observados']) && is_array($payload['observados'])) {
$o = $payload['observados'][0];
$detalle = [
'tipo_observacion' => $o['tipo_observacion'] ?? null,
'categoria' => $o['categoria'] ?? null,
'observaciones' => $o['observaciones'] ?? null,
'fecha_sancion' => $o['fecha_sancion'] ?? null,
'fecha_fin' => $o['fecha_fin'] ?? null,
];
}
return response()->json([
'success' => true,
'dni' => $dni,
'es_observado' => $esObservado,
'mensaje' => $esObservado
? 'Usted tiene una observación. Acérquese a la Dirección de Admisión para regularizar su situación.'
: 'Usted está apto para postular en este proceso.',
'detalle' => $detalle, // si no lo quieres, bórralo
]);
} catch (\Throwable $e) {
Log::error('Error consultando observaciones del postulante', [
'dni' => $dni,
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Error interno consultando observaciones'
], 500);
}
}
} }

@ -226,4 +226,6 @@ Route::middleware('auth:sanctum')->prefix('admin')->group(function () {
Route::delete('/comunicados/{id}', [ComunicadoController::class, 'destroy']); Route::delete('/comunicados/{id}', [ComunicadoController::class, 'destroy']);
Route::patch('/comunicados/{id}/toggle-activo', [ComunicadoController::class, 'toggleActivo']); Route::patch('/comunicados/{id}/toggle-activo', [ComunicadoController::class, 'toggleActivo']);
Route::delete('/comunicados/imagenes/{imagenId}', [ComunicadoController::class, 'destroyImagen']); Route::delete('/comunicados/imagenes/{imagenId}', [ComunicadoController::class, 'destroyImagen']);
}); });
Route::middleware('auth:sanctum')->get('/postulante/observacion', [PostulanteAuthController::class, 'miObservacion']);

@ -112,6 +112,25 @@ export const useAuthStore = defineStore('auth', () => {
return false return false
} }
const getObservacion = async () => {
try {
loading.value = true
error.value = null
const response = await api.get('/postulante/observacion', {
headers: { Authorization: `Bearer ${token.value}` }
})
return response.data
} catch (err) {
error.value = err.response?.data?.message || 'Error consultando observación'
return { success: false, message: error.value }
} finally {
loading.value = false
}
}
return { return {
token, token,
@ -128,6 +147,7 @@ export const useAuthStore = defineStore('auth', () => {
register, register,
login, login,
logout, logout,
checkAuth checkAuth,
getObservacion,
} }
}) })

@ -6,7 +6,7 @@
<div class="header"> <div class="header">
<div class="headerLeft"> <div class="headerLeft">
<div class="subtitle"> <div class="subtitle">
Proceso 31: <b>Examen General 2026-I</b> Proceso: <b>Examen General 2026-I</b>
</div> </div>
</div> </div>
@ -124,13 +124,24 @@ const normalizar = (txt) =>
const indicador = computed(() => { const indicador = computed(() => {
const st = normalizar(avance.value?.estado); const st = normalizar(avance.value?.estado);
if (!st) return "Sigue revisando esta sección para ver el siguiente paso."; if (!st) return "Sigue revisando esta sección para ver el siguiente paso.";
if (st.includes("preins")) if (st.includes("preins")) {
return "Ya realizaste la preinscripción. Por ahora, espera que el sistema habilite el siguiente paso."; return "Ya realizaste la preinscripción. Por ahora, espera que el sistema habilite el siguiente paso.";
if (st.includes("inscrip")) }
return "Estás en inscripción final. Completa lo solicitado para generar tu constancia.";
return "Por ahora, espera que el sistema habilite el siguiente paso."; // Registro + foto + huella (1 solo paso)
if (st.includes("registro") || st.includes("huella") || st.includes("foto") || st.includes("biometr")) {
return "Estás en inscripción final (registro, foto y huella). Completa lo solicitado para obtener tu constancia.";
}
// Constancia generada -> recién aquí mostrar examen
if (st.includes("constancia")) {
return "Ya generaste tu constancia. Prepárate para rendir el examen el 14 de febrero. Debes estar antes de las 9:30 a. m.; un minuto tarde y no podrás ingresar.";
}
return "Sigue revisando esta sección para ver el siguiente paso.";
}); });
onMounted(() => { onMounted(() => {

@ -8,6 +8,24 @@
<div class="hello">Bienvenido, {{ authStore.userName }}</div> <div class="hello">Bienvenido, {{ authStore.userName }}</div>
<div class="sub">DNI: {{ authStore.userDni || "No registrado" }}</div> <div class="sub">DNI: {{ authStore.userDni || "No registrado" }}</div>
</div> </div>
<!-- Estado observado (DERECHA) -->
<div class="topbarRight" v-if="esObservado !== null">
<div
class="statusPill"
:class="esObservado ? 'statusBad' : 'statusOk'"
:title="mensaje"
>
<span class="statusDot" />
<span class="statusText">
{{ esObservado ? "Observado" : "Apto" }}
</span>
</div>
<div class="statusMsg" :class="esObservado ? 'msgBad' : 'msgOk'">
{{ mensaje }}
</div>
</div>
</div> </div>
<a-divider class="softDivider" /> <a-divider class="softDivider" />
@ -30,7 +48,7 @@
<div class="bulletRow"> <div class="bulletRow">
<span class="dot" /> <span class="dot" />
<span> <span>
Si tu proceso pide secuencia, también puedes usar la del pago de tu Si el test pide secuencia, también puedes usar la del pago de tu
<b>Carpeta de Postulante</b> (no pagas extra por este test). <b>Carpeta de Postulante</b> (no pagas extra por este test).
</span> </span>
</div> </div>
@ -95,7 +113,7 @@
type="primary" type="primary"
block block
class="actionBtnPrimary" class="actionBtnPrimary"
:disabled="!record.link_preinscripcion" :disabled="!record.link_preinscripcion || esObservado === true"
@click="onApply(record)" @click="onApply(record)"
> >
Postular Postular
@ -118,7 +136,7 @@
<script setup> <script setup>
import { computed, onMounted, reactive, ref } from "vue"; import { computed, onMounted, reactive, ref } from "vue";
import { Modal, message } from "ant-design-vue"; import { Modal } from "ant-design-vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useAuthStore } from "../../store/postulanteStore"; import { useAuthStore } from "../../store/postulanteStore";
import axios from "../../axiosPostulante"; import axios from "../../axiosPostulante";
@ -127,6 +145,10 @@ const router = useRouter();
const authStore = useAuthStore(); const authStore = useAuthStore();
const loading = ref(false); const loading = ref(false);
const canApply = computed(() => esObservado.value === false);
// estado observado
const esObservado = ref(null);
const mensaje = ref("");
const state = reactive({ const state = reactive({
test: { hasAssigned: true }, test: { hasAssigned: true },
@ -189,6 +211,18 @@ function onApply(process) {
window.open(process.link_preinscripcion, "_blank", "noopener,noreferrer"); window.open(process.link_preinscripcion, "_blank", "noopener,noreferrer");
} }
onMounted(async () => {
// Observación (derecha)
const r = await authStore.getObservacion();
if (r?.success) {
esObservado.value = r.es_observado;
mensaje.value = r.mensaje;
} else {
esObservado.value = null;
mensaje.value = "";
}
});
onMounted(fetchDashboard); onMounted(fetchDashboard);
</script> </script>
@ -219,6 +253,13 @@ onMounted(fetchDashboard);
align-items: flex-start; align-items: flex-start;
} }
.topbarRight {
display: grid;
gap: 8px;
justify-items: end;
text-align: right;
}
.hello { .hello {
font-size: 28px; font-size: 28px;
font-weight: 900; font-weight: 900;
@ -233,6 +274,48 @@ onMounted(fetchDashboard);
color: #64748b; color: #64748b;
} }
/* estado */
.statusPill {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 999px;
font-weight: 900;
font-size: 12px;
border: 1px solid rgba(15, 23, 42, 0.12);
background: rgba(15, 23, 42, 0.03);
}
.statusDot {
width: 10px;
height: 10px;
border-radius: 999px;
background: currentColor;
}
.statusOk {
color: #16a34a;
border-color: rgba(22, 163, 74, 0.25);
background: rgba(22, 163, 74, 0.08);
}
.statusBad {
color: #dc2626;
border-color: rgba(220, 38, 38, 0.25);
background: rgba(220, 38, 38, 0.08);
}
.statusMsg {
max-width: 340px;
font-size: 12px;
color: #64748b;
line-height: 1.35;
}
.msgOk { color: #166534; }
.msgBad { color: #7f1d1d; }
/* ====== TEST CARD ====== */ /* ====== TEST CARD ====== */
.testBox { .testBox {
border: 1px solid rgba(15, 23, 42, 0.08); border: 1px solid rgba(15, 23, 42, 0.08);
@ -382,6 +465,16 @@ onMounted(fetchDashboard);
.testHeadRight { .testHeadRight {
justify-items: stretch; justify-items: stretch;
} }
.topbarRight {
width: 100%;
justify-items: start;
text-align: left;
}
.statusMsg {
max-width: 100%;
}
} }
@media (max-width: 768px) { @media (max-width: 768px) {
@ -405,7 +498,7 @@ onMounted(fetchDashboard);
font-size: 22px; font-size: 22px;
} }
/* card full width en móvil (pro) */ /* card full width en móvil */
.testBox, .testBox,
.tableWrap { .tableWrap {
border-radius: 0; border-radius: 0;

@ -4,10 +4,9 @@
<a-col :xs="22" :sm="20" :md="20" :lg="16" :xl="14"> <a-col :xs="22" :sm="20" :md="20" :lg="16" :xl="14">
<div class="auth-shell"> <div class="auth-shell">
<a-row :gutter="[0, 0]" class="auth-layout"> <a-row :gutter="[0, 0]" class="auth-layout">
<!-- FORM -->
<a-col :xs="24" :md="12" class="auth-pane auth-pane-form"> <a-col :xs="24" :md="12" class="auth-pane auth-pane-form">
<div class="pane-inner"> <div class="pane-inner">
<div class="brand"> <div class="brand">
<div class="brand-mark"> <div class="brand-mark">
<img <img
@ -51,7 +50,15 @@
> >
<!-- DNI --> <!-- DNI -->
<a-form-item v-if="isRegister" label="DNI" name="dni"> <a-form-item v-if="isRegister" label="DNI" name="dni">
<a-input v-model:value="formState.dni" size="large" placeholder="Ingrese su DNI"> <a-input
v-model:value="formState.dni"
size="large"
placeholder="Ingrese su DNI"
inputmode="numeric"
:maxlength="8"
autocomplete="off"
@input="onDniInput"
>
<template #prefix><IdcardOutlined /></template> <template #prefix><IdcardOutlined /></template>
</a-input> </a-input>
</a-form-item> </a-form-item>
@ -61,30 +68,45 @@
v-model:value="formState.name" v-model:value="formState.name"
size="large" size="large"
placeholder="Ingrese su nombre completo" placeholder="Ingrese su nombre completo"
autocomplete="name"
> >
<template #prefix><UserOutlined /></template> <template #prefix><UserOutlined /></template>
</a-input> </a-input>
</a-form-item> </a-form-item>
<a-form-item label="Correo electrónico" name="email"> <a-form-item label="Correo electrónico" name="email">
<a-input v-model:value="formState.email" size="large" placeholder="correo@ejemplo.com"> <a-input
v-model:value="formState.email"
size="large"
placeholder="correo@ejemplo.com"
autocomplete="username"
>
<template #prefix><MailOutlined /></template> <template #prefix><MailOutlined /></template>
</a-input> </a-input>
</a-form-item> </a-form-item>
<!-- PASSWORD -->
<a-form-item label="Contraseña" name="password"> <a-form-item label="Contraseña" name="password">
<a-input-password <a-input-password
v-model:value="formState.password" v-model:value="formState.password"
size="large" size="large"
placeholder="Ingrese su contraseña" placeholder="Ingrese su contraseña"
:autocomplete="isRegister ? 'new-password' : 'current-password'"
> >
<template #prefix><LockOutlined /></template> <template #prefix><LockOutlined /></template>
</a-input-password> </a-input-password>
<!-- Solo en registro: requisitos (sin títulos/alertas/tips) -->
<ul v-if="isRegister" class="pwd-req">
<li :style="reqStyle(hasMinLength)">Mínimo 8 caracteres</li>
<li :style="reqStyle(hasUpper)">Al menos 1 mayúscula (A-Z)</li>
<li :style="reqStyle(hasLower)">Al menos 1 minúscula (a-z)</li>
<li :style="reqStyle(hasNumber)">Al menos 1 número (0-9)</li>
<li :style="reqStyle(hasSpecial)">Al menos 1 símbolo (@$!%*?&)</li>
</ul>
</a-form-item> </a-form-item>
<!-- CONFIRM PASSWORD -->
<a-form-item <a-form-item
v-if="isRegister" v-if="isRegister"
label="Confirmar contraseña" label="Confirmar contraseña"
@ -94,26 +116,17 @@
v-model:value="formState.password_confirmation" v-model:value="formState.password_confirmation"
size="large" size="large"
placeholder="Repita su contraseña" placeholder="Repita su contraseña"
autocomplete="new-password"
> >
<template #prefix><LockOutlined /></template> <template #prefix><LockOutlined /></template>
</a-input-password> </a-input-password>
</a-form-item> </a-form-item>
<!-- ROW (LOGIN) -->
<a-row <a-row v-if="!isRegister" justify="space-between" align="middle" class="form-row">
v-if="!isRegister"
justify="space-between"
align="middle"
class="form-row"
>
<a-checkbox v-model:checked="rememberMe">Recordarme</a-checkbox> <a-checkbox v-model:checked="rememberMe">Recordarme</a-checkbox>
<a-button <a-button type="link" size="small" class="link-muted" @click="handleForgotPassword">
type="link"
size="small"
class="link-muted"
@click="handleForgotPassword"
>
¿Olvidó su contraseña? ¿Olvidó su contraseña?
</a-button> </a-button>
</a-row> </a-row>
@ -137,68 +150,57 @@
</div> </div>
</a-col> </a-col>
<a-col :xs="24" :md="12" class="auth-pane auth-pane-info"> <!-- INFO -->
<div class="pane-inner pane-inner-info"> <a-col :xs="24" :md="12" class="auth-pane auth-pane-info">
<div class="info-top"> <div class="pane-inner pane-inner-info">
<a-tag class="info-tag">Universidad Nacional del Altiplano Puno</a-tag> <div class="info-top">
<a-tag class="info-tag">Universidad Nacional del Altiplano Puno</a-tag>
<a-typography-title :level="3" style="margin: 8px 0 0">
{{ isRegister ? "Registro de Postulante" : "Portal del Postulante" }}
</a-typography-title>
<a-typography-text type="secondary">
{{
isRegister
? "Crea tu cuenta para participar en el proceso de admisión y acceder a todos los servicios del portal."
: "Ingresa al portal para gestionar tu inscripción, revisar procesos disponibles y rendir un test de referencia."
}}
</a-typography-text>
</div>
<div class="info-section"> <a-typography-title :level="3" style="margin: 8px 0 0">
<div class="info-section-title"> {{ isRegister ? "Registro de Postulante" : "Portal del Postulante" }}
{{ isRegister ? "Al registrarte podrás" : "Al ingresar podrás" }} </a-typography-title>
</div>
<div class="info-list">
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Rendir un test de referencia</b>.</span>
</div>
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Ver procesos disponibles</b> según tu modalidad.</span>
</div>
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Consultar tu estado</b> de inscripción y seguimiento del proceso.</span>
</div>
<!-- <div class="info-item">
<span class="info-bullet"></span>
<span><b>Ver tu resultado detallado</b> por cursos.</span>
</div> -->
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Revisar comunicados oficiales</b> del proceso de admisión.</span>
</div>
</div>
</div>
<div class="info-foot"> <a-typography-text type="secondary">
<a-typography-text type="secondary"> {{
Plataforma oficial de admisión Soporte en horario institucional isRegister
</a-typography-text> ? "Crea tu cuenta para participar en el proceso de admisión y acceder a los servicios del portal."
</div> : "Ingresa al portal para ver tu estado de inscripción, revisar procesos disponibles y rendir un test de referencia."
}}
</a-typography-text>
</div>
<div class="info-section">
<div class="info-section-title">
{{ isRegister ? "Al registrarte podrás" : "Al ingresar podrás" }}
</div> </div>
</a-col>
<div class="info-list">
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Rendir un test de referencia</b>.</span>
</div>
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Ver procesos disponibles</b>.</span>
</div>
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Consultar tu estado</b> de inscripción y seguimiento del proceso.</span>
</div>
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Revisar comunicados oficiales</b> del proceso de admisión.</span>
</div>
</div>
</div>
<div class="info-foot">
<a-typography-text type="secondary">
Plataforma oficial de admisión Soporte en horario institucional
</a-typography-text>
</div>
</div>
</a-col>
</a-row> </a-row>
</div> </div>
</a-col> </a-col>
@ -221,7 +223,6 @@ const isRegister = ref(false);
const rememberMe = ref(false); const rememberMe = ref(false);
const loading = ref(false); const loading = ref(false);
const logoSrc = "/logotiny.png"; const logoSrc = "/logotiny.png";
const logoError = ref(false); const logoError = ref(false);
@ -243,6 +244,17 @@ watch(isRegister, () => {
formRef.value?.clearValidate(); formRef.value?.clearValidate();
}); });
const onDniInput = () => {
formState.dni = (formState.dni || "").replace(/\D/g, "").slice(0, 8);
};
// Requisitos visuales (mismos del backend)
const hasMinLength = computed(() => (formState.password || "").length >= 8);
const hasUpper = computed(() => /[A-Z]/.test(formState.password || ""));
const hasLower = computed(() => /[a-z]/.test(formState.password || ""));
const hasNumber = computed(() => /\d/.test(formState.password || ""));
const hasSpecial = computed(() => /[@$!%*?&]/.test(formState.password || ""));
const rules = computed(() => ({ const rules = computed(() => ({
dni: [ dni: [
{ required: isRegister.value, message: "Ingrese su DNI", trigger: "blur" }, { required: isRegister.value, message: "Ingrese su DNI", trigger: "blur" },
@ -258,20 +270,36 @@ const rules = computed(() => ({
], ],
password: [ password: [
{ required: true, message: "Ingrese su contraseña", trigger: "blur" }, { required: true, message: "Ingrese su contraseña", trigger: "blur" },
{ min: 6, message: "La contraseña debe tener al menos 6 caracteres", trigger: "blur" },
],
password_confirmation: [
{ required: isRegister.value, message: "Confirme su contraseña", trigger: "blur" },
{ {
// Solo en registro validamos composición; en login no molestamos.
validator: (rule, value) => { validator: (rule, value) => {
if (!isRegister.value) return Promise.resolve(); if (!isRegister.value) return Promise.resolve();
if (!value) return Promise.reject("Confirme su contraseña");
if (value !== formState.password) return Promise.reject("Las contraseñas no coinciden"); const v = value || "";
return Promise.resolve(); const ok =
v.length >= 8 &&
/[A-Z]/.test(v) &&
/[a-z]/.test(v) &&
/\d/.test(v) &&
/[@$!%*?&]/.test(v);
return ok ? Promise.resolve() : Promise.reject("Contraseña inválida");
}, },
trigger: "blur", trigger: "blur",
}, },
], ],
password_confirmation: [
{ required: isRegister.value, message: "Confirme su contraseña", trigger: "blur" },
{
validator: (rule, value) => {
if (!isRegister.value) return Promise.resolve();
if (!value) return Promise.resolve(); // el required ya se encarga
if (value !== formState.password) return Promise.reject("Las contraseñas no coinciden");
return Promise.resolve();
},
trigger: "blur",
},
],
})); }));
const showNotification = (type, message, description = "") => { const showNotification = (type, message, description = "") => {
@ -288,13 +316,18 @@ const handleForgotPassword = () => {
showNotification("info", "Recuperación de contraseña", "Por favor, contacte al administrador del sistema"); showNotification("info", "Recuperación de contraseña", "Por favor, contacte al administrador del sistema");
}; };
const reqStyle = (ok) => ({
color: ok ? "#16a34a" : "#6b7280",
fontWeight: ok ? "700" : "500",
});
const handleSubmit = async () => { const handleSubmit = async () => {
loading.value = true; loading.value = true;
try { try {
if (isRegister.value) { if (isRegister.value) {
const result = await authStore.register({ ...formState }); const result = await authStore.register({ ...formState });
if (result.success) { if (result.success) {
showNotification("success", "¡Registro exitoso!", "Tu cuenta ha sido creada correctamente"); showNotification("success", "¡Registro exitoso!");
toggleMode(); toggleMode();
} else { } else {
showNotification("error", "Error en registro", result.error); showNotification("error", "Error en registro", result.error);
@ -377,10 +410,6 @@ checkExistingAuth();
gap: 14px; gap: 14px;
} }
.pane-inner-info {
justify-content: space-between;
}
/* Branding */ /* Branding */
.brand { .brand {
display: flex; display: flex;
@ -426,10 +455,6 @@ checkExistingAuth();
font-size: 0.95rem; font-size: 0.95rem;
} }
.auth-header {
text-align: left;
}
.auth-divider { .auth-divider {
margin: 6px 0 14px; margin: 6px 0 14px;
} }
@ -474,29 +499,15 @@ checkExistingAuth();
font-weight: 800; font-weight: 800;
} }
.info-top {
text-align: left;
}
.info-tag { .info-tag {
border: 0; border: 0;
background: color-mix(in srgb, var(--ant-colorPrimary) 14%, transparent); background: rgba(22, 119, 255, 0.12);
color: var(--ant-colorPrimary, #1677ff); color: var(--ant-colorPrimary, #1677ff);
font-weight: 800; font-weight: 800;
border-radius: 999px; border-radius: 999px;
padding: 6px 12px; padding: 6px 12px;
} }
.info-section {
margin-top: 8px;
}
.info-section-title {
font-weight: 800;
color: var(--ant-colorTextHeading, #111827);
margin: 6px 0 10px;
}
.info-list { .info-list {
margin-top: 10px; margin-top: 10px;
display: grid; display: grid;
@ -525,6 +536,11 @@ checkExistingAuth();
border-top: 1px solid var(--ant-colorBorderSecondary, rgba(0, 0, 0, 0.06)); border-top: 1px solid var(--ant-colorBorderSecondary, rgba(0, 0, 0, 0.06));
} }
.pwd-req {
margin: 8px 0 0 16px;
font-size: 12px;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.auth-pane { .auth-pane {
padding: 22px; padding: 22px;
@ -537,10 +553,4 @@ checkExistingAuth();
min-height: auto; min-height: auto;
} }
} }
@supports not (color: color-mix(in srgb, white 50%, black)) {
.info-tag {
background: rgba(22, 119, 255, 0.12);
}
}
</style> </style>

@ -27,7 +27,6 @@
<span class="counterLabel">Total</span> <span class="counterLabel">Total</span>
<span class="counterValue">{{ procesosFiltrados.length }}</span> <span class="counterValue">{{ procesosFiltrados.length }}</span>
</div> </div>
</div> </div>
<!-- Desktop --> <!-- Desktop -->
@ -63,7 +62,7 @@
</template> </template>
<template #emptyText> <template #emptyText>
<a-empty description="No se encontraron procesos" /> <a-empty :description="emptyMessage" />
</template> </template>
</a-table> </a-table>
</div> </div>
@ -104,7 +103,7 @@
</div> </div>
</template> </template>
<a-empty v-else description="No se encontraron procesos" /> <a-empty v-else :description="emptyMessage" />
</div> </div>
</a-spin> </a-spin>
</a-card> </a-card>
@ -126,6 +125,10 @@ const columns = [
{ title: "Acciones", key: "acciones", width: 160 }, { title: "Acciones", key: "acciones", width: 160 },
]; ];
const emptyMessage = computed(() => {
return "Aún no tienes procesos anteriores registrados. Si participaste recientemente, esta sección puede demorar en actualizarse.";
});
const obtenerProcesos = async () => { const obtenerProcesos = async () => {
loading.value = true; loading.value = true;
try { try {
@ -225,10 +228,6 @@ onMounted(() => {
font-size: 18px; font-size: 18px;
} }
.search {
border-radius: 12px;
}
.tableWrap { .tableWrap {
width: 100%; width: 100%;
overflow-x: auto; overflow-x: auto;

@ -124,7 +124,7 @@
</a-menu-item> --> </a-menu-item> -->
<a-menu-item key="mis-procesos"> <a-menu-item key="mis-procesos">
<FolderOutlined /> <FolderOutlined />
<span>Mis Procesos</span> <span>Mis procesos anteriores</span>
</a-menu-item> </a-menu-item>
<!-- <a-menu-item key="pagos"> <!-- <a-menu-item key="pagos">
@ -141,7 +141,7 @@
<a-menu-item key="seguimiento"> <a-menu-item key="seguimiento">
<LineChartOutlined /> <LineChartOutlined />
<span>Estado del Proceso</span> <span>Seguimiento de inscripción</span>
</a-menu-item> </a-menu-item>
<!-- <a-menu-item key="resultados"> <!-- <a-menu-item key="resultados">

@ -499,7 +499,7 @@ No se realiza ningún pago adicional.
/> />
<a-form v-else ref="formRef" :model="formState" :rules="rules" layout="vertical"> <a-form v-else ref="formRef" :model="formState" :rules="rules" layout="vertical">
<a-form-item label="Proceso" name="proceso_id" required> <a-form-item label="Nombre" name="proceso_id" required>
<a-select <a-select
v-model:value="formState.proceso_id" v-model:value="formState.proceso_id"
placeholder="Selecciona un proceso" placeholder="Selecciona un proceso"

Loading…
Cancel
Save