feat: add sign-in flow, routing shell, and searchable book list

Pin @testing-library/jest-dom to ~6.9.1 (6.10.0 is npm-deprecated).

Claude-Session: https://claude.ai/code/session_01M9MLit5Ko3X4s7rzC5Kv7X
This commit is contained in:
2026-10-02 14:23:42 -05:00
parent e1096da1a7
commit f0efa25f23
14 changed files with 625 additions and 11 deletions
+64 -1
View File
@@ -1,3 +1,66 @@
import { useState } from 'react'
import { BrowserRouter, Link, Navigate, Outlet, Route, Routes } from 'react-router'
import { errorMessage } from './api'
import { AuthProvider, useAuth } from './auth/AuthContext'
import { LoginForm } from './auth/LoginForm'
import { RequireAuth } from './auth/RequireAuth'
import { BookList } from './books/BookList'
import { secondaryButton } from './ui'
export function App() {
return <h1 className="p-6 text-2xl font-semibold">My Library</h1>
return (
<BrowserRouter>
<AuthProvider>
<AppRoutes />
</AuthProvider>
</BrowserRouter>
)
}
export function AppRoutes() {
return (
<Routes>
<Route path="/login" element={<LoginForm />} />
<Route element={<RequireAuth />}>
<Route element={<Shell />}>
<Route path="/books" element={<BookList />} />
</Route>
</Route>
<Route path="*" element={<Navigate to="/books" replace />} />
</Routes>
)
}
function Shell() {
const { user, logout } = useAuth()
const [error, setError] = useState<string | null>(null)
return (
<div className="min-h-screen bg-slate-50 text-slate-900">
<header className="border-b border-slate-200 bg-white">
<div className="mx-auto flex max-w-4xl items-center justify-between p-4">
<Link to="/books" className="text-lg font-semibold">
My Library
</Link>
<div className="flex items-center gap-3 text-sm">
<span>{user?.username}</span>
<button
type="button"
className={secondaryButton}
onClick={() => logout().catch((err) => setError(errorMessage(err)))}
>
Log out
</button>
</div>
</div>
{error && (
<p role="alert" className="mx-auto max-w-4xl px-4 pb-2 text-sm text-red-700">
{error}
</p>
)}
</header>
<main className="mx-auto max-w-4xl p-4">
<Outlet />
</main>
</div>
)
}