mns-mini-zabor/app.vue

171 lines
4.9 KiB
Vue

<script setup lang="ts">
const config = useRuntimeConfig()
const apiBase = config.public.apiBase
import k_logo from '@/assets/logo.svg'
type ApiKpType = {
id: number
title: string
content: string
url: string
meta_title: any
meta_description: string
keywords: any
is_indexed: boolean
}
type ApiPagesType = {
id: number
title: string
menu_title: string
slug: string
external_link: string
content: string
image: string
}
type ApiReviewsType = {
id: number
image: string
text: string
comment: string
}
type ApiFooterType = {
id: number
text: string
small_text: boolean
}
import '@/assets/main.scss'
const { data: seoData } = await useFetch<ApiKpType>(`${apiBase}/kp/1`)
useSeoMeta({
title: seoData.value?.title,
ogTitle: seoData.value?.title,
description: seoData.value?.content,
ogDescription: seoData.value?.content,
// ogImage: 'https://example.com/image.png',
// twitterCard: 'summary_large_image',
})
const { data: pagesData } = await useFetch<ApiPagesType[]>(`${apiBase}/pages/?ordering=order`)
const { data: reviewsData } = await useFetch<ApiReviewsType[]>(`${apiBase}/review/`)
const about = (pagesData.value as ApiPagesType[]).find(el => el.slug == 'about')
const reviews = (pagesData.value as ApiPagesType[]).find(el => el.slug == 'clients')
const delivery = (pagesData.value as ApiPagesType[]).find(el => el.slug == 'delivery')
const { data: footerData } = await useFetch<ApiFooterType[]>(`${apiBase}/footer/`)
const isModalOpen = ref<boolean>(false)
const toggleModal = () => {
isModalOpen.value = !!isModalOpen
}
const modal_phone = ref()
const model_form = reactive({
disabled: true,
errors: [],
})
const validateInput = (evt: KeyboardEvent) => {
const valid_symbols = /[a-zA-Z0-9\+(\\)\ @\.]/
if (!valid_symbols.test(evt.key)) {
evt.preventDefault()
return
}
}
const validate = (evt: KeyboardEvent) => {
const phone_regexp = /\(?\+[0-9]{1,3}\)? ?-?[0-9]{1,3} ?-?[0-9]{3,5} ?-?[0-9]{4}( ?-?[0-9]{3})? ?(\w{1,10}\s?\d{1,6})?/
const email_regex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/
if (modal_phone.value.length < 3) {
model_form.disabled = true
return
}
if (phone_regexp.test(modal_phone.value) || email_regex.test(modal_phone.value)) {
model_form.disabled = false
return
}
}
</script>
<template>
<div>
<div class="header">
<div class="container">
<div class="logo">
Купи забор
</div>
<div class="menu">
<template v-for="item in pagesData">
<NuxtLink :to="item.external_link || `#${item.slug}`" :target="item.external_link ? '_blank' : '_self'">
{{ item.menu_title }}
</NuxtLink>
</template>
</div>
</div>
</div>
<div class="block bg-white" :id="about?.slug">
<div class="container">
<div class="block-content">
<h2 class="block-title">{{ about?.title }}</h2>
<div class="block-text">
{{ about?.content }}
<p>
<button class="not-prose" @click="toggleModal">Купить прямо сейчас</button>
</p>
</div>
</div>
<div class="block-image">
<NuxtImg :src="[apiBase, about?.image].join('/')" />
</div>
</div>
</div>
<div class="block block_imgbg bg-slate-500"
:style="[{ backgroundImage: `url(${[apiBase, reviews?.image].join('/')})` }]" :id="reviews?.slug">
<NuxtImg :src="[apiBase, reviews?.image].join('/')" class="invisible" />
</div>
<div class="block bg-white" :id="reviews?.slug">
<div class="container">
<template v-for="item in reviewsData?.slice(0, 3)">
<div class="review">
<div class="review-image">
<NuxtImg :src="[apiBase, item.image].join('/')" />
</div>
<div class="review-content">
{{ item.comment }}
</div>
<div class="review-title">
{{ item.text }}
</div>
</div>
</template>
</div>
</div>
<div class="block block_imgbg bg-slate-500"
:style="[{ backgroundImage: `url(${[apiBase, delivery?.image].join('/')})` }]">
<NuxtImg :src="[apiBase, delivery?.image].join('/')" class="invisible" />
</div>
<div class="footer">
<div class="container">
<div class="k-logo">
<k_logo />
</div>
<template v-for="item in footerData">
<div class="footer-text" :class="[{ 'footer-text-small': item.small_text }]">{{ item.text }}</div>
</template>
</div>
</div>
<div v-if="isModalOpen" class="modal-backdrop">
<div class="modal">
<h2>Оставьте номер телефона для связи</h2>
<input type="phone" v-model="modal_phone" @keypress="validateInput" @keyup="validate" />
<button class="button not-prose" :disabled="model_form.disabled">Отправить</button>
</div>
</div>
</div>
</template>