<!
DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>MI CRÉDITO - Calculadora</title>
<link href="https://fonts.googleapis.com/css2?
family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #0277bd;
--secondary: #01579b;
--background: #f0f4f8;
--surface: #ffffff;
--text-primary: #263238;
--text-secondary: #0277bd;
--shadow: rgba(2, 119, 189, 0.3);
}
* {
margin: 0; padding: 0; box-sizing: border-box;
}
body {
font-family: 'Montserrat', sans-serif;
background-color: var(--background);
color: var(--text-primary);
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 60px auto;
background-color: var(--surface);
padding: 50px 60px;
border-radius: 24px;
box-shadow: 0 8px 24px var(--shadow);
}
h1 {
font-size: 42px;
font-weight: 700;
color: var(--primary);
text-align: center;
margin-bottom: 40px;
letter-spacing: 2px;
text-shadow: 0 0 6px rgba(0,0,0,0.1);
}
label {
display: block;
font-weight: 600;
font-size: 16px;
color: var(--secondary);
margin-top: 28px;
margin-bottom: 8px;
letter-spacing: 0.03em;
}
input[type="number"], input[type="range"] {
width: 100%;
padding: 14px 18px;
font-size: 16px;
border-radius: 14px;
background-color: #e3f2fd;
border: 1.8px solid var(--secondary);
color: var(--text-primary);
transition: border-color 0.3s ease;
}
input[type="number"]:focus, input[type="range"]:focus {
border-color: var(--primary);
outline: none;
box-shadow: 0 0 10px var(--primary);
}
input[type="range"] {
-webkit-appearance: none;
height: 8px;
cursor: pointer;
margin-top: 10px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 24px;
height: 24px;
background: var(--primary);
border-radius: 50%;
cursor: pointer;
box-shadow: 0 0 8px var(--primary);
margin-top: -8px;
transition: background 0.3s ease;
}
input[type="range"]::-webkit-slider-thumb:hover {
background: var(--secondary);
}
button {
margin-top: 45px;
width: 100%;
padding: 18px;
background: linear-gradient(90deg, var(--primary), var(--secondary));
border: none;
border-radius: 18px;
font-size: 20px;
font-weight: 700;
color: #fff;
cursor: pointer;
box-shadow: 0 4px 14px var(--primary);
transition: background 0.4s ease;
letter-spacing: 1.1px;
}
button:hover {
background: linear-gradient(90deg, var(--secondary), var(--primary));
box-shadow: 0 6px 20px var(--secondary);
}
.result {
margin-top: 50px;
background-color: #e3f2fd;
border-radius: 20px;
padding: 30px 35px;
box-shadow: 0 0 22px var(--primary);
color: var(--text-secondary);
font-size: 19px;
font-weight: 600;
letter-spacing: 0.02em;
}
.result span {
display: block;
margin-bottom: 16px;
font-size: 22px;
color: var(--primary);
}
.result span:nth-last-child(-n+2) {
margin-top: 16px;
font-size: 20px;
color: var(--primary);
}
.breakdown {
margin-top: 40px;
background-color: #bbdefb;
border-radius: 20px;
padding: 28px 32px;
box-shadow: 0 0 20px var(--secondary);
color: var(--text-primary);
}
.breakdown h3 {
color: var(--primary);
margin-bottom: 18px;
font-weight: 700;
letter-spacing: 0.04em;
}
.breakdown ul {
list-style: none;
max-height: 280px;
overflow-y: auto;
padding-right: 8px;
}
.breakdown ul::-webkit-scrollbar {
width: 8px;
}
.breakdown ul::-webkit-scrollbar-thumb {
background-color: var(--primary);
border-radius: 10px;
}
.breakdown li {
padding: 8px 12px;
border-bottom: 1px solid #90caf9;
font-size: 16px;
font-weight: 500;
letter-spacing: 0.01em;
transition: background-color 0.3s ease;
}
.breakdown li:hover {
background-color: #1565c0;
color: #e3f2fd;
}
</style>
</head>
<body>
<div class="container">
<h1>MI CRÉDITO 🇺🇾</h1>
<label for="amount">💰 Monto del crédito (UYU)</label>
<input type="number" id="amountInput" value="100000" min="10000" max="10000000"
step="1000" />
<input type="range" id="amountSlider" value="100000" min="10000" max="10000000"
step="1000" />
<label for="months">📅 Plazo del crédito (meses)</label>
<input type="number" id="monthsInput" value="12" min="1" max="60" />
<input type="range" id="monthsSlider" value="12" min="1" max="60" />
<label for="rate">📈 Tasa de interés mensual (%)</label>
<input type="number" id="rateInput" value="4" min="0" max="20" step="0.1" />
<input type="range" id="rateSlider" value="4" min="0" max="20" step="0.1" />
<button onclick="calculatePayment()">🔍 CALCULAR</button>
<div class="result" aria-live="polite" aria-atomic="true">
<span>📌 <strong>Pago mensual:</strong> <span id="monthlyPayment">UYU
0</span></span>
<span>💳 <strong>Pago total:</strong> <span id="totalPayment">UYU
0</span></span>
<span>📊 <strong>Total intereses:</strong> <span id="totalInterest">UYU
0</span></span>
<span>🧾 <strong>Monto de sobrepago:</strong> <span id="overpayAmount">UYU
0</span></span>
<span><strong>🔔 Total de la sobrepaga exacta:</strong> <span
id="exactOverpay">UYU 0</span></span>
<span><strong>⏳ Plazo total:</strong> <span id="totalTerm">0
meses</span></span>
</div>
<div class="breakdown" aria-live="polite" aria-atomic="true">
<h3>📅 Detalle mensual de pagos:</h3>
<ul id="breakdownList"></ul>
</div>
</div>
<script>
const amountInput = document.getElementById('amountInput');
const amountSlider = document.getElementById('amountSlider');
const monthsInput = document.getElementById('monthsInput');
const monthsSlider = document.getElementById('monthsSlider');
const rateInput = document.getElementById('rateInput');
const rateSlider = document.getElementById('rateSlider');
const monthlyPayment = document.getElementById('monthlyPayment');
const totalPayment = document.getElementById('totalPayment');
const totalInterest = document.getElementById('totalInterest');
const overpayAmount = document.getElementById('overpayAmount');
const exactOverpay = document.getElementById('exactOverpay');
const totalTerm = document.getElementById('totalTerm');
const breakdownList = document.getElementById('breakdownList');
function syncInputs(input, slider) {
input.addEventListener('input', () => {
slider.value = input.value;
});
slider.addEventListener('input', () => {
input.value = slider.value;
});
}
syncInputs(amountInput, amountSlider);
syncInputs(monthsInput, monthsSlider);
syncInputs(rateInput, rateSlider);
function formatCurrency(num) {
return `UYU ${num.toLocaleString('es-UY')}`;
}
function calculatePayment() {
const P = parseFloat(amountInput.value);
const n = parseInt(monthsInput.value);
const r = parseFloat(rateInput.value) / 100;
if (P <= 0 || n <= 0 || r < 0) {
alert('Por favor, ingrese valores válidos.');
return;
}
let M;
if (r === 0) {
M = P / n;
} else {
M = P * r / (1 - Math.pow(1 + r, -n));
}
const totalPay = M * n;
const totalInt = totalPay - P;
const overpay = totalInt;
const exactOverpayValue = overpay;
monthlyPayment.textContent = formatCurrency(M);
totalPayment.textContent = formatCurrency(totalPay);
totalInterest.textContent = formatCurrency(totalInt);
overpayAmount.textContent = formatCurrency(overpay);
exactOverpay.textContent = formatCurrency(exactOverpayValue);
totalTerm.textContent = `${n} meses`;
breakdownList.innerHTML = '';
let remainingPrincipal = P;
for (let i = 1; i <= n; i++) {
let interestForMonth = remainingPrincipal * r;
let principalForMonth = M - interestForMonth;
remainingPrincipal -= principalForMonth;
if (remainingPrincipal < 0) remainingPrincipal = 0;
const li = document.createElement('li');
li.textContent = `Mes ${i}: Pago = ${formatCurrency(M)}, Interés = $
{formatCurrency(interestForMonth)}, Capital pagado = $
{formatCurrency(principalForMonth)}, Saldo restante = $
{formatCurrency(remainingPrincipal)}`;
breakdownList.appendChild(li);
}
}
calculatePayment();
</script>
</body>
</html>