calcuation fixes
This commit is contained in:
@@ -13,16 +13,28 @@ import LatestItemsList, { LatestItem } from "./components/LatestItemsList";
|
||||
import HistoryChart from "./components/HistoryChart";
|
||||
|
||||
import {
|
||||
fetchLatestExpenses,
|
||||
fetchLatestTransactions,
|
||||
fetchAggregatedExpenses,
|
||||
fetchAggregatedIncome,
|
||||
AggregatedDashboardData
|
||||
} from "./utils/dashboardLoader";
|
||||
|
||||
export default function Dashboard() {
|
||||
const [latest, setLatest] = React.useState<LatestItem[]>([]);
|
||||
const [aggregated, setAggregated] =
|
||||
React.useState<AggregatedDashboardData | null>(null);
|
||||
const [latest, setLatest] = React.useState<{
|
||||
expense: LatestItem[];
|
||||
income: LatestItem[];
|
||||
}>({
|
||||
expense: [],
|
||||
income: []
|
||||
});
|
||||
|
||||
const [aggregated, setAggregated] = React.useState<{
|
||||
expense: AggregatedDashboardData | null;
|
||||
income: AggregatedDashboardData | null;
|
||||
}>({
|
||||
expense: null,
|
||||
income: null
|
||||
});
|
||||
|
||||
const [mode, setMode] =
|
||||
React.useState<"expense" | "income">("expense");
|
||||
@@ -30,21 +42,33 @@ export default function Dashboard() {
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
|
||||
// -------- LOAD DATA --------
|
||||
// -------- LOAD ONCE --------
|
||||
React.useEffect(() => {
|
||||
async function loadData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const latestData = await fetchLatestExpenses();
|
||||
const [
|
||||
latestExpense,
|
||||
latestIncome,
|
||||
expenseData,
|
||||
incomeData
|
||||
] = await Promise.all([
|
||||
fetchLatestTransactions("expense"),
|
||||
fetchLatestTransactions("income"),
|
||||
fetchAggregatedExpenses(),
|
||||
fetchAggregatedIncome()
|
||||
]);
|
||||
|
||||
const aggData =
|
||||
mode === "expense"
|
||||
? await fetchAggregatedExpenses()
|
||||
: await fetchAggregatedIncome();
|
||||
setLatest({
|
||||
expense: latestExpense,
|
||||
income: latestIncome
|
||||
});
|
||||
|
||||
setLatest(latestData);
|
||||
setAggregated(aggData);
|
||||
setAggregated({
|
||||
expense: expenseData,
|
||||
income: incomeData
|
||||
});
|
||||
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
@@ -55,7 +79,10 @@ export default function Dashboard() {
|
||||
}
|
||||
|
||||
loadData();
|
||||
}, [mode]);
|
||||
}, []);
|
||||
|
||||
const currentData = aggregated[mode];
|
||||
const currentLatest = latest[mode];
|
||||
|
||||
// -------- UI STATES --------
|
||||
if (loading) {
|
||||
@@ -89,22 +116,22 @@ export default function Dashboard() {
|
||||
</Box>
|
||||
|
||||
<Grid container spacing={4} direction="row">
|
||||
{/* LEFT → 1/3 (4 cols) */}
|
||||
{/* LEFT → 1/3 */}
|
||||
<Grid size={4}>
|
||||
<LatestItemsList
|
||||
title="Recent Transactions"
|
||||
items={latest}
|
||||
title={`Recent ${mode === "expense" ? "Expenses" : "Income"}`}
|
||||
items={currentLatest}
|
||||
onViewAll={() => {}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{/* RIGHT → 2/3 (8 cols) */}
|
||||
{/* RIGHT → 2/3 */}
|
||||
<Grid size={8}>
|
||||
<HistoryChart
|
||||
header={`${mode === "expense" ? "Expense" : "Income"} Breakdown`}
|
||||
summary="Interactive chronological tracking"
|
||||
tabs={["Today", "Week", "Month", "Year"]}
|
||||
data={aggregated?.chartData || {}}
|
||||
tabs={["Week", "Month", "Year"]}
|
||||
data={currentData?.chartData || {}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -10,14 +10,22 @@ const DEFAULT_ICON = React.createElement(MonetizationOnIcon, {
|
||||
});
|
||||
|
||||
// ---------------- LATEST ----------------
|
||||
export async function fetchLatestExpenses(): Promise<LatestItem[]> {
|
||||
export async function fetchLatestTransactions(
|
||||
type: "expense" | "income"
|
||||
): Promise<LatestItem[]> {
|
||||
const res = await api.get('/expenses', {
|
||||
params: { limit: 10, sort: '-occurred_at' }
|
||||
params: { limit: 100, sort: '-occurred_at' }
|
||||
});
|
||||
|
||||
const items = res.data?.items || res.data || [];
|
||||
|
||||
return items.map((exp: any, index: number) => {
|
||||
const isValid = (amt: number) =>
|
||||
type === "expense" ? amt < 0 : amt > 0;
|
||||
|
||||
return items
|
||||
.filter((item: any) => isValid(Number(item.amount) || 0))
|
||||
.slice(0, 10)
|
||||
.map((exp: any, index: number) => {
|
||||
const time = new Date(
|
||||
exp.occurred_at || exp.created_at || Date.now()
|
||||
).getTime();
|
||||
@@ -29,10 +37,11 @@ export async function fetchLatestExpenses(): Promise<LatestItem[]> {
|
||||
return {
|
||||
id: exp.id || index,
|
||||
icon: DEFAULT_ICON,
|
||||
iconBgColor: "#e8f5e9",
|
||||
iconBgColor:
|
||||
type === "expense" ? "#ffebee" : "#e8f5e9",
|
||||
title: exp.payee?.name || exp.payee || "Unknown Payee",
|
||||
subtitle: exp.category?.name || exp.account?.name || "Transaction",
|
||||
amount: `Rs ${exp.amount || 0}`,
|
||||
amount: `Rs ${Math.abs(exp.amount || 0)}`,
|
||||
timeAgo: diffDays === 0 ? "Today" : `${diffDays} days ago`
|
||||
};
|
||||
});
|
||||
@@ -62,12 +71,6 @@ export async function fetchAggregatedData(
|
||||
|
||||
const normalize = (amt: number) => Math.abs(amt);
|
||||
|
||||
// ---------------- BUCKETS ----------------
|
||||
const todayBuckets: Record<string, number> = {
|
||||
"12am":0,"3am":0,"6am":0,"9am":0,
|
||||
"12pm":0,"3pm":0,"6pm":0,"9pm":0
|
||||
};
|
||||
|
||||
const weekBuckets: Record<string, number> = {
|
||||
"Mon":0,"Tue":0,"Wed":0,"Thu":0,
|
||||
"Fri":0,"Sat":0,"Sun":0
|
||||
@@ -134,25 +137,6 @@ export async function fetchAggregatedData(
|
||||
const payee = item.payee?.name || item.payee || "Unknown";
|
||||
payeeMap[payee] = (payeeMap[payee] || 0) + amt;
|
||||
|
||||
// ---- TODAY
|
||||
if (
|
||||
d.getDate() === now.getDate() &&
|
||||
d.getMonth() === now.getMonth() &&
|
||||
d.getFullYear() === now.getFullYear()
|
||||
) {
|
||||
const hr = d.getHours();
|
||||
let label = "12am";
|
||||
if (hr >= 3 && hr < 6) label = "3am";
|
||||
else if (hr >= 6 && hr < 9) label = "6am";
|
||||
else if (hr >= 9 && hr < 12) label = "9am";
|
||||
else if (hr >= 12 && hr < 15) label = "12pm";
|
||||
else if (hr >= 15 && hr < 18) label = "3pm";
|
||||
else if (hr >= 18 && hr < 21) label = "6pm";
|
||||
else if (hr >= 21) label = "9pm";
|
||||
|
||||
todayBuckets[label] += amt;
|
||||
}
|
||||
|
||||
// ---- WEEK
|
||||
if (d >= weekStart && d <= weekEnd) {
|
||||
const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()];
|
||||
@@ -192,7 +176,6 @@ export async function fetchAggregatedData(
|
||||
}));
|
||||
|
||||
const chartData = {
|
||||
today: toPoints(todayBuckets),
|
||||
week: toPoints(weekBuckets),
|
||||
month: toPoints(monthBuckets),
|
||||
year: toPoints(yearBuckets)
|
||||
|
||||
Reference in New Issue
Block a user