117 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 'use client'
 | |
| 
 | |
| import {ProductResource} from '@prisma/client'
 | |
| import {EmblaOptionsType} from 'embla-carousel'
 | |
| import useEmblaCarousel from 'embla-carousel-react'
 | |
| import Image from 'next/image'
 | |
| import React, {useCallback, useEffect, useState} from 'react'
 | |
| 
 | |
| import {Thumb} from './thumb'
 | |
| import {Dialog, DialogContent, DialogTitle} from '@/ui/dialog'
 | |
| 
 | |
| type PropType = {
 | |
| 	slides: number[]
 | |
| 	options?: EmblaOptionsType
 | |
| }
 | |
| 
 | |
| export default function ProductCarousel({
 | |
| 	images,
 | |
| 	title
 | |
| }: {
 | |
| 	images: ProductResource[] | null
 | |
| 	title: string
 | |
| }) {
 | |
| 	//const {slides, options} = props
 | |
| 	const [selectedIndex, setSelectedIndex] = useState(0)
 | |
| 	const [emblaMainRef, emblaMainApi] = useEmblaCarousel({}) //options
 | |
| 	const [emblaThumbsRef, emblaThumbsApi] = useEmblaCarousel({
 | |
| 		containScroll: 'keepSnaps',
 | |
| 		dragFree: true
 | |
| 	})
 | |
| 
 | |
| 	const onThumbClick = useCallback(
 | |
| 		(index: number) => {
 | |
| 			if (!emblaMainApi || !emblaThumbsApi) return
 | |
| 			emblaMainApi.scrollTo(index)
 | |
| 		},
 | |
| 		[emblaMainApi, emblaThumbsApi]
 | |
| 	)
 | |
| 
 | |
| 	const onSelect = useCallback(() => {
 | |
| 		if (!emblaMainApi || !emblaThumbsApi) return
 | |
| 		setSelectedIndex(emblaMainApi.selectedScrollSnap())
 | |
| 		emblaThumbsApi.scrollTo(emblaMainApi.selectedScrollSnap())
 | |
| 	}, [emblaMainApi, emblaThumbsApi, setSelectedIndex])
 | |
| 
 | |
| 	useEffect(() => {
 | |
| 		if (!emblaMainApi) return
 | |
| 		onSelect()
 | |
| 
 | |
| 		emblaMainApi.on('select', onSelect).on('reInit', onSelect)
 | |
| 	}, [emblaMainApi, onSelect])
 | |
| 	//let featuredImage: ProductResource | null | undefined
 | |
| 	/*if ((resources || []).length > 0) {
 | |
| 		featuredImage = resources?.find(resource => resource.isFeature)
 | |
| 	}*/
 | |
| 
 | |
| 	return (
 | |
| 		<div className='embla my-8'>
 | |
| 			<div className='embla__viewport' ref={emblaMainRef}>
 | |
| 				<div className='embla__container'>
 | |
| 					{images?.map((image: ProductResource, index: number) => (
 | |
| 						<div className='embla__slide' key={index}>
 | |
| 							<div className='embla__slide__number h-[480px] overflow-hidden'>
 | |
| 								<Image
 | |
| 									src={image.uri}
 | |
| 									alt=''
 | |
| 									width={image.width || 100}
 | |
| 									height={image.height || 100}
 | |
| 									sizes='100vw'
 | |
| 									style={{
 | |
| 										width: '100%',
 | |
| 										height: 'auto',
 | |
| 										maxHeight: '480px',
 | |
| 										objectFit: 'contain'
 | |
| 									}}
 | |
| 								/>
 | |
| 							</div>
 | |
| 						</div>
 | |
| 					))}
 | |
| 				</div>
 | |
| 			</div>
 | |
| 
 | |
| 			<div className='embla-thumbs mb-8 mt-6'>
 | |
| 				<div className='embla-thumbs__viewport' ref={emblaThumbsRef}>
 | |
| 					<div className='embla-thumbs__container flex items-center justify-center gap-x-6'>
 | |
| 						{images?.map((image: ProductResource, index: number) => (
 | |
| 							<Dialog key={index}>
 | |
| 								<DialogTitle className='hidden'>{title}</DialogTitle>
 | |
| 								<Thumb
 | |
| 									image={image}
 | |
| 									onClick={() => onThumbClick(index)}
 | |
| 									selected={index === selectedIndex}
 | |
| 									index={index}
 | |
| 								/>
 | |
| 								<DialogContent className='overflow w-full'>
 | |
| 									<Image
 | |
| 										src={image.uri}
 | |
| 										alt=''
 | |
| 										width={image.width || 100}
 | |
| 										height={image.height || 100}
 | |
| 										sizes='100vw'
 | |
| 										style={{
 | |
| 											width: '100%',
 | |
| 											maxHeight: '100dvh',
 | |
| 											objectFit: 'contain'
 | |
| 										}}
 | |
| 									/>
 | |
| 								</DialogContent>
 | |
| 							</Dialog>
 | |
| 						))}
 | |
| 					</div>
 | |
| 				</div>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 	)
 | |
| }
 |