fix: cap request bodies, link login error, add book-form retry, guard double add

Limit request bodies to 1 MiB (413 JSON), wire aria-describedby on the
login form, add Retry and cancellation to the book form load, disable
Add entry while a note POST is in flight, and poll pg_isready in README.

Claude-Session: https://claude.ai/code/session_01M9MLit5Ko3X4s7rzC5Kv7X
This commit is contained in:
2026-10-02 14:36:14 -05:00
parent 35ad0b13e2
commit 2512c67893
9 changed files with 72 additions and 13 deletions
+21 -9
View File
@@ -19,11 +19,16 @@ export function BookForm() {
const [loadError, setLoadError] = useState<string | null>(null)
const [error, setError] = useState<FormError | null>(null)
const [busy, setBusy] = useState(false)
const [attempt, setAttempt] = useState(0)
useEffect(() => {
if (!editing) return
let cancelled = false
setLoadError(null)
setLoading(true)
api<Book>('GET', `/books/${id}`).then(
(book) => {
if (cancelled) return
setFields({
title: book.title,
author: book.author,
@@ -34,11 +39,15 @@ export function BookForm() {
setLoading(false)
},
(err) => {
if (cancelled) return
setLoadError(errorMessage(err))
setLoading(false)
},
)
}, [editing, id])
return () => {
cancelled = true
}
}, [editing, id, attempt])
function set(name: keyof Fields) {
return (event: { target: { value: string } }) => setFields((prev) => ({ ...prev, [name]: event.target.value }))
@@ -72,13 +81,16 @@ export function BookForm() {
if (loadError) {
return (
<div className={card}>
<p role="alert" className="text-red-700">
{loadError}
</p>
<Link to="/books" className="mt-2 inline-block text-indigo-700 underline">
← Back to library
</Link>
<div role="alert" className={card}>
<p className="text-red-700">{loadError}</p>
<div className="mt-2 flex items-center gap-3">
<button type="button" className={secondaryButton} onClick={() => setAttempt((n) => n + 1)}>
Retry
</button>
<Link to="/books" className="text-indigo-700 underline">
← Back to library
</Link>
</div>
</div>
)
}
@@ -106,7 +118,7 @@ export function BookForm() {
))}
</select>
</label>
{genresError && <p className="text-sm text-red-700">{`Could not load genres: ${genresError}`}</p>}
{genresError && <p role="alert" className="text-sm text-red-700">{`Could not load genres: ${genresError}`}</p>}
<div className="flex gap-4">
<label className="block">
<span className={labelText}>Total pages</span>