188 lines
7.6 KiB
Vue
188 lines
7.6 KiB
Vue
<script setup>
|
|
import { ref } from 'vue';
|
|
import GoogleIcon from '@Shared/GoogleIcon.vue';
|
|
|
|
// Datos de ejemplo de los cursos
|
|
const courses = ref([
|
|
{
|
|
id: 1,
|
|
area: 'Desarrollo',
|
|
courseName: 'React Avanzado y GraphQL',
|
|
unitCost: 499.00,
|
|
url: 'https://example.com/react-avanzado',
|
|
status: 'pending'
|
|
},
|
|
{
|
|
id: 2,
|
|
area: 'Seguridad',
|
|
courseName: 'Certified Ethical Hacker (CEH)',
|
|
unitCost: 1199.00,
|
|
url: 'https://example.com/ceh',
|
|
status: 'pending'
|
|
},
|
|
{
|
|
id: 3,
|
|
area: 'Redes',
|
|
courseName: 'Cisco CCNA 200-301',
|
|
unitCost: 300.00,
|
|
url: 'https://example.com/ccna',
|
|
status: 'pending'
|
|
}
|
|
]);
|
|
|
|
// Funciones para las acciones
|
|
const viewCourse = (course) => {
|
|
console.log('Ver curso:', course.courseName);
|
|
// Aquí puedes implementar la lógica para ver el curso
|
|
};
|
|
|
|
const approveCourse = (course) => {
|
|
console.log('Aprobar curso:', course.courseName);
|
|
course.status = 'approved';
|
|
// Aquí puedes implementar la lógica para aprobar el curso
|
|
};
|
|
|
|
const rejectCourse = (course) => {
|
|
console.log('Rechazar curso:', course.courseName);
|
|
course.status = 'rejected';
|
|
// Aquí puedes implementar la lógica para rechazar el curso
|
|
};
|
|
|
|
const formatCurrency = (amount) => {
|
|
return new Intl.NumberFormat('es-MX', {
|
|
style: 'currency',
|
|
currency: 'USD'
|
|
}).format(amount);
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="p-6 max-w-auto mx-auto">
|
|
<!-- Header -->
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div>
|
|
<h1 class="text-4xl font-extrabold text-gray-900 dark:text-primary-dt">Gestión de Solicitudes de Capacitación</h1>
|
|
<p class="mt-1 text-sm text-gray-500 dark:text-primary-dt/70">Administra y aprueba las solicitudes de cursos de capacitación</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card principal con tabla -->
|
|
<section class="mt-6 bg-white rounded-lg shadow-sm p-6 dark:bg-primary-d dark:border-primary/20 dark:text-primary-dt">
|
|
<!-- Tabla de cursos -->
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead>
|
|
<tr class="border-b border-gray-100 dark:border-primary/20">
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">Área</th>
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">Nombre del Curso</th>
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">Costo Unitario</th>
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">Url</th>
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">Opciones</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr
|
|
v-for="course in courses"
|
|
:key="course.id"
|
|
class="border-b border-gray-50 dark:border-primary/10 hover:bg-gray-50 dark:hover:bg-primary/5"
|
|
>
|
|
<!-- Área -->
|
|
<td class="py-4 px-4">
|
|
<span class="inline-block bg-blue-100 text-blue-800 text-sm px-3 py-1 rounded-full dark:bg-blue-900/30 dark:text-blue-300">
|
|
{{ course.area }}
|
|
</span>
|
|
</td>
|
|
|
|
<!-- Nombre del curso -->
|
|
<td class="py-4 px-4">
|
|
<div class="font-medium text-gray-900 dark:text-primary-dt">
|
|
{{ course.courseName }}
|
|
</div>
|
|
</td>
|
|
|
|
<!-- Costo unitario -->
|
|
<td class="py-4 px-4">
|
|
<div class="text-lg font-bold text-[#2563eb] dark:text-primary-dt">
|
|
{{ formatCurrency(course.unitCost) }}
|
|
</div>
|
|
</td>
|
|
|
|
<!-- URL -->
|
|
<td class="py-4 px-4">
|
|
<a
|
|
:href="course.url"
|
|
target="_blank"
|
|
class="text-blue-600 hover:text-blue-800 underline text-sm dark:text-blue-400 dark:hover:text-blue-300"
|
|
>
|
|
Ver curso
|
|
</a>
|
|
</td>
|
|
|
|
<!-- Opciones -->
|
|
<td class="py-4 px-4">
|
|
<div class="flex items-center gap-2">
|
|
<!-- Botón Ver -->
|
|
<button
|
|
@click="viewCourse(course)"
|
|
class="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors dark:text-primary-dt/70 dark:hover:text-primary-dt dark:hover:bg-primary/10"
|
|
title="Ver detalles"
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Botón Aprobar -->
|
|
<button
|
|
@click="approveCourse(course)"
|
|
class="p-2 text-gray-400 hover:text-green-600 hover:bg-green-50 rounded-lg transition-colors dark:text-primary-dt/70 dark:hover:text-green-400 dark:hover:bg-green-900/20"
|
|
title="Aprobar curso"
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Botón Rechazar -->
|
|
<button
|
|
@click="rejectCourse(course)"
|
|
class="p-2 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors dark:text-primary-dt/70 dark:hover:text-red-400 dark:hover:bg-red-900/20"
|
|
title="Rechazar curso"
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Footer con estadísticas -->
|
|
<div class="mt-6 border-t border-gray-100 pt-4 flex items-center justify-between dark:border-primary/20">
|
|
<div class="text-sm text-gray-500 dark:text-primary-dt/70">
|
|
Mostrando {{ courses.length }} solicitudes
|
|
</div>
|
|
|
|
<div class="flex items-center gap-4">
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<span class="w-3 h-3 bg-yellow-400 rounded-full"></span>
|
|
<span class="text-gray-600 dark:text-primary-dt/70">Pendientes: {{ courses.filter(c => c.status === 'pending').length }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<span class="w-3 h-3 bg-green-400 rounded-full"></span>
|
|
<span class="text-gray-600 dark:text-primary-dt/70">Aprobadas: {{ courses.filter(c => c.status === 'approved').length }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<span class="w-3 h-3 bg-red-400 rounded-full"></span>
|
|
<span class="text-gray-600 dark:text-primary-dt/70">Rechazadas: {{ courses.filter(c => c.status === 'rejected').length }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</template>
|