470 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			470 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
@extends('base')
 | 
						||
@section('body-class', 'property')
 | 
						||
@section('header')
 | 
						||
<nav>
 | 
						||
  <strong>Property: {{ $base['check_data'] }} ({{ $base['region_name'] }})</strong>
 | 
						||
  <ul>
 | 
						||
    <li><a href="/">Start</a></li>
 | 
						||
    @foreach($regions as $r)
 | 
						||
    <li><a href="/region/{{ $r['region_id'] }}">{{ $r['region_name'] }}</a></li>
 | 
						||
    @endforeach
 | 
						||
  </ul>
 | 
						||
</nav>
 | 
						||
<button popovertarget="prop-details"></button>
 | 
						||
<div popover id="prop-details">
 | 
						||
    <dl>
 | 
						||
        <dt>Region</dt>
 | 
						||
        <dd>{{ $base['region_name'] }}</dd>
 | 
						||
        <dt>Zum ersten mal gefunden</dt>
 | 
						||
        <dd>{{ $base['first_found'] }}</dd>
 | 
						||
        <dt>Zum letzten mal gefunden</dt>
 | 
						||
        <dd>{{ $base['last_found'] }}</dd>
 | 
						||
    </dl>
 | 
						||
</div>
 | 
						||
@endsection
 | 
						||
 | 
						||
@section('main')
 | 
						||
@if(!isset($propertyCapacities['capacities']))
 | 
						||
<div style="position: absolute;">
 | 
						||
    Für dieses Mietobjekt sind keine Daten vorhanden.
 | 
						||
</div>
 | 
						||
@else
 | 
						||
<article style="grid-area: timeline;">
 | 
						||
    <div id="timeline"></div>
 | 
						||
</article>
 | 
						||
<article class="header" style="grid-area: chart1;">
 | 
						||
    <header>
 | 
						||
        <h2 id="belegung-title">
 | 
						||
            Kalenderansicht der Verfügbarkeit am <span class="date">{{ $startDate }}</span>
 | 
						||
        </h2><button popovertarget="popup-cal"></button>
 | 
						||
        <div popover id="popup-cal">
 | 
						||
            <p>
 | 
						||
                Das Kalenderdiagram zeigt die drei Verfügbarkeitskategorien des Mietobjekts.
 | 
						||
            </p>
 | 
						||
        </div>
 | 
						||
    </header>
 | 
						||
    <div id="chart-calendar"></div>
 | 
						||
</article>
 | 
						||
<article class="header map" style="grid-area: chart5;">
 | 
						||
    <header>
 | 
						||
        <h2 id="belegung-title">
 | 
						||
            Kurzzeitmietobjekte in der Nähe
 | 
						||
        </h2>
 | 
						||
    </header>
 | 
						||
    <div id="chart-map"></div>
 | 
						||
</article>
 | 
						||
<article class="header" style="grid-area: chart3;">
 | 
						||
    <header>
 | 
						||
        <h2>
 | 
						||
            Verfügbarkeit Mietobjekt Monate am <span class="date">{{ $startDate }}</span>
 | 
						||
        </h2>
 | 
						||
    </header>
 | 
						||
    <div id="chart-capacity-monthly">
 | 
						||
    </div>
 | 
						||
</article>
 | 
						||
<article class="header" style="grid-area: chart2;">
 | 
						||
    <header>
 | 
						||
        <h2>
 | 
						||
            Entwicklung der Verfügbarkeit
 | 
						||
        </h2>
 | 
						||
        <button popovertarget="chart-capacity-popover"></button>
 | 
						||
        <div id="chart-capacity-popover" popover>
 | 
						||
            <h2>Erkläung zum Diagramm</h2>
 | 
						||
            <p>Das Liniendiagramm zeigt, wie sich die insgesamte Verfügbarkeit des Kurzzeitmietobjekts entwickelt hat.</p>
 | 
						||
        </div>
 | 
						||
    </header>
 | 
						||
    <div id="chart-capacity"></div>
 | 
						||
