117 lines
4.1 KiB
Vue
117 lines
4.1 KiB
Vue
<script setup>
|
|
import { watchEffect, computed } from 'vue' // Added computed
|
|
import TopBar from '@/components/ui/TopBar.vue'
|
|
import NavBar from '@/components/ui/NavBar.vue'
|
|
import FloatingChat from '@/components/chat/FloatingChat.vue'
|
|
import SnackbarContainer from '@/components/ui/SnackbarContainer.vue'
|
|
|
|
import { useUi } from '@/stores/useUi'
|
|
|
|
const ui = useUi()
|
|
|
|
watchEffect(() => {
|
|
const root = document.documentElement
|
|
|
|
root.style.setProperty('--primary-color', ui.primaryColor)
|
|
root.style.setProperty('--secondary-color', ui.secondaryColor)
|
|
root.style.setProperty('--warning-color', ui.warningColor)
|
|
root.style.setProperty('--background-color', ui.backgroundColor)
|
|
root.style.setProperty('--font-family', ui.fontFamily)
|
|
root.style.setProperty('--font-size', `${ui.fontSize}px`)
|
|
|
|
// Module-specific accent colors
|
|
root.style.setProperty('--accent-color-empleados', ui.accentColorEmpleados)
|
|
root.style.setProperty('--accent-color-tareas', ui.accentColorTareas)
|
|
root.style.setProperty('--accent-color-planillas', ui.accentColorPlanillas)
|
|
root.style.setProperty('--accent-color-asistencias', ui.accentColorAsistencias)
|
|
// Note: Configuracion accent color is missing here, should be added if used for CSS vars.
|
|
// root.style.setProperty('--accent-color-configuracion', ui.accentColorConfiguracion)
|
|
|
|
|
|
// Per-module table background colors
|
|
root.style.setProperty('--table-bg-color-empleados', ui.tableBgColorEmpleados)
|
|
root.style.setProperty('--table-bg-color-tareas', ui.tableBgColorTareas)
|
|
root.style.setProperty('--table-bg-color-planillas', ui.tableBgColorPlanillas)
|
|
root.style.setProperty('--table-bg-color-asistencias', ui.tableBgColorAsistencias)
|
|
root.style.setProperty('--table-bg-color-configuracion', ui.tableBgColorConfiguracion)
|
|
|
|
if (ui.theme === 'dark') {
|
|
root.classList.add('theme-dark')
|
|
root.classList.remove('theme-light')
|
|
} else {
|
|
root.classList.add('theme-light')
|
|
root.classList.remove('theme-dark')
|
|
}
|
|
|
|
if (ui.animationsEnabled) {
|
|
root.classList.remove('animations-disabled')
|
|
} else {
|
|
root.classList.add('animations-disabled')
|
|
}
|
|
})
|
|
|
|
const transitionDurationStyle = computed(() => {
|
|
// Assuming base duration of 0.3s for normal speed (transitionSpeed = 1)
|
|
const baseDuration = 0.3
|
|
const effectiveDuration = baseDuration * ui.transitionSpeed
|
|
return {
|
|
'--current-transition-duration': `${effectiveDuration}s`
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<!-- TopBar fija -->
|
|
<TopBar />
|
|
|
|
<!-- wrapper: deja espacio para TopBar (pt-14 = 56px) y, en desktop, para NavBar (pl-60) -->
|
|
<div :class="[
|
|
'pt-14 min-h-screen transition-[padding-left] duration-200',
|
|
(ui.sidebarOpen && ui.desktopNavbarPersistent) ? 'md:pl-60' : '',
|
|
// The global style.css will handle base background and text color via body styling
|
|
// but we can keep specific overrides here if needed or theme classes.
|
|
// ui.theme === 'dark' ? 'bg-gray-800 text-gray-100' : 'bg-gray-100 text-gray-900'
|
|
]" :style="transitionDurationStyle">
|
|
<!-- NavBar fija -->
|
|
<NavBar />
|
|
<FloatingChat />
|
|
|
|
<!-- contenido principal -->
|
|
<main class="min-h-[calc(100vh-56px)] flex flex-col overflow-hidden">
|
|
<router-view v-slot="{ Component }">
|
|
<transition name="slide-fade" mode="out-in">
|
|
<component :is="Component" class="flex-1 overflow-auto" />
|
|
</transition>
|
|
</router-view>
|
|
</main>
|
|
<SnackbarContainer />
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
/* Scoped styles remain, global styles are in style.css */
|
|
/* We can add specific App.vue styling here if needed, that doesn't rely on theme variables directly */
|
|
|
|
.slide-fade-enter-active,
|
|
.slide-fade-leave-active {
|
|
transition: all var(--current-transition-duration) ease-out; /* Use the CSS variable */
|
|
}
|
|
|
|
.slide-fade-enter-from {
|
|
opacity: 0;
|
|
transform: translateX(-20px); /* Slide in from the left */
|
|
}
|
|
|
|
.slide-fade-leave-to {
|
|
opacity: 0;
|
|
transform: translateX(20px); /* Slide out to the right */
|
|
}
|
|
|
|
/* Ensure content is fully opaque and in place when active/not transitioning */
|
|
.slide-fade-enter-to,
|
|
.slide-fade-leave-from {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
</style>
|