actualizada API empleados, conectando UI con API
This commit is contained in:
@@ -1,142 +1,126 @@
|
||||
import express from 'express';
|
||||
const router = express.Router();
|
||||
import { PrismaClient } from '../../prisma/generated/client/index.js';
|
||||
const prisma = new PrismaClient();
|
||||
import express from 'express'
|
||||
import { PrismaClient } from '../../prisma/generated/client/index.js'
|
||||
|
||||
// GET all empleados
|
||||
router.get('/', async (req, res) => {
|
||||
const router = express.Router()
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
// ⚙️ helper: evita el crash al serializar BigInt
|
||||
const fixBigInt = (data) =>
|
||||
JSON.parse(JSON.stringify(data, (_, v) => (typeof v === 'bigint' ? v.toString() : v)))
|
||||
|
||||
// ───── GET todos los empleados ─────
|
||||
router.get('/', async (_req, res) => {
|
||||
try {
|
||||
const empleados = await prisma.cliente.findMany({
|
||||
where: { empleado: true },
|
||||
});
|
||||
res.json(empleados);
|
||||
} catch (error) {
|
||||
console.error(error); // Log the error for debugging
|
||||
res.status(500).json({ error: 'Error al obtener empleados.' });
|
||||
const empleados = await prisma.cliente.findMany({ where: { empleado: true } })
|
||||
res.json(fixBigInt(empleados))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
res.status(500).json({ error: 'Error al obtener empleados.' })
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// GET empleado by ID
|
||||
// ───── GET empleado por ID ─────
|
||||
router.get('/:id', async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const id = BigInt(req.params.id)
|
||||
try {
|
||||
const empleado = await prisma.cliente.findFirst({
|
||||
where: {
|
||||
id: parseInt(id),
|
||||
empleado: true
|
||||
},
|
||||
});
|
||||
if (empleado) {
|
||||
res.json(empleado);
|
||||
} else {
|
||||
res.status(404).json({ error: 'Empleado no encontrado.' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error); // Log the error for debugging
|
||||
res.status(500).json({ error: 'Error al obtener empleado.' });
|
||||
const empleado = await prisma.cliente.findFirst({ where: { id, empleado: true } })
|
||||
if (!empleado) return res.status(404).json({ error: 'Empleado no encontrado.' })
|
||||
res.json(fixBigInt(empleado))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
res.status(500).json({ error: 'Error al obtener empleado.' })
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// POST create new empleado
|
||||
// ───── POST crear empleado ─────
|
||||
router.post('/', async (req, res) => {
|
||||
const { nombre, apellido, dni, telefono, direccion, email } = req.body;
|
||||
try {
|
||||
const nuevoEmpleado = await prisma.cliente.create({
|
||||
data: {
|
||||
nombre,
|
||||
apellido,
|
||||
dni,
|
||||
telefono,
|
||||
direccion,
|
||||
email,
|
||||
empleado: true, // Ensure empleado is set to true
|
||||
},
|
||||
});
|
||||
res.status(201).json(nuevoEmpleado);
|
||||
} catch (error) {
|
||||
console.error(error); // Log the error for debugging
|
||||
if (error.code === 'P2002' && error.meta?.target?.includes('dni')) {
|
||||
return res.status(400).json({ error: 'Ya existe un cliente con este DNI.' });
|
||||
}
|
||||
if (error.code === 'P2002' && error.meta?.target?.includes('email')) {
|
||||
return res.status(400).json({ error: 'Ya existe un cliente con este Email.' });
|
||||
}
|
||||
res.status(500).json({ error: 'Error al crear empleado.' });
|
||||
}
|
||||
});
|
||||
const {
|
||||
name,
|
||||
cedula,
|
||||
telefono,
|
||||
ubicacion = '.',
|
||||
grupo_estudio,
|
||||
avatar_url,
|
||||
idciat,
|
||||
} = req.body
|
||||
|
||||
// PUT update empleado by ID
|
||||
try {
|
||||
const nuevo = await prisma.cliente.create({
|
||||
data: {
|
||||
name,
|
||||
cedula: BigInt(cedula),
|
||||
telefono,
|
||||
ubicacion,
|
||||
grupo_estudio,
|
||||
avatar_url,
|
||||
idciat,
|
||||
empleado: true,
|
||||
},
|
||||
})
|
||||
res.status(201).json(fixBigInt(nuevo))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
if (e.code === 'P2002' && e.meta?.target?.includes('cedula'))
|
||||
return res.status(400).json({ error: 'Ya existe un cliente con esa cédula.' })
|
||||
res.status(500).json({ error: 'Error al crear empleado.' })
|
||||
}
|
||||
})
|
||||
|
||||
// ───── PUT actualizar empleado ─────
|
||||
router.put('/:id', async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { nombre, apellido, dni, telefono, direccion, email } = req.body;
|
||||
const id = BigInt(req.params.id)
|
||||
const {
|
||||
name,
|
||||
cedula,
|
||||
telefono,
|
||||
ubicacion,
|
||||
grupo_estudio,
|
||||
avatar_url,
|
||||
idciat,
|
||||
} = req.body
|
||||
|
||||
try {
|
||||
// First, check if the employee exists and is an employee
|
||||
const existingEmpleado = await prisma.cliente.findFirst({
|
||||
where: {
|
||||
id: parseInt(id),
|
||||
empleado: true,
|
||||
},
|
||||
});
|
||||
const existe = await prisma.cliente.findFirst({ where: { id, empleado: true } })
|
||||
if (!existe) return res.status(404).json({ error: 'Empleado no encontrado.' })
|
||||
|
||||
if (!existingEmpleado) {
|
||||
return res.status(404).json({ error: 'Empleado no encontrado.' });
|
||||
}
|
||||
|
||||
const empleadoActualizado = await prisma.cliente.update({
|
||||
where: { id: parseInt(id) },
|
||||
const actualizado = await prisma.cliente.update({
|
||||
where: { id },
|
||||
data: {
|
||||
nombre,
|
||||
apellido,
|
||||
dni,
|
||||
name,
|
||||
cedula: cedula !== undefined ? BigInt(cedula) : undefined,
|
||||
telefono,
|
||||
direccion,
|
||||
email,
|
||||
// empleado: true, // Keep it as an employee, or allow changing this? For now, keep as true.
|
||||
ubicacion,
|
||||
grupo_estudio,
|
||||
avatar_url,
|
||||
idciat,
|
||||
},
|
||||
});
|
||||
res.json(empleadoActualizado);
|
||||
} catch (error) {
|
||||
console.error(error); // Log the error for debugging
|
||||
if (error.code === 'P2002' && error.meta?.target?.includes('dni')) {
|
||||
return res.status(400).json({ error: 'Ya existe un cliente con este DNI.' });
|
||||
}
|
||||
if (error.code === 'P2002' && error.meta?.target?.includes('email')) {
|
||||
return res.status(400).json({ error: 'Ya existe un cliente con este Email.' });
|
||||
}
|
||||
if (error.code === 'P2025') { // Record to update not found
|
||||
return res.status(404).json({ error: 'Empleado no encontrado para actualizar.' });
|
||||
}
|
||||
res.status(500).json({ error: 'Error al actualizar empleado.' });
|
||||
})
|
||||
res.json(fixBigInt(actualizado))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
if (e.code === 'P2002' && e.meta?.target?.includes('cedula'))
|
||||
return res.status(400).json({ error: 'Ya existe un cliente con esa cédula.' })
|
||||
if (e.code === 'P2025')
|
||||
return res.status(404).json({ error: 'Empleado no encontrado para actualizar.' })
|
||||
res.status(500).json({ error: 'Error al actualizar empleado.' })
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// DELETE empleado by ID
|
||||
// ───── DELETE eliminar empleado ─────
|
||||
router.delete('/:id', async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const id = BigInt(req.params.id)
|
||||
try {
|
||||
// First, check if the employee exists and is an employee
|
||||
const existingEmpleado = await prisma.cliente.findFirst({
|
||||
where: {
|
||||
id: parseInt(id),
|
||||
empleado: true,
|
||||
},
|
||||
});
|
||||
const existe = await prisma.cliente.findFirst({ where: { id, empleado: true } })
|
||||
if (!existe) return res.status(404).json({ error: 'Empleado no encontrado.' })
|
||||
|
||||
if (!existingEmpleado) {
|
||||
return res.status(404).json({ error: 'Empleado no encontrado para eliminar.' });
|
||||
}
|
||||
|
||||
await prisma.cliente.delete({
|
||||
where: { id: parseInt(id) },
|
||||
});
|
||||
res.status(204).send(); // No content
|
||||
} catch (error) {
|
||||
console.error(error); // Log the error for debugging
|
||||
if (error.code === 'P2025') { // Record to delete not found
|
||||
return res.status(404).json({ error: 'Empleado no encontrado para eliminar.' });
|
||||
}
|
||||
res.status(500).json({ error: 'Error al eliminar empleado.' });
|
||||
await prisma.cliente.delete({ where: { id } })
|
||||
res.status(204).send()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
if (e.code === 'P2025')
|
||||
return res.status(404).json({ error: 'Empleado no encontrado para eliminar.' })
|
||||
res.status(500).json({ error: 'Error al eliminar empleado.' })
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
export default router;
|
||||
export default router
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
<svg class="w-5 h-5 mr-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
|
||||
<span>{{ employee.ubicacion }}</span>
|
||||
</div>
|
||||
<div v-if="employee.idciat" class="flex items-center text-gray-700">
|
||||
<div v-if="employee.cedula" class="flex items-center text-gray-700">
|
||||
<svg class="w-5 h-5 mr-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 012-2h2a2 2 0 012 2v1m-4 0h4m-6 10v-5m0 5v0z"></path></svg>
|
||||
<span>ID CIAT: {{ employee.idciat }}</span>
|
||||
<span>ID CIAT: {{ employee.cedula }}</span>
|
||||
</div>
|
||||
<div v-if="employee.grupo_estudio" class="flex items-center text-gray-700">
|
||||
<svg class="w-5 h-5 mr-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 14l9-5-9-5-9 5 9 5z"></path><path d="M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-5.998 12.083 12.083 0 01.665-6.479L12 14z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 14l9-5-9-5-9 5 9 5zm0 0v3.945m0-3.945L6.161 10.58M17.839 10.58L12 14m5.839-3.42L12 14m0 0l6.161 3.42m-6.161-3.42L5.839 14.002"></path></svg>
|
||||
|
||||
@@ -47,8 +47,9 @@ export const useEmpleadosStore = defineStore('empleados', {
|
||||
|
||||
async createEmpleado (empleadoData) {
|
||||
try {
|
||||
await apiClient.post('/api/empleados', empleadoData);
|
||||
const {data} = await apiClient.post('/api/empleados/', empleadoData);
|
||||
await this.fetchEmpleados();
|
||||
return data
|
||||
} catch (err) {
|
||||
console.error('Error creando empleado:', err);
|
||||
throw err; // para que el form muestre feedback
|
||||
@@ -57,9 +58,10 @@ export const useEmpleadosStore = defineStore('empleados', {
|
||||
|
||||
async updateEmpleado (id, empleadoData) {
|
||||
try {
|
||||
await apiClient.put(`/api/empleados/${id}`, empleadoData);
|
||||
const {data} = await apiClient.put(`/api/empleados/${id}`, empleadoData);
|
||||
await this.fetchEmpleados();
|
||||
this.clearCurrentEmpleado();
|
||||
return data
|
||||
} catch (err) {
|
||||
console.error(`Error actualizando empleado ${id}:`, err);
|
||||
throw err;
|
||||
|
||||
@@ -3,100 +3,140 @@
|
||||
<h1 class="text-3xl font-bold mb-8 text-center text-gray-700">
|
||||
{{ isEditMode ? 'Editar Empleado' : 'Crear Empleado' }}
|
||||
</h1>
|
||||
|
||||
<form
|
||||
@submit.prevent="handleSubmit"
|
||||
class="max-w-lg mx-auto bg-white p-8 rounded-lg shadow-lg"
|
||||
>
|
||||
<!-- ───────── Nombre ───────── -->
|
||||
<div class="mb-6">
|
||||
<label for="name" class="block text-gray-700 font-semibold mb-2">Nombre Completo</label>
|
||||
<label
|
||||
for="name"
|
||||
class="block text-gray-700 font-semibold mb-2"
|
||||
>Nombre Completo</label>
|
||||
<input
|
||||
id="name"
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
required
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Ej: Juan Pérez"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ───────── Cédula ───────── -->
|
||||
<div class="mb-6">
|
||||
<label for="cedula" class="block text-gray-700 font-semibold mb-2">Cédula</label>
|
||||
<label
|
||||
for="cedula"
|
||||
class="block text-gray-700 font-semibold mb-2"
|
||||
>Cédula</label>
|
||||
<input
|
||||
id="cedula"
|
||||
v-model="form.cedula"
|
||||
type="number"
|
||||
required
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Ej: 123456789"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ───────── Ubicación ───────── -->
|
||||
<div class="mb-6">
|
||||
<label for="ubicacion" class="block text-gray-700 font-semibold mb-2">Ubicación</label>
|
||||
<label
|
||||
for="ubicacion"
|
||||
class="block text-gray-700 font-semibold mb-2"
|
||||
>Ubicación</label>
|
||||
<input
|
||||
id="ubicacion"
|
||||
v-model="form.ubicacion"
|
||||
type="text"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Ej: Oficina Principal"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ───────── Grupo de estudio ───────── -->
|
||||
<div class="mb-6">
|
||||
<label for="grupo_estudio" class="block text-gray-700 font-semibold mb-2">Grupo de Estudio</label>
|
||||
<label
|
||||
for="grupo_estudio"
|
||||
class="block text-gray-700 font-semibold mb-2"
|
||||
>Grupo de Estudio</label>
|
||||
<input
|
||||
id="grupo_estudio"
|
||||
v-model="form.grupo_estudio"
|
||||
type="text"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Ej: Grupo A"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ───────── Avatar ───────── -->
|
||||
<div class="mb-6">
|
||||
<label for="avatar_url" class="block text-gray-700 font-semibold mb-2">URL del Avatar</label>
|
||||
<label
|
||||
for="avatar_url"
|
||||
class="block text-gray-700 font-semibold mb-2"
|
||||
>URL del Avatar</label>
|
||||
<input
|
||||
id="avatar_url"
|
||||
v-model="form.avatar_url"
|
||||
type="url"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Ej: https://example.com/avatar.png"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ───────── Teléfono ───────── -->
|
||||
<div class="mb-6">
|
||||
<label for="telefono" class="block text-gray-700 font-semibold mb-2">Teléfono</label>
|
||||
<label
|
||||
for="telefono"
|
||||
class="block text-gray-700 font-semibold mb-2"
|
||||
>Teléfono</label>
|
||||
<input
|
||||
id="telefono"
|
||||
v-model="form.telefono"
|
||||
type="tel"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Ej: 0991234567"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ───────── ID CIAT ───────── -->
|
||||
<div class="mb-6">
|
||||
<label for="idciat" class="block text-gray-700 font-semibold mb-2">ID CIAT</label>
|
||||
<label
|
||||
for="idciat"
|
||||
class="block text-gray-700 font-semibold mb-2"
|
||||
>ID CIAT</label>
|
||||
<input
|
||||
id="idciat"
|
||||
v-model="form.idciat"
|
||||
type="text"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Ej: CIAT123"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- ───────── Botones ───────── -->
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
type="button"
|
||||
@click="handleCancel"
|
||||
class="mr-4 px-6 py-2 text-gray-700 border border-gray-300 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-400"
|
||||
class="mr-4 px-6 py-2 text-gray-700 border border-gray-300 rounded-md
|
||||
hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-400"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="px-6 py-2 bg-blue-600 text-white font-semibold rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
||||
class="px-6 py-2 bg-blue-600 text-white font-semibold rounded-md
|
||||
hover:bg-blue-700 focus:outline-none focus:ring-2
|
||||
focus:ring-blue-500 focus:ring-offset-2"
|
||||
>
|
||||
{{ isEditMode ? 'Actualizar' : 'Crear' }}
|
||||
</button>
|
||||
@@ -108,7 +148,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEmpleadosStore } from '@/stores/useEmpleados.js'
|
||||
|
||||
/* ───── Tipos ───── */
|
||||
interface EmpleadoForm {
|
||||
name: string
|
||||
cedula: number | null
|
||||
@@ -119,154 +162,111 @@ interface EmpleadoForm {
|
||||
idciat?: string
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const form = ref<EmpleadoForm>({
|
||||
/* ───── helpers ───── */
|
||||
const defaultForm = (): EmpleadoForm => ({
|
||||
name: '',
|
||||
cedula: null,
|
||||
ubicacion: '.', // Default value as per schema
|
||||
ubicacion: '.', // default del schema
|
||||
grupo_estudio: '',
|
||||
avatar_url: '',
|
||||
telefono: '',
|
||||
idciat: '',
|
||||
})
|
||||
|
||||
const employeeId = ref<string | null>(null)
|
||||
/* ───── Router ───── */
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const isEditMode = computed(() => !!employeeId.value)
|
||||
/* ───── Store ───── */
|
||||
const empleadosStore = useEmpleadosStore()
|
||||
const { currentEmpleado } = storeToRefs(empleadosStore)
|
||||
|
||||
/* ───── State ───── */
|
||||
const form = ref<EmpleadoForm>(defaultForm())
|
||||
const employeeId = computed(() => route.params.id as string | undefined)
|
||||
const isEditMode = computed(() => !!employeeId.value)
|
||||
|
||||
/* ───── Lifecycle ───── */
|
||||
onMounted(async () => {
|
||||
if (route.params.id) {
|
||||
employeeId.value = route.params.id as string
|
||||
// In a real application, you would fetch the employee data here
|
||||
// For example:
|
||||
// const response = await fetch(`/api/employees/${employeeId.value}`)
|
||||
// const data = await response.json()
|
||||
// form.value = data // Populate form with fetched data
|
||||
// For now, we'll simulate fetching data or indicate that it needs to be done
|
||||
if (employeeId.value) {
|
||||
console.log(`Editing employee ID: ${employeeId.value}. Need to fetch data.`);
|
||||
// Example: Pre-populate form for an existing employee
|
||||
// form.value = {
|
||||
// name: 'Juan Pérez Existente',
|
||||
// cedula: 123456789,
|
||||
// ubicacion: 'Oficina Antigua',
|
||||
// grupo_estudio: 'Grupo Z',
|
||||
// avatar_url: 'https://example.com/avatar_existente.png',
|
||||
// telefono: '0987654321',
|
||||
// idciat: 'CIATXYZ'
|
||||
// };
|
||||
if (isEditMode.value && employeeId.value) {
|
||||
try {
|
||||
await empleadosStore.fetchEmpleadoById(employeeId.value)
|
||||
// copiamos solo campos que el form necesita
|
||||
form.value = {
|
||||
name : currentEmpleado.value.name ?? '',
|
||||
cedula : currentEmpleado.value.cedula ?? null,
|
||||
ubicacion : currentEmpleado.value.ubicacion ?? '.',
|
||||
grupo_estudio : currentEmpleado.value.grupo_estudio ?? '',
|
||||
avatar_url : currentEmpleado.value.avatar_url ?? '',
|
||||
telefono : currentEmpleado.value.telefono ?? '',
|
||||
idciat : currentEmpleado.value.idciat ?? '',
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error cargando empleado:', err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/* ───── Submit ───── */
|
||||
const handleSubmit = async () => {
|
||||
// Ensure cedula is a number if provided, or null otherwise
|
||||
const cedulaValue = form.value.cedula ? Number(form.value.cedula) : null;
|
||||
|
||||
const payload = {
|
||||
...form.value,
|
||||
cedula: cedulaValue,
|
||||
empleado: true, // This form is specifically for employees
|
||||
}
|
||||
const payload = { ...form.value, empleado: true }
|
||||
|
||||
try {
|
||||
if (isEditMode.value) {
|
||||
console.log('Actualizando empleado:', employeeId.value, payload)
|
||||
// Replace with actual API call
|
||||
// const response = await fetch(`/api/clientes/${employeeId.value}`, {
|
||||
// method: 'PUT',
|
||||
// headers: { 'Content-Type': 'application/json' },
|
||||
// body: JSON.stringify(payload),
|
||||
// })
|
||||
// if (!response.ok) throw new Error('Failed to update employee')
|
||||
// const updatedEmployee = await response.json()
|
||||
// console.log('Empleado actualizado:', updatedEmployee)
|
||||
if (isEditMode.value && employeeId.value) {
|
||||
await empleadosStore.updateEmpleado(employeeId.value, payload)
|
||||
} else {
|
||||
console.log('Creando empleado:', payload)
|
||||
// Replace with actual API call
|
||||
// const response = await fetch('/api/clientes', {
|
||||
// method: 'POST',
|
||||
// headers: { 'Content-Type': 'application/json' },
|
||||
// body: JSON.stringify(payload),
|
||||
// })
|
||||
// if (!response.ok) throw new Error('Failed to create employee')
|
||||
// const newEmployee = await response.json()
|
||||
// console.log('Empleado creado:', newEmployee)
|
||||
await empleadosStore.createEmpleado(payload)
|
||||
}
|
||||
router.push('/empleados') // Or wherever the employee list is
|
||||
} catch (error) {
|
||||
console.error('Error submitting form:', error)
|
||||
// Handle error (e.g., show a notification to the user)
|
||||
router.push('/empleados')
|
||||
} catch (err) {
|
||||
console.error('Error al guardar empleado:', err)
|
||||
// aquí podrías disparar una notificación
|
||||
}
|
||||
}
|
||||
|
||||
/* ───── Cancel ───── */
|
||||
const handleCancel = () => {
|
||||
router.go(-1) // Go back to the previous page or to a default route
|
||||
empleadosStore.clearCurrentEmpleado()
|
||||
router.go(-1)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Custom styles for better visual appeal if needed */
|
||||
/* --- Validación rápida de inputs requeridos --- */
|
||||
input:required:invalid {
|
||||
border-color: #e53e3e; /* Tailwind's red-600 */
|
||||
border-color: #e53e3e; /* red-600 */
|
||||
}
|
||||
|
||||
input:focus, button:focus {
|
||||
/* --- Focus global para inputs y botones --- */
|
||||
input:focus,
|
||||
button:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px #3b82f6; /* Tailwind's blue-500 */
|
||||
box-shadow: 0 0 0 2px #3b82f6; /* blue-500 */
|
||||
}
|
||||
|
||||
/* Styling for a more elegant look and feel */
|
||||
.form-container {
|
||||
background-color: #f9fafb; /* Tailwind's gray-50 */
|
||||
}
|
||||
/* --- Look & feel extra (opcional, podés ajustar) --- */
|
||||
.form-container { background-color: #f9fafb; } /* gray-50 */
|
||||
.form-card { box-shadow: 0 10px 15px -3px rgba(0,0,0,.1),
|
||||
0 4px 6px -2px rgba(0,0,0,.05); }
|
||||
|
||||
.form-card {
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* Tailwind's shadow-xl */
|
||||
}
|
||||
|
||||
.form-title {
|
||||
color: #1f2937; /* Tailwind's gray-800 */
|
||||
}
|
||||
|
||||
.form-label {
|
||||
color: #374151; /* Tailwind's gray-700 */
|
||||
font-weight: 600; /* semibold */
|
||||
}
|
||||
|
||||
.form-input {
|
||||
border-color: #d1d5db; /* Tailwind's gray-300 */
|
||||
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
.form-title { color: #1f2937; } /* gray-800 */
|
||||
.form-label { color: #374151; font-weight: 600; } /* gray-700 */
|
||||
.form-input { border-color: #d1d5db; transition: border-color .2s, box-shadow .2s; }
|
||||
.form-input:focus {
|
||||
border-color: #2563eb; /* Tailwind's blue-600 */
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5); /* Ring focus */
|
||||
border-color: #2563eb; /* blue-600 */
|
||||
box-shadow: 0 0 0 3px rgba(59,130,246,.5);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #2563eb; /* Tailwind's blue-600 */
|
||||
color: white;
|
||||
font-weight: 600; /* semibold */
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 0.375rem; /* rounded-md */
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background-color: #1d4ed8; /* Tailwind's blue-700 */
|
||||
background-color: #2563eb; color: #fff; font-weight: 600;
|
||||
padding: .75rem 1.5rem; border-radius: .375rem; transition: background-color .2s;
|
||||
}
|
||||
.btn-primary:hover { background-color: #1d4ed8; }
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #e5e7eb; /* Tailwind's gray-200 */
|
||||
color: #374151; /* Tailwind's gray-700 */
|
||||
font-weight: 600; /* semibold */
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 0.375rem; /* rounded-md */
|
||||
border: 1px solid #d1d5db; /* Tailwind's gray-300 */
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
}
|
||||
.btn-secondary:hover {
|
||||
background-color: #d1d5db; /* Tailwind's gray-300 */
|
||||
background-color: #e5e7eb; color: #374151; font-weight: 600;
|
||||
padding: .75rem 1.5rem; border-radius: .375rem; border: 1px solid #d1d5db;
|
||||
transition: background-color .2s;
|
||||
}
|
||||
.btn-secondary:hover { background-color: #d1d5db; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user