diff --git a/src/components/listing-image-gallery/ListingImageGallery.tsx b/src/components/listing-image-gallery/ListingImageGallery.tsx new file mode 100644 index 0000000..a18d6f6 --- /dev/null +++ b/src/components/listing-image-gallery/ListingImageGallery.tsx @@ -0,0 +1,171 @@ +"use client"; + +import "./styles/index.css"; +import Image from "next/image"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import { FC, Fragment, useEffect, useRef } from "react"; +import Modal from "./components/Modal"; +import type { ListingGalleryImage } from "./utils/types"; +import { useLastViewedPhoto } from "./utils/useLastViewedPhoto"; +import { ArrowSmallLeftIcon } from "@heroicons/react/24/outline"; +import { Dialog, Transition } from "@headlessui/react"; +import LikeSaveBtns from "../LikeSaveBtns"; +import { Route } from "next"; + +const PHOTOS: string[] = [ + "https://images.pexels.com/photos/6129967/pexels-photo-6129967.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260", + "https://images.pexels.com/photos/7163619/pexels-photo-7163619.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", + "https://images.pexels.com/photos/6527036/pexels-photo-6527036.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", + "https://images.pexels.com/photos/6969831/pexels-photo-6969831.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", + "https://images.pexels.com/photos/6438752/pexels-photo-6438752.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", + "https://images.pexels.com/photos/1320686/pexels-photo-1320686.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", + "https://images.pexels.com/photos/261394/pexels-photo-261394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", + "https://images.pexels.com/photos/2861361/pexels-photo-2861361.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", +]; + +export const DEMO_IMAGE: ListingGalleryImage[] = [...PHOTOS].map( + (item, index): ListingGalleryImage => { + return { + id: index, + url: item, + }; + } +); + +export const getNewParam = ({ + paramName = "photoId", + value, +}: { + paramName?: string; + value: string | number; +}) => { + let params = new URLSearchParams(document.location.search); + params.set(paramName, String(value)); + return params.toString(); +}; + +interface Props { + images?: ListingGalleryImage[]; + onClose?: () => void; + isShowModal: boolean; +} + +const ListingImageGallery: FC = ({ + images = DEMO_IMAGE, + onClose, + isShowModal, +}) => { + const searchParams = useSearchParams(); + const photoId = searchParams?.get("photoId"); + const router = useRouter(); + const [lastViewedPhoto, setLastViewedPhoto] = useLastViewedPhoto(); + + const lastViewedPhotoRef = useRef(null); + const thisPathname = usePathname(); + useEffect(() => { + // This effect keeps track of the last viewed photo in the modal to keep the index page in sync when the user navigates back + if (lastViewedPhoto && !photoId) { + lastViewedPhotoRef.current?.scrollIntoView({ block: "center" }); + setLastViewedPhoto(null); + } + }, [photoId, lastViewedPhoto, setLastViewedPhoto]); + + const handleClose = () => { + onClose && onClose(); + }; + + const renderContent = () => { + return ( +
+ {photoId && ( + { + // @ts-ignore + setLastViewedPhoto(photoId); + let params = new URLSearchParams(document.location.search); + params.delete("photoId"); + router.push(`${thisPathname}/?${params.toString()}` as Route); + }} + /> + )} + +
+ {images.map(({ id, url }) => ( +
{ + const newPathname = getNewParam({ value: id }); + router.push(`${thisPathname}/?${newPathname}` as Route); + }} + ref={id === Number(lastViewedPhoto) ? lastViewedPhotoRef : null} + className="after:content group relative mb-5 block w-full cursor-zoom-in after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:shadow-highlight focus:outline-none" + > + chisfis listing gallery +
+ ))} +
+
+ ); + }; + + return ( + <> + + + +
+ + +
+
+ + +
+ +
+ + + {renderContent()} + + +
+
+
+
+ + ); +}; + +export default ListingImageGallery;