Files
ibiza_sistema/views/configurar/index.php
Administrador Ibiza 0858a9c9cd feat: Implementar página dedicada de gráficos para análisis de pagos de agua
- Crear nueva página /graficos con 4 tipos de gráficos interactivos
- Agregar compatibilidad con tema oscuro en selectores
- Implementar exportación a PDF profesional con encabezados
- Agregar campo 'Monto Real del Recibo' a configuración mensual
- Crear migración para nueva columna real_amount en monthly_bills
- Mejorar filtros con botones interactivos en lugar de select múltiple
- Agregar resumen ejecutivo con estadísticas detalladas
- Optimizar espacio visual y responsividad de gráficos
- Integrar Chart.js y jsPDF para funcionalidad avanzada
- Corregir problemas de carga de datos y filtros dinámicos
2026-01-03 22:23:05 -06:00

116 lines
4.8 KiB
PHP
Executable File

<div class="row mb-4">
<div class="col-12">
<h2><i class="bi bi-gear"></i> Configuración Mensual</h2>
<p class="text-muted">Configurar montos esperados de agua por mes</p>
</div>
</div>
<div class="mb-4">
<label for="yearSelect" class="form-label me-2">Año:</label>
<select id="yearSelect" class="form-select d-inline-block" style="width: auto;">
<?php for ($y = 2024; $y <= 2030; $y++): ?>
<option value="<?= $y ?>" <?= $y == $year ? 'selected' : '' ?>><?= $y ?></option>
<?php endfor; ?>
</select>
</div>
<div class="row">
<?php foreach ($months as $month):
$bill = $monthlyBills[$month] ?? null;
?>
<div class="col-md-4 mb-3">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="mb-0"><?= $month ?></h6>
<?php if ($bill): ?>
<span class="badge bg-success">$<?= number_format($bill['amount_per_house'], 2) ?>/casa</span>
<?php endif; ?>
</div>
<div class="card-body">
<div class="mb-2">
<small class="text-muted">Monto Total del Mes</small>
<input type="number" step="0.01" class="form-control form-control-sm"
id="total_<?= $month ?>" value="<?= $bill['total_amount'] ?? '' ?>">
</div>
<div class="mb-2">
<small class="text-muted">Monto por Casa</small>
<input type="number" step="0.01" class="form-control form-control-sm"
id="per_house_<?= $month ?>" value="<?= $bill['amount_per_house'] ?? '' ?>">
</div>
<div class="mb-2">
<small class="text-muted">Monto Real del Recibo</small>
<input type="number" step="0.01" class="form-control form-control-sm"
id="real_<?= $month ?>" value="<?= $bill['real_amount'] ?? '' ?>">
</div>
<div class="mb-2">
<small class="text-muted">Fecha de Vencimiento</small>
<input type="date" class="form-control form-control-sm"
id="due_<?= $month ?>" value="<?= $bill['due_date'] ?? '' ?>">
</div>
<button onclick="saveMonth('<?= $month ?>')" class="btn btn-primary btn-sm w-100">
<i class="bi bi-save"></i> Guardar
</button>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="card mt-4">
<div class="card-header">
<h5 class="card-title mb-0"><i class="bi bi-info-circle"></i> Información</h5>
</div>
<div class="card-body">
<p class="mb-2">El <strong>Monto por Casa</strong> se usa para determinar si un pago está completo, parcial o pendiente en la tabla de pagos.</p>
<p class="mb-0">Casas marcadas como "consumo_only" reciben un descuento de $100 (desde 2025)</p>
</div>
</div>
<script>
document.getElementById('yearSelect').addEventListener('change', function() {
window.location.href = '/dashboard.php?page=configurar&year=' + this.value;
});
function saveMonth(month) {
const total = document.getElementById('total_' + month).value;
const perHouse = document.getElementById('per_house_' + month).value;
const realAmount = document.getElementById('real_' + month).value;
const dueDate = document.getElementById('due_' + month).value;
const year = <?= $year ?>;
if (total === '' || perHouse === '') {
Swal.fire('Error', 'Debe ingresar el monto total y el monto por casa', 'error');
return;
}
fetch('/dashboard.php?page=config_actions&action=save_monthly_bill', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
year: year,
month: month,
total_amount: parseFloat(total),
amount_per_house: parseFloat(perHouse),
real_amount: realAmount ? parseFloat(realAmount) : null,
due_date: dueDate || null
})
})
.then(r => {
console.log('Response status:', r.status);
return r.json();
})
.then(data => {
console.log('Response data:', data);
if (data.success) {
Swal.fire('Éxito', 'Configuración guardada', 'success').then(() => location.reload());
} else {
Swal.fire('Error', data.message, 'error');
}
})
.catch(error => {
console.error('Error:', error);
Swal.fire('Error', 'Error al guardar: ' + error.message, 'error');
});
}
</script>