feat: add new chart components for opportunity, quotation status, receipt, and sales

This commit is contained in:
puriphatt 2025-03-05 14:11:16 +07:00 committed by Methapon2001
parent 5ec7012119
commit f168b43b1a
4 changed files with 371 additions and 0 deletions

View file

@ -0,0 +1,58 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import VueApexCharts from 'vue3-apexcharts';
const props = withDefaults(
defineProps<{
series: number[];
labels: string[];
}>(),
{
labels: () => ['series-1', 'series-2', 'series-3', 'series-4'],
series: () => [1, 1, 1, 1],
},
);
const chartOptions = computed(() => ({
labels: props.labels,
colors: [
'#1F253B',
'#1B285C',
'#031B7D',
'#0023AE',
'#0933DA',
'#365AE9',
'#6380F8',
'#7583BB',
],
chart: {
fontFamily: 'Noto Sans Thai',
type: 'donut',
},
dataLabels: {
style: {
fontSize: '10px',
color: 'red',
},
},
legend: {
show: false,
position: 'bottom',
},
}));
</script>
<template>
<div class="surface-1 rounded bordered q-pa-md">
{{ $t('dashboard.opportunity.title') }}
<div class="text-caption app-text-muted">
{{ $t('dashboard.opportunity.caption') }}
</div>
<VueApexCharts
type="donut"
height="200"
:options="chartOptions"
:series="series"
></VueApexCharts>
</div>
</template>

View file

@ -0,0 +1,107 @@
<script lang="ts" setup>
import { computed } from 'vue';
import VueApexCharts from 'vue3-apexcharts';
const props = withDefaults(
defineProps<{
series: { data: number[] }[];
labels: string[];
}>(),
{
series: () => [
{
data: [1, 2, 3, 4],
},
],
labels: () => ['1', '2', '3', '4'],
},
);
const chartOptions = computed(() => ({
chart: {
type: 'bar',
fontFamily: 'Noto Sans Thai',
},
plotOptions: {
bar: {
barHeight: '100%',
distributed: true,
horizontal: true,
borderRadius: 6,
borderRadiusApplication: 'end',
dataLabels: {
position: 'bottom',
},
},
},
colors: ['#f59f00', '#035aa1', '#0ca678', '#c92a2a'],
dataLabels: {
enabled: false,
textAnchor: 'start',
style: {
colors: ['#fff'],
},
formatter: function (
val: string,
opt: {
w: { globals: { labels: { [x: string]: string } } };
dataPointIndex: string | number;
},
) {
return opt.w.globals.labels[opt.dataPointIndex] + ': ' + val;
},
offsetX: 0,
dropShadow: {
enabled: true,
},
},
stroke: {
width: 1,
colors: ['#fff'],
},
xaxis: {
categories: props.labels,
},
yaxis: {
labels: {
show: false,
},
},
legend: {
show: false,
},
tooltip: {
theme: 'dark',
x: {
show: false,
},
y: {
title: {
formatter: function (
val: string,
opt: {
w: { globals: { labels: { [x: string]: string } } };
dataPointIndex: string | number;
},
) {
return opt.w.globals.labels[opt.dataPointIndex] + ':';
},
},
},
},
}));
</script>
<template>
<div class="surface-1 rounded bordered q-pa-md">
{{ $t('dashboard.quotation.title') }}
<div class="text-caption app-text-muted">
{{ $t('dashboard.quotation.caption') }}
</div>
<VueApexCharts
type="bar"
height="200"
:options="chartOptions"
:series="series"
></VueApexCharts>
</div>
</template>

View file

