import { useQuery } from "@tanstack/react-query";
import { Link } from "wouter";
import { type Article } from "@shared/schema";
import { format } from "date-fns";
import { de } from "date-fns/locale";
import { Eye, Play, Images } from "lucide-react";
import { Skeleton } from "@/components/ui/skeleton";
import Header from "@/components/header";
import Footer from "@/components/footer";
import AdSense from "@/components/adsense";
import { PhotoGalleryWidget } from "@/components/photo-gallery";
import { HoroscopeWidget } from "@/components/horoscope-widget";
import { RecipeWidget } from "@/components/recipe-widget";
import { NewsWidget } from "@/components/news-widget";
import { useState, useEffect, useCallback } from "react";
interface GalleryImage {
folder: string;
fileName: string;
thumb: string;
large: string;
}
function thumbUrl(src: string | null): string {
if (!src) return "/images/article-1.png";
if (src.endsWith(".webp")) return src.replace(".webp", "-thumb.webp");
return src;
}
function timeAgo(date: Date): string {
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffH = Math.floor(diffMs / 3600000);
const diffD = Math.floor(diffMs / 86400000);
if (diffH < 1) return "Gerade eben";
if (diffH < 24) return `vor ${diffH} Std.`;
if (diffD < 7) return `vor ${diffD} T.`;
return format(date, "d. MMM yyyy", { locale: de });
}
function HeroCard({ article }: { article: Article }) {
const isVideo = article.category === "Video";
return (

{isVideo && (
)}
{article.category}
{timeAgo(new Date(article.publishedAt))}
{article.title}
{article.excerpt}
);
}
function GalleryHeroCard({ images }: { images: GalleryImage[] }) {
const [idx, setIdx] = useState(0);
useEffect(() => {
const timer = setInterval(() => setIdx((i) => (i + 1) % images.length), 10000);
return () => clearInterval(timer);
}, [images.length]);
return (
Fotogalerie
Backstage & Events
{images.length} exklusive Fotos aus der Welt der Volksmusik
);
}
function MediumCard({ article }: { article: Article }) {
const isVideo = article.category === "Video";
return (
{article.author}
{timeAgo(new Date(article.publishedAt))}
{article.title}
{article.excerpt}
{article.views.toLocaleString()}
);
}
function SideCard({ article }: { article: Article }) {
const isVideo = article.category === "Video";
return (
{article.author}
{timeAgo(new Date(article.publishedAt))}
{article.title}
{article.excerpt}
);
}
function NativeAdCard() {
return (
);
}
function TopStoriesList({ articles }: { articles: Article[] }) {
return (
Top-Storys
{articles.slice(0, 5).map((article) => (
{article.title}
{article.author}
{timeAgo(new Date(article.publishedAt))}
))}
);
}
function FeaturedCarousel({ articles, popular, galleryImages }: { articles: Article[]; popular?: Article[]; galleryImages?: GalleryImage[] }) {
const hasGallery = galleryImages && galleryImages.length > 0;
const articlePages = Math.min(5, Math.max(1, articles.length));
const total = articlePages + (hasGallery ? 1 : 0);
const [page, setPage] = useState(0);
const [paused, setPaused] = useState(false);
const next = useCallback(() => {
setPage((p) => (p + 1) % total);
}, [total]);
useEffect(() => {
if (paused || total <= 1) return;
const timer = setInterval(next, 8000);
return () => clearInterval(timer);
}, [paused, next, total]);
const isGalleryPage = hasGallery && page === total - 1;
const isWidePage = page === 1;
let hero: Article | null = null;
if (!isGalleryPage && articles.length > 0) {
hero = articles[page % articles.length];
}
return (
setPaused(true)} onMouseLeave={() => setPaused(false)}>
{isGalleryPage && galleryImages ? (
) : hero ? (
) : null}
{popular && popular.length > 0 && }
{total > 1 && (
{Array.from({ length: total }).map((_, i) => (
)}
);
}
function BentoSkeleton() {
return (
);
}
export default function Home() {
const { data: articles, isLoading } = useQuery({
queryKey: ["/api/articles"],
});
const { data: popular } = useQuery({
queryKey: ["/api/articles/popular"],
});
const { data: galleryImages } = useQuery({
queryKey: ["/api/gallery"],
});
if (isLoading || !articles) {
return (
);
}
const row2Left = articles.slice(0, 2);
const row3Middle = articles.slice(2, 4);
const row4Articles = articles.slice(4, 7);
const row5Articles = articles.slice(7, 10);
return (
{row2Left.map((a) => (
))}
{row3Middle.map((a) => (
))}
{row4Articles.length > 0 && (
{row4Articles.map((a) => (
))}
)}
{row5Articles.length > 0 && (
{row5Articles.map((a) => (
))}
)}
);
}