Search filters now backed by DB per locale/version: fetch books from /api/bible/books; send bookKeys + locale to API; API constrains by versionId and bookKey/name; keeps testament filter.

This commit is contained in:
andupetcu
2025-09-20 18:10:50 +03:00
parent 0f31dfca8e
commit a1b92be2a5
2 changed files with 89 additions and 44 deletions

View File

@@ -35,7 +35,6 @@ import {
} from '@mui/icons-material'
import { useState, useEffect } from 'react'
import { useTranslations, useLocale } from 'next-intl'
import { translateBookName } from '@/lib/book-translations'
interface SearchResult {
id: string
@@ -48,10 +47,18 @@ interface SearchResult {
interface SearchFilter {
testament: 'all' | 'old' | 'new'
books: string[]
bookKeys: string[]
exactMatch: boolean
}
interface BookOption {
id: string
name: string
bookKey: string
orderNum: number
testament: string
}
export default function SearchPage() {
const theme = useTheme()
const t = useTranslations('pages.search')
@@ -60,23 +67,11 @@ export default function SearchPage() {
const [results, setResults] = useState<SearchResult[]>([])
const [loading, setLoading] = useState(false)
const [searchHistory, setSearchHistory] = useState<string[]>([])
const [filters, setFilters] = useState<SearchFilter>({
testament: 'all',
books: [],
exactMatch: false,
})
const [filters, setFilters] = useState<SearchFilter>({ testament: 'all', bookKeys: [], exactMatch: false })
const [booksData, setBooksData] = useState<BookOption[]>([])
const oldTestamentBooks = [
'Geneza', 'Exodul', 'Leviticul', 'Numerii', 'Deuteronomul',
'Iosua', 'Judecătorii', 'Rut', '1 Samuel', '2 Samuel',
'Psalmii', 'Proverbele', 'Isaia', 'Ieremia', 'Daniel'
]
const newTestamentBooks = [
'Matei', 'Marcu', 'Luca', 'Ioan', 'Faptele Apostolilor',
'Romani', '1 Corinteni', '2 Corinteni', 'Galateni', 'Efeseni',
'Filipeni', 'Coloseni', 'Evrei', 'Iacob', '1 Petru', 'Apocalipsa'
]
const oldTestamentBooks = booksData.filter(b => b.orderNum <= 39)
const newTestamentBooks = booksData.filter(b => b.orderNum > 39)
const popularSearches: string[] = t.raw('popular.items')
@@ -88,6 +83,23 @@ export default function SearchPage() {
}
}, [])
useEffect(() => {
// Fetch available books for current locale/version
fetch(`/api/bible/books?locale=${locale}`)
.then(res => res.json())
.then(data => {
const mapped: BookOption[] = (data.books || []).map((b: any) => ({
id: b.id,
name: b.name,
bookKey: b.bookKey,
orderNum: b.orderNum,
testament: b.testament,
}))
setBooksData(mapped)
})
.catch(() => setBooksData([]))
}, [locale])
const handleSearch = async () => {
if (!searchQuery.trim()) return
@@ -103,7 +115,8 @@ export default function SearchPage() {
q: searchQuery,
testament: filters.testament,
exactMatch: filters.exactMatch.toString(),
books: filters.books.join(','),
bookKeys: filters.bookKeys.join(','),
locale,
})
const response = await fetch(`/api/search/verses?${params}`)
@@ -228,15 +241,16 @@ export default function SearchPage() {
.concat(filters.testament === 'new' || filters.testament === 'all' ? newTestamentBooks : [])
.map((book) => (
<Chip
key={book}
label={translateBookName(book, locale)}
key={book.bookKey}
label={book.name}
size="small"
variant={filters.books.includes(book) ? 'filled' : 'outlined'}
variant={filters.bookKeys.includes(book.bookKey) ? 'filled' : 'outlined'}
onClick={() => {
const newBooks = filters.books.includes(book)
? filters.books.filter(b => b !== book)
: [...filters.books, book]
setFilters({ ...filters, books: newBooks })
const exists = filters.bookKeys.includes(book.bookKey)
const newBookKeys = exists
? filters.bookKeys.filter(b => b !== book.bookKey)
: [...filters.bookKeys, book.bookKey]
setFilters({ ...filters, bookKeys: newBookKeys })
}}
sx={{ mb: 0.5, mr: 0.5 }}
/>
@@ -330,10 +344,10 @@ export default function SearchPage() {
</Button>
</Box>
{filters.books.length > 0 && (
{filters.bookKeys.length > 0 && (
<Box sx={{ mt: 2 }}>
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
{t('searchIn', { books: filters.books.map(b => translateBookName(b, locale)).join(', ') })}
{t('searchIn', { books: filters.bookKeys.map(k => booksData.find(b => b.bookKey === k)?.name || k).join(', ') })}
</Typography>
</Box>
)}