Files
planilla/ui/src/components/planillas/tablaPlanillas.vue
google-labs-jules[bot] a5aaad5201 feat: Centralize table component into NucleoTable
I've created a new reusable table component `NucleoTable.vue` to standardize table implementations across the UI.

Key changes:
- `NucleoTable.vue` (`ui/src/components/ui/NucleoTable.vue`) created with props for columns, items, accent color, and background color name. It supports custom cell rendering and action slots.
- I've implemented basic styling using Tailwind CSS, respecting dynamic accent and background colors from the UI store.
- It declares `editItem` and `deleteItem` events for parent components to handle.
- I've refactored existing table components to use `NucleoTable.vue`:
    - `tablaAsistencias.vue`
    - `tablaEmpleados.vue`
    - `tablaPlanillas.vue`
    - `tablaTareas.vue`
- Each refactored table now passes its specific data, column definitions, and styling props to `NucleoTable`. Custom cell rendering and action button logic are maintained using slots, preserving original functionality and styling.

This change reduces code duplication and makes future updates to table structures and styles more manageable. You've confirmed that all tables function and appear as expected after refactoring.
2025-06-03 19:44:53 +00:00

83 lines
4.0 KiB
Vue

<template>
<NucleoTable
:columns="columns"
:items="props.planillas"
accent-color="--accent-color-planillas"
table-bg-color-name="tableBgColorPlanillas"
>
<template #cell-fecha_desde="{ item }">
{{ formatDate(item.fecha_desde) }}
</template>
<template #cell-fecha_hasta="{ item }">
{{ formatDate(item.fecha_hasta) }}
</template>
<template #cell-total="{ item }">
{{ formatCurrency(item.total) }}
</template>
<template #cell-estado="{ item }">
<span :class="['px-2.5 py-0.5 rounded-full text-xs font-semibold', getStatusClass(item.estado)]">
{{ item.estado }}
</span>
</template>
<template #actions="{ item }">
<div class="flex items-center space-x-2">
<button @click="editPlanilla(item.id)" class="p-1.5 sm:p-2 rounded-md transition-all duration-150 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-600/20 focus:ring-blue-500 dark:focus:ring-blue-400" title="Editar">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" /></svg>
</button>
<button @click="confirmDeletePlanilla(item)" class="p-1.5 sm:p-2 rounded-md transition-all duration-150 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300 hover:bg-red-100 dark:hover:bg-red-600/20 focus:ring-red-500 dark:focus:ring-red-400" title="Eliminar">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12.56 0c1.153 0 2.24.03 3.22.077m3.22-.077L10.879 3.28a2.25 2.25 0 012.244-2.077h.093c.956 0 1.853.543 2.244 2.077L14.74 5.79m-4.858 0l-2.828-2.828A1.875 1.875 0 016.188 2.188l2.828 2.828m6.912 0l2.828-2.828a1.875 1.875 0 00-2.652-2.652L12 5.79M9.26 9h5.48L9.26 9z" /></svg>
</button>
</div>
</template>
</NucleoTable>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
import NucleoTable from '../ui/NucleoTable.vue'; // Import NucleoTable
import { usePlanillasStore } from '../../stores/usePlanillas';
import { formatDate, formatCurrency, getStatusClass } from '../../utils/formatters.js';
// useUi store is now handled by NucleoTable
const props = defineProps({
planillas: {
type: Array,
required: true,
default: () => [],
},
});
const emit = defineEmits(['edit']); // Emits 'edit' to parent (PlanillasIndex.vue)
const planillasStore = usePlanillasStore();
const columns = [
{ key: 'id', label: 'ID' },
{ key: 'titulo', label: 'Título' },
{ key: 'empleado_id', label: 'Empleado ID' },
{ key: 'fecha_desde', label: 'Fecha Desde' },
{ key: 'fecha_hasta', label: 'Fecha Hasta' },
{ key: 'total', label: 'Total' },
{ key: 'estado', label: 'Estado' },
];
// Keep existing methods
const editPlanilla = (id) => {
emit('edit', id);
};
const confirmDeletePlanilla = (planilla) => {
if (confirm(`¿Está seguro de que desea eliminar la planilla "${planilla.titulo}" (ID: ${planilla.id})?`)) {
deletePlanillaInternal(planilla.id);
}
};
const deletePlanillaInternal = async (id) => {
try {
await planillasStore.deletePlanilla(id);
} catch (error) {
console.error(`Error deleting planilla with id ${id}:`, error);
// Optional: Show error notification
}
};
</script>