folx-tv/client/src/components/adsense.tsx
sebastjanartic ba4d22c513 Ensure ads properly fill available space in the content grid
Adjust ad components to fill vertical space, preventing empty gaps below them in the grid layout.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 517dfa7b-26ac-463d-a6e1-a58c6df97188
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 4400694b-0a33-4db8-aef6-2acb356cdf9b
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/517dfa7b-26ac-463d-a6e1-a58c6df97188/nFw7xof
Replit-Helium-Checkpoint-Created: true
2026-03-02 17:36:29 +00:00

135 lines
3.4 KiB
TypeScript

import { useEffect, useRef, useState } from "react";
type AdFormat = "auto" | "fluid" | "rectangle" | "horizontal" | "vertical" | "autorelaxed";
interface AdSenseProps {
slot: string;
format?: AdFormat;
responsive?: boolean;
className?: string;
style?: Record<string, string>;
layout?: string;
layoutKey?: string;
onAdStatus?: (filled: boolean) => void;
}
export default function AdSense({
slot,
format = "auto",
responsive = true,
className = "",
style,
layout,
layoutKey,
onAdStatus,
}: AdSenseProps) {
const adRef = useRef<HTMLModElement>(null);
const pushed = useRef(false);
useEffect(() => {
if (pushed.current) return;
try {
const adsbygoogle = (window as any).adsbygoogle || [];
adsbygoogle.push({});
pushed.current = true;
} catch (e) {
}
if (onAdStatus) {
const checkAd = () => {
if (adRef.current) {
const ins = adRef.current;
const status = ins.getAttribute("data-ad-status");
if (status === "filled") {
onAdStatus(true);
return;
}
if (status === "unfilled") {
onAdStatus(false);
return;
}
if (ins.clientHeight > 10) {
onAdStatus(true);
return;
}
}
};
const t1 = setTimeout(checkAd, 2000);
const t2 = setTimeout(checkAd, 5000);
return () => { clearTimeout(t1); clearTimeout(t2); };
}
}, []);
return (
<div className={`ad-container ${className}`} data-testid={`ad-slot-${slot}`}>
<ins
ref={adRef}
className="adsbygoogle"
style={style || { display: "block" }}
data-ad-client="ca-pub-4465464714854276"
data-ad-slot={slot}
data-ad-format={format}
data-full-width-responsive={responsive ? "true" : undefined}
{...(layout ? { "data-ad-layout": layout } : {})}
{...(layoutKey ? { "data-ad-layout-key": layoutKey } : {})}
/>
</div>
);
}
export function ArticleCardAd() {
return (
<div className="bg-card rounded-md border border-card-border overflow-hidden h-full min-h-[200px] flex flex-col">
<AdSense
slot="3854634730"
format="fluid"
layoutKey="-6r+cy-10+8a-3"
style={{ display: "block", flex: "1" }}
/>
</div>
);
}
export function InArticleAd() {
return (
<div className="my-8 py-4 border-y border-border/30">
<div className="text-[10px] text-muted-foreground/40 text-center mb-2 uppercase tracking-widest">Anzeige</div>
<AdSense
slot="4154017639"
format="fluid"
layout="in-article"
style={{ display: "block", textAlign: "center" }}
/>
</div>
);
}
export function MultiplexAd() {
return (
<div className="bg-card rounded-md border border-card-border overflow-hidden">
<AdSense
slot="4593001335"
format="autorelaxed"
style={{ display: "block" }}
className="w-full min-h-[250px]"
/>
</div>
);
}
export function SidebarAd() {
const [visible, setVisible] = useState(false);
return (
<div className={`sticky top-4 ${visible ? "" : "hidden"}`}>
<div className="bg-card rounded-md border border-card-border p-4 mt-4">
<AdSense
slot="2398082838"
format="auto"
onAdStatus={(filled) => setVisible(filled)}
/>
</div>
</div>
);
}