web_page_finish

main
elmer-20 2 months ago
parent 9cbd6d2a88
commit 7a528bd7bf

@ -161,28 +161,28 @@ class PostulanteAuthController extends Controller
$pagos = [];
// ===============================
// 1⃣ PAGOS PYTO PERÚ
// ===============================
$urlPyto = "https://service2.unap.edu.pe/PAYMENTS_MNG/v1/{$dni}/8/";
$responsePyto = Http::get($urlPyto);
if ($responsePyto->successful()) {
$dataPyto = $responsePyto->json();
if (!empty($dataPyto['data'])) {
foreach ($dataPyto['data'] as $pago) {
$pagos[] = [
'tipo' => 'pyto_peru',
'codigo' => $pago['autorizationCode'] ?? null,
'monto' => $pago['total'] ?? null,
'fecha_pago' => $pago['confirmedDate'] ?? null,
'estado' => true,
'raw' => $pago // devuelve toda la info original
];
}
}
}
// // ===============================
// // 1⃣ PAGOS PYTO PERÚ
// // ===============================
// $urlPyto = "https://service2.unap.edu.pe/PAYMENTS_MNG/v1/{$dni}/8/";
// $responsePyto = Http::get($urlPyto);
// if ($responsePyto->successful()) {
// $dataPyto = $responsePyto->json();
// if (!empty($dataPyto['data'])) {
// foreach ($dataPyto['data'] as $pago) {
// $pagos[] = [
// 'tipo' => 'pyto_peru',
// 'codigo' => $pago['autorizationCode'] ?? null,
// 'monto' => $pago['total'] ?? null,
// 'fecha_pago' => $pago['confirmedDate'] ?? null,
// 'estado' => true,
// 'raw' => $pago // devuelve toda la info original
// ];
// }
// }
// }
// ===============================
// 2⃣ PAGOS CAJA

