Add autocomplete suggestions for Author, Chapter, and Reviewer fields

Adds a GET /api/jobs/suggestions endpoint that returns distinct values for
author, chapter, and reviewer_name from the database, and wires them into
HTML datalist elements on the New Job, result view, and Browse Jobs pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aaron Roberts
2026-06-09 18:24:49 +01:00
parent 1d15b5f0c1
commit 5ea18d76d6
5 changed files with 88 additions and 12 deletions

View File

@@ -1,4 +1,5 @@
import { useState, useCallback } from 'react'
import { useSuggestions } from './hooks/useSuggestions'
import { motion, AnimatePresence } from 'framer-motion'
import {
Sparkles, Zap, Loader2, Settings, Image as ImageIcon, FileText,
@@ -39,6 +40,8 @@ function App() {
base_size: 1024, image_size: 640, crop_mode: true, test_compress: false,
})
const suggestions = useSuggestions()
const [metadata, setMetadata] = useState({ author: '', book: '', chapter: '', page: '' })
const [editedOcrText, setEditedOcrText] = useState('')
const [commitLoading, setCommitLoading] = useState(false)
@@ -268,17 +271,24 @@ function App() {
{/* Metadata row */}
<div className="glass p-4 rounded-2xl flex-shrink-0">
<datalist id="rv-authors">
{suggestions.authors.map(a => <option key={a} value={a} />)}
</datalist>
<datalist id="rv-chapters">
{suggestions.chapters.map(c => <option key={c} value={c} />)}
</datalist>
<div className="grid grid-cols-4 gap-4">
{[
{ key: 'author', label: 'Author', placeholder: 'Author name' },
{ key: 'book', label: 'Book', placeholder: 'Book title' },
{ key: 'chapter', label: 'Chapter', placeholder: 'Chapter' },
{ key: 'page', label: 'Page', placeholder: 'Page number' },
].map(({ key, label, placeholder }) => (
{ key: 'author', label: 'Author', placeholder: 'Author name', list: 'rv-authors' },
{ key: 'book', label: 'Book', placeholder: 'Book title', list: undefined },
{ key: 'chapter', label: 'Chapter', placeholder: 'Chapter', list: 'rv-chapters' },
{ key: 'page', label: 'Page', placeholder: 'Page number', list: undefined },
].map(({ key, label, placeholder, list }) => (
<div key={key}>
<label className="text-xs text-gray-400 mb-1 block">{label}</label>
<input
type="text"
list={list}
value={metadata[key]}
onChange={metaField(key)}
placeholder={placeholder}
@@ -379,7 +389,7 @@ function App() {
</div>
</div>
<MetadataForm metadata={metadata} onChange={setMetadata} />
<MetadataForm metadata={metadata} onChange={setMetadata} suggestions={suggestions} />
<ModeSelector
mode={mode} onModeChange={setMode}