2024-07-05 14:36:50 +08:00
|
|
|
import { PlayCircle, PlayIcon, PlusIcon, VideoIcon } from "lucide-react";
|
|
|
|
import { useState } from "react";
|
|
|
|
import Lightbox, { GenericSlide, VideoSlide } from "yet-another-react-lightbox";
|
|
|
|
import "yet-another-react-lightbox/styles.css";
|
|
|
|
import { Message } from "./ChatWindow";
|
2024-04-30 14:31:32 +05:30
|
|
|
|
|
|
|
type Video = {
|
|
|
|
url: string;
|
|
|
|
img_src: string;
|
|
|
|
title: string;
|
|
|
|
iframe_src: string;
|
|
|
|
};
|
|
|
|
|
2024-07-05 14:36:50 +08:00
|
|
|
declare module "yet-another-react-lightbox" {
|
2024-04-30 14:31:32 +05:30
|
|
|
export interface VideoSlide extends GenericSlide {
|
2024-07-05 14:36:50 +08:00
|
|
|
type: "video-slide";
|
2024-04-30 14:31:32 +05:30
|
|
|
src: string;
|
|
|
|
iframe_src: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface SlideTypes {
|
2024-07-05 14:36:50 +08:00
|
|
|
"video-slide": VideoSlide;
|
2024-04-30 14:31:32 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-05 14:36:50 +08:00
|
|
|
const Searchvideos = ({ query, chat_history }: { query: string; chat_history: Message[] }) => {
|
2024-04-30 14:31:32 +05:30
|
|
|
const [videos, setVideos] = useState<Video[] | null>(null);
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const [open, setOpen] = useState(false);
|
|
|
|
const [slides, setSlides] = useState<VideoSlide[]>([]);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{!loading && videos === null && (
|
|
|
|
<button
|
|
|
|
onClick={async () => {
|
|
|
|
setLoading(true);
|
2024-05-02 12:14:26 +05:30
|
|
|
|
2024-07-05 14:36:50 +08:00
|
|
|
const chatModelProvider = localStorage.getItem("chatModelProvider");
|
|
|
|
const chatModel = localStorage.getItem("chatModel");
|
2024-05-02 12:14:26 +05:30
|
|
|
|
2024-07-05 14:36:50 +08:00
|
|
|
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/videos`, {
|
|
|
|
method: "POST",
|
|
|
|
headers: {
|
|
|
|
"Content-Type": "application/json",
|
2024-04-30 14:31:32 +05:30
|
|
|
},
|
2024-07-05 14:36:50 +08:00
|
|
|
body: JSON.stringify({
|
|
|
|
query: query,
|
|
|
|
chat_history: chat_history,
|
|
|
|
chat_model_provider: chatModelProvider,
|
|
|
|
chat_model: chatModel,
|
|
|
|
}),
|
|
|
|
});
|
2024-04-30 14:31:32 +05:30
|
|
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
|
|
|
const videos = data.videos;
|
|
|
|
setVideos(videos);
|
|
|
|
setSlides(
|
|
|
|
videos.map((video: Video) => {
|
|
|
|
return {
|
2024-07-05 14:36:50 +08:00
|
|
|
type: "video-slide",
|
2024-04-30 14:31:32 +05:30
|
|
|
iframe_src: video.iframe_src,
|
|
|
|
src: video.img_src,
|
|
|
|
};
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
setLoading(false);
|
|
|
|
}}
|
2024-05-29 14:44:25 +08:00
|
|
|
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"
|
2024-04-30 14:31:32 +05:30
|
|
|
>
|
|
|
|
<div className="flex flex-row items-center space-x-2">
|
|
|
|
<VideoIcon size={17} />
|
|
|
|
<p>Search videos</p>
|
|
|
|
</div>
|
|
|
|
<PlusIcon className="text-[#24A0ED]" size={17} />
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
{loading && (
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
2024-07-05 15:49:43 +08:00
|
|
|
{Array.from({ length: 4 }).map((_, index) => (
|
2024-04-30 14:31:32 +05:30
|
|
|
<div
|
2024-07-05 15:49:43 +08:00
|
|
|
key={index}
|
2024-05-27 11:49:09 +08:00
|
|
|
className="bg-light-secondary dark:bg-dark-secondary h-32 w-full rounded-lg animate-pulse aspect-video object-cover"
|
2024-04-30 14:31:32 +05:30
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
{videos !== null && videos.length > 0 && (
|
|
|
|
<>
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
{videos.length > 4
|
2024-07-05 15:49:43 +08:00
|
|
|
? videos.slice(0, 3).map((video, index) => (
|
2024-04-30 14:31:32 +05:30
|
|
|
<div
|
|
|
|
onClick={() => {
|
|
|
|
setOpen(true);
|
2024-07-05 15:49:43 +08:00
|
|
|
setSlides([slides[index], ...slides.slice(0, index), ...slides.slice(index + 1)]);
|
2024-04-30 14:31:32 +05:30
|
|
|
}}
|
|
|
|
className="relative transition duration-200 active:scale-95 hover:scale-[1.02] cursor-pointer"
|
2024-07-05 15:49:43 +08:00
|
|
|
key={index}
|
2024-04-30 14:31:32 +05:30
|
|
|
>
|
|
|
|
<img
|
|
|
|
src={video.img_src}
|
|
|
|
alt={video.title}
|
|
|
|
className="relative h-full w-full aspect-video object-cover rounded-lg"
|
|
|
|
/>
|
2024-05-24 22:41:06 +08:00
|
|
|
<div className="absolute bg-white/70 dark:bg-black/70 text-black/70 dark:text-white/70 px-2 py-1 flex flex-row items-center space-x-1 bottom-1 right-1 rounded-md">
|
2024-04-30 14:31:32 +05:30
|
|
|
<PlayCircle size={15} />
|
|
|
|
<p className="text-xs">Video</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
))
|
2024-07-05 15:49:43 +08:00
|
|
|
: videos.map((video, index) => (
|
2024-04-30 14:31:32 +05:30
|
|
|
<div
|
|
|
|
onClick={() => {
|
|
|
|
setOpen(true);
|
2024-07-05 15:49:43 +08:00
|
|
|
setSlides([slides[index], ...slides.slice(0, index), ...slides.slice(index + 1)]);
|
2024-04-30 14:31:32 +05:30
|
|
|
}}
|
|
|
|
className="relative transition duration-200 active:scale-95 hover:scale-[1.02] cursor-pointer"
|
2024-07-05 15:49:43 +08:00
|
|
|
key={index}
|
2024-04-30 14:31:32 +05:30
|
|
|
>
|
|
|
|
<img
|
|
|
|
src={video.img_src}
|
|
|
|
alt={video.title}
|
|
|
|
className="relative h-full w-full aspect-video object-cover rounded-lg"
|
|
|
|
/>
|
2024-05-24 20:29:49 +08:00
|
|
|
<div className="absolute bg-white/70 dark:bg-black/70 text-black/70 dark:text-white/70 px-2 py-1 flex flex-row items-center space-x-1 bottom-1 right-1 rounded-md">
|
2024-04-30 14:31:32 +05:30
|
|
|
<PlayCircle size={15} />
|
|
|
|
<p className="text-xs">Video</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
{videos.length > 4 && (
|
|
|
|
<button
|
|
|
|
onClick={() => setOpen(true)}
|
2024-05-28 10:15:42 +08:00
|
|
|
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"
|
2024-04-30 14:31:32 +05:30
|
|
|
>
|
|
|
|
<div className="flex flex-row items-center space-x-1">
|
2024-07-05 15:49:43 +08:00
|
|
|
{videos.slice(3, 6).map((video, index) => (
|
2024-04-30 14:31:32 +05:30
|
|
|
<img
|
2024-07-05 15:49:43 +08:00
|
|
|
key={index}
|
2024-04-30 14:31:32 +05:30
|
|
|
src={video.img_src}
|
|
|
|
alt={video.title}
|
|
|
|
className="h-6 w-12 rounded-md lg:h-3 lg:w-6 lg:rounded-sm aspect-video object-cover"
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
2024-07-05 14:36:50 +08:00
|
|
|
<p className="text-black/70 dark:text-white/70 text-xs">View {videos.length - 3} more</p>
|
2024-04-30 14:31:32 +05:30
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
<Lightbox
|
|
|
|
open={open}
|
|
|
|
close={() => setOpen(false)}
|
|
|
|
slides={slides}
|
|
|
|
render={{
|
|
|
|
slide: ({ slide }) =>
|
2024-07-05 14:36:50 +08:00
|
|
|
slide.type === "video-slide" ? (
|
2024-04-30 14:31:32 +05:30
|
|
|
<div className="h-full w-full flex flex-row items-center justify-center">
|
|
|
|
<iframe
|
|
|
|
src={slide.iframe_src}
|
|
|
|
className="aspect-video max-h-[95vh] w-[95vw] rounded-2xl md:w-[80vw]"
|
|
|
|
allowFullScreen
|
|
|
|
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
) : null,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Searchvideos;
|