|
|
|
|
@ -4,65 +4,76 @@
|
|
|
|
|
import {dataApp} from "../../data/data_app";
|
|
|
|
|
import { navegationState, type PageId } from "../stores/navegation.svelte.js";
|
|
|
|
|
import PdfBoton from "./PdfBoton.svelte";
|
|
|
|
|
import { fade, slide } from 'svelte/transition';
|
|
|
|
|
|
|
|
|
|
let mobileMenuOpen = $state(false);
|
|
|
|
|
|
|
|
|
|
function toggleMobileMenu () : void { mobileMenuOpen = !mobileMenuOpen; }
|
|
|
|
|
function toggleMobileMenu () : void {
|
|
|
|
|
mobileMenuOpen = !mobileMenuOpen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleOnclick (sectionId: PageId) {
|
|
|
|
|
navegationState.activePage = sectionId;
|
|
|
|
|
mobileMenuOpen = false;
|
|
|
|
|
mobileMenuOpen = false; // Cierra menú móvil al seleccionar
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Nueva función para cerrar menú al hacer click fuera (opcional)
|
|
|
|
|
function handleBackdropClick(event: MouseEvent) {
|
|
|
|
|
if ((event.target as HTMLElement).classList.contains('mobile-menu-backdrop')) {
|
|
|
|
|
mobileMenuOpen = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<nav class="bg-white shadow-md border-b border-gray-200 sticky top-0 z-50">
|
|
|
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
|
|
|
<div class="flex justify-between items-center h-16">
|
|
|
|
|
<div class="flex-shrink-0">
|
|
|
|
|
<div class="flex items-center">
|
|
|
|
|
|
|
|
|
|
<div role="button"
|
|
|
|
|
tabindex="0"
|
|
|
|
|
class="text-white px-3 py-2 rounded-md font-bold text-lg">
|
|
|
|
|
<a href={empresaData.url} target="_blank">
|
|
|
|
|
<img src={empresaData.logos.default} alt={empresaData.nombre} class="h-16 p-1.5 object-contain" />
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<span class="ml-2 sm:ml-4 text-gray-500 font-bold uppercase tracking-widest text-xl sm:text-1+xl truncate max-w-32 sm:max-w-none">
|
|
|
|
|
{dataApp.titulo}
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
role="button"
|
|
|
|
|
tabindex="0"
|
|
|
|
|
class="ml-2 sm:ml-4 text-gray-600 font-medium text-sm sm:text-base truncate max-w-32 sm:max-w-none cursor-pointer"
|
|
|
|
|
onclick={() => handleOnclick('ini') }
|
|
|
|
|
onkeydown={(e) => { if (e.key === 'Enter' || e.key === 'Space') handleOnclick('ini'); } }
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
<img src={proyecto.logos.default} alt={proyecto.nombre} class="h-16 p-1.5 object-contain" />
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
<!-- Logo y branding - Más compacto en mobile -->
|
|
|
|
|
<div class="flex-shrink-0 flex items-center space-x-2 sm:space-x-4">
|
|
|
|
|
<!-- Logo empresa - Más pequeño en mobile -->
|
|
|
|
|
<div role="button" tabindex="0" class="flex-shrink-0">
|
|
|
|
|
<a href={empresaData.url} target="_blank" rel="noopener noreferrer">
|
|
|
|
|
<img
|
|
|
|
|
src={empresaData.logos.default}
|
|
|
|
|
alt={empresaData.nombre}
|
|
|
|
|
class="h-10 sm:h-12 lg:h-14 p-1 object-contain transition-all duration-200 hover:scale-105"
|
|
|
|
|
/>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Título app - Más compacto y truncado en mobile -->
|
|
|
|
|
<span class="hidden sm:block text-black-600 font-bold uppercase tracking-wider text-center
|
|
|
|
|
sm:text-sx lg:text-xl truncate max-w-xs sm:max-w-none">
|
|
|
|
|
{dataApp.titulo}
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<!-- Logo proyecto - Oculto en mobile muy pequeño, visible en sm+ -->
|
|
|
|
|
<!-- CORRECTO - Clases combinadas -->
|
|
|
|
|
<div class="sm:flex sm:ml-2 lg:ml-4 items-center text-gray-600 font-medium cursor-pointer"
|
|
|
|
|
role="button" tabindex="0"
|
|
|
|
|
onclick={() => handleOnclick('ini')}
|
|
|
|
|
onkeydown={(e) => { if (e.key === 'Enter' || e.key === 'Space') handleOnclick('ini'); }}>
|
|
|
|
|
<img
|
|
|
|
|
src={proyecto.logos.default}
|
|
|
|
|
alt={proyecto.nombre}
|
|
|
|
|
class="h-10 sm:h-12 lg:h-14 p-1 object-contain hover:scale-105 transition-transform"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="hidden md:flex space-x-1">
|
|
|
|
|
<!-- Menú desktop -->
|
|
|
|
|
<div class="hidden md:flex items-center space-x-1 lg:space-x-2">
|
|
|
|
|
{#each navegationState.sectionsInfo as section}
|
|
|
|
|
{#if section.menu }
|
|
|
|
|
<button type="button"
|
|
|
|
|
class="px-3 lg:px-4 mr-4 py-2 rounded-md text-base font-medium transition-colors duration-200 font-sans {
|
|
|
|
|
navegationState.activePage === section.id
|
|
|
|
|
? 'bg-blue-100 text-primary-700 border border-blue-200'
|
|
|
|
|
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100 cursor-pointer'
|
|
|
|
|
}"
|
|
|
|
|
onclick={() => handleOnclick(section.id) } >
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class="px-3 py-2 lg:px-4 lg:py-2 rounded-md text-sm lg:text-base font-medium
|
|
|
|
|
transition-all duration-200 font-sans hover:shadow-sm
|
|
|
|
|
{navegationState.activePage === section.id
|
|
|
|
|
? 'bg-blue-100 text-blue-700 border border-blue-200 shadow-sm'
|
|
|
|
|
: 'text-gray-600 hover:text-gray-900 hover:bg-blue-50 cursor-pointer'
|
|
|
|
|
}"
|
|
|
|
|
onclick={() => handleOnclick(section.id)}>
|
|
|
|
|
{section.label}
|
|
|
|
|
</button>
|
|
|
|
|
{/if}
|
|
|
|
|
@ -70,19 +81,26 @@
|
|
|
|
|
<PdfBoton />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="md:hidden">
|
|
|
|
|
<button type="button"
|
|
|
|
|
class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary-500"
|
|
|
|
|
<!-- Botón hamburguesa - Mejoras visuales -->
|
|
|
|
|
<div class="md:hidden flex items-center">
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class="inline-flex items-center justify-center p-2 rounded-md text-gray-400
|
|
|
|
|
hover:text-gray-600 hover:bg-gray-100 focus:outline-none focus:ring-2
|
|
|
|
|
focus:ring-inset focus:ring-blue-500 transition-colors duration-200
|
|
|
|
|
{mobileMenuOpen ? 'bg-gray-100 text-gray-600' : ''}"
|
|
|
|
|
onclick={toggleMobileMenu}
|
|
|
|
|
aria-expanded="false" >
|
|
|
|
|
<span class="sr-only">Abrir menú principal</span>
|
|
|
|
|
aria-expanded={mobileMenuOpen}
|
|
|
|
|
aria-label={mobileMenuOpen ? "Cerrar menú" : "Abrir menú"}>
|
|
|
|
|
{#if !mobileMenuOpen}
|
|
|
|
|
<svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
|
|
|
|
<!-- Icono hamburguesa -->
|
|
|
|
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
|
|
|
|
|
</svg>
|
|
|
|
|
{:else}
|
|
|
|
|
<svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
|
|
|
<!-- Icono X -->
|
|
|
|
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
|
|
|
</svg>
|
|
|
|
|
{/if}
|
|
|
|
|
</button>
|
|
|
|
|
@ -90,31 +108,63 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Menú móvil mejorado -->
|
|
|
|
|
<!-- Menú móvil con slide funcionando -->
|
|
|
|
|
{#if mobileMenuOpen}
|
|
|
|
|
<div class="md:hidden border-t border-gray-200">
|
|
|
|
|
<div class="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white">
|
|
|
|
|
{#each navegationState.sectionsInfo as section}
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class="w-full text-left px-3 py-2 rounded-md text-base font-medium transition-colors duration-200 {
|
|
|
|
|
navegationState.activePage === section.id
|
|
|
|
|
? 'bg-green-100 text-primary-700 border border-primary-200'
|
|
|
|
|
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100 cursor-pointer'
|
|
|
|
|
}"
|
|
|
|
|
onclick={() => handleOnclick(section.id)}
|
|
|
|
|
>
|
|
|
|
|
{section.label}
|
|
|
|
|
</button>
|
|
|
|
|
{/each}
|
|
|
|
|
<div
|
|
|
|
|
class="fixed inset-0 bg-black bg-opacity-50 z-40 md:hidden"
|
|
|
|
|
transition:fade={{ duration: 150 }}
|
|
|
|
|
onclick={() => mobileMenuOpen = false}>
|
|
|
|
|
|
|
|
|
|
<!-- Menú que desliza desde arriba -->
|
|
|
|
|
<div
|
|
|
|
|
class="absolute top-16 left-0 right-0 bg-white shadow-xl border-t border-gray-200
|
|
|
|
|
max-h-[calc(100vh-4rem)] overflow-y-auto"
|
|
|
|
|
transition:slide={{
|
|
|
|
|
duration: 300,
|
|
|
|
|
axis: 'Y',
|
|
|
|
|
easing: 'cubic-out'
|
|
|
|
|
}}>
|
|
|
|
|
<div class="px-2 pt-2 pb-4 space-y-1 sm:px-3">
|
|
|
|
|
{#each navegationState.sectionsInfo as section}
|
|
|
|
|
{#if section.menu }
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class="w-full text-left px-4 py-3 rounded-md text-base font-medium
|
|
|
|
|
transition-all duration-200 border-l-4
|
|
|
|
|
{navegationState.activePage === section.id
|
|
|
|
|
? 'bg-blue-50 text-blue-700 border-blue-500'
|
|
|
|
|
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-50 border-transparent'
|
|
|
|
|
}"
|
|
|
|
|
onclick={() => handleOnclick(section.id)}>
|
|
|
|
|
<div class="flex items-center justify-between">
|
|
|
|
|
<span>{section.mome ?? section.label}</span>
|
|
|
|
|
{#if navegationState.activePage === section.id}
|
|
|
|
|
<svg class="w-5 h-5 text-blue-500" fill="currentColor" viewBox="0 0 20 20">
|
|
|
|
|
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
|
|
|
|
</svg>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
{/if}
|
|
|
|
|
{/each}
|
|
|
|
|
<div class="px-4 py-3 border-t border-gray-200 mt-2">
|
|
|
|
|
<PdfBoton />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{/if}
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
button:disabled {
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
/* Smooth scroll para navegación */
|
|
|
|
|
html {
|
|
|
|
|
scroll-behavior: smooth;
|
|
|
|
|
}
|
|
|
|
|
</style>
|