Files
avbeat-com/src/components/SponsorLogoStrip.tsx

116 lines
4.1 KiB
TypeScript

import Link from "next/link";
import { createAdminClient } from "@/lib/supabase/admin";
type Sponsor = {
slug: string;
name: string;
logoUrl: string | null;
};
/** Partner logos that need alternate assets on dark homepage bands. */
const LOGO_OVERRIDES: Record<string, string> = {
// Full-color wordmark PNG reads cleanly on the white logo tile (unlike the gray SVG).
"blackmagic-design": "/img/partners/blackmagic-design.png",
"magewell": "/img/partners/magewell.png",
};
function resolveLogoUrl(slug: string, logoUrl: string | null): string {
return LOGO_OVERRIDES[slug] || logoUrl || "";
}
/**
* Content Partners strip — mirrors Broadcast Beat partner list (bb schema +
* broadcastbeat advertisers) so both RMP sites show the same logos.
*/
async function fetchSponsors(): Promise<Sponsor[]> {
try {
const adv = createAdminClient("adv");
const { data: ads } = await adv
.from("active_advertisers_by_property")
.select("company_name_lower")
.eq("property", "broadcastbeat");
const names = Array.from(new Set((ads || []).map((r: any) => String(r.company_name_lower))));
const bb = createAdminClient("bb");
const bySlug = new Map<string, Sponsor>();
if (names.length > 0) {
const { data: dir } = await bb
.from("tracked_companies")
.select("slug, company_name, logo_url")
.eq("directory_visible", true)
.in("company_name", names.map((n) => n));
for (const d of (dir || []) as any[]) {
bySlug.set(d.slug, { slug: d.slug, name: d.company_name, logoUrl: d.logo_url || null });
}
const matchedNames = new Set((dir || []).map((d: any) => String(d.company_name).toLowerCase()));
const missing = names.filter((n) => !matchedNames.has(n));
for (const n of missing) {
const { data: hit } = await bb
.from("tracked_companies")
.select("slug, company_name, logo_url")
.eq("directory_visible", true)
.ilike("company_name", n)
.limit(1)
.maybeSingle();
if (hit) bySlug.set(hit.slug, { slug: hit.slug, name: hit.company_name, logoUrl: hit.logo_url || null });
}
}
const { data: pinned } = await bb
.from("tracked_companies")
.select("slug, company_name, logo_url")
.eq("directory_visible", true)
.eq("featured", true)
.limit(40);
for (const d of (pinned || []) as any[]) {
if (!bySlug.has(d.slug)) {
bySlug.set(d.slug, { slug: d.slug, name: d.company_name, logoUrl: d.logo_url || null });
}
}
return Array.from(bySlug.values()).filter((s) => resolveLogoUrl(s.slug, s.logoUrl));
} catch {
return [];
}
}
export default async function SponsorLogoStrip() {
const sponsors = await fetchSponsors();
if (sponsors.length === 0) return null;
return (
<section className="max-w-container mx-auto px-4" aria-label="Content partners">
<div className="bg-[#0d1520] border border-[#DCE6F2] py-6 md:py-8 px-4">
<div className="flex items-center gap-4 mb-3">
<span className="text-[10px] uppercase tracking-widest text-[#1D4ED8] font-bold">
Content Partners
</span>
<div className="flex-1 h-px bg-[#DCE6F2]" />
<Link href="/advertise" className="text-[10px] text-[#888] hover:text-[#1D4ED8] font-mono">
Advertise
</Link>
</div>
<div className="flex flex-wrap items-center justify-center gap-x-8 gap-y-4">
{sponsors.map((s) => (
<Link
key={s.slug}
href={`/manufacturers/${s.slug}`}
data-company-slug={s.slug}
className="block opacity-70 hover:opacity-100 transition-opacity"
title={s.name}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={resolveLogoUrl(s.slug, s.logoUrl)}
alt={s.name}
className="h-14 md:h-16 w-auto object-contain max-w-[180px] bg-white p-2 rounded"
loading="lazy"
/>
</Link>
))}
</div>
</div>
</section>
);
}