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',
           ...