feat: otimização de performance e ajustes finais
This commit is contained in:
+79
@@ -0,0 +1,79 @@
|
||||
import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts';
|
||||
import { BudgetExecutionDTO } from '@/types/budget';
|
||||
import { formatCurrency } from '@/utils/locale';
|
||||
|
||||
interface BudgetExecutionChartProps {
|
||||
data: BudgetExecutionDTO[];
|
||||
}
|
||||
|
||||
export function BudgetExecutionChart({ data = [] }: BudgetExecutionChartProps) {
|
||||
// Aggregate data by type
|
||||
const chartData = [
|
||||
{
|
||||
name: 'Compromissos',
|
||||
valor: data
|
||||
.filter((e) => e.movementType === 'COMMITMENT')
|
||||
.reduce((sum, e) => sum + e.amount, 0),
|
||||
fill: '#f97316', // orange-500
|
||||
},
|
||||
{
|
||||
name: 'Liquidações',
|
||||
valor: data
|
||||
.filter((e) => e.movementType === 'LIQUIDATION')
|
||||
.reduce((sum, e) => sum + e.amount, 0),
|
||||
fill: '#3b82f6', // blue-500
|
||||
},
|
||||
{
|
||||
name: 'Pagamentos',
|
||||
valor: data
|
||||
.filter((e) => e.movementType === 'PAYMENT')
|
||||
.reduce((sum, e) => sum + e.amount, 0),
|
||||
fill: '#22c55e', // green-500
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="bg-white p-6 rounded-xl shadow-sm border border-gray-100">
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-6">Resumo da Execução Orçamentária</h3>
|
||||
<div className="h-[300px] w-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={chartData}>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#f3f4f6" />
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fill: '#6b7280', fontSize: 12 }}
|
||||
/>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fill: '#6b7280', fontSize: 12 }}
|
||||
tickFormatter={(value) => formatCurrency(value).split(',')[0]} // Simplified currency
|
||||
/>
|
||||
<Tooltip
|
||||
formatter={(value: number, name: string) => [formatCurrency(value), name]}
|
||||
contentStyle={{ borderRadius: '8px', border: 'none', boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)' }}
|
||||
labelStyle={{ color: '#374151', fontWeight: 600, marginBottom: '0.5rem' }}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="valor"
|
||||
radius={[4, 4, 0, 0]}
|
||||
barSize={60}
|
||||
/>
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
<div className="mt-4 grid grid-cols-3 gap-4">
|
||||
{chartData.map((item) => (
|
||||
<div key={item.name} className="text-center p-3 rounded-lg bg-gray-50">
|
||||
<p className="text-xs text-gray-500 uppercase font-semibold mb-1">{item.name}</p>
|
||||
<p className="text-sm font-bold" style={{ color: item.fill }}>
|
||||
{formatCurrency(item.valor)}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user