215 lines
6.7 KiB
Vue

<script setup>
import { ref, computed, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { api, useForm } from '@Services/Api';
import { apiTo, viewTo } from './Module';
import GoogleIcon from '@Shared/GoogleIcon.vue';
import Input from '@Holos/Form/Input.vue';
import PageHeader from '@Holos/PageHeader.vue';
import IconButton from '@Holos/Button/Icon.vue';
/** Definiciones */
const router = useRouter();
const vroute = useRoute();
/** Propiedades */
const form = useForm({
users: [],
start_date: '',
end_date: '',
exam_date: '',
});
const course = ref(null);
const users = ref([]);
// Computed para contar usuarios seleccionados
const selectedUsersCount = computed(() => {
return users.value.filter(u => u.selected).length;
});
// Funciones
const toggleUser = (user) => {
user.selected = !user.selected;
};
const selectAllUsers = () => {
const allSelected = users.value.every(u => u.selected);
users.value.forEach(u => u.selected = !allSelected);
};
// Función para calcular la fecha final del curso
const calculateEndDate = () => {
if (form.start_date && course.value?.duration) {
const startDate = new Date(form.start_date);
const duration = parseInt(course.value.duration);
// Agregar la duración en días a la fecha de inicio
const endDate = new Date(startDate);
endDate.setDate(startDate.getDate() + duration);
// Formatear la fecha como YYYY-MM-DD para el input
const formattedDate = endDate.toISOString().split('T')[0];
form.end_date = formattedDate;
}
};
// Watcher para calcular automáticamente la fecha final cuando cambie la fecha de inicio
watch(() => form.start_date, () => {
calculateEndDate();
});
const submit = () => {
form.transform(data => ({
...data,
users: users.value.filter(u => u.selected).map(u => u.id)
})).post(apiTo('assign-course', { course: vroute.params.id }), {
onSuccess: () => {
Notify.success(Lang('register.assign.onSuccess'))
router.push(viewTo({ name: 'index' }));
}
});
};
/** Ciclos */
onMounted(() => {
api.get(apiTo('show', { course: vroute.params.id }), {
onSuccess: (r) => {
course.value = r.course
users.value = r.course.users ?? []
}
});
});
</script>
<template>
<PageHeader
title="Asignación de Cursos a Personal"
>
<RouterLink :to="viewTo({ name: 'index' })">
<IconButton
class="text-white"
icon="arrow_back"
:title="$t('return')"
filled
/>
</RouterLink>
</PageHeader>
<div class="w-full pb-2">
<p class="text-justify text-sm">Asigna cursos aprobados al personal seleccionado</p>
</div>
<!-- Card principal -->
<section class="mt-6 bg-white rounded-lg shadow-sm p-6 dark:bg-primary-d dark:border-primary/20 dark:text-primary-dt">
<!-- Información del Curso -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 dark:text-primary-dt mb-2">
Curso Seleccionado
</label>
<div v-if="course" class="w-full px-4 py-3 bg-gray-50 border border-gray-300 rounded-lg dark:bg-primary-d dark:border-primary/20">
<div class="font-medium text-gray-900 dark:text-primary-dt">{{ course.name }}</div>
<div class="text-sm text-gray-500 dark:text-primary-dt/70">
{{ course.department?.name }} {{ course.cost }} {{ course.cost_currency }}
</div>
<div v-if="course.description" class="text-sm text-gray-600 dark:text-primary-dt/80 mt-1">
{{ course.description }}
</div>
</div>
<div v-else class="w-full px-4 py-3 bg-gray-50 border border-gray-300 rounded-lg dark:bg-primary-d dark:border-primary/20">
<div class="text-gray-500 dark:text-primary-dt/70">Cargando información del curso...</div>
</div>
</div>
<!-- Asignación de Usuarios -->
<div class="mb-6">
<div class="flex items-center justify-between mb-3">
<label class="block text-sm font-medium text-gray-700 dark:text-primary-dt">
Asignar a usuarios
</label>
<button
type="button"
@click="selectAllUsers"
class="text-sm text-[#2563eb] hover:text-[#1e40af] font-medium"
>
{{ users.every(u => u.selected) ? 'Deseleccionar todo' : 'Seleccionar todo' }}
</button>
</div>
<div class="border border-gray-300 rounded-lg p-4 max-h-48 overflow-y-auto dark:bg-primary-d dark:border-primary/20">
<div class="space-y-2">
<div
v-for="user in users"
:key="user.id"
@click="toggleUser(user)"
class="flex items-center p-2 rounded-lg cursor-pointer hover:bg-gray-50 dark:hover:bg-primary/10 transition-colors"
>
<div class="flex items-center h-5">
<input
:checked="user.selected"
type="checkbox"
class="w-4 h-4 text-[#2563eb] bg-gray-100 border-gray-300 rounded focus:ring-[#2563eb] dark:focus:ring-[#2563eb] dark:ring-offset-gray-800 focus:ring-2 dark:bg-primary-d dark:border-primary/20"
@click.stop
@change="toggleUser(user)"
>
</div>
<div class="ml-3 text-sm">
<label class="font-medium text-gray-900 dark:text-primary-dt cursor-pointer">
{{ user.name }} {{ user.paternal }} {{ user.maternal }}
</label>
<div class="text-xs text-gray-500 dark:text-primary-dt/70">
{{ user.email }}
</div>
</div>
</div>
</div>
</div>
<div class="mt-2 text-sm text-gray-500 dark:text-primary-dt/70">
{{ selectedUsersCount }} usuario(s) seleccionado(s)
</div>
</div>
<!-- Fechas -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<Input
v-model="form.start_date"
id="start_date"
title="dates.start"
type="date"
required
/>
<Input
v-model="form.end_date"
id="end_date"
title="dates.end"
type="date"
required
/>
<Input
v-model="form.exam_date"
id="exam_date"
title="exam_date"
type="date"
/>
</div>
<!-- Botones de Acción -->
<div class="flex items-center justify-end gap-3 pt-4 border-t border-gray-100 dark:border-primary/20">
<button
@click="submit"
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[#7c3aed] hover:bg-[#6d28d9] text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-[#7c3aed] focus:ring-offset-2"
>
<GoogleIcon class="text-white text-xl" name="notifications" />
Notificar
</button>
</div>
</section>
</template>