Solucionado submodulos y subiendo codigo real

This commit is contained in:
Panchito
2026-06-27 11:58:05 -05:00
parent 6b99090835
commit 762f596f53
116 changed files with 24068 additions and 2 deletions

View File

@@ -0,0 +1,34 @@
// src/components/Modal.jsx
export default function Modal({ title, onClose, children, width = 900 }) {
return (
<div
onClick={onClose}
style={{
position: "fixed", inset: 0, background: "rgba(15,23,42,0.55)",
display: "flex", alignItems: "center", justifyContent: "center",
zIndex: 1000, padding: 20,
}}
>
<div
onClick={(e) => e.stopPropagation()}
style={{
background: "#fff", borderRadius: 16, width: "100%", maxWidth: width,
maxHeight: "90vh", overflow: "auto", boxShadow: "0 20px 60px rgba(0,0,0,0.3)",
}}
>
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "center",
padding: "16px 22px", borderBottom: "1px solid #e2e8f0", position: "sticky",
top: 0, background: "#fff", zIndex: 2,
}}>
<h3 style={{ fontSize: 16, fontWeight: 700, color: "#1e40af" }}>{title}</h3>
<button onClick={onClose} style={{
border: "none", background: "#f1f5f9", borderRadius: 8, width: 32, height: 32,
cursor: "pointer", fontSize: 18, color: "#475569",
}}>×</button>
</div>
<div style={{ padding: 22 }}>{children}</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,54 @@
// src/components/Sidebar.jsx
import { useAuth } from "../lib/auth";
const MENU = [
{ id: "ocupabilidad", ico: "📊", label: "Ocupabilidad" },
{ id: "ventas", ico: "💰", label: "Ventas" },
{ id: "comisiones", ico: "🧮", label: "Comisiones" },
{ id: "cobranza", ico: "📋", label: "Cobranza" },
{ id: "rentabilidad", ico: "📈", label: "Rentabilidad" },
{ id: "asesores", ico: "👥", label: "Asesores" },
{ id: "usuarios", ico: "🔐", label: "Usuarios" },
];
export default function Sidebar({ active, onChange }) {
const { perfil, permisos, logout } = useAuth();
const visibles = MENU.filter((m) => permisos.includes(m.id));
return (
<aside className="sidebar">
<div className="sidebar-logo">Escuela <span>Refrigeración</span></div>
<nav className="nav" style={{ flex: 1 }}>
{visibles.map((m) => (
<button
key={m.id}
className={`nav-item ${active === m.id ? "active" : ""}`}
onClick={() => onChange(m.id)}
>
<span className="ico">{m.ico}</span> {m.label}
</button>
))}
</nav>
<div style={{ padding: 14, borderTop: "1px solid rgba(255,255,255,0.08)" }}>
<div style={{ fontSize: 12, color: "#94a3b8", marginBottom: 2 }}>
{perfil?.nombre || "Usuario"}
</div>
<div style={{ fontSize: 11, color: "#60a5fa", fontWeight: 600, marginBottom: 10 }}>
{perfil?.rol || ""}
</div>
<button
onClick={logout}
style={{
width: "100%", padding: "8px", border: "1px solid rgba(255,255,255,0.15)",
borderRadius: 8, background: "transparent", color: "#cbd5e1", fontSize: 12,
cursor: "pointer", fontWeight: 500,
}}
>
🚪 Cerrar sesión
</button>
</div>
</aside>
);
}

View File

@@ -0,0 +1,51 @@
// src/components/UI.jsx
export function Loader({ text = "Cargando..." }) {
return (
<div className="loader-wrap">
<div className="spinner" />
<div className="loader-text">{text}</div>
</div>
);
}
export function ErrorBox({ msg }) {
return <div className="error-box">⚠️ {msg}</div>;
}
export function colorSemaforo(pct) {
if (pct >= 80) return { bg: "#d1fae5", fg: "#065f46", fill: "#10b981" };
if (pct >= 60) return { bg: "#fef9c3", fg: "#854d0e", fill: "#f59e0b" };
return { bg: "#fee2e2", fg: "#991b1b", fill: "#ef4444" };
}
export function ProgressBar({ pct }) {
const c = colorSemaforo(pct);
const w = Math.min(Math.max(pct, 0), 100);
return (
<div className="pbar">
<span className="pct" style={{ color: c.fg }}>{pct.toFixed(1)}%</span>
<div className="track">
<div className="fill" style={{ width: `${w}%`, background: c.fill }} />
</div>
</div>
);
}
export function Filters({ children }) {
return <div className="filters">{children}</div>;
}
export function Select({ label, value, options, onChange }) {
return (
<div className="filter-group">
{label && <label>{label}</label>}
<select value={value} onChange={(e) => onChange(e.target.value)}>
{options.map((o) => {
const val = typeof o === "object" ? o.value : o;
const txt = typeof o === "object" ? o.label : o;
return <option key={val} value={val}>{txt}</option>;
})}
</select>
</div>
);
}