/* GestiFalla — iconos + componentes compartidos */
const { useState, useEffect, useRef } = React;
window.useState = React.useState; window.useEffect = React.useEffect; window.useRef = React.useRef;
/* ---------- Icon set (outline, 20px viewBox 24) ---------- */
const I = {
bell: (p) => ,
chat: (p) => ,
chevR: (p) => ,
chevD: (p) => ,
back: (p) => ,
star: (p) => ,
home: (p) => ,
id: (p) => ,
calendar: (p) => ,
wallet: (p) => ,
user: (p) => ,
transfer: (p) => ,
plus: (p) => ,
list: (p) => ,
cart: (p) => ,
users: (p) => ,
euro: (p) => ,
doc: (p) => ,
home2: (p) => ,
pin: (p) => ,
note: (p) => ,
check: (p) => ,
eye: (p) => ,
eyeOff: (p) => ,
share: (p) => ,
download: (p) => ,
shield: (p) => ,
logout: (p) => ,
bellGear: (p) => ,
qr: (p) => ,
ticket: (p) => ,
arrowUp: (p) => ,
arrowDown: (p) => ,
clock: (p) => ,
};
/* ---------- Avatar ---------- */
function Avatar({ name, src, size = 44, fontSize, ring }) {
const initials = name ? name.split(' ').slice(0,2).map(w => w[0]).join('').toUpperCase() : '?';
const st = { width: size, height: size, fontSize: fontSize || size * 0.36 };
if (ring) Object.assign(st, { boxShadow: `0 0 0 ${ring}px rgba(255,255,255,0.25)` });
if (src) return
;
return
{initials}
;
}
/* ---------- Header universal ---------- */
function Header({ children }) {
return {children}
;
}
function HeaderBrand({ onBell, onChat, notif = true }) {
return (
);
}
function SubHeader({ title, onBack, right }) {
return (
<>
>
);
}
/* ---------- Data cell ---------- */
function Cell({ label, value }) {
return (
);
}
/* ---------- Bottom nav ---------- */
const NAV = [
{ id: 'home', label: 'Inicio', icon: I.home },
{ id: 'ficha', label: 'Mi ficha', icon: I.id },
{ id: 'eventos', label: 'Eventos', icon: I.calendar },
{ id: 'monedero', label: 'Monedero', icon: I.wallet },
{ id: 'perfil', label: 'Perfil', icon: I.user },
];
function BottomNav({ active, onNav }) {
return (
);
}
/* ---------- Toast ---------- */
function Toast({ msg, show }) {
if (!show) return null;
return (
);
}
function useToast() {
const [toast, setToast] = useState(null);
const fire = (msg) => { setToast(msg); };
useEffect(() => { if (toast) { const t = setTimeout(() => setToast(null), 2500); return () => clearTimeout(t); } }, [toast]);
return [toast, fire];
}
/* ---------- Bottom sheet ---------- */
function Sheet({ open, onClose, title, children }) {
if (!open) return null;
return (
e.stopPropagation()}>
{title &&
{title}
}
{children}
);
}
/* ---------- QR code (deterministic pseudo-pattern) ---------- */
function QR({ size = 96, fg = '#0d2a50', seed = 7 }) {
const n = 21;
const cell = size / n;
const rects = [];
let s = seed;
const rnd = () => { s = (s * 9301 + 49297) % 233280; return s / 233280; };
const finder = (x, y) => x < 7 && y < 7 || x >= n-7 && y < 7 || x < 7 && y >= n-7;
for (let y = 0; y < n; y++) for (let x = 0; x < n; x++) {
if (finder(x,y)) continue;
if (rnd() > 0.52) rects.push();
}
const Finder = ({ x, y }) => (
);
return (
);
}
Object.assign(window, { I, Avatar, Header, HeaderBrand, SubHeader, Cell, BottomNav, NAV, Toast, useToast, Sheet, QR });