diff --git a/packages/web/src/App.tsx b/packages/web/src/App.tsx
index e0c7f22..1680c13 100644
--- a/packages/web/src/App.tsx
+++ b/packages/web/src/App.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect, useRef } from 'react'
+import { useState, useEffect, useRef, Component, type ReactNode, type ErrorInfo } from 'react'
import { BrowserRouter, Routes, Route, useLocation, useNavigate, Link } from 'react-router-dom'
import { IconShieldCheck, IconArrowRight, IconX, IconSearch, IconChevronUp, IconMessageCircle, IconBug, IconBulb, IconCommand, IconArrowNarrowRight } from '@tabler/icons-react'
import { AuthProvider, useAuthState } from './hooks/useAuth'
@@ -45,6 +45,26 @@ import ProfilePage from './pages/ProfilePage'
import RecoverPage from './pages/RecoverPage'
import EmbedBoard from './pages/EmbedBoard'
import { api } from './lib/api'
+
+class ErrorBoundary extends Component<{ children: ReactNode }, { error: Error | null }> {
+ state = { error: null as Error | null }
+ static getDerivedStateFromError(error: Error) { return { error } }
+ componentDidCatch(error: Error, info: ErrorInfo) { console.error('React error:', error, info) }
+ render() {
+ if (this.state.error) {
+ return (
+
+
+
Something went wrong
+
{this.state.error.message}
+
+
+
+ )
+ }
+ return this.props.children
+ }
+}
import BoardIcon from './components/BoardIcon'
import StatusBadge from './components/StatusBadge'
import Avatar from './components/Avatar'
@@ -348,16 +368,16 @@ function SearchPage() {
}
function RequireAdmin({ children }: { children: React.ReactNode }) {
- const [ok, setOk] = useState(null)
+ const admin = useAdmin()
const nav = useNavigate()
useEffect(() => {
- api.get('/admin/boards')
- .then(() => setOk(true))
- .catch(() => nav('/admin/login', { replace: true }))
- }, [nav])
+ if (!admin.loading && !admin.isAdmin) {
+ nav('/', { replace: true })
+ }
+ }, [admin.loading, admin.isAdmin, nav])
- if (!ok) return null
+ if (admin.loading || !admin.isAdmin) return null
return <>{children}>
}
@@ -407,7 +427,7 @@ function AdminBanner() {
Admin panel