"use client"; import { useEffect, useState, useRef } from "react"; import { useParams, useRouter } from "next/navigation"; import Link from "next/link"; export default function EventPage() { const params = useParams(); const router = useRouter(); const eventId = params.id as string; // Helper function to format seconds to HH:MM format const formatTime = (seconds: number): string => { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`; }; const [connected, setConnected] = useState(false); const [position, setPosition] = useState(null); const [estimatedWait, setEstimatedWait] = useState(null); const [activeUsers, setActiveUsers] = useState(0); const [hasAccess, setHasAccess] = useState(false); const [tokenExpiry, setTokenExpiry] = useState(null); const [eventData, setEventData] = useState(null); const [selectedTicket, setSelectedTicket] = useState("Normal"); const [quantity, setQuantity] = useState(1); const [purchasing, setPurchasing] = useState(false); const [loading, setLoading] = useState(true); const socketRef = useRef(null); // Load event data useEffect(() => { if (!eventId) return; fetch(`/api/events?id=${eventId}`) .then(res => res.json()) .then(data => { console.log('Event API response:', data); if (data.error) { console.log('Event API error, redirecting:', data.error); router.push('/'); return; } setEventData(data); setLoading(false); if (data.tickets && data.tickets.length > 0) { setSelectedTicket(data.tickets[0].type); } }) .catch(error => { console.error('Error loading event:', error); router.push('/'); }); }, [eventId, router]); // Socket.IO connection useEffect(() => { if (!eventId || loading) return; let mounted = true; // Initialize Socket.IO server fetch('/api/socketio') .then(() => { return import("socket.io-client"); }) .then(({ io }) => { if (!mounted) return; const socketPort = process.env.NEXT_PUBLIC_SOCKET_PORT || "4000"; const socketHost = process.env.NEXT_PUBLIC_SOCKET_HOST || window.location.hostname; const socket = io(`http://${socketHost}:${socketPort}`, { autoConnect: true }); socketRef.current = socket; socket.on("connect", () => { setConnected(true); socket.emit("join_event", { eventId }); }); socket.on("disconnect", () => { setConnected(false); setPosition(null); setHasAccess(false); setTokenExpiry(null); }); socket.on("queue_update", (data: any) => { setPosition(data.position ?? null); setEstimatedWait(data.estimatedWait ?? null); setActiveUsers(data.activeCount ?? 0); }); socket.on("granted", (data: any) => { setHasAccess(true); setTokenExpiry(data.expiresAt ? Date.parse(data.expiresAt) : Date.now() + 15 * 60 * 1000); try { localStorage.setItem("event_token", data.token); } catch (e) {} }); socket.on("revoked", () => { setHasAccess(false); setTokenExpiry(null); localStorage.removeItem("event_token"); }); socket.on("token_expired", () => { setHasAccess(false); setTokenExpiry(null); localStorage.removeItem("event_token"); // Redirect to homepage window.location.href = "/"; }); }) .catch(error => { console.error("Socket initialization error:", error); }); return () => { mounted = false; if (socketRef.current) socketRef.current.disconnect(); }; }, [eventId, loading]); // Check for existing token on page load useEffect(() => { try { const existingToken = localStorage.getItem("event_token"); if (existingToken) { console.log('Found existing token, clearing it'); localStorage.removeItem("event_token"); } } catch (e) { console.log('localStorage access error:', e); } }, []); // Token expiry timer - ellenőrzés minden másodpercben useEffect(() => { if (!tokenExpiry) return; console.log('Setting token expiry timer for:', new Date(tokenExpiry)); const id = setInterval(() => { const msLeft = tokenExpiry - Date.now(); console.log('Token check - ms left:', msLeft); if (msLeft <= 0) { console.log('Token expired, redirecting to homepage'); setHasAccess(false); setTokenExpiry(null); localStorage.removeItem("event_token"); // Disconnect socket and redirect to homepage if (socketRef.current) { socketRef.current.disconnect(); } window.location.href = "/"; } }, 1000); return () => clearInterval(id); }, [tokenExpiry]); const tryBuy = async () => { if (!hasAccess || purchasing) return; setPurchasing(true); try { const token = localStorage.getItem("event_token"); if (!token) { alert("Nincs érvényes token!"); return; } const response = await fetch('/api/purchase', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ eventId, ticketType: selectedTicket, quantity, token }) }); const result = await response.json(); if (response.ok) { alert(`🎉 Sikeres vásárlás!\\n\\nJegyek: ${quantity}x ${selectedTicket}\\nÖsszeg: ${result.totalPrice.toLocaleString()} Ft\\nRendelés ID: ${result.orderId}`); // Refresh event data const eventResponse = await fetch(`/api/events?id=${eventId}`); const eventData = await eventResponse.json(); setEventData(eventData); } else { alert(`Hiba: ${result.error}`); } } catch (error) { console.error('Purchase error:', error); alert('Hiba történt a vásárlás során!'); } finally { setPurchasing(false); } }; if (loading) { return (
Loading event...
); } const timeLeft = tokenExpiry ? Math.max(0, tokenExpiry - Date.now()) : 0; const minutesLeft = Math.floor(timeLeft / 60000); const secondsLeft = Math.floor((timeLeft % 60000) / 1000); return (
{/* Background Effects */}
{/* Header */}
← Vissza az eseményekhez
{connected ? 'Kapcsolódva' : 'Nincs kapcsolat'}

🎵 {eventData?.event?.name || eventId}

{eventData?.event?.description}

{/* Main Content */}
{/* Queue Status Card */}
{position ? ( <>
#{position}

Helyed a várakozási sorban

{estimatedWait && (

Becsült várakozási idő: {formatTime(Math.ceil(estimatedWait))}

)} ) : hasAccess ? ( <>
🎫

Hozzáféred engedélyezve!

Most vásárolhatsz jegyeket

) : ( <>

Csatlakozás a sorhoz...

)}
{/* Stats Grid */}
{activeUsers}
Aktív felhasználó
{position || '—'}
Pozíció
{estimatedWait ? formatTime(Math.ceil(estimatedWait)) : '—'}
Várható idő
{/* Purchase Form */} {hasAccess && (
setQuantity(parseInt(e.target.value))} className="w-full bg-white/10 border border-white/20 rounded-xl px-4 py-3 text-white" />
)} {/* Action Button */}
{/* Token Timer */} {hasAccess && tokenExpiry && (
⏰ Hozzáférés lejár: {minutesLeft}:{secondsLeft.toString().padStart(2, '0')}
Használd ki a lehetőséget!
)}
{/* Ticket Prices */} {eventData?.tickets && (

🎟️ Jegytípusok

{eventData.tickets.map((ticket: any, index: number) => { const available = ticket.total_quantity - ticket.sold_quantity; const colors = ['text-green-400', 'text-yellow-400', 'text-purple-400']; const borders = ['border-green-400/30', 'border-yellow-400/30', 'border-purple-400/30']; return (
{ticket.type}
{ticket.price.toLocaleString()} Ft
{available > 0 ? `${available} db elérhető` : 'Elfogyott'}
); })}
)}
{/* Footer */}
); }