I've standardized the visual appearance, structure, and functionality of card components across different modules (Asistencias, Empleados, Planillas, Tareas) to ensure a consistent user experience for you.
Key changes include:
- **Consistent HTML Structure:** All cards now follow a common layout with `card-header`, `card-body`, and `card-actions` sections.
- **Tailwind CSS Styling:** I've refactored card styling to use Tailwind CSS utility classes, removing scoped CSS where possible. This promotes maintainability and a unified design language. Tailwind CSS has been configured for the `ui` package.
- **CSS Variables for Theming:** I've introduced global CSS variables in `ui/src/style.css` for module-specific accent colors and common UI elements (e.g., warning colors, shadows), allowing for easier theming and consistent color usage.
- **Standardized Functionality:**
- I've ensured "Edit" and "Delete" buttons have a consistent appearance and behavior.
- Delete confirmation dialogs now use a standard message format.
- I've removed the "View Details" button from `cardEmpleado.vue` for consistency, as other modules integrate detail viewing within their "Edit" forms.
- **README Update:** I've added a comprehensive section to `ui/README.md` documenting the standardized card components, including their structure, styling approach with Tailwind, theming via CSS variables, and basic usage guidelines.
These changes improve the visual consistency and maintainability of the UI's card elements.
117 lines
4.5 KiB
Vue
117 lines
4.5 KiB
Vue
<template>
|
|
<div class="bg-white shadow-md rounded-lg p-4 md:p-6 m-2 border border-gray-200 hover:shadow-lg transition-shadow duration-300 ease-in-out flex flex-col">
|
|
<div class="flex justify-between items-center mb-3 md:mb-4 pb-2 md:pb-3 border-b border-gray-100">
|
|
<h4 class="text-lg md:text-xl font-semibold" :style="{ color: 'var(--accent-color-tareas)' }">Tarea ID: {{ tarea.id }}</h4>
|
|
<span :class="['px-2 py-1 text-xs font-bold text-white rounded-full', getStatusClass(tarea.estado)]">
|
|
{{ tarea.estado || 'N/A' }}
|
|
</span>
|
|
</div>
|
|
<div class="text-sm text-gray-700 space-y-2">
|
|
<p><strong class="font-medium text-gray-900">Título:</strong> {{ tarea.titulo }}</p>
|
|
<p><strong class="font-medium text-gray-900">Empleado ID:</strong> {{ tarea.empleado_id }}</p>
|
|
<p><strong class="font-medium text-gray-900">Fecha:</strong> {{ formatDate(tarea.fecha) }}</p>
|
|
<p><strong class="font-medium text-gray-900">Tipo:</strong> {{ tarea.tipo || 'N/A' }}</p>
|
|
<p v-if="tarea.precio != null"><strong class="font-medium text-gray-900">Precio:</strong> {{ formatCurrency(tarea.precio) }}</p>
|
|
<p v-if="tarea.observacion" class="italic text-gray-600 bg-gray-50 p-2 border-l-3 rounded" :style="{ borderColor: 'var(--accent-color-tareas)' }">
|
|
<strong class="font-medium text-gray-900">Observación:</strong> {{ tarea.observacion }}
|
|
</p>
|
|
</div>
|
|
<div class="mt-auto pt-3 md:pt-4 flex justify-end space-x-2 md:space-x-3">
|
|
<button
|
|
@click="editTarea"
|
|
class="px-3 py-1 md:px-4 md:py-2 text-xs md:text-sm font-medium rounded-md transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 text-white"
|
|
:style="{ backgroundColor: 'var(--accent-color-tareas)', borderColor: 'var(--accent-color-tareas)' }"
|
|
@mouseover="buttonHover($event, true)"
|
|
@mouseleave="buttonHover($event, false)"
|
|
:class="`focus:ring-[var(--accent-color-tareas)]`"
|
|
>Editar</button>
|
|
<button
|
|
@click="confirmDeleteTarea"
|
|
class="px-3 py-1 md:px-4 md:py-2 text-xs md:text-sm font-medium rounded-md transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 bg-red-600 hover:bg-red-700 text-white focus:ring-red-500"
|
|
>Eliminar</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { defineProps, defineEmits } from 'vue';
|
|
import { useTareasStore } from '../../stores/useTareas';
|
|
|
|
const props = defineProps({
|
|
tarea: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(['edit']);
|
|
|
|
const tareasStore = useTareasStore();
|
|
|
|
const formatDate = (dateString) => {
|
|
if (!dateString) return 'N/A';
|
|
const date = new Date(dateString);
|
|
return date.toLocaleString('es-HN', { timeZone: 'America/Tegucigalpa', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' });
|
|
};
|
|
|
|
const formatCurrency = (value) => {
|
|
if (value == null) return '';
|
|
return Number(value).toLocaleString('es-PY', {
|
|
style: 'currency',
|
|
currency: 'PYG',
|
|
});
|
|
};
|
|
|
|
const editTarea = () => {
|
|
emit('edit', props.tarea.id);
|
|
};
|
|
|
|
const confirmDeleteTarea = () => {
|
|
if (confirm(`¿Está seguro de que desea eliminar la tarea "${props.tarea.titulo}" (ID: ${props.tarea.id})?`)) {
|
|
deleteTareaInternal();
|
|
}
|
|
};
|
|
|
|
const deleteTareaInternal = async () => {
|
|
try {
|
|
await tareasStore.deleteTarea(props.tarea.id);
|
|
} catch (error) {
|
|
console.error('Error deleting tarea:', error);
|
|
alert('Ocurrió un error al eliminar la tarea. Por favor, intente de nuevo.');
|
|
}
|
|
};
|
|
|
|
const getStatusClass = (status) => {
|
|
if (!status) return 'bg-gray-400';
|
|
const statusNormalized = status.toLowerCase().replace(/\s+/g, '-');
|
|
switch (statusNormalized) {
|
|
case 'pendiente': return 'bg-yellow-500 text-gray-800';
|
|
case 'realizada':
|
|
case 'completada':
|
|
case 'hecho': return 'bg-green-500';
|
|
case 'en-progreso': return 'bg-blue-500';
|
|
case 'anulada':
|
|
case 'cancelada': return 'bg-red-500';
|
|
case 'archivada': return 'bg-gray-500';
|
|
default: return 'bg-gray-400';
|
|
}
|
|
};
|
|
|
|
const buttonHover = (event, isHovering) => {
|
|
if (isHovering) {
|
|
event.target.style.filter = 'brightness(90%)';
|
|
} else {
|
|
event.target.style.filter = 'brightness(100%)';
|
|
}
|
|
};
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* Minimal scoped styles, mainly for complex status colors if not handled by Tailwind directly */
|
|
/* Or for :style bindings if preferred for dynamic properties like accent colors */
|
|
.border-l-3 {
|
|
border-left-width: 3px;
|
|
}
|
|
</style>
|