LiveDisplayX / src / app / display / twitch / page.tsx
page.tsx
Raw
"use client";

import { useEffect, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import {
  Clock,
  TwitchIcon,
  Calendar,
  Users,
  Trophy,
  Gamepad2,
} from "lucide-react";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay } from "swiper/modules";
import Image from "next/image";
import useSWR from "swr";

// Import Swiper styles
import "swiper/css";
import "swiper/css/autoplay";

interface Event {
  id: string;
  title: string;
  description: string;
  startTime: string;
  endTime: string;
  type: "tournament" | "special" | "maintenance";
}

interface StreamData {
  defaultStream: string;
  events: Event[];
}

const openingHours = [
  { day: "Mandag", hours: "Stengt" },
  { day: "Tirsdag", hours: "16:30–22:00" },
  { day: "Onsdag", hours: "16:30–22:00" },
  { day: "Torsdag", hours: "16:30–22:00" },
  { day: "Fredag", hours: "17:00–00:00" },
  { day: "Lørdag", hours: "14:00–00:00" },
  { day: "Søndag", hours: "14:00–21:00" },
];

const sponsors = [
  {
    name: "Sponsor 1",
    image:
      "https://images.unsplash.com/photo-1599305445671-ac291c95aaa9?w=200&h=100&fit=crop",
  },
  {
    name: "Sponsor 2",
    image:
      "https://images.unsplash.com/photo-1599305445671-ac291c95aaa9?w=200&h=100&fit=crop",
  },
  {
    name: "Sponsor 3",
    image:
      "https://images.unsplash.com/photo-1599305445671-ac291c95aaa9?w=200&h=100&fit=crop",
  },
];

const exampleEvents = [
  {
    id: "1",
    title: "CS2 Tournament Finals",
    description: "Grand finals of the Counter-Strike 2 Championship",
    startTime: "2024-04-15T14:00:00",
    endTime: "2024-04-15T20:00:00",
    type: "tournament" as const,
    participants: 16,
  },
  {
    id: "2",
    title: "Community Game Night",
    description: "Join us for a night of party games and prizes",
    startTime: "2024-04-16T18:00:00",
    endTime: "2024-04-16T23:00:00",
    type: "special" as const,
    participants: 24,
  },
  {
    id: "3",
    title: "Valorant Tournament",
    description: "Monthly Valorant championship with cash prizes",
    startTime: "2024-04-17T15:00:00",
    endTime: "2024-04-17T21:00:00",
    type: "tournament" as const,
    participants: 20,
  },
  {
    id: "4",
    title: "Retro Gaming Evening",
    description: "Classic console games from the 90s",
    startTime: "2024-04-18T17:00:00",
    endTime: "2024-04-18T22:00:00",
    type: "special" as const,
    participants: 30,
  },
];

