feat: 优化大厅 Jackpot 参与提示与玩家页头布局
This commit is contained in:
@@ -31,6 +31,7 @@ type HallBetPreviewDialogProps = {
|
||||
currencyCode: string;
|
||||
data: TicketPreviewData | null;
|
||||
placing: boolean;
|
||||
jackpotEnabled?: boolean;
|
||||
/** 界面 §4.2:封盘后禁止提交,主按钮文案为「已封盘」 */
|
||||
allowSubmit?: boolean;
|
||||
onConfirmPlace: () => void;
|
||||
@@ -107,6 +108,7 @@ export function HallBetPreviewDialog({
|
||||
currencyCode,
|
||||
data,
|
||||
placing,
|
||||
jackpotEnabled = false,
|
||||
allowSubmit = true,
|
||||
onConfirmPlace,
|
||||
}: HallBetPreviewDialogProps) {
|
||||
@@ -188,6 +190,16 @@ export function HallBetPreviewDialog({
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{jackpotEnabled ? (
|
||||
<Alert className="border-[#d9ecff] bg-[#f4f9ff] text-[#0b3f96]">
|
||||
<CheckCircle2 className="size-4" />
|
||||
<AlertTitle>{t("hall.jackpotParticipation.title")}</AlertTitle>
|
||||
<AlertDescription className="text-xs leading-relaxed">
|
||||
{t("hall.jackpotParticipation.previewDescription")}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
|
||||
<div className="overflow-x-auto rounded-xl border border-[#dfe8f6]">
|
||||
<table className="min-w-[640px] w-full border-collapse text-xs">
|
||||
<thead className="bg-[#f4f7fd] text-[#304f86]">
|
||||
|
||||
@@ -21,6 +21,7 @@ type HallBetResultDialogProps = {
|
||||
onOpenChange: (open: boolean) => void;
|
||||
currencyCode: string;
|
||||
data: TicketPlaceData | null;
|
||||
jackpotEnabled?: boolean;
|
||||
};
|
||||
|
||||
export function HallBetResultDialog({
|
||||
@@ -28,6 +29,7 @@ export function HallBetResultDialog({
|
||||
onOpenChange,
|
||||
currencyCode,
|
||||
data,
|
||||
jackpotEnabled = false,
|
||||
}: HallBetResultDialogProps) {
|
||||
const { t } = useTranslation("player");
|
||||
|
||||
@@ -119,6 +121,13 @@ export function HallBetResultDialog({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{jackpotEnabled ? (
|
||||
<div className="rounded-lg border border-[#d9ecff] bg-[#f4f9ff] px-3 py-3 text-sm leading-relaxed text-[#0b3f96]">
|
||||
<p className="font-black">{t("hall.jackpotParticipation.title")}</p>
|
||||
<p className="mt-1 text-xs">{t("hall.jackpotParticipation.resultDescription")}</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-black text-[#e5002c]">
|
||||
{t("hall.result.items")}
|
||||
|
||||
@@ -84,7 +84,6 @@ const categoryTabs: { value: HallCategory; label: string }[] = [
|
||||
{ value: "D2", label: "2D" },
|
||||
{ value: "D3", label: "3D" },
|
||||
{ value: "D4", label: "4D" },
|
||||
{ value: "JACKPOT", label: "Jackpot" },
|
||||
];
|
||||
|
||||
const D2_PLAY_ORDER = ["pos_2a", "pos_2b", "pos_2c", "pos_2abc"] as const;
|
||||
@@ -496,8 +495,25 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
const currentQuickFill = quickFillState[activeCategory] ?? { favorites: [], history: [] };
|
||||
const favorites = currentQuickFill.favorites;
|
||||
const historyNumbers = currentQuickFill.history;
|
||||
const jackpotPanelCopy = !jackpot?.enabled
|
||||
? {
|
||||
title: t("hall.jackpotPanel.disabledTitle"),
|
||||
subtitle: t("hall.jackpotPanel.disabledSubtitle"),
|
||||
description: t("hall.jackpotPanel.disabledDescription"),
|
||||
}
|
||||
: isBettable
|
||||
? {
|
||||
title: t("hall.jackpotPanel.infoTitle"),
|
||||
subtitle: t("hall.jackpotPanel.infoSubtitle"),
|
||||
description: t("hall.jackpotPanel.infoDescription"),
|
||||
}
|
||||
: {
|
||||
title: t("hall.jackpotPanel.closedInfoTitle"),
|
||||
subtitle: t("hall.jackpotPanel.closedInfoSubtitle"),
|
||||
description: t("hall.jackpotPanel.closedInfoDescription"),
|
||||
};
|
||||
|
||||
const tableDisabled = activeCategory === "JACKPOT" || !isBettable || catalogState.kind !== "ok";
|
||||
const tableDisabled = !isBettable || catalogState.kind !== "ok";
|
||||
const sealedBetUi = Boolean(display && isHallSealedCountdownUi(display.status));
|
||||
const numberPlaceholder = activeCategory === "D2" ? "00" : activeCategory === "D3" ? "000" : "0000";
|
||||
|
||||
@@ -888,7 +904,7 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
<>
|
||||
<section className="space-y-3" aria-label={t("hall.aria")}>
|
||||
<div className="rounded-xl border border-[#e8eef7] bg-white p-1 shadow-[0_6px_18px_rgba(30,64,175,0.06)]">
|
||||
<div className="grid grid-cols-4 gap-1">
|
||||
<div className="grid grid-cols-3 gap-1">
|
||||
{categoryTabs.map((tab) => {
|
||||
const active = activeCategory === tab.value;
|
||||
return (
|
||||
@@ -941,33 +957,18 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{activeCategory === "JACKPOT" ? (
|
||||
<div className="rounded-xl border border-[#edf1f7] bg-[#f7f9fc] p-7 text-center text-slate-500">
|
||||
<div className="mx-auto flex size-14 items-center justify-center rounded-full bg-slate-200 text-slate-600">
|
||||
<Ticket className="size-7" aria-hidden />
|
||||
<div className="rounded-xl border border-[#e3ebf7] bg-white px-3 py-3 shadow-[0_8px_24px_rgba(15,23,42,0.045)]">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<p className="text-sm font-bold leading-5 text-slate-950">
|
||||
{t("hall.quickFill.title")}
|
||||
</p>
|
||||
<p className="mt-0.5 text-xs leading-5 text-slate-500">
|
||||
{t("hall.quickFill.description")}
|
||||
</p>
|
||||
</div>
|
||||
<p className="mt-3 text-lg font-bold text-slate-900">
|
||||
{t("hall.closed.title")}
|
||||
</p>
|
||||
<p className="mt-1 text-xs">{t("hall.closed.subtitle")}</p>
|
||||
<div className="mt-5 rounded-lg border border-[#cbdcf7] bg-white px-3 py-3 text-left text-xs text-[#315a9f]">
|
||||
{t("hall.closed.description")}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="rounded-xl border border-[#e3ebf7] bg-white px-3 py-3 shadow-[0_8px_24px_rgba(15,23,42,0.045)]">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<p className="text-sm font-bold leading-5 text-slate-950">
|
||||
{t("hall.quickFill.title")}
|
||||
</p>
|
||||
<p className="mt-0.5 text-xs leading-5 text-slate-500">
|
||||
{t("hall.quickFill.description")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1.5">
|
||||
{activeRow?.number ? (
|
||||
<div className="flex shrink-0 items-center gap-1.5">
|
||||
{activeRow?.number ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
@@ -1275,8 +1276,6 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
? t("hall.table.insufficientBalance")
|
||||
: t("hall.table.submitBet")}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<HallBetPreviewDialog
|
||||
@@ -1288,6 +1287,7 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
currencyCode={currencyCode}
|
||||
data={previewData}
|
||||
placing={placeLoading}
|
||||
jackpotEnabled={Boolean(jackpot?.enabled)}
|
||||
allowSubmit={isBettable && availableMinor >= debouncedSummary.actual}
|
||||
onConfirmPlace={() => void handlePlace()}
|
||||
/>
|
||||
@@ -1300,6 +1300,7 @@ export function HallBettingGrid({ drawLive }: { drawLive: HallDrawLiveSnapshot }
|
||||
}}
|
||||
currencyCode={currencyCode}
|
||||
data={resultData}
|
||||
jackpotEnabled={Boolean(jackpot?.enabled)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user