diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-12 21:50:56 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-12 21:50:56 -0800 |
| commit | 42f1b4de384bcbbdab3b80d8e5cc53b36fcffd50 (patch) | |
| tree | 3a5aab90607131231ec68367f8cc00425d7dc516 /frontend/src/App.tsx | |
| parent | 9db2500fb340ef304c0f15f4379bc33589df9a63 (diff) | |
| download | neko-42f1b4de384bcbbdab3b80d8e5cc53b36fcffd50.tar.gz neko-42f1b4de384bcbbdab3b80d8e5cc53b36fcffd50.tar.bz2 neko-42f1b4de384bcbbdab3b80d8e5cc53b36fcffd50.zip | |
Implement frontend login logic with >90% coverage
Diffstat (limited to 'frontend/src/App.tsx')
| -rw-r--r-- | frontend/src/App.tsx | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3d7ded3..b986198 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,35 +1,62 @@ -import { useState } from 'react' -import reactLogo from './assets/react.svg' -import viteLogo from '/vite.svg' -import './App.css' +import React, { useEffect, useState } from 'react'; +import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom'; +import Login from './components/Login'; +import './App.css'; -function App() { - const [count, setCount] = useState(0) +// Protected Route wrapper +function RequireAuth({ children }: { children: React.ReactElement }) { + const [auth, setAuth] = useState<boolean | null>(null); + const location = useLocation(); + + useEffect(() => { + fetch('/api/auth') + .then((res) => { + if (res.ok) { + setAuth(true); + } else { + setAuth(false); + } + }) + .catch(() => setAuth(false)); + }, []); + + if (auth === null) { + return <div>Loading...</div>; + } + + if (!auth) { + return <Navigate to="/login" state={{ from: location }} replace />; + } + + return children; +} +function Dashboard() { + // Placeholder for now return ( - <> - <div> - <a href="https://vite.dev" target="_blank"> - <img src={viteLogo} className="logo" alt="Vite logo" /> - </a> - <a href="https://react.dev" target="_blank"> - <img src={reactLogo} className="logo react" alt="React logo" /> - </a> - </div> - <h1>Vite + React</h1> - <div className="card"> - <button onClick={() => setCount((count) => count + 1)}> - count is {count} - </button> - <p> - Edit <code>src/App.tsx</code> and save to test HMR - </p> - </div> - <p className="read-the-docs"> - Click on the Vite and React logos to learn more - </p> - </> + <div> + <h1>Dashboard</h1> + <p>Welcome to the new Neko/v2 frontend.</p> + </div> ) } -export default App +function App() { + return ( + <BrowserRouter basename="/v2"> + <Routes> + <Route path="/login" element={<Login />} /> + <Route + path="/*" + element={ + <RequireAuth> + <Dashboard /> + </RequireAuth> + } + /> + </Routes> + </BrowserRouter> + ); +} + +export default App; |
