import { useState, useEffect } from "react"; import { useQuery } from "@tanstack/react-query"; import { type Video } from "@shared/schema"; import VideoGrid from "@/components/video-grid"; import { Link } from "wouter"; import { Input } from "@/components/ui/input"; import { Search, Menu, X } from "lucide-react"; import NetflixGrid from "@/components/netflix-grid"; import go4LogoPath from "@assets/go4_1756394900352.png"; interface VideosResponse { videos: Video[]; total: number; hasMore: boolean; } export default function Home() { const [searchQuery, setSearchQuery] = useState(""); const [viewMode, setViewMode] = useState<"grid" | "list">("grid"); const [offset, setOffset] = useState(0); const [allVideos, setAllVideos] = useState([]); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); // Fetch videos with optimized loading const { data: videosResponse, isLoading, refetch } = useQuery({ queryKey: ["/api/videos", { limit: 150, // Naloži dovolj videov za vse kategorije offset: 0, search: searchQuery || undefined }], queryFn: async ({ queryKey }) => { const [, params] = queryKey as [string, any]; const searchParams = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined) { searchParams.append(key, String(value)); } }); const response = await fetch(`/api/videos?${searchParams}`); if (!response.ok) { throw new Error('Failed to fetch videos'); } return response.json(); }, staleTime: 5 * 60 * 1000, // 5 minutes cache - much faster gcTime: 10 * 60 * 1000, // 10 minutes retention refetchOnWindowFocus: false, // Don't refetch on focus refetchOnReconnect: false // Don't refetch on reconnect }); // Update videos when new data comes in useEffect(() => { if (videosResponse) { setAllVideos(videosResponse.videos); } }, [videosResponse]); // Reset videos when search changes const handleSearch = (query: string) => { setSearchQuery(query); setAllVideos([]); }; // Only refetch when search changes, not offset (for speed) useEffect(() => { if (searchQuery !== undefined) { refetch(); } }, [searchQuery, refetch]); return (
{/* STICKY HEADER */}
{/* Left side - Logo */}

go4.video

{/* Right side - Navigation + Search */}
{/* Desktop navigation */}
setSearchQuery(e.target.value)} className="bg-white border border-gray-300 rounded-lg px-4 py-2 pl-10 text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:border-bunny-blue transition-colors w-64" />
{/* Mobile menu button */}
{/* Mobile menu dropdown - kompakten */} {isMobileMenuOpen && (
{/* Mobile navigation links - horizontal */} {/* Mobile search - manjši */}
setSearchQuery(e.target.value)} className="bg-white border border-gray-300 rounded-lg px-3 py-2 pl-9 text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:border-bunny-blue transition-colors w-full" />
)}
{/* Trikotniki na robovih - ne prekrivajo video kartic */}
{viewMode === "grid" ? ( ) : ( {}} viewMode={viewMode} /> )}
{/* Footer with large triangle design */}
); }