feat: initial commit - finanzas app

Complete personal finance management application with:
- Dashboard with financial metrics and alerts
- Credit card management and payments
- Fixed and variable debt tracking
- Monthly budget planning
- Intelligent alert system
- Responsive design with Tailwind CSS

Tech stack: Next.js 14, TypeScript, Zustand, Recharts

🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
renato97
2026-01-29 00:00:32 +00:00
commit 712b06f118
65 changed files with 8556 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
'use client'
import { AlertCircle, CreditCard, PiggyBank, Wallet } from 'lucide-react'
import { MetricCard } from './MetricCard'
import { ExpenseChart } from './ExpenseChart'
import { useFinanzasStore } from '@/lib/store'
import {
calculateTotalFixedDebts,
calculateTotalVariableDebts,
} from '@/lib/utils'
import {
getCurrentMonthBudget,
calculateCurrentSpending,
} from '@/lib/alerts'
import { cn } from '@/lib/utils'
export function SummarySection() {
const {
fixedDebts,
variableDebts,
creditCards,
monthlyBudgets,
alerts,
currentMonth,
currentYear,
} = useFinanzasStore()
// Calcular métricas
const totalFixedDebts = calculateTotalFixedDebts(fixedDebts)
const totalVariableDebts = calculateTotalVariableDebts(variableDebts)
const totalPendingDebts = totalFixedDebts + totalVariableDebts
const totalCardBalance = creditCards.reduce(
(sum, card) => sum + card.currentBalance,
0
)
const currentBudget = getCurrentMonthBudget(
monthlyBudgets,
currentMonth,
currentYear
)
const currentSpending = calculateCurrentSpending(fixedDebts, variableDebts)
// Presupuesto disponible (ingresos - gastos actuales)
const availableBudget = currentBudget
? currentBudget.totalIncome - currentSpending
: 0
// Meta de ahorro proyectada
const projectedSavings = currentBudget
? currentBudget.totalIncome - currentSpending
: 0
const savingsGoal = currentBudget?.savingsGoal || 0
// Alertas no leídas (primeras 3)
const unreadAlerts = alerts
.filter((alert) => !alert.isRead)
.slice(0, 3)
// Colores por severidad de alerta
const severityColors = {
danger: 'border-rose-500 bg-rose-500/10 text-rose-400',
warning: 'border-amber-500 bg-amber-500/10 text-amber-400',
info: 'border-blue-500 bg-blue-500/10 text-blue-400',
}
return (
<div className="space-y-6">
{/* Grid de métricas */}
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<MetricCard
title="Deudas Pendientes"
amount={totalPendingDebts}
subtitle={`${fixedDebts.filter((d) => !d.isPaid).length + variableDebts.filter((d) => !d.isPaid).length} pagos pendientes`}
icon={Wallet}
color="text-rose-400"
/>
<MetricCard
title="Balance en Tarjetas"
amount={totalCardBalance}
subtitle={`${creditCards.length} tarjetas activas`}
icon={CreditCard}
color="text-blue-400"
/>
<MetricCard
title="Presupuesto Disponible"
amount={availableBudget}
subtitle={
currentBudget
? `de ${currentBudget.totalIncome.toLocaleString('es-AR', {
style: 'currency',
currency: 'ARS',
})} ingresos`
: 'Sin presupuesto definido'
}
icon={PiggyBank}
color="text-emerald-400"
/>
<MetricCard
title="Meta de Ahorro"
amount={projectedSavings}
subtitle={
savingsGoal > 0
? `${((projectedSavings / savingsGoal) * 100).toFixed(0)}% de la meta`
: 'Sin meta definida'
}
icon={PiggyBank}
color="text-violet-400"
/>
</div>
{/* Gráfico y alertas */}
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
{/* Gráfico de distribución */}
<ExpenseChart fixedDebts={fixedDebts} variableDebts={variableDebts} />
{/* Alertas destacadas */}
<div className="rounded-xl border border-slate-700 bg-slate-800 p-6">
<h3 className="mb-4 text-lg font-semibold text-white">
Alertas Destacadas
</h3>
{unreadAlerts.length === 0 ? (
<div className="flex h-48 items-center justify-center">
<p className="text-slate-500">No hay alertas pendientes</p>
</div>
) : (
<div className="space-y-3">
{unreadAlerts.map((alert) => (
<div
key={alert.id}
className={cn(
'flex items-start gap-3 rounded-lg border p-4',
severityColors[alert.severity]
)}
>
<AlertCircle className="mt-0.5 h-5 w-5 shrink-0" />
<div>
<h4 className="font-medium">{alert.title}</h4>
<p className="mt-1 text-sm opacity-90">{alert.message}</p>
</div>
</div>
))}
</div>
)}
</div>
</div>
</div>
)
}