// ===== RIVAMAR Group — Módulos del panel admin (v1.1) =====
const { useState, useMemo } = React;
// ---------- Iconos ----------
const AdminIcons = {
grid: ,
list: ,
calendar: ,
image: ,
edit: ,
users: ,
chart: ,
briefcase: ,
home: ,
trash: ,
star: ,
plus: ,
reset: ,
mail: ,
globe: ,
book: ,
};
function AdIcon({ name, size = 18 }) {
return ;
}
// ---------- Vista calendario ----------
function CalendarView({ reservas, onSelect }) {
const [month, setMonth] = useState(new Date(2026, 5, 1)); // junio 2026 (local)
const y = month.getFullYear(), m = month.getMonth();
const first = new Date(y, m, 1);
const startDow = (first.getDay() + 6) % 7; // lunes=0
const days = new Date(y, m + 1, 0).getDate();
const monthName = month.toLocaleDateString('es-CL', { month: 'long', year: 'numeric' });
const byDate = {};
reservas.forEach((r) => { (byDate[r.fecha] = byDate[r.fecha] || []).push(r); });
const cells = [];
for (let i = 0; i < startDow; i++) cells.push(null);
for (let d = 1; d <= days; d++) cells.push(d);
const dateStr = (d) => `${y}-${String(m + 1).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
return (
{monthName}
{['Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá', 'Do'].map((d) =>
{d}
)}
{cells.map((d, i) => {
if (!d) return
;
const items = byDate[dateStr(d)] || [];
return (
{d}
{items.slice(0, 2).map((r) => (
))}
{items.length > 2 &&
+{items.length - 2} más
}
);
})}
);
}
// ---------- Modal editar reserva ----------
function EditModal({ reserva, onSave, onClose }) {
const [r, setR] = useState(reserva);
if (!reserva) return null;
const set = (k) => (e) => setR({ ...r, [k]: e.target.value });
return (
e.stopPropagation()}>
Editar reserva {r.id}
Cancelar
onSave(r)} className="flex-1">Guardar cambios
);
}
// ---------- Reportes ----------
function Reportes({ reservas }) {
const porLocal = LOCALES.map((l) => ({
local: l.nombre,
total: reservas.filter((r) => r.local === l.id).length,
exponor: reservas.filter((r) => r.local === l.id && r.exponor).length,
tono: l.tono,
}));
const maxTotal = Math.max(1, ...porLocal.map((p) => p.total));
const pax = reservas.reduce((s, r) => s + (r.estado !== 'cancelada' ? r.pax : 0), 0);
const exponorPax = reservas.filter((r) => r.exponor).reduce((s, r) => s + r.pax, 0);
const confirmadas = reservas.filter((r) => r.estado === 'confirmada').length;
const tasa = Math.round(100 * confirmadas / Math.max(1, reservas.length));
const exportPDF = () => {
const fecha = new Date().toLocaleDateString('es-CL', { day: '2-digit', month: 'long', year: 'numeric' });
const filas = porLocal.map((p) => `| ${p.local} | ${p.total} | ${p.exponor} |
`).join('');
const html = `Reporte RIVAMAR
R
RIVAMAR Group — Reporte de Reservas
Antofagasta, Chile · MAEDY GROUP
Generado el ${fecha} · Periodo: histórico acumulado
${reservas.length}
Total reservas
${confirmadas}
Confirmadas
${tasa}%
Tasa confirmación
Reservas por local
| Local | Total reservas | Con EXPONOR |
${filas}
Beneficio EXPONOR 2026
| Reservas con descuento EXPONOR | ${reservas.filter(r=>r.exponor).length} |
| Comensales bajo beneficio EXPONOR | ${exponorPax} |