* [WIP] Transfer analytics to own branch * code style changes * Refactor country name conversion * Clean up api and ssr for settings page * refactor analytics into reusables * Refactor chart tooltip and reset functionality * Update dayjs import and formatTimestamp function * Fix bug in login functionality * Abstract data fetching * Refactor analytics data formatting * Refactor useFetchAllAnalytics function signature * Refactor analytics processing functions * Fix chart data in ChartDisplay.vue * Refactor analytics pages * Refactor delete labrinth.ts test types * Fix import statement for dayjs and update usage of unix function * Fix dropdown select in ChartDisplay.vue and add Analytics link in creations.vue * Update chart colors in ChartDisplay.vue and analytics.js * Update defaultRanges in ChartDisplay.vue * Add colors to chart * Update legend position in ChartDisplay.vue * Refactor color conversion functions in analytics.js * Bug fixes * Use softer colors * Import dayjs unix module for analytics.js * Refactor chart tooltip generation * Fix calculation of total value in generateTooltip function * Fix button-base styling in ChartDisplay.vue * Adopt intl standard rather than iso-3166-1 * Add support for potential flags * Analytics rebased * fix cf pages * now? * try now * now? * Fix this time * address rev * Finish analytics * fix api url --------- Co-authored-by: Carter <safe@fea.st>
281 lines
4.8 KiB
Vue
281 lines
4.8 KiB
Vue
<script setup>
|
|
import { Card } from 'omorphia'
|
|
import VueApexCharts from 'vue3-apexcharts'
|
|
|
|
// let VueApexCharts
|
|
// if (process.client) {
|
|
// VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
|
// }
|
|
|
|
const props = defineProps({
|
|
value: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
title: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
data: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
labels: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
prefix: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
suffix: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
isMoney: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
color: {
|
|
type: String,
|
|
default: 'var(--color-brand)',
|
|
},
|
|
})
|
|
|
|
// no grid lines, no toolbar, no legend, no data labels
|
|
const chartOptions = {
|
|
chart: {
|
|
id: props.title,
|
|
fontFamily:
|
|
'Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif',
|
|
foreColor: 'var(--color-base)',
|
|
toolbar: {
|
|
show: false,
|
|
},
|
|
zoom: {
|
|
enabled: false,
|
|
},
|
|
sparkline: {
|
|
enabled: true,
|
|
},
|
|
parentHeightOffset: 0,
|
|
},
|
|
stroke: {
|
|
curve: 'smooth',
|
|
width: 2,
|
|
},
|
|
fill: {
|
|
colors: [props.color],
|
|
type: 'gradient',
|
|
opacity: 1,
|
|
gradient: {
|
|
shade: 'light',
|
|
type: 'vertical',
|
|
shadeIntensity: 0,
|
|
gradientToColors: [props.color],
|
|
inverseColors: true,
|
|
opacityFrom: 0.5,
|
|
opacityTo: 0,
|
|
stops: [0, 100],
|
|
colorStops: [],
|
|
},
|
|
},
|
|
grid: {
|
|
show: false,
|
|
},
|
|
legend: {
|
|
show: false,
|
|
},
|
|
colors: [props.color],
|
|
dataLabels: {
|
|
enabled: false,
|
|
},
|
|
xaxis: {
|
|
type: 'datetime',
|
|
categories: props.labels,
|
|
labels: {
|
|
show: false,
|
|
},
|
|
axisTicks: {
|
|
show: false,
|
|
},
|
|
tooltip: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
yaxis: {
|
|
labels: {
|
|
show: false,
|
|
},
|
|
axisBorder: {
|
|
show: false,
|
|
},
|
|
axisTicks: {
|
|
show: false,
|
|
},
|
|
tooltip: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
tooltip: {
|
|
enabled: false,
|
|
},
|
|
}
|
|
|
|
const chart = ref(null)
|
|
|
|
const resetChart = () => {
|
|
chart.value?.updateSeries([...props.data])
|
|
chart.value?.updateOptions({
|
|
xaxis: {
|
|
categories: props.labels,
|
|
},
|
|
})
|
|
chart.value?.resetSeries()
|
|
}
|
|
|
|
defineExpose({
|
|
resetChart,
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<Card class="compact-chart">
|
|
<h1 class="value">
|
|
{{ value }}
|
|
</h1>
|
|
<div class="subtitle">
|
|
{{ title }}
|
|
</div>
|
|
<div class="chart">
|
|
<VueApexCharts ref="chart" type="area" :options="chartOptions" :series="data" height="70" />
|
|
</div>
|
|
</Card>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.compact-chart {
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
gap: var(--gap-xs);
|
|
border: 1px solid var(--color-button-bg);
|
|
border-radius: var(--radius-md);
|
|
background-color: var(--color-raised-bg);
|
|
box-shadow: var(--shadow-floating);
|
|
|
|
color: var(--color-base);
|
|
font-size: var(--font-size-nm);
|
|
|
|
width: 100%;
|
|
|
|
padding-top: var(--gap-xl);
|
|
padding-bottom: 0;
|
|
|
|
.value {
|
|
margin: 0;
|
|
}
|
|
}
|
|
|
|
.chart {
|
|
// width: calc(100% + 3rem);
|
|
margin: 0 -1.5rem 0.25rem -1.5rem;
|
|
}
|
|
|
|
svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
:deep(.apexcharts-menu),
|
|
:deep(.apexcharts-tooltip),
|
|
:deep(.apexcharts-yaxistooltip) {
|
|
background: var(--color-raised-bg) !important;
|
|
border-radius: var(--radius-sm) !important;
|
|
border: 1px solid var(--color-button-bg) !important;
|
|
box-shadow: var(--shadow-floating) !important;
|
|
font-size: var(--font-size-nm) !important;
|
|
}
|
|
|
|
:deep(.apexcharts-graphical) {
|
|
width: 100%;
|
|
}
|
|
|
|
:deep(.apexcharts-tooltip) {
|
|
.bar-tooltip {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--gap-xs);
|
|
padding: var(--gap-sm);
|
|
|
|
.card-divider {
|
|
margin: var(--gap-xs) 0;
|
|
}
|
|
|
|
.label {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
}
|
|
|
|
.value {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
gap: var(--gap-xs);
|
|
color: var(--color-base);
|
|
}
|
|
|
|
.list-entry {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--gap-md);
|
|
}
|
|
|
|
.circle {
|
|
width: 0.5rem;
|
|
height: 0.5rem;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
margin-right: var(--gap-sm);
|
|
}
|
|
|
|
svg {
|
|
height: 1em;
|
|
width: 1em;
|
|
}
|
|
|
|
.divider {
|
|
font-size: var(--font-size-lg);
|
|
font-weight: 400;
|
|
}
|
|
}
|
|
}
|
|
|
|
.legend {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
gap: var(--gap-md);
|
|
justify-content: center;
|
|
}
|
|
|
|
:deep(.apexcharts-grid-borders) {
|
|
line {
|
|
stroke: var(--color-button-bg) !important;
|
|
}
|
|
}
|
|
|
|
:deep(.apexcharts-xaxis) {
|
|
line {
|
|
stroke: none;
|
|
}
|
|
}
|
|
|
|
.legend-checkbox :deep(.checkbox.checked) {
|
|
background-color: var(--color);
|
|
}
|
|
</style>
|