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.
101 lines
3.1 KiB
Vue
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>
|