Add search functionality to version and book dropdowns

- Replace Select components with Autocomplete for enhanced UX
- Add real-time search for bible versions (1400+ options)
- Enable book search by name or testament
- Improve version display format: "Name - Abbreviation"
- Add rich option rendering with metadata (language, chapters)
- Include smart filtering across multiple fields
- Maintain keyboard navigation and accessibility
- Fix header visibility issue in full screen mode

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-24 13:05:22 +00:00
parent ebd2519974
commit 6329ad0618
2 changed files with 96 additions and 44 deletions

View File

@@ -44,7 +44,8 @@ import {
FormControl, FormControl,
InputLabel, InputLabel,
Select, Select,
Container Container,
Autocomplete
} from '@mui/material' } from '@mui/material'
import { import {
Menu as MenuIcon, Menu as MenuIcon,
@@ -703,36 +704,56 @@ export default function BibleReaderNew() {
{/* Version Selection */} {/* Version Selection */}
<Box sx={{ flex: { xs: '1 1 100%', sm: '1 1 auto' }, minWidth: { sm: 180, md: 200 } }}> <Box sx={{ flex: { xs: '1 1 100%', sm: '1 1 auto' }, minWidth: { sm: 180, md: 200 } }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}> <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<FormControl fullWidth size="small"> <Autocomplete
<InputLabel>{t('version')}</InputLabel> size="small"
<Select fullWidth
value={selectedVersion} value={versions.find(v => v.id === selectedVersion) || null}
label={t('version')} onChange={(event, newValue) => {
onChange={(e) => { if (newValue) {
setSelectedVersion(e.target.value) setSelectedVersion(newValue.id)
// Reset to first book when version changes // Reset to first book when version changes
if (books.length > 0) { if (books.length > 0) {
setSelectedBook(books[0].id) setSelectedBook(books[0].id)
setSelectedChapter(1) setSelectedChapter(1)
updateUrl(books[0].id, 1, e.target.value) updateUrl(books[0].id, 1, newValue.id)
}
} }
}} }}
options={versions}
getOptionLabel={(option) => `${option.name} - ${option.abbreviation}`}
renderInput={(params) => (
<TextField
{...params}
label={t('version')}
placeholder="Search versions..."
/>
)}
renderOption={(props, option) => (
<Box component="li" {...props}>
<Box>
<Typography variant="body2" sx={{ fontWeight: 'medium' }}>
{option.name}
</Typography>
<Typography variant="caption" color="text.secondary">
{option.abbreviation} {option.language.toUpperCase()}
</Typography>
</Box>
</Box>
)}
disabled={versionsLoading} disabled={versionsLoading}
MenuProps={{ loading={versionsLoading}
PaperProps: { filterOptions={(options, { inputValue }) => {
style: { const filtered = options.filter((option) =>
maxHeight: 400, option.name.toLowerCase().includes(inputValue.toLowerCase()) ||
}, option.abbreviation.toLowerCase().includes(inputValue.toLowerCase()) ||
}, option.language.toLowerCase().includes(inputValue.toLowerCase())
)
return filtered
}} }}
> ListboxProps={{
{versions.map((version) => ( style: { maxHeight: 400 }
<MenuItem key={version.id} value={version.id}> }}
{version.abbreviation} - {version.name} ({version.language.toUpperCase()}) />
</MenuItem>
))}
</Select>
</FormControl>
<Tooltip title={showAllVersions ? 'Show language versions only' : 'Show all versions'}> <Tooltip title={showAllVersions ? 'Show language versions only' : 'Show all versions'}>
<IconButton <IconButton
size="small" size="small"
@@ -747,24 +768,48 @@ export default function BibleReaderNew() {
{/* Books Selection */} {/* Books Selection */}
<Box sx={{ flex: { xs: '1 1 100%', sm: '1 1 auto' }, minWidth: { sm: 200, md: 250 } }}> <Box sx={{ flex: { xs: '1 1 100%', sm: '1 1 auto' }, minWidth: { sm: 200, md: 250 } }}>
<FormControl fullWidth size="small"> <Autocomplete
<InputLabel>{t('book')}</InputLabel> size="small"
<Select fullWidth
value={selectedBook} value={books.find(b => b.id === selectedBook) || null}
label={t('book')} onChange={(event, newValue) => {
onChange={(e) => { if (newValue) {
setSelectedBook(e.target.value) setSelectedBook(newValue.id)
setSelectedChapter(1) setSelectedChapter(1)
updateUrl(e.target.value, 1, selectedVersion) updateUrl(newValue.id, 1, selectedVersion)
}
}} }}
> options={books}
{books.map((book) => ( getOptionLabel={(option) => option.name}
<MenuItem key={book.id} value={book.id}> renderInput={(params) => (
{book.name} <TextField
</MenuItem> {...params}
))} label={t('book')}
</Select> placeholder="Search books..."
</FormControl> />
)}
renderOption={(props, option) => (
<Box component="li" {...props}>
<Box>
<Typography variant="body2" sx={{ fontWeight: 'medium' }}>
{option.name}
</Typography>
<Typography variant="caption" color="text.secondary">
{option.testament} {option.chapters?.length || 0} chapters
</Typography>
</Box>
</Box>
)}
filterOptions={(options, { inputValue }) => {
return options.filter((option) =>
option.name.toLowerCase().includes(inputValue.toLowerCase()) ||
option.testament.toLowerCase().includes(inputValue.toLowerCase())
)
}}
ListboxProps={{
style: { maxHeight: 300 }
}}
/>
</Box> </Box>
{/* Chapter Selection */} {/* Chapter Selection */}

View File

@@ -28,12 +28,19 @@ body {
} }
/* Bible Reader Full Screen Mode - Hide only site-level elements */ /* Bible Reader Full Screen Mode - Hide only site-level elements */
.bible-fullscreen-mode .MuiAppBar-root:first-child, .bible-fullscreen-mode header,
.bible-fullscreen-mode nav,
.bible-fullscreen-mode .MuiAppBar-root,
.bible-fullscreen-mode footer, .bible-fullscreen-mode footer,
.bible-fullscreen-mode [data-floating-chat="true"] { .bible-fullscreen-mode [data-floating-chat="true"] {
display: none !important; display: none !important;
} }
/* Exception: Keep bible reader's internal navigation visible */
.bible-fullscreen-mode .MuiContainer-root .MuiPaper-root {
display: block !important;
}
.bible-fullscreen-mode { .bible-fullscreen-mode {
overflow: auto; overflow: auto;
} }