| "use client"; |
|
|
| import React, { useEffect, useRef } from "react"; |
| import Link from "next/link"; |
|
|
| import { useRouter, useSearchParams } from "next/navigation"; |
| import { postParentMessageWithParams } from "@/utils/postParentMessage"; |
|
|
| type ExploreGridProps = { |
| datasets: Array<{ id: string; videoUrl: string | null }>; |
| currentPage: number; |
| totalPages: number; |
| }; |
|
|
| export default function ExploreGrid({ |
| datasets, |
| currentPage, |
| totalPages, |
| }: ExploreGridProps) { |
| |
| useEffect(() => { |
| postParentMessageWithParams((params: URLSearchParams) => { |
| params.set("path", window.location.pathname + window.location.search); |
| }); |
| }, []); |
|
|
| |
| const videoRefs = useRef<(HTMLVideoElement | null)[]>([]); |
|
|
| return ( |
| <main className="p-8"> |
| <h1 className="text-2xl font-bold mb-6">Explore LeRobot Datasets</h1> |
| <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> |
| {datasets.map((ds, idx) => ( |
| <Link |
| key={ds.id} |
| href={`/${ds.id}`} |
| className="relative border rounded-lg p-4 bg-white shadow hover:shadow-lg transition overflow-hidden h-48 flex items-end group" |
| onMouseEnter={() => { |
| const vid = videoRefs.current[idx]; |
| if (vid) vid.play(); |
| }} |
| onMouseLeave={() => { |
| const vid = videoRefs.current[idx]; |
| if (vid) { |
| vid.pause(); |
| vid.currentTime = 0; |
| } |
| }} |
| > |
| <video |
| ref={(el) => { |
| videoRefs.current[idx] = el; |
| }} |
| src={ds.videoUrl || undefined} |
| className="absolute top-0 left-0 w-full h-full object-cover object-center z-0" |
| loop |
| muted |
| playsInline |
| preload="metadata" |
| onTimeUpdate={(e) => { |
| const vid = e.currentTarget; |
| if (vid.currentTime >= 15) { |
| vid.pause(); |
| vid.currentTime = 0; |
| } |
| }} |
| /> |
| <div className="absolute top-0 left-0 w-full h-full bg-black/40 z-10 pointer-events-none" /> |
| <div className="relative z-20 font-mono text-blue-100 break-all text-sm bg-black/60 backdrop-blur px-2 py-1 rounded shadow"> |
| {ds.id} |
| </div> |
| </Link> |
| ))} |
| </div> |
| <div className="flex justify-center mt-8 gap-4"> |
| {currentPage > 1 && ( |
| <button |
| className="px-6 py-2 bg-gray-600 text-white rounded shadow hover:bg-gray-700 transition" |
| onClick={() => { |
| const params = new URLSearchParams(window.location.search); |
| params.set("p", (currentPage - 1).toString()); |
| window.location.search = params.toString(); |
| }} |
| > |
| Previous |
| </button> |
| )} |
| {currentPage < totalPages && ( |
| <button |
| className="px-6 py-2 bg-blue-600 text-white rounded shadow hover:bg-blue-700 transition" |
| onClick={() => { |
| const params = new URLSearchParams(window.location.search); |
| params.set("p", (currentPage + 1).toString()); |
| window.location.search = params.toString(); |
| }} |
| > |
| Next |
| </button> |
| )} |
| </div> |
| </main> |
| ); |
| } |
|
|