videofolxtv/client/src/components/video-grid.tsx
sebastjanartic 25562ab317 Update interface text to German for better user experience
Translate UI elements and messages from English to German across various components and pages, including video availability, loading states, and recommendations.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 051a65da-1176-4478-a61c-c662f2a15536
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/051a65da-1176-4478-a61c-c662f2a15536/9NQBiz8
2025-08-30 22:03:12 +00:00

113 lines
3.3 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) => {
// Navigate to individual video page instead of modal
window.location.href = `/video/${video.id}`;
};
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">
No videos found
</div>
<p className="text-sm text-bunny-muted">
Try adjusting your search or filter criteria
</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>Wird geladen...</span>
</>
) : (
<>
<span>Weitere Videos laden</span>
<ChevronDown className="w-4 h-4" />
</>
)}
</Button>
</div>
)}
<BunnyVideoModal
video={selectedVideo}
isOpen={isModalOpen}
onClose={handleCloseModal}
videos={videos}
onVideoChange={handleVideoChange}
/>
</>
);
}