JSFiddle - React, Tailwind, and code Playground
by Константин Дралюк
HTML
# TODO
# Combine mansard and simple floors in one array
# Write styles
# Do calculations
<div id='calc' class='calc'>
<h1 class='calc__title'>Калькулятор</h1>
<div v-for='field in fields.header' :key='field.name'>
<field :field='field'></field>
</div>
<div v-for='floor, index in fields.floors'>
<floor :index='index + 1' :header='floor.header' :outer-walls-holes='floor.outer_walls_holes' :inner-walls-holes='floor.inner_walls_holes'></floor>
</div>
</div>
<script type='text/x-template' id='field'>
<label class='calc-label'>
<span class='calc-label__title'>
<span v-text='field.title'></span>
<span class='calc-label__hint' v-text='field.hint' v-if='field.hint'></span>
</span>
<template v-if='field.options'>
<select class='calc-label__field -select' v-model='field.value'>
<option v-for='value, text in field.options' v-text='text' :value='value'></option>
</select>
</template>
<template v-else>
<input class='calc-label__field' type='number' min='0' step='1' v-model='field.value'>
</template>
</label>
</script>
<script type='text/x-template' id='floor'>
<div class='calc-floor'>
<h2 class='calc__md-title'>{{ index }} этаж</h2>
<div class='calc-floor__header'>
<div v-for='field in header' :key='field.name'>
<field :field='field'></field>
</div>
</div>
<div class='calc-floor__outer-walls-holes'>
<div v-for='field in header' :key='field.name'>
<field :field='field'></field>
</div>
</div>
<div class='calc-floor__inner-walls-holes'>
<div v-for='field in header' :key='field.name'>
<field :field='field'></field>
</div>
</div>
</div>
</script>
<script type='text/x-template' id='outer-walls-holes'>
<div>1</div>
</script>
<script type='text/x-template' id='inner-walls-holes'>
<div>1</div>
</script>
<script type='text/x-template' id='mansard'>
<div>1</div>
</script>
JavaScript
Vue.component('field', {
template: '#field',
props: ['field']
})
Vue.component('floor', {
template: '#floor',
props: ['index', 'header', 'outer-walls-holes', 'inner-walls-holes']
})
Vue.component('outer-walls-hole', {
template: '#floor',
props: ['props']
})
Vue.component('inner-walls-hole', {
template: '#floor',
props: ['props']
})
Vue.component('mansard', {
template: '#mansard',
props: ['props']
})
new Vue({
el: '#calc',
data() {
return {
fields: {
header: [{
title: 'Длина дома, м',
name: 'house_length',
value: '',
hint: 'Подсказка для поля'
},{
title: 'Ширина дома, м',
name: 'house_width',
value: '',
hint: 'Подсказка для поля'
},{
title: 'Длина внутренних несущих стен, м',
name: 'inner_bearing_walls_length',
value: '',
hint: 'Подсказка для поля'
},{
title: 'Толщина наружной стены, мм',
name: 'outer_wall_thickness',
value: '',
options: {
'100': 100,
'200': 200,
'300': 300
},
hint: 'Подсказка для поля'
},{
title: 'Толщина внутренних несущих стен, мм',
name: 'outer_bearing_walls_thickness',
value: '',
options: {
'100': 100,
'200': 200,
'300': 300
},
hint: 'Подсказка для поля'
},{
title: 'Наличие перегородок',
name: 'outer_bearing_walls_thickness',
value: '',
options: {
'Есть': true,
'Нет': false
}
}],
floors: [{
header: [{
title: 'Высота от пола до потолка, м',
name: 'floor_height',
value: '',
hint: 'Подсказка для поля'
},{
title: 'Количество этажей данного типа',
name: 'floors_length',
...