leumas-private-shared
Version:
Private React JSX Package For Leumas Shared Components, Headers, Footers, Asides, Login Pages, API Key Manager and much more. Styles and everything reusable to avoid DRY code across all of our subdomains
133 lines (121 loc) • 4.82 kB
JSX
import React, { useState } from 'react';
import { Container, Grid, Card, CardContent, CardMedia, Typography, Button, Box, Tabs, Tab, Pagination } from '@mui/material';
const Gallery = ({ images, frequencyData, audioPlaying, strobeMode }) => {
const [activeCategory, setActiveCategory] = useState('All');
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 12;
// Derive categories from images
const categories = ['All', ...new Set(images.map(image => image.category))];
// Filter images based on the active category
const filteredImages = images.filter(image =>
activeCategory === 'All' || image.category === activeCategory
);
// Paginate images
const paginatedImages = filteredImages.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
const handleCategoryChange = (event, newValue) => {
setActiveCategory(newValue);
setCurrentPage(1); // Reset to the first page when the category changes
};
const handlePageChange = (event, value) => {
setCurrentPage(value);
};
// Function to get the border style based on the frequency data
const getBorderStyle = (index) => {
if (audioPlaying && frequencyData && frequencyData.length > 0) {
const colorIndex = index % frequencyData.length;
const intensity = frequencyData[colorIndex];
const getColor = () => {
if (strobeMode) {
const randomColor = `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255})`;
return randomColor;
}
return `rgba(0, 0, 255, ${intensity / 255})`;
};
return {
borderImage: `linear-gradient(45deg, ${getColor()}, ${getColor()}) 1`,
animation: 'wave 1s infinite',
boxShadow: `0 0 ${intensity / 5}px ${getColor()}`
};
}
return {
border: '3px solid transparent'
};
};
return (
<Container sx={{ py: 4 }}>
<Box sx={{ borderBottom: 1, borderColor: 'divider', mb: 4 }}>
<Tabs
value={activeCategory}
onChange={handleCategoryChange}
variant="scrollable"
scrollButtons="auto"
aria-label="gallery categories"
>
{categories.map((category, index) => (
<Tab key={index} label={category} value={category} />
))}
</Tabs>
</Box>
<Grid container spacing={2}>
{paginatedImages.map((image, index) => (
<Grid item key={index} xs={12} sm={6} md={4}>
<Card
sx={{
cursor: 'pointer',
display: 'flex',
flexDirection: 'column',
borderRadius: '8px',
transition: 'transform 0.3s, box-shadow 0.3s, border-color 0.5s ease, border-width 0.5s ease',
':hover': {
transform: 'scale(1.05)',
boxShadow: '0 8px 16px rgba(0, 0, 0, 0.3)'
},
...getBorderStyle(index),
'@keyframes wave': {
'0%': { borderImage: `linear-gradient(45deg, rgba(0, 0, 255, 0.1), rgba(0, 0, 128, 0.1)) 1` },
'50%': { borderImage: `linear-gradient(45deg, rgba(0, 0, 255, 1), rgba(0, 0, 128, 1)) 1` },
'100%': { borderImage: `linear-gradient(45deg, rgba(0, 0, 255, 0.1), rgba(0, 0, 128, 0.1)) 1` },
}
}}
>
<CardMedia
component="img"
sx={{
pt: 0, // Ensure the image starts at the top
height: '180px' // Set a fixed height for the images
}}
image={image.src}
alt={image.title}
/>
<CardContent sx={{ flexGrow: 1 }}>
<Typography gutterBottom variant="h5" component="h2">
{image.title.substring(0,22)}...
</Typography>
</CardContent>
<Box sx={{ p: 2, textAlign: 'center' }}>
<Button
variant="contained"
color="primary"
href={image.link}
target="_blank"
rel="noopener noreferrer"
>
Learn More
</Button>
</Box>
</Card>
</Grid>
))}
</Grid>
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 4 }}>
<Pagination
count={Math.ceil(filteredImages.length / itemsPerPage)}
page={currentPage}
onChange={handlePageChange}
color="primary"
/>
</Box>
</Container>
);
};
export default Gallery;