diff --git a/src/app/home-page/page.tsx b/src/app/home-page/page.tsx index 5c0d830..b179687 100644 --- a/src/app/home-page/page.tsx +++ b/src/app/home-page/page.tsx @@ -4,7 +4,7 @@ import Header from "@/components/Header"; import Footer from "@/components/Footer"; import FeaturedBentoFromDb from '@/components/FeaturedBentoFromDb'; import FeaturedCarouselServer from '@/components/FeaturedCarouselServer'; -import DoubleTicker from '@/components/DoubleTicker'; +import LiveWireTicker from '@/components/LiveWireTicker'; import NewsTicker from "./components/NewsTicker"; import FeaturedBento from "./components/FeaturedBento"; import SpotlightCarousel from "./components/SpotlightCarousel"; @@ -147,10 +147,10 @@ export default function HomePage() {

Broadcast Beat — Broadcast Engineering News & Insights

- {/* Scrolling news + forum tickers */} + {/* Scrolling news ticker */}
}> - +
diff --git a/src/components/DoubleTicker.tsx b/src/components/DoubleTicker.tsx deleted file mode 100644 index a76a06f..0000000 --- a/src/components/DoubleTicker.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import Link from "next/link"; -import { createClient } from "@supabase/supabase-js"; - -export const dynamic = "force-dynamic"; - -interface TickerItem { - href: string; - title: string; -} - -export default async function DoubleTicker() { - const sb = createClient( - process.env.NEXT_PUBLIC_SUPABASE_URL!, - process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, - { - db: { schema: (process.env.NEXT_PUBLIC_SUPABASE_SCHEMA || "bb") as "public" }, - auth: { persistSession: false }, - } - ); - - const [wireRes, forumRes] = await Promise.all([ - sb - .from("wp_imported_posts") - .select("wp_slug, title") - .eq("status", "published") - .order("wp_published_at", { ascending: false, nullsFirst: false }) - .limit(14), - sb - .from("forum_threads") - .select("id, title") - .order("last_reply_at", { ascending: false, nullsFirst: false }) - .limit(14), - ]); - - const wire: TickerItem[] = (wireRes.data || []).map((r: any) => ({ - href: `/news/${r.wp_slug}`, - title: r.title, - })); - const forum: TickerItem[] = (forumRes.data || []).map((r: any) => ({ - href: `/forum/thread/${r.id}`, - title: r.title, - })); - - // Fallback to keep layout sensible if either feed is empty - const wireItems = wire.length > 0 ? wire : [{ href: "/news", title: "Latest broadcast industry news loading…" }]; - const forumItems = forum.length > 0 ? forum : [{ href: "/forum", title: "Join the conversation in the forum" }]; - - return ( -
- {/* LANE 1 — LIVE WIRE (red) */} -
- - -
-
- {[...wireItems, ...wireItems].map((item, i) => ( - - - {item.title} - - ))} -
-
-
- - {/* LANE 2 — RECENT FORUM POSTS (teal-green) */} -
- - -
-
- {[...forumItems, ...forumItems].map((item, i) => ( - - - {item.title} - - ))} -
-
-
-
- ); -} diff --git a/src/components/LiveWireTicker.tsx b/src/components/LiveWireTicker.tsx new file mode 100644 index 0000000..11d2235 --- /dev/null +++ b/src/components/LiveWireTicker.tsx @@ -0,0 +1,118 @@ +import Link from "next/link"; +import { createClient } from "@supabase/supabase-js"; + +export const dynamic = "force-dynamic"; + +interface Item { + slug: string; + title: string; + published_at: string; + source_code: string; +} + +const SOURCE_CODES: { match: RegExp; code: string }[] = [ + { match: /blackmagic|davinci/i, code: "BMD" }, + { match: /magewell/i, code: "MGW" }, + { match: /aja/i, code: "AJA" }, + { match: /sony/i, code: "SONY" }, + { match: /matrox/i, code: "MTRX" }, + { match: /telestream/i, code: "TLST" }, + { match: /grass valley/i, code: "GV" }, + { match: /lawo/i, code: "LAWO" }, + { match: /calrec/i, code: "CLRC" }, + { match: /zixi/i, code: "ZIXI" }, + { match: /liveu/i, code: "LVU" }, + { match: /netflix/i, code: "NFLX" }, + { match: /youtube/i, code: "YT" }, + { match: /amazon|aws/i, code: "AWS" }, +]; + +function codeFor(title: string): string { + for (const { match, code } of SOURCE_CODES) if (match.test(title)) return code; + return "WIRE"; +} + +function hhmm(iso: string): string { + const d = new Date(iso); + const h = String(d.getUTCHours()).padStart(2, "0"); + const m = String(d.getUTCMinutes()).padStart(2, "0"); + return `${h}:${m}`; +} + +export default async function LiveWireTicker() { + const sb = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + db: { schema: (process.env.NEXT_PUBLIC_SUPABASE_SCHEMA || "bb") as "public" }, + auth: { persistSession: false }, + } + ); + + const [wp, ai] = await Promise.all([ + sb + .from("wp_imported_posts") + .select("wp_slug, title, wp_published_at") + .eq("status", "published") + .order("wp_published_at", { ascending: false }) + .limit(12), + sb + .from("ai_rewritten_articles") + .select("slug, title, published_at") + .eq("status", "published") + .order("published_at", { ascending: false, nullsFirst: false }) + .limit(6), + ]); + + const items: Item[] = []; + for (const r of (wp.data || []) as any[]) { + items.push({ + slug: r.wp_slug, + title: r.title, + published_at: r.wp_published_at, + source_code: codeFor(r.title || ""), + }); + } + for (const r of (ai.data || []) as any[]) { + items.push({ + slug: r.slug, + title: r.title, + published_at: r.published_at, + source_code: codeFor(r.title || ""), + }); + } + items.sort( + (a, b) => new Date(b.published_at).getTime() - new Date(a.published_at).getTime() + ); + + const display = items.slice(0, 14); + + return ( +
+
+ + Live wire + +
+
+ {[...display, ...display].map((it, i) => ( + + [{hhmm(it.published_at)}] + [{it.source_code}] + {it.title} + + ))} +
+
+
+
+ ); +} diff --git a/src/styles/tailwind.css b/src/styles/tailwind.css index a07e74f..15f4bde 100644 --- a/src/styles/tailwind.css +++ b/src/styles/tailwind.css @@ -807,197 +807,4 @@ h1, h2, h3 { .ProseMirror strong { font-weight: 700; color: #fff; } .ProseMirror em { font-style: italic; } .ProseMirror u { text-decoration: underline; } -.ProseMirror s { text-decoration: line-through; } - -/* ===================== - DOUBLE TICKER (LIVE WIRE + RECENT FORUM POSTS) - ===================== */ -.bb-ticker-stack { - width: 100%; - border-bottom: 1px solid #1a1a1a; -} - -.bb-ticker { - display: flex; - align-items: stretch; - height: 34px; - width: 100%; - overflow: hidden; - position: relative; -} - -.bb-ticker--wire { - background: linear-gradient(90deg, #0a0a0a 0%, #161616 50%, #0a0a0a 100%); - border-bottom: 1px solid #1f1212; -} - -.bb-ticker--forum { - background: linear-gradient(90deg, #08120e 0%, #0f1d18 50%, #08120e 100%); -} - -.bb-ticker-label { - flex-shrink: 0; - display: inline-flex; - align-items: center; - gap: 8px; - padding: 0 16px; - font-family: var(--font-body); - font-size: 11px; - font-weight: 800; - letter-spacing: 0.22em; - color: #ffffff; - white-space: nowrap; - position: relative; - z-index: 2; -} - -.bb-ticker-label--red { - background: linear-gradient(90deg, #d40000 0%, #a30000 100%); - box-shadow: 0 0 18px rgba(212, 0, 0, 0.45), inset 0 -1px 0 rgba(255, 255, 255, 0.05); - clip-path: polygon(0 0, 100% 0, calc(100% - 10px) 100%, 0 100%); - padding-right: 24px; -} - -.bb-ticker-label--green { - background: linear-gradient(90deg, #0c8a63 0%, #086149 100%); - box-shadow: 0 0 18px rgba(12, 138, 99, 0.40), inset 0 -1px 0 rgba(255, 255, 255, 0.05); - clip-path: polygon(0 0, 100% 0, calc(100% - 10px) 100%, 0 100%); - padding-right: 24px; -} - -.bb-ticker-pulse { - display: inline-block; - width: 7px; - height: 7px; - border-radius: 999px; - background: #ffffff; - box-shadow: 0 0 8px rgba(255, 255, 255, 0.9); - animation: bb-ticker-pulse-anim 1.4s ease-in-out infinite; -} - -.bb-ticker-pulse--green { - animation-duration: 1.8s; -} - -@keyframes bb-ticker-pulse-anim { - 0%, 100% { opacity: 1; transform: scale(1); } - 50% { opacity: 0.4; transform: scale(1.25); } -} - -.bb-ticker-mask { - flex: 1; - min-width: 0; - overflow: hidden; - position: relative; - -webkit-mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%); - mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%); -} - -.bb-ticker-track { - display: inline-flex; - align-items: center; - width: max-content; - white-space: nowrap; - animation-name: bb-ticker-scroll; - animation-timing-function: linear; - animation-iteration-count: infinite; - will-change: transform; -} - -/* Different speeds so the two lanes never sync up — feels alive */ -.bb-ticker-track--wire { animation-duration: 65s; } -.bb-ticker-track--forum { animation-duration: 82s; } - -.bb-ticker-track:hover, -.bb-ticker-track:focus-within { - animation-play-state: paused; -} - -@keyframes bb-ticker-scroll { - 0% { transform: translate3d(0, 0, 0); } - 100% { transform: translate3d(-50%, 0, 0); } -} - -.bb-ticker-item { - display: inline-flex; - align-items: center; - gap: 10px; - padding: 0 22px; - height: 34px; - text-decoration: none; - font-family: var(--font-body); - font-size: 13px; - font-weight: 500; - letter-spacing: 0.005em; - color: #d8d8d8; - transition: color 0.18s ease; - border-right: 1px solid rgba(255, 255, 255, 0.05); -} - -.bb-ticker-item--wire:hover { color: #ff6b6b; } -.bb-ticker-item--forum:hover { color: #5eead4; } - -.bb-ticker-bullet { - flex-shrink: 0; - font-weight: 700; - color: rgba(255, 255, 255, 0.35); -} - -.bb-ticker-item--wire:hover .bb-ticker-bullet { color: #ff6b6b; } -.bb-ticker-item--forum:hover .bb-ticker-bullet { color: #5eead4; } - -/* ===================== - BROWSE NAV BAR (sits below the 728x90 header banner) - ===================== */ -.bb-browse-bar { - background: linear-gradient(180deg, #0b0b0b 0%, #0e0e0e 100%); - border-top: 1px solid #1a1a1a; - border-bottom: 1px solid #1a1a1a; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); -} - -.bb-browse-row { - display: flex; - align-items: stretch; - gap: 0; - height: 44px; -} - -.bb-browse-item { - position: relative; - display: inline-flex; - align-items: center; - padding: 0 16px; - font-family: var(--font-body); - font-size: 12px; - font-weight: 700; - letter-spacing: 0.06em; - text-transform: uppercase; - color: #cccccc; - text-decoration: none; - border-right: 1px solid #1a1a1a; - transition: background 0.15s ease, color 0.15s ease; -} - -.bb-browse-item:first-of-type { - border-left: 1px solid #1a1a1a; -} - -.bb-browse-item:hover, -.bb-browse-item[aria-expanded="true"] { - background: #161616; - color: var(--color-accent); -} - -.bb-browse-item .bb-browse-caret { - display: inline-block; - margin-left: 6px; - font-size: 8px; - opacity: 0.7; - transform: translateY(-1px); - transition: transform 0.15s ease; -} - -.bb-browse-item[aria-expanded="true"] .bb-browse-caret { - transform: rotate(180deg) translateY(1px); -} \ No newline at end of file +.ProseMirror s { text-decoration: line-through; } \ No newline at end of file