import { ImagesIcon, PlusIcon } from "lucide-react"; import { useState } from "react"; import Lightbox from "yet-another-react-lightbox"; import "yet-another-react-lightbox/styles.css"; import { Message } from "./ChatWindow"; type Image = { url: string; img_src: string; title: string; }; const SearchImages = ({ query, chat_history }: { query: string; chat_history: Message[] }) => { const [images, setImages] = useState<Image[] | null>(null); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); // eslint-disable-next-line @typescript-eslint/no-explicit-any const [slides, setSlides] = useState<any[]>([]); return ( <> {!loading && images === null && ( <button onClick={async () => { setLoading(true); const chatModelProvider = localStorage.getItem("chatModelProvider"); const chatModel = localStorage.getItem("chatModel"); const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/images`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: query, chat_history: chat_history, chat_model_provider: chatModelProvider, chat_model: chatModel, }), }); const data = await res.json(); const images = data.images; setImages(images); setSlides( images.map((image: Image) => { return { src: image.img_src, }; }), ); setLoading(false); }} className="border border-dashed border-light-200 dark:border-dark-200 hover:bg-light-200 dark:hover:bg-dark-200 active:scale-95 duration-200 transition px-4 py-2 flex flex-row items-center justify-between rounded-lg dark:text-white text-sm w-full" > <div className="flex flex-row items-center space-x-2"> <ImagesIcon size={17} /> <p>Search images</p> </div> <PlusIcon className="text-[#24A0ED]" size={17} /> </button> )} {loading && ( <div className="grid grid-cols-2 gap-2"> {Array.from({ length: 4 }).map((_, index) => ( <div key={index} className="bg-light-secondary dark:bg-dark-secondary h-32 w-full rounded-lg animate-pulse aspect-video object-cover" /> ))} </div> )} {images !== null && images.length > 0 && ( <> <div className="grid grid-cols-2 gap-2"> {images.length > 4 ? images.slice(0, 3).map((image, index) => ( <img onClick={() => { setOpen(true); setSlides([slides[index], ...slides.slice(0, index), ...slides.slice(index + 1)]); }} key={index} src={image.img_src} alt={image.title} className="h-full w-full aspect-video object-cover rounded-lg transition duration-200 active:scale-95 hover:scale-[1.02] cursor-zoom-in" /> )) : images.map((image, index) => ( <img onClick={() => { setOpen(true); setSlides([slides[index], ...slides.slice(0, index), ...slides.slice(index + 1)]); }} key={index} src={image.img_src} alt={image.title} className="h-full w-full aspect-video object-cover rounded-lg transition duration-200 active:scale-95 hover:scale-[1.02] cursor-zoom-in" /> ))} {images.length > 4 && ( <button onClick={() => setOpen(true)} className="bg-light-100 hover:bg-light-200 dark:bg-dark-100 dark:hover:bg-dark-200 transition duration-200 active:scale-95 hover:scale-[1.02] h-auto w-full rounded-lg flex flex-col justify-between text-white p-2" > <div className="flex flex-row items-center space-x-1"> {images.slice(3, 6).map((image, index) => ( <img key={index} src={image.img_src} alt={image.title} className="h-6 w-12 rounded-md lg:h-3 lg:w-6 lg:rounded-sm aspect-video object-cover" /> ))} </div> <p className="text-black/70 dark:text-white/70 text-xs">View {images.length - 3} more</p> </button> )} </div> <Lightbox open={open} close={() => setOpen(false)} slides={slides} /> </> )} </> ); }; export default SearchImages;