videofolxtv/client/src/components/video-grid.tsx
sebastjanartic 22aac877b9 Add video navigation and translate UI elements to Slovenian
Introduce left/right arrow navigation for videos and translate several UI strings to Slovenian.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 2eb1084e-b728-4449-9231-f1665924c8d5
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/2eb1084e-b728-4449-9231-f1665924c8d5/14Urb47
2025-08-28 20:24:30 +00:00

113 lines
3.2 KiB
TypeScript

import { useState } from "react";
import { type Video } from "@shared/schema";
import VideoCard from "./video-card";
import BunnyVideoModal from "./bunny-video-modal";
import { Button } from "@/components/ui/button";
import { ChevronDown } from "lucide-react";
interface VideoGridProps {
videos: Video[];
isLoading: boolean;
hasMore: boolean;
onLoadMore: () => void;
viewMode: "grid" | "list";
}
export default function VideoGrid({ videos, isLoading, hasMore, onLoadMore, viewMode }: VideoGridProps) {
const [selectedVideo, setSelectedVideo] = useState<Video | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const handleVideoClick = (video: Video) => {
setSelectedVideo(video);
setIsModalOpen(true);
};
const handleCloseModal = () => {
setIsModalOpen(false);
setSelectedVideo(null);
};
const handleVideoChange = (video: Video) => {
setSelectedVideo(video);
};
if (isLoading && videos.length === 0) {
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6" data-testid="grid-loading">
{Array.from({ length: 8 }).map((_, index) => (
<div key={index} className="animate-pulse">
<div className="bg-bunny-gray aspect-video rounded-xl mb-4"></div>
<div className="space-y-2">
<div className="h-4 bg-bunny-gray rounded w-3/4"></div>
<div className="h-3 bg-bunny-gray rounded w-1/2"></div>
</div>
</div>
))}
</div>
);
}
if (videos.length === 0) {
return (
<div className="text-center py-12">
<div className="text-bunny-muted text-lg mb-4" data-testid="text-no-videos">
Ni najdenih videjev
</div>
<p className="text-sm text-bunny-muted">
Poskusi prilagoditi iskalne ali filter kriterije
</p>
</div>
);
}
const gridClass = viewMode === "grid"
? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"
: "grid grid-cols-1 gap-4";
return (
<>
<div className={gridClass} data-testid="grid-videos">
{videos.map((video) => (
<VideoCard
key={video.id}
video={video}
onClick={handleVideoClick}
/>
))}
</div>
{hasMore && (
<div className="text-center mt-12">
<Button
onClick={onLoadMore}
disabled={isLoading}
className="bg-bunny-blue hover:bg-blue-600 text-white px-8 py-3 rounded-lg font-medium transition-colors inline-flex items-center space-x-2"
data-testid="button-load-more"
>
{isLoading ? (
<>
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
<span>Nalagam...</span>
</>
) : (
<>
<span>Naloži Več Videjev</span>
<ChevronDown className="w-4 h-4" />
</>
)}
</Button>
</div>
)}
<BunnyVideoModal
video={selectedVideo}
isOpen={isModalOpen}
onClose={handleCloseModal}
videos={videos}
onVideoChange={handleVideoChange}
/>
</>
);
}