diff --git a/src/pages/admin/DashboardHome.tsx b/src/pages/admin/DashboardHome.tsx index 1353ae3..d2c8869 100644 --- a/src/pages/admin/DashboardHome.tsx +++ b/src/pages/admin/DashboardHome.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useMemo } from "react"; import { - DollarSign, + PhilippinePeso, ShoppingBag, CreditCard, TrendingUp, @@ -21,11 +21,10 @@ import { ResponsiveContainer, BarChart, Bar, - Legend, PieChart, Pie, Cell, - LabelList, + Legend, } from "recharts"; import { getSales, type Sale } from "../../services/poss/sales"; import { getProducts, type Product } from "../../services/ims/product"; @@ -44,18 +43,29 @@ const DashboardHome = () => { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); - // 1. Fetch Data + // 1. Fetch Data Safely useEffect(() => { const fetchData = async () => { try { - const [salesData, productsData] = await Promise.all([ - getSales(), - getProducts(), - ]); + // Fetch independently so one failure doesn't break the other + const salesData = await getSales().catch((err) => { + console.error("Sales fetch failed:", err); + return []; + }); + + const productsData = await getProducts().catch((err) => { + console.error("Products fetch failed:", err); + return []; + }); + + console.log( + `Loaded ${salesData.length} sales and ${productsData.length} products.` + ); + setSales(salesData); setProducts(productsData); } catch (error) { - console.error("Failed to load dashboard data"); + console.error("Unexpected error loading dashboard:", error); } finally { setLoading(false); } @@ -65,17 +75,18 @@ const DashboardHome = () => { // 2. Compute "Today's" Data const todayStats = useMemo(() => { - const now = new Date(); - const startOfDay = new Date( - now.getFullYear(), - now.getMonth(), - now.getDate() - ); + // Helper to compare dates in PH Timezone + const getPHDateString = (dateInput: string | Date) => { + const date = new Date(dateInput); + return date.toLocaleDateString("en-US", { timeZone: "Asia/Manila" }); + }; - // Filter Sales for Today + const todayStr = getPHDateString(new Date()); + + // Filter Sales for Today using string comparison (Robust against time offsets) const todaysSales = sales.filter((s) => { - const saleDate = new Date(s.sale_date); - return saleDate >= startOfDay; + if (!s.sale_date) return false; + return getPHDateString(s.sale_date) === todayStr; }); const completedSales = todaysSales.filter((s) => s.status === "completed"); @@ -84,12 +95,14 @@ const DashboardHome = () => { // A. Summary Metrics const totalSalesAmount = completedSales.reduce( - (sum, s) => sum + s.total_amount, + (sum, s) => sum + (s.total_amount || 0), 0 ); const totalTransactions = completedSales.length; + // Safety check for items array const totalItemsSold = completedSales.reduce( - (sum, s) => sum + s.items.reduce((is, i) => is + i.quantity, 0), + (sum, s) => + sum + (s.items || []).reduce((is, i) => is + (i.quantity || 0), 0), 0 ); const averageOrderValue = @@ -103,7 +116,13 @@ const DashboardHome = () => { })); completedSales.forEach((s) => { - const hour = new Date(s.sale_date).getHours(); + // Get hour in PH time + const phTime = new Date( + new Date(s.sale_date).toLocaleString("en-US", { + timeZone: "Asia/Manila", + }) + ); + const hour = phTime.getHours(); if (hours[hour]) hours[hour].sales += s.total_amount; }); @@ -111,12 +130,11 @@ const DashboardHome = () => { const productMap = new Map(); const categoryMap = new Map(); - // Helper: Map Product Name to Category using Product List const getCategory = (name: string) => products.find((p) => p.name === name)?.category || "Uncategorized"; completedSales.forEach((s) => { - s.items.forEach((item) => { + (s.items || []).forEach((item) => { // Product Level const existingProd = productMap.get(item.product_name) || { qty: 0, @@ -149,7 +167,8 @@ const DashboardHome = () => { // D. Payment Methods const paymentMap = new Map(); completedSales.forEach((s) => { - paymentMap.set(s.payment_type, (paymentMap.get(s.payment_type) || 0) + 1); + const type = s.payment_type || "Unknown"; + paymentMap.set(type, (paymentMap.get(type) || 0) + 1); }); const paymentMethods = Array.from(paymentMap.entries()).map( ([name, value]) => ({ name, value }) @@ -177,7 +196,7 @@ const DashboardHome = () => { (a, b) => new Date(b.sale_date).getTime() - new Date(a.sale_date).getTime() ) - .slice(0, 20); // Last 20 + .slice(0, 20); return { totalSalesAmount, @@ -193,16 +212,15 @@ const DashboardHome = () => { }; }, [sales, products]); - // 3. Compute Inventory Stats (Real-time based on fetched products) + // 3. Compute Inventory Stats const inventoryStats = useMemo(() => { const lowStock = products.filter((p) => p.quantity <= p.minQuantity); const totalInventoryValue = products.reduce( (sum, p) => sum + p.price * p.quantity, 0 ); - const totalSKUs = products.length; - return { lowStock, totalInventoryValue, totalSKUs }; + return { lowStock, totalInventoryValue }; }, [products]); if (loading) @@ -220,7 +238,10 @@ const DashboardHome = () => { Today's Dashboard

- Real-time overview for {new Date().toLocaleDateString()} + Real-time overview for{" "} + {new Date().toLocaleDateString("en-US", { + timeZone: "Asia/Manila", + })}

@@ -246,7 +267,7 @@ const DashboardHome = () => {
- +
@@ -390,7 +411,7 @@ const DashboardHome = () => { label={({ name, percent }) => // @ts-ignore `${(percent * 100).toFixed(0)}%` - } // Show % on chart + } > {/* @ts-ignore */} {todayStats.paymentMethods.map((entry, index) => ( @@ -401,15 +422,7 @@ const DashboardHome = () => { ))} - ( - - {value}: {entry.payload.value} - - )} - /> +
@@ -428,7 +441,7 @@ const DashboardHome = () => { { fill="#8b5cf6" radius={[0, 4, 4, 0]} barSize={20} - > - `₱${val.toLocaleString()}`} - style={{ fill: "#64748b", fontSize: 12, fontWeight: 500 }} - /> - + />