import React, { createContext, useContext, useState, useEffect } from 'react'; import { BrowserRouter as Router, Routes, Route, Link, NavLink, useNavigate, Outlet, Navigate, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Search, Store } from 'lucide-react'; import Home from './pages/Home'; import PluginDetail from './pages/PluginDetail'; import LoginPage from './pages/auth/LoginPage'; import RegisterPage from './pages/auth/RegisterPage'; import ForgotPasswordPage from './pages/auth/ForgotPasswordPage'; import ResetPasswordPage from './pages/auth/ResetPasswordPage'; import VerifyEmailPage from './pages/auth/VerifyEmailPage'; import ConfirmEmailChangePage from './pages/auth/ConfirmEmailChangePage'; import CheckEmailPage from './pages/auth/CheckEmailPage'; import ProfilePage from './pages/ProfilePage'; import AuthorProfilePage from './pages/AuthorProfilePage'; import SearchResultsPage from './pages/SearchResultsPage'; import DashboardAudience from './pages/dashboard/DashboardAudience'; import DashboardPlugins from './pages/dashboard/DashboardPlugins'; import ManagePlugin from './pages/dashboard/plugin/ManagePlugin'; import AddPlugin from './pages/dashboard/plugin/AddPlugin'; import TermsOfServicePage from './pages/legal/TermsOfServicePage'; import PrivacyPolicyPage from './pages/legal/PrivacyPolicyPage'; import GuidelinesPage from './pages/legal/GuidelinesPage'; import DeveloperTermsPage from './pages/legal/DeveloperTermsPage'; import LegalNoticePage from './pages/legal/LegalNoticePage'; import AdminPanel from './pages/admin/AdminPanel'; import { CookieBanner } from './components/CookieBanner'; import { openCookiePreferencesModal } from './utils/consent'; import './App.css'; import api from './api'; // --- Scroll To Top Helper --- const ScrollToTop = () => { const { pathname } = useLocation(); useEffect(() => { window.scrollTo(0, 0); }, [pathname]); return null; }; // --- Auth Context --- const AuthContext = createContext(null); export const useAuth = () => useContext(AuthContext); const AuthProvider = ({ children }: { children: React.ReactNode }) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); // Helper to decode JWT payload safely const decodeToken = (token: string) => { try { const base64Url = token.split('.')[1]; const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); } catch (e) { console.error('Failed to decode token', e); return null; } }; useEffect(() => { const token = localStorage.getItem('token'); if (token) { const payload = decodeToken(token); if (payload && payload.exp * 1000 > Date.now()) { setUser(payload); } else { localStorage.removeItem('token'); } } setLoading(false); }, []); const login = (token: string) => { localStorage.setItem('token', token); const payload = decodeToken(token); setUser(payload); }; const logout = () => { localStorage.removeItem('token'); setUser(null); }; const refreshUser = async () => { try { const res = await api.get('/user/me'); if (res.data.token) { login(res.data.token); } } catch (e) { console.error('Failed to refresh user', e); } }; return ( {!loading && children} ); }; // --- Protected Route --- const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { const { user } = useAuth(); if (!user) { return ; } return children; }; // --- Staff Route (Admin & Moderator) --- const StaffRoute = ({ children }: { children: React.ReactNode }) => { const { user } = useAuth(); if (!user || (user.role !== 'admin' && user.role !== 'moderator')) { return ; } return children; }; // --- Main App & Layout --- const App = () => ( {/* All marketplace routes share MainLayout (original navbar + footer) */} }> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* Developer Studio layout (Developer Studio navbar replaces original navbar when in dev menu) */} }> } /> } /> } /> } /> } /> ); const MainLayout = () => { const { user } = useAuth(); return ( <>