123 lines
4.7 KiB
TypeScript
123 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { BoothConfig } from "@/types/booth";
|
|
import { SpookyAtmosphere } from "@/components/SpookyAtmosphere";
|
|
import { useI18n } from "@/lib/i18n";
|
|
import { Globe } from "lucide-react";
|
|
|
|
interface KioskFrameProps {
|
|
config: BoothConfig;
|
|
children: React.ReactNode;
|
|
showHeaderLogo?: boolean;
|
|
showLanguageToggle?: boolean;
|
|
}
|
|
|
|
export const KioskFrame: React.FC<KioskFrameProps> = ({
|
|
config,
|
|
children,
|
|
showHeaderLogo = true,
|
|
showLanguageToggle = true,
|
|
}) => {
|
|
const [isModeFullscreen, setIsModeFullscreen] = useState(false);
|
|
const { language, toggleLanguage, isWeChat } = useI18n();
|
|
|
|
useEffect(() => {
|
|
if (typeof window !== "undefined") {
|
|
const params = new URLSearchParams(window.location.search);
|
|
const isFull = params.get("mode") === "fullscreen";
|
|
setIsModeFullscreen(isFull);
|
|
|
|
if (isFull) {
|
|
const triggerFullscreen = () => {
|
|
if (!document.fullscreenElement && document.documentElement.requestFullscreen) {
|
|
document.documentElement.requestFullscreen().catch((err) => {
|
|
console.log("[Kiosk] Fullscreen request prevented:", err);
|
|
});
|
|
}
|
|
};
|
|
|
|
window.addEventListener("pointerdown", triggerFullscreen, { once: true });
|
|
return () => window.removeEventListener("pointerdown", triggerFullscreen);
|
|
}
|
|
}
|
|
}, []);
|
|
|
|
const theme = config.theme;
|
|
|
|
return (
|
|
<div
|
|
data-fullscreen={isModeFullscreen}
|
|
className={`relative flex flex-col overflow-hidden select-none transition-all duration-300 ${
|
|
isModeFullscreen
|
|
? "w-screen h-screen max-w-none max-h-none rounded-none border-0 shadow-none"
|
|
: "kiosk-viewport rounded-none sm:rounded-3xl border-4 border-black shadow-[0_12px_0_#090314,0_0_40px_rgba(255,109,0,0.25)]"
|
|
}`}
|
|
style={
|
|
{
|
|
"--brand-primary": theme.primaryColor,
|
|
"--brand-accent": theme.accentColor,
|
|
"--brand-bg": theme.backgroundColor,
|
|
"--brand-surface": theme.surfaceColor,
|
|
"--brand-text": theme.textColor,
|
|
} as React.CSSProperties
|
|
}
|
|
>
|
|
{/* Dynamic Martial Arts & Shanghai Halloween Atmosphere */}
|
|
<SpookyAtmosphere />
|
|
|
|
{/* Floating Language Toggle (Top Right) */}
|
|
{showLanguageToggle && (
|
|
<div className="absolute top-[max(0.75rem,env(safe-area-inset-top))] right-4 z-30">
|
|
<button
|
|
onClick={toggleLanguage}
|
|
className="flex items-center space-x-1.5 px-3 py-1.5 rounded-full bg-[#1b0f2e]/90 hover:bg-[#2b184a] text-amber-300 border-2 border-black shadow-[0_3px_0_#090314] text-xs font-black tracking-wider transition active:scale-95"
|
|
title={language === "zh" ? "Switch to English" : "切换为中文"}
|
|
>
|
|
<Globe size={13} className="text-amber-400" />
|
|
<span>{language === "zh" ? "EN" : "中"}</span>
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
{/* Brand Header Logo - 20% larger */}
|
|
{showHeaderLogo && (
|
|
<header className="no-print pt-[max(0.5rem,env(safe-area-inset-top))] sm:pt-3 pb-0.5 px-4 flex justify-center items-center z-20">
|
|
<div className="relative flex items-center justify-center">
|
|
{theme.logoUrl ? (
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
<img
|
|
src={theme.logoUrl}
|
|
alt={config.appName}
|
|
className="w-56 sm:w-72 md:w-84 h-auto max-h-16 sm:max-h-20 object-contain drop-shadow-[0_4px_14px_rgba(0,0,0,0.85)] filter"
|
|
/>
|
|
) : (
|
|
<h1 className="text-lg sm:text-xl font-black tracking-wider text-white uppercase drop-shadow-[0_3px_0_#090314]">
|
|
{config.appName}
|
|
</h1>
|
|
)}
|
|
</div>
|
|
</header>
|
|
)}
|
|
|
|
{/* Screen Content Layer */}
|
|
<main className="flex-1 relative flex flex-col overflow-hidden z-10 w-full pl-[max(0px,env(safe-area-inset-left))] pr-[max(0px,env(safe-area-inset-right))]">
|
|
{children}
|
|
</main>
|
|
|
|
{/* Dojo Brand Footer - clean single line, smaller font, no emoji */}
|
|
<footer className="no-print pt-0.5 pb-[max(0.75rem,env(safe-area-inset-bottom))] px-2 flex items-center justify-center z-20 select-none">
|
|
<a
|
|
href="https://www.shanghaikarate.com"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-[8.5px] sm:text-[9.5px] text-white/50 hover:text-amber-300 transition-colors whitespace-nowrap overflow-hidden text-ellipsis tracking-wide"
|
|
title="Shanghai Karate Club (shanghaikarate.com)"
|
|
>
|
|
<span>上海健志空手道馆 · Shanghai Karate Club · Est. 2008</span>
|
|
</a>
|
|
</footer>
|
|
</div>
|
|
);
|
|
};
|