write/frontend/src/App.jsx
chris 37448be5a8 Add notes panel, font picker, sticky toolbar, and prompt improvements
- Notes: per-story rich-text notes panel (right drawer) with TipTap
  editor, image support, autosave, and full CRUD API
- Font picker: 15 Google Fonts selectable from a floating Aa button,
  persisted to localStorage via --font-body CSS variable
- Sticky toolbar: pulled formatting bar out of overflow:hidden wrapper
  so it sticks below the topbar while scrolling
- Prompts: 100 additional built-in prompts (120 total) in a shuffled
  no-repeat queue; pre-fetch on page load so the AI has time to respond;
  timeout raised to 45s; error logging + /api/prompts/test debug endpoint;
  source badge shows whether prompt came from AI or built-in list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:21:26 -04:00

47 lines
1.9 KiB
JavaScript

import { Routes, Route, Navigate } from 'react-router-dom'
import { useState, useEffect } from 'react'
import { getUser } from './lib/api'
import { ToastProvider } from './components/Toast'
import { ConfirmProvider } from './components/ConfirmDialog'
import Login from './pages/Login'
import Stories from './pages/Stories'
import EditorPage from './pages/EditorPage'
import Admin from './pages/Admin'
import ThemePicker from './components/ThemePicker'
import FontPicker, { FONTS } from './components/FontPicker'
const THEMES = ['grunge', 'gothic', 'forest', 'manuscript', 'noir']
export default function App() {
const [user, setUser] = useState(() => getUser())
const [theme, setTheme] = useState(() => localStorage.getItem('sw-theme') || 'grunge')
const [fontId, setFontId] = useState(() => localStorage.getItem('sw-font') || 'lora')
useEffect(() => {
document.documentElement.setAttribute('data-theme', theme)
localStorage.setItem('sw-theme', theme)
}, [theme])
useEffect(() => {
const font = FONTS.find(f => f.id === fontId) ?? FONTS[0]
document.documentElement.style.setProperty('--font-body', font.family)
localStorage.setItem('sw-font', fontId)
}, [fontId])
return (
<ToastProvider>
<ConfirmProvider>
<Routes>
<Route path="/login" element={user ? <Navigate to="/" /> : <Login onLogin={setUser} />} />
<Route path="/admin" element={<Admin />} />
<Route path="/" element={user ? <Stories onLogout={() => setUser(null)} /> : <Navigate to="/login" />} />
<Route path="/story/:id" element={user ? <EditorPage /> : <Navigate to="/login" />} />
<Route path="*" element={<Navigate to="/" />} />
</Routes>
{user && <ThemePicker theme={theme} setTheme={setTheme} themes={THEMES} />}
{user && <FontPicker fontId={fontId} setFont={setFontId} />}
</ConfirmProvider>
</ToastProvider>
)
}