[dyad] wrote 3 file(s)

This commit is contained in:
[dyad] 2025-09-10 13:22:04 +02:00
parent 06cb8c1a6b
commit bdbcf2d811
3 changed files with 93 additions and 26 deletions

View file

@ -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 <Card className="col-span-1"><CardContent className="h-80 flex items-center justify-center text-gray-500">Loading chart data...</CardContent></Card>;
}
if (error) {
return <Card className="col-span-1"><CardContent className="h-80 flex items-center justify-center text-red-500">Error loading chart: {error}</CardContent></Card>;
}
return (
<Card className="col-span-1">
<CardHeader>
@ -19,7 +20,7 @@ const StockActivityChart = () => {
</CardHeader>
<CardContent className="h-80">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={data}>
<BarChart data={monthlyActivityData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />

View file

@ -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 <Card className="col-span-1 lg:col-span-2"><CardContent className="h-80 flex items-center justify-center text-gray-500">Loading chart data...</CardContent></Card>;
}
if (error) {
return <Card className="col-span-1 lg:col-span-2"><CardContent className="h-80 flex items-center justify-center text-red-500">Error loading chart: {error}</CardContent></Card>;
}
return (
<Card className="col-span-1 lg:col-span-2">
<CardHeader>
@ -19,7 +20,7 @@ const StockChart = () => {
</CardHeader>
<CardContent className="h-80">
<ResponsiveContainer width="100%" height="100%">
<LineChart data={data}>
<LineChart data={monthlyActivityData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />

View file

@ -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<DashboardStats>({
totalStockValue: "R0.00",
@ -16,6 +22,7 @@ export function useDashboardData() {
stockOutLast30Days: "0",
lowStockAlerts: "0",
});
const [monthlyActivityData, setMonthlyActivityData] = useState<MonthlyActivity[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(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<string, { stockIn: number; stockOut: number }>();
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 };
}