@ -79,7 +79,7 @@ Route::middleware(['auth:sanctum'])->prefix('admin')->group(function () {
Route::delete('/noticias/{noticia}', [NoticiaController::class, 'destroy']);
});
Route::get('/noticias', [NoticiaController::class, 'index']);
Route::get('/noticias/{noticia}', [NoticiaController::class, 'showPublic']);
Route::get('/noticias/{noticia}', [NoticiaController::class, 'showPublic']);
Route::middleware(['auth:sanctum'])->prefix('admin')->group(function () {

@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>frontend</title>
<title>Admisión</title>
</head>
<body>
<div id="app"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

@ -11,7 +11,7 @@
<ConvocatoriasSection/>
<ProgramasSection/>
<!-- <ProgramasSection/> -->
<StatsSection />
@ -19,6 +19,7 @@
<ContactSection />
</div>

@ -1,139 +1,171 @@
<!-- components/contact/ContactSection.vue -->
<template>
<section class="contact-section">
<section class="process-section" aria-labelledby="faq-title">
<div class="section-container">
<div class="contact-grid">
<div class="contact-info">
<h2 class="section-title">¿Necesitas Ayuda?</h2>
<p class="contact-subtitle">Nuestro equipo está listo para asistirte en todo el proceso de admisión</p>
<div class="contact-methods">
<div class="contact-method">
<PhoneOutlined />
<div>
<h4>Teléfono</h4>
<p>(01) 123-4567</p>
</div>
</div>
<div class="contact-method">
<MailOutlined />
<div>
<h4>Email</h4>
<p>admision@universidad.edu.pe</p>
</div>
</div>
<div class="contact-method">
<ClockCircleOutlined />
<div>
<h4>Horario</h4>
<p>Lun-Vie: 8:00 AM - 6:00 PM</p>
</div>
</div>
</div>
</div>
<div class="contact-form">
<h3>Envíanos un Mensaje</h3>
<a-form layout="vertical">
<a-form-item label="Nombre completo">
<a-input placeholder="Ingresa tu nombre completo" />
</a-form-item>
<a-form-item label="Email">
<a-input placeholder="tu@email.com" />
</a-form-item>
<a-form-item label="Consulta">
<a-textarea placeholder="Describe tu consulta..." :rows="4" />
</a-form-item>
<a-button type="primary" block>Enviar Mensaje</a-button>
</a-form>
</div>
<!-- Header -->
<div class="section-header">
<h2 id="faq-title" class="section-title">
Preguntas Frecuentes
</h2>
<p class="section-subtitle">
Resolvemos las dudas más comunes sobre el proceso de admisión y el uso de nuestra plataforma.
</p>
</div>
<div class="process-card">
<!-- FAQ -->
<a-collapse accordion class="modern-collapse">
<a-collapse-panel key="1" header="01. ¿Puedo postular con DNI caducado?">
No, su DNI debe estar vigente al momento de la inscripción.
En su defecto, puede presentar la Hoja C4 o el ticket de trámite acompañado de una copia del DNI.
</a-collapse-panel>
<a-collapse-panel key="2" header="02. ¿Qué requisitos debo presentar si postulo como persona con discapacidad?">
Certificado de Discapacidad emitido por entidades de salud acreditadas en el RENIPRESS.
Este debe ser adjuntado junto a los demás requisitos.
</a-collapse-panel>
<a-collapse-panel key="3" header="03. ¿Qué hago si ingreso mal mis datos en la preinscripción?">
No es posible modificarlos en línea una vez guardados.
Debe acercarse al local de inscripción y solicitar ayuda en la oficina de soporte técnico.
</a-collapse-panel>
<a-collapse-panel key="4" header="04. ¿Cuáles son los códigos para realizar los pagos?">
<p><b>Código 26:</b> Derechos de Admisión.</p>
<p><b>Código 27:</b> Rezagados al proceso de inscripción.</p>
<p><b>Código 28:</b> Carpeta de postulante.</p>
</a-collapse-panel>
<a-collapse-panel key="5" header="05. ¿Cómo debo realizar la preinscripción e inscripción?">
Ingrese a admision.unap.edu.pe para la preinscripción.
<br /><br />
La inscripción presencial se realiza según el último dígito del DNI, según el cronograma oficial.
</a-collapse-panel>
<a-collapse-panel key="6" header="06. ¿Qué requisitos debo presentar si postulo a Medicina Humana o Educación Física?">
Constancia de evaluación médica emitida por un establecimiento de salud primario,
además de los demás requisitos exigidos.
</a-collapse-panel>
<a-collapse-panel key="7" header="07. ¿Puedo cambiar de programa de estudio luego de inscribirme?">
. Tras obtener su constancia de inscripción, debe realizar un pago de S/.100 (Código 27)
en caja de la Universidad o Banco de la Nación, incluyendo comisión.
</a-collapse-panel>
<a-collapse-panel key="8" header="08. ¿Qué debo traer para inscribirme presencialmente?">
<ul>
<li>Comprobantes de pago o vouchers</li>
<li>DNI original y copia</li>
<li>Solicitud de Preinscripción impresa</li>
<li>Certificado de estudios original y copia</li>
</ul>
</a-collapse-panel>
<a-collapse-panel key="9" header="09. ¿Los postulantes con discapacidad hacen cola?">
No. Deben presentar su Certificado de Discapacidad y se les brindará atención preferencial.
</a-collapse-panel>
</a-collapse>
</div>
</div>
</section>
</template>
<script setup>
import { PhoneOutlined, MailOutlined, ClockCircleOutlined } from '@ant-design/icons-vue'
</script>
<style scoped>
.contact-section {
padding: 80px 0;
/* reutiliza la misma base visual de ProcessSection */
.process-section {
padding: 30px 0;
background: #ffffff;
font-family: "Times New Roman", Times, serif;
}
.section-container {
max-width: 1200px;
max-width: 1100px;
margin: 0 auto;
padding: 0 24px;
padding: 0 20px;
}
.contact-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 80px;
align-items: start;
.section-header {
text-align: center;
margin-bottom: 18px;
}
.section-title {
font-size: 2.5rem;
font-size: 2.1rem;
font-weight: 700;
color: #1a237e;
margin-bottom: 16px;
color: #2c3e50;
margin: 0 0 6px 0;
}
.contact-subtitle {
color: #666;
font-size: 1.125rem;
margin-bottom: 40px;
.section-subtitle {
font-size: 1rem;
color: #777;
margin: 0;
}
.contact-methods {
display: flex;
flex-direction: column;
gap: 24px;
.process-card {
border: 1px solid #e5e7eb;
border-radius: 14px;
padding: 20px 18px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.04);
background: #fff;
}
.contact-method {
display: flex;
align-items: center;
gap: 16px;
/* Ilustración */
.illustration-box {
text-align: center;
margin-bottom: 20px;
}
.contact-method svg {
color: #1890ff;
font-size: 24px;
.illustration-img {
width: 160px;
margin-bottom: 8px;
}
.contact-method h4 {
margin: 0 0 4px;
color: #1a237e;
.illustration-text {
font-size: 0.9rem;
color: #6b7280;
}
.contact-method p {
margin: 0;
color: #666;
/* Collapse estilo limpio */
.modern-collapse {
background: transparent;
}
.contact-form {
background: white;
padding: 40px;
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
.modern-collapse :deep(.ant-collapse-item) {
border-radius: 10px !important;
margin-bottom: 10px;
background: #f8fafc;
border: 1px solid #e5e7eb;
}
.contact-form h3 {
margin: 0 0 32px;
color: #1a237e;
.modern-collapse :deep(.ant-collapse-header) {
font-weight: 700;
color: #1e3a8a;
}
@media (max-width: 992px) {
.contact-grid {
grid-template-columns: 1fr;
gap: 48px;
}
.modern-collapse :deep(.ant-collapse-content) {
background: #ffffff;
border-top: 1px solid #eef2f7;
}
/* Responsive */
@media (max-width: 768px) {
.section-title {
font-size: 2rem;
font-size: 1.6rem;
}
.process-card {
padding: 14px 12px;
}
.illustration-img {
width: 120px;
}
}
</style>
</style>

@ -140,51 +140,53 @@
<!-- SECUNDARIAS (hardcode por ahora) -->
<div class="secondary-list">
<a-card class="secondary-convocatoria-card">
<a-card class="secondary-convocatoria-card">
<div class="convocatoria-header">
<div>
<h4 class="secondary-title">CEPREUNA</h4>
<h4 class="secondary-title">Extraordinario</h4>
<p class="convocatoria-date">30 de enero</p>
</div>
<a-tag class="status-tag" color="default">FINALIZADO</a-tag>
<a-tag class="status-tag" color="orange">Finalizado</a-tag>
</div>
<p class="convocatoria-desc">Postulantes del CEPRE</p>
<p class="convocatoria-desc">
Modalidad extraordinaria para perfiles específicos
</p>
<div class="card-footer">
<a-button type="link" size="small" @click="emit('show-modal', 'cepreuna')">
<!-- <div class="card-footer">
<a-button
type="link"
size="small"
@click="emit('show-modal', 'extraordinario')"
>
Ver detalles
</a-button>
<a-button type="primary" ghost size="small">Consultar</a-button>
</div>
</div> -->
</a-card>
<a-card class="secondary-convocatoria-card">
<div class="convocatoria-header">
<div>
<h4 class="secondary-title">Extraordinario</h4>
<p class="convocatoria-date">15 de febrero</p>
<h4 class="secondary-title">CEPREUNA</h4>
<p class="convocatoria-date">10 y 11 de enero</p>
</div>
<a-tag class="status-tag" color="orange">PRÓXIMAMENTE</a-tag>
<a-tag class="status-tag" color="orange">Finalizado</a-tag>
</div>
<p class="convocatoria-desc">
Modalidad extraordinaria para perfiles específicos
</p>
<p class="convocatoria-desc">Postulantes del CEPREUNA</p>
<div class="card-footer">
<a-button
type="link"
size="small"
@click="emit('show-modal', 'extraordinario')"
>
<!-- <div class="card-footer">
<a-button type="link" size="small" @click="emit('show-modal', 'cepreuna')">
Ver detalles
</a-button>
<a-button type="primary" ghost size="small">Consultar</a-button>
</div>
</div> -->
</a-card>
</div>
</div>
</div>
@ -204,7 +206,7 @@
:key="detalle.id"
style="margin-bottom: 25px"
>
<h3>{{ detalle.titulo_detalle }}</h3>
<!-- <h3>{{ detalle.titulo_detalle }}</h3> -->
<p v-if="detalle.descripcion">
{{ detalle.descripcion }}

@ -1,15 +1,16 @@
<!-- components/hero/HeroSection.vue -->
<template>
<section class="hero" aria-label="Sección principal de admisión">
<div class="hero-bg" aria-hidden="true">
<div class="hero-grid"></div>
<div class="hero-shape hero-shape-1"></div>
<div class="hero-shape hero-shape-2"></div>
</div>
<section
class="hero"
:style="{ backgroundImage: `url(${heroImg})` }"
aria-label="Sección principal de admisión"
>
<!-- Overlay oscuro -->
<div class="hero-overlay"></div>
<div class="hero-container">
<!-- CONTENIDO -->
<div class="hero-content">
<div class="hero-badges">
<a-tag class="hero-tag">Convocatoria 2026</a-tag>
@ -18,14 +19,18 @@
Inscripciones abiertas
</span>
</div>
<div class="glass-cardtitle">
<h1 class="hero-title">
Admisión <span class="hero-year">2026</span>
</h1>
</div>
<h1 class="hero-title">
Admisión <span class="hero-year">2026</span>
</h1>
<p class="hero-subtitle">
Forma parte de una comunidad académica de excelencia.
<span class="hero-subtitle-muted">Postula, infórmate y conoce el proceso.</span>
<span class="hero-subtitle-muted">
Postula, infórmate y conoce el proceso.
</span>
</p>
<div class="hero-actions">
@ -39,78 +44,48 @@
Postular ahora
</a-button>
<a-button size="large" class="secondary-button" @click="$emit('virtual-tour')">
<template #icon><PlayCircleOutlined /></template>
Tour virtual
</a-button>
</div>
<div class="hero-metrics">
<div class="metric">
<span class="metric-value">44</span>
<span class="metric-label">Programas</span>
</div>
<div class="metric">
<span class="metric-value">3</span>
<span class="metric-label">Áreas</span>
</div>
<div class="metric">
<span class="metric-value">+10</span>
<span class="metric-label">Sedes</span>
</div>
</div>
</div>
<!-- Visual -->
<div class="hero-visual">
<div class="visual-stack">
<div class="floating-card">
<div class="card-header">
<CalendarOutlined />
<span>Próximo evento</span>
</div>
<h3 class="card-title">Charla informativa</h3>
<div class="card-info">
<span class="info-item">
<ClockCircleOutlined />
25 Nov 4:00 PM
</span>
<span class="info-item">
<VideoCameraOutlined />
Virtual
</span>
</div>
<a-button type="primary" ghost class="card-cta" size="middle">
Registrarse
</a-button>
<!-- CARD -->
<!-- <div class="hero-visual">
<div class="glass-card">
<div class="card-header">
<CalendarOutlined />
<span>Próximo evento</span>
</div>
<div class="mini-card" aria-hidden="true">
<span class="mini-dot"></span>
<div class="mini-text">
<div class="mini-title">Guía del postulante</div>
<div class="mini-sub">Requisitos y fechas</div>
</div>
<ArrowRightOutlined class="mini-icon" />
</div>
<h3>Charla informativa</h3>
<p class="card-date">
<ClockCircleOutlined />
25 Nov 4:00 PM Virtual
</p>
<a-button
size="large"
class="secondary-button"
@click="$emit('virtual-tour')"
>
<template #icon><PlayCircleOutlined /></template>
Tour virtual
</a-button>
</div>
</div>
</div> -->
</div>
</section>
</template>
<script setup>
const heroImg = "/PORTADA.jpg.jpeg";
import {
RightCircleOutlined,
PlayCircleOutlined,
CalendarOutlined,
CheckCircleOutlined,
ClockCircleOutlined,
VideoCameraOutlined,
ArrowRightOutlined,
ClockCircleOutlined
} from "@ant-design/icons-vue";
defineEmits(["scroll-to-convocatoria", "virtual-tour"]);
@ -118,346 +93,161 @@ defineEmits(["scroll-to-convocatoria", "virtual-tour"]);
<style scoped>
/* 🔥 TODA LA SECCIÓN EN TIMES */
.hero,
.hero * {
font-family: "Times New Roman", Times, serif;
}
.hero {
--inst-primary: #1a237e; /* AZUL institucional (ejemplo) */
--inst-secondary: #0f172a; /* oscuro de apoyo */
--inst-accent: #c8a100; /* dorado institucional (ejemplo) */
position: relative;
padding: 110px 0;
color: white;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
overflow: hidden;
color: #ffffff;
padding: 88px 0;
background: var(--inst-primary); /* SIN DEGRADADOS */
}
/* Fondo decorativo sutil (sin degradados) */
.hero-bg {
position: absolute;
inset: 0;
pointer-events: none;
}
/* Patrón de líneas muy suave */
.hero-grid {
position: absolute;
inset: 0;
opacity: 0.10;
background-image: linear-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.14) 1px, transparent 1px);
background-size: 52px 52px;
--text: rgba(245, 247, 255, 0.92); /* blanco suave */
--muted: rgba(229, 235, 255, 0.72);
}
.hero-shape {
position: absolute;
border-radius: 999px;
opacity: 0.16;
background: #ffffff;
}
.hero-shape-1 {
width: 460px;
height: 460px;
left: -220px;
top: -240px;
}
.hero-shape-2 {
width: 560px;
height: 560px;
right: -260px;
bottom: -320px;
}
.hero-container {
position: relative;
z-index: 1;
max-width: 1200px;
margin: 0 auto;
margin: auto;
padding: 0 24px;
display: grid;
grid-template-columns: 1.1fr 0.9fr;
gap: 72px;
grid-template-columns: 1.2fr 0.8fr;
align-items: center;
gap: 60px;
}
/* BADGES */
.hero-badges {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 20px;
flex-wrap: wrap;
margin-bottom: 22px;
}
.hero-tag {
background: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.25);
color: #fff;
background: rgba(255, 255, 255, 0.12);
font-weight: 700;
color: rgb(255, 255, 255);
font-weight: bold;
}
.hero-pill {
display: inline-flex;
display: flex;
align-items: center;
gap: 8px;
gap: 6px;
background: rgba(255, 255, 255, 0.12);
padding: 6px 12px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.22);
background: rgba(0, 0, 0, 0.10);
font-size: 0.95rem;
font-weight: 700;
font-weight: bold;
}
/* TITULO */
.hero-title {
font-size: 3.4rem;
font-weight: 900;
line-height: 1.08;
margin: 0 0 18px;
letter-spacing: -0.01em;
font-size: 3.5rem;
font-weight: bold;
margin: 0 0 20px;
color: rgba(245, 247, 255, 0.96);
}
.hero-year {
color: var(--inst-accent);
position: relative;
}
font-size: 2.8rem;
font-weight: 900;
line-height: 1;
.hero-year::after {
content: "";
position: absolute;
left: 0;
bottom: -10px;
width: 100%;
height: 4px;
background: var(--inst-accent);
border-radius: 999px;
opacity: 0.9;
background: linear-gradient(45deg, #ffd700, #ff6b6b);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: 1.18rem;
opacity: 0.95;
margin: 0 0 32px;
line-height: 1.65;
max-width: 560px;
font-weight: 600;
}
.hero-subtitle-muted {
display: inline-block;
margin-left: 6px;
opacity: 0.9;
font-weight: 600;
font-size: 1.2rem;
max-width: 550px;
margin-bottom: 30px;
line-height: 1.6;
}
/* BOTONES */
.hero-actions {
display: flex;
gap: 14px;
gap: 15px;
flex-wrap: wrap;
}
.cta-button {
border: 1px solid rgba(255, 255, 255, 0.22);
font-weight: 800;
border-radius: 12px;
background: var(--inst-accent);
color: var(--inst-secondary);
}
.cta-button:hover {
filter: brightness(1.02);
transform: translateY(-1px);
font-weight: bold;
border-radius: 8px;
}
.secondary-button {
background: transparent;
border: 2px solid rgba(255, 255, 255, 0.28);
color: #fff;
border-radius: 12px;
font-weight: 800;
border: 2px solid rgba(255, 255, 255, 0.6);
color: white;
border-radius: 8px;
font-weight: bold;
}
.secondary-button:hover {
background: rgba(255, 255, 255, 0.08);
}
.hero-metrics {
margin-top: 28px;
display: flex;
gap: 14px;
flex-wrap: wrap;
}
.metric {
min-width: 120px;
padding: 12px 14px;
border-radius: 14px;
background: rgba(255, 255, 255, 0.10);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.metric-value {
display: block;
font-size: 1.25rem;
font-weight: 900;
line-height: 1.1;
color: #fff;
}
.metric-label {
display: block;
opacity: 0.9;
font-size: 0.95rem;
margin-top: 2px;
font-weight: 700;
}
/* ====== VISUAL ====== */
/* CARD */
.hero-visual {
display: flex;
justify-content: flex-end;
}
.visual-stack {
width: min(420px, 100%);
display: grid;
gap: 14px;
}
.floating-card {
background: #ffffff;
color: #111827;
padding: 22px;
border-radius: 18px;
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.18);
border: 1px solid rgba(17, 24, 39, 0.08);
transition: transform 0.25s ease, box-shadow 0.25s ease;
.glass-card {
background: rgba(106, 136, 219, 0.55);
padding: 28px;
border-radius: 16px;
width: 100%;
max-width: 360px;
box-shadow: 0 25px 60px rgba(0, 0, 0, 0.3);
}
.floating-card:hover {
transform: translateY(-4px);
box-shadow: 0 28px 70px rgba(0, 0, 0, 0.22);
.glass-cardtitle {
background: rgba(190, 200, 228, 0.55);
padding: 12px 24px;
border-radius: 16px;
width: fit-content; /* 👈 se ajusta al contenido */
max-width: 100%;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
.card-header {
display: flex;
align-items: center;
gap: 10px;
color: #6b7280;
margin-bottom: 14px;
font-weight: 800;
}
.card-title {
margin: 0 0 12px;
color: #111827;
font-weight: 900;
}
.card-info {
display: flex;
flex-wrap: wrap;
gap: 10px 14px;
margin-bottom: 14px;
color: #374151;
font-weight: 700;
}
.info-item {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 0.95rem;
font-weight: 800;
font-weight: bold;
}
.card-cta {
border-radius: 12px;
font-weight: 900;
border-color: var(--inst-primary);
color: var(--inst-primary);
}
.mini-card {
.card-date {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-radius: 16px;
background: rgba(255, 255, 255, 0.10);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.mini-dot {
width: 10px;
height: 10px;
border-radius: 999px;
background: var(--inst-accent);
box-shadow: 0 0 0 6px rgba(200, 161, 0, 0.18);
}
.mini-title {
font-weight: 900;
line-height: 1.1;
}
.mini-sub {
opacity: 0.9;
font-size: 0.95rem;
margin-top: 2px;
font-weight: 700;
gap: 6px;
margin-bottom: 20px;
}
.mini-icon {
opacity: 0.9;
}
/* ====== Responsive ====== */
/* RESPONSIVE */
@media (max-width: 992px) {
.hero {
padding: 72px 0;
}
.hero-container {
grid-template-columns: 1fr;
text-align: center;
gap: 40px;
}
.hero-subtitle {
margin-left: auto;
margin-right: auto;
}
.hero-actions {
justify-content: center;
}
.hero-visual {
justify-content: center;
margin-top: 40px;
}
.hero-title {
font-size: 2.7rem;
font-size: 2.4rem;
}
.hero-metrics {
.hero-actions {
justify-content: center;
}
}
@media (max-width: 768px) {
.hero-title {
font-size: 2.15rem;
}
.metric {
min-width: 110px;
}
}
</style>
</style>

@ -20,7 +20,7 @@
<!-- GUÍA PARA POSTULANTES -->
<div class="help-box" v-if="store.procesoPrincipal">
<div class="help-title">📌 Guía rápida (para no perderte)</div>
<div class="help-title"> Guía rápida (para no perderte)</div>
<div class="help-grid">
<!-- Etapas activas -->
@ -100,7 +100,7 @@
<!-- Nota fija sobre inscripción presencial -->
<div class="campus-note">
🏫 <b>Importante:</b> La <b>Inscripción</b> se realiza de forma <b>presencial</b> en el
<b>Importante:</b> La <b>Inscripción</b> se realiza de forma <b>presencial</b> en el
<b>Campus Universitario</b>. Lleva tu DNI y los requisitos solicitados.
</div>
</div>
@ -336,30 +336,30 @@ const tareasHoy = computed(() => {
const tareas = []
if (a.pre) {
tareas.push("Entra a la Preinscripción Virtual y completa tus datos sin apuro (verifica nombres y DNI).")
tareas.push("📌 Al terminar, guarda tu constancia o captura y revisa los Requisitos del proceso.")
tareas.push("Entra a la Preinscripción Virtual y completa tus datos sin apuro (verifica nombres y DNI).")
tareas.push("Al terminar, descarga e imprime tu solicitud de preinscripción y revisa los Requisitos del proceso.")
}
if (a.ins) {
tareas.push("🏫 Acércate al Campus Universitario para la Inscripción Presencial.")
tareas.push("🪪 Lleva tu DNI y los documentos/pagos solicitados por Admisión.")
tareas.push("Acércate al Campus Universitario para la Inscripción Presencial.")
tareas.push("Lleva tu DNI y los documentos/pagos solicitados.")
}
if (a.exa) {
tareas.push("📝 Hoy es el Examen: llega temprano, lleva tu DNI y sigue las indicaciones del reglamento.")
tareas.push("Hoy es el Examen: llega temprano, lleva tu DNI, constancia de inscripción y sigue las indicaciones del reglamento.")
}
if (a.res) {
tareas.push("📣 Hoy salen Resultados: revisa el enlace oficial y guarda una captura/constancia.")
tareas.push("Hoy salen Resultados.")
}
if (a.bio) {
tareas.push("Si ingresaste: acércate al control biométrico dentro de las fechas indicadas.")
tareas.push("Si ingresaste: acércate al control biométrico dentro de las fechas indicadas.")
}
if (tareas.length === 0) {
tareas.push("📅 Revisa las fechas del proceso en los pasos de arriba.")
tareas.push("Si aún no inicia: alístate con requisitos, documentos y pagos para no correr a última hora.")
tareas.push("Revisa las fechas del proceso en los pasos de arriba.")
tareas.push("Si aún no inicia: alístate con requisitos, documentos y pagos para no correr a última hora.")
}
return tareas

@ -3,7 +3,7 @@
<section class="stats-section" aria-labelledby="stats-title">
<div class="section-container">
<div class="section-header">
<h2 id="stats-title" class="section-title">Cifras Clave</h2>
<h2 id="stats-title" class="section-title">LA UNA PUNO EN CIFRAS</h2>
<p class="section-subtitle">
Indicadores institucionales que reflejan nuestro compromiso académico
</p>
@ -11,31 +11,35 @@
<div class="stats-grid">
<div class="stat-card">
<p class="stat-label">Fundada en</p>
<div class="stat-top">
<span class="stat-number">25+</span>
<span class="stat-number">1856</span>
</div>
<p class="stat-label">Carreras Profesionales</p>
</div>
<div class="stat-card">
<p class="stat-label">Facultades</p>
<div class="stat-top">
<span class="stat-number">98%</span>
<span class="stat-number">20</span>
</div>
<p class="stat-label">Índice de Satisfacción</p>
</div>
<div class="stat-card">
<p class="stat-label">Escuelas Profesionales</p>
<div class="stat-top">
<span class="stat-number">15,000+</span>
<span class="stat-number">39</span>
</div>
<p class="stat-label">Estudiantes Activos</p>
</div>
<div class="stat-card">
<p class="stat-label">Estudiantes Matriculados</p>
<div class="stat-top">
<span class="stat-number">85%</span>
<span class="stat-number">19,160</span>
</div>
<p class="stat-label">Egresados Laborando</p>
</div>
</div>
</div>
@ -43,7 +47,6 @@
</template>
<style scoped>
.stats-section {
position: relative;
padding: 70px 0;
@ -53,7 +56,6 @@
overflow: hidden;
}
.stats-section::before {
content: "";
position: absolute;
@ -79,7 +81,6 @@
);
}
.stats-section::after {
content: "";
position: absolute;
@ -121,20 +122,17 @@
line-height: 1.45;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 18px;
}
.stat-card {
padding: 22px 18px;
border-radius: 16px;
text-align: center;
background: rgba(255, 255, 255, 0.10);
border: 1px solid rgba(255, 255, 255, 0.18);
backdrop-filter: blur(10px);
@ -156,7 +154,6 @@
gap: 6px;
}
.stat-number {
font-size: 2.8rem;
font-weight: 900;
@ -168,14 +165,12 @@
background-clip: text;
}
/* Texto */
.stat-label {
margin: 10px 0 0;
font-size: 1.02rem;
opacity: 0.92;
}
@media (max-width: 992px) {
.stats-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
@ -196,4 +191,4 @@
font-size: 2.4rem;
}
}
</style>
</style>

@ -8,7 +8,7 @@
<a-badge count="Modalidad" class="new-badge" />
</div>
<p class="section-subtitle">
Examen de admisión del Centro Preuniversitario (Capítulo VI Sub-capítulo I)
Examen de admisión del Centro Preuniversitario
</p>
</div>
@ -20,7 +20,7 @@
<h3>Examen de Admisión del Centro Preuniversitario</h3>
<p class="convocatoria-date">Convocatoria: una vez por semestre</p>
</div>
<a-tag class="status-tag" color="success">CEPREUNA</a-tag>
<!-- <a-tag class="status-tag" color="success">CEPREUNA</a-tag> -->
</div>
<a-alert
@ -40,19 +40,12 @@
</p>
</a-card>
<a-card class="soft-card" size="small">
<h4 class="subheading">Asignación de vacantes</h4>
<p class="text">
Las vacantes se cubren de acuerdo con el puntaje alcanzado, hasta completar el número ofertado
por los programas de estudio, según lo dispuesto por el reglamento.
</p>
</a-card>
<a-card class="soft-card" size="small">
<h4 class="subheading">Requisitos y documentos</h4>
<a-list size="small" :split="false" class="info-list">
<a-list-item>
Presentar la constancia de no adeudar al CEPREUNA con la debida anticipación.
Presentar la constancia de no adeudar al CEPREUNA y DNI vigente.
</a-list-item>
<a-list-item>
Presentar los documentos exigidos por el reglamento para esta modalidad (según requisitos generales).

@ -8,7 +8,7 @@
<a-badge count="Modalidades" class="new-badge" />
</div>
<p class="section-subtitle">
Examen convocado una vez al año con varias formas de postulación (Capítulo VI Sub-capítulo II)
Examen convocado una vez al año con varias formas de postulación
</p>
</div>
@ -20,7 +20,7 @@
<h3>Examen de Admisión Extraordinario</h3>
<p class="convocatoria-date">Convocatoria: una vez al año</p>
</div>
<a-tag class="status-tag" color="orange">Extraordinario</a-tag>
<!-- <a-tag class="status-tag" color="orange">Extraordinario</a-tag> -->
</div>
<a-card class="soft-card" size="small">
@ -31,13 +31,6 @@
</p>
</a-card>
<a-card class="soft-card" size="small">
<h4 class="subheading">Asignación de vacantes</h4>
<p class="text">
Las vacantes se cubren de acuerdo con el puntaje alcanzado hasta completar el número ofertado por los
programas de estudio, conforme a lo establecido en el reglamento.
</p>
</a-card>
<a-divider class="custom-divider" />

@ -20,8 +20,8 @@
<h3>Examen de Admisión General</h3>
<p class="convocatoria-date">Convocatoria: una vez por semestre</p>
</div>
<a-tag class="status-tag" color="blue">General</a-tag>
<!--
<a-tag class="status-tag" color="blue">General</a-tag> -->
</div>
<a-alert
@ -69,7 +69,7 @@
<script setup>
import NavbarModerno from '../../nabvar.vue'
import FooterModerno from '../../Footer.vue'
import Nabvar from '../../nabvar.vue';
</script>

@ -2,6 +2,7 @@
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
import WebPage from '../components/WebPage.vue'
import NotFound from '../views/NotFound.vue'
import { useUserStore } from '../store/user'
import { useAuthStore as usePostulanteStore } from '../store/postulanteStore'
@ -18,6 +19,12 @@ const routes = [
meta: { guest: true },
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound
},
{
path: '/resultados',
name: 'Resultados',

@ -0,0 +1,124 @@
<template>
<section class="modalidades-section">
<div class="section-container">
<div class="section-header">
<h1 class="section-title">404</h1>
<p class="section-subtitle">
La página que estás buscando no existe o fue movida.
</p>
</div>
<div class="modalidades-grid">
<a-card class="modalidad-card">
<div class="modalidad-icon bg-error">
<WarningOutlined />
</div>
<h4>Enlace incorrecto</h4>
<p>
Verifica que la dirección esté escrita correctamente
o regresa al inicio.
</p>
<a-button type="primary" @click="$router.push('/')">
Volver al Inicio
</a-button>
</a-card>
</div>
</div>
</section>
</template>
<script setup>
import { WarningOutlined } from "@ant-design/icons-vue"
</script>
<style scoped>
.modalidades-section {
padding: 100px 0;
background: #f8f9fa;
min-height: 100vh;
display: flex;
align-items: center;
}
.section-container {
max-width: 900px;
margin: 0 auto;
padding: 0 24px;
width: 100%;
}
.section-header {
text-align: center;
margin-bottom: 50px;
}
.section-title {
font-size: 5rem;
font-weight: 700;
color: #1a237e;
margin-bottom: 10px;
}
.section-subtitle {
font-size: 1.125rem;
color: #666;
}
.modalidades-grid {
display: flex;
justify-content: center;
}
.modalidad-card {
border: none;
border-radius: 12px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
text-align: center;
padding: 40px 32px;
transition: transform 0.3s ease;
max-width: 420px;
width: 100%;
}
.modalidad-card:hover {
transform: translateY(-4px);
}
.modalidad-icon {
width: 72px;
height: 72px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 24px;
color: white;
font-size: 32px;
}
.bg-error {
background: #ef4444;
}
.modalidad-card h4 {
margin: 0 0 12px;
color: #1a237e;
}
.modalidad-card p {
color: #666;
font-size: 0.95rem;
line-height: 1.6;
margin-bottom: 20px;
}
@media (max-width: 992px) {
.section-title {
font-size: 3rem;
}
}
</style>

@ -138,60 +138,69 @@
</div>
</a-col>
<!-- PANEL DERECHO: INFO (CORTO Y DINÁMICO) -->
<a-col :xs="24" :md="12" class="auth-pane auth-pane-info">
<div class="pane-inner pane-inner-info">
<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 iniciar tu inscripción al proceso de admisión."
: "Inicia sesión para continuar tu inscripción y consultar tu estado."
}}
</a-typography-text>
</div>
<div class="info-section">
<div class="info-section-title">
{{ isRegister ? "Al registrarte podrás" : "Al ingresar podrás" }}
</div>
<div class="info-list">
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Completar tu postulación</b> (modalidad, sede y programa).</span>
</div>
<div class="info-item">
<span class="info-bullet"></span>
<span><b>Subir requisitos</b> y revisar observaciones.</span>
<!-- PANEL DERECHO: INFO (CORTO Y DINÁMICO) -->
<a-col :xs="24" :md="12" class="auth-pane auth-pane-info">
<div class="pane-inner pane-inner-info">
<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-item" v-if="!isRegister">
<span class="info-bullet"></span>
<span><b>Ver comunicados y resultados</b> del proceso.</span>
<div class="info-section">
<div class="info-section-title">
{{ isRegister ? "Al registrarte podrás" : "Al ingresar podrás" }}
</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-item">
<span class="info-bullet"></span>
<span><b>Consultar tu estado</b> de inscripción/admisión.</span>
<div class="info-foot">
<a-typography-text type="secondary">
Plataforma oficial de admisión Soporte en horario institucional
</a-typography-text>
</div>
</div>
</div>
</a-col>
<div class="info-foot">
<a-typography-text type="secondary">
Soporte: Mesa de ayuda Atención en horario institucional
</a-typography-text>
</div>
</div>
</a-col>
</a-row>
</div>
</a-col>

@ -1,14 +1,20 @@
<template>
<div class="title">Mis procesos de admisión</div>
<a-card class="card" :bordered="true">
<template #title>
<div class="header">
<div class="headerLeft">
<div class="title">Mis procesos de admisión</div>
<div class="subtitle">Resultados registrados por DNI</div>
</div>
<div class="headerRight">
<a-button @click="obtenerProcesos" :loading="loading" class="btn" block>
<a-button
@click="obtenerProcesos"
:loading="loading"
class="btn"
type="primary"
>
Actualizar
</a-button>
</div>
@ -16,7 +22,8 @@
</template>
<a-spin :spinning="loading">
<!-- Top tools -->
<!-- Tools -->
<div class="tools">
<div class="counter">
<span class="counterLabel">Total</span>
@ -31,10 +38,9 @@
/>
</div>
<!-- Desktop/tablet: tabla -->
<div v-if="!isMobile" class="tableWrap">
<!-- ================= DESKTOP / TABLE ================= -->
<div class="tableWrap desktopOnly">
<a-table
class="table"
:dataSource="procesosFiltrados"
:columns="columns"
rowKey="id"
@ -42,6 +48,7 @@
:scroll="{ x: 900 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'nombre'">
<div class="nombre">{{ record.nombre || "-" }}</div>
<div class="meta">ID: {{ record.id }}</div>
@ -59,10 +66,11 @@
</template>
<template v-else-if="column.key === 'acciones'">
<a-space>
<a-button size="small" @click="verDetalle(record)">Ver detalle</a-button>
</a-space>
<a-button size="small" @click="verDetalle(record)">
Ver detalle
</a-button>
</template>
</template>
<template #emptyText>
@ -71,10 +79,14 @@
</a-table>
</div>
<!-- Mobile: cards -->
<div v-else class="cards">
<!-- ================= MOBILE / CARDS ================= -->
<div class="cards mobileOnly">
<template v-if="procesosFiltrados.length">
<div v-for="p in procesosFiltrados" :key="p.id" class="itemCard">
<div
v-for="p in procesosFiltrados"
:key="p.id"
class="itemCard"
>
<div class="itemTop">
<div class="itemTitle">{{ p.nombre || "-" }}</div>
<span class="statusPill" :class="statusClass(p.apto)">
@ -87,6 +99,7 @@
<div class="k">Puntaje</div>
<div class="v strong">{{ p.puntaje ?? "-" }}</div>
</div>
<div class="kv">
<div class="k">ID</div>
<div class="v">{{ p.id }}</div>
@ -94,7 +107,12 @@
</div>
<div class="itemActions">
<a-button type="primary" class="btnPrimary" block @click="verDetalle(p)">
<a-button
type="primary"
block
class="btnPrimary"
@click="verDetalle(p)"
>
Ver detalle
</a-button>
</div>
@ -103,12 +121,13 @@
<a-empty v-else description="No se encontraron procesos" />
</div>
</a-spin>
</a-card>
</template>
<script setup>
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
import { ref, computed, onMounted } from "vue";
import { message } from "ant-design-vue";
import api from "../../axiosPostulante";
@ -133,7 +152,6 @@ const obtenerProcesos = async () => {
message.error("No se pudieron obtener los procesos");
}
} catch (e) {
console.error(e);
message.error(e.response?.data?.message || "Error al cargar procesos");
} finally {
loading.value = false;
@ -141,58 +159,39 @@ const obtenerProcesos = async () => {
};
const aptoTexto = (apto) => {
if (apto === 1 || apto === true || apto === "1") return "APTO";
if (apto === 0 || apto === false || apto === "0") return "NO APTO";
return String(apto ?? "-").toUpperCase();
if (apto == 1) return "APTO";
if (apto == 0) return "NO APTO";
return "-";
};
/** ✅ Un solo color: no usamos verde/rojo; solo estilos neutros + primary sutil */
const statusClass = (apto) => {
if (apto === 1 || apto === true || apto === "1") return "ok";
if (apto === 0 || apto === false || apto === "0") return "bad";
if (apto == 1) return "ok";
if (apto == 0) return "bad";
return "neutral";
};
const procesosFiltrados = computed(() => {
const q = search.value.trim().toLowerCase();
if (!q) return procesos.value;
return procesos.value.filter((p) => String(p.nombre || "").toLowerCase().includes(q));
return procesos.value.filter((p) =>
String(p.nombre || "").toLowerCase().includes(q)
);
});
const verDetalle = (record) => {
message.info(`Proceso: ${record.nombre} | Puntaje: ${record.puntaje ?? "-"}`);
};
/* ✅ Responsive real: detecta móvil para cambiar a cards */
const isMobile = ref(false);
let mq = null;
function setMobile() {
isMobile.value = window.matchMedia("(max-width: 640px)").matches;
}
onMounted(() => {
obtenerProcesos();
mq = window.matchMedia("(max-width: 640px)");
setMobile();
// addEventListener es lo moderno; fallback por compatibilidad
if (mq.addEventListener) mq.addEventListener("change", setMobile);
else mq.addListener(setMobile);
});
onBeforeUnmount(() => {
if (!mq) return;
if (mq.removeEventListener) mq.removeEventListener("change", setMobile);
else mq.removeListener(setMobile);
});
</script>
<style scoped>
/* =========================
Base (formal 17+, sin degradados)
1 color acento: primary
========================= */
/* Card */
.card {
width: 100%;
max-width: 1100px;
margin: 16px auto;
border-radius: 14px;
@ -202,32 +201,22 @@ onBeforeUnmount(() => {
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 12px;
gap: 16px;
flex-wrap: wrap;
}
.headerLeft {
min-width: 240px;
}
.title {
margin: 0;
font-size: 1.85rem;
font-size: clamp(1.2rem, 4vw, 1.8rem);
font-weight: 700;
color: #0d1b52;
line-height: 1.15;
line-height: 1.2;
word-break: break-word;
}
.subtitle {
margin-top: 4px;
font-size: 12px;
color: var(--ant-colorTextSecondary, #6b7280);
}
.headerRight {
min-width: 180px;
display: flex;
justify-content: flex-end;
}
.btn {
border-radius: 10px;
color: #6b7280;
margin-top: 4px;
}
/* Tools */
@ -235,88 +224,71 @@ onBeforeUnmount(() => {
display: grid;
grid-template-columns: 220px 1fr;
gap: 12px;
align-items: center;
margin-bottom: 12px;
}
.counter {
border: 1px solid var(--ant-colorBorderSecondary, rgba(0,0,0,.08));
background: var(--ant-colorFillAlter, #fafafa);
background: #fafafa;
border-radius: 12px;
padding: 10px 12px;
display: flex;
justify-content: space-between;
align-items: baseline;
}
.counterLabel {
font-size: 12px;
color: var(--ant-colorTextSecondary, #6b7280);
font-weight: 700;
}
.counterValue {
font-size: 18px;
font-weight: 900;
color: var(--ant-colorTextHeading, #111827);
}
.search {
border-radius: 12px;
}
/* Table */
.tableWrap {
border-radius: 12px;
overflow: hidden;
}
.table :deep(.ant-table) {
border-radius: 12px;
overflow: hidden;
width: 100%;
overflow-x: auto;
}
.nombre {
font-weight: 800;
color: var(--ant-colorTextHeading, #111827);
}
.puntaje {
font-weight: 900;
color: var(--ant-colorPrimary, #1677ff); /* ✅ único acento */
color: #1677ff;
}
.meta {
font-size: 12px;
color: var(--ant-colorTextSecondary, #6b7280);
margin-top: 2px;
color: #6b7280;
}
/* Status pill (sin verde/rojo) */
/* Status */
.statusPill {
display: inline-flex;
align-items: center;
padding: 3px 10px;
padding: 4px 10px;
border-radius: 999px;
font-weight: 900;
font-size: 12px;
border: 1px solid var(--ant-colorBorderSecondary, rgba(0,0,0,.08));
background: var(--ant-colorFillAlter, #fafafa);
color: var(--ant-colorTextHeading, #111827);
font-weight: 900;
background: #f5f5f5;
}
.statusPill.ok {
border-color: rgba(22,119,255,.35);
background: rgba(22,119,255,.08);
background: rgba(22,119,255,.1);
border: 1px solid rgba(22,119,255,.3);
}
.statusPill.bad {
border-color: rgba(0,0,0,.10);
background: rgba(0,0,0,.04);
}
.statusPill.neutral {
opacity: .85;
}
/* Mobile cards */
.cards {
display: grid;
gap: 12px;
}
.itemCard {
border: 1px solid var(--ant-colorBorderSecondary, rgba(0,0,0,.08));
background: var(--ant-colorBgContainer, #fff);
border: 1px solid rgba(0,0,0,.08);
border-radius: 14px;
padding: 12px;
}
@ -324,68 +296,68 @@ onBeforeUnmount(() => {
.itemTop {
display: flex;
justify-content: space-between;
gap: 10px;
align-items: flex-start;
flex-wrap: wrap;
}
.itemTitle {
font-weight: 900;
color: var(--ant-colorTextHeading, #111827);
line-height: 1.2;
}
.itemGrid {
margin-top: 10px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 10px;
margin-top: 10px;
}
.kv {
border: 1px solid var(--ant-colorBorderSecondary, rgba(0,0,0,.06));
background: var(--ant-colorFillAlter, #fafafa);
background: #fafafa;
border-radius: 12px;
padding: 10px 12px;
padding: 10px;
}
.k {
font-size: 12px;
color: var(--ant-colorTextSecondary, #6b7280);
font-weight: 700;
color: #6b7280;
}
.v {
margin-top: 4px;
font-weight: 900;
color: var(--ant-colorTextHeading, #111827);
}
.v.strong {
color: var(--ant-colorPrimary, #1677ff);
color: #1677ff;
}
.itemActions {
margin-top: 12px;
}
.btnPrimary {
height: 42px;
border-radius: 12px;
font-weight: 900;
margin-top: 12px;
}
/* Responsive tools */
@media (max-width: 640px) {
.card {
margin: 0;
border-radius: 0;
}
.headerRight {
width: 100%;
min-width: 0;
}
/* Responsive */
.desktopOnly { display: block; }
.mobileOnly { display: none; }
@media (max-width: 768px) {
.tools {
grid-template-columns: 1fr;
}
.itemGrid {
grid-template-columns: 1fr;
.desktopOnly { display: none; }
.mobileOnly { display: block; }
.header {
flex-direction: column;
}
.title {
font-size: 1.3rem;
}
.card {
margin: 0;
border-radius: 0;
}
}
</style>

@ -1,9 +1,10 @@
<template>
<div class="title">Mis pagos realizados</div>
<a-card class="card" :bordered="true">
<template #title>
<div class="header">
<div class="headerLeft">
<div class="title">Mis pagos realizados</div>
<div class="subtitle">Historial de pagos registrados en el sistema</div>
</div>
@ -253,11 +254,11 @@ onBeforeUnmount(() => {
min-width: 240px;
}
.title {
margin: 0;
font-size: 1.85rem;
font-size: clamp(1.2rem, 4vw, 1.8rem);
font-weight: 700;
color: #0d1b52;
line-height: 1.15;
line-height: 1.2;
word-break: break-word;
}
.subtitle {
margin-top: 4px;
@ -466,6 +467,9 @@ onBeforeUnmount(() => {
width: 100%;
min-width: 0;
}
.title {
font-size: 1.3rem;
}
.tools {
grid-template-columns: 1fr;
}

@ -273,7 +273,7 @@ const handleLogout = async () => {
try {
await authStore.logout()
message.success('Sesión cerrada correctamente')
router.push('/login-postulante')
router.push('/')
} catch (error) {
message.error('Error al cerrar sesión')
}
@ -298,6 +298,7 @@ onUnmounted(() => {
})
</script>
<style scoped>

@ -5,7 +5,7 @@
<div class="head">
<div>
<div class="hTitle">Resultados del examen</div>
<div class="hSub">Resumen claro + detalle por curso. Todo responsivo.</div>
<div class="hSub">Resumen claro + detalle por curso.</div>
</div>
<!-- (opcional) acciones -->
@ -33,7 +33,7 @@
</div>
<div v-if="resultado.orden_merito != null" class="chipRank">
Orden: <b>#{{ resultado.orden_merito }}</b>
Puesto: <b>#{{ resultado.orden_merito }}</b>
</div>
</div>
@ -43,8 +43,8 @@
<div class="bigProgress">
<a-progress :percent="notaPercent" />
<div class="bigProgressMeta">
<span>Nota equivalente</span>
<b>{{ fmt2(resultado.calificacion_sobre_20) }}/20</b>
<!-- <span>Nota equivalente</span>
<b>{{ fmt2(resultado.calificacion_sobre_20) }}/20</b> -->
</div>
</div>
@ -135,7 +135,7 @@
<span class="courseDot"></span>
<div>
<div class="courseName">{{ record.curso }}</div>
<div class="courseMeta">Ratio: {{ record.ratio }}%</div>
<div class="courseMeta">{{ record.ratio }}%</div>
</div>
</div>
</template>

@ -3,6 +3,9 @@ import { ref, computed, reactive, onMounted, watch } from "vue";
import { useRouter } from "vue-router";
import { useExamenStore } from "../../store/examen.store";
import { message } from "ant-design-vue";
import voucherCaja from "../../assets/images/caja.png";
import voucherPagalo from "../../assets/images/pagalo.png";
import voucherBn from "../../assets/images/boletabn.jpg";
const router = useRouter();
const examenStore = useExamenStore();
@ -50,11 +53,12 @@ const secuenciaTitle = computed(() => {
const voucherSrc = computed(() => {
const map = {
caja: "/voucher-caja.png",
pagalo: "/voucher-pagalo.png",
bn: "/voucher-bn.png",
caja: voucherCaja,
pagalo: voucherPagalo,
bn: voucherBn,
};
return map[secuenciaTipo.value] || "/voucher-bn.png";
return map[secuenciaTipo.value] || "";
});
const habilitacionTexto = computed(() =>
@ -155,27 +159,7 @@ const procesoRequierePago = computed(() => {
return normalizeRequierePago(proceso.requiere_pago);
});
/** Si ya tienes examen asignado */
const examenRequierePago = computed(() => {
const v = examenStore.examenActual?.proceso?.requiere_pago;
return normalizeRequierePago(v);
});
/** ✅ Solo para mostrar un texto informativo */
const requierePagoInfo = computed(() => procesoRequierePago.value || examenRequierePago.value);
/** ✅ Contexto para jóvenes (texto claro y tranquilizador) */
const textoReferencial = computed(() => ({
message: "✅ Test referencial (no afecta tu postulación)",
description:
"Este test solo te ayuda a medir tu nivel y practicar. No cambia tu puntaje ni tu postulación oficial.",
}));
const textoCarpeta = computed(() => ({
message: "💳 Secuencia: también sirve la de tu Carpeta de Postulante",
description:
"Si tu proceso pide secuencia, puedes usar la misma del pago de la Carpeta de Postulante. No pagas nada extra por este test.",
}));
/** Validación (condicional) */
const rules = {
@ -362,6 +346,7 @@ onMounted(async () => {
<div class="muted">
Este test te ayuda a medir tu nivel y practicar. No cambia tu puntaje ni tu postulación oficial.
</div>
</div>
</a-space>
</a-card>
@ -370,15 +355,15 @@ onMounted(async () => {
<div class="heroFacts hide-mobile">
<div class="fact">
<div class="factK">Proceso</div>
<div class="factK">Nombre:</div>
<div class="factV">{{ procesoNombre }}</div>
</div>
<div class="fact">
<div class="factK">Área</div>
<div class="factK">Área:</div>
<div class="factV">{{ areaNombre }}</div>
</div>
<div class="fact">
<div class="factK">Intentos</div>
<div class="factK">Intentos:</div>
<div class="factV">{{ intentosActuales }} / {{ intentosMax }}</div>
</div>
</div>
@ -386,12 +371,15 @@ onMounted(async () => {
<!-- BOTONES DE BANCO -->
<div class="bankActions">
<div class="bankHead">
<div class="bankTitle">Ver ejemplos de Secuencia</div>
<div class="bankTitle">Requisito de acceso</div>
<div class="bankSub">
Te sirve si el proceso te pide secuencia (puede ser la de la Carpeta de Postulante).
Este test es completamente GRATUITO.
No se realiza ningún pago adicional.
Únicamente debes ingresar el número de secuencia del pago de tu Carpeta de Postulante, el cual ya realizaste previamente para el proceso de admisión.
</div>
</div>
<div style="font-weight: 700; color:#1a237e;">Ver Secuencia</div>
<a-space wrap>
<a-button class="bankBtn" @click="openSecuencia('caja')">Caja</a-button>
<a-button class="bankBtn" @click="openSecuencia('pagalo')">pagalo.pe</a-button>

Loading…
Cancel
Save