Localize /[locale]/search page via next-intl; translate UI strings, filters, statuses; use bookTranslations to render book labels by locale; keep DB filters steady; support popular searches per locale.
This commit is contained in:
@@ -34,6 +34,8 @@ import {
|
|||||||
History,
|
History,
|
||||||
} from '@mui/icons-material'
|
} from '@mui/icons-material'
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
|
import { useTranslations, useLocale } from 'next-intl'
|
||||||
|
import { translateBookName } from '@/lib/book-translations'
|
||||||
|
|
||||||
interface SearchResult {
|
interface SearchResult {
|
||||||
id: string
|
id: string
|
||||||
@@ -52,6 +54,8 @@ interface SearchFilter {
|
|||||||
|
|
||||||
export default function SearchPage() {
|
export default function SearchPage() {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
const t = useTranslations('pages.search')
|
||||||
|
const locale = useLocale()
|
||||||
const [searchQuery, setSearchQuery] = useState('')
|
const [searchQuery, setSearchQuery] = useState('')
|
||||||
const [results, setResults] = useState<SearchResult[]>([])
|
const [results, setResults] = useState<SearchResult[]>([])
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
@@ -74,10 +78,7 @@ export default function SearchPage() {
|
|||||||
'Filipeni', 'Coloseni', 'Evrei', 'Iacob', '1 Petru', 'Apocalipsa'
|
'Filipeni', 'Coloseni', 'Evrei', 'Iacob', '1 Petru', 'Apocalipsa'
|
||||||
]
|
]
|
||||||
|
|
||||||
const popularSearches = [
|
const popularSearches: string[] = t.raw('popular.items')
|
||||||
'dragoste', 'credință', 'speranță', 'iertare', 'pace',
|
|
||||||
'rugăciune', 'înțelepciune', 'bucurie', 'răbdare', 'milostivire'
|
|
||||||
]
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Load search history from localStorage
|
// Load search history from localStorage
|
||||||
@@ -181,10 +182,10 @@ export default function SearchPage() {
|
|||||||
<Box sx={{ mb: 4, textAlign: 'center' }}>
|
<Box sx={{ mb: 4, textAlign: 'center' }}>
|
||||||
<Typography variant="h3" component="h1" gutterBottom>
|
<Typography variant="h3" component="h1" gutterBottom>
|
||||||
<Search sx={{ fontSize: 40, mr: 2, verticalAlign: 'middle' }} />
|
<Search sx={{ fontSize: 40, mr: 2, verticalAlign: 'middle' }} />
|
||||||
Căutare în Scriptură
|
{t('title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" color="text.secondary">
|
<Typography variant="body1" color="text.secondary">
|
||||||
Găsește rapid versete și pasaje din întreaga Biblie
|
{t('subtitle')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -197,29 +198,29 @@ export default function SearchPage() {
|
|||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
||||||
<Typography variant="h6">
|
<Typography variant="h6">
|
||||||
<FilterList sx={{ mr: 1, verticalAlign: 'middle' }} />
|
<FilterList sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||||
Filtre
|
{t('filters.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button size="small" onClick={clearFilters}>
|
<Button size="small" onClick={clearFilters}>
|
||||||
Șterge
|
{t('filters.clear')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<FormControl fullWidth sx={{ mb: 2 }}>
|
<FormControl fullWidth sx={{ mb: 2 }}>
|
||||||
<InputLabel>Testament</InputLabel>
|
<InputLabel>{t('filters.testament')}</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
value={filters.testament}
|
value={filters.testament}
|
||||||
label="Testament"
|
label={t('filters.testament')}
|
||||||
onChange={(e) => setFilters({ ...filters, testament: e.target.value as any })}
|
onChange={(e) => setFilters({ ...filters, testament: e.target.value as any })}
|
||||||
>
|
>
|
||||||
<MenuItem value="all">Toată Biblia</MenuItem>
|
<MenuItem value="all">{t('filters.options.all')}</MenuItem>
|
||||||
<MenuItem value="old">Vechiul Testament</MenuItem>
|
<MenuItem value="old">{t('filters.options.old')}</MenuItem>
|
||||||
<MenuItem value="new">Noul Testament</MenuItem>
|
<MenuItem value="new">{t('filters.options.new')}</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<Accordion>
|
<Accordion>
|
||||||
<AccordionSummary expandIcon={<ExpandMore />}>
|
<AccordionSummary expandIcon={<ExpandMore />}>
|
||||||
<Typography variant="body2">Cărți specifice</Typography>
|
<Typography variant="body2">{t('filters.specificBooks')}</Typography>
|
||||||
</AccordionSummary>
|
</AccordionSummary>
|
||||||
<AccordionDetails>
|
<AccordionDetails>
|
||||||
<Box sx={{ maxHeight: 200, overflow: 'auto' }}>
|
<Box sx={{ maxHeight: 200, overflow: 'auto' }}>
|
||||||
@@ -228,7 +229,7 @@ export default function SearchPage() {
|
|||||||
.map((book) => (
|
.map((book) => (
|
||||||
<Chip
|
<Chip
|
||||||
key={book}
|
key={book}
|
||||||
label={book}
|
label={translateBookName(book, locale)}
|
||||||
size="small"
|
size="small"
|
||||||
variant={filters.books.includes(book) ? 'filled' : 'outlined'}
|
variant={filters.books.includes(book) ? 'filled' : 'outlined'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -252,7 +253,7 @@ export default function SearchPage() {
|
|||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
<History sx={{ mr: 1, verticalAlign: 'middle' }} />
|
<History sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||||
Căutări recente
|
{t('history.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
{searchHistory.slice(0, 5).map((query, index) => (
|
{searchHistory.slice(0, 5).map((query, index) => (
|
||||||
<Chip
|
<Chip
|
||||||
@@ -272,7 +273,7 @@ export default function SearchPage() {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
Căutări populare
|
{t('popular.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
{popularSearches.map((query, index) => (
|
{popularSearches.map((query, index) => (
|
||||||
<Chip
|
<Chip
|
||||||
@@ -297,7 +298,7 @@ export default function SearchPage() {
|
|||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="Caută cuvinte, fraze sau referințe biblice..."
|
placeholder={t('input.placeholder')}
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
onKeyPress={handleKeyPress}
|
onKeyPress={handleKeyPress}
|
||||||
@@ -325,14 +326,14 @@ export default function SearchPage() {
|
|||||||
disabled={!searchQuery.trim() || loading}
|
disabled={!searchQuery.trim() || loading}
|
||||||
sx={{ minWidth: 100 }}
|
sx={{ minWidth: 100 }}
|
||||||
>
|
>
|
||||||
{loading ? <CircularProgress size={20} color="inherit" /> : 'Caută'}
|
{loading ? <CircularProgress size={20} color="inherit" /> : t('button.search')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{filters.books.length > 0 && (
|
{filters.books.length > 0 && (
|
||||||
<Box sx={{ mt: 2 }}>
|
<Box sx={{ mt: 2 }}>
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||||
Căutare în: {filters.books.join(', ')}
|
{t('searchIn', { books: filters.books.map(b => translateBookName(b, locale)).join(', ') })}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
@@ -344,7 +345,7 @@ export default function SearchPage() {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
Se caută...
|
{t('searching')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<List>
|
<List>
|
||||||
{Array.from({ length: 3 }).map((_, index) => (
|
{Array.from({ length: 3 }).map((_, index) => (
|
||||||
@@ -375,7 +376,7 @@ export default function SearchPage() {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
Rezultate ({results.length})
|
{t('results', { count: results.length })}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
@@ -388,7 +389,7 @@ export default function SearchPage() {
|
|||||||
{result.book} {result.chapter}:{result.verse}
|
{result.book} {result.chapter}:{result.verse}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Chip
|
<Chip
|
||||||
label={`${Math.round(result.relevance * 100)}% relevanță`}
|
label={`${Math.round(result.relevance * 100)}% ${t('relevance')}`}
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -411,10 +412,10 @@ export default function SearchPage() {
|
|||||||
{!loading && searchQuery && results.length === 0 && (
|
{!loading && searchQuery && results.length === 0 && (
|
||||||
<Paper sx={{ p: 4, textAlign: 'center' }}>
|
<Paper sx={{ p: 4, textAlign: 'center' }}>
|
||||||
<Typography variant="h6" color="text.secondary" gutterBottom>
|
<Typography variant="h6" color="text.secondary" gutterBottom>
|
||||||
Nu s-au găsit rezultate
|
{t('noResults.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="text.secondary">
|
<Typography variant="body2" color="text.secondary">
|
||||||
Încearcă să modifici termenul de căutare sau să ajustezi filtrele.
|
{t('noResults.description')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
)}
|
)}
|
||||||
@@ -423,10 +424,10 @@ export default function SearchPage() {
|
|||||||
<Paper sx={{ p: 4, textAlign: 'center' }}>
|
<Paper sx={{ p: 4, textAlign: 'center' }}>
|
||||||
<MenuBook sx={{ fontSize: 64, color: 'text.secondary', mb: 2 }} />
|
<MenuBook sx={{ fontSize: 64, color: 'text.secondary', mb: 2 }} />
|
||||||
<Typography variant="h6" color="text.secondary" gutterBottom>
|
<Typography variant="h6" color="text.secondary" gutterBottom>
|
||||||
Începe să cauți în Scriptură
|
{t('empty.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="text.secondary">
|
<Typography variant="body2" color="text.secondary">
|
||||||
Introdu un cuvânt, o frază sau o referință biblică pentru a găsi versete relevante.
|
{t('empty.description')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
)}
|
)}
|
||||||
@@ -435,4 +436,4 @@ export default function SearchPage() {
|
|||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,10 +143,55 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search Scripture",
|
||||||
"placeholder": "Search the Bible...",
|
"subtitle": "Find verses and passages across the Bible",
|
||||||
"results": "Results",
|
"input": {
|
||||||
"noResults": "No results found"
|
"placeholder": "Search words, phrases or references..."
|
||||||
|
},
|
||||||
|
"button": {
|
||||||
|
"search": "Search"
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"title": "Filters",
|
||||||
|
"clear": "Clear",
|
||||||
|
"testament": "Testament",
|
||||||
|
"options": {
|
||||||
|
"all": "Whole Bible",
|
||||||
|
"old": "Old Testament",
|
||||||
|
"new": "New Testament"
|
||||||
|
},
|
||||||
|
"specificBooks": "Specific books"
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"title": "Recent searches"
|
||||||
|
},
|
||||||
|
"popular": {
|
||||||
|
"title": "Popular searches",
|
||||||
|
"items": [
|
||||||
|
"love",
|
||||||
|
"faith",
|
||||||
|
"hope",
|
||||||
|
"forgiveness",
|
||||||
|
"peace",
|
||||||
|
"prayer",
|
||||||
|
"wisdom",
|
||||||
|
"joy",
|
||||||
|
"patience",
|
||||||
|
"mercy"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"searching": "Searching...",
|
||||||
|
"results": "Results ({count})",
|
||||||
|
"relevance": "relevance",
|
||||||
|
"searchIn": "Searching in: {books}",
|
||||||
|
"noResults": {
|
||||||
|
"title": "No results found",
|
||||||
|
"description": "Try changing the search term or adjusting the filters."
|
||||||
|
},
|
||||||
|
"empty": {
|
||||||
|
"title": "Start searching Scripture",
|
||||||
|
"description": "Enter a word, a phrase, or a Bible reference to find relevant verses."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|||||||
@@ -143,10 +143,55 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Căutare",
|
"title": "Căutare în Scriptură",
|
||||||
"placeholder": "Caută în Biblie...",
|
"subtitle": "Găsește versete și pasaje din întreaga Biblie",
|
||||||
"results": "Rezultate",
|
"input": {
|
||||||
"noResults": "Nu s-au găsit rezultate"
|
"placeholder": "Caută cuvinte, fraze sau referințe biblice..."
|
||||||
|
},
|
||||||
|
"button": {
|
||||||
|
"search": "Caută"
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"title": "Filtre",
|
||||||
|
"clear": "Șterge",
|
||||||
|
"testament": "Testament",
|
||||||
|
"options": {
|
||||||
|
"all": "Toată Biblia",
|
||||||
|
"old": "Vechiul Testament",
|
||||||
|
"new": "Noul Testament"
|
||||||
|
},
|
||||||
|
"specificBooks": "Cărți specifice"
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"title": "Căutări recente"
|
||||||
|
},
|
||||||
|
"popular": {
|
||||||
|
"title": "Căutări populare",
|
||||||
|
"items": [
|
||||||
|
"dragoste",
|
||||||
|
"credință",
|
||||||
|
"speranță",
|
||||||
|
"iertare",
|
||||||
|
"pace",
|
||||||
|
"rugăciune",
|
||||||
|
"înțelepciune",
|
||||||
|
"bucurie",
|
||||||
|
"răbdare",
|
||||||
|
"milostivire"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"searching": "Se caută...",
|
||||||
|
"results": "Rezultate ({count})",
|
||||||
|
"relevance": "relevanță",
|
||||||
|
"searchIn": "Căutare în: {books}",
|
||||||
|
"noResults": {
|
||||||
|
"title": "Nu s-au găsit rezultate",
|
||||||
|
"description": "Încearcă să modifici termenul de căutare sau să ajustezi filtrele."
|
||||||
|
},
|
||||||
|
"empty": {
|
||||||
|
"title": "Începe să cauți în Scriptură",
|
||||||
|
"description": "Introdu un cuvânt, o frază sau o referință biblică pentru a găsi versete relevante."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|||||||
Reference in New Issue
Block a user