Files
planilla/ui/src/components/planillas/cardPlanilla.vue
google-labs-jules[bot] 0de3a8faf4 Refactor: Centralize UI card component with NucleoDataCard
This commit introduces a new `NucleoDataCard.vue` component to centralize the common structure and styling of various card elements used throughout the UI.

The following existing card components have been refactored to use `NucleoDataCard.vue`:
- `ui/src/components/asistencias/cardAsistencia.vue`
- `ui/src/components/empleados/cardEmpleado.vue`
- `ui/src/components/planillas/cardPlanilla.vue`
- `ui/src/components/tareas/cardTarea.vue`

Key changes:
- Created `NucleoDataCard.vue` in `ui/src/components/ui/` with flexible props (title, status, fields, accentColor, backgroundColor, avatarUrl, observation, showEditButton, showDeleteButton) and slots (header, body, footer, actions) to accommodate different card designs.
- Updated `NucleoDataCard.vue` to directly use hex color values for `accentColor` and `backgroundColor` props for easier integration with the UI store.
- Refactored the listed existing card components to utilize `NucleoDataCard.vue`, passing data through props and customizing specific sections (like avatars or field icons) via slots.
- Ensured that all functionalities, including edit/delete actions and dynamic styling based on the UI store, are preserved in the refactored components.

This centralization reduces code duplication, improves maintainability, and provides a consistent foundation for future card-based UI elements.
2025-06-03 19:40:48 +00:00

101 lines
3.1 KiB
Vue

<template>
<NucleoDataCard
:title="`Planilla ID: ${planilla.id}`"
:status="planilla.estado"
:fields="cardFields"
:accent-color="ui.accentColorPlanillas"
:background-color="ui.tableBgColorPlanillas"
@edit="editPlanilla"
@delete="confirmDeletePlanilla"
>
<template #header>
<div class="flex items-center justify-between w-full">
<h2 class="text-xl font-semibold" :style="{ color: ui.accentColorPlanillas }">Planilla ID: {{ planilla.id }}</h2>
<span :class="['px-2 py-1 text-xs font-bold text-white rounded-full', getStatusClass(planilla.estado)]">
{{ planilla.estado || 'N/A' }}
</span>
</div>
</template>
</NucleoDataCard>
</template>
<script setup>
import { defineProps, defineEmits, computed } from 'vue';
import { usePlanillasStore } from '../../stores/usePlanillas';
import { useUi } from '../../stores/useUi.js';
import NucleoDataCard from '../ui/NucleoDataCard.vue';
const ui = useUi();
const props = defineProps({
planilla: {
type: Object,
required: true,
},
});
const emit = defineEmits(['edit']);
const planillasStore = usePlanillasStore();
const formatDate = (dateString) => {
if (!dateString) return 'N/A';
const date = new Date(dateString);
return date.toLocaleDateString('es-HN', { timeZone: 'America/Tegucigalpa', year: 'numeric', month: 'long', day: 'numeric' });
};
const formatCurrency = (value) => {
if (value == null) return 'N/A';
return Number(value).toLocaleString('es-PY', {
style: 'currency',
currency: 'PYG',
minimumFractionDigits: 0, // Ensure no decimals for PYG if that's standard
maximumFractionDigits: 0,
});
};
const cardFields = computed(() => [
{ label: 'Título', value: props.planilla.titulo },
{ label: 'Empleado ID', value: props.planilla.empleado_id },
{ label: 'Desde', value: formatDate(props.planilla.fecha_desde) },
{ label: 'Hasta', value: formatDate(props.planilla.fecha_hasta) },
{ label: 'Total', value: formatCurrency(props.planilla.total) },
]);
const editPlanilla = () => {
emit('edit', props.planilla.id);
};
const confirmDeletePlanilla = () => {
if (confirm(`¿Está seguro de que desea eliminar la planilla "${props.planilla.titulo}" (ID: ${props.planilla.id})?`)) {
deletePlanillaInternal();
}
};
const deletePlanillaInternal = async () => {
try {
await planillasStore.deletePlanilla(props.planilla.id);
} catch (error) {
console.error('Error deleting planilla:', error);
alert('Ocurrió un error al eliminar la planilla.');
}
};
const getStatusClass = (status) => {
if (!status) return 'bg-gray-400 text-white';
const statusNormalized = status.toLowerCase().replace(/\s+/g, '-');
switch (statusNormalized) {
case 'pagado': return 'bg-green-500 text-white';
case 'pendiente': return 'bg-yellow-500 text-gray-800';
case 'anulado': return 'bg-red-500 text-white';
case 'borrador': return 'bg-gray-500 text-white';
default: return 'bg-gray-400 text-white';
}
};
// buttonHover removed
</script>
<style scoped>
/* Scoped styles can be removed or adjusted if not needed after refactor. */
</style>