Skip to content

Commit 13cb448

Browse files
committed
charts progress
1 parent fc52dfd commit 13cb448

File tree

14 files changed

+641
-275
lines changed

14 files changed

+641
-275
lines changed

adminforth/spa/package-lock.json

Lines changed: 77 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adminforth/spa/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
1717
"@unhead/vue": "^1.9.12",
1818
"@vueuse/core": "^10.10.0",
19+
"apexcharts": "^4.3.0",
1920
"dayjs": "^1.11.11",
2021
"debounce": "^2.1.0",
2122
"flowbite": "^2.3.0",
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<template>
2+
<div ref="chart"></div>
3+
</template>
4+
5+
<script setup lang="ts">
6+
import ApexCharts, { type ApexOptions } from 'apexcharts';
7+
import { ref, type Ref, watch, computed } from 'vue';
8+
9+
const chart: Ref<HTMLDivElement | null> = ref(null);
10+
11+
const props = defineProps<{
12+
data: {
13+
x: string,
14+
[key: string]: any,
15+
}[],
16+
series: {
17+
name: string,
18+
fieldName: string,
19+
color: string,
20+
}[],
21+
options: ApexOptions,
22+
}>();
23+
24+
25+
26+
const optionsBase = {
27+
chart: {
28+
height: 150,
29+
type: "area",
30+
fontFamily: "Inter, sans-serif",
31+
dropShadow: {
32+
enabled: false,
33+
},
34+
toolbar: {
35+
show: false,
36+
},
37+
},
38+
tooltip: {
39+
enabled: true,
40+
x: {
41+
show: false,
42+
},
43+
},
44+
fill: {
45+
type: "gradient",
46+
gradient: {
47+
opacityFrom: 0.55,
48+
opacityTo: 0,
49+
shade: "#1C64F2",
50+
gradientToColors: ["#1C64F2"],
51+
},
52+
},
53+
dataLabels: {
54+
enabled: false,
55+
},
56+
stroke: {
57+
width: 6,
58+
},
59+
grid: {
60+
show: false,
61+
strokeDashArray: 4,
62+
padding: {
63+
left: 2,
64+
right: 2,
65+
top: 0
66+
},
67+
},
68+
series: [],
69+
xaxis: {
70+
categories: [],
71+
labels: {
72+
show: false,
73+
},
74+
axisBorder: {
75+
show: false,
76+
},
77+
axisTicks: {
78+
show: false,
79+
},
80+
},
81+
yaxis: {
82+
show: false,
83+
},
84+
};
85+
86+
const options = computed(() => {
87+
if (props.data?.length > 0) {
88+
props.series.forEach((s) => {
89+
if (props.data[0][s.fieldName] === undefined) {
90+
throw new Error(`Field ${s.fieldName} not found even in first data point ${JSON.stringify(props.data[0])}, something is wrong`);
91+
}
92+
});
93+
}
94+
const options = {
95+
...optionsBase,
96+
97+
// shade and gradient take from first series
98+
fill: {
99+
...optionsBase.fill,
100+
gradient: {
101+
...optionsBase.fill.gradient,
102+
shade: props.series[0].color,
103+
gradientToColors: [props.series[0].color],
104+
},
105+
},
106+
series: props.series.map((s) => ({
107+
data: props.data?.map((item) => item[s.fieldName]) ?? [],
108+
...s,
109+
})),
110+
xaxis: {
111+
...optionsBase.xaxis,
112+
categories: props.data?.map((item) => item.x) ?? [],
113+
},
114+
};
115+
116+
// for each of ...props.options merge on lowest level. so if { chart: {height : 2} }, it should not replace chart level, only height level
117+
function mergeOptions(options: any, newOptions: any) {
118+
for (const key in newOptions) {
119+
if (typeof newOptions[key] === 'object') {
120+
if (!options[key]) {
121+
options[key] = {};
122+
}
123+
mergeOptions(options[key], newOptions[key]);
124+
} else {
125+
options[key] = newOptions[key];
126+
}
127+
}
128+
}
129+
mergeOptions(options, props.options);
130+
131+
return options;
132+
});
133+
134+
let apexChart: ApexCharts;
135+
136+
watch(() => options.value, (value) => {
137+
if (apexChart) {
138+
apexChart.updateOptions(value);
139+
} else {
140+
console.log('chart.value', value);
141+
apexChart = new ApexCharts(chart.value, value);
142+
apexChart.render();
143+
}
144+
});
145+
146+
</script>

0 commit comments

Comments
 (0)