eliminar empresa
This commit is contained in:
parent
0b37323652
commit
fefb045108
@ -42,9 +42,9 @@ onMounted(() => {
|
||||
<template #leftSidebar>
|
||||
<Section name="Principal">
|
||||
<Link
|
||||
icon="grid_view"
|
||||
name="Dashboard"
|
||||
to="admin.dashboard.index"
|
||||
icon="grid_view"
|
||||
name="Dashboard"
|
||||
to="admin.dashboard.index"
|
||||
/>
|
||||
<DropDown
|
||||
icon="people"
|
||||
@ -52,21 +52,21 @@ onMounted(() => {
|
||||
to="admin.users.index"
|
||||
:collapsed="true"
|
||||
>
|
||||
<Link
|
||||
icon="school"
|
||||
name="Historial Académico"
|
||||
to="admin.users.academic.index"
|
||||
/>
|
||||
<Link
|
||||
icon="security"
|
||||
name="Seguridad y Salud"
|
||||
to="admin.users.security"
|
||||
/>
|
||||
<Link
|
||||
icon="info"
|
||||
name="Información Adicional"
|
||||
to="admin.users.additional"
|
||||
/>
|
||||
<Link
|
||||
icon="school"
|
||||
name="Historial Académico"
|
||||
to="admin.users.academic.index"
|
||||
/>
|
||||
<Link
|
||||
icon="security"
|
||||
name="Seguridad y Salud"
|
||||
to="admin.users.security"
|
||||
/>
|
||||
<Link
|
||||
icon="info"
|
||||
name="Información Adicional"
|
||||
to="admin.users.additional"
|
||||
/>
|
||||
</DropDown>
|
||||
</Section>
|
||||
<Section name="Vacaciones">
|
||||
@ -83,6 +83,11 @@ onMounted(() => {
|
||||
to="admin.courses.index"
|
||||
:collapsed="true"
|
||||
>
|
||||
<Link
|
||||
icon="grid_view"
|
||||
name="Solicitud de Cursos"
|
||||
to="admin.courses.request"
|
||||
/>
|
||||
<Link
|
||||
icon="grid_view"
|
||||
name="Calendario de Cursos"
|
||||
|
||||
@ -23,34 +23,13 @@ const form = useForm({
|
||||
participants_count: '',
|
||||
cost: '',
|
||||
observations: '',
|
||||
company_id: '',
|
||||
petty_cash_id: '',
|
||||
files: null,
|
||||
});
|
||||
|
||||
const companies = ref([]);
|
||||
const pettyCashes = ref([]);
|
||||
const availableBudget = ref('');
|
||||
|
||||
// Función para cargar cajas chicas por empresa
|
||||
const loadPettyCashesByCompany = () => {
|
||||
if (form.company_id?.id) {
|
||||
api.catalog({
|
||||
'pettyCash:byCompany': form.company_id.id
|
||||
}, {
|
||||
onSuccess: (r) => {
|
||||
pettyCashes.value = r['pettyCash:byCompany'] ?? [];
|
||||
// Limpiar selección de caja chica al cambiar empresa
|
||||
form.petty_cash_id = '';
|
||||
availableBudget.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Watch para cargar cajas chicas cuando cambie la empresa
|
||||
watch(() => form.company_id, loadPettyCashesByCompany, { deep: true });
|
||||
|
||||
// Watch para actualizar el presupuesto disponible cuando cambie la caja chica
|
||||
watch(() => form.petty_cash_id, (newValue) => {
|
||||
availableBudget.value = newValue?.available_budget ?? 0;
|
||||
@ -83,7 +62,6 @@ const removeFile = () => {
|
||||
function submit() {
|
||||
form.transform(data => ({
|
||||
...data,
|
||||
company_id: data.company_id?.id,
|
||||
petty_cash_id: data.petty_cash_id?.id
|
||||
})).post(apiTo('store-expense-justification'), {
|
||||
onSuccess: () => {
|
||||
@ -96,9 +74,9 @@ function submit() {
|
||||
/** Ciclos */
|
||||
onMounted(() => {
|
||||
api.catalog({
|
||||
'company:all': null
|
||||
'pettyCash:all': null
|
||||
}, {
|
||||
onSuccess: (r) => companies.value = r['company:all'] ?? []
|
||||
onSuccess: (r) => pettyCashes.value = r['pettyCash:all'] ?? []
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@ -157,17 +135,8 @@ onMounted(() => {
|
||||
/>
|
||||
|
||||
<!-- Detalles Financieros y Participantes -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
|
||||
<Selectable
|
||||
v-model="form.company_id"
|
||||
id="company_id"
|
||||
title="Empresa"
|
||||
:onError="form.errors.company_id"
|
||||
:options="companies"
|
||||
required
|
||||
/>
|
||||
|
||||
<Input
|
||||
v-model.number="form.participants_count"
|
||||
id="participants_count"
|
||||
|
||||
@ -15,32 +15,17 @@ const router = useRouter();
|
||||
const form = useForm({
|
||||
name: '',
|
||||
description: '',
|
||||
company_id: '',
|
||||
});
|
||||
|
||||
const companies = ref([]);
|
||||
|
||||
/** Métodos */
|
||||
function submit() {
|
||||
form.transform(data => ({
|
||||
...data,
|
||||
company_id: form.company_id?.id
|
||||
})).post(apiTo('store'), {
|
||||
form.post(apiTo('store'), {
|
||||
onSuccess: () => {
|
||||
Notify.success(Lang('register.create.onSuccess'))
|
||||
router.push(viewTo({ name: 'index' }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Ciclos */
|
||||
onMounted(() => {
|
||||
api.catalog({
|
||||
'company:all': null
|
||||
}, {
|
||||
onSuccess: (r) => companies.value = r['company:all'] ?? []
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -59,7 +44,6 @@ onMounted(() => {
|
||||
<Form
|
||||
action="create"
|
||||
:form="form"
|
||||
:companies="companies"
|
||||
@submit="submit"
|
||||
/>
|
||||
</template>
|
||||
@ -17,17 +17,11 @@ const form = useForm({
|
||||
id: null,
|
||||
name: '',
|
||||
description: '',
|
||||
company_id: '',
|
||||
});
|
||||
|
||||
const companies = ref([]);
|
||||
|
||||
/** Métodos */
|
||||
function submit() {
|
||||
form.transform(data => ({
|
||||
...data,
|
||||
company_id: data.company_id?.id
|
||||
})).put(apiTo('update', { petty_cash: form.id }), {
|
||||
form.put(apiTo('update', { petty_cash: form.id }), {
|
||||
onSuccess: () => {
|
||||
Notify.success(Lang('register.edit.onSuccess'))
|
||||
router.push(viewTo({ name: 'index' }));
|
||||
@ -39,17 +33,8 @@ onMounted(() => {
|
||||
api.get(apiTo('show', { petty_cash: vroute.params.id }), {
|
||||
onSuccess: (r) => {
|
||||
form.fill(r.petty_cash)
|
||||
form.company_id = r.petty_cash.company
|
||||
}
|
||||
});
|
||||
|
||||
api.catalog({
|
||||
'company:all': null,
|
||||
}, {
|
||||
onSuccess: (r) => {
|
||||
companies.value = r['company:all'] ?? [];
|
||||
}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -67,7 +52,6 @@ onMounted(() => {
|
||||
<Form
|
||||
action="edit"
|
||||
:form="form"
|
||||
:companies="companies"
|
||||
@submit="submit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@ -4,7 +4,6 @@ import { transl } from './Module';
|
||||
import PrimaryButton from '@Holos/Button/Primary.vue';
|
||||
import Input from '@Holos/Form/Input.vue';
|
||||
import Textarea from '@Holos/Form/Textarea.vue';
|
||||
import Selectable from '@Holos/Form/Selectable.vue';
|
||||
|
||||
/** Eventos */
|
||||
const emit = defineEmits([
|
||||
@ -35,23 +34,13 @@ function submit() {
|
||||
<form @submit.prevent="submit" class="space-y-6">
|
||||
|
||||
<!-- Campos del formulario -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<Input
|
||||
v-model="form.name"
|
||||
id="name"
|
||||
title="name"
|
||||
:onError="form.errors.name"
|
||||
required
|
||||
/>
|
||||
<Selectable
|
||||
v-model="form.company_id"
|
||||
id="company_id"
|
||||
title="company"
|
||||
:onError="form.errors.company_id"
|
||||
:options="companies"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
v-model="form.name"
|
||||
id="name"
|
||||
title="name"
|
||||
:onError="form.errors.name"
|
||||
required
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
v-model="form.description"
|
||||
|
||||
@ -62,7 +62,6 @@ onMounted(() => {
|
||||
<th v-text="$t('name')" />
|
||||
<th v-text="$t('description')" />
|
||||
<th v-text="$t('available_budget')" />
|
||||
<th v-text="$t('company')" />
|
||||
<th class="w-32 text-center" v-text="$t('actions')" />
|
||||
</template>
|
||||
|
||||
@ -71,7 +70,6 @@ onMounted(() => {
|
||||
<td>{{ model.name }}</td>
|
||||
<td>{{ model.description ?? '-' }}</td>
|
||||
<td>${{ model.available_budget ?? 0 }}</td>
|
||||
<td>{{ model.company?.name }}</td>
|
||||
<td>
|
||||
<div class="table-actions">
|
||||
<IconButton icon="visibility" :title="$t('crud.show')" @click="showModal.open(model)"
|
||||
|
||||
@ -42,17 +42,8 @@ defineExpose({
|
||||
<div v-if="model">
|
||||
<Header
|
||||
:title="model.name"
|
||||
:subtitle="model.company?.name ?? '-'"
|
||||
>
|
||||
<div class="flex w-full flex-col">
|
||||
<div class="flex w-full justify-center items-center">
|
||||
<GoogleIcon
|
||||
class="text-6xl text-primary"
|
||||
name="account_balance_wallet"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Header>
|
||||
:subtitle="model.description"
|
||||
/>
|
||||
<div class="flex w-full p-4">
|
||||
<GoogleIcon
|
||||
class="text-xl text-success"
|
||||
@ -70,10 +61,6 @@ defineExpose({
|
||||
<b>{{ $t('description') }}: </b>
|
||||
{{ model.description }}
|
||||
</p>
|
||||
<p>
|
||||
<b>{{ $t('company') }}: </b>
|
||||
{{ model.company?.name ?? '-' }}
|
||||
</p>
|
||||
<p>
|
||||
<b>{{ $t('available_budget') }}: </b>
|
||||
${{ model.available_budget ?? 0 }}
|
||||
|
||||
268
src/pages/Courses/Admin/Request.vue
Normal file
268
src/pages/Courses/Admin/Request.vue
Normal file
@ -0,0 +1,268 @@
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { api, useForm } from '@Services/Api';
|
||||
import { apiTo, viewTo } from './Module';
|
||||
|
||||
import GoogleIcon from '@Shared/GoogleIcon.vue';
|
||||
import PageHeader from '@Holos/PageHeader.vue';
|
||||
import IconButton from '@Holos/Button/Icon.vue';
|
||||
import Input from '@Holos/Form/Input.vue';
|
||||
import Textarea from '@Holos/Form/Textarea.vue';
|
||||
import Selectable from '@Holos/Form/Selectable.vue';
|
||||
import PrimaryButton from '@Holos/Button/Primary.vue';
|
||||
|
||||
/** Definiciones */
|
||||
const router = useRouter();
|
||||
|
||||
/** Propiedades */
|
||||
const form = useForm({
|
||||
name: '',
|
||||
cost: '',
|
||||
cost_currency: '',
|
||||
description: '',
|
||||
certification_name: '',
|
||||
certification_type: '',
|
||||
duration: '',
|
||||
url: '',
|
||||
department_id: '',
|
||||
users: []
|
||||
});
|
||||
|
||||
// Lista de departamentos y usuarios
|
||||
const departments = ref([]);
|
||||
const users = ref([]);
|
||||
const currencies = ref([]);
|
||||
|
||||
// Computed para contar usuarios seleccionados
|
||||
const selectedUsersCount = computed(() => {
|
||||
return users.value.filter(u => u.selected).length;
|
||||
});
|
||||
|
||||
/** Métodos */
|
||||
function submit() {
|
||||
form.transform(data => ({
|
||||
...data,
|
||||
department_id: form.department_id?.id,
|
||||
cost_currency: form.cost_currency?.id,
|
||||
users: users.value.filter(u => u.selected).map(u => u.id)
|
||||
})).post(apiTo('store'), {
|
||||
onSuccess: () => {
|
||||
Notify.success(Lang('register.create.onSuccess'))
|
||||
router.push(viewTo({ name: 'index' }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Función para cargar usuarios cuando se seleccione un departamento
|
||||
const loadUsersByDepartment = () => {
|
||||
api.catalog({
|
||||
'user:byDepartment': form.department_id?.id
|
||||
}, {
|
||||
onSuccess: (r) => users.value = r['user:byDepartment'] ?? []
|
||||
});
|
||||
};
|
||||
|
||||
// Funciones para manejar selección de usuarios
|
||||
const toggleUser = (user) => {
|
||||
user.selected = !user.selected;
|
||||
};
|
||||
|
||||
const selectAllUsers = () => {
|
||||
const allSelected = users.value.every(u => u.selected);
|
||||
users.value.forEach(u => u.selected = !allSelected);
|
||||
};
|
||||
|
||||
// Watcher para cargar usuarios automáticamente cuando cambie el departamento
|
||||
watch(() => form.department_id, () => {
|
||||
loadUsersByDepartment();
|
||||
});
|
||||
|
||||
/** Ciclos */
|
||||
onMounted(() => {
|
||||
api.catalog({
|
||||
'department:all': null,
|
||||
'currency:all': null
|
||||
}, {
|
||||
onSuccess: (r) => {
|
||||
departments.value = r['department:all'] ?? []
|
||||
currencies.value = r['currency:all'] ?? []
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageHeader
|
||||
title="Solicitud de Nuevo Curso"
|
||||
>
|
||||
<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">Completa la información para solicitar un nuevo curso de capacitación</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">
|
||||
|
||||
<!-- Formulario -->
|
||||
<form @submit.prevent="submit" class="space-y-6">
|
||||
|
||||
<!-- Campos del formulario en dos columnas -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
|
||||
<!-- Columna izquierda -->
|
||||
<div class="space-y-6">
|
||||
<Input
|
||||
v-model="form.name"
|
||||
id="name"
|
||||
title="name"
|
||||
:onError="form.errors.name"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
v-model="form.cost"
|
||||
id="cost"
|
||||
title="cost"
|
||||
:onError="form.errors.cost"
|
||||
type="number"
|
||||
min="0"
|
||||
step="0.01"
|
||||
required
|
||||
/>
|
||||
<Selectable
|
||||
v-model="form.cost_currency"
|
||||
id="cost_currency"
|
||||
title="currency"
|
||||
:onError="form.errors.cost_currency"
|
||||
:options="currencies"
|
||||
/>
|
||||
<Textarea
|
||||
v-model="form.description"
|
||||
id="description"
|
||||
title="description"
|
||||
:onError="form.errors.description"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
v-model="form.certification_name"
|
||||
id="certification_name"
|
||||
title="certification_name"
|
||||
:onError="form.errors.certification_name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Columna derecha -->
|
||||
<div class="space-y-6">
|
||||
<Selectable
|
||||
v-model="form.department_id"
|
||||
id="department_id"
|
||||
title="department"
|
||||
:onError="form.errors.department_id"
|
||||
:options="departments"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
v-model="form.certification_type"
|
||||
id="certification_type"
|
||||
title="certification_type"
|
||||
:onError="form.errors.certification_type"
|
||||
/>
|
||||
<Input
|
||||
v-model="form.duration"
|
||||
id="duration"
|
||||
title="duration"
|
||||
:onError="form.errors.duration"
|
||||
type="number"
|
||||
min="1"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
v-model="form.url"
|
||||
id="url"
|
||||
title="url"
|
||||
:onError="form.errors.url"
|
||||
type="url"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sección de Personal a Capacitar -->
|
||||
<div class="mt-8">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-primary-dt">
|
||||
Personal a capacitar
|
||||
</label>
|
||||
<button
|
||||
v-if="users.length > 0"
|
||||
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 v-if="users.length > 0" 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 v-else class="border border-gray-300 rounded-lg p-4 dark:bg-primary-d dark:border-primary/20">
|
||||
<div class="text-center text-gray-500 dark:text-primary-dt/70">
|
||||
<GoogleIcon class="w-8 h-8 mx-auto mb-2 text-gray-400" name="people" />
|
||||
<p>Selecciona un departamento para ver el personal disponible</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="users.length > 0" class="mt-2 text-sm text-gray-500 dark:text-primary-dt/70">
|
||||
{{ selectedUsersCount }} usuario(s) seleccionado(s)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Botón de Enviar -->
|
||||
<div class="flex justify-end pt-6 border-t border-gray-100 dark:border-primary/20">
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
:processing="form.processing"
|
||||
>
|
||||
Enviar Solicitud
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</section>
|
||||
</template>
|
||||
@ -194,6 +194,11 @@ const router = createRouter({
|
||||
name: 'admin.courses.index',
|
||||
component: () => import('@Pages/Courses/Admin/Index.vue'),
|
||||
},
|
||||
{
|
||||
path: 'request',
|
||||
name: 'admin.courses.request',
|
||||
component: () => import('@Pages/Courses/Admin/Request.vue'),
|
||||
},
|
||||
{
|
||||
path: ':id/assignamment',
|
||||
name: 'admin.courses.assignamment',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user