Skip to content

Commit dc55c62

Browse files
author
Lasim
committed
feat(frontend): add chart components with echarts integration
1 parent d147bfb commit dc55c62

File tree

5 files changed

+251
-0
lines changed

5 files changed

+251
-0
lines changed

package-lock.json

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

services/frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@vueuse/core": "^13.9.0",
2121
"class-variance-authority": "^0.7.1",
2222
"clsx": "^2.1.1",
23+
"echarts": "^6.0.0",
2324
"lucide-vue-next": "^0.544.0",
2425
"marked": "^16.3.0",
2526
"mitt": "^3.0.1",
@@ -30,6 +31,7 @@
3031
"tailwindcss-animate": "^1.0.7",
3132
"vee-validate": "^4.15.1",
3233
"vue": "^3.5.21",
34+
"vue-echarts": "^8.0.0",
3335
"vue-i18n": "^11.1.12",
3436
"vue-router": "^4.5.1",
3537
"vue-sonner": "^2.0.9",
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue'
3+
import VChart from 'vue-echarts'
4+
import { cva, type VariantProps } from 'class-variance-authority'
5+
import { cn } from '@/lib/utils'
6+
import type { EChartsOption } from 'echarts'
7+
8+
const chartVariants = cva(
9+
'w-full',
10+
{
11+
variants: {
12+
variant: {
13+
line: '',
14+
area: '',
15+
bar: '',
16+
pie: '',
17+
},
18+
size: {
19+
sm: 'h-[200px]',
20+
md: 'h-[300px]',
21+
lg: 'h-[400px]',
22+
xl: 'h-[500px]',
23+
},
24+
},
25+
defaultVariants: {
26+
variant: 'line',
27+
size: 'md',
28+
},
29+
}
30+
)
31+
32+
export interface ChartProps {
33+
option: EChartsOption
34+
variant?: VariantProps<typeof chartVariants>['variant']
35+
size?: VariantProps<typeof chartVariants>['size']
36+
loading?: boolean
37+
autoresize?: boolean
38+
class?: string
39+
}
40+
41+
const props = withDefaults(defineProps<ChartProps>(), {
42+
variant: 'line',
43+
size: 'md',
44+
loading: false,
45+
autoresize: true,
46+
})
47+
</script>
48+
49+
<template>
50+
<div :class="cn(chartVariants({ variant, size }), props.class)">
51+
<VChart
52+
:option="option"
53+
:autoresize="autoresize"
54+
:loading="loading"
55+
class="h-full w-full"
56+
/>
57+
</div>
58+
</template>
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue'
3+
import { use } from 'echarts/core'
4+
import { LineChart as EChartsLineChart } from 'echarts/charts'
5+
import {
6+
GridComponent,
7+
TooltipComponent,
8+
LegendComponent,
9+
} from 'echarts/components'
10+
import { CanvasRenderer } from 'echarts/renderers'
11+
import Chart, { type ChartProps } from './Chart.vue'
12+
import type { EChartsOption } from 'echarts'
13+
14+
use([
15+
GridComponent,
16+
TooltipComponent,
17+
LegendComponent,
18+
EChartsLineChart,
19+
CanvasRenderer,
20+
])
21+
22+
export interface LineChartProps extends Omit<ChartProps, 'option' | 'variant'> {
23+
data: number[]
24+
labels: string[]
25+
name?: string
26+
smooth?: boolean
27+
showArea?: boolean
28+
color?: string
29+
areaColor?: string
30+
}
31+
32+
const props = withDefaults(defineProps<LineChartProps>(), {
33+
name: 'Data',
34+
smooth: true,
35+
showArea: true,
36+
color: '#0f766e',
37+
areaColor: 'rgba(15, 118, 110, 0.3)',
38+
})
39+
40+
const chartOption = computed<EChartsOption>(() => ({
41+
tooltip: {
42+
trigger: 'axis',
43+
backgroundColor: 'white',
44+
borderColor: '#e5e7eb',
45+
borderWidth: 1,
46+
textStyle: {
47+
color: '#374151',
48+
},
49+
axisPointer: {
50+
type: 'line',
51+
lineStyle: {
52+
color: props.color,
53+
opacity: 0.5,
54+
},
55+
},
56+
},
57+
grid: {
58+
left: '3%',
59+
right: '4%',
60+
bottom: '3%',
61+
top: '10%',
62+
containLabel: true,
63+
},
64+
xAxis: {
65+
type: 'category',
66+
data: props.labels,
67+
boundaryGap: false,
68+
axisLine: {
69+
lineStyle: {
70+
color: '#6b7280',
71+
},
72+
},
73+
axisLabel: {
74+
color: '#6b7280',
75+
fontSize: 12,
76+
},
77+
},
78+
yAxis: {
79+
type: 'value',
80+
axisLine: {
81+
lineStyle: {
82+
color: '#6b7280',
83+
},
84+
},
85+
axisLabel: {
86+
color: '#6b7280',
87+
fontSize: 12,
88+
},
89+
splitLine: {
90+
lineStyle: {
91+
color: '#f3f4f6',
92+
},
93+
},
94+
},
95+
series: [
96+
{
97+
name: props.name,
98+
type: 'line',
99+
smooth: props.smooth,
100+
data: props.data,
101+
lineStyle: {
102+
color: props.color,
103+
width: 2,
104+
},
105+
itemStyle: {
106+
color: props.color,
107+
},
108+
...(props.showArea && {
109+
areaStyle: {
110+
color: {
111+
type: 'linear',
112+
x: 0,
113+
y: 0,
114+
x2: 0,
115+
y2: 1,
116+
colorStops: [
117+
{
118+
offset: 0,
119+
color: props.areaColor,
120+
},
121+
{
122+
offset: 1,
123+
color: 'rgba(15, 118, 110, 0)',
124+
},
125+
],
126+
},
127+
},
128+
}),
129+
emphasis: {
130+
focus: 'series',
131+
},
132+
},
133+
],
134+
}))
135+
</script>
136+
137+
<template>
138+
<Chart
139+
:option="chartOption"
140+
variant="line"
141+
:size="size"
142+
:loading="loading"
143+
:autoresize="autoresize"
144+
:class="props.class"
145+
/>
146+
</template>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as Chart } from './Chart.vue'
2+
export { default as LineChart } from './LineChart.vue'

0 commit comments

Comments
 (0)