From 64600c4f285fa4359eeb3a97e49c5b80c25a4d2f Mon Sep 17 00:00:00 2001 From: Local Administrator Date: Thu, 25 Jun 2026 16:15:36 +0000 Subject: [PATCH] Manufacturer profile: fix light-theme text contrast and BMD logo --- src/app/manufacturers/[slug]/page.tsx | 940 +++++++++++++------------- 1 file changed, 474 insertions(+), 466 deletions(-) diff --git a/src/app/manufacturers/[slug]/page.tsx b/src/app/manufacturers/[slug]/page.tsx index 1829ca8..cbc8b0b 100644 --- a/src/app/manufacturers/[slug]/page.tsx +++ b/src/app/manufacturers/[slug]/page.tsx @@ -1,478 +1,486 @@ -import type { Metadata } from "next"; -import { notFound } from "next/navigation"; -import Link from "next/link"; -import Header from "@/components/Header"; -import Footer from "@/components/Footer"; -import { createClient } from "@/lib/supabase/server"; -import BackLink from "./BackLink"; - -export const revalidate = 1800; - +import type { Metadata } from "next"; +import { notFound } from "next/navigation"; +import Link from "next/link"; +import Header from "@/components/Header"; +import Footer from "@/components/Footer"; +import { createClient } from "@/lib/supabase/server"; +import BackLink from "./BackLink"; + +export const revalidate = 1800; + type Params = { slug: string }; -// Known show date ranges. Booth numbers only render when the show is -// upcoming within 90 days; otherwise the row is shown without a booth. -const SHOW_DATES: Record = { - "NAB Show:2026": { start: "2026-04-11", end: "2026-04-16" }, - "NAB Show NY:2026": { start: "2026-10-21", end: "2026-10-23" }, - "IBC:2026": { start: "2026-09-11", end: "2026-09-14" }, - "NAB Show:2027": { start: "2027-04-17", end: "2027-04-22" }, +const LOGO_OVERRIDES: Record = { + "blackmagic-design": "/img/partners/blackmagic-design.png", }; -function normaliseShowName(raw: string | null | undefined): string { - const s = (raw || "").trim(); - if (!s) return s; - if (/^nab(\s*show)?$/i.test(s)) return "NAB Show"; - if (/^nab\s*(show\s*)?(ny|new\s*york)$/i.test(s)) return "NAB Show NY"; - if (/^ibc(\s*show)?$/i.test(s)) return "IBC"; - return s; -} - -function shouldShowBooth(show: string, year: number | null): boolean { - if (!year) return false; - const dates = SHOW_DATES[`${show}:${year}`]; - if (!dates) return false; - const today = new Date(); - const start = new Date(dates.start + "T00:00:00Z"); - const end = new Date(dates.end + "T23:59:59Z"); - if (today > end) return false; - const daysUntilStart = (start.getTime() - today.getTime()) / 86_400_000; - return daysUntilStart <= 90; -} - -async function loadManufacturer(slug: string) { - const supabase = await createClient(); - const { data } = await supabase - .from("tracked_companies") - .select( - "id, slug, company_name, bio, bio_source, logo_url, company_website, contact_email, contact_url, phone, hq_address, hq_city, hq_country, linkedin_url, twitter_handle, youtube_url, press_url, categories, exhibits_nab, exhibits_ibc, mention_count, last_mentioned, featured, ad_status" - ) - .eq("slug", slug) - .eq("directory_visible", true) - .maybeSingle(); - if (!data) return null; - - const { data: shows } = await supabase - .from("trade_show_exhibitors") - .select("show, show_year, booth, description, url, website") - .eq("exhibitor_name", data.company_name) - .order("show_year", { ascending: false }); - - const { data: pressReleases } = await supabase - .from("press_releases") - .select("title, slug, published_at, source_url") - .eq("manufacturer_id", data.id) - .order("published_at", { ascending: false }) - .limit(10); - - const { data: executives } = await supabase - .from("manufacturer_executives") - .select("id, name, title, photo_url, linkedin_url, bio") - .eq("company_id", data.id) - .order("sort_order") - .order("name"); - - // Recent stories: title contains the company name. The same heuristic the - // article auto-linker and the hover card use — keeps the directory in sync - // with the editorial coverage even when manufacturer_id isn't backfilled. - const needle = String(data.company_name || "").trim(); - let recentStories: any[] = []; - if (needle.length >= 3) { - const { data: stories } = await supabase - .from("wp_imported_posts") - .select("wp_slug, title, excerpt, featured_image, wp_published_at, category") - .eq("status", "published") - .ilike("title", `%${needle.replace(/[%_]/g, "")}%`) - .order("wp_published_at", { ascending: false, nullsFirst: false }) - .limit(12); - recentStories = stories || []; - } - - return { - company: data, - shows: shows || [], - pressReleases: pressReleases || [], - executives: executives || [], - recentStories, - }; -} - -export async function generateMetadata({ - params, -}: { - params: Promise; -}): Promise { - const { slug } = await params; - const result = await loadManufacturer(slug); - if (!result) { - return { title: "Manufacturer not found — AV Beat" }; - } - const { company } = result; - const title = `${company.company_name} — Manufacturer Profile | AV Beat`; - const description = - (company.bio || "").slice(0, 200) || - `${company.company_name} is a broadcast industry manufacturer covered by AV Beat.`; - return { - title, - description, - alternates: { canonical: `/manufacturers/${slug}` }, - openGraph: { - title, - description, - url: `https://avbeat.com/manufacturers/${slug}`, - type: "profile", - ...(company.logo_url ? { images: [{ url: company.logo_url }] } : {}), - }, - }; -} - -export default async function ManufacturerProfile({ - params, -}: { - params: Promise; -}) { - const { slug } = await params; - const result = await loadManufacturer(slug); - if (!result) notFound(); - const { company, shows, pressReleases, executives, recentStories } = result; - - const jsonLd = { - "@context": "https://schema.org", - "@type": "Organization", - name: company.company_name, - description: company.bio || undefined, - url: company.company_website || undefined, - logo: company.logo_url || undefined, - sameAs: [ - company.linkedin_url, - company.twitter_handle ? `https://twitter.com/${company.twitter_handle}` : null, - company.youtube_url, - ].filter(Boolean), - address: - company.hq_city || company.hq_country - ? { - "@type": "PostalAddress", - addressLocality: company.hq_city || undefined, - addressCountry: company.hq_country || undefined, - } - : undefined, - }; - - return ( -
-
-