Files
planilla/ui/src/views/empleados/EmpleadosIndex.vue
google-labs-jules[bot] 32aa41f59f feat: Add default index view setting for modules
This commit introduces a new customization option in the appearance settings, allowing you to choose your default index view (card or table) for each module (Empleados, Tareas, Planillas, Asistencias).

Key changes:

- **Store Updates (`useUi.js`):**
    - Added new state properties (e.g., `defaultViewEmpleados`) to store the preferred view for each module.
    - Added corresponding actions (e.g., `setDefaultViewEmpleados`) to update these settings.
    - Settings are persisted to local storage.

- **Settings UI (`SettingsView.vue`):**
    - Added dropdown selectors in the module-specific sections of the appearance settings page for you to choose 'Table' or 'Card' as your default view.
    - These selectors are bound to the new store properties.

- **Module Index Views (e.g., `EmpleadosIndex.vue`):**
    - Modified to read the default view setting from the `useUi` store.
    - Conditionally render either the table component or the card component based on this setting.
    - Removed manual view toggle buttons, as the default is now managed via settings.

- **Testing:**
    - I added unit tests for the new store actions and state.
    - I added component tests for `SettingsView.vue` to verify the new UI elements and their interaction with the store.
    - I added component tests for each module's index view to ensure they render the correct view (table or card) based on the global setting and display data or "no data" messages appropriately.

This feature provides you with more control over your preferred data display format within each module, enhancing the user experience.
2025-05-31 07:59:01 +00:00

135 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="p-6 bg-gray-50 min-h-screen">
<!-- encabezado -->
<header class="mb-8">
<div class="flex justify-between items-center">
<h1 class="text-4xl font-bold text-gray-800">Gestión de Empleados</h1>
<button
@click="goToCreateEmployee"
class="create-button px-6 py-3 text-white font-semibold rounded-lg shadow-md focus:outline-none transition duration-150 ease-in-out"
>
<!-- ícono -->
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block mr-2" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
Crear Empleado
</button>
</div>
<p class="mt-2 text-gray-600">Visualiza, crea y gestiona los empleados de la organización.</p>
</header>
<!-- selector de vista -->
<!-- Removed manual view toggle buttons -->
<!-- contenido -->
<div>
<div v-if="loading" class="text-center py-10">
<p class="text-gray-500 text-xl">Cargando empleados...</p>
</div>
<div v-else-if="error" class="text-center py-10">
<p class="text-red-500 text-xl">Error al cargar los empleados: {{ error }}</p>
</div>
<div v-else>
<!-- vista de tarjetas -->
<div
v-if="currentView === 'card'"
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"
>
<CardEmpleado
v-for="employee in employees"
:key="employee.id"
:employee="employee"
/>
<div v-if="employees.length === 0" class="col-span-full text-center py-10">
<p class="text-gray-500 text-xl">No hay empleados para mostrar en la vista de tarjetas.</p>
</div>
</div>
<!-- vista de tabla -->
<div v-if="currentView === 'table'">
<TablaEmpleados :employees="employees" />
<div
v-if="employees.length === 0"
class="text-center py-10 bg-white shadow-md rounded-lg mt-4"
>
<p class="text-gray-500 text-xl">No hay empleados para mostrar en la vista de tabla.</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { storeToRefs } from 'pinia';
import { useRouter } from 'vue-router';
import { useUi } from '@/stores/useUi'; // Import useUi
import CardEmpleado from '@/components/empleados/cardEmpleado.vue';
import TablaEmpleados from '@/components/empleados/tablaEmpleados.vue';
import { useEmpleadosStore } from '@/stores/useEmpleados.js'; // ruta según tu proyecto
// --- refs locales ---
const router = useRouter();
const ui = useUi(); // Access the ui store
const currentView = ref<'card' | 'table'>(ui.defaultViewEmpleados); // Initialize from store
const loading = ref(true);
const error = ref<string | null>(null);
// --- store ---
const empleadosStore = useEmpleadosStore();
const { empleados } = storeToRefs(empleadosStore);
// alias para plantilla
const employees = empleados;
// --- helpers ---
// Removed btnClass as manual toggle buttons are removed
// --- fetch inicial ---
const fetchEmployees = async () => {
loading.value = true;
error.value = null;
try {
await empleadosStore.fetchEmpleados();
} catch (e) {
console.error('Error al traer empleados:', e);
error.value = e instanceof Error ? e.message : 'Ocurrió un error desconocido.';
} finally {
loading.value = false;
}
};
onMounted(fetchEmployees);
// --- navegación ---
const goToCreateEmployee = () => router.push({ name: 'empleados-new' });
</script>
<style scoped>
.min-h-screen { min-height: calc(100vh - var(--navbar-height, 0px)); } /* Assuming --navbar-height is defined elsewhere or adjust */
.create-button {
background-color: var(--accent-color-empleados);
}
.create-button:hover {
filter: brightness(1.1);
}
.create-button:focus {
box-shadow: 0 0 0 2px var(--background-color), 0 0 0 4px var(--accent-color-empleados);
}
.view-toggle-active {
background-color: var(--accent-color-empleados);
/* For focus, assuming white text on accent. Adjust if needed. */
box-shadow: 0 0 0 2px var(--background-color), 0 0 0 4px var(--accent-color-empleados);
}
/* Inactive toggle button styling is handled by Tailwind classes directly in btnClass function */
.view-enter-active, .view-leave-active { transition: opacity .3s ease; }
.view-enter-from, .view-leave-to { opacity: 0; }
</style>