From 7a8bd59bb47fe22369ac156aecde89d6bd4500d4 Mon Sep 17 00:00:00 2001 From: efrilm Date: Thu, 14 Aug 2025 02:07:55 +0700 Subject: [PATCH] feat: add categories at daily report --- .../dashboards/daily-report/page.tsx | 62 +++++++- src/services/queries/analytics.ts | 39 ++++- src/types/services/analytic.ts | 139 ++++++++++-------- 3 files changed, 173 insertions(+), 67 deletions(-) diff --git a/src/app/[lang]/(dashboard)/(private)/dashboards/daily-report/page.tsx b/src/app/[lang]/(dashboard)/(private)/dashboards/daily-report/page.tsx index da88704..ef07537 100644 --- a/src/app/[lang]/(dashboard)/(private)/dashboards/daily-report/page.tsx +++ b/src/app/[lang]/(dashboard)/(private)/dashboards/daily-report/page.tsx @@ -4,7 +4,8 @@ import { useProductSalesAnalytics, useProfitLossAnalytics, useSalesAnalytics, - usePaymentAnalytics + usePaymentAnalytics, + useCategoryAnalytics } from '@/services/queries/analytics' import { useOutletById } from '@/services/queries/outlets' import { formatCurrency, formatDate, formatDateDDMMYYYY, formatDatetime } from '@/utils/transform' @@ -45,6 +46,7 @@ const DailyPOSReport = () => { const { data: profitLoss } = useProfitLossAnalytics(dateParams) const { data: products } = useProductSalesAnalytics(dateParams) const { data: paymentAnalytics } = usePaymentAnalytics(dateParams) + const { data: category } = useCategoryAnalytics(dateParams) const productSummary = { totalQuantitySold: products?.data?.reduce((sum, item) => sum + (item?.quantity_sold || 0), 0) || 0, @@ -60,6 +62,13 @@ const DailyPOSReport = () => { totalQuantity: profitLoss?.product_data?.reduce((sum, item) => sum + (item?.quantity_sold || 0), 0) || 0 } + const categorySummary = { + totalRevenue: category?.data?.reduce((sum, item) => sum + (item?.total_revenue || 0), 0) || 0, + orderCount: category?.data?.reduce((sum, item) => sum + (item?.order_count || 0), 0) || 0, + productCount: category?.data?.reduce((sum, item) => sum + (item?.product_count || 0), 0) || 0, + totalQuantity: category?.data?.reduce((sum, item) => sum + (item?.total_quantity || 0), 0) || 0 + } + useEffect(() => { setNow(new Date()) }, []) @@ -199,13 +208,13 @@ const DailyPOSReport = () => { {/* Performance Summary */}

- 1. Ringkasan Kinerja + 1. Ringkasan

- TOTAL PENJUALAN (termasuk rasik) + Total Penjualan (termasuk rasik) {formatCurrency(profitLoss?.summary.total_revenue ?? 0)} @@ -359,7 +368,50 @@ const DailyPOSReport = () => { {formatCurrency(paymentAnalytics?.summary.total_amount ?? 0)} - 100.0% + + + + +
+
+ + {/* Category Summary */} +
+

+ 2. Ringkasan Kategori +

+ +
+ + + + + + + + + + + + {category?.data?.map((c, index) => ( + + + + + + + + )) || []} + + + + + + + +
NamaTotal ProdukQtyJumlah OrderPendapatan
{c.category_name}{c.product_count}{c.total_quantity}{c.order_count} + {formatCurrency(c.total_revenue)} +
TOTAL{categorySummary?.productCount ?? 0}{categorySummary?.totalQuantity ?? 0}{categorySummary?.orderCount ?? 0}{formatCurrency(categorySummary?.totalRevenue ?? 0)}
@@ -369,7 +421,7 @@ const DailyPOSReport = () => { {/* Transaction Summary */}

- 3. Ringkasan Transaksi + 4. Ringkasan Item

diff --git a/src/services/queries/analytics.ts b/src/services/queries/analytics.ts index 27e30bf..f169c28 100644 --- a/src/services/queries/analytics.ts +++ b/src/services/queries/analytics.ts @@ -1,5 +1,12 @@ import { useQuery } from '@tanstack/react-query' -import { DashboardReport, PaymentReport, ProductSalesReport, ProfitLossReport, SalesReport } from '../../types/services/analytic' +import { + CategoryReport, + DashboardReport, + PaymentReport, + ProductSalesReport, + ProfitLossReport, + SalesReport +} from '../../types/services/analytic' import { api } from '../api' import { formatDateDDMMYYYY } from '../../utils/transform' @@ -157,3 +164,33 @@ export function useProfitLossAnalytics(params: AnalyticQueryParams = {}) { } }) } + +export function useCategoryAnalytics(params: AnalyticQueryParams = {}) { + const today = new Date() + const monthAgo = new Date() + monthAgo.setDate(today.getDate() - 30) + + const defaultDateTo = formatDateDDMMYYYY(today) + const defaultDateFrom = formatDateDDMMYYYY(monthAgo) + + const { date_from = defaultDateFrom, date_to = defaultDateTo, ...filters } = params + + return useQuery({ + queryKey: ['analytics-categories', { date_from, date_to, ...filters }], + queryFn: async () => { + const queryParams = new URLSearchParams() + + queryParams.append('date_from', date_from) + queryParams.append('date_to', date_to) + + Object.entries(filters).forEach(([key, value]) => { + if (value !== undefined && value !== null && value !== '') { + queryParams.append(key, value.toString()) + } + }) + + const res = await api.get(`/analytics/categories?${queryParams.toString()}`) + return res.data.data + } + }) +} diff --git a/src/types/services/analytic.ts b/src/types/services/analytic.ts index 6f057ce..a978ccf 100644 --- a/src/types/services/analytic.ts +++ b/src/types/services/analytic.ts @@ -1,31 +1,31 @@ export interface SalesSummary { - total_sales: number; - total_orders: number; - total_items: number; - average_order_value: number; - total_tax: number; - total_discount: number; - net_sales: number; + total_sales: number + total_orders: number + total_items: number + average_order_value: number + total_tax: number + total_discount: number + net_sales: number } export interface SalesDataItem { - date: string; // ISO string, e.g., "2025-08-03T00:00:00Z" - sales: number; - orders: number; - items: number; - tax: number; - discount: number; - net_sales: number; + date: string // ISO string, e.g., "2025-08-03T00:00:00Z" + sales: number + orders: number + items: number + tax: number + discount: number + net_sales: number } export interface SalesReport { - organization_id: string; - outlet_id: string; - date_from: string; // ISO string with timezone, e.g., "2025-08-01T00:00:00+07:00" - date_to: string; // ISO string with timezone - group_by: string; // e.g., "day", "month", etc. - summary: SalesSummary; - data: SalesDataItem[]; + organization_id: string + outlet_id: string + date_from: string // ISO string with timezone, e.g., "2025-08-01T00:00:00+07:00" + date_to: string // ISO string with timezone + group_by: string // e.g., "day", "month", etc. + summary: SalesSummary + data: SalesDataItem[] } export interface ProductData { @@ -105,53 +105,70 @@ export type DashboardReport = { } export interface ProfitLossReport { - organization_id: string; - date_from: string; // ISO date string with timezone - date_to: string; // ISO date string with timezone - group_by: string; - summary: Summary; - data: DailyData[]; - product_data: ProductDataReport[]; + organization_id: string + date_from: string // ISO date string with timezone + date_to: string // ISO date string with timezone + group_by: string + summary: Summary + data: DailyData[] + product_data: ProductDataReport[] } export interface Summary { - total_revenue: number; - total_cost: number; - gross_profit: number; - gross_profit_margin: number; - total_tax: number; - total_discount: number; - net_profit: number; - net_profit_margin: number; - total_orders: number; - average_profit: number; - profitability_ratio: number; + total_revenue: number + total_cost: number + gross_profit: number + gross_profit_margin: number + total_tax: number + total_discount: number + net_profit: number + net_profit_margin: number + total_orders: number + average_profit: number + profitability_ratio: number } export interface DailyData { - date: string; // ISO date string with timezone - revenue: number; - cost: number; - gross_profit: number; - gross_profit_margin: number; - tax: number; - discount: number; - net_profit: number; - net_profit_margin: number; - orders: number; + date: string // ISO date string with timezone + revenue: number + cost: number + gross_profit: number + gross_profit_margin: number + tax: number + discount: number + net_profit: number + net_profit_margin: number + orders: number } export interface ProductDataReport { - product_id: string; - product_name: string; - category_id: string; - category_name: string; - quantity_sold: number; - revenue: number; - cost: number; - gross_profit: number; - gross_profit_margin: number; - average_price: number; - average_cost: number; - profit_per_unit: number; + product_id: string + product_name: string + category_id: string + category_name: string + quantity_sold: number + revenue: number + cost: number + gross_profit: number + gross_profit_margin: number + average_price: number + average_cost: number + profit_per_unit: number +} + +export interface CategoryReport { + organization_id: string + outlet_id: string + date_from: string + date_to: string + data: CategoryDataReport[] +} + +export interface CategoryDataReport { + category_id: string + category_name: string + total_revenue: number + total_quantity: number + product_count: number + order_count: number }