update
Some checks failed
continuous-integration/drone/push Build is failing

dfdsf
This commit is contained in:
2026-04-18 16:45:58 +03:00
parent 6c3a954323
commit 18c37768cb
29 changed files with 3786 additions and 1470 deletions

View File

@@ -1,76 +1,86 @@
<template>
<q-layout view="lHr lpr lFr" class="bg-grey-11 relative-position">
<q-header
class="main-content q-py-sm q-px-md"
:class="isHeroScroll ? 'text-white bg-transparent' : 'text-grey glass shadow-6'"
style="
transition: background-color 0.5s ease, color 0.5s ease;
border-bottom-left-radius: var(--base-radius);
border-bottom-right-radius: var(--base-radius);
"
class="main-content bg-transparent"
reveal
style="transition: all 0.5s ease"
ref="headerRef"
>
<div
ref="headerContainer"
class="flex q-mx-md justify-between no-wrap items-center"
class="q-mx-md q-mt-lg q-py-sm q-px-md"
:class="isHeroScroll ? 'text-white' : 'text-white glass shadow-6'"
style="
transition: background-color 0.5s ease, color 0.5s ease;
border-radius: var(--base-radius)
"
>
<base-logo ref="logo" class="text-h6"/>
<div
ref="menuContainer"
class="row items-center q-ml-md no-wrap"
style="min-width: 42px"
ref="headerContainer"
class="flex justify-between no-wrap items-center"
>
<base-logo ref="logo" class="text-h6" />
<div
ref="buttonsContainer"
:class="{ 'invisible absolute': !showFullMenu }"
class="flex row no-wrap"
ref="menuContainer"
class="row items-center q-ml-md no-wrap"
style="min-width: 42px"
>
<q-btn
v-for="item in menuItems"
:key="item.id"
flat
no-caps
@click="scrollToElement(item.ref)"
ref="menuButtons"
:color="isHeroScroll ? 'white' : 'primary'"
<div
ref="buttonsContainer"
:class="{ 'invisible absolute': !showFullMenu }"
class="flex row no-wrap"
>
<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="isHeroScroll ? 'white' : 'primary'"
class="q-ml-sm"
>
<div class="flex items-center no-wrap">
<span class="text-bold">{{ locale.split('-')[0] }}</span>
<q-btn
v-for="item in menuItems"
:key="item.id"
flat
no-caps
@click="scrollToElement(item.ref)"
ref="menuButtons"
:color="isHeroScroll ? 'white' : 'black'"
>
<span class="text-no-wrap">{{ $t(item.title) }}</span>
</q-btn>
</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>
<q-btn
v-if="!showFullMenu"
flat
round
icon="menu"
@click="showDrawer = !showDrawer"
:color="isHeroScroll ? 'white' : 'black'"
/>
<q-btn
outline
:color="isHeroScroll ? 'white' : 'black'"
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.locale"
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-resize-observer @resize="checkSpace"/>
</div>
</q-header>
@@ -94,40 +104,55 @@
</div>
</q-drawer>
<q-page-container
class="main-content q-pa-none q-ma-none bg-transparent"
>
<q-scroll-observer axis="vertical" @scroll="updateHeaderStyle"/>
<q-page-container class="main-content q-pa-none q-ma-none bg-transparent">
<q-scroll-observer axis="vertical" @scroll="updateHeaderStyle" />
<q-page class="column">
<hero-banner class="q-pa-none" style="margin-top: -58px;" id='hero_banner'/>
<problem-section/>
<how-works-section id='how_works'/>
<price-section id='price'/>
<faq-section id='FAQ'/>
<footer-section id='contacts'/>
<hero-banner
class="q-pa-none q-pt-xl"
style="margin-top: -100px"
id="hero_banner"
/>
<problem-section id="problems"/>
<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 { ref, onMounted, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { scroll } from 'quasar'
import { useI18n } from 'vue-i18n'
import { setGlobalLocale } from 'src/boot/i18n'
import baseLogo from 'components/BaseLogo.vue'
import heroBanner from 'components/HeroBanner.vue'
import problemSection from 'components/ProblemSection.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 { locale } = useI18n({ useScope: 'global' })
const { getScrollTarget, setVerticalScrollPosition } = scroll
const route = useRoute()
const isHeroScroll = ref(true)
const updateHeaderStyle = (e) => {
isHeroScroll.value = e.position.top <= 5
}
const showDrawer = ref(false)
const showFullMenu = ref(true)
const isManualScrolling = ref(false)
const menuButtons = ref([])
const headerContainer = ref(null)
const logo = ref(null)
const menuContainer = ref(null)
const headerRef = ref(null)
const HEADER_OFFSET = 60
const menuItems = [
{ id: 0, title: 'main__how_it_works', ref: 'how_works' },
@@ -136,64 +161,102 @@
{ 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 allSections = [
'hero_banner',
'problems',
'how_works',
'price',
'FAQ',
'contacts'
]
const calculateButtonsWidth = () => {
return menuButtons.value.reduce(
(total, btn) => total + (btn?.$el.offsetWidth || 0), 0
)
const langNames = [
{ locale: 'en-US', label: 'English' },
{ locale: 'ru-RU', label: 'Русский' }
]
const updateHeaderStyle = (e) => {
isHeroScroll.value = e.position.top <= 15
if (isManualScrolling.value) return
for (const id of allSections) {
const el = document.getElementById(id)
if (el) {
const rect = el.getBoundingClientRect()
if (rect.top >= -100 && rect.top <= 150) {
if (id === 'hero_banner') {
if (window.location.hash !== '') {
history.replaceState(null, '', window.location.pathname + window.location.search)
}
} else {
const newHash = `#${id}`
if (window.location.hash !== newHash) {
history.replaceState(null, '', newHash)
}
}
break
}
}
}
}
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()
const availableWidth = headerWidth - logoWidth - menuMargin - 80
const buttonsWidth = menuButtons.value.reduce(
(total, btn) => total + (btn?.$el.offsetWidth || 0), 0
)
showFullMenu.value = buttonsWidth <= availableWidth
}
const scrollToElement = (id, animate = true) => {
const el = document.getElementById(id)
if (!el) return
const target = getScrollTarget(el)
const headerNativeEl = headerRef.value?.$el
if (animate) isManualScrolling.value = true
const duration = animate ? 350 : 0
setVerticalScrollPosition(target, el.offsetTop, duration)
const checkAction = () => {
if (headerNativeEl?.classList.contains('q-header--hidden')) {
setVerticalScrollPosition(target, el.offsetTop + HEADER_OFFSET, 100)
}
if (animate) {
setTimeout(() => { isManualScrolling.value = false }, 100)
}
}
if (animate) {
setTimeout(checkAction, 350)
showDrawer.value = false
history.pushState(null, '', `#${id}`)
} else {
setTimeout(checkAction, 350)
}
}
const isCurrentLang = (lang) => locale.value === lang
const setLocale = (newLocale) => setGlobalLocale(newLocale.locale)
onMounted(async () => {
await nextTick()
checkSpace()
if (route.hash) {
const id = route.hash.replace('#', '')
setTimeout(() => {
scrollToElement(id, false)
}, 450)
}
})
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>
@@ -201,9 +264,10 @@
opacity: 0;
pointer-events: none;
}
.glass {
background-color: rgba(255, 255, 255, 0.8) !important;
backdrop-filter: blur(8px);
background-color: rgba(255, 255, 255, 0.45) !important;
backdrop-filter: blur(12px) saturate(180%);
-webkit-backdrop-filter: blur(12px) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.3);
}
</style>
</style>