248 lines
11 KiB
Vue
248 lines
11 KiB
Vue
<script setup lang="ts">
|
||
import { getColorNameFromRal } from '@/components/ral'
|
||
import type { ralTypes } from '@/components/ral'
|
||
|
||
import { predefLamelleColors, predefPillarColors } from '~/composables/useCalc';
|
||
|
||
const lamelle_height = use_lamelle_height()
|
||
const lamelles_count = use_lamelles_count()
|
||
const fence_section = use_fence_section()
|
||
const remove_pillar = use_remove_pillar()
|
||
const pillar_color = use_pillar_color()
|
||
const lamelle_color = use_lamelle_color()
|
||
const section_count = use_section_count()
|
||
const extra_section = use_extra_section()
|
||
const total_length = use_total_length()
|
||
const min_length = use_min_length()
|
||
|
||
const parametric = reactive({
|
||
length: {
|
||
min: min_length.value,
|
||
max: 2470,
|
||
step: 1,
|
||
},
|
||
total_length: {
|
||
min: min_length.value * 0.001,
|
||
max: undefined,
|
||
step: 0.5,
|
||
},
|
||
height: {
|
||
min: 20 + lamelle_height.value * 1000 * 5,
|
||
max: 20 + lamelle_height.value * 1000 * 20,
|
||
step: lamelle_height.value * 1000,
|
||
}
|
||
})
|
||
const form_state = reactive({
|
||
length: fence_section.value * 1000,
|
||
fence_length: 104,
|
||
height: 100 + lamelles_count.value * parametric.height.step,
|
||
total_length: total_length.value,
|
||
total_length_mm: fence_section.value * 1000,
|
||
full_sections: section_count.value,
|
||
extra_section: 0,
|
||
auto_length: true,
|
||
remove_pillar: false
|
||
})
|
||
const form_refs = {
|
||
length: ref(),
|
||
height: ref(),
|
||
total_length: ref(),
|
||
}
|
||
|
||
const changeParametres = () => {
|
||
if (form_state.total_length * 1000 < parametric.length.min) {
|
||
return
|
||
}
|
||
const lamelles = Math.floor(form_state.height / parametric.height.step)
|
||
|
||
for (const key in form_state) {
|
||
if (parametric.hasOwnProperty(key)) {
|
||
const key_p = key as keyof typeof parametric
|
||
const key_s = key as keyof typeof form_state
|
||
if (parametric[key_p].max) {
|
||
if (form_state[key_s] > parametric[key_p].max) {
|
||
form_state[key_s] = parametric[key_p].max
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (form_state.total_length_mm < form_state.length) {
|
||
form_state.length = form_state.total_length_mm
|
||
}
|
||
form_state.total_length_mm = form_state.total_length * 1000
|
||
|
||
let { fence_length, total_length_mm, auto_length, length, full_sections } = form_state
|
||
length = parseFloat(length.toString())
|
||
|
||
if (auto_length) {
|
||
let w = parametric.length.min
|
||
const max_sections = Math.floor((total_length_mm - fence_length) / (parametric.length.min + fence_length))
|
||
const min_sections = Math.ceil((total_length_mm - fence_length) / (parametric.length.max + fence_length))
|
||
|
||
for (let index = min_sections; index <= max_sections; index++) {
|
||
full_sections = index
|
||
w = (total_length_mm - fence_length * (index - 1)) / index
|
||
if (
|
||
w >= parametric.length.min
|
||
&& w <= parametric.length.max
|
||
&& w * index <= total_length_mm
|
||
) {
|
||
break
|
||
}
|
||
}
|
||
length = w
|
||
} else {
|
||
full_sections = Math.floor((total_length_mm - fence_length) / (length + fence_length))
|
||
if (full_sections == 0) {
|
||
length = total_length_mm - fence_length - fence_length
|
||
}
|
||
}
|
||
|
||
if (((full_sections * length) + (full_sections * fence_length) + fence_length) <= total_length_mm) {
|
||
form_state.extra_section = Math.floor((total_length_mm - fence_length) % length)
|
||
} else {
|
||
form_state.extra_section = 0
|
||
}
|
||
|
||
form_state.full_sections = full_sections
|
||
form_state.length = length
|
||
form_state.fence_length = fence_length
|
||
|
||
total_length.value = form_state.total_length
|
||
lamelles_count.value = lamelles
|
||
fence_section.value = form_state.length * 0.001
|
||
section_count.value = form_state.full_sections
|
||
extra_section.value = form_state.extra_section
|
||
remove_pillar.value = form_state.remove_pillar
|
||
|
||
goal('calc_fence', form_state)
|
||
}
|
||
|
||
const setLamelleColor = (color: ralTypes) => {
|
||
lamelle_color.value = color
|
||
}
|
||
const setPillarColor = (color: ralTypes) => {
|
||
pillar_color.value = color
|
||
}
|
||
watch(form_state, changeParametres, { deep: true })
|
||
|
||
const isModalOpen = useState('modal_open', () => false)
|
||
const toggleModal = () => {
|
||
isModalOpen.value = !isModalOpen.value
|
||
}
|
||
const plurals = {
|
||
lamelle: { one: 'ламель', few: 'ламели', many: 'ламелей' },
|
||
fence: { one: 'cтолб', few: 'столба', many: 'столбов' },
|
||
section: { one: 'секция', few: 'секции', many: 'секций' },
|
||
}
|
||
const goal = (target: string, params: object) => {
|
||
const nuxtApp = useNuxtApp()
|
||
if (nuxtApp.$metrika) {
|
||
nuxtApp.$metrika.reachGoal(target, params || {})
|
||
}
|
||
}
|
||
</script>
|
||
<template>
|
||
<div class="container relative py-4">
|
||
<form class="form">
|
||
<div class="col-span-12 lg:col-span-6">
|
||
<div class="form-row">
|
||
<div class="form-item w-full">
|
||
<label for="length">Длина ламельного блока, мм</label>
|
||
<input disabled :value="`${form_state.length} мм`" class="w-28" />
|
||
<input id="length" type="range" class="w-full" v-bind="parametric.length"
|
||
v-model="form_state.length" :disabled="form_state.auto_length" :ref="form_refs.length" />
|
||
</div>
|
||
<div class="form-item w-full">
|
||
<label for="height">Высота забора, мм</label>
|
||
<input disabled :value="`${form_state.height} мм`" class="w-28" />
|
||
<input id="height" type="range" class="w-full" v-bind="parametric.height"
|
||
v-model="form_state.height" :ref="form_refs.height" />
|
||
</div>
|
||
<div class="form-item">
|
||
<label for="total_length">Общая длина забора, м</label>
|
||
<input type="number" id="total_length" v-bind="parametric.total_length"
|
||
v-model="form_state.total_length" :ref="form_refs.total_length" />
|
||
</div>
|
||
<div class="form-item form-item_checkbox">
|
||
<input id="auto_length" type="checkbox" v-model="form_state.auto_length" />
|
||
<label for="auto_length">Автоматический подбор секции</label>
|
||
</div>
|
||
<div class="form-item form-item_checkbox">
|
||
<input id="remove_pillar" type="checkbox" v-model="form_state.remove_pillar" />
|
||
<label for="remove_pillar">Без столбов</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-span-12 lg:col-span-6">
|
||
<div class="form-row">
|
||
<div class="form-item">
|
||
<label for="lamelle_color">Цвет ламелей</label>
|
||
<input id="lamelle_color" type="text" :value="getColorNameFromRal(lamelle_color)" class="w-60"
|
||
disabled />
|
||
<ColorPicker :cb="setLamelleColor" />
|
||
</div>
|
||
<div class="form-item">
|
||
<template v-for="item in predefLamelleColors">
|
||
<ColorPicker :color="item" :cb="setLamelleColor" :open="false"
|
||
:active="lamelle_color == item" />
|
||
</template>
|
||
</div>
|
||
<div class="form-item">
|
||
<label for="pillar_color">Цвет столба</label>
|
||
<input id="pillar_color" type="text" :value="getColorNameFromRal(pillar_color)" class="w-60"
|
||
disabled />
|
||
<ColorPicker :cb="setPillarColor" />
|
||
</div>
|
||
<div class="form-item">
|
||
<template v-for="item in predefPillarColors">
|
||
<ColorPicker :color="item" :cb="setPillarColor" :open="false"
|
||
:active="pillar_color == item" />
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-span-12 lg:col-span-8 prose min-w-full">
|
||
<template v-if="(form_state.total_length * 1000) >= parametric.length.min">
|
||
<p>
|
||
Забор общей длиной {{ form_state.total_length }}{{ '\xa0' }}м,
|
||
{{ section_count }}
|
||
<Plural :n="section_count" :forms="plurals.section" /> по
|
||
{{ `${parseFloat(form_state.length.toString()).toFixed(2)}\xa0мм` }}{{
|
||
form_state.extra_section ? ` и 1 дополнительная секция
|
||
длиной ${form_state.extra_section.toFixed(2)}\xa0мм` : '' }}.
|
||
</p>
|
||
<p v-if="parametric.length.min <= form_state.total_length * 1000">
|
||
Всего <template v-if="!form_state.remove_pillar">
|
||
{{ section_count + ~~(!!form_state.extra_section) + 1 }}
|
||
<Plural :forms="plurals.fence" :n="section_count + ~~(!!form_state.extra_section) + 1" />,
|
||
</template>
|
||
{{ section_count * lamelles_count }}
|
||
<Plural :n="section_count * lamelles_count" :forms="plurals.lamelle" />
|
||
{{ `длиной ${parseFloat(form_state.length.toString()).toFixed(2)}\xa0мм` }}<template
|
||
v-if="form_state.extra_section">
|
||
{{ ` и ${~~(!!form_state.extra_section.toFixed(2)) * lamelles_count}` }}
|
||
<Plural :n="~~(!!form_state.extra_section) * lamelles_count" :forms="plurals.lamelle" />
|
||
{{ `длиной ${form_state.extra_section}\xa0мм` }}
|
||
</template>.
|
||
</p>
|
||
<p>
|
||
Окрашивается по технологии порошковой окраски: <br />
|
||
ламели: {{ getColorNameFromRal(lamelle_color)?.toLowerCase() }};
|
||
столбы: {{ getColorNameFromRal(pillar_color)?.toLowerCase() }}.
|
||
</p>
|
||
</template>
|
||
</div>
|
||
<div class="prose col-span-4">
|
||
<p v-if="form_state.extra_section" class="text-ioprim">
|
||
Внимание! Дополнительная секция приводит к увеличению стоимости.
|
||
Рекомендуем вам изменить длину забора или длину секции!
|
||
</p>
|
||
</div>
|
||
<div class="form-row justify-center">
|
||
<button @click.prevent="toggleModal">Рассчитать прямо сейчас</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</template> |