Files
yourwillyourwish/components/UpcomingWebinars.tsx
2026-02-06 21:44:04 -06:00

135 lines
6.6 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Link from "next/link";
import { useEffect, useState } from "react";
export default function UpcomingWebinars() {
const [data, setData] = useState<any>(null);
const [categories, setCategories] = useState<string[]>([]);
const [active, setActive] = useState<string>("All");
useEffect(() => {
fetch("/api/public/app-setup")
.then((r) => r.json())
.then((d) => setCategories(["All", ...(d?.setup?.categories || [])]))
.catch(() => setCategories(["All"]));
}, []);
useEffect(() => {
fetch("/api/webinars")
.then((r) => r.json())
.then(setData)
.catch(() => setData({ ok: false, message: "Something went wrong. Please contact the website owner." }));
}, []);
const webinars = data?.ok ? data.webinars : [];
const filtered = active === "All" ? webinars : webinars.filter((w: any) => w.category === active);
return (
<section className="py-28 bg-gradient-to-br from-gray-50 via-white to-blue-50 dark:from-slate-900 dark:via-darkbg dark:to-slate-900">
<div className="max-w-7xl mx-auto px-6">
<div className="space-y-8">
{/* Header */}
<div className="text-center space-y-3">
<h2 className="text-5xl font-black text-gray-900 dark:text-white">
📚 Upcoming <span className="text-primary">Webinars</span>
</h2>
<p className="text-lg text-gray-600 dark:text-gray-300 font-medium">Register now to secure your spot in our expert-led sessions</p>
</div>
{/* Category Filter */}
<div className="flex flex-wrap gap-3 justify-center">
{categories.map((c) => (
<button
key={c}
onClick={() => setActive(c)}
className={`px-6 py-2.5 rounded-full text-sm font-bold transition-all duration-300 border-2 ${
active === c
? "bg-primary text-white border-transparent shadow-glow hover:shadow-lg"
: "border-gray-300 dark:border-slate-600 text-gray-700 dark:text-gray-300 hover:border-primary hover:text-primary dark:hover:text-primary"
}`}
>
{c}
</button>
))}
</div>
{/* Webinars Table */}
<div className="overflow-hidden rounded-2xl shadow-soft border border-gray-200 dark:border-slate-700">
<div className="overflow-x-auto">
<div className="bg-gray-50 dark:bg-slate-800 grid grid-cols-5 gap-4 px-6 py-4 text-xs font-bold text-gray-700 dark:text-gray-300 uppercase tracking-wider">
<div className="col-span-2">📝 Webinar</div>
<div>📅 Date & Time</div>
<div>👨🏫 Instructor</div>
<div className="text-right">💰 Price</div>
</div>
<div className="divide-y divide-gray-200 dark:divide-slate-700 bg-white dark:bg-slate-800/50">
{!data ? (
<div className="px-6 py-8 text-center">
<div className="inline-flex items-center gap-2 text-gray-600 dark:text-gray-400 font-medium">
<div className="w-4 h-4 border-2 border-primary border-r-transparent rounded-full animate-spin"></div>
Loading webinars...
</div>
</div>
) : !data.ok ? (
<div className="px-6 py-8 text-center text-danger font-semibold">{data.message}</div>
) : filtered.length === 0 ? (
<div className="px-6 py-8 text-center text-gray-600 dark:text-gray-400 font-medium">No webinars found in this category</div>
) : (
filtered.map((w: any) => (
<div key={w.id} className="grid grid-cols-5 gap-4 px-6 py-4 items-center hover:bg-gray-50 dark:hover:bg-slate-700/30 transition-colors duration-200 group">
{/* Webinar Title & Tags */}
<div className="col-span-2 space-y-2">
<div className="font-bold text-gray-900 dark:text-white group-hover:text-primary transition-colors">{w.title}</div>
<div className="flex gap-2 flex-wrap">
<span className={`px-3 py-1 rounded-full text-xs font-bold ${
w.priceCents <= 0
? "bg-success/15 text-success dark:text-emerald-400"
: "bg-secondary/15 text-secondary dark:text-pink-400"
}`}>
{w.priceCents <= 0 ? "✨ FREE" : "⭐ PREMIUM"}
</span>
<span className="px-3 py-1 rounded-full text-xs font-bold bg-primary/15 text-primary dark:text-indigo-400">
{w.category}
</span>
</div>
</div>
{/* Date & Time */}
<div className="text-sm font-semibold text-gray-600 dark:text-gray-400">
{new Date(w.startAt).toLocaleDateString()} <br />
<span className="text-xs opacity-80">{new Date(w.startAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</span>
</div>
{/* Instructor */}
<div className="text-sm font-semibold text-gray-600 dark:text-gray-400">{w.speaker}</div>
{/* Price & Button */}
<div className="flex items-center justify-end gap-4">
<div className={`text-lg font-black ${w.priceCents <= 0 ? "text-success" : "text-primary"}`}>
{w.priceCents <= 0 ? "FREE" : `$${(w.priceCents / 100).toFixed(0)}`}
</div>
<Link href={`/webinars/${w.id}`} className="btn-primary !px-5 !py-2.5 text-sm font-bold whitespace-nowrap">
{w.priceCents <= 0 ? "🎓 Register" : "💳 Purchase"}
</Link>
</div>
</div>
))
)}
</div>
</div>
</div>
{/* View All Link */}
<div className="text-center">
<Link href="/webinars" className="inline-flex items-center gap-2 text-lg font-bold text-primary hover:text-secondary transition-colors duration-300 hover-lift">
🔗 View All Webinars <span className="group-hover:translate-x-1 transition-transform"></span>
</Link>
</div>
</div>
</div>
</section>
);
}