"use client"; import Image from "next/image"; import { useEffect, useState, useRef } from "react"; export default function Home() { 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 socketRef = useRef(null); useEffect(() => { let mounted = true; // dynamic import to avoid bundling issues on server import("socket.io-client").then(({ io }) => { if (!mounted) return; // default to the same origin and connect to the Next.js API route at /api/socket const serverUrl = process.env.NEXT_PUBLIC_SOCKET_URL || window.location.origin; const socket = io(serverUrl, { autoConnect: true, path: "/api/socket" }); socketRef.current = socket; socket.on("connect", () => { setConnected(true); // join a named event (example eventId: pamkutya) socket.emit("join_event", { eventId: "pamkutya" }); }); 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) => { // { token, expiresAt } setHasAccess(true); setTokenExpiry(data.expiresAt ? Date.parse(data.expiresAt) : Date.now() + 15 * 60 * 1000); // store token locally for API calls try { localStorage.setItem("event_token", data.token); } catch (e) {} }); socket.on("revoked", () => { setHasAccess(false); setTokenExpiry(null); localStorage.removeItem("event_token"); }); }); return () => { mounted = false; if (socketRef.current) socketRef.current.disconnect(); }; }, []); useEffect(() => { if (!tokenExpiry) return; const id = setInterval(() => { const msLeft = tokenExpiry - Date.now(); if (msLeft <= 0) { setHasAccess(false); setTokenExpiry(null); localStorage.removeItem("event_token"); } }, 1000); return () => clearInterval(id); }, [tokenExpiry]); const tryBuy = () => { if (!hasAccess) return; // Here you'd call your purchase API with the stored token alert("You can proceed to purchase (this is a demo stub)."); }; return (

Koncert jegyek — Queue rendszer demo

Event: pamkutya
Socket:{" "} {connected ? "connected" : "disconnected"}
Aktív felhasználók
{activeUsers}
Helyed a sorban
{position ?? "—"}
Becsült várakozás
{estimatedWait ? `${Math.ceil(estimatedWait)} s` : "—"}
{tokenExpiry && (
Token lejár: {new Date(tokenExpiry).toLocaleTimeString()}
)}

A rendszer WebSocket + JWT alapú. Ha a rendezvény eléri a küszöböt, a rendszer sorba helyez.

); }