Files
sensor-web-v2/src/components/Chart.vue
Marco Crapts 27cda7f222
All checks were successful
continuous-integration/drone/push Build is passing
upgrade to Vue 3.4.3
2024-01-02 22:33:03 +01:00

124 lines
3.1 KiB
Vue

<template>
<div class="chart-container">
<Loader v-if="loading"></Loader>
<div class="chart" id="chart" ref="chart" v-else></div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import * as Highcharts from 'highcharts'
import 'highcharts/css/highcharts.scss'
import Loader from '@/components/Loader.vue'
import { capitalizeFirstLetter } from '@/utils/helpers'
import type { Window, NavType } from '@/utils/types'
import { typeApi } from '@/utils/types'
import { useFetch } from '@vueuse/core'
Highcharts.setOptions({
time: {
timezoneOffset: new Date().getTimezoneOffset()
}
})
const props = defineProps<{
activeWindow: Window
activeType: NavType | undefined
}>()
const chart = ref<HTMLElement | null>(null)
const fetchUrl = computed(() => {
const [start, end] = [props.activeWindow.getStart(), props.activeWindow.getEnd()]
const sample = Math.round((end - start) / 60 / 288) || 1
const host = import.meta.env.MODE === 'development' ? 'http://localhost:3000' : ''
const fetchUrl = `${host}/type/${
typeApi[props.activeType || 'temperatuur']
}/startDate/${start}/endDate/${end}/sample/${sample}`
return fetchUrl
})
interface ChartDataPoint {
date: Number
value: Number
}
const { data: chartData, isFetching: loading } = useFetch(fetchUrl, { refetch: true }).json<ChartDataPoint[]>()
watch([chart, chartData], () => {
if (chart.value && chartData.value) renderChart()
})
const renderChart = () => {
const data = (chartData.value || []).map(({ date, value }) => ({ x: date, y: value })) as any[]
Highcharts.chart({
chart: { renderTo: chart.value || '', styledMode: true, marginBottom: 25 },
title: { text: '' },
legend: { enabled: false },
plotOptions: { series: { animation: false, marker: { enabled: false } } },
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
millisecond: '%H:%M:%S.%L',
second: '%H:%M:%S',
minute: '%H:%M',
hour: '%H:%M',
day: '%a %e %b',
week: '%e %b',
month: "%b '%y",
year: '%Y'
}
},
yAxis: {
labels: {
formatter() {
const suffix = props.activeType === 'temperatuur' ? '°C' : '%'
return this.value + suffix
}
},
title: { text: null },
minTickInterval: 0.1
},
series: [{ name: capitalizeFirstLetter(props.activeType || ''), data: data, type: 'line' }],
credits: { enabled: false }
})
}
</script>
<style lang="scss">
@import '@/style/_variables.scss';
.chart-container {
display: flex;
flex-direction: column;
flex-grow: 1;
align-items: center;
justify-content: center;
margin-bottom: 24px;
position: relative;
}
.chart {
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
}
.highcharts-graph {
stroke-width: 3px;
}
.highcharts-color-0 {
fill: $primary;
stroke: $primary;
}
.highcharts-axis-line {
// stroke-width: 1px !important;
stroke: $border !important;
}
.highcharts-grid-line {
stroke-width: 1px !important;
stroke-dasharray: 5, 5 !important;
stroke: $border !important;
}
text {
font-size: 0.8rem;
}
</style>