This commit addresses several UI and text-related changes across multiple components and pages. Key updates include: - Modifying link hover colors from a specific red (#da234d) to white for better contrast and consistency. - Adjusting text colors in various elements, such as buttons and labels, to white for improved readability. - Translating loading messages and "no results found" messages into German for enhanced localization. - Minor adjustments to the loading spinner text. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 946a0075-7e32-454b-b348-9e7f576d7f45 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/60d372ff-2c10-46c7-b01b-10c3435136b0/946a0075-7e32-454b-b348-9e7f576d7f45/B14VAa5
116 lines
3.7 KiB
TypeScript
116 lines
3.7 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="flex items-center justify-center py-20" data-testid="grid-loading">
|
|
<div className="text-center">
|
|
<div className="w-16 h-16 bg-[#da234d] rounded-lg flex items-center justify-center shadow-lg animate-pulse mb-4 mx-auto">
|
|
<div className="w-0 h-0 border-l-[12px] border-l-white border-y-[9px] border-y-transparent ml-1"></div>
|
|
</div>
|
|
<h3 className="text-white text-xl font-bold mb-2">video.folx.tv</h3>
|
|
<p className="text-bunny-light">Videos werden geladen...</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (videos.length === 0) {
|
|
return (
|
|
<div className="text-center py-12">
|
|
<div className="w-12 h-12 bg-[#da234d] rounded-lg flex items-center justify-center shadow-lg mb-4 mx-auto opacity-50">
|
|
<div className="w-0 h-0 border-l-[9px] border-l-white border-y-[7px] border-y-transparent ml-1"></div>
|
|
</div>
|
|
<div className="text-bunny-muted text-lg mb-4" data-testid="text-no-videos">
|
|
Keine Videos gefunden
|
|
</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-[#da234d] 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="w-4 h-4 bg-[#da234d] rounded flex items-center justify-center animate-pulse">
|
|
<div className="w-0 h-0 border-l-[3px] border-l-white border-y-[2px] border-y-transparent"></div>
|
|
</div>
|
|
<span>Mehr laden...</span>
|
|
</>
|
|
) : (
|
|
<>
|
|
<span>Load more videos</span>
|
|
<ChevronDown className="w-4 h-4" />
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
|
|
<BunnyVideoModal
|
|
video={selectedVideo}
|
|
isOpen={isModalOpen}
|
|
onClose={handleCloseModal}
|
|
videos={videos}
|
|
onVideoChange={handleVideoChange}
|
|
/>
|
|
</>
|
|
);
|
|
}
|