feat: creats frontend for the project

This commit is contained in:
vakabunga
2026-03-02 00:33:09 +03:00
parent 4d67636633
commit cd56e2bf9d
37 changed files with 3762 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
import {
PieChart,
Pie,
Cell,
Tooltip,
ResponsiveContainer,
} from 'recharts';
import type { ByCategoryItem } from '@family-budget/shared';
import { formatAmount } from '../utils/format';
interface Props {
data: ByCategoryItem[];
}
const COLORS = [
'#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6',
'#ec4899', '#06b6d4', '#84cc16', '#f97316', '#6366f1',
'#14b8a6', '#e11d48', '#0ea5e9', '#a855f7', '#22c55e',
];
const rubFormatter = new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB',
maximumFractionDigits: 0,
});
export function CategoryChart({ data }: Props) {
if (data.length === 0) {
return <div className="chart-empty">Нет данных за период</div>;
}
const chartData = data.map((item) => ({
name: item.categoryName,
value: Math.abs(item.amount) / 100,
txCount: item.txCount,
share: item.share,
}));
return (
<div className="category-chart-wrapper">
<ResponsiveContainer width="100%" height={300}>
<PieChart>
<Pie
data={chartData}
cx="50%"
cy="50%"
outerRadius={100}
dataKey="value"
nameKey="name"
label={({ name, share }: { name: string; share: number }) =>
`${name} ${(share * 100).toFixed(0)}%`
}
labelLine
>
{chartData.map((_, idx) => (
<Cell
key={idx}
fill={COLORS[idx % COLORS.length]}
/>
))}
</Pie>
<Tooltip
formatter={(value: number) => rubFormatter.format(value)}
/>
</PieChart>
</ResponsiveContainer>
<table className="category-table">
<thead>
<tr>
<th>Категория</th>
<th>Сумма</th>
<th className="th-center">Операций</th>
<th className="th-center">Доля</th>
</tr>
</thead>
<tbody>
{data.map((item, idx) => (
<tr key={item.categoryId}>
<td>
<span
className="color-dot"
style={{
backgroundColor:
COLORS[idx % COLORS.length],
}}
/>
{item.categoryName}
</td>
<td>{formatAmount(item.amount)}</td>
<td className="td-center">{item.txCount}</td>
<td className="td-center">
{(item.share * 100).toFixed(1)}%
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}