diff --git a/src/components/StockActivityChart.tsx b/src/components/StockActivityChart.tsx index 0896436..fa4a4f6 100644 --- a/src/components/StockActivityChart.tsx +++ b/src/components/StockActivityChart.tsx @@ -1,17 +1,18 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts'; - -const data = [ - { name: 'Jan', stockIn: 400, stockOut: 240 }, - { name: 'Feb', stockIn: 300, stockOut: 139 }, - { name: 'Mar', stockIn: 200, stockOut: 980 }, - { name: 'Apr', stockIn: 278, stockOut: 390 }, - { name: 'May', stockIn: 189, stockOut: 480 }, - { name: 'Jun', stockIn: 239, stockOut: 380 }, - { name: 'Jul', stockIn: 349, stockOut: 430 }, -]; +import { useDashboardData } from '@/hooks/useDashboardData'; const StockActivityChart = () => { + const { monthlyActivityData, loading, error } = useDashboardData(); + + if (loading) { + return Loading chart data...; + } + + if (error) { + return Error loading chart: {error}; + } + return ( @@ -19,7 +20,7 @@ const StockActivityChart = () => { - + diff --git a/src/components/StockChart.tsx b/src/components/StockChart.tsx index 4d92d25..c313af8 100644 --- a/src/components/StockChart.tsx +++ b/src/components/StockChart.tsx @@ -1,17 +1,18 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts'; - -const data = [ - { name: 'Jan', stockIn: 4000, stockOut: 2400 }, - { name: 'Feb', stockIn: 3000, stockOut: 1398 }, - { name: 'Mar', stockIn: 2000, stockOut: 9800 }, - { name: 'Apr', stockIn: 2780, stockOut: 3908 }, - { name: 'May', stockIn: 1890, stockOut: 4800 }, - { name: 'Jun', stockIn: 2390, stockOut: 3800 }, - { name: 'Jul', stockIn: 3490, stockOut: 4300 }, -]; +import { useDashboardData } from '@/hooks/useDashboardData'; const StockChart = () => { + const { monthlyActivityData, loading, error } = useDashboardData(); + + if (loading) { + return Loading chart data...; + } + + if (error) { + return Error loading chart: {error}; + } + return ( @@ -19,7 +20,7 @@ const StockChart = () => { - + diff --git a/src/hooks/useDashboardData.ts b/src/hooks/useDashboardData.ts index 4bc9088..ac031f0 100644 --- a/src/hooks/useDashboardData.ts +++ b/src/hooks/useDashboardData.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from "react"; import pb from "@/lib/pocketbase"; -import { subDays } from "date-fns"; +import { subDays, format, startOfMonth, eachMonthOfInterval } from "date-fns"; interface DashboardStats { totalStockValue: string; @@ -9,6 +9,12 @@ interface DashboardStats { lowStockAlerts: string; } +interface MonthlyActivity { + name: string; // Month name, e.g., 'Jan' + stockIn: number; + stockOut: number; +} + export function useDashboardData() { const [stats, setStats] = useState({ totalStockValue: "R0.00", @@ -16,6 +22,7 @@ export function useDashboardData() { stockOutLast30Days: "0", lowStockAlerts: "0", }); + const [monthlyActivityData, setMonthlyActivityData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -42,12 +49,12 @@ export function useDashboardData() { // Fetch book out records for the last 30 days const thirtyDaysAgo = subDays(new Date(), 30).toISOString(); - const bookOutRecords = await pb.collection('book_out_records').getFullList({ + const bookOutRecordsLast30Days = await pb.collection('book_out_records').getFullList({ filter: `date_booked_out >= "${thirtyDaysAgo}"`, }); let calculatedStockOutLast30Days = 0; - bookOutRecords.forEach((record: any) => { + bookOutRecordsLast30Days.forEach((record: any) => { calculatedStockOutLast30Days += record.quantity; }); @@ -60,6 +67,63 @@ export function useDashboardData() { stockOutLast30Days: calculatedStockOutLast30Days.toString(), lowStockAlerts: calculatedLowStockAlerts.toString(), }); + + // --- Monthly Activity Data for Charts --- + const now = new Date(); + const twelveMonthsAgo = subDays(now, 365); // Roughly 12 months ago + const monthsInterval = eachMonthOfInterval({ + start: startOfMonth(twelveMonthsAgo), + end: startOfMonth(now), + }); + + const monthlyDataMap = new Map(); + + monthsInterval.forEach(month => { + const monthKey = format(month, 'MMM'); // e.g., 'Jan', 'Feb' + monthlyDataMap.set(monthKey, { stockIn: 0, stockOut: 0 }); + }); + + // Process stock items for 'stockIn' (based on creation date) + stockRecords.forEach((item: any) => { + const createdDate = new Date(item.created); + if (createdDate >= twelveMonthsAgo) { + const monthKey = format(createdDate, 'MMM'); + if (monthlyDataMap.has(monthKey)) { + const current = monthlyDataMap.get(monthKey)!; + current.stockIn += item.quantity; + monthlyDataMap.set(monthKey, current); + } + } + }); + + // Process all book out records for 'stockOut' + const allBookOutRecords = await pb.collection('book_out_records').getFullList({ + sort: '-created', + }); + + allBookOutRecords.forEach((record: any) => { + const bookedOutDate = new Date(record.date_booked_out); + if (bookedOutDate >= twelveMonthsAgo) { + const monthKey = format(bookedOutDate, 'MMM'); + if (monthlyDataMap.has(monthKey)) { + const current = monthlyDataMap.get(monthKey)!; + current.stockOut += record.quantity; + monthlyDataMap.set(monthKey, current); + } + } + }); + + // Convert map to array, maintaining chronological order + const sortedMonthlyData: MonthlyActivity[] = monthsInterval.map(month => { + const monthKey = format(month, 'MMM'); + return { + name: monthKey, + ...monthlyDataMap.get(monthKey), + }; + }); + + setMonthlyActivityData(sortedMonthlyData); + } catch (err) { console.error("Failed to fetch dashboard data:", err); setError("Failed to load dashboard data."); @@ -69,6 +133,7 @@ export function useDashboardData() { stockOutLast30Days: "0", lowStockAlerts: "0", }); + setMonthlyActivityData([]); } finally { setLoading(false); } @@ -78,5 +143,5 @@ export function useDashboardData() { fetchDashboardStats(); }, [fetchDashboardStats]); - return { stats, loading, error, refresh: fetchDashboardStats }; + return { stats, monthlyActivityData, loading, error, refresh: fetchDashboardStats }; } \ No newline at end of file