Add version selector to /[locale]/search: new /api/bible/versions endpoint; fetch versions per locale; refetch books on version change; pass version to search API; localized label.

This commit is contained in:
andupetcu
2025-09-20 18:13:13 +03:00
parent a1b92be2a5
commit df0eb6661f
4 changed files with 73 additions and 2 deletions

View File

@@ -69,6 +69,8 @@ export default function SearchPage() {
const [searchHistory, setSearchHistory] = useState<string[]>([]) const [searchHistory, setSearchHistory] = useState<string[]>([])
const [filters, setFilters] = useState<SearchFilter>({ testament: 'all', bookKeys: [], exactMatch: false }) const [filters, setFilters] = useState<SearchFilter>({ testament: 'all', bookKeys: [], exactMatch: false })
const [booksData, setBooksData] = useState<BookOption[]>([]) const [booksData, setBooksData] = useState<BookOption[]>([])
const [versions, setVersions] = useState<Array<{ id: string; name: string; abbreviation: string; isDefault: boolean }>>([])
const [selectedVersion, setSelectedVersion] = useState<string>('')
const oldTestamentBooks = booksData.filter(b => b.orderNum <= 39) const oldTestamentBooks = booksData.filter(b => b.orderNum <= 39)
const newTestamentBooks = booksData.filter(b => b.orderNum > 39) const newTestamentBooks = booksData.filter(b => b.orderNum > 39)
@@ -84,8 +86,26 @@ export default function SearchPage() {
}, []) }, [])
useEffect(() => { useEffect(() => {
// Fetch available versions for locale
fetch(`/api/bible/versions?locale=${locale}`)
.then(res => res.json())
.then(data => {
const list = (data.versions || []) as Array<{ id: string; name: string; abbreviation: string; isDefault: boolean }>
setVersions(list)
const def = list.find(v => v.isDefault) || list[0]
setSelectedVersion(def?.abbreviation || '')
})
.catch(() => {
setVersions([])
setSelectedVersion('')
})
}, [locale])
useEffect(() => {
if (!selectedVersion && versions.length === 0) return
// Fetch available books for current locale/version // Fetch available books for current locale/version
fetch(`/api/bible/books?locale=${locale}`) const qs = new URLSearchParams({ locale, ...(selectedVersion ? { version: selectedVersion } : {}) })
fetch(`/api/bible/books?${qs}`)
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {
const mapped: BookOption[] = (data.books || []).map((b: any) => ({ const mapped: BookOption[] = (data.books || []).map((b: any) => ({
@@ -98,7 +118,7 @@ export default function SearchPage() {
setBooksData(mapped) setBooksData(mapped)
}) })
.catch(() => setBooksData([])) .catch(() => setBooksData([]))
}, [locale]) }, [locale, selectedVersion, versions.length])
const handleSearch = async () => { const handleSearch = async () => {
if (!searchQuery.trim()) return if (!searchQuery.trim()) return
@@ -117,6 +137,7 @@ export default function SearchPage() {
exactMatch: filters.exactMatch.toString(), exactMatch: filters.exactMatch.toString(),
bookKeys: filters.bookKeys.join(','), bookKeys: filters.bookKeys.join(','),
locale, locale,
...(selectedVersion ? { version: selectedVersion } : {}),
}) })
const response = await fetch(`/api/search/verses?${params}`) const response = await fetch(`/api/search/verses?${params}`)
@@ -231,6 +252,21 @@ export default function SearchPage() {
</Select> </Select>
</FormControl> </FormControl>
<FormControl fullWidth sx={{ mb: 2 }}>
<InputLabel>{t('filters.version')}</InputLabel>
<Select
value={selectedVersion}
label={t('filters.version')}
onChange={(e) => setSelectedVersion(e.target.value as string)}
>
{versions.map(v => (
<MenuItem key={v.abbreviation} value={v.abbreviation}>
{v.name} ({v.abbreviation})
</MenuItem>
))}
</Select>
</FormControl>
<Accordion> <Accordion>
<AccordionSummary expandIcon={<ExpandMore />}> <AccordionSummary expandIcon={<ExpandMore />}>
<Typography variant="body2">{t('filters.specificBooks')}</Typography> <Typography variant="body2">{t('filters.specificBooks')}</Typography>

View File

@@ -0,0 +1,33 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/db'
export const runtime = 'nodejs'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const locale = (searchParams.get('locale') || 'ro').toLowerCase()
const langCandidates = Array.from(new Set([locale, locale.toLowerCase(), locale.toUpperCase()]))
const versions = await prisma.bibleVersion.findMany({
where: { language: { in: langCandidates } },
orderBy: [{ isDefault: 'desc' }, { name: 'asc' }]
})
return NextResponse.json({
success: true,
versions: versions.map(v => ({
id: v.id,
name: v.name,
abbreviation: v.abbreviation,
language: v.language,
isDefault: v.isDefault,
}))
})
} catch (error) {
console.error('Error fetching versions:', error)
return NextResponse.json({ success: false, versions: [] }, { status: 500 })
}
}

View File

@@ -155,6 +155,7 @@
"title": "Filters", "title": "Filters",
"clear": "Clear", "clear": "Clear",
"testament": "Testament", "testament": "Testament",
"version": "Version",
"options": { "options": {
"all": "Whole Bible", "all": "Whole Bible",
"old": "Old Testament", "old": "Old Testament",

View File

@@ -155,6 +155,7 @@
"title": "Filtre", "title": "Filtre",
"clear": "Șterge", "clear": "Șterge",
"testament": "Testament", "testament": "Testament",
"version": "Versiune",
"options": { "options": {
"all": "Toată Biblia", "all": "Toată Biblia",
"old": "Vechiul Testament", "old": "Vechiul Testament",