@extends('base') @section('body-class', 'property') @section('header') <nav> <strong>Property: {{ $base['check_data'] }}</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') <article style="grid-area: timeline;"> <div id="timeline"></div> </article> <article class="header" style="grid-area: chart1;"> <header> <h2 id="belegung-title"> Kalenderansicht der Belegung 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> Belegung 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> Belegung 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: 'Auslastung 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: 'Auslastung 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: { data: ['Auslastung Property', 'Auslastung {{ $base['region_name'] }}', 'Auslastung alle Regionen'] }, 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: 'Auslastung in Prozent', nameLocation: 'center', nameGap: 38, nameTextStyle: { fontWeight: 'bold', } }, series: [ { name: 'Auslastung Property', type: 'line', symbolSize: 7, data: {!! json_encode($propertyCapacities['capacities']) !!} }, { name: 'Auslastung {{ $base['region_name'] }}', type: 'line', symbolSize: 7, data: {!! json_encode($regionCapacities[0]) !!} }, { name: 'Auslastung 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, }, { orient: 'horizontal', range: '2025', top: '47%', right: 10, bottom: '33%', left: 50, }, { orient: 'horizontal', range: '2026', top: '79%', right: 10, bottom: '1%', left: 50, } ], 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> @endsection