import { useEffect, useState } from "react"; import Sidebar from "./components/layout/Sidebar"; import TopMenu from "./components/layout/TopMenu"; import Home from "./pages/Home"; import MetersPage from "./pages/meters/MeterPage"; import ConcentratorsPage from "./pages/concentrators/ConcentratorsPage"; import ProjectsPage from "./pages/projects/ProjectsPage"; import UsersPage from "./pages/UsersPage"; import RolesPage from "./pages/RolesPage"; import ConsumptionPage from "./pages/consumption/ConsumptionPage"; import ProfileModal from "./components/layout/common/ProfileModal"; import { updateMyProfile } from "./api/me"; import SettingsModal, { type AppSettings, loadSettings, } from "./components/SettingsModals"; import LoginPage from "./pages/LoginPage"; // Auth imports import { isAuthenticated, getMe, logout as authLogout, clearAuth, type AuthUser, } from "./api/auth"; import ConfirmModal from "./components/layout/common/ConfirmModal"; import Watermark from "./components/layout/common/Watermark"; export type Page = | "home" | "projects" | "meters" | "concentrators" | "consumption" | "users" | "roles"; export default function App() { const [isAuth, setIsAuth] = useState(false); const [user, setUser] = useState(null); const [authLoading, setAuthLoading] = useState(true); // Check authentication on mount useEffect(() => { const checkAuth = async () => { if (isAuthenticated()) { try { const userData = await getMe(); setUser(userData); setIsAuth(true); } catch { clearAuth(); setIsAuth(false); setUser(null); } } setAuthLoading(false); }; checkAuth(); }, []); const handleLogin = () => { // After successful login, fetch user data const fetchUser = async () => { try { const userData = await getMe(); setUser(userData); setIsAuth(true); } catch { clearAuth(); setIsAuth(false); } }; fetchUser(); }; const handleLogout = async () => { try { await authLogout(); } catch { // Ignore logout errors } clearAuth(); setUser(null); setIsAuth(false); // Reset navigation setPage("home"); setSubPage("default"); setSelectedProject(""); }; // ✅ confirm logout modal state const [logoutOpen, setLogoutOpen] = useState(false); const [loggingOut, setLoggingOut] = useState(false); const [page, setPage] = useState("home"); const [subPage, setSubPage] = useState("default"); const [selectedProject, setSelectedProject] = useState(""); const [profileOpen, setProfileOpen] = useState(false); const [savingProfile, setSavingProfile] = useState(false); const [settingsOpen, setSettingsOpen] = useState(false); const [settings, setSettings] = useState(() => loadSettings()); const navigateToMetersWithProject = (projectName: string) => { setSelectedProject(projectName); setSubPage(projectName); setPage("meters"); }; const handleUploadAvatar = async (file: File) => { const base64 = await fileToBase64(file); localStorage.setItem("mock_avatar", base64); setUser((prev) => prev ? { ...prev, avatar_url: base64 } : null); }; function fileToBase64(file: File) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(String(reader.result)); reader.onerror = reject; reader.readAsDataURL(file); }); } const handleSaveProfile = async (next: { name: string; email: string; organismName?: string; }) => { if (!user) return; setSavingProfile(true); try { const updated = await updateMyProfile(next); setUser((prev) => prev ? ({ ...prev, name: updated.name ?? next.name ?? prev.name, email: updated.email ?? next.email ?? prev.email, avatar_url: updated.avatarUrl ?? prev.avatar_url, }) : null); setProfileOpen(false); } finally { setSavingProfile(false); } }; useEffect(() => { const root = document.documentElement; root.classList.remove("dark"); if (settings.theme === "dark") root.classList.add("dark"); if (settings.theme === "system") { const prefersDark = window.matchMedia?.( "(prefers-color-scheme: dark)" )?.matches; if (prefersDark) root.classList.add("dark"); } }, [settings.theme]); const renderPage = () => { switch (page) { case "projects": return ; case "meters": return ; case "concentrators": return ; case "consumption": return ; case "users": return ; case "roles": return ; case "home": default: return ( { setPage(p); setSubPage("default"); }} navigateToMetersWithProject={navigateToMetersWithProject} /> ); } }; // Show loading while checking authentication if (authLoading) { return (
Cargando...
); } if (!isAuth) { return ; } return (
{ setPage(p); setSubPage("default"); if (p !== "meters") setSelectedProject(""); }} />
setProfileOpen(true)} onRequestLogout={() => setLogoutOpen(true)} />
{/* ✅ AQUÍ VA LA MARCA DE AGUA */}
{renderPage()}
setSettingsOpen(false)} settings={settings} setSettings={setSettings} /> setProfileOpen(false)} onSave={handleSaveProfile} onUploadAvatar={handleUploadAvatar} /> {/* ✅ ConfirmModal: Cerrar sesión */} setLogoutOpen(false)} onConfirm={async () => { setLoggingOut(true); try { await handleLogout(); setLogoutOpen(false); } finally { setLoggingOut(false); } }} />
); }