// Main layout for gallery page.
import { useCallback, useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Link as RouterLink } from 'react-router-dom'
import PropTypes from 'prop-types'
import {
Button,
Card,
CardActionArea,
CardActions,
CardContent,
CardMedia,
Container,
CssBaseline,
FormControl,
Grid,
Input,
InputLabel,
MenuItem,
Select,
Typography
} from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import { fetchGallery } from '../redux/dashboardSlice'
import api from '../utils/Api'
const useStyles = makeStyles((theme) => ({
mainHead: {
width: '100%',
backgroundColor: '#404040',
color: '#fff'
},
title: {
fontSize: 18,
color: '#80ff80'
},
header: {
padding: theme.spacing(5, 0, 6, 0)
},
root: {
display: 'flex',
minHeight: '100vh',
backgroundColor: '#f4f6f8'
},
media: {
marginTop: theme.spacing(3),
height: 170
}
}))
const images = require.context('../static/gallery', true)
// Card displaying overview of gallery sample schematics.
const SchematicCard = ({ sch }) => {
const classes = useStyles()
useEffect(() => {
document.title = 'Gallery - ' + process.env.REACT_APP_NAME
}, [])
const imageName = images('./' + sch.media)
return (
<>
{sch.name}
{sch.description}
>
)
}
SchematicCard.propTypes = {
sch: PropTypes.object
}
// Card displaying gallery page header.
const MainCard = () => {
const classes = useStyles()
const typography = process.env.REACT_APP_NAME + ' Gallery'
const diagramTypography = 'Sample ' + process.env.REACT_APP_SMALL_DIAGRAMS_NAME + ' are listed below...'
return (
{typography}
{diagramTypography}
)
}
const BookDropdown = ({ onBookChange }) => {
const [books, setBooks] = useState([]) // To store books from the backend
const [selectedBook, setSelectedBook] = useState('')
// Fetch books from the backend (optional, or use static data)
const fetchBooks = useCallback(() => {
api.get('save/books')
.then((res) => {
if (res.status !== 200) {
throw new Error(`HTTP error! Status: ${res.status}`)
}
setBooks(res.data) // Assuming the API returns an array of books
})
.catch(err => { console.error('Error fetching books:', err) })
}, [])
useEffect(() => {
fetchBooks()
return () => { setBooks([]) }
}, [fetchBooks])
// Handle dropdown selection change
const handleChange = (evt) => {
const selectedValue = evt.target.value
setSelectedBook(selectedValue)
onBookChange(selectedValue) // Notify the parent component
}
return (
Book
)
}
BookDropdown.propTypes = {
onBookChange: PropTypes.func.isRequired
}
const SearchComponent = ({ onSearch }) => {
const [searchTerm, setSearchTerm] = useState('')
const handleSearch = (event) => {
const value = event.target.value.trimStart()
setSearchTerm(value)
onSearch(value)
}
return (
Search
)
}
SearchComponent.propTypes = {
onSearch: PropTypes.func.isRequired
}
const Gallery = () => {
const classes = useStyles()
const GallerySchSample = useSelector(state => state.dashboard.gallery)
// State to store the selected book ID
const [selectedBook, setSelectedBook] = useState('')
const [searchTerm, setSearchTerm] = useState('')
const dispatch = useDispatch()
useEffect(() => {
dispatch(fetchGallery())
}, [dispatch])
// Handle dropdown selection change
const handleBookChange = (book) => {
setSelectedBook(book)
}
// Handle search term change
const handleSearch = (term) => {
setSearchTerm(term)
}
const filteredSchematics =
(() => {
if (!selectedBook) return []
if (selectedBook === 'all') return GallerySchSample
const selectedBookId = Number(selectedBook)
return GallerySchSample.filter((sch) => sch.book_id === selectedBookId)
})()
const NOBLOCK = /^no./
const SCE = /^(sce|sci|script)/
const NOSCE = /^no(sce|sci|script)/
const terms = searchTerm.trim().toLowerCase().split(/\s+/).filter(Boolean)
// Then, filter based on the search term (independent from book selection)
const finalfilteredSchematics =
terms.length === 0
? filteredSchematics
: filteredSchematics.filter((sch) => {
return terms.every((st) =>
sch.lcname.includes(st) ||
sch.lcdescription.includes(st) ||
(!NOBLOCK.test(st) && (';' + sch.blocks).includes(';' + st)) ||
(NOBLOCK.test(st) && !(';' + sch.blocks + ';').includes(';' + st.substring(2) + ';')) ||
sch.save_id.startsWith('gallery' + st) ||
(SCE.test(st) && sch.has_script) ||
(NOSCE.test(st) && !sch.has_script)
)
})
return (
{/* Gallery Header */}
{/* BookDropdown */}
{/* SearchComponent */}
{/* Display a message or blank gallery */}
{
finalfilteredSchematics.length === 0
? `No ${process.env.REACT_APP_SMALL_DIAGRAMS_NAME} to display. ${selectedBook === ''
? 'Please select a book.'
: selectedBook === 'all'
? 'Please try another search term.'
: 'Please select another book or try another search term.'
}`
: `${finalfilteredSchematics.length} ${finalfilteredSchematics.length !== 1
? `${process.env.REACT_APP_SMALL_DIAGRAMS_NAME}`
: `${process.env.REACT_APP_SMALL_DIAGRAM_NAME}`}`
}
{
finalfilteredSchematics.map((sch) => (
))
}
)
}
export default Gallery