export default function TwitchDisplay() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [channel, setChannel] = useState<string>(
    searchParams.get("channel") || "hasanabi"
  );

  const fetcher = (url: string) => fetch(url).then((r) => r.json());
  const { data } = useSWR<StreamData>("/api/events", fetcher, {
    refreshInterval: 30000,
  });

  useEffect(() => {
    if (data?.defaultStream && !channel) {
      setChannel(data.defaultStream);
    }
  }, [data, channel]);

  useEffect(() => {
    const eventSource = new EventSource("/api/stream");

    eventSource.onmessage = (event) => {
      try {
        const streamData = JSON.parse(event.data);
        if (streamData.stream) {
          setChannel(streamData.stream);
        }
      } catch (error) {
        console.error("Error parsing stream data:", error);
      }
    };

    return () => eventSource.close();
  }, []);

  const getEventIcon = (type: string) => {
    switch (type) {
      case "tournament":
        return <Trophy className="h-4 w-4" />;
      case "special":
        return <Gamepad2 className="h-4 w-4" />;
      default:
        return <Calendar className="h-4 w-4" />;
    }
  };

  return (
    <div className="h-screen bg-black flex flex-col">
      {/* Main Content Area */}
      <div className="flex-1 flex">
        {/* Twitch Stream */}
        <div className="flex-1 bg-black">
          {channel && (
            <iframe
              src={`https://player.twitch.tv/?channel=${channel}&parent=localhost&autoplay=true&muted=true`}
              height="100%"
              width="100%"
              allowFullScreen
            />
          )}
        </div>

        {/* Opening Hours Sidebar */}
        <div className="w-64 bg-gradient-to-b from-violet-950/90 via-purple-950/90 to-fuchsia-950/90 backdrop-blur-xl border-l border-purple-500/20 p-4">
          {/* Currently Streaming */}
          <div className="mb-6">
            <div className="flex items-center gap-2 mb-3">
              <TwitchIcon className="h-5 w-5 text-purple-400" />
              <h3 className="text-lg font-semibold text-white">
                Currently Streaming
              </h3>
            </div>
            <div className="bg-purple-950/30 rounded-lg p-3">
              <div className="flex items-center gap-2">
                <div className="w-2 h-2 bg-red-500 rounded-full animate-pulse" />
                <span className="text-purple-200">
                  {channel || "No stream"}
                </span>
              </div>
            </div>
          </div>

          {/* Opening Hours */}
          <div className="flex items-center gap-2 mb-4">
            <Clock className="h-5 w-5 text-purple-400" />
            <h3 className="text-lg font-semibold text-white">Opening Hours</h3>
          </div>
          <div className="space-y-2">
            {openingHours.map((item) => (
              <div
                key={item.day}
                className="flex justify-between items-center py-2 px-3 rounded-lg bg-purple-950/30"
              >
                <span className="text-purple-200">{item.day}</span>
                <span className="text-purple-300">{item.hours}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Bottom Bar - Reduced height */}
      <div className="h-36 bg-gradient-to-r from-violet-950/90 via-purple-950/90 to-fuchsia-950/90 backdrop-blur-xl border-t border-purple-500/20 flex">
        {/* Sponsors */}
        <div className="w-64 border-r border-purple-500/20 p-3">
          <div className="h-full">
            <Swiper
              modules={[Autoplay]}
              direction="vertical"
              spaceBetween={16}
              slidesPerView={1}
              autoplay={{
                delay: 3000,
                disableOnInteraction: false,
              }}
              loop={true}
              className="h-full"
            >
              {sponsors.map((sponsor, index) => (
                <SwiperSlide key={index}>
                  <div className="h-full relative rounded-lg overflow-hidden">
                    <Image
                      src={sponsor.image}
                      alt={sponsor.name}
                      fill
                      className="object-cover"
                    />
                  </div>
                </SwiperSlide>
              ))}
            </Swiper>
          </div>
        </div>

        {/* Events */}

        <div className="flex">
          <div>
            <div className="flex items-center gap-3  ml-3 mt-2 ">
              <Calendar className="h-5 w-5 text-purple-400" />
              <h1 className="text-2xl font-semibold text-white"> Events</h1>
            </div>
            <div className="h-20 w-20 bg-white ml-6">
              <h1>qrcode</h1>
            </div>
          </div>

          <div className="mt-8 ml-3">
            <div className="flex gap-3 overflow-x-auto pb-1">
              {exampleEvents.map((event) => (
                <Card
                  key={event.id}
                  className="bg-purple-950/50 border-purple-500/20 w-[250px] flex-shrink-0"
                >
                  <CardContent className="p-3">
                    <div className="flex items-start justify-between">
                      <h4 className="font-medium text-white text-sm line-clamp-1 flex-1 mr-2">
                        {event.title}
                      </h4>
                      <Badge className="bg-purple-500/10 text-purple-400 flex items-center gap-1 flex-shrink-0">
                        {getEventIcon(event.type)}
                      </Badge>
                    </div>
                    <p className="text-xs text-purple-300 mt-1 mb-2 line-clamp-1">
                      {event.description}
                    </p>
                    <div className="flex items-center justify-between text-xs text-purple-400">
                      <div className="flex items-center gap-1">
                        <Clock className="h-3 w-3" />
                        <span>
                          {new Date(event.startTime).toLocaleTimeString([], {
                            hour: "2-digit",
                            minute: "2-digit",
                          })}
                        </span>
                      </div>
                      <div className="flex items-center gap-1">
                        <Users className="h-3 w-3" />
                        <span>{event.participants}</span>
                      </div>
                    </div>
                  </CardContent>
                </Card>
              ))}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}