170 lines
8.3 KiB
Vue
170 lines
8.3 KiB
Vue
<template>
|
|
<div class="private-layout min-h-screen text-white">
|
|
<!-- Modular header with BaseHeader + Lego components -->
|
|
<BaseHeader>
|
|
<template #left>
|
|
<HeaderLogo />
|
|
</template>
|
|
|
|
<template #center>
|
|
<!-- Center slot: kept empty for breathing space -->
|
|
</template>
|
|
|
|
<template #right>
|
|
<!-- Language Switcher -->
|
|
<LanguageSwitcher />
|
|
|
|
<!-- Hamburger Menu (Private Garage Navigation) -->
|
|
<div class="relative hamburger-container">
|
|
<button
|
|
@click.stop="isHamburgerOpen = !isHamburgerOpen"
|
|
class="flex h-9 w-9 items-center justify-center rounded-lg text-white/60 hover:text-white hover:bg-white/10 transition-all duration-200 cursor-pointer"
|
|
:aria-label="t('header.menu')"
|
|
:title="t('header.menu')"
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Hamburger Dropdown -->
|
|
<Transition
|
|
enter-active-class="transition duration-150 ease-out"
|
|
enter-from-class="scale-95 opacity-0 -translate-y-2"
|
|
enter-to-class="scale-100 opacity-100 translate-y-0"
|
|
leave-active-class="transition duration-100 ease-in"
|
|
leave-from-class="scale-100 opacity-100 translate-y-0"
|
|
leave-to-class="scale-95 opacity-0 -translate-y-2"
|
|
>
|
|
<div
|
|
v-if="isHamburgerOpen"
|
|
class="absolute right-0 top-full mt-2 w-56 z-50 rounded-xl border border-white/10 bg-[#04151F]/95 backdrop-blur-xl shadow-2xl shadow-black/40 overflow-hidden"
|
|
>
|
|
<div class="py-1">
|
|
<!-- Vezérlőpult (Dashboard) -->
|
|
<button
|
|
@click="navigateToDashboard"
|
|
class="flex w-full items-center gap-3 px-4 py-2.5 text-sm text-white/80 transition-all duration-150 hover:bg-white/5 hover:text-white"
|
|
>
|
|
<svg class="w-4 h-4 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
|
</svg>
|
|
{{ t('header.dashboard') }}
|
|
</button>
|
|
|
|
<!-- Járművek -->
|
|
<button
|
|
@click="navigateToCard('vehicles')"
|
|
class="flex w-full items-center gap-3 px-4 py-2.5 text-sm text-white/80 transition-all duration-150 hover:bg-white/5 hover:text-white"
|
|
>
|
|
<svg class="w-4 h-4 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
</svg>
|
|
{{ t('menu.garage') }}
|
|
</button>
|
|
|
|
<!-- Költségek -->
|
|
<button
|
|
@click="navigateToCard('costs')"
|
|
class="flex w-full items-center gap-3 px-4 py-2.5 text-sm text-white/80 transition-all duration-150 hover:bg-white/5 hover:text-white"
|
|
>
|
|
<svg class="w-4 h-4 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
{{ t('menu.finance') }}
|
|
</button>
|
|
|
|
<!-- Szerviz kereső (belső) -->
|
|
<button
|
|
@click="navigateToCard('service')"
|
|
class="flex w-full items-center gap-3 px-4 py-2.5 text-sm text-white/80 transition-all duration-150 hover:bg-white/5 hover:text-white"
|
|
>
|
|
<svg class="w-4 h-4 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
</svg>
|
|
{{ t('menu.features') }}
|
|
</button>
|
|
|
|
<!-- Szervíz (külső oldal) -->
|
|
<button
|
|
@click="openExternalServiceFinder"
|
|
class="flex w-full items-center gap-3 px-4 py-2.5 text-sm text-white/80 transition-all duration-150 hover:bg-white/5 hover:text-white"
|
|
>
|
|
<svg class="w-4 h-4 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
|
</svg>
|
|
{{ t('menu.service') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</div>
|
|
|
|
<HeaderCompanySwitcher />
|
|
<HeaderProfile />
|
|
</template>
|
|
</BaseHeader>
|
|
|
|
<!-- Main content slot for child routes -->
|
|
<main class="relative z-10">
|
|
<router-view />
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useAuthStore } from '../stores/auth'
|
|
import BaseHeader from '../components/layout/BaseHeader.vue'
|
|
import HeaderLogo from '../components/header/HeaderLogo.vue'
|
|
import HeaderCompanySwitcher from '../components/header/HeaderCompanySwitcher.vue'
|
|
import HeaderProfile from '../components/header/HeaderProfile.vue'
|
|
import LanguageSwitcher from '../components/LanguageSwitcher.vue'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const { t } = useI18n()
|
|
const authStore = useAuthStore()
|
|
|
|
// ── Hamburger Menu State ──────────────────────────────────────────
|
|
const isHamburgerOpen = ref(false)
|
|
|
|
// ── Navigate to dashboard with card query param ────────────────────
|
|
function navigateToCard(cardId: string) {
|
|
isHamburgerOpen.value = false
|
|
// 'vehicles' opens the flip modal with PrivateVehicleManager
|
|
// 'costs' and 'service' navigate to dashboard where their cards are already visible inline
|
|
if (cardId === 'costs' || cardId === 'service') {
|
|
router.push('/dashboard')
|
|
} else {
|
|
router.push({ path: '/dashboard', query: { card: cardId } })
|
|
}
|
|
}
|
|
|
|
// ── Navigate to Service Finder page (same tab) ─────────────────────
|
|
function openExternalServiceFinder() {
|
|
isHamburgerOpen.value = false
|
|
router.push('/dashboard/service-finder')
|
|
}
|
|
|
|
// ── Navigate to Dashboard homepage ─────────────────────────────────
|
|
function navigateToDashboard() {
|
|
isHamburgerOpen.value = false
|
|
router.push('/dashboard')
|
|
}
|
|
|
|
// ── Close hamburger on outside click ──────────────────────────────
|
|
function handleOutsideClick(e: MouseEvent) {
|
|
const target = e.target as HTMLElement
|
|
if (isHamburgerOpen.value && !target.closest('.hamburger-container')) {
|
|
isHamburgerOpen.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => document.addEventListener('mousedown', handleOutsideClick))
|
|
onUnmounted(() => document.removeEventListener('mousedown', handleOutsideClick))
|
|
</script>
|