171 lines
7.0 KiB
Vue
171 lines
7.0 KiB
Vue
<script setup lang="ts">
|
|
const config = useRuntimeConfig()
|
|
const imgBase = config.public.imgBase
|
|
|
|
import { apiFetch } from '~/utils/apiFetch';
|
|
import { marked } from 'marked';
|
|
|
|
import og_img from '/og_img.png'
|
|
|
|
const globalFenceType = useGlobalFenceType()
|
|
|
|
const { data: seoData } = await apiFetch<ApiKpType>(`kp/1/`)
|
|
useSeoMeta({
|
|
title: seoData.value?.title,
|
|
ogTitle: seoData.value?.title,
|
|
description: seoData.value?.content,
|
|
ogDescription: seoData.value?.content,
|
|
ogImage: config.public.baseUrl + og_img,
|
|
// twitterCard: 'summary_large_image',
|
|
})
|
|
|
|
const { data: menuData } = await apiFetch<ApiMenuType>(`menu/1/?ordering=order`)
|
|
const pagesData = menuData.value ? menuData.value.pages : []
|
|
|
|
const { data: reviewsData } = await apiFetch<ApiReviewsType[]>(`review/`)
|
|
|
|
const { data: calculators } = await apiFetch<ApiCalcType[]>('calculator/')
|
|
const openTab = ref<number>()
|
|
if (calculators.value?.length) openTab.value = calculators.value[0].id
|
|
|
|
const about = pagesData.find(el => el.slug == 'about')
|
|
const reviews = pagesData.find(el => el.slug == 'clients')
|
|
const delivery = pagesData.find(el => el.slug == 'how_to')
|
|
const advantages = pagesData.find(el => el.slug == 'advantages')
|
|
|
|
const roubleSign = new Intl.NumberFormat('ru-RU', {
|
|
style: 'currency',
|
|
currency: 'RUB',
|
|
});
|
|
|
|
const aboutText = computed(() => marked.parse(about?.content || ''))
|
|
const deliveryText = computed(() => delivery?.content.split('[col]').map(el => marked.parse(el || '')))
|
|
const advantagesText = computed(() => {
|
|
let c = advantages?.content || ''
|
|
Object.entries(calculators.value?.find(el => el.id == openTab.value) || {}).map(item => {
|
|
c = c.replaceAll(`[${item[0]}]`, roubleSign.format(item[1] as number))
|
|
})
|
|
return marked.parse(c)
|
|
})
|
|
|
|
const { data: advData } = await apiFetch<ApiAdvantageType[]>(`advantage/`)
|
|
|
|
watch(openTab, () => {
|
|
if (!openTab.value) return
|
|
if (!calculators.value) return
|
|
let type = 'standart'
|
|
if (openTab.value == 6) {
|
|
type = 'aristo'
|
|
}
|
|
const v = {
|
|
id: openTab.value as number,
|
|
type: type as "standart" | "aristo",
|
|
calc: calculators.value.find(el => el.id == openTab.value) as ApiCalcType,
|
|
}
|
|
globalFenceType.value = v
|
|
})
|
|
</script>
|
|
<template>
|
|
<div>
|
|
<Modal :calcData="(calculators || []).find(el => el.id == openTab)" />
|
|
<div class="siteblock bg-white" :id="about?.slug" v-if="about">
|
|
<div class="container">
|
|
<h1 class="siteblock-title">{{ about?.title }}</h1>
|
|
<div class="siteblock-content">
|
|
<div class="siteblock-text">
|
|
<span v-html="aboutText"></span>
|
|
</div>
|
|
</div>
|
|
<div class="siteblock-image">
|
|
<NuxtImg :src="[imgBase, about?.image].join('/')" alt="разные цвета забора" title=""
|
|
format="webp" />
|
|
</div>
|
|
<div class="feature">
|
|
<template v-for="item in advData">
|
|
<div class="feature-item">
|
|
<div class="feature-name">{{ item.title }}</div> {{ item.content }}
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="siteblock siteblock_imgbg bg-slate-500"
|
|
:style="[{ backgroundImage: `url(${[imgBase, reviews?.image].join('/')})` }]" v-if="reviews">
|
|
<NuxtImg :src="[imgBase, reviews?.image].join('/')" class="invisible" alt="отзыв" title="" format="webp"
|
|
loading="lazy" />
|
|
</div>
|
|
<div class="siteblock bg-white" :id="reviews?.slug" v-if="reviews">
|
|
<div class="container">
|
|
<template v-for="item in reviewsData?.slice(0, 3)">
|
|
<div class="review">
|
|
<div class="review-image">
|
|
<NuxtImg :src="[imgBase, item.image].join('/')" :alt="item.text" title="" format="webp"
|
|
loading="lazy" />
|
|
</div>
|
|
<div class="review-content">
|
|
{{ item.comment }}
|
|
</div>
|
|
<div class="review-title">
|
|
{{ item.text }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div class="siteblock bg-white" :id="advantages?.slug">
|
|
<div class="flex col-span-full gap-2 justify-center">
|
|
<template v-for="item in calculators">
|
|
<div class="flex items-center gap-2">
|
|
<label class="rounded p-2 cursor-pointer flex gap-2" :for="item.id.toString()">
|
|
<input type="radio" :id="item.id.toString()" :value="item.id" v-model="openTab"
|
|
:checked="openTab == item.id">
|
|
<span :class="[
|
|
'text-2xl font-bold bg-clip-text text-transparent drop-shadow-xs',
|
|
openTab == item.id
|
|
? 'bg-gradient-to-r from-yellow-400 via-orange-500 to-red-600'
|
|
: 'bg-gradient-to-r from-slate-400 to-slate-600'
|
|
]">
|
|
{{ item.title }}
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<div class="container gap-4">
|
|
<div class="col-span-full xl:col-span-8">
|
|
<ExpDiagram />
|
|
</div>
|
|
<div class="col-span-full xl:col-span-4 prose">
|
|
<span v-html="advantagesText"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="siteblock siteblock_imgbg bg-slate-500 "
|
|
:style="[{ backgroundImage: `url(${[imgBase, delivery?.image].join('/')})` }]">
|
|
<NuxtImg :src="[imgBase, delivery?.image].join('/')" class="invisible" v-if="delivery"
|
|
alt="коричневый забор" title="" format="webp" loading="lazy" />
|
|
</div>
|
|
<div class="siteblock siteblock_calc bg-white">
|
|
<div class="container">
|
|
<div class="col-span-12 xl:col-span-9 h-full relative">
|
|
<Suspense>
|
|
<LazyCalcModels />
|
|
</Suspense>
|
|
</div>
|
|
<div class="col-span-12 xl:col-span-3">
|
|
<CalcValues />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="siteblock bg-white siteblock_content" :id="delivery?.slug" v-if="deliveryText">
|
|
<div class="container">
|
|
<div class="prose col-span-12 xl:col-span-6">
|
|
<span v-html="deliveryText[0]"></span>
|
|
</div>
|
|
<div class="prose col-span-12 xl:col-span-6">
|
|
<span v-html="deliveryText[1]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template> |