</article>
 | 
						||
<article class="header" style="grid-area: chart4;">
 | 
						||
    <header>
 | 
						||
        <h2>
 | 
						||
            Verfügbarkeit Mietobjekt Tage am <span class="date">{{ $startDate }}</span>
 | 
						||
        </h2>
 | 
						||
    </header>
 | 
						||
    <div id="chart-capacity-daily">
 | 
						||
</article>
 | 
						||
<script type="module">
 | 
						||
 | 
						||
const sharedOptions = {
 | 
						||
  basic: {
 | 
						||
    color: {!! $chartOptions['colors'] !!},
 | 
						||
    grid: {
 | 
						||
      top: 20,
 | 
						||
      left: 60,
 | 
						||
      right: 0,
 | 
						||
      bottom: 50
 | 
						||
    },
 | 
						||
    tooltip: {
 | 
						||
        show: true,
 | 
						||
        trigger: 'axis',
 | 
						||
        valueFormatter: (value) => value.toFixed(2)+' %'
 | 
						||
    },
 | 
						||
    name: (opt) => {
 | 
						||
      return {
 | 
						||
        name: opt.name,
 | 
						||
        nameLocation: opt.location,
 | 
						||
        nameGap: 24,
 | 
						||
        nameTextStyle: {
 | 
						||
          fontWeight: 'bold',
 | 
						||
        },
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
const chartTimeline = document.getElementById('timeline');
 | 
						||
const cTimeline = echarts.init(chartTimeline);
 | 
						||
 | 
						||
const cTimelineOptions = {
 | 
						||
    grid: {
 | 
						||
        show: false,
 | 
						||
    },
 | 
						||
    timeline: {
 | 
						||
        data: {!! $extractiondates !!},
 | 
						||
        playInterval: 1000,
 | 
						||
        axisType: 'time',
 | 
						||
        left: 8,
 | 
						||
        right: 8,
 | 
						||
        bottom: 0,
 | 
						||
        label: {
 | 
						||
            show: false
 | 
						||
        }
 | 
						||
    },
 | 
						||
};
 | 
						||
 | 
						||
cTimeline.setOption(cTimelineOptions);
 | 
						||
 | 
						||
const chartCapacityMonthly = document.getElementById('chart-capacity-monthly');
 | 
						||
const cCapacityMonthly = echarts.init(chartCapacityMonthly);
 | 
						||
 | 
						||
const cCapacityMonthlyOptions = {
 | 
						||
    tooltip: sharedOptions.basic.tooltip,
 | 
						||
    timeline: {
 | 
						||
        show: false,
 | 
						||
        data: {!! $extractiondates !!},
 | 
						||
        axisType: 'time',
 | 
						||
    },
 | 
						||
    grid: {
 | 
						||
        top: 5,
 | 
						||
        bottom: 40,
 | 
						||
        left: 70,
 | 
						||
        right: 10
 | 
						||
    },
 | 
						||
    xAxis: {
 | 
						||
        type: 'value',
 | 
						||
        max: 100,
 | 
						||
        name: 'Verfügbarkeit in %',
 | 
						||
        nameLocation: 'center',
 | 
						||
        nameGap: 25,
 | 
						||
            nameTextStyle: {
 | 
						||
          fontWeight: 'bold',
 | 
						||
        }
 | 
						||
    },
 | 
						||
    yAxis: {
 | 
						||
        type: 'category',
 | 
						||
    },
 | 
						||
    options: [
 | 
						||
        @foreach ($capacitiesMonthly as $cM)
 | 
						||
        {
 | 
						||
        yAxis: {
 | 
						||
            data: {!! json_encode($cM['months']) !!}
 | 
						||
        },
 | 
						||
        series: [{
 | 
						||
            type: 'bar',
 | 
						||
            itemStyle: {
 | 
						||
                color: sharedOptions.basic.color[3]
 | 
						||
            },
 | 
						||
            data: {!! json_encode($cM['capacities']) !!}
 | 
						||
        }]
 | 
						||
    },
 | 
						||
    @endforeach
 | 
						||
    ]
 | 
						||
};
 | 
						||
 | 
						||
cCapacityMonthly.setOption(cCapacityMonthlyOptions);
 | 
						||
 | 
						||
const chartCapacityDaily = document.getElementById('chart-capacity-daily');
 | 
						||
const cCapacityDaily = echarts.init(chartCapacityDaily);
 | 
						||
 | 
						||
const cCapacityDailyOptions = {
 | 
						||
    tooltip: sharedOptions.basic.tooltip,
 | 
						||
    timeline: {
 | 
						||
        show: false,
 | 
						||
        data: {!! $extractiondates !!},
 | 
						||
        axisType: 'time',
 | 
						||
    },
 | 
						||
    grid: {
 | 
						||
        top: 5,
 | 
						||
        bottom: 40,
 | 
						||
        left: 70,
 | 
						||
        right: 10
 | 
						||
    },
 | 
						||
    xAxis: {
 | 
						||
        type: 'value',
 | 
						||
        max: 100,
 | 
						||
        name: 'Verfügbarkeit in %',
 | 
						||
        nameLocation: 'center',
 | 
						||
        nameGap: 25,
 | 
						||
            nameTextStyle: {
 | 
						||
          fontWeight: 'bold',
 | 
						||
        }
 | 
						||
    },
 | 
						||
    yAxis: {
 | 
						||
        type: 'category',
 | 
						||
    },
 | 
						||
    options: [
 | 
						||
        @foreach ($capacitiesDaily as $cD)
 | 
						||
        {
 | 
						||
        yAxis: {
 | 
						||
            data: {!! json_encode($cD['weekdays']) !!}
 | 
						||
        },
 | 
						||
        series: [{
 | 
						||
            type: 'bar',
 | 
						||
            itemStyle: {
 | 
						||
                color: sharedOptions.basic.color[3]
 | 
						||
            },
 | 
						||
            data: {!! json_encode($cD['capacities']) !!}
 | 
						||
        }]
 | 
						||
    },
 | 
						||
    @endforeach
 | 
						||
    ]
 | 
						||
};
 | 
						||
 | 
						||
cCapacityDaily.setOption(cCapacityDailyOptions);
 | 
						||
 | 
						||
const chartCapacity = document.getElementById('chart-capacity');
 | 
						||
const cCapacity = echarts.init(chartCapacity);
 | 
						||
 | 
						||
const cCapacityOptions = {
 | 
						||
    color: sharedOptions.basic.color,
 | 
						||
    legend: {
 | 
						||
        show: true
 | 
						||
    },
 | 
						||
  tooltip: {
 | 
						||
    trigger: 'axis',
 | 
						||
    valueFormatter: (value) => value.toFixed(2)+' %'
 | 
						||
  },
 | 
						||
  grid: {
 | 
						||
    top: 40,
 | 
						||
    left: 25,
 | 
						||
    right: 10,
 | 
						||
    bottom: 20,
 | 
						||
    containLabel: true
 | 
						||
  },
 | 
						||
  xAxis: {
 | 
						||
    type: 'category',
 | 
						||
    boundaryGap: false,
 | 
						||
    data: {!! json_encode($propertyCapacities['dates']) !!},
 | 
						||
    name: 'Zeitpunkt Scraping',
 | 
						||
    nameLocation: 'center',
 | 
						||
    nameGap: 24,
 | 
						||
    nameTextStyle: {
 | 
						||
      fontWeight: 'bold',
 | 
						||
    }
 | 
						||
  },
 | 
						||
  yAxis: {
 | 
						||
    type: 'value',
 | 
						||
    min: 0,
 | 
						||
    max: 100,
 | 
						||
    name: 'Verfügbarkeit in %',
 | 
						||
    nameLocation: 'center',
 | 
						||
    nameGap: 38,
 | 
						||
    nameTextStyle: {
 | 
						||
      fontWeight: 'bold',
 | 
						||
    }
 | 
						||
  },
 | 
						||
  series: [
 | 
						||
    {
 | 
						||
          name: 'Verfügbarkeit Mietobjekt',
 | 
						||
          type: 'line',
 | 
						||
          symbolSize: 7,
 | 
						||
          data: {!! json_encode($propertyCapacities['capacities']) !!}
 | 
						||
        },
 | 
						||
        {
 | 
						||
            name: 'Verfügbarkeit {{ $base['region_name'] }}',
 | 
						||
            type: 'line',
 | 
						||
            symbolSize: 7,
 | 
						||
            data: {!! json_encode($regionCapacities[0]) !!}
 | 
						||
        },
 | 
						||
        {
 | 
						||
            name: 'Verfügbarkeit alle Regionen',
 | 
						||
            type: 'line',
 | 
						||
            symbolSize: 7,
 | 
						||
            data: {!! json_encode($regionCapacities[1]) !!}
 | 
						||
        }
 | 
						||
    ]
 | 
						||
};
 | 
						||
 | 
						||
cCapacity.setOption(cCapacityOptions);
 | 
						||
 | 
						||
const chartCalendar = document.getElementById('chart-calendar');
 | 
						||
const cCalendar = echarts.init(chartCalendar);
 | 
						||
const h2Belegung = document.getElementById('belegung-title');
 | 
						||
 | 
						||
const cCalendarOptions = {
 | 
						||
    timeline: {
 | 
						||
        show: false,
 | 
						||
        data: {!! json_encode($propertyCapacities['dates']) !!},
 | 
						||
        axisType: 'time',
 | 
						||
    },
 | 
						||
    visualMap: {
 | 
						||
        categories: [0,1,2],
 | 
						||
        inRange: {
 | 
						||
            color: ['#ca0020', '#92c5de', '#0571b0']
 | 
						||
        },
 | 
						||
        formatter: (cat) => {
 | 
						||
            switch (cat) {
 | 
						||
                case 0:
 | 
						||
                return 'Ausgebucht';
 | 
						||
                case 1:
 | 
						||
                    return 'Verfügbar (kein Anreisetag)';
 | 
						||
                case 2:
 | 
						||
                    return 'Verfügbar';
 | 
						||
            }
 | 
						||
        },
 | 
						||
        type: 'piecewise',
 | 
						||
        orient: 'horizontal',
 | 
						||
        left: 'center',
 | 
						||
        top: 0
 | 
						||
    },
 | 
						||
    calendar:[
 | 
						||
        {
 | 
						||
          orient: 'horizontal',
 | 
						||
          range: '2024',
 | 
						||
          top: '15%',
 | 
						||
          right: 10,
 | 
						||
          bottom: '65%',
 | 
						||
          left: 50,
 | 
						||
          dayLabel: {
 | 
						||
            fontSize: 10
 | 
						||
          }
 | 
						||
        },
 | 
						||
        {
 | 
						||
          orient: 'horizontal',
 | 
						||
          range: '2025',
 | 
						||
          top: '47%',
 | 
						||
          right: 10,
 | 
						||
          bottom: '33%',
 | 
						||
          left: 50,
 | 
						||
          dayLabel: {
 | 
						||
            fontSize: 10
 | 
						||
          }
 | 
						||
        },
 | 
						||
        {
 | 
						||
          orient: 'horizontal',
 | 
						||
          range: '2026',
 | 
						||
          top: '79%',
 | 
						||
          right: 10,
 | 
						||
          bottom: '1%',
 | 
						||
          left: 50,
 | 
						||
          dayLabel: {
 | 
						||
            fontSize: 10
 | 
						||
          }
 | 
						||
        }
 | 
						||
    ],
 | 
						||
    options: [
 | 
						||
        @foreach ($calendar as $c)
 | 
						||
        {
 | 
						||
            series: [{
 | 
						||
                type: 'heatmap',
 | 
						||
                coordinateSystem: 'calendar',
 | 
						||
                calendarIndex: 0,
 | 
						||
                data: {!! json_encode($c) !!}
 | 
						||
            },
 | 
						||
            {
 | 
						||
                type: 'heatmap',
 | 
						||
                coordinateSystem: 'calendar',
 | 
						||
                calendarIndex: 1,
 | 
						||
                data: {!! json_encode($c) !!}
 | 
						||
            },
 | 
						||
            {
 | 
						||
                type: 'heatmap',
 | 
						||
                coordinateSystem: 'calendar',
 | 
						||
                calendarIndex: 2,
 | 
						||
                data: {!! json_encode($c) !!}
 | 
						||
            }]
 | 
						||
        },
 | 
						||
        @endforeach
 | 
						||
    ]
 | 
						||
};
 | 
						||
 | 
						||
cCalendar.setOption(cCalendarOptions);
 | 
						||
 | 
						||
 | 
						||
cTimeline.on('timelinechanged', (e) => {
 | 
						||
 | 
						||
    let dateTitles = document.querySelectorAll('span.date');
 | 
						||
    dateTitles.forEach(el => {
 | 
						||
        el.innerText = cTimelineOptions.timeline.data[e.currentIndex];
 | 
						||
    });
 | 
						||
 | 
						||
    // Set markpoint on linechart
 | 
						||
    let x = cCapacityOptions.xAxis.data[e.currentIndex];
 | 
						||
    let y = cCapacityOptions.series[0].data[e.currentIndex];
 | 
						||
 | 
						||
    cCapacityMonthly.dispatchAction({
 | 
						||
        type: 'timelineChange',
 | 
						||
        currentIndex: e.currentIndex
 | 
						||
    });
 | 
						||
 | 
						||
    cCapacityDaily.dispatchAction({
 | 
						||
        type: 'timelineChange',
 | 
						||
        currentIndex: e.currentIndex
 | 
						||
    });
 | 
						||
 | 
						||
     cCalendar.dispatchAction({
 | 
						||
        type: 'timelineChange',
 | 
						||
        currentIndex: e.currentIndex
 | 
						||
    });
 | 
						||
 | 
						||
    cCapacity.setOption({
 | 
						||
        series: {
 | 
						||
            markPoint: {
 | 
						||
            data: [{
 | 
						||
                    coord: [x, y]
 | 
						||
                }]
 | 
						||
            }
 | 
						||
        }
 | 
						||
    });
 | 
						||
 | 
						||
})
 | 
						||
 | 
						||
/* Map w/ neighbours*/
 | 
						||
const map = L.map('chart-map');
 | 
						||
 | 
						||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
 | 
						||
    maxZoom: 19,
 | 
						||
    attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
 | 
						||
}).addTo(map);
 | 
						||
 | 
						||
function icon(id = 0){
 | 
						||
  return L.divIcon({
 | 
						||
    className: "region"+id,
 | 
						||
    html: '<span></span>'
 | 
						||
  })
 | 
						||
}
 | 
						||
 | 
						||
const markers = L.featureGroup([
 | 
						||
    L.marker([{{ $base['check_data'] }}], {icon: icon(1)}),
 | 
						||
    @foreach($neighbours as $n)
 | 
						||
    L.marker([{{ $n['lat'] }}, {{ $n['lon'] }}], {icon: icon()}).bindPopup('<a href="/property/{{ $n['id'] }}">{{ $n['lat'] }}, {{ $n['lon'] }}</a>'),
 | 
						||
    @endforeach
 | 
						||
]).addTo(map);
 | 
						||
 | 
						||
map.fitBounds(markers.getBounds(), {padding: [20,20]})
 | 
						||
 | 
						||
cCapacity.on('click', 'series', (e) => {
 | 
						||
 | 
						||
    // Switch to correct calendar in the timeline
 | 
						||
    cTimeline.dispatchAction({
 | 
						||
        type: 'timelineChange',
 | 
						||
        currentIndex: e.dataIndex
 | 
						||
    });
 | 
						||
 | 
						||
});
 | 
						||
 | 
						||
 | 
						||
</script>
 | 
						||
@endif
 | 
						||
@endsection
 |