diff --git a/src/app/client/client-view.tsx b/src/app/client/client-view.tsx new file mode 100644 index 00000000..57a88e9b --- /dev/null +++ b/src/app/client/client-view.tsx @@ -0,0 +1,104 @@ +"use client"; + +import { useCallback, useEffect, useState, type ReactNode } from "react"; +import Link from "next/link"; + +function ToolbarBtn({ onClick, title, children, href }: { + onClick?: () => void; title: string; children: ReactNode; href?: string; +}) { + const cls = "w-10 h-10 rounded-lg border-2 cursor-pointer flex items-center justify-center shadow-lg transition-all duration-200 hover:-translate-y-0.5 hover:shadow-xl active:translate-y-0"; + const style = { + borderColor: "color-mix(in srgb, var(--color-primary, #eeb425) 75%, black)", + background: "linear-gradient(135deg, var(--color-primary, #eeb425) 0%, color-mix(in srgb, var(--color-primary, #eeb425) 80%, black) 100%)", + color: "var(--button-text-color, #1a1a2e)", + } as const; + if (href) { + return {children}; + } + return ; +} + +export function ClientView({ ticket, clientUrl, hotelName, initialOnline }: { + ticket: string; clientUrl: string; hotelName: string; initialOnline: number; +}) { + const [isFullscreen, setIsFullscreen] = useState(false); + const [onlineCount, setOnlineCount] = useState(initialOnline); + + useEffect(() => { + const interval = setInterval(async () => { + try { + const res = await fetch("/api/online/count"); + if (res.ok) setOnlineCount((await res.json()).count ?? 0); + } catch {} + }, 15000); + return () => clearInterval(interval); + }, []); + + const toggleFullscreen = useCallback(() => { + if (!document.fullscreenElement) { + document.documentElement.requestFullscreen().catch(() => {}); + setIsFullscreen(true); + } else { + document.exitFullscreen().catch(() => {}); + setIsFullscreen(false); + } + }, []); + + useEffect(() => { + function onChange() { setIsFullscreen(!!document.fullscreenElement); } + document.addEventListener("fullscreenchange", onChange); + return () => document.removeEventListener("fullscreenchange", onChange); + }, []); + + const base = clientUrl.replace(/(\?|&)sso=[^&]*/, ""); + const sep = base.includes("?") ? "&" : "?"; + const clientSrc = `${base}${sep}sso=${encodeURIComponent(ticket)}`; + + return ( +
+
+ + + + + + + window.location.reload()} title="Reload"> + + + + + + + + + + + +
+ + + + + {onlineCount} +
+
+ +