whisper-money/resources/js/hooks/use-dashboard-data.ts

150 lines
5.1 KiB
TypeScript

import { Account } from '@/types/account';
import { Category } from '@/types/category';
import { format, subDays, subMonths } from 'date-fns';
import { useEffect, useState } from 'react';
export interface DashboardData {
netWorth: {
current: number;
previous: number;
diff: number;
};
monthlySpending: {
current: number;
limit: null;
previous: number;
};
cashFlow: {
income: number;
expense: number;
previous: {
income: number;
expense: number;
};
};
netWorthHistory: Array<{ date: string; value: number }>;
accounts: Array<
Account & {
current_balance: number;
previous_balance: number;
history: Array<{ date: string; value: number }>;
}
>;
topCategories: Array<{
category: Category;
amount: number;
}>;
isLoading: boolean;
}
export function useDashboardData(): DashboardData {
const [data, setData] = useState<Omit<DashboardData, 'isLoading'>>({
netWorth: { current: 0, previous: 0, diff: 0 },
monthlySpending: { current: 0, limit: null, previous: 0 },
cashFlow: {
income: 0,
expense: 0,
previous: { income: 0, expense: 0 },
},
netWorthHistory: [],
accounts: [],
topCategories: [],
});
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
const now = new Date();
const to = format(now, 'yyyy-MM-dd');
// Last 12 months for evolution charts
const from12Months = format(subMonths(now, 12), 'yyyy-MM-dd');
const params12Months = new URLSearchParams({
from: from12Months,
to,
});
const query12Months = `?${params12Months.toString()}`;
// Last 30 days for top blocks and categories
const from30Days = format(subDays(now, 30), 'yyyy-MM-dd');
const params30Days = new URLSearchParams({
from: from30Days,
to,
});
const query30Days = `?${params30Days.toString()}`;
const [
netWorth,
monthlySpending,
cashFlow,
netWorthEvolution,
accountBalances,
topCategories,
] = await Promise.all([
fetch(`/api/dashboard/net-worth${query30Days}`).then((r) =>
r.json(),
),
fetch(`/api/dashboard/monthly-spending${query30Days}`).then(
(r) => r.json(),
),
fetch(`/api/dashboard/cash-flow${query30Days}`).then((r) =>
r.json(),
),
fetch(
`/api/dashboard/net-worth-evolution${query12Months}`,
).then((r) => r.json()),
fetch(
`/api/dashboard/account-balances${query12Months}`,
).then((r) => r.json()),
fetch(`/api/dashboard/top-categories${query30Days}`).then(
(r) => r.json(),
),
]);
setData({
netWorth: {
current: netWorth.current,
previous: netWorth.previous,
diff: netWorth.current - netWorth.previous,
},
monthlySpending: {
current: monthlySpending.current,
previous: monthlySpending.previous,
limit: null,
},
cashFlow: {
income: cashFlow.current.income,
expense: cashFlow.current.expense,
previous: cashFlow.previous,
},
netWorthHistory: netWorthEvolution,
accounts: accountBalances.map(
(acc: {
id: string;
name: string;
current_balance: number;
previous_balance: number;
}) => ({
...acc,
currentBalance: acc.current_balance,
previousBalance: acc.previous_balance,
diff: acc.current_balance - acc.previous_balance,
}),
),
topCategories,
});
} catch (error) {
console.error('Failed to fetch dashboard data:', error);
} finally {
setIsLoading(false);
}
};
fetchData();
}, []);
return { ...data, isLoading };
}