feat: add quick filter options for date range selection in Analysis.vue to enhance user experience
This commit is contained in:
parent
11232293a9
commit
cecbf92310
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Head, router } from '@inertiajs/vue3';
|
import { Head, router } from '@inertiajs/vue3';
|
||||||
import { Banknote, DollarSign, Package, Percent, ShoppingCart, TrendingDown, TrendingUp, UserCheck } from '@lucide/vue';
|
import { Banknote, Package, Percent, ShoppingCart, TrendingDown, TrendingUp, UserCheck } from '@lucide/vue';
|
||||||
import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue';
|
import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import StatCard from '@/components/card/StatCard.vue';
|
import StatCard from '@/components/card/StatCard.vue';
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
import type { ChartConfig } from '@/components/ui/chart';
|
import type { ChartConfig } from '@/components/ui/chart';
|
||||||
import { ChartContainer } from '@/components/ui/chart';
|
import { ChartContainer } from '@/components/ui/chart';
|
||||||
import { DatePicker } from '@/components/ui/date-picker';
|
import { DatePicker } from '@/components/ui/date-picker';
|
||||||
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||||
import { formatRupiah } from '@/lib/rupiah';
|
import { formatRupiah } from '@/lib/rupiah';
|
||||||
import admin from '@/routes/admin';
|
import admin from '@/routes/admin';
|
||||||
@ -116,9 +117,45 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const startDate = ref(props.filters.start_date ?? '');
|
const startDate = ref(props.filters.start_date ?? '');
|
||||||
const endDate = ref(props.filters.end_date ?? '');
|
const endDate = ref(props.filters.end_date ?? '');
|
||||||
|
const selectedPreset = ref<string>('');
|
||||||
|
|
||||||
const hasActiveFilters = computed(() => !!startDate.value || !!endDate.value);
|
const hasActiveFilters = computed(() => !!startDate.value || !!endDate.value);
|
||||||
|
|
||||||
|
function formatDate(date: Date): string {
|
||||||
|
return date.toISOString().split('T')[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPresetChange(value: any) {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedPreset.value = value;
|
||||||
|
const now = new Date();
|
||||||
|
let start: Date;
|
||||||
|
|
||||||
|
switch (value) {
|
||||||
|
case 'today':
|
||||||
|
start = new Date(now);
|
||||||
|
break;
|
||||||
|
case 'week':
|
||||||
|
start = new Date(now);
|
||||||
|
start.setDate(now.getDate() - now.getDay() + 1);
|
||||||
|
break;
|
||||||
|
case 'month':
|
||||||
|
start = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
|
break;
|
||||||
|
case 'year':
|
||||||
|
start = new Date(now.getFullYear(), 0, 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
startDate.value = formatDate(start);
|
||||||
|
endDate.value = formatDate(now);
|
||||||
|
}
|
||||||
|
|
||||||
// Revenue Chart
|
// Revenue Chart
|
||||||
type MonthlyRevenueData = { month: string; total: number; net: number; potongan: number; ongkir: number };
|
type MonthlyRevenueData = { month: string; total: number; net: number; potongan: number; ongkir: number };
|
||||||
|
|
||||||
@ -263,6 +300,7 @@ function applyFilters() {
|
|||||||
function clearFilters() {
|
function clearFilters() {
|
||||||
startDate.value = '';
|
startDate.value = '';
|
||||||
endDate.value = '';
|
endDate.value = '';
|
||||||
|
selectedPreset.value = '';
|
||||||
applyFilters();
|
applyFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,17 +315,25 @@ watch([startDate, endDate], () => {
|
|||||||
|
|
||||||
<AdminLayout>
|
<AdminLayout>
|
||||||
<div class="flex flex-col gap-6">
|
<div class="flex flex-col gap-6">
|
||||||
<!-- Header & Filter -->
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div
|
|
||||||
class="flex flex-col gap-4 rounded-lg border bg-card p-6 shadow-xs md:flex-row md:items-center md:justify-between">
|
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<h2 class="text-2xl font-bold tracking-tight">Analisa</h2>
|
<h2 class="text-2xl font-bold tracking-tight">Analisa</h2>
|
||||||
<p class="text-sm text-muted-foreground">
|
|
||||||
Halaman analisa data dan performa toko.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Date Filters -->
|
|
||||||
<div class="flex flex-wrap items-center gap-3">
|
<div class="flex flex-wrap items-center gap-3">
|
||||||
|
<Select v-model="selectedPreset" @update:model-value="onPresetChange">
|
||||||
|
<SelectTrigger class="w-[140px] h-9">
|
||||||
|
<SelectValue placeholder="Filter Cepat" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectItem value="today">Hari Ini</SelectItem>
|
||||||
|
<SelectItem value="week">Minggu Ini</SelectItem>
|
||||||
|
<SelectItem value="month">Bulan Ini</SelectItem>
|
||||||
|
<SelectItem value="year">Tahun Ini</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="text-xs font-semibold tracking-wider text-muted-foreground uppercase">Mulai:</span>
|
<span class="text-xs font-semibold tracking-wider text-muted-foreground uppercase">Mulai:</span>
|
||||||
<DatePicker v-model="startDate" class="w-[170px]" placeholder="Pilih tanggal" />
|
<DatePicker v-model="startDate" class="w-[170px]" placeholder="Pilih tanggal" />
|
||||||
@ -492,7 +538,8 @@ watch([startDate, endDate], () => {
|
|||||||
<!-- Profit Metrics Cards -->
|
<!-- Profit Metrics Cards -->
|
||||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||||
<StatCard title="Total Order" :icon="ShoppingCart" main-label="Pesanan Selesai"
|
<StatCard title="Total Order" :icon="ShoppingCart" main-label="Pesanan Selesai"
|
||||||
:main-value="profitMetrics.total_orders.toLocaleString('id-ID')" :sub-label="'AOV: Rp' + formatRupiah(profitMetrics.aov)" :items="[
|
:main-value="profitMetrics.total_orders.toLocaleString('id-ID')"
|
||||||
|
:sub-label="'AOV: Rp' + formatRupiah(profitMetrics.aov)" :items="[
|
||||||
{
|
{
|
||||||
label: 'Produk Terjual',
|
label: 'Produk Terjual',
|
||||||
value: profitMetrics.total_products_sold.toLocaleString('id-ID'),
|
value: profitMetrics.total_products_sold.toLocaleString('id-ID'),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user