diff --git a/backend/main.py b/backend/main.py index 36f55a5..d792412 100644 --- a/backend/main.py +++ b/backend/main.py @@ -756,13 +756,14 @@ async def list_jobs( @app.get("/api/jobs/suggestions") async def job_suggestions(): - """Return distinct values for author, chapter, and reviewer_name to power autocomplete.""" + """Return distinct values for author, book, chapter, and reviewer_name to power autocomplete.""" try: with get_db() as conn: with conn.cursor() as cur: cur.execute(""" SELECT array_remove(array_agg(DISTINCT author ORDER BY author), NULL) AS authors, + array_remove(array_agg(DISTINCT book ORDER BY book), NULL) AS books, array_remove(array_agg(DISTINCT chapter ORDER BY chapter), NULL) AS chapters, array_remove(array_agg(DISTINCT reviewer_name ORDER BY reviewer_name), NULL) AS reviewers FROM ocr_jobs @@ -774,6 +775,7 @@ async def job_suggestions(): return JSONResponse({ "authors": row["authors"] or [], + "books": row["books"] or [], "chapters": row["chapters"] or [], "reviewers": row["reviewers"] or [], }) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 229f3f9..d72cb6a 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -274,13 +274,16 @@ function App() { {suggestions.authors.map(a => + + {(suggestions.books || []).map(b => {suggestions.chapters.map(c =>
{[ { key: 'author', label: 'Author', placeholder: 'Author name', list: 'rv-authors' }, - { key: 'book', label: 'Book', placeholder: 'Book title', list: undefined }, + { key: 'book', label: 'Book', placeholder: 'Book title', list: 'rv-books' }, { key: 'chapter', label: 'Chapter', placeholder: 'Chapter', list: 'rv-chapters' }, { key: 'page', label: 'Page', placeholder: 'Page number', list: undefined }, ].map(({ key, label, placeholder, list }) => ( diff --git a/frontend/src/components/JobsPanel.jsx b/frontend/src/components/JobsPanel.jsx index 73405ea..8d26796 100644 --- a/frontend/src/components/JobsPanel.jsx +++ b/frontend/src/components/JobsPanel.jsx @@ -181,6 +181,9 @@ function JobDetail({ jobId, onClose, onReviewed, suggestions = {} }) { {(suggestions.authors || []).map(a => + + {(suggestions.books || []).map(b => {(suggestions.chapters || []).map(c => @@ -194,7 +197,7 @@ function JobDetail({ jobId, onClose, onReviewed, suggestions = {} }) {
- setEditBook(e.target.value)} placeholder="Book title" className={INPUT_CLASS} /> + setEditBook(e.target.value)} placeholder="Book title" className={INPUT_CLASS} />
@@ -355,6 +358,9 @@ export default function JobsPanel() { {suggestions.authors.map(a => + + {(suggestions.books || []).map(b =>
setFilterAuthor(e.target.value)} placeholder="Author..." className={INPUT_CLASS} /> - setFilterBook(e.target.value)} placeholder="Book..." className={INPUT_CLASS} /> + setFilterBook(e.target.value)} placeholder="Book..." className={INPUT_CLASS} />
diff --git a/frontend/src/components/MetadataForm.jsx b/frontend/src/components/MetadataForm.jsx index b028890..232b119 100644 --- a/frontend/src/components/MetadataForm.jsx +++ b/frontend/src/components/MetadataForm.jsx @@ -2,7 +2,7 @@ import { BookOpen } from 'lucide-react' export default function MetadataForm({ metadata, onChange, suggestions = {} }) { const { author, book, chapter, page } = metadata - const { authors = [], chapters = [] } = suggestions + const { authors = [], books = [], chapters = [] } = suggestions const field = (key) => (e) => onChange({ ...metadata, [key]: e.target.value }) @@ -20,6 +20,9 @@ export default function MetadataForm({ metadata, onChange, suggestions = {} }) { {authors.map(a => + + {books.map(b => {chapters.map(c => @@ -40,6 +43,7 @@ export default function MetadataForm({ metadata, onChange, suggestions = {} }) { { fetch(`${API_BASE}/jobs/suggestions`)