import React, { useState } from 'react';
import { DollarSign, Users, TrendingUp, Calculator, Plus, Search, X, Check, CreditCard, History, FileText } from 'lucide-react';
export default function LoanApp() {
const [activeTab, setActiveTab] = useState('dashboard');
const [loans, setLoans] = useState([
{
id: 1, client: 'Juan Pérez', amount: 5000, rate: 12, term: 12, date: '2024-01-15', status: 'active',
payments: Array.from({length: 12}, (_, i) => ({
number: i + 1, amount: 444.24,
dueDate: new Date(2024, i + 1, 15).toISOString().split('T')[0],
paid: i < 3, paidDate: i < 3 ? new Date(2024, i + 1, 14).toISOString().split('T')[0] : null
}))
},
{
id: 2, client: 'María García', amount: 10000, rate: 10, term: 24, date: '2024-02-20', status: 'active',
payments: Array.from({length: 24}, (_, i) => ({
number: i + 1, amount: 461.45,
dueDate: new Date(2024, 2 + i, 20).toISOString().split('T')[0],
paid: i < 5, paidDate: i < 5 ? new Date(2024, 2 + i, 19).toISOString().split('T')[0] : null
}))
},
{
id: 3, client: 'Carlos López', amount: 3000, rate: 15, term: 6, date: '2024-03-10', status: 'paid',
payments: Array.from({length: 6}, (_, i) => ({
number: i + 1, amount: 521.27,
dueDate: new Date(2024, 3 + i, 10).toISOString().split('T')[0],
paid: true, paidDate: new Date(2024, 3 + i, 9).toISOString().split('T')[0]
}))
},
]);
const [showNewLoan, setShowNewLoan] = useState(false);
const [showDetail, setShowDetail] = useState(false);
const [selected, setSelected] = useState(null);
const [newLoan, setNewLoan] = useState({client: '', amount: '', rate: '', term: ''});
const [calc, setCalc] = useState({amount: 10000, rate: 12, term: 12});
const [search, setSearch] = useState('');
const [filter, setFilter] = useState('all');
const calcPayment = (p, r, m) => {
const mr = r / 100 / 12;
return (p * (mr * Math.pow(1 + mr, m)) / (Math.pow(1 + mr, m) - 1)).toFixed(2);
};
const addLoan = () => {
if (!newLoan.client || !newLoan.amount || !newLoan.rate || !newLoan.term) return;
const mp = parseFloat(calcPayment(parseFloat(newLoan.amount), parseFloat(newLoan.rate), parseInt(newLoan.term)));
const loan = {
id: loans.length + 1, client: newLoan.client, amount: parseFloat(newLoan.amount),
rate: parseFloat(newLoan.rate), term: parseInt(newLoan.term),
date: new Date().toISOString().split('T')[0], status: 'active',
payments: Array.from({length: parseInt(newLoan.term)}, (_, i) => ({
number: i + 1, amount: mp,
dueDate: new Date(Date.now() + (i + 1) * 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
paid: false, paidDate: null
}))
};
setLoans([...loans, loan]);
setNewLoan({client: '', amount: '', rate: '', term: ''});
setShowNewLoan(false);
};
const pay = (lid, pnum) => {
const updatedLoans = loans.map(l => {
if (l.id === lid) {
const up = l.payments.map(p => p.number === pnum ? {...p, paid: true, paidDate: new Date().toISOString().split('T')[0]} : p);
const updatedLoan = {...l, payments: up, status: up.every(p => p.paid) ? 'paid' : 'active'};
setSelected(updatedLoan);
return updatedLoan;
}
return l;
});
setLoans(updatedLoans);
};
const openDetail = (l) => { setSelected(l); setShowDetail(true); };
const total = loans.reduce((s, l) => s + l.amount, 0);
const active = loans.filter(l => l.status === 'active').length;
const avgR = loans.length > 0 ? (loans.reduce((s, l) => s + l.rate, 0) / loans.length).toFixed(1) : 0;
const history = loans.flatMap(l => l.payments.filter(p => p.paid).map(p => ({...p, client: l.client}))).sort((a, b) => new Date(b.paidDate) - new Date(a.paidDate));
const filtered = loans.filter(l => l.client.toLowerCase().includes(search.toLowerCase()) && (filter === 'all' || l.status === filter));
return (
Sistema de Préstamos
{[
{id: 'dashboard', label: 'Panel', icon: TrendingUp},
{id: 'loans', label: 'Préstamos', icon: FileText},
{id: 'history', label: 'Historial', icon: History},
{id: 'calculator', label: 'Calculadora', icon: Calculator}
].map(t => (
))}
{activeTab === 'dashboard' && (
Total Prestado
${total.toLocaleString()}
Préstamos Recientes
| Cliente |
Monto |
Estado |
Acción |
{loans.slice(-3).reverse().map(l => (
| {l.client} |
${l.amount.toLocaleString()} |
{l.status === 'active' ? 'Activo' : 'Pagado'}
|
|
))}
)}
{activeTab === 'loans' && (
| Cliente |
Monto |
Progreso |
Estado |
Acción |
{filtered.map(l => {
const paid = l.payments.filter(p => p.paid).length;
return (
| {l.client} |
${l.amount.toLocaleString()} |
{paid}/{l.payments.length} |
{l.status === 'active' ? 'Activo' : 'Pagado'}
|
|
);
})}
)}
{activeTab === 'history' && (
Historial de Pagos
| Fecha |
Cliente |
Cuota |
Monto |
{history.length === 0 ? (
| No hay pagos |
) : (
history.map((p, i) => (
| {p.paidDate} |
{p.client} |
#{p.number} |
${p.amount.toFixed(2)} |
))
)}
)}
{activeTab === 'calculator' && (
Calculadora
Resumen
Monto:
${calc.amount.toLocaleString()}
Cuota:
${calcPayment(calc.amount, calc.rate, calc.term)}
Total:
${(calcPayment(calc.amount, calc.rate, calc.term) * calc.term).toFixed(2)}
Interés:
${((calcPayment(calc.amount, calc.rate, calc.term) * calc.term) - calc.amount).toFixed(2)}
)}
{showNewLoan && (
Nuevo Préstamo
)}
{showDetail && selected && (
{selected.client}
Préstamo #{selected.id}
Monto
${selected.amount.toLocaleString()}
Plazo
{selected.term} meses
Cuota
${calcPayment(selected.amount, selected.rate, selected.term)}
Tabla de Pagos
| Cuota |
Vencimiento |
Monto |
Estado |
Acción |
{selected.payments.map(p => (
| #{p.number} |
{p.dueDate} |
${p.amount.toFixed(2)} |
{p.paid ? (
Pagado
) : (
Pendiente
)}
|
{!p.paid && (
)}
|
))}
)}
);
}