Files
tgCrewLanding/src/layouts/MainLayout.vue
CCTVcalc 4771b374ac
All checks were successful
continuous-integration/drone/push Build is passing
add docs
2025-08-11 17:50:52 +03:00

186 lines
5.3 KiB
Vue

<template>
<q-layout view="lHr lpr lFr" class="bg-transparent">
<q-header class="main-content text-grey glass">
<div ref="headerContainer" class="flex q-ma-md justify-between no-wrap items-center">
<base-logo ref="logo" class="text-h6"/>
<div
ref="menuContainer"
class="row items-center q-ml-md no-wrap"
style="min-width: 42px"
>
<div
ref="buttonsContainer"
:class="{ 'invisible absolute': !showFullMenu }"
class="flex row no-wrap"
>
<q-btn
v-for="item in menuItems"
:key="item.id"
flat
no-caps
@click="scrollToElement(item.ref)"
ref="menuButtons"
>
<span class="text-no-wrap">{{ $t(item.title) }}</span>
</q-btn>
</div>
<q-btn
v-if="!showFullMenu"
flat
round
icon="menu"
@click="showDrawer = !showDrawer"
/>
<q-btn outline color="primary" class="q-ml-sm">
<div class="flex items-center no-wrap">
<span class="text-bold">{{ locale.split('-')[0] }}</span>
</div>
<q-menu>
<q-list style="min-width: 100px">
<q-item
v-for="lang in langNames"
:key="lang"
clickable
v-close-popup
@click="setLocale(lang)"
>
<q-item-section>
<q-item-label :class="isCurrentLang(lang.locale) ? 'text-primary' : ''">{{ lang.label }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
<q-resize-observer @resize="checkSpace"/>
</div>
</q-header>
<q-drawer v-model="showDrawer" side="right" overlay>
<div class="flex column items-end q-gutter-y-md q-pa-md">
<q-btn
flat
round
icon="mdi-close"
@click="showDrawer = !showDrawer"
/>
<q-btn
v-for="item in menuItems"
:key="item.id"
flat
no-caps
@click="scrollToElement(item.ref)"
>
<span class="text-no-wrap text-h6">{{ $t(item.title) }}</span>
</q-btn>
</div>
</q-drawer>
<q-page-container
class="main-content q-pa-none q-ma-none bg-transparent"
>
<q-page class="column">
<hero-banner/>
<problem-section/>
<how-works-section id='how_works'/>
<price-section id='price'/>
<faq-section id='FAQ'/>
<footer-section id='contacts'/>
</q-page>
</q-page-container>
</q-layout>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import baseLogo from 'components/BaseLogo.vue'
import heroBanner from 'components/HeroBanner.vue'
import problemSection from 'components/ProblemSection.vue'
import HowWorksSection from 'components/HowWorksSection.vue'
import PriceSection from 'components/PriceSection.vue'
import FaqSection from 'components/FAQSection.vue'
import FooterSection from 'components/FooterSection.vue'
const showDrawer = ref(false)
const menuItems = [
{ id: 0, title: 'main__how_it_works', ref: 'how_works' },
{ id: 1, title: 'main__price', ref: 'price' },
{ id: 2, title: 'main__faq', ref: 'FAQ' },
{ id: 3, title: 'main__contacts', ref: 'contacts' }
]
const showFullMenu = ref(true)
const menuButtons = ref([])
const headerContainer = ref(null)
const logo = ref(null)
const menuContainer = ref(null)
const calculateButtonsWidth = () => {
return menuButtons.value.reduce(
(total, btn) => total + (btn?.$el.offsetWidth || 0), 0
)
}
const checkSpace = () => {
if (!headerContainer.value || !logo.value || !menuContainer.value) return
const headerWidth = headerContainer.value.offsetWidth
const logoWidth = logo.value.$el.offsetWidth
const menuMargin = parseFloat(getComputedStyle(menuContainer.value).marginLeft) || 0
const availableWidth = headerWidth - logoWidth - menuMargin - 40 // 40px - запас
const buttonsWidth = calculateButtonsWidth()
showFullMenu.value = buttonsWidth <= availableWidth
}
onMounted(async () => {
await nextTick()
checkSpace()
})
import { scroll } from 'quasar'
const { getScrollTarget, setVerticalScrollPosition } = scroll
const scrollToElement = (id) => {
const el = document.querySelector('#' + id)
const target = getScrollTarget(el)
const offset = el.offsetTop - 12
const duration = 300
setVerticalScrollPosition(target, offset, duration)
showDrawer.value = false
}
import { useI18n } from 'vue-i18n'
import { setGlobalLocale } from 'src/boot/i18n'
const { locale } = useI18n({ useScope: 'global' })
const langNames = [
{ locale: 'en-US', label: 'English'},
{ locale: 'ru-RU', label: 'Русский'}
]
const isCurrentLang = (lang) => locale.value === lang
const setLocale = (newLocale) => {
setGlobalLocale(newLocale.locale)
}
</script>
<style scoped>
.invisible {
opacity: 0;
pointer-events: none;
}
.glass {
background-color: rgba(255, 255, 255, 0.8) !important;
backdrop-filter: blur(8px);
}
</style>