some polishing

main
Giò Diani 2025-01-15 16:57:18 +01:00
parent 959b84d1e1
commit 3290c1cce3
6 changed files with 185 additions and 83 deletions

View File

@ -5,7 +5,7 @@ namespace App;
class Chart
{
public static function colors(int $count = 5){
$colors = ['#bfd3e6','#8c96c6','#88419d','#810f7c','#4d004b'];
$colors = ['#9ebcda','#8c96c6','#88419d','#810f7c','#4d004b'];
return json_encode($colors);
}

View File

@ -54,10 +54,19 @@ dd + dt{
margin-top: .2em;
}
nav + button,
span + button{
margin-left: .5em;
}
ul{
padding-left: 1em;
}
p + ul{
margin-top: 1em;
}
button[popovertarget]{
background: no-repeat center / .3em #4d004b url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 192 512'%3E%3C!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--%3E%3Cpath fill='%23fff' d='M48 80a48 48 0 1 1 96 0A48 48 0 1 1 48 80zM0 224c0-17.7 14.3-32 32-32l64 0c17.7 0 32 14.3 32 32l0 224 32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 512c-17.7 0-32-14.3-32-32s14.3-32 32-32l32 0 0-192-32 0c-17.7 0-32-14.3-32-32z'/%3E%3C/svg%3E%0A");
cursor: pointer;
@ -95,6 +104,10 @@ button[popovertarget]>span{
background-color: rgba(0,0,0,.5);
}
[popover] h2{
font-size: 1em;
}
/*
9. Create a root stacking context
@ -118,8 +131,7 @@ body>header{
body>header>nav{
text-align: center;
max-width: 10em;
width: 100%;
min-width: 10em;
background: #fff;
border-radius: .2em;
position: relative;
@ -174,25 +186,28 @@ body.overview main{
"chart3 chart3 chart3 chart2 chart2 chart2 chart4 chart4"
}
body.property main{
body.region main{
grid-template-columns: repeat(4, minmax(10%, 50%));
grid-template-rows: repeat(3, 1fr) 4em;
grid-template-rows: repeat(6, 1fr) 4em;
grid-template-areas:
"chart2 chart2 chart1 chart1"
"chart5 chart5 chart1 chart1"
"chart5 chart5 chart3 chart4"
"chart5 chart5 timeline timeline";
"chart1 chart1 chart2 chart2"
"chart1 chart1 chart2 chart2"
"chart1 chart1 chart3 chart4"
"chart1 chart1 chart3 chart4"
"chart1 chart1 chart6 chart6"
"chart1 chart1 chart6 chart6"
"chart1 chart1 timeline timeline";
}
body.region main{
body.property main{
grid-template-columns: repeat(4, minmax(10%, 50%));
grid-template-rows: repeat(4, 1fr) 4em;
grid-template-areas:
"chart1 chart1 chart2 chart2"
"chart1 chart1 chart6 chart6"
"chart1 chart1 chart3 chart4"
"chart1 chart1 chart3 chart4"
"chart1 chart1 timeline timeline";
"chart2 chart2 chart1 chart1"
"chart2 chart2 chart1 chart1"
"chart5 chart5 chart3 chart4"
"chart5 chart5 chart3 chart4"
"chart5 chart5 timeline timeline";
}
article{
@ -205,7 +220,7 @@ article{
article.header{
grid-template-columns: 100%;
grid-template-rows: minmax(1%, 2.5em) 1fr;
grid-template-rows: minmax(1%, 2em) 1fr;
padding: .5em 1em 1em .5em;
}

View File

@ -11,16 +11,44 @@
</nav>
@endsection
@section('main')
<article class="header" style="grid-area: chart3;">
<header>
<h2>Auslastung aller Mietobjekte über Gesamte Zeit</h2>
<button popovertarget="pop1">
<span>Erklärungen zum Diagramm</span>
</button>
<div popover id="pop1">
<h2>Auslastung aller Mietobjekte über Gesamte Zeit</h2>
<p>
Das Diagramm gibt eine Übersicht, wie die Auslastung von Mietobjekten am Datum des Scrapings waren. Dazu wird für jedes Mietobjekt die durchschnittliche Verfügbarkeit ermittelt.
</p>
<ul>
<li>X-Achse: Zeitpunkt Scraping.</li>
<li>Y-Achse: Mietobjekte.</li>
<li>Kategorien: 0% = Das Mietobjekt ist komplett verfügbar; 100% = Das Mietobjekt ist komplett ausgebucht.</li>
</ul>
</div>
<div>
</header>
<div id="chart-heatmap"></div>
</article>
<article class="header" style="grid-area: chart1;">
<header>
<h2>
Anzahl jemals gefundene Kurzzeitmietobjekte pro Region
</h2>
<button popovertarget="pop1">
<button popovertarget="pop2">
<span>Erklärungen zum Diagramm</span>
</button>
<div popover id="pop1">
<p>Das Diagram zeigt...</p>
<div popover id="pop2">
<h2>Anzahl jemals gefundene Kurzzeitmietobjekte pro Region</h2>
<p>
Das Balkendiagramm zeigt wieviele Kurzzeitmietobjekte insgesamt pro Region über den gesamten Datenerhebungszeitraum, gefunden wurden.
</p>
<ul>
<li>X-Achse: Bezeichnung der Region.</li>
<li>Y-Achse: Anzahl Mietobjekte.</li>
</ul>
</div>
<div>
</header>
@ -31,36 +59,41 @@
<h2>
Entwicklung der Anzahl jemals gefunden Kurzzeitmietobjekte
</h2>
<button popovertarget="pop3">
<span>Erklärungen zum Diagramm</span>
</button>
<div popover id="pop3">
<h2>Entwicklung Anzahl jemals gefundener Kurzzeitmietobjekte pro Region</h2>
<p>
Das Liniendiagramm zeigt die Entwicklung der gefundenen Mietobjekte pro Region.
</p>
<ul>
<li>X-Achse: Zeitpunkt Scraping.</li>
<li>Y-Achse: Anzahl Mietobjekte.</li>
</ul>
</div>
<div>
</header>
<div id="extractions"></div>
</article>
<article style="grid-area: chart4;">
<div id="leaflet"></div>
</article>
<article class="header" style="grid-area: chart3;">
<header>
<h2>
Gesamtauslastung
</h2>
</header>
<div id="chart-heatmap"></div>
</article>
<script type="module">
const sharedOptions = {
basic: {
color: {!! $chartOptions['colors'] !!},
grid: {
top: 20,
left: 60,
top: 30,
left: 70,
right: 0,
bottom: 50
bottom: 45
},
name: (opt) => {
return {
name: opt.name,
nameLocation: opt.location,
nameGap: 24,
nameGap: 50,
nameTextStyle: {
fontWeight: 'bold',
},
@ -160,7 +193,7 @@ const cPropsPerRegionOptions = {
xAxis: {
name: 'Region',
nameLocation: 'center',
nameGap: 24,
nameGap: 30,
nameTextStyle: {
fontWeight: 'bold',
},
@ -169,9 +202,9 @@ const cPropsPerRegionOptions = {
},
yAxis: {
type: 'value',
name: 'Anzahl Kurzzeitmietobjekte',
name: 'Anzahl Mietobjekte',
nameLocation: 'middle',
nameGap: 38,
nameGap: 50,
nameTextStyle: {
fontWeight: 'bold',
},
@ -219,9 +252,9 @@ const cExtractionsOptions = {
data: extractionDates
},
yAxis: {
name: 'Anzahl Kurzzeitmietobjekte',
name: 'Anzahl Mietobjekte',
nameLocation: 'center',
nameGap: 38,
nameGap: 50,
nameTextStyle: {
fontWeight: 'bold',
},

View File

@ -1,7 +1,16 @@
@extends('base')
@section('body-class', 'property')
@section('header')
<span>Property {{ $base['property_platform_id'] }}</span><button popovertarget="prop-details"></button>
<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>
@ -80,6 +89,11 @@ const sharedOptions = {
right: 0,
bottom: 50
},
tooltip: {
show: true,
trigger: 'axis',
valueFormatter: (value) => value.toFixed(2)+'%'
},
name: (opt) => {
return {
name: opt.name,
@ -102,7 +116,7 @@ const cTimelineOptions = {
},
timeline: {
data: {!! $extractiondates !!},
playInterval: 2000,
playInterval: 1000,
axisType: 'time',
left: 8,
right: 8,
@ -119,20 +133,27 @@ 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: 0,
bottom: 25,
top: 5,
bottom: 40,
left: 70,
right: 10
},
xAxis: {
type: 'value',
max: 100
max: 100,
name: 'Auslastung in %',
nameLocation: 'center',
nameGap: 25,
nameTextStyle: {
fontWeight: 'bold',
}
},
yAxis: {
type: 'category',
@ -161,20 +182,27 @@ 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: 0,
bottom: 25,
top: 5,
bottom: 40,
left: 70,
right: 10
},
xAxis: {
type: 'value',
max: 100
max: 100,
name: 'Auslastung in %',
nameLocation: 'center',
nameGap: 25,
nameTextStyle: {
fontWeight: 'bold',
}
},
yAxis: {
type: 'category',
@ -277,7 +305,7 @@ const cCalendarOptions = {
visualMap: {
categories: [0,1,2],
inRange: {
color: ['#d95f02', '#7570b3', '#1b9e77']
color: ['#ca0020', '#92c5de', '#0571b0']
},
formatter: (cat) => {
switch (cat) {

View File

@ -19,20 +19,20 @@
</article>
<article class="header" style="grid-area: chart6;">
<header>
<h2 id="prediction-title">Gleitender Mittelwert für die Auslastung von {{ $region[0]['region_name'] }}</h2>
<h2 id="prediction-title">Gleitender Mittelwert für die Auslastung der Region</h2>
</header>
<div id="chart-prediction"></div>
</article>
<article class="header" style="grid-area: chart1;">
<header>
<h2 id="belegung-title">Gesamtauslastung</h2>
<h2 id="belegung-title">Auslastung aller Mietobjekte über Gesamte Zeit der Region</h2>
</header>
<div id="chart-heatmap"></div>
</article>
<article class="header" style="grid-area: chart3;">
<header>
<h2>
Auslastung der Region nach Monat am <span class="date">{{ $startDate }}</span>
Auslastung Region nach Monat am <span class="date">{{ $startDate }}</span>
</h2>
</header>
<div id="chart-capacity-monthly">
@ -54,7 +54,7 @@
<article class="header" style="grid-area: chart4;">
<header>
<h2>
Auslastung der Region nach Wochentage am <span class="date">{{ $startDate }}</span>
Auslastung Wochentage am <span class="date">{{ $startDate }}</span>
</h2>
</header>
<div id="chart-capacity-daily">
@ -71,6 +71,11 @@ const sharedOptions = {
right: 0,
bottom: 50
},
tooltip: {
show: true,
trigger: 'axis',
valueFormatter: (value) => value.toFixed(2)+'%'
},
name: (opt) => {
return {
name: opt.name,
@ -89,12 +94,9 @@ const cCapacity = echarts.init(chartCapacity);
const cCapacityOptions = {
legend: {
data: ['Auslastung Region', 'Auslastung alle Regionen']
},
tooltip: {
trigger: 'axis',
valueFormatter: (value) => value.toFixed(2)+'%'
show: true
},
tooltip: sharedOptions.basic.tooltip,
color: sharedOptions.basic.color,
grid: {
top: 20,
@ -151,18 +153,25 @@ const cCapacityMonthlyOptions = {
axisType: 'time',
},
grid: {
top: 0,
bottom: 25,
top: 5,
bottom: 40,
left: 70,
right: 10
},
xAxis: {
type: 'value',
max: 100
max: 100,
name: 'Auslastung in %',
nameLocation: 'center',
nameGap: 25,
nameTextStyle: {
fontWeight: 'bold',
}
},
yAxis: {
type: 'category',
},
tooltip: sharedOptions.basic.tooltip,
options: [
@foreach ($regionCapacities['region_monthly'] as $m)
{
@ -192,15 +201,22 @@ const cCapacityDailyOptions = {
data: {!! json_encode($regionCapacities['region']['dates']) !!},
axisType: 'time',
},
tooltip: sharedOptions.basic.tooltip,
grid: {
top: 0,
bottom: 25,
top: 5,
bottom: 40,
left: 70,
right: 10
},
xAxis: {
type: 'value',
max: 100
max: 100,
name: 'Auslastung in %',
nameLocation: 'center',
nameGap: 25,
nameTextStyle: {
fontWeight: 'bold',
}
},
yAxis: {
type: 'category',
@ -229,6 +245,7 @@ const chartPrediction = document.getElementById('chart-prediction');
const cPrediction = echarts.init(chartPrediction);
const cPredictionOptions = {
color: sharedOptions.basic.color,
timeline: {
show: false,
data: {!! json_encode($regionCapacities['region']['dates']) !!},
@ -238,10 +255,7 @@ const cPredictionOptions = {
legend: {
show: true
},
tooltip: {
trigger: 'axis',
valueFormatter: (value) => value.toFixed(2)+'%'
},
tooltip: sharedOptions.basic.tooltip,
grid: {
top: 20,
left: 25,
@ -468,6 +482,16 @@ cTimeline.on('timelinechanged', (e) => {
})
document.querySelector('header').addEventListener('click', () => {
console.log('test');
cCapacityMonthly.dispatchAction({
type: 'timelineChange',
currentIndex: 10
});
})
cCapacity.on('click', 'series', (e) => {
// Switch to correct calendar in the timeline

View File

@ -86,7 +86,8 @@ Route::get('/property/{id}', function (int $id) {
$chartOptions = [
'colors' => Chart::colors()
];
$regionBaseAll = Api::regionBase(-1);
$regionBaseAll[] = ['region_name' => 'Alle Regionen', 'region_id' => -1];
$propertyBase = Api::propertyBase($id);
$calendars = Api::propertyExtractions($id);
$propertyCapacities = Api::propertyCapacities($id);
@ -137,6 +138,7 @@ Route::get('/property/{id}', function (int $id) {
'chartOptions' => $chartOptions,
'startDate' => $propertyCapacities['dates'][0],
'base' => $propertyBase[0],
'regions' => $regionBaseAll,
'extractiondates' => json_encode($propertyCapacities['dates']),
'calendar' => $data,
'propertyCapacities' => $propertyCapacities,