add gallery
This commit is contained in:
+356
-93
@@ -1,93 +1,356 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import axios from 'axios'
|
||||
import AppContainer from './appContainer'
|
||||
import { AppFile, AppUrl } from '../lib/api'
|
||||
import Image from 'next/image'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Suspense } from 'react'
|
||||
|
||||
import { MDBBtn, MDBCol, MDBContainer, MDBRow } from 'mdb-react-ui-kit'
|
||||
import { LightBox } from 'react-lightbox-pack'
|
||||
import { Button, Divider, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react'
|
||||
|
||||
const APV = dynamic(() => import('./components/Videos'), {
|
||||
ssr: false
|
||||
})
|
||||
const shimmer = (w, h) => `
|
||||
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="g">
|
||||
<stop stop-color="#333" offset="20%" />
|
||||
<stop stop-color="#222" offset="50%" />
|
||||
<stop stop-color="#333" offset="70%" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="${w}" height="${h}" fill="#333" />
|
||||
<rect id="r" width="${w}" height="${h}" fill="url(#g)" />
|
||||
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
||||
</svg>`
|
||||
|
||||
const toBase64 = str => (typeof window === 'undefined' ? Buffer.from(str).toString('base64') : window.btoa(str))
|
||||
|
||||
const Gallery = dataImage => {
|
||||
const [Images, SetImages] = useState(dataImage)
|
||||
const [justifyActive, setJustifyActive] = React.useState('tab1')
|
||||
const [toggle, setToggle] = React.useState(false)
|
||||
const [sIndex, setSIndex] = React.useState(0)
|
||||
const [filterId, setFilterId] = React.useState(1)
|
||||
const Parallax = ({ quality }) => {
|
||||
return `../resource/parallax/Gallery.jpg`
|
||||
}
|
||||
// const Filter = async filter => {
|
||||
// const res = await axios.get(AppUrl(`FilterGalleyImages/${filter}`))
|
||||
// SetImages({ dataImage: res.data })
|
||||
// setFilterId(filter)
|
||||
// }
|
||||
|
||||
// const AllImage = async () => {
|
||||
// const res = await axios.get(AppUrl(`GetGalleyImages`))
|
||||
// SetImages({ dataImage: res.data })
|
||||
// }
|
||||
|
||||
// Handler
|
||||
// const lightBoxHandler = (state, sIndex) => {
|
||||
// setToggle(state)
|
||||
// setSIndex(sIndex)
|
||||
// }
|
||||
|
||||
const handleJustifyClick = value => {
|
||||
if (value === justifyActive) {
|
||||
return
|
||||
}
|
||||
|
||||
setJustifyActive(value)
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<style jsx>
|
||||
{`
|
||||
.cardImage {
|
||||
background-color: #f3f4f6;
|
||||
padding: 5px;
|
||||
border-radius: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 2px;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<AppContainer></AppContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export async function getServerSideProps(context) {
|
||||
// const res = await axios.get(AppUrl('GetGalleyImages'));
|
||||
return {
|
||||
props: {
|
||||
dataImage: null
|
||||
} // will be passed to the page component as props
|
||||
}
|
||||
}
|
||||
export default Gallery
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Image from 'next/image'
|
||||
import AppContainer from './appContainer'
|
||||
|
||||
const shimmer = (width, height) => `
|
||||
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="gradient">
|
||||
<stop stop-color="#e5e7eb" offset="20%" />
|
||||
<stop stop-color="#f9fafb" offset="50%" />
|
||||
<stop stop-color="#e5e7eb" offset="70%" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="${width}" height="${height}" fill="#e5e7eb" />
|
||||
<rect width="${width}" height="${height}" fill="url(#gradient)" />
|
||||
</svg>
|
||||
`
|
||||
|
||||
const toBase64 = value =>
|
||||
typeof window === 'undefined' ? Buffer.from(value).toString('base64') : window.btoa(value)
|
||||
|
||||
const galleryBannerLoader = () => '/resource/parallax/Gallery.jpg'
|
||||
|
||||
const Gallery = ({ images }) => {
|
||||
const [selectedImage, setSelectedImage] = useState(null)
|
||||
|
||||
const closeLightbox = () => setSelectedImage(null)
|
||||
|
||||
const showPreviousImage = () => {
|
||||
setSelectedImage(current => (current === 0 ? images.length - 1 : current - 1))
|
||||
}
|
||||
|
||||
const showNextImage = () => {
|
||||
setSelectedImage(current => (current === images.length - 1 ? 0 : current + 1))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedImage === null) return undefined
|
||||
|
||||
const handleKeyDown = event => {
|
||||
if (event.key === 'Escape') setSelectedImage(null)
|
||||
if (event.key === 'ArrowRight') {
|
||||
setSelectedImage(current => (current === images.length - 1 ? 0 : current + 1))
|
||||
}
|
||||
if (event.key === 'ArrowLeft') {
|
||||
setSelectedImage(current => (current === 0 ? images.length - 1 : current - 1))
|
||||
}
|
||||
}
|
||||
|
||||
const previousOverflow = document.body.style.overflow
|
||||
document.body.style.overflow = 'hidden'
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
|
||||
return () => {
|
||||
document.body.style.overflow = previousOverflow
|
||||
window.removeEventListener('keydown', handleKeyDown)
|
||||
}
|
||||
}, [selectedImage, images.length])
|
||||
|
||||
return (
|
||||
<AppContainer title='گالری بیمارستان مهر ایرانیان پرند'>
|
||||
<style jsx>{`
|
||||
.gallery-page {
|
||||
direction: rtl;
|
||||
padding: 3rem 1rem 5rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.gallery-header {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto 2rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.gallery-header h2 {
|
||||
margin: 0 0 0.5rem;
|
||||
color: #263238;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.gallery-header p {
|
||||
margin: 0;
|
||||
color: #6b7280;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.gallery-header::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 54px;
|
||||
height: 3px;
|
||||
margin-top: 0.9rem;
|
||||
border-radius: 999px;
|
||||
background: #009688;
|
||||
}
|
||||
|
||||
.gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 1rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.gallery-card {
|
||||
position: relative;
|
||||
aspect-ratio: 16 / 9;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.85rem;
|
||||
background: #f3f4f6;
|
||||
cursor: zoom-in;
|
||||
box-shadow: 0 4px 14px rgba(15, 23, 42, 0.07);
|
||||
transition: transform 180ms ease, box-shadow 180ms ease;
|
||||
}
|
||||
|
||||
.gallery-card:hover,
|
||||
.gallery-card:focus-visible {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.15);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.gallery-card :global(img) {
|
||||
transition: transform 250ms ease;
|
||||
}
|
||||
|
||||
.gallery-card:hover :global(img) {
|
||||
transform: scale(1.035);
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
position: fixed;
|
||||
z-index: 1500;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4.5rem 5rem 3rem;
|
||||
background: rgba(0, 0, 0, 0.92);
|
||||
}
|
||||
|
||||
.lightbox-image {
|
||||
max-width: 100%;
|
||||
max-height: calc(100vh - 7.5rem);
|
||||
object-fit: contain;
|
||||
border-radius: 0.4rem;
|
||||
}
|
||||
|
||||
.lightbox-close,
|
||||
.lightbox-navigation {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
color: #fff;
|
||||
background: rgba(255, 255, 255, 0.13);
|
||||
cursor: pointer;
|
||||
transition: background 150ms ease;
|
||||
}
|
||||
|
||||
.lightbox-close:hover,
|
||||
.lightbox-navigation:hover {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.lightbox-close {
|
||||
top: 1.25rem;
|
||||
right: 1.25rem;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
font-size: 1.9rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.lightbox-navigation {
|
||||
top: 50%;
|
||||
width: 46px;
|
||||
height: 58px;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 2rem;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.lightbox-previous {
|
||||
left: 1.25rem;
|
||||
}
|
||||
|
||||
.lightbox-next {
|
||||
right: 1.25rem;
|
||||
}
|
||||
|
||||
.lightbox-counter {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
left: 50%;
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: 0.9rem;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.gallery-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.gallery-page {
|
||||
padding: 2rem 1rem 4rem;
|
||||
}
|
||||
|
||||
.gallery-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
padding: 4rem 1rem;
|
||||
}
|
||||
|
||||
.lightbox-navigation {
|
||||
top: auto;
|
||||
bottom: 0.8rem;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.lightbox-previous {
|
||||
left: 1rem;
|
||||
}
|
||||
|
||||
.lightbox-next {
|
||||
right: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.gallery-header h2 {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.gallery-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<div className='parallax-container'>
|
||||
<h1 className='center-align text-white header_back service-text dana font-weight-bold'>گالری بیمارستان</h1>
|
||||
<Image
|
||||
loader={galleryBannerLoader}
|
||||
src='gallery-banner.jpg'
|
||||
className='responsive-img shadow-5'
|
||||
alt='گالری بیمارستان مهر ایرانیان پرند'
|
||||
width={3000}
|
||||
height={1300}
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
|
||||
<main className='gallery-page'>
|
||||
<header className='gallery-header'>
|
||||
<h2>گالری تصاویر</h2>
|
||||
<p>تصاویر بیمارستان مهر ایرانیان پرند</p>
|
||||
</header>
|
||||
|
||||
<section className='gallery-grid' aria-label='تصاویر گالری بیمارستان'>
|
||||
{images.map((image, index) => (
|
||||
<button
|
||||
type='button'
|
||||
className='gallery-card'
|
||||
key={image.id}
|
||||
aria-label={`نمایش تصویر ${index + 1} از گالری`}
|
||||
onClick={() => setSelectedImage(index)}
|
||||
>
|
||||
<Image
|
||||
src={image.image}
|
||||
alt={image.title}
|
||||
layout='fill'
|
||||
objectFit='cover'
|
||||
placeholder='blur'
|
||||
blurDataURL={`data:image/svg+xml;base64,${toBase64(shimmer(640, 360))}`}
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</section>
|
||||
</main>
|
||||
|
||||
{selectedImage !== null && (
|
||||
<div className='lightbox' role='dialog' aria-modal='true' aria-label='نمایش تصویر گالری' onClick={closeLightbox}>
|
||||
<button type='button' className='lightbox-close' aria-label='بستن تصویر' onClick={closeLightbox}>
|
||||
×
|
||||
</button>
|
||||
<button
|
||||
type='button'
|
||||
className='lightbox-navigation lightbox-previous'
|
||||
aria-label='تصویر قبلی'
|
||||
onClick={event => {
|
||||
event.stopPropagation()
|
||||
showPreviousImage()
|
||||
}}
|
||||
>
|
||||
‹
|
||||
</button>
|
||||
<img
|
||||
className='lightbox-image'
|
||||
src={images[selectedImage].image}
|
||||
alt={images[selectedImage].title}
|
||||
onClick={event => event.stopPropagation()}
|
||||
/>
|
||||
<button
|
||||
type='button'
|
||||
className='lightbox-navigation lightbox-next'
|
||||
aria-label='تصویر بعدی'
|
||||
onClick={event => {
|
||||
event.stopPropagation()
|
||||
showNextImage()
|
||||
}}
|
||||
>
|
||||
›
|
||||
</button>
|
||||
<p className='lightbox-counter'>
|
||||
{selectedImage + 1} از {images.length}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</AppContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
const galleryDirectory = path.join(process.cwd(), 'public', 'resource', 'images', 'gallery')
|
||||
const fileNames = fs
|
||||
.readdirSync(galleryDirectory)
|
||||
.filter(fileName => /\.(jpe?g|png|webp)$/i.test(fileName))
|
||||
.sort((first, second) => first.localeCompare(second, undefined, { numeric: true }))
|
||||
|
||||
const images = fileNames.map((fileName, index) => ({
|
||||
id: fileName,
|
||||
image: `/resource/images/gallery/${encodeURIComponent(fileName)}`,
|
||||
title: `تصویر ${index + 1} از بیمارستان مهر ایرانیان پرند`
|
||||
}))
|
||||
|
||||
return {
|
||||
props: { images }
|
||||
}
|
||||
}
|
||||
|
||||
export default Gallery
|
||||
|
||||
Reference in New Issue
Block a user