Initial commit

This commit is contained in:
Developer
2026-02-06 21:44:04 -06:00
commit f85e93c7a6
151 changed files with 22916 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
"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>
);
}