feat: add responsive behavior to charts and improve layout in Analysis component
This commit is contained in:
parent
f82b56d540
commit
ed2cb2e53d
@ -14,7 +14,7 @@ import {
|
||||
VisTooltip,
|
||||
VisXYContainer,
|
||||
} from '@unovis/vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||
import StatCard from '@/components/card/StatCard.vue';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
@ -367,6 +367,21 @@ const peakHour = computed(() => {
|
||||
);
|
||||
});
|
||||
|
||||
const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1024);
|
||||
|
||||
onMounted(() => {
|
||||
const onResize = () => { windowWidth.value = window.innerWidth; };
|
||||
window.addEventListener('resize', onResize);
|
||||
onBeforeUnmount(() => window.removeEventListener('resize', onResize));
|
||||
});
|
||||
|
||||
const busyHourTickValues = computed(() => {
|
||||
const all = props.busyHours.map((_, i) => i);
|
||||
if (windowWidth.value < 640) return all.filter((_, i) => i % 4 === 0);
|
||||
if (windowWidth.value < 1024) return all.filter((_, i) => i % 2 === 0);
|
||||
return all;
|
||||
});
|
||||
|
||||
// Top 5 Chart configs
|
||||
type SupplierData = { name: string; amount: number };
|
||||
type CustomerData = { name: string; amount: number };
|
||||
@ -710,7 +725,7 @@ watch([startDate, endDate], () => {
|
||||
<div class="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
|
||||
<CardTitle>Pendapatan</CardTitle>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex flex-col sm:flex-row">
|
||||
<div v-for="chart in visibleRevenueCharts" :key="chart"
|
||||
class="flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-left even:border-l sm:border-t-0 sm:border-l sm:px-8 sm:py-6">
|
||||
<span class="text-xs text-muted-foreground">
|
||||
@ -765,7 +780,7 @@ watch([startDate, endDate], () => {
|
||||
<div class="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
|
||||
<CardTitle>Pengeluaran</CardTitle>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex flex-col sm:flex-row">
|
||||
<div v-for="chart in visibleExpenseCharts" :key="chart"
|
||||
class="flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-left even:border-l sm:border-t-0 sm:border-l sm:px-8 sm:py-6">
|
||||
<span class="text-xs text-muted-foreground">
|
||||
@ -843,7 +858,7 @@ watch([startDate, endDate], () => {
|
||||
:color="busyHoursChartConfig.orders.color" :bar-padding="0.1" :rounded-corners="4" />
|
||||
<VisAxis type="x" :x="(_d: BusyHourData, i: number) => i" :tick-line="false"
|
||||
:domain-line="false" :grid-line="false" :tick-format="(d: number) => busyHours[d]?.hour ?? ''
|
||||
" :tick-values="busyHours.map((_, i) => i)" />
|
||||
" :tick-values="busyHourTickValues" />
|
||||
<VisAxis type="y" :num-ticks="4" :tick-line="false" :domain-line="false" :tick-format="(d: number) => Math.round(d).toString()
|
||||
" />
|
||||
<VisTooltip :triggers="{ [barSelector]: busyHoursTooltip }" class-name="custom-tooltip" />
|
||||
@ -906,7 +921,7 @@ watch([startDate, endDate], () => {
|
||||
</div>
|
||||
|
||||
<!-- Top 5 Charts -->
|
||||
<div class="grid gap-4 md:grid-cols-3">
|
||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<Card v-if="can('analysis.top_suppliers')">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">Top 5 Supplier</CardTitle>
|
||||
@ -914,7 +929,7 @@ watch([startDate, endDate], () => {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ChartContainer v-if="supplierBarData.length > 0" :config="supplierChartConfig"
|
||||
class="min-h-[250px] w-full">
|
||||
class="aspect-auto h-[250px] w-full">
|
||||
<VisXYContainer :data="supplierBarData" :y-domain="[0, undefined]">
|
||||
<VisGroupedBar :x="(_d: SupplierData, i: number) => i"
|
||||
:y="(d: SupplierData) => d.amount" :color="supplierChartConfig.amount.color"
|
||||
@ -945,7 +960,7 @@ watch([startDate, endDate], () => {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ChartContainer v-if="customerBarData.length > 0" :config="customerChartConfig"
|
||||
class="min-h-[250px] w-full">
|
||||
class="aspect-auto h-[250px] w-full">
|
||||
<VisXYContainer :data="customerBarData" :y-domain="[0, undefined]">
|
||||
<VisGroupedBar :x="(_d: CustomerData, i: number) => i"
|
||||
:y="(d: CustomerData) => d.amount" :color="customerChartConfig.amount.color"
|
||||
@ -976,7 +991,7 @@ watch([startDate, endDate], () => {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ChartContainer v-if="productBarData.length > 0" :config="productChartConfig"
|
||||
class="min-h-[250px] w-full">
|
||||
class="aspect-auto h-[250px] w-full">
|
||||
<VisXYContainer :data="productBarData" :y-domain="[0, undefined]">
|
||||
<VisGroupedBar :x="(_d: ProductData, i: number) => i" :y="(d: ProductData) => d.qty"
|
||||
:color="productChartConfig.qty.color" :rounded-corners="4" bar-padding="0.1" />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user