feat: 增加 Jackpot 爆池实时弹层与奖池信息展示

This commit is contained in:
2026-05-18 15:08:29 +08:00
parent 418b446c09
commit 321b56e997
11 changed files with 379 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
"use client";
import { useCallback, useEffect, useState } from "react";
import type { TFunction } from "i18next";
import { getLotteryEcho } from "@/lib/lottery-echo";
import { formatMinorAsCurrency } from "@/lib/money";
import type { JackpotBurstEvent } from "@/features/hall/jackpot-burst-overlay";
function notifyBrowser(event: JackpotBurstEvent, t: TFunction<"player">): void {
if (typeof window === "undefined" || !("Notification" in window)) {
return;
}
const currency = event.currency_code.toUpperCase();
const amount = formatMinorAsCurrency(event.total_payout_amount, currency);
const title = t("hall.jackpotBurst.notificationTitle", {
defaultValue: "Jackpot 爆池",
});
const body = t("hall.jackpotBurst.notificationBody", {
defaultValue: "期号 {{drawNo}} 派发 {{amount}}",
drawNo: event.draw_no,
amount,
});
const push = () => {
try {
new Notification(title, { body, tag: `jackpot-burst-${event.draw_id}` });
} catch {
// 浏览器通知失败不影响页面内爆池动画。
}
};
if (Notification.permission === "granted") {
push();
return;
}
if (Notification.permission === "default") {
void Notification.requestPermission().then((permission) => {
if (permission === "granted") {
push();
}
});
}
}
export function useJackpotBurstLive(t: TFunction<"player">) {
const [event, setEvent] = useState<JackpotBurstEvent | null>(null);
const handleBurst = useCallback(
(payload: JackpotBurstEvent) => {
setEvent(payload);
notifyBrowser(payload, t);
window.dispatchEvent(new Event("lottery-wallet-refresh"));
},
[t],
);
useEffect(() => {
const echo = getLotteryEcho();
if (!echo) return;
const channel = echo.channel("lottery-hall");
channel.listen(".jackpot.burst", handleBurst);
return () => {
channel.stopListening(".jackpot.burst");
};
}, [handleBurst]);
return {
burstEvent: event,
clearBurstEvent: () => setEvent(null),
};
}