Refactor: Standardize UI for Empleados and Chat modules
This commit brings the Empleados and Chat UI modules more in line with the visual and functional conventions established by other modules in your application, particularly Planillas.
**Key Changes for Empleados Module:**
- **`EmpleadosIndex.vue`:**
- Standardized page header structure and styling (title, create button).
- Removed extra descriptive paragraph from header.
- Aligned styling for loading, error, and no-data messages with other modules.
- Create button icon removed for consistency.
- **`cardEmpleado.vue`:**
- Edit action now emits an event instead of direct navigation.
- Added a delete button with confirmation and store integration.
- Converted component from TypeScript to JavaScript.
- Adjusted layout for consistency with other card components.
- **`tablaEmpleados.vue`:**
- Edit action now emits an event.
- Removed the "View Details" button to streamline actions.
- Added a delete button with confirmation and store integration.
- Converted component from TypeScript to JavaScript.
- Ensured action button styling and no-data messages are consistent.
**Key Changes for Chat Module:**
- **`ChatView.vue`:**
- Added a standard page header with the title "Chat".
- **`CanvasChat.vue`:**
- Standardized styling for the message input textarea and send button, using the new `accent-color-chat`.
- Updated message bubble colors for user (using `accent-color-chat`) and bot messages for better theme alignment.
- Adjusted custom scrollbar colors to use `accent-color-chat`.
- **`useUi.js` (UI Store):**
- Added `accentColorChat` to the store's state, appearance keys, and actions, allowing it to be configurable and persisted. Defaulted to Teal (#0D9488).
These changes aim to provide a more cohesive user experience across your application by ensuring that common UI elements and interactions behave and look similar in the Empleados and Chat modules as they do elsewhere.
This commit is contained in:
@@ -4,11 +4,34 @@ import CanvasChat from '@/components/chat/CanvasChat.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full flex flex-col">
|
||||
<CanvasChat class="flex-1" />
|
||||
<div class="chat-view-container flex flex-col h-full">
|
||||
<header class="page-header">
|
||||
<h1>Chat</h1>
|
||||
</header>
|
||||
<CanvasChat class="flex-1 min-h-0" /> <!-- Added min-h-0 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* nada por ahora */
|
||||
.chat-view-container {
|
||||
/* Ensures the container itself takes full height if not already globally managed */
|
||||
/* No padding or max-width needed here to allow CanvasChat to control its layout */
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between; /* Consistent with other headers, even if no button on right */
|
||||
align-items: center;
|
||||
margin-bottom: 25px; /* Consistent with PlanillasIndex */
|
||||
padding: 10px 20px; /* Provides padding for the header itself */
|
||||
border-bottom: 1px solid #eee; /* Consistent with PlanillasIndex */
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
color: var(--accent-color-chat, var(--default-accent-color, #3498db)); /* Fallback color strategy */
|
||||
font-size: 2.2em; /* Consistent with PlanillasIndex */
|
||||
font-weight: 600; /* Consistent with PlanillasIndex */
|
||||
}
|
||||
|
||||
/* CanvasChat is expected to manage its own internal padding and scrolling */
|
||||
</style>
|
||||
|
||||
@@ -26,6 +26,26 @@
|
||||
<input type="checkbox" id="desktopNavbarPersistent" v-model="ui.desktopNavbarPersistent" @change="ui.setDesktopNavbarPersistent($event.target.checked)"
|
||||
class="custom-checkbox relative w-10 h-5 appearance-none bg-gray-300 dark:bg-gray-600 rounded-full cursor-pointer transition-colors duration-300 ease-in-out checked:bg-[var(--primary-color)] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--primary-color)] focus:ring-offset-[var(--background-color)]">
|
||||
</div>
|
||||
|
||||
<!-- Animation Speed Setting -->
|
||||
<div class="setting-item mt-6 md:col-span-2"> <!-- md:col-span-2 to make it take full width on medium screens if the grid has 2 columns -->
|
||||
<label class="block text-sm font-medium mb-1 text-[var(--text-color)]">Animation Speed</label>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mb-2">
|
||||
Adjust the speed of screen transitions (applied if animations are enabled).
|
||||
</p>
|
||||
<div class="flex flex-col space-y-1 sm:flex-row sm:space-y-0 sm:space-x-4">
|
||||
<label v-for="option in speedOptions" :key="option.value"
|
||||
class="flex items-center p-2 rounded-md hover:bg-gray-200/50 dark:hover:bg-gray-700/50 cursor-pointer transition-colors duration-150 ease-in-out border border-gray-300 dark:border-gray-600 hover:border-[var(--primary-color)]">
|
||||
<input type="radio"
|
||||
name="transitionSpeed"
|
||||
:value="option.value"
|
||||
:checked="ui.transitionSpeed === option.value"
|
||||
@change="ui.setTransitionSpeed(option.value)"
|
||||
class="form-radio h-4 w-4 text-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)] border-gray-300 dark:border-gray-500 bg-white dark:bg-gray-800 focus:ring-offset-white dark:focus:ring-offset-gray-900">
|
||||
<span class="ml-2 text-sm text-[var(--text-color)]">{{ option.label }} <span class="text-xs text-gray-500 dark:text-gray-400">({{ option.value }}x)</span></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -211,6 +231,12 @@ onMounted(() => {
|
||||
isMounted.value = true
|
||||
}, 50)
|
||||
})
|
||||
|
||||
const speedOptions = [
|
||||
{ label: 'Slow', value: 2 },
|
||||
{ label: 'Normal', value: 1 },
|
||||
{ label: 'Fast', value: 0.5 },
|
||||
]
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="asistencia-form-container">
|
||||
<div class="asistencia-form-container" :style="{ backgroundColor: uiStore.tableBgColorAsistencias }">
|
||||
<h2>{{ formTitle }}</h2>
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="form-group">
|
||||
@@ -48,6 +48,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue';
|
||||
import { useAsistenciasStore } from '../../stores/useAsistencias';
|
||||
import { useUi } from '@/stores/useUi'; // Corrected UI store import
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
|
||||
const props = defineProps({
|
||||
@@ -57,6 +58,7 @@ const props = defineProps({
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const asistenciasStore = useAsistenciasStore();
|
||||
const uiStore = useUi(); // Corrected UI store instantiation
|
||||
|
||||
const formatDateTimeForInput = (dateString) => {
|
||||
const date = dateString ? new Date(dateString) : new Date();
|
||||
@@ -207,7 +209,7 @@ const handleCancel = () => {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 25px;
|
||||
background-color: #f9f9f9;
|
||||
/* background-color: #f9f9f9; */ /* Removed to use dynamic background */
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
<form
|
||||
@submit.prevent="handleSubmit"
|
||||
class="max-w-lg mx-auto bg-white p-8 rounded-lg shadow-lg"
|
||||
class="max-w-lg mx-auto p-8 rounded-lg shadow-lg"
|
||||
:style="{ backgroundColor: uiStore.tableBgColorEmpleados }"
|
||||
>
|
||||
<!-- ───────── Nombre ───────── -->
|
||||
<div class="mb-6">
|
||||
@@ -149,6 +150,7 @@ import { ref, onMounted, computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEmpleadosStore } from '@/stores/useEmpleados.js'
|
||||
import { useUi } from '@/stores/useUi'; // Corrected UI store import
|
||||
|
||||
/* ───── Tipos ───── */
|
||||
interface EmpleadoForm {
|
||||
@@ -179,6 +181,7 @@ const router = useRouter()
|
||||
/* ───── Store ───── */
|
||||
const empleadosStore = useEmpleadosStore()
|
||||
const { currentEmpleado } = storeToRefs(empleadosStore)
|
||||
const uiStore = useUi(); // Corrected UI store instantiation
|
||||
|
||||
/* ───── State ───── */
|
||||
const form = ref<EmpleadoForm>(defaultForm())
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<template>
|
||||
<div class="empleados-index-container">
|
||||
<!-- … encabezado … -->
|
||||
<header class="page-header">
|
||||
<h1>Gestión de Empleados</h1>
|
||||
<button @click="goToCreateEmployee" class="btn-create">
|
||||
<!-- í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>
|
||||
</header>
|
||||
@@ -33,12 +30,11 @@
|
||||
|
||||
<!-- contenido -->
|
||||
<div>
|
||||
<div v-if="loading" class="loading-message">
|
||||
Cargando empleados...
|
||||
</div>
|
||||
<div v-if="loading" class="loading-message">Cargando empleados...</div>
|
||||
|
||||
<div v-else-if="error" class="error-message-full">
|
||||
<p>Error al cargar los empleados: {{ error }}</p>
|
||||
<p>Error al cargar los empleados. Por favor, intente de nuevo más tarde.</p>
|
||||
<p v-if="error">Detalle: {{ error }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
@@ -52,15 +48,15 @@
|
||||
:key="employee.id"
|
||||
:employee="employee"
|
||||
/>
|
||||
<div v-if="employees.length === 0" class="no-data-message">
|
||||
No hay empleados para mostrar en la vista de tarjetas.
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="currentView === 'card' && employees.length === 0 && !loading" class="no-data-message">
|
||||
No hay empleados para mostrar en la vista de tarjetas.
|
||||
</div>
|
||||
|
||||
<!-- vista de tabla -->
|
||||
<div v-if="currentView === 'table'">
|
||||
<TablaEmpleados :employees="employees" />
|
||||
<div v-if="employees.length === 0" class="no-data-message">
|
||||
<div v-if="employees.length === 0 && !loading" class="no-data-message">
|
||||
No hay empleados para mostrar en la vista de tabla.
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,8 +94,7 @@ const employees = empleados;
|
||||
const btnViewClass = (viewType: 'card' | 'table') => {
|
||||
const base = 'p-2 rounded-md transition-colors duration-150 ease-in-out';
|
||||
if (currentView.value === viewType) {
|
||||
// Apply the dedicated class for active state which includes focus styles, and add shadow-lg for general active appearance
|
||||
return `${base} view-toggle-active shadow-lg`;
|
||||
return `${base} bg-[var(--accent-color-empleados)] text-white shadow-lg`;
|
||||
}
|
||||
return `${base} bg-gray-200 text-gray-700 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600`;
|
||||
};
|
||||
@@ -130,6 +125,7 @@ const goToCreateEmployee = () => router.push({ name: 'empleados-new' });
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
font-family: Arial, sans-serif;
|
||||
min-height: calc(100vh - var(--navbar-height, 0px)); /* Assuming --navbar-height is defined elsewhere or adjust */
|
||||
}
|
||||
|
||||
.page-header {
|
||||
@@ -161,17 +157,14 @@ const goToCreateEmployee = () => router.push({ name: 'empleados-new' });
|
||||
}
|
||||
|
||||
.btn-create:hover {
|
||||
filter: brightness(0.9); /* Darken, similar to PlanillasIndex */
|
||||
filter: brightness(0.9);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.btn-create:focus {
|
||||
outline: none; /* Remove default outline */
|
||||
box-shadow: 0 0 0 2px var(--background-color, #fff), 0 0 0 4px var(--accent-color-empleados); /* Replicate Planillas focus */
|
||||
box-shadow: 0 0 0 2px var(--background-color, #fff), 0 0 0 4px var(--accent-color-empleados);
|
||||
}
|
||||
|
||||
|
||||
/* Styles for loading, error, no-data messages, adapted from PlanillasIndex */
|
||||
.loading-message,
|
||||
.error-message-full,
|
||||
.no-data-message {
|
||||
@@ -184,7 +177,6 @@ const goToCreateEmployee = () => router.push({ name: 'empleados-new' });
|
||||
|
||||
.loading-message {
|
||||
color: #7f8c8d; /* Gray */
|
||||
/* Consider adding a subtle background if needed, e.g., background-color: #f8f9f9; */
|
||||
}
|
||||
|
||||
.error-message-full {
|
||||
@@ -193,24 +185,17 @@ const goToCreateEmployee = () => router.push({ name: 'empleados-new' });
|
||||
border: 1px solid #f5b7b1; /* Light red border */
|
||||
}
|
||||
.error-message-full p {
|
||||
margin: 5px 0; /* Consistent with Planillas */
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.no-data-message {
|
||||
background-color: #eafaf1; /* Lighter green/blue */
|
||||
color: #2ecc71; /* Green */
|
||||
border: 1px solid #a3e4d7; /* Light green/blue border */
|
||||
/* If using accent color for these messages:
|
||||
background-color: var(--accent-color-empleados-light);
|
||||
color: var(--accent-color-empleados-dark);
|
||||
border: 1px solid var(--accent-color-empleados);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
.view-toggle-active { /* Class for active view toggle button */
|
||||
.view-toggle-active {
|
||||
background-color: var(--accent-color-empleados);
|
||||
color: white; /* Ensure text is white for contrast */
|
||||
/* For focus, assuming white text on accent. Adjust if needed. */
|
||||
box-shadow: 0 0 0 2px var(--background-color, #fff), 0 0 0 4px var(--accent-color-empleados);
|
||||
}
|
||||
@@ -218,7 +203,4 @@ const goToCreateEmployee = () => router.push({ name: 'empleados-new' });
|
||||
|
||||
.view-enter-active, .view-leave-active { transition: opacity .3s ease; }
|
||||
.view-enter-from, .view-leave-to { opacity: 0; }
|
||||
|
||||
/* Remove min-h-screen if .empleados-index-container handles height/layout sufficiently */
|
||||
/* .min-h-screen { min-height: calc(100vh - var(--navbar-height, 0px)); } */
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="planilla-form-container">
|
||||
<div class="planilla-form-container" :style="{ backgroundColor: uiStore.tableBgColorPlanillas }">
|
||||
<h2>{{ formTitle }}</h2>
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="form-group">
|
||||
@@ -53,6 +53,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed, watch } from 'vue';
|
||||
import { usePlanillasStore } from '../../stores/usePlanillas';
|
||||
import { useUi } from '@/stores/useUi'; // Corrected UI store import
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
|
||||
const props = defineProps({
|
||||
@@ -63,6 +64,7 @@ const router = useRouter();
|
||||
const route = useRoute(); // Can also get id from route.params.id
|
||||
|
||||
const planillasStore = usePlanillasStore();
|
||||
const uiStore = useUi(); // Corrected UI store instantiation
|
||||
|
||||
const formData = reactive({
|
||||
titulo: '',
|
||||
@@ -215,7 +217,7 @@ const handleCancel = () => {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
background-color: #f9f9f9;
|
||||
/* background-color: #f9f9f9; */ /* Removed to use dynamic background */
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="tarea-form-container">
|
||||
<div class="tarea-form-container" :style="{ backgroundColor: uiStore.tableBgColorTareas }">
|
||||
<h2>{{ formTitle }}</h2>
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="form-group">
|
||||
@@ -65,6 +65,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue';
|
||||
import { useTareasStore } from '../../stores/useTareas';
|
||||
import { useUi } from '@/stores/useUi'; // Corrected UI store import
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
|
||||
const props = defineProps({
|
||||
@@ -74,6 +75,7 @@ const props = defineProps({
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const tareasStore = useTareasStore();
|
||||
const uiStore = useUi(); // Corrected UI store instantiation
|
||||
|
||||
const formatDateForInput = (dateString) => {
|
||||
const date = dateString ? new Date(dateString) : new Date();
|
||||
@@ -227,7 +229,7 @@ const handleCancel = () => {
|
||||
max-width: 650px;
|
||||
margin: 20px auto;
|
||||
padding: 25px;
|
||||
background-color: #f9f9f9;
|
||||
/* background-color: #f9f9f9; */ /* Removed to use dynamic background */
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user