"use client";
import type { TFunction } from "i18next";
import {
AlertCircle,
AlertTriangle,
CheckCircle2,
Globe,
Loader2,
RefreshCw,
ShieldCheck,
} from "lucide-react";
import Image from "next/image";
import { useTranslation } from "react-i18next";
import { LanguageSwitcher } from "@/components/language-switcher";
import { Button, buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils";
export type DesktopEntryStepStatus = "pending" | "in-progress" | "done" | "error";
type DesktopEntryStep = {
id: "token" | "account" | "hall";
status: DesktopEntryStepStatus;
};
type DesktopFailureRow = {
code?: string;
detailKey?: string;
fallbackMessage?: string;
};
type PlayerEntryDesktopProps = {
phase: "loading" | "success" | "failed";
waitingForToken: boolean;
progress: number;
steps: DesktopEntryStep[];
failureDetails: DesktopFailureRow[];
t: TFunction<"entry">;
tc: TFunction<"common">;
mainSiteUrl: string;
onRetry: () => void;
};
/** PC Token 入场校验,视觉与账号密码登录保持一致。 */
export function PlayerEntryDesktop({
phase,
waitingForToken,
progress,
steps,
failureDetails,
t,
tc,
mainSiteUrl,
onRetry,
}: PlayerEntryDesktopProps) {
const isLoading = phase === "loading" || waitingForToken;
return (
{isLoading ? (
) : null}
{phase === "failed" ? (
) : null}
{t("footer.secure")}
);
}
function EntryProgress({
progress,
steps,
t,
}: Pick) {
return (
<>
{t("loading.title")}
{t("loading.progress")}
{t("loading.progress")}
{progress}%
{steps.map((step) => (
{t(`steps.${step.id}.title`)}
{t(`steps.${step.id}.description`)}
))}
>
);
}
function EntryFailure({
details,
mainSiteUrl,
onRetry,
t,
tc,
}: Pick & {
details: DesktopFailureRow[];
}) {
return (
{t("failure.title")}
{t("failure.subtitle")}
{details.length > 0 ? (
{t("failure.detailsTitle")}
{details.map((detail, index) => (
{index + 1}
{detail.code ?? tc("errors.general")}
{detail.detailKey
? t(detail.detailKey)
: (detail.fallbackMessage ?? t("errors.unknown"))}
))}
) : null}
);
}
function StepIcon({ status }: { status: DesktopEntryStepStatus }) {
const className = cn(
"flex size-8 shrink-0 items-center justify-center rounded-full border-2",
status === "done" && "border-emerald-500 bg-emerald-500 text-white",
status === "in-progress" && "border-blue-600 bg-blue-600 text-white",
status === "pending" && "border-slate-200 bg-slate-50 text-slate-400",
status === "error" && "border-red-500 bg-red-500 text-white",
);
return (
{status === "done" ?
: null}
{status === "in-progress" ?
: null}
{status === "pending" ?
: null}
{status === "error" ?
: null}
);
}
function StepBadge({ status }: { status: DesktopEntryStepStatus }) {
const { t } = useTranslation("common");
const className = cn(
"shrink-0 rounded px-2 py-0.5 text-xs font-medium",
status === "done" && "bg-emerald-50 text-emerald-700",
status === "in-progress" && "bg-blue-50 text-blue-700",
status === "pending" && "bg-slate-100 text-slate-500",
status === "error" && "bg-red-50 text-red-700",
);
const label = {
done: t("status.done"),
"in-progress": t("status.inProgress"),
pending: t("status.pending"),
error: t("status.failed"),
}[status];
return {label};
}