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:
@@ -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)
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
disabled={versionsLoading}
|
}}
|
||||||
MenuProps={{
|
options={versions}
|
||||||
PaperProps: {
|
getOptionLabel={(option) => `${option.name} - ${option.abbreviation}`}
|
||||||
style: {
|
renderInput={(params) => (
|
||||||
maxHeight: 400,
|
<TextField
|
||||||
},
|
{...params}
|
||||||
},
|
label={t('version')}
|
||||||
}}
|
placeholder="Search versions..."
|
||||||
>
|
/>
|
||||||
{versions.map((version) => (
|
)}
|
||||||
<MenuItem key={version.id} value={version.id}>
|
renderOption={(props, option) => (
|
||||||
{version.abbreviation} - {version.name} ({version.language.toUpperCase()})
|
<Box component="li" {...props}>
|
||||||
</MenuItem>
|
<Box>
|
||||||
))}
|
<Typography variant="body2" sx={{ fontWeight: 'medium' }}>
|
||||||
</Select>
|
{option.name}
|
||||||
</FormControl>
|
</Typography>
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
{option.abbreviation} • {option.language.toUpperCase()}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
disabled={versionsLoading}
|
||||||
|
loading={versionsLoading}
|
||||||
|
filterOptions={(options, { inputValue }) => {
|
||||||
|
const filtered = options.filter((option) =>
|
||||||
|
option.name.toLowerCase().includes(inputValue.toLowerCase()) ||
|
||||||
|
option.abbreviation.toLowerCase().includes(inputValue.toLowerCase()) ||
|
||||||
|
option.language.toLowerCase().includes(inputValue.toLowerCase())
|
||||||
|
)
|
||||||
|
return filtered
|
||||||
|
}}
|
||||||
|
ListboxProps={{
|
||||||
|
style: { maxHeight: 400 }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<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)
|
||||||
}}
|
}
|
||||||
>
|
}}
|
||||||
{books.map((book) => (
|
options={books}
|
||||||
<MenuItem key={book.id} value={book.id}>
|
getOptionLabel={(option) => option.name}
|
||||||
{book.name}
|
renderInput={(params) => (
|
||||||
</MenuItem>
|
<TextField
|
||||||
))}
|
{...params}
|
||||||
</Select>
|
label={t('book')}
|
||||||
</FormControl>
|
placeholder="Search books..."
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
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 */}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user