From da505ae64305d1a2fed87716c5e3d36ced621a4c Mon Sep 17 00:00:00 2001 From: openhands Date: Thu, 9 Jul 2026 18:30:46 +0200 Subject: [PATCH] Optimize client page: combine fetch calls, extract ToolbarBtn component, reduce duplicated inline styles --- src/app/client/page.tsx | 97 +++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 61 deletions(-) diff --git a/src/app/client/page.tsx b/src/app/client/page.tsx index cd48f7a2..98439704 100644 --- a/src/app/client/page.tsx +++ b/src/app/client/page.tsx @@ -1,10 +1,25 @@ "use client"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useRef, useState, type ReactNode } from "react"; import Link from "next/link"; import { useTranslations } from "next-intl"; import { ContentCard, SkeletonCard } from "@/components/public/ui"; +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 default function ClientPage() { const t = useTranslations("pages.client"); const [ticket, setTicket] = useState(null); @@ -21,16 +36,19 @@ export default function ClientPage() { if (fetchedRef.current) return; fetchedRef.current = true; - async function fetchTicket() { + async function init() { try { - const res = await fetch("/api/client/sso"); - if (res.status === 401) { + const [ssoRes] = await Promise.all([ + fetch("/api/client/sso"), + fetch("/api/online/count").then(r => r.ok ? r.json() : { count: 0 }).then(d => setOnlineCount(d.count)).catch(() => {}), + ]); + if (ssoRes.status === 401) { setErrorType("auth"); setError(t("errors.unauthorized")); return; } - if (!res.ok) throw new Error("SSO fetch failed"); - const data = await res.json(); + if (!ssoRes.ok) throw new Error("SSO fetch failed"); + const data = await ssoRes.json(); setTicket(data.ticket); setHotelName(data.hotelName); if (data.clientUrl) setClientUrl(data.clientUrl); @@ -41,25 +59,16 @@ export default function ClientPage() { setLoading(false); } } - fetchTicket(); - }, [t]); + init(); - useEffect(() => { - async function fetchOnline() { + const interval = setInterval(async () => { try { const res = await fetch("/api/online/count"); - if (res.ok) { - const data = await res.json(); - setOnlineCount(data.count ?? 0); - } - } catch { - // ignore - } - } - fetchOnline(); - const interval = setInterval(fetchOnline, 15000); + if (res.ok) setOnlineCount((await res.json()).count ?? 0); + } catch {} + }, 15000); return () => clearInterval(interval); - }, []); + }, [t]); const toggleFullscreen = useCallback(() => { if (!document.fullscreenElement) { @@ -150,58 +159,24 @@ export default function ClientPage() {
{/* Floating Toolbar */}
- {/* Home Button */} - + - - - {/* Reload Button */} - - - {/* Fullscreen Button */} - - - {/* Online Count Button */} +