videofolxtv/client/src/pages/home.tsx
sebastjanartic 6664335202 Adjust layout to prevent video cards from overlapping
Update the Home page component to adjust the positioning of decorative elements, ensuring they do not obscure video cards in different view modes.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 890577b1-c154-40a4-a177-a0c6d55320c3
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/890577b1-c154-40a4-a177-a0c6d55320c3/SHCPaqp
2025-09-01 17:56:41 +00:00

258 lines
11 KiB
TypeScript

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<Video[]>([]);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
// Fetch videos with optimized loading
const { data: videosResponse, isLoading, refetch } = useQuery<VideosResponse>({
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 (
<div className="has-fixed-header" style={{minHeight: '100vh', background: 'linear-gradient(135deg, hsl(250, 50%, 15%) 0%, hsl(240, 30%, 25%) 100%)', color: 'white'}}>
{/* STICKY HEADER */}
<div className="header-sticky bg-transparent overflow-hidden">
<div className="container py-4">
<div className="flex items-center justify-between">
{/* Left side - Logo */}
<div className="flex items-center space-x-4">
<Link href="/" className="flex items-center space-x-2 hover:opacity-80 transition-opacity">
<div className="w-9 h-9 gradient-primary rounded-lg flex items-center justify-center shadow-lg">
<div className="w-0 h-0 border-l-[10px] border-l-white border-y-[7px] border-y-transparent ml-1"></div>
</div>
<h1 className="text-2xl font-bold text-white tracking-wide">go4.video</h1>
</Link>
</div>
{/* Right side - Navigation + Search */}
<div className="flex items-center gap-4">
{/* Desktop navigation */}
<div className="hidden md:flex items-center space-x-6">
<nav className="flex space-x-6">
<Link href="/" className="text-bunny-light hover:text-bunny-blue transition-colors">
Home
</Link>
<Link href="/folx-stadl" className="text-bunny-light hover:text-bunny-blue transition-colors">
FOLX STADL
</Link>
</nav>
<div className="relative">
<Input
type="search"
placeholder="Videos suchen..."
value={searchQuery}
onChange={(e) => 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"
/>
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
</div>
</div>
{/* Mobile menu button */}
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className="md:hidden p-2 rounded-lg bg-white/10 hover:bg-white/20 transition-colors"
data-testid="button-mobile-menu"
>
{isMobileMenuOpen ? (
<X className="w-6 h-6 text-white" />
) : (
<Menu className="w-6 h-6 text-white" />
)}
</button>
</div>
</div>
</div>
{/* Mobile menu dropdown - kompakten */}
{isMobileMenuOpen && (
<div className="md:hidden border-t border-white/20 bg-bunny-dark/95 backdrop-blur-md">
<div className="px-4 py-3">
{/* Mobile navigation links - horizontal */}
<nav className="flex space-x-6 mb-3">
<Link
href="/"
className="text-bunny-light hover:text-bunny-blue transition-colors text-sm font-medium"
onClick={() => setIsMobileMenuOpen(false)}
>
Home
</Link>
<Link
href="/folx-stadl"
className="text-bunny-light hover:text-bunny-blue transition-colors text-sm font-medium"
onClick={() => setIsMobileMenuOpen(false)}
>
FOLX STADL
</Link>
</nav>
{/* Mobile search - manjši */}
<div className="relative">
<Input
type="search"
placeholder="Search..."
value={searchQuery}
onChange={(e) => 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"
/>
<Search className="absolute left-2.5 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
</div>
</div>
</div>
)}
</div>
<main className="w-full pt-0 pb-8 relative">
{/* Trikotniki na robovih - ne prekrivajo video kartic */}
<div className="absolute top-10 right-2 w-0 h-0 border-l-[70px] border-l-transparent border-r-[70px] border-r-transparent border-b-[100px] border-b-blue-400/8 rotate-12 z-0"></div>
<div className="absolute top-1/2 left-2 w-0 h-0 border-l-[60px] border-l-transparent border-r-[60px] border-r-transparent border-b-[85px] border-b-purple-400/8 -rotate-12 z-0"></div>
<div className="absolute bottom-1/4 right-2 w-0 h-0 border-l-[50px] border-l-transparent border-r-[50px] border-r-transparent border-b-[70px] border-b-cyan-400/8 rotate-45 z-0"></div>
{viewMode === "grid" ? (
<NetflixGrid
videos={allVideos}
isLoading={isLoading}
/>
) : (
<div className="container">
<VideoGrid
videos={allVideos}
isLoading={isLoading}
hasMore={false}
onLoadMore={() => {}}
viewMode={viewMode}
/>
</div>
)}
</main>
{/* Footer with large triangle design */}
<footer className="bunny-gray border-t border-white/20 mt-16 relative overflow-hidden">
{/* Trikotniki v footerju - manjši in bolje pozicionirani */}
<div className="absolute top-0 right-0 w-0 h-0 border-l-[80px] border-l-transparent border-b-[50px] border-b-blue-500/4 z-0"></div>
<div className="absolute bottom-0 left-0 w-0 h-0 border-r-[70px] border-r-transparent border-t-[45px] border-t-purple-500/4 z-0"></div>
<div className="container py-12">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div className="col-span-1 md:col-span-2">
<div className="flex items-center space-x-2 mb-4">
<div className="w-8 h-8 gradient-primary rounded-lg flex items-center justify-center shadow-lg">
<div className="w-0 h-0 border-l-[8px] border-l-white border-y-[5px] border-y-transparent ml-1"></div>
</div>
<h3 className="text-xl font-bold text-bunny-light">go4.video</h3>
</div>
<p className="text-bunny-muted mb-4">
Premium Video-Streaming-Plattform für Volksmusik, Schlager und Shows von Folx TV.
</p>
<div className="flex space-x-4">
<a href="#" className="text-bunny-muted hover:text-bunny-blue transition-colors">
Twitter
</a>
<a href="#" className="text-bunny-muted hover:text-bunny-blue transition-colors">
Facebook
</a>
<a href="#" className="text-bunny-muted hover:text-bunny-blue transition-colors">
YouTube
</a>
</div>
</div>
<div>
<h4 className="font-semibold mb-4 text-bunny-light">Plattform</h4>
<ul className="space-y-2 text-bunny-muted">
<li><a href="#" className="hover:text-bunny-light transition-colors">Hochladen</a></li>
<li><a href="#" className="hover:text-bunny-light transition-colors">Statistiken</a></li>
<li><a href="#" className="hover:text-bunny-light transition-colors">API Docs</a></li>
<li><a href="#" className="hover:text-bunny-light transition-colors">Support</a></li>
</ul>
</div>
<div>
<h4 className="font-semibold mb-4 text-bunny-light">Unternehmen</h4>
<ul className="space-y-2 text-bunny-muted">
<li><a href="#" className="hover:text-bunny-light transition-colors">Über uns</a></li>
<li><a href="#" className="hover:text-bunny-light transition-colors">Datenschutz</a></li>
<li><a href="#" className="hover:text-bunny-light transition-colors">AGB</a></li>
<li><a href="#" className="hover:text-bunny-light transition-colors">Kontakt</a></li>
</ul>
</div>
</div>
<div className="border-t border-gray-700 mt-8 pt-8 text-center text-bunny-muted">
<p>&copy; 2024 go4.video. Alle Rechte vorbehalten.</p>
</div>
</div>
</footer>
</div>
);
}