/* global React, ReactDOM, window */ // Ruticomidas — app shell const { useState, useEffect, useRef } = React; const D = window.RC_DATA; const SCREENS = window.RC_SCREENS; const { AuthGate, useAuth } = window.RC_Auth; const { StoreProvider } = window.RC_STORE; function Sidebar({ current, onNav }) { const auth = useAuth(); const user = auth?.user; const displayName = user ? (user.name || user.email?.split('@')[0] || '—') : '—'; const role = user?.is_admin ? 'Hogar · admin' : 'Hogar · miembro'; const avatarLetter = displayName[0]?.toUpperCase() || '?'; return ( ); } function NotificationsPanel({ notifications, onClose, onReload, onOpenTicket }) { const unread = notifications.filter(n => !n.read); const markAll = async () => { await window.api('/api/notifications/read-all', 'POST', {}); await onReload(); }; const handleClick = async (n) => { if (!n.read) { await window.api(`/api/notifications/${n.id}/read`, 'POST', {}); await onReload(); } const { queueItemId } = window.RC_notifText(n); if (queueItemId) { onClose(); onOpenTicket && onOpenTicket(queueItemId); } }; return (
Notificaciones {unread.length > 0 && ( )}
{notifications.length === 0 && (
Sin notificaciones
)} {notifications.map(n => { const { title, body } = window.RC_notifText(n); return (
handleClick(n)} style={{ padding: '12px 16px', borderBottom: '1px solid var(--frame)', background: n.read ? 'transparent' : 'rgba(60,255,208,.06)', cursor: 'pointer', }}>
{title}
{body ?
{body}
: null}
{n.created_at?.slice(0, 16).replace('T', ' ')}
); })}
); } function Topbar({ current }) { const { notifications, reload } = window.RC_STORE.useStore(); const [showNotifs, setShowNotifs] = useState(false); const unreadCount = notifications.filter(n => !n.read).length; const panelRef = useRef(null); useEffect(() => { if (!showNotifs) return; const handler = (e) => { if (panelRef.current && !panelRef.current.contains(e.target)) setShowNotifs(false); }; document.addEventListener('mousedown', handler); return () => document.removeEventListener('mousedown', handler); }, [showNotifs]); return (
{showNotifs && ( setShowNotifs(false)} onReload={reload.notifications} onOpenTicket={(qid) => { window.location.hash = '#tickets'; }} /> )}
); } function App() { const [route, setRoute] = useState(() => { const h = window.location.hash.slice(1); return SCREENS[h] ? h : 'planning'; }); useEffect(() => { window.location.hash = route; }, [route]); useEffect(() => { const handler = () => { const h = window.location.hash.slice(1); if (SCREENS[h]) setRoute(h); }; window.addEventListener('hashchange', handler); return () => window.removeEventListener('hashchange', handler); }, []); const Screen = SCREENS[route]; return (
); } ReactDOM.createRoot(document.getElementById('root')).render( );