@ -0,0 +1,131 @@
<script lang="ts" setup>
import { Icon } from '@iconify/vue/dist/iconify.js';
import VueApexCharts from 'vue3-apexcharts';
import DataDisplay from 'src/components/08_request-list/DataDisplay.vue';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
const { locale } = useI18n({ useScope: 'global' });
withDefaults(
defineProps<{
series: { name: string; data: number[] }[];
summary: number[];
}>(),
{
series: () => [
{ name: 'series-1', data: [0, 0] },
{ name: 'series-2', data: [1, 1] },
{ name: 'series-3', data: [2, 2] },
{ name: 'series-4', data: [3, 3] },
],
summary: () => [0, 0, 0, 0],
},
);
const chartOptions = computed(() => {
const thaiMonths = [
'ม.ค.',
'ก.พ.',
'มี.ค.',
'เม.ย.',
'พ.ค.',
'มิ.ย.',
'ก.ค.',
'ส.ค.',
'ก.ย.',
'ต.ค.',
'พ.ย.',
'ธ.ค.',
];
return {
colors: ['#035aa1', '#ae3ec9', '#ffa94d', '#e64980'],
chart: {
fontFamily: 'Noto Sans Thai',
type: 'line',
zoom: {
enabled: false,
},
},
legend: {
position: 'right',
},
xaxis: {
categories:
locale.value === 'tha'
? thaiMonths
: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
],
},
};
});
const detail = [
{
label: 'total',
color: 'var(--brand-1)',
icon: 'hugeicons:wallet-03',
},
{
label: 'paid',
color: 'var(--purple-7)',
icon: 'material-symbols-light:credit-card-clock-outline-rounded',
},
{
label: 'pending',
color: 'var(--orange-4)',
icon: 'material-symbols-light:credit-card-outline',
},
{
label: 'cancel',
color: 'var(--pink-7)',
icon: 'hugeicons:wallet-remove-02',
},
];
</script>
<template>
<div class="surface-1 rounded bordered q-pa-md">
{{ $t('dashboard.receipt.title') }}
<div class="text-caption app-text-muted">
{{ $t('dashboard.receipt.caption') }}
</div>
<VueApexCharts
type="line"
height="150"
:options="chartOptions"
:series="series"
></VueApexCharts>
<div class="row items-center">
<span
class="col-md col-6 row no-wrap items-center"
v-for="(v, i) in detail"
:key="v.label"
>
<q-avatar
class="q-mr-sm"
size="md"
font-size="18px"
:style="`background-color: ${v.color}; color: var(--surface-1)`"
>
<Icon :icon="v.icon" />
</q-avatar>
<DataDisplay
:label="$t(`dashboard.receipt.${v.label}`)"
:value="summary[i].toString()"
/>
</span>
</div>
</div>
</template>

View file

@ -0,0 +1,75 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import VueApexCharts from 'vue3-apexcharts';
const { t } = useI18n();
const series = [
{
name: 'Net Profit',
data: [44, 55, 57, 56, 61, 58, 63, 60, 66],
},
{
name: 'Revenue',
data: [76, 85, 101, 98, 87, 105, 91, 114, 94],
},
{
name: 'Free Cash Flow',
data: [35, 41, 36, 26, 45, 48, 52, 53, 41],
},
];
const chartOptions = {
chart: {
type: 'bar',
fontFamily: 'Noto Sans Thai',
},
plotOptions: {
bar: {
horizontal: false,
columnWidth: '55%',
borderRadius: 2,
borderRadiusApplication: 'end',
},
},
dataLabels: {
enabled: false,
},
stroke: {
show: true,
width: 2,
colors: ['transparent'],
},
xaxis: {
categories: ['Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct'],
},
yaxis: {
title: {
text: '$ (thousands)',
},
},
fill: {
opacity: 1,
},
tooltip: {
y: {
formatter: function (val: string) {
return '$ ' + val + ' thousands';
},
},
},
};
</script>
<template>
<div class="surface-1 rounded bordered q-pa-md">
{{ $t('dashboard.sales.title') }}
<div class="text-caption app-text-muted">
{{ $t('dashboard.sales.caption') }}
</div>
<VueApexCharts
type="bar"
height="200"
:options="chartOptions"
:series="series"
></VueApexCharts>
</div>
</template>