Merge pull request #12 from josedario87/feat/module-card-views

Feat: Implement card view option in Asistencias, Planillas, and Tarea…
This commit is contained in:
josedario87
2025-05-31 01:02:27 -06:00
committed by GitHub
6 changed files with 185 additions and 40 deletions

View File

@@ -1,12 +1,13 @@
<template>
<div class="asistencia-card">
<div class="card-header">
<span class="empleado-id">Empleado ID: {{ asistencia.empleado_id }}</span>
<h4>Asistencia ID: {{ asistencia.id }}</h4>
<span :class="`estado-asistencia estado-${asistencia.estado?.toLowerCase().replace(/\s+/g, '-')}`">
{{ asistencia.estado || 'N/A' }}
</span>
</div>
<div class="card-body">
<p><strong>Empleado ID:</strong> {{ asistencia.empleado_id }}</p>
<p><strong>Entrada:</strong> {{ formatDateTime(asistencia.entrada) }}</p>
<p><strong>Salida:</strong> {{ asistencia.salida ? formatDateTime(asistencia.salida) : 'No registrada' }}</p>
<p v-if="asistencia.observacion" class="observacion">
@@ -40,14 +41,14 @@ const asistenciasStore = useAsistenciasStore();
const formatDateTime = (dateTimeString) => {
if (!dateTimeString) return 'N/A';
const date = new Date(dateTimeString);
return date.toLocaleString('es-ES', { // Spanish locale
year: 'numeric',
month: '2-digit', // Using 2-digit for month for brevity in card
day: '2-digit', // Using 2-digit for day
hour: '2-digit',
minute: '2-digit',
return date.toLocaleString('es-HN', { timeZone: 'America/Tegucigalpa', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); // Spanish locale
// year: 'numeric', // Already present in the new options
// month: '2-digit', // Using 2-digit for month for brevity in card // Already present in the new options
// day: '2-digit', // Using 2-digit for day // Already present in the new options
// hour: '2-digit', // Already present in the new options
// minute: '2-digit', // Already present in the new options
// second: '2-digit', // Optional: include seconds
});
// }); // Removed this line as options are now in a single line
};
const editAsistencia = () => {
@@ -96,7 +97,14 @@ const deleteAsistenciaInternal = async () => {
border-bottom: 1px solid #f0f0f0; /* Even lighter border */
}
.empleado-id {
.card-header h4 { /* Style for the new Asistencia ID header */
font-weight: bold;
color: var(--accent-color-asistencias); /* Accent color */
font-size: 1.15em; /* Slightly larger for main header element */
margin: 0; /* Remove default margin */
}
.empleado-id { /* This class is no longer used in the header, but could be reused elsewhere if needed */
font-weight: bold;
color: var(--accent-color-asistencias); /* Accent color */
font-size: 1.05em;

View File

@@ -1,6 +1,7 @@
<template>
<div class="planilla-card">
<h3>{{ planilla.titulo }}</h3>
<h4>Planilla ID: {{ planilla.id }}</h4>
<p><strong>Título:</strong> {{ planilla.titulo }}</p>
<p><strong>Empleado ID:</strong> {{ planilla.empleado_id }}</p>
<p><strong>Desde:</strong> {{ formatDate(planilla.fecha_desde) }}</p>
<p><strong>Hasta:</strong> {{ formatDate(planilla.fecha_hasta) }}</p>
@@ -31,11 +32,7 @@ const planillasStore = usePlanillasStore();
const formatDate = (dateString) => {
if (!dateString) return 'N/A';
const date = new Date(dateString);
return date.toLocaleDateString('es-ES', { // Using Spanish locale for date
year: 'numeric',
month: 'long',
day: 'numeric',
});
return date.toLocaleDateString('es-HN', { timeZone: 'America/Tegucigalpa', year: 'numeric', month: 'long', day: 'numeric' });
};
const formatCurrency = (value) => {
@@ -80,7 +77,13 @@ const deletePlanilla = async () => {
background-color: #f9f9f9;
}
.planilla-card h3 {
.planilla-card h4 { /* Updated selector from h3 to h4 */
margin-top: 0;
color: var(--accent-color-planillas); /* Accent color for title */
font-size: 1.2em; /* Adjust size as needed, h4 is typically smaller than h3 */
}
.planilla-card h3 { /* Keep if h3 is used elsewhere, or remove if h4 is the new standard */
margin-top: 0;
color: var(--accent-color-planillas); /* Accent color for title */
}

View File

@@ -1,6 +1,7 @@
<template>
<div class="tarea-card">
<h4>{{ tarea.titulo }}</h4>
<h4>Tarea ID: {{ tarea.id }}</h4>
<p><strong>Título:</strong> {{ tarea.titulo }}</p>
<p><strong>Empleado ID:</strong> {{ tarea.empleado_id }}</p>
<p><strong>Fecha:</strong> {{ formatDate(tarea.fecha) }}</p>
<p><strong>Estado:</strong> <span :class="`estado-${tarea.estado?.toLowerCase().replace(/\s+/g, '-')}`">{{ tarea.estado }}</span></p>
@@ -33,11 +34,7 @@ const tareasStore = useTareasStore();
const formatDate = (dateString) => {
if (!dateString) return 'N/A';
const date = new Date(dateString);
return date.toLocaleDateString('es-ES', { // Spanish locale
year: 'numeric',
month: 'long',
day: 'numeric',
});
return date.toLocaleString('es-HN', { timeZone: 'America/Tegucigalpa', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' });
};
const formatCurrency = (value) => {

View File

@@ -7,6 +7,16 @@
</button>
</header>
<div class="mb-6 flex justify-end items-center space-x-3">
<span class="text-sm font-medium text-gray-700">Cambiar Vista:</span>
<button @click="currentView = 'card'" :class="btnClass('card')">
Tarjetas
</button>
<button @click="currentView = 'table'" :class="btnClass('table')">
Tabla
</button>
</div>
<div v-if="isLoading" class="loading-message">
Cargando asistencias...
</div>
@@ -17,12 +27,30 @@
</div>
<div v-else>
<tabla-asistencias
:asistencias="asistenciasList"
@edit="handleEditAsistencia"
/>
<div v-if="!asistenciasList || asistenciasList.length === 0 && !isLoading" class="no-data-message">
No hay asistencias registradas. Puede registrar una nueva haciendo clic en el botón de arriba.
<!-- Vista de Tabla -->
<div v-if="currentView === 'table'">
<tabla-asistencias
:asistencias="asistenciasList"
@edit="handleEditAsistencia"
/>
<div v-if="asistenciasList.length === 0 && !isLoading" class="no-data-message">
No hay asistencias para mostrar en la vista de tabla.
</div>
</div>
<!-- Vista de Tarjetas -->
<div v-if="currentView === 'card'">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<CardAsistencia
v-for="asistencia in asistenciasList"
:key="asistencia.id"
:asistencia="asistencia"
@edit="handleEditAsistencia"
/>
</div>
<div v-if="asistenciasList.length === 0 && !isLoading" class="no-data-message">
No hay asistencias para mostrar en la vista de tarjetas.
</div>
</div>
</div>
@@ -34,6 +62,7 @@ import { ref, computed, onMounted } from 'vue';
import { useAsistenciasStore } from '../../stores/useAsistencias';
import { useRouter } from 'vue-router';
import TablaAsistencias from '../../components/asistencias/tablaAsistencias.vue';
import CardAsistencia from '../../components/asistencias/cardAsistencia.vue';
const asistenciasStore = useAsistenciasStore();
const router = useRouter();
@@ -42,6 +71,8 @@ const isLoading = ref(true);
const errorLoading = ref(false);
const errorMessage = ref('');
const currentView = ref('table'); // Default to table view
const asistenciasList = computed(() => asistenciasStore.asistencias);
onMounted(async () => {
@@ -69,6 +100,14 @@ const handleEditAsistencia = (asistenciaId) => {
router.push({ name: 'asistencias-edit', params: { id: asistenciaId } });
};
const btnClass = (view) => {
const baseClasses = 'px-4 py-2 rounded-md text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2';
if (currentView.value === view) {
return `${baseClasses} text-white shadow-sm view-toggle-active-asistencias`;
}
return `${baseClasses} bg-gray-200 text-gray-700 hover:bg-gray-300 focus:ring-gray-400`;
};
</script>
<style scoped>
@@ -140,4 +179,12 @@ const handleEditAsistencia = (asistenciaId) => {
color: #343a40;
border: 1px solid #e9ecef;
}
/* Added for view toggle buttons */
.view-toggle-active-asistencias {
background-color: var(--accent-color-asistencias);
/* Assuming --background-color is defined globally or use a fallback like #fff */
/* For Tailwind, theme('colors.white') could be an option if JIT is enabled and configured */
box-shadow: 0 0 0 2px var(--background-color, #fff), 0 0 0 4px var(--accent-color-asistencias);
}
</style>

View File

@@ -7,6 +7,16 @@
</button>
</header>
<div class="mb-6 flex justify-end items-center space-x-3">
<span class="text-sm font-medium text-gray-700">Cambiar Vista:</span>
<button @click="currentView = 'card'" :class="btnClass('card')">
Tarjetas
</button>
<button @click="currentView = 'table'" :class="btnClass('table')">
Tabla
</button>
</div>
<div v-if="isLoading" class="loading-message">
Cargando planillas...
</div>
@@ -17,12 +27,30 @@
</div>
<div v-else>
<tabla-planillas
:planillas="planillasList"
@edit="handleEditPlanilla"
/>
<div v-if="!planillasList || planillasList.length === 0 && !isLoading" class="no-data-message">
No hay planillas registradas. Puede crear una nueva haciendo clic en el botón de arriba.
<!-- Vista de Tabla -->
<div v-if="currentView === 'table'">
<tabla-planillas
:planillas="planillasList"
@edit="handleEditPlanilla"
/>
<div v-if="planillasList.length === 0 && !isLoading" class="no-data-message">
No hay planillas para mostrar en la vista de tabla.
</div>
</div>
<!-- Vista de Tarjetas -->
<div v-if="currentView === 'card'">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<CardPlanilla
v-for="planilla in planillasList"
:key="planilla.id"
:planilla="planilla"
@edit="handleEditPlanilla"
/>
</div>
<div v-if="planillasList.length === 0 && !isLoading" class="no-data-message">
No hay planillas para mostrar en la vista de tarjetas.
</div>
</div>
</div>
@@ -34,6 +62,7 @@ import { ref, computed, onMounted } from 'vue';
import { usePlanillasStore } from '../../stores/usePlanillas';
import { useRouter } from 'vue-router';
import TablaPlanillas from '../../components/planillas/tablaPlanillas.vue'; // Corrected path
import CardPlanilla from '../../components/planillas/cardPlanilla.vue';
const planillasStore = usePlanillasStore();
const router = useRouter();
@@ -42,6 +71,8 @@ const isLoading = ref(true); // Set to true initially
const errorLoading = ref(false);
const errorMessage = ref('');
const currentView = ref('table'); // Default to table view
// Computed property to get planillas from the store
const planillasList = computed(() => planillasStore.planillas);
@@ -75,6 +106,14 @@ const handleEditPlanilla = (planillaId) => {
router.push({ name: 'planillas-edit', params: { id: planillaId } });
};
const btnClass = (view) => {
const baseClasses = 'px-4 py-2 rounded-md text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2';
if (currentView.value === view) {
return `${baseClasses} text-white shadow-sm view-toggle-active-planillas`;
}
return `${baseClasses} bg-gray-200 text-gray-700 hover:bg-gray-300 focus:ring-gray-400`;
};
</script>
<style scoped>
@@ -149,4 +188,10 @@ const handleEditPlanilla = (planillaId) => {
/* Styling for the imported tablaPlanillas can be managed within its own component,
but you can add overrides or container styles here if needed. */
/* Added for view toggle buttons */
.view-toggle-active-planillas {
background-color: var(--accent-color-planillas);
box-shadow: 0 0 0 2px var(--background-color, #fff), 0 0 0 4px var(--accent-color-planillas);
}
</style>

View File

@@ -7,6 +7,16 @@
</button>
</header>
<div class="mb-6 flex justify-end items-center space-x-3">
<span class="text-sm font-medium text-gray-700">Cambiar Vista:</span>
<button @click="currentView = 'card'" :class="btnClass('card')">
Tarjetas
</button>
<button @click="currentView = 'table'" :class="btnClass('table')">
Tabla
</button>
</div>
<div v-if="isLoading" class="loading-message">
Cargando tareas...
</div>
@@ -17,12 +27,30 @@
</div>
<div v-else>
<tabla-tareas
:tareas="tareasList"
@edit="handleEditTarea"
/>
<div v-if="!tareasList || tareasList.length === 0 && !isLoading" class="no-data-message">
No hay tareas registradas. Puede crear una nueva haciendo clic en el botón de arriba.
<!-- Vista de Tabla -->
<div v-if="currentView === 'table'">
<tabla-tareas
:tareas="tareasList"
@edit="handleEditTarea"
/>
<div v-if="tareasList.length === 0 && !isLoading" class="no-data-message">
No hay tareas para mostrar en la vista de tabla.
</div>
</div>
<!-- Vista de Tarjetas -->
<div v-if="currentView === 'card'">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<CardTarea
v-for="tarea in tareasList"
:key="tarea.id"
:tarea="tarea"
@edit="handleEditTarea"
/>
</div>
<div v-if="tareasList.length === 0 && !isLoading" class="no-data-message">
No hay tareas para mostrar en la vista de tarjetas.
</div>
</div>
</div>
@@ -34,6 +62,7 @@ import { ref, computed, onMounted } from 'vue';
import { useTareasStore } from '../../stores/useTareas';
import { useRouter } from 'vue-router';
import TablaTareas from '../../components/tareas/tablaTareas.vue';
import CardTarea from '../../components/tareas/cardTarea.vue';
const tareasStore = useTareasStore();
const router = useRouter();
@@ -42,6 +71,8 @@ const isLoading = ref(true);
const errorLoading = ref(false);
const errorMessage = ref('');
const currentView = ref('table'); // Default to table view
const tareasList = computed(() => tareasStore.tareas);
onMounted(async () => {
@@ -69,6 +100,14 @@ const handleEditTarea = (tareaId) => {
router.push({ name: 'tareas-edit', params: { id: tareaId } });
};
const btnClass = (view) => {
const baseClasses = 'px-4 py-2 rounded-md text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2';
if (currentView.value === view) {
return `${baseClasses} text-white shadow-sm view-toggle-active-tareas`;
}
return `${baseClasses} bg-gray-200 text-gray-700 hover:bg-gray-300 focus:ring-gray-400`;
};
</script>
<style scoped>
@@ -140,4 +179,10 @@ const handleEditTarea = (tareaId) => {
color: #495057;
border: 1px solid #ced4da;
}
/* Added for view toggle buttons */
.view-toggle-active-tareas {
background-color: var(--accent-color-tareas);
box-shadow: 0 0 0 2px var(--background-color, #fff), 0 0 0 4px var(--accent-color-tareas);
}
</style>