|
|
|
|
@ -10,32 +10,44 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="props.menu">
|
|
|
|
|
<Drawer v-model:visible="menuShow" header=" " position="right" :pt="{ root: 'border-0' }">
|
|
|
|
|
<template #header>
|
|
|
|
|
<div class="flex flex-col">
|
|
|
|
|
<div>{{ auth.user.nev }}</div>
|
|
|
|
|
<div class="text-xs">{{ auth.user.email }}</div>
|
|
|
|
|
<!-- Backdrop overlay -->
|
|
|
|
|
<div
|
|
|
|
|
class="fixed inset-0 bg-black z-40"
|
|
|
|
|
:class="backdropClass"
|
|
|
|
|
:style="{ opacity: backdropOpacity }"
|
|
|
|
|
@click="closeMenu"
|
|
|
|
|
></div>
|
|
|
|
|
|
|
|
|
|
<!-- Swipeable Drawer -->
|
|
|
|
|
<div
|
|
|
|
|
ref="drawerRef"
|
|
|
|
|
class="fixed top-0 right-0 h-full w-72 bg-surface-0 dark:bg-surface-900 z-50 shadow-xl will-change-transform"
|
|
|
|
|
:class="drawerClass"
|
|
|
|
|
:style="{ transform: `translateX(${translateX}px)` }"
|
|
|
|
|
>
|
|
|
|
|
<div class="p-4">
|
|
|
|
|
<div class="flex flex-col mb-4">
|
|
|
|
|
<div class="font-medium">{{ auth.user?.nev }}</div>
|
|
|
|
|
<div class="text-xs opacity-70">{{ auth.user?.email }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex flex-col space-y-3 text-sm">
|
|
|
|
|
<NuxtLink to="/profile" @click="closeMenu">Adataim</NuxtLink>
|
|
|
|
|
<Divider />
|
|
|
|
|
<NuxtLink
|
|
|
|
|
:to="'/page/' + p.id"
|
|
|
|
|
v-for="p in config?.config.menu"
|
|
|
|
|
:key="p.id"
|
|
|
|
|
@click="closeMenu"
|
|
|
|
|
>{{ p.label }}</NuxtLink>
|
|
|
|
|
<Divider />
|
|
|
|
|
<NuxtLink @click="logOut()">Kijelentkezés</NuxtLink>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
<div class="flex flex-col space-y-3 text-sm">
|
|
|
|
|
<NuxtLink to="/profile">Adataim</NuxtLink>
|
|
|
|
|
<Divider />
|
|
|
|
|
<NuxtLink :to="'/page/' + p.id" v-for="p in config?.config.menu">{{ p.label }}</NuxtLink>
|
|
|
|
|
<!-- <NuxtLink to="/page/72">GYIK</NuxtLink>
|
|
|
|
|
<NuxtLink to="/page/66">Autóbérlés feltételei</NuxtLink>
|
|
|
|
|
<NuxtLink to="/page/69">Általános Szerződési Feltételek</NuxtLink>
|
|
|
|
|
<NuxtLink to="/page/68">Adatvédelmi nyilatkozat</NuxtLink>
|
|
|
|
|
<NuxtLink to="/page/70">Lemondási és távolmaradási feltételek</NuxtLink>
|
|
|
|
|
<NuxtLink to="/page/65">Elérhetőség</NuxtLink> -->
|
|
|
|
|
<Divider />
|
|
|
|
|
<NuxtLink @click="logOut()">Kijelentketés</NuxtLink>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</Drawer>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Button variant="link" icon="pi pi-calendar" @click="$router.push({ path: '/' })"></Button>
|
|
|
|
|
<Button variant="link" icon="pi pi-user" @click="$router.push({ path: '/profile' })"></Button>
|
|
|
|
|
<Button variant="link" icon="pi pi-bars" @click="menuShow = true"></Button>
|
|
|
|
|
<Button variant="link" icon="pi pi-bars" @click="openMenu"></Button>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="props.title">
|
|
|
|
|
{{ props.title }}
|
|
|
|
|
@ -65,17 +77,177 @@ const auth = useAuthStore()
|
|
|
|
|
const config = useMyConfigStore()
|
|
|
|
|
|
|
|
|
|
const token = useCookie('_auth')
|
|
|
|
|
const menuShow = ref()
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
|
|
|
|
const isHome = computed(()=>{
|
|
|
|
|
return (route.fullPath === '/')
|
|
|
|
|
const isHome = computed(() => {
|
|
|
|
|
return (route.fullPath === '/')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function logOut(){
|
|
|
|
|
token.value = null
|
|
|
|
|
auth.user = null
|
|
|
|
|
router.push({path:'/login'})
|
|
|
|
|
// Drawer constants
|
|
|
|
|
const DRAWER_WIDTH = 288
|
|
|
|
|
const SWIPE_THRESHOLD = 80
|
|
|
|
|
const EDGE_ZONE = 40
|
|
|
|
|
|
|
|
|
|
// Simple state
|
|
|
|
|
const drawerRef = ref<HTMLElement | null>(null)
|
|
|
|
|
const isOpen = ref(false)
|
|
|
|
|
const isDragging = ref(false)
|
|
|
|
|
const dragOffset = ref(0) // 0 = fully open position, DRAWER_WIDTH = fully closed
|
|
|
|
|
const menuHistoryPushed = ref(false)
|
|
|
|
|
|
|
|
|
|
// Touch tracking
|
|
|
|
|
let touchStartX = 0
|
|
|
|
|
let touchStartY = 0
|
|
|
|
|
let startedFromEdge = false
|
|
|
|
|
let isHorizontalSwipe: boolean | null = null
|
|
|
|
|
|
|
|
|
|
// Computed translate value
|
|
|
|
|
const translateX = computed(() => {
|
|
|
|
|
if (isDragging.value) {
|
|
|
|
|
return Math.max(0, Math.min(DRAWER_WIDTH, dragOffset.value))
|
|
|
|
|
}
|
|
|
|
|
return isOpen.value ? 0 : DRAWER_WIDTH
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Backdrop opacity based on position
|
|
|
|
|
const backdropOpacity = computed(() => {
|
|
|
|
|
const openness = 1 - (translateX.value / DRAWER_WIDTH)
|
|
|
|
|
return openness * 0.5
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Dynamic classes
|
|
|
|
|
const drawerClass = computed(() => ({
|
|
|
|
|
'transition-transform duration-300 ease-out': !isDragging.value,
|
|
|
|
|
'pointer-events-none': !isOpen.value && !isDragging.value
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
const backdropClass = computed(() => ({
|
|
|
|
|
'transition-opacity duration-300': !isDragging.value,
|
|
|
|
|
'pointer-events-none': backdropOpacity.value <= 0
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
function openMenu() {
|
|
|
|
|
isOpen.value = true
|
|
|
|
|
if (!menuHistoryPushed.value) {
|
|
|
|
|
window.history.pushState({ menuOpen: true }, '')
|
|
|
|
|
menuHistoryPushed.value = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function closeMenu() {
|
|
|
|
|
isOpen.value = false
|
|
|
|
|
if (menuHistoryPushed.value) {
|
|
|
|
|
menuHistoryPushed.value = false
|
|
|
|
|
window.history.back()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function closeMenuWithoutHistory() {
|
|
|
|
|
isOpen.value = false
|
|
|
|
|
menuHistoryPushed.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handlePopState() {
|
|
|
|
|
if (isOpen.value) {
|
|
|
|
|
closeMenuWithoutHistory()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleTouchStart(e: TouchEvent) {
|
|
|
|
|
const touch = e.touches[0]
|
|
|
|
|
touchStartX = touch.clientX
|
|
|
|
|
touchStartY = touch.clientY
|
|
|
|
|
isHorizontalSwipe = null
|
|
|
|
|
|
|
|
|
|
const screenWidth = window.innerWidth
|
|
|
|
|
startedFromEdge = touchStartX > screenWidth - EDGE_ZONE
|
|
|
|
|
|
|
|
|
|
if (isOpen.value) {
|
|
|
|
|
dragOffset.value = 0
|
|
|
|
|
} else if (startedFromEdge) {
|
|
|
|
|
dragOffset.value = DRAWER_WIDTH
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleTouchMove(e: TouchEvent) {
|
|
|
|
|
if (!isOpen.value && !startedFromEdge) return
|
|
|
|
|
|
|
|
|
|
const touch = e.touches[0]
|
|
|
|
|
const deltaX = touch.clientX - touchStartX
|
|
|
|
|
const deltaY = touch.clientY - touchStartY
|
|
|
|
|
|
|
|
|
|
// Determine swipe direction on first significant movement
|
|
|
|
|
if (isHorizontalSwipe === null && (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10)) {
|
|
|
|
|
isHorizontalSwipe = Math.abs(deltaX) > Math.abs(deltaY)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isHorizontalSwipe) return
|
|
|
|
|
|
|
|
|
|
// Start dragging
|
|
|
|
|
if (!isDragging.value) {
|
|
|
|
|
if (isOpen.value && deltaX > 0) {
|
|
|
|
|
isDragging.value = true
|
|
|
|
|
} else if (startedFromEdge && deltaX < 0) {
|
|
|
|
|
isDragging.value = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isDragging.value) {
|
|
|
|
|
if (isOpen.value) {
|
|
|
|
|
// Dragging to close: deltaX > 0 means moving right
|
|
|
|
|
dragOffset.value = Math.max(0, deltaX)
|
|
|
|
|
} else {
|
|
|
|
|
// Dragging to open: deltaX < 0 means moving left
|
|
|
|
|
dragOffset.value = DRAWER_WIDTH + deltaX
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleTouchEnd() {
|
|
|
|
|
if (!isDragging.value) {
|
|
|
|
|
startedFromEdge = false
|
|
|
|
|
isHorizontalSwipe = null
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const currentOffset = dragOffset.value
|
|
|
|
|
|
|
|
|
|
if (isOpen.value) {
|
|
|
|
|
// Was open - check if should close
|
|
|
|
|
if (currentOffset > SWIPE_THRESHOLD) {
|
|
|
|
|
closeMenu()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Was closed - check if should open
|
|
|
|
|
if (currentOffset < DRAWER_WIDTH - SWIPE_THRESHOLD) {
|
|
|
|
|
openMenu()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset
|
|
|
|
|
isDragging.value = false
|
|
|
|
|
startedFromEdge = false
|
|
|
|
|
isHorizontalSwipe = null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
document.addEventListener('touchstart', handleTouchStart, { passive: true })
|
|
|
|
|
document.addEventListener('touchmove', handleTouchMove, { passive: true })
|
|
|
|
|
document.addEventListener('touchend', handleTouchEnd, { passive: true })
|
|
|
|
|
window.addEventListener('popstate', handlePopState)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
document.removeEventListener('touchstart', handleTouchStart)
|
|
|
|
|
document.removeEventListener('touchmove', handleTouchMove)
|
|
|
|
|
document.removeEventListener('touchend', handleTouchEnd)
|
|
|
|
|
window.removeEventListener('popstate', handlePopState)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function logOut() {
|
|
|
|
|
token.value = null
|
|
|
|
|
auth.user = null
|
|
|
|
|
router.push({ path: '/login' })
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|