112 lines
4.6 KiB
TypeScript
112 lines
4.6 KiB
TypeScript
import { cn } from "@/lib/utils";
|
|
import { grades, pkPageCursorClass } from "../constants";
|
|
import type { ClassType, Grade } from "../types";
|
|
|
|
type StartScreenProps = {
|
|
selectedGrade: Grade;
|
|
classTypes: ClassType[];
|
|
selectedClassTypeId: number;
|
|
selectedClassTypeName?: string;
|
|
availableWordCount: number;
|
|
plannedRoundCount: number;
|
|
loadingSetup: boolean;
|
|
scorePerCorrect: number;
|
|
scorePerWrong: number;
|
|
onSelectGrade: (grade: Grade) => void;
|
|
onSelectClassType: (classTypeId: number) => void;
|
|
onStartGame: () => void;
|
|
};
|
|
|
|
export function StartScreen({
|
|
selectedGrade,
|
|
classTypes,
|
|
selectedClassTypeId,
|
|
selectedClassTypeName,
|
|
availableWordCount,
|
|
plannedRoundCount,
|
|
loadingSetup,
|
|
scorePerCorrect,
|
|
scorePerWrong,
|
|
onSelectGrade,
|
|
onSelectClassType,
|
|
onStartGame,
|
|
}: StartScreenProps) {
|
|
return (
|
|
<main
|
|
className={cn(
|
|
pkPageCursorClass,
|
|
"pk-start-stage mx-auto grid min-h-[calc(100vh-60px)] max-w-5xl place-items-center px-4 py-4",
|
|
)}
|
|
>
|
|
<section className="pk-start-card w-full rounded-[24px] bg-white p-[clamp(18px,3vw,36px)] text-center shadow-soft">
|
|
<div className="pk-start-visual mb-2 text-[clamp(54px,8vw,92px)] leading-none">🦊 VS 🦓</div>
|
|
<h1 className="pk-start-title text-balance text-[clamp(28px,4vw,44px)] font-black text-rose-500">字母单词PK赛</h1>
|
|
<p className="pk-start-subtitle mt-2 text-[clamp(15px,1.6vw,19px)] text-slate-600">
|
|
红队蓝队轮流答题,答对加{scorePerCorrect}分
|
|
{scorePerWrong > 0 ? `,答错扣${scorePerWrong}分。` : ",答错不扣分。"}
|
|
</p>
|
|
|
|
<div className="pk-start-panel mx-auto mt-5 grid max-w-3xl gap-3 rounded-2xl border bg-slate-50 p-4 text-left">
|
|
<div>
|
|
<div className="mb-2 text-xs font-semibold text-slate-600">选择年级</div>
|
|
<div className="grid grid-cols-3 gap-3">
|
|
{grades.map((grade) => (
|
|
<button
|
|
key={grade}
|
|
onClick={() => onSelectGrade(grade)}
|
|
className={cn(
|
|
"pk-start-choice rounded-lg border bg-white px-4 py-2.5 text-center text-base font-bold transition hover:border-rose-300",
|
|
selectedGrade === grade && "border-rose-500 bg-rose-50 text-rose-700 shadow-sm",
|
|
)}
|
|
>
|
|
{grade}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="mb-2 text-xs font-semibold text-slate-600">选择班级类型</div>
|
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
|
|
{classTypes.map((classType) => (
|
|
<button
|
|
key={classType.id}
|
|
onClick={() => onSelectClassType(classType.id)}
|
|
className={cn(
|
|
"pk-start-choice rounded-lg border bg-white px-4 py-2.5 text-center text-base font-bold transition hover:border-blue-300",
|
|
selectedClassTypeId === classType.id && "border-blue-500 bg-blue-50 text-blue-700 shadow-sm",
|
|
)}
|
|
>
|
|
{classType.name}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pk-start-summary rounded-lg bg-white px-4 py-2 text-center text-sm text-slate-600">
|
|
当前选择:<span className="font-bold text-slate-900">{selectedGrade}</span>
|
|
<span className="mx-2 text-slate-300">/</span>
|
|
<span className="font-bold text-slate-900">{selectedClassTypeName ?? "未选择班型"}</span>
|
|
<span className="mx-2 text-slate-300">/</span>
|
|
本轮题目 <span className="font-bold text-emerald-600">{plannedRoundCount}</span> 道
|
|
<span className="mx-2 text-slate-300">/</span>
|
|
题库可用 <span className="font-bold text-slate-900">{availableWordCount}</span> 道
|
|
</div>
|
|
</div>
|
|
|
|
{!loadingSetup && availableWordCount === 0 && (
|
|
<p className="pk-start-warning mt-4 text-sm font-medium text-red-500">当前年级和班级类型没有启用题目,请先到后台管理启用词库。</p>
|
|
)}
|
|
|
|
<button
|
|
onClick={onStartGame}
|
|
disabled={loadingSetup || availableWordCount === 0}
|
|
className="pk-start-button mt-5 rounded-full bg-rose-500 px-10 py-3 text-[clamp(17px,1.8vw,21px)] font-bold text-white shadow-lg transition hover:bg-rose-600 disabled:cursor-not-allowed disabled:bg-slate-300 disabled:shadow-none"
|
|
>
|
|
{loadingSetup ? "加载中..." : "开始PK"}
|
|
</button>
|
|
</section>
|
|
</main>
|
|
);
|
|
}
|