feat(game): 添加奖池功能支持
- 在国际化文件中添加奖池相关的翻译配置 - 定义 JackpotPoolState 和 GameJackpotPoolDto 类型接口 - 在 DashboardState 中添加 jackpotPool 字段 - 实现 normalizeJackpotPoolState 函数处理奖池数据转换 - 更新游戏 API 中的初始化和数据归一化逻辑 - 添加 Oxanium 字体依赖并配置奖池金额字体样式 - 实现 JackpotPoolTicker 组件显示动态增长的奖池金额 - 在消息广播组件中集成奖池显示功能 - 更新实时同步钩子中的奖池数据处理逻辑
This commit is contained in:
12
.cloudbase-sites/preview.json
Normal file
12
.cloudbase-sites/preview.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"pid": 98343,
|
||||||
|
"port": 17174,
|
||||||
|
"host": "0.0.0.0",
|
||||||
|
"base": "/",
|
||||||
|
"framework": "vite-react",
|
||||||
|
"command": "/Users/jiaunun/.nvm/versions/node/v24.15.0/bin/node /Users/jiaunun/Desktop/36-character-flower/node_modules/vite/bin/vite.js --host 0.0.0.0 --port 17174 --strictPort --base /",
|
||||||
|
"internalUrl": "http://127.0.0.1:17174/",
|
||||||
|
"logPath": "/Users/jiaunun/Desktop/36-character-flower/.cloudbase-sites/logs/preview-1784093877629.log",
|
||||||
|
"cwd": "/Users/jiaunun/Desktop/36-character-flower",
|
||||||
|
"startedAt": "2026-07-15T05:37:58.655Z"
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/geist": "^5.2.8",
|
"@fontsource-variable/geist": "^5.2.8",
|
||||||
|
"@fontsource-variable/oxanium": "^5.2.8",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
"@tanstack/react-query": "^5.99.0",
|
"@tanstack/react-query": "^5.99.0",
|
||||||
"@tanstack/react-query-devtools": "^5.99.0",
|
"@tanstack/react-query-devtools": "^5.99.0",
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
|||||||
'@fontsource-variable/geist':
|
'@fontsource-variable/geist':
|
||||||
specifier: ^5.2.8
|
specifier: ^5.2.8
|
||||||
version: 5.2.9
|
version: 5.2.9
|
||||||
|
'@fontsource-variable/oxanium':
|
||||||
|
specifier: ^5.2.8
|
||||||
|
version: 5.2.8
|
||||||
'@hookform/resolvers':
|
'@hookform/resolvers':
|
||||||
specifier: ^5.2.2
|
specifier: ^5.2.2
|
||||||
version: 5.4.0(react-hook-form@7.75.0(react@19.2.5))
|
version: 5.4.0(react-hook-form@7.75.0(react@19.2.5))
|
||||||
@@ -635,6 +638,9 @@ packages:
|
|||||||
'@fontsource-variable/geist@5.2.9':
|
'@fontsource-variable/geist@5.2.9':
|
||||||
resolution: {integrity: sha512-TP+QSBG3wxKGPE33CbMy/L0Nu3qvJ6Fy81Yc4LnQ95xH+i+cfEp8fyU8/kfV14YwszxIFPhnoMTbjL71waVpyQ==}
|
resolution: {integrity: sha512-TP+QSBG3wxKGPE33CbMy/L0Nu3qvJ6Fy81Yc4LnQ95xH+i+cfEp8fyU8/kfV14YwszxIFPhnoMTbjL71waVpyQ==}
|
||||||
|
|
||||||
|
'@fontsource-variable/oxanium@5.2.8':
|
||||||
|
resolution: {integrity: sha512-W3HWxRLXVB6yox3dgm1DIGOp98pz8KglwiM6/2BsMopvZrg98mXI9citFWz2pUX0FOOLwf8fmHxX+KrIn+6BoA==}
|
||||||
|
|
||||||
'@hono/node-server@1.19.14':
|
'@hono/node-server@1.19.14':
|
||||||
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
|
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
|
||||||
engines: {node: '>=18.14.1'}
|
engines: {node: '>=18.14.1'}
|
||||||
@@ -4785,6 +4791,8 @@ snapshots:
|
|||||||
|
|
||||||
'@fontsource-variable/geist@5.2.9': {}
|
'@fontsource-variable/geist@5.2.9': {}
|
||||||
|
|
||||||
|
'@fontsource-variable/oxanium@5.2.8': {}
|
||||||
|
|
||||||
'@hono/node-server@1.19.14(hono@4.12.18)':
|
'@hono/node-server@1.19.14(hono@4.12.18)':
|
||||||
dependencies:
|
dependencies:
|
||||||
hono: 4.12.18
|
hono: 4.12.18
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import type {
|
|||||||
GameBootstrapSnapshot,
|
GameBootstrapSnapshot,
|
||||||
GameCell,
|
GameCell,
|
||||||
GameCellDto,
|
GameCellDto,
|
||||||
|
GameJackpotPoolDto,
|
||||||
GameLobbyInitDto,
|
GameLobbyInitDto,
|
||||||
GameLobbyInitResult,
|
GameLobbyInitResult,
|
||||||
GameLobbyPeriodDto,
|
GameLobbyPeriodDto,
|
||||||
@@ -40,6 +41,7 @@ import type {
|
|||||||
GameRoundFeedDto,
|
GameRoundFeedDto,
|
||||||
HistoryEntry,
|
HistoryEntry,
|
||||||
HistoryEntryDto,
|
HistoryEntryDto,
|
||||||
|
JackpotPoolState,
|
||||||
NoticeConfirmDto,
|
NoticeConfirmDto,
|
||||||
NoticeDetailDto,
|
NoticeDetailDto,
|
||||||
NoticeListDto,
|
NoticeListDto,
|
||||||
@@ -164,10 +166,33 @@ function normalizeAnnouncementState(dto: AnnouncementStateDto) {
|
|||||||
} satisfies AnnouncementState
|
} satisfies AnnouncementState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeJackpotPoolState(
|
||||||
|
dto: GameJackpotPoolDto | null | undefined,
|
||||||
|
updatedAt: string | null,
|
||||||
|
) {
|
||||||
|
if (!dto) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const current = Number(dto.current)
|
||||||
|
const speed = Number(dto.speed)
|
||||||
|
|
||||||
|
if (!Number.isFinite(current) || !Number.isFinite(speed)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
current,
|
||||||
|
speedPerSecond: Math.max(0, speed),
|
||||||
|
updatedAt,
|
||||||
|
} satisfies JackpotPoolState
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeDashboardState(dto: DashboardStateDto) {
|
function normalizeDashboardState(dto: DashboardStateDto) {
|
||||||
return {
|
return {
|
||||||
countdownMs: dto.countdown_ms,
|
countdownMs: dto.countdown_ms,
|
||||||
featuredCellId: dto.featured_cell_id,
|
featuredCellId: dto.featured_cell_id,
|
||||||
|
jackpotPool: normalizeJackpotPoolState(dto.jackpot_pool, dto.updated_at),
|
||||||
onlinePlayers: dto.online_players,
|
onlinePlayers: dto.online_players,
|
||||||
tableLimitMax: dto.table_limit_max,
|
tableLimitMax: dto.table_limit_max,
|
||||||
tableLimitMin: dto.table_limit_min,
|
tableLimitMin: dto.table_limit_min,
|
||||||
@@ -334,6 +359,7 @@ export function normalizeGameLobbyInit(dto: GameLobbyInitDto) {
|
|||||||
dashboard: {
|
dashboard: {
|
||||||
countdownMs: 0,
|
countdownMs: 0,
|
||||||
featuredCellId: null,
|
featuredCellId: null,
|
||||||
|
jackpotPool: normalizeJackpotPoolState(dto.jackpot_pool, baseIso),
|
||||||
onlinePlayers: 0,
|
onlinePlayers: 0,
|
||||||
tableLimitMax: Number(dto.bet_config.max_bet_per_number) || 0,
|
tableLimitMax: Number(dto.bet_config.max_bet_per_number) || 0,
|
||||||
tableLimitMin: Number(dto.bet_config.min_bet_per_number) || 0,
|
tableLimitMin: Number(dto.bet_config.min_bet_per_number) || 0,
|
||||||
|
|||||||
138
src/components/jackpot-pool-ticker.tsx
Normal file
138
src/components/jackpot-pool-ticker.tsx
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import diamond from '@/assets/system/diamond.webp'
|
||||||
|
import { SmartImage } from '@/components/smart-image.tsx'
|
||||||
|
import { cn } from '@/lib/utils.ts'
|
||||||
|
import { useGameSessionStore } from '@/store/game'
|
||||||
|
|
||||||
|
const JACKPOT_POOL_TICK_MS = 1000
|
||||||
|
const jackpotPoolFormatter = new Intl.NumberFormat('en-US', {
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
type JackpotPoolTickerProps = {
|
||||||
|
className?: string
|
||||||
|
variant?: 'inline' | 'standalone'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function JackpotPoolTicker({
|
||||||
|
className,
|
||||||
|
variant = 'standalone',
|
||||||
|
}: JackpotPoolTickerProps) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const jackpotPool = useGameSessionStore(
|
||||||
|
(state) => state.dashboard.jackpotPool,
|
||||||
|
)
|
||||||
|
const poolCurrent = jackpotPool?.current ?? null
|
||||||
|
const poolSpeedPerSecond = jackpotPool?.speedPerSecond ?? 0
|
||||||
|
const poolUpdatedAt = jackpotPool?.updatedAt ?? null
|
||||||
|
const [nowMs, setNowMs] = useState(() => Date.now())
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNowMs(Date.now())
|
||||||
|
|
||||||
|
if (poolCurrent === null || poolSpeedPerSecond <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const timerId = window.setInterval(() => {
|
||||||
|
setNowMs(Date.now())
|
||||||
|
}, JACKPOT_POOL_TICK_MS)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.clearInterval(timerId)
|
||||||
|
}
|
||||||
|
}, [poolCurrent, poolSpeedPerSecond])
|
||||||
|
|
||||||
|
const displayAmount = useMemo(() => {
|
||||||
|
if (poolCurrent === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedAtMs = poolUpdatedAt ? Date.parse(poolUpdatedAt) : Number.NaN
|
||||||
|
const baseTimeMs = Number.isFinite(updatedAtMs) ? updatedAtMs : nowMs
|
||||||
|
const elapsedSeconds = Math.max(0, (nowMs - baseTimeMs) / 1000)
|
||||||
|
|
||||||
|
return poolCurrent + elapsedSeconds * poolSpeedPerSecond
|
||||||
|
}, [nowMs, poolCurrent, poolSpeedPerSecond, poolUpdatedAt])
|
||||||
|
|
||||||
|
if (displayAmount === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const amountLabel = jackpotPoolFormatter.format(displayAmount)
|
||||||
|
const isInline = variant === 'inline'
|
||||||
|
const amountCharacterCounts = new Map<string, number>()
|
||||||
|
const amountCharacterItems = Array.from(amountLabel).map((character) => {
|
||||||
|
const nextCount = (amountCharacterCounts.get(character) ?? 0) + 1
|
||||||
|
|
||||||
|
amountCharacterCounts.set(character, nextCount)
|
||||||
|
|
||||||
|
return {
|
||||||
|
character,
|
||||||
|
key: `${character}-${nextCount}`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
aria-label={t('game.jackpotPool.ariaLabel', { amount: amountLabel })}
|
||||||
|
className={cn(
|
||||||
|
'relative flex w-full min-w-0 items-center overflow-hidden whitespace-nowrap',
|
||||||
|
isInline
|
||||||
|
? 'h-design-20 rounded-[3px] border border-[#B86A13]/55 bg-[rgba(32,18,3,0.72)] px-design-4 md:h-design-52 md:rounded-[4px] md:px-design-10'
|
||||||
|
: 'h-design-34 !rounded-[4px] border border-[#B86A13]/70 bg-[rgba(32,18,3,0.82)] !px-design-10 !py-0 md:h-design-48 md:!rounded-[5px] md:!px-design-16',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<SmartImage
|
||||||
|
alt={t('game.jackpotPool.iconAlt')}
|
||||||
|
className={cn(
|
||||||
|
'shrink-0',
|
||||||
|
isInline
|
||||||
|
? 'mr-design-3 h-design-10 w-design-10 md:mr-design-8 md:h-design-24 md:w-design-24'
|
||||||
|
: 'mr-design-5 h-design-14 w-design-14 md:mr-design-10 md:h-design-26 md:w-design-26',
|
||||||
|
)}
|
||||||
|
src={diamond}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
'shrink-0 font-bold tracking-[0.08em] text-[#D8AA49]',
|
||||||
|
isInline
|
||||||
|
? 'mr-[20px] text-design-6 md:text-design-12'
|
||||||
|
: 'mr-[20px] text-design-8 md:text-design-14',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{t('game.jackpotPool.label')}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
'min-w-0 shrink truncate font-jackpot-amount font-extrabold leading-none tabular-nums [font-variation-settings:"wght"_760]',
|
||||||
|
isInline
|
||||||
|
? 'text-design-10 md:text-design-27'
|
||||||
|
: 'text-design-16 md:text-design-30',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{amountCharacterItems.map(({ character, key }) => {
|
||||||
|
const isNumber = /\d/.test(character)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className={cn(
|
||||||
|
'inline-block text-[#FFD15A]',
|
||||||
|
isNumber
|
||||||
|
? '[text-shadow:0_0_calc(var(--design-unit)*3)_rgba(255,240,166,0.88),0_0_calc(var(--design-unit)*7)_rgba(255,209,90,0.64),0_calc(var(--design-unit)*1)_0_rgba(92,43,2,0.92)]'
|
||||||
|
: 'mx-[0.03em] text-[#D49322]',
|
||||||
|
)}
|
||||||
|
key={key}
|
||||||
|
>
|
||||||
|
{character}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { AnimatePresence, motion, useReducedMotion } from 'motion/react'
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import broadcast from '@/assets/system/broadcast.webp'
|
import broadcast from '@/assets/system/broadcast.webp'
|
||||||
|
import { JackpotPoolTicker } from '@/components/jackpot-pool-ticker.tsx'
|
||||||
import { SmartImage } from '@/components/smart-image.tsx'
|
import { SmartImage } from '@/components/smart-image.tsx'
|
||||||
import { cn } from '@/lib/utils.ts'
|
import { cn } from '@/lib/utils.ts'
|
||||||
import { useGameSessionStore } from '@/store/game'
|
import { useGameSessionStore } from '@/store/game'
|
||||||
@@ -103,11 +104,12 @@ export function MessageBroadcast({ className }: MessageBroadcastProps) {
|
|||||||
aria-label={t('game.jackpotBroadcast.ariaLabel')}
|
aria-label={t('game.jackpotBroadcast.ariaLabel')}
|
||||||
className={cn(
|
className={cn(
|
||||||
'common-neon-inset flex w-full min-w-0 items-center overflow-hidden',
|
'common-neon-inset flex w-full min-w-0 items-center overflow-hidden',
|
||||||
'h-design-24 gap-design-5 !rounded-[3px] !px-design-7 !py-0 text-design-8',
|
'h-design-24 gap-design-4 !rounded-[3px] !px-design-5 !py-0 text-design-8',
|
||||||
'md:h-design-65 md:gap-design-10 md:!rounded-[5px] md:!px-design-20 md:text-design-16',
|
'md:h-design-65 md:gap-design-12 md:!rounded-[5px] md:!px-design-20 md:text-design-16',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
<div className="flex min-w-0 flex-1 items-center gap-design-4 md:gap-design-10">
|
||||||
<SmartImage
|
<SmartImage
|
||||||
className="h-design-12 w-design-12 shrink-0 md:h-design-24 md:w-design-24"
|
className="h-design-12 w-design-12 shrink-0 md:h-design-24 md:w-design-24"
|
||||||
alt={t('game.jackpotBroadcast.iconAlt')}
|
alt={t('game.jackpotBroadcast.iconAlt')}
|
||||||
@@ -162,6 +164,11 @@ export function MessageBroadcast({ className }: MessageBroadcastProps) {
|
|||||||
) : null}
|
) : null}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<JackpotPoolTicker
|
||||||
|
variant="inline"
|
||||||
|
className="!w-fit max-w-[54%] shrink-0 md:max-w-[calc(var(--design-unit)*320)]"
|
||||||
|
/>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ function createEmptyDashboardState(nowIso: string): DashboardState {
|
|||||||
return {
|
return {
|
||||||
countdownMs: 0,
|
countdownMs: 0,
|
||||||
featuredCellId: null,
|
featuredCellId: null,
|
||||||
|
jackpotPool: null,
|
||||||
onlinePlayers: 0,
|
onlinePlayers: 0,
|
||||||
tableLimitMax: 0,
|
tableLimitMax: 0,
|
||||||
tableLimitMin: 0,
|
tableLimitMin: 0,
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ function applyLobbySync(result: Awaited<ReturnType<typeof getGameLobbyInit>>) {
|
|||||||
},
|
},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
...currentSessionState.dashboard,
|
...currentSessionState.dashboard,
|
||||||
|
jackpotPool: result.snapshot.dashboard.jackpotPool,
|
||||||
tableLimitMax: result.snapshot.dashboard.tableLimitMax,
|
tableLimitMax: result.snapshot.dashboard.tableLimitMax,
|
||||||
tableLimitMin: result.snapshot.dashboard.tableLimitMin,
|
tableLimitMin: result.snapshot.dashboard.tableLimitMin,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -178,6 +178,11 @@ export default {
|
|||||||
streak: '{{count}}-win streak',
|
streak: '{{count}}-win streak',
|
||||||
winAction: 'won',
|
winAction: 'won',
|
||||||
},
|
},
|
||||||
|
jackpotPool: {
|
||||||
|
ariaLabel: 'Current jackpot pool {{amount}}',
|
||||||
|
iconAlt: 'Jackpot pool',
|
||||||
|
label: 'Jackpot',
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
unifiedBetHint: 'Unified bet',
|
unifiedBetHint: 'Unified bet',
|
||||||
totalBet: 'Total bet',
|
totalBet: 'Total bet',
|
||||||
|
|||||||
@@ -177,6 +177,11 @@ export default {
|
|||||||
streak: 'streak {{count}} menang',
|
streak: 'streak {{count}} menang',
|
||||||
winAction: 'memenangkan',
|
winAction: 'memenangkan',
|
||||||
},
|
},
|
||||||
|
jackpotPool: {
|
||||||
|
ariaLabel: 'Pool jackpot saat ini {{amount}}',
|
||||||
|
iconAlt: 'Pool jackpot',
|
||||||
|
label: 'Jackpot',
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
unifiedBetHint: 'Bet seragam',
|
unifiedBetHint: 'Bet seragam',
|
||||||
totalBet: 'Total bet',
|
totalBet: 'Total bet',
|
||||||
|
|||||||
@@ -180,6 +180,11 @@ export default {
|
|||||||
streak: 'streak {{count}} menang',
|
streak: 'streak {{count}} menang',
|
||||||
winAction: 'memenangi',
|
winAction: 'memenangi',
|
||||||
},
|
},
|
||||||
|
jackpotPool: {
|
||||||
|
ariaLabel: 'Dana jackpot semasa {{amount}}',
|
||||||
|
iconAlt: 'Dana jackpot',
|
||||||
|
label: 'Jackpot',
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
unifiedBetHint: 'Taruhan seragam',
|
unifiedBetHint: 'Taruhan seragam',
|
||||||
totalBet: 'Jumlah taruhan',
|
totalBet: 'Jumlah taruhan',
|
||||||
|
|||||||
@@ -175,6 +175,11 @@ export default {
|
|||||||
streak: '{{count}} 连胜',
|
streak: '{{count}} 连胜',
|
||||||
winAction: '赢得',
|
winAction: '赢得',
|
||||||
},
|
},
|
||||||
|
jackpotPool: {
|
||||||
|
ariaLabel: '彩金池当前金额 {{amount}}',
|
||||||
|
iconAlt: '彩金池',
|
||||||
|
label: '彩金池',
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
unifiedBetHint: '统一下注额',
|
unifiedBetHint: '统一下注额',
|
||||||
totalBet: '总下注',
|
totalBet: '总下注',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
@import "tw-animate-css";
|
@import "tw-animate-css";
|
||||||
@import "shadcn/tailwind.css";
|
@import "shadcn/tailwind.css";
|
||||||
@import "@fontsource-variable/geist";
|
@import "@fontsource-variable/geist";
|
||||||
|
@import "@fontsource-variable/oxanium";
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
@@ -12,6 +13,8 @@
|
|||||||
--font-mono:
|
--font-mono:
|
||||||
"JetBrains Mono", "SFMono-Regular", "SF Mono", Consolas, monospace;
|
"JetBrains Mono", "SFMono-Regular", "SF Mono", Consolas, monospace;
|
||||||
--font-countdown: "Countdown", "Inter", "SF Pro Display", sans-serif;
|
--font-countdown: "Countdown", "Inter", "SF Pro Display", sans-serif;
|
||||||
|
--font-jackpot-amount:
|
||||||
|
"Oxanium Variable", "Countdown", "SF Pro Display", sans-serif;
|
||||||
--color-game-bg: #07111f;
|
--color-game-bg: #07111f;
|
||||||
--color-game-surface: #0d1b2d;
|
--color-game-surface: #0d1b2d;
|
||||||
--color-game-surface-strong: #12253d;
|
--color-game-surface-strong: #12253d;
|
||||||
|
|||||||
@@ -109,9 +109,16 @@ export interface AnnouncementState {
|
|||||||
lastUpdatedAt: string | null
|
lastUpdatedAt: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface JackpotPoolState {
|
||||||
|
current: number
|
||||||
|
speedPerSecond: number
|
||||||
|
updatedAt: string | null
|
||||||
|
}
|
||||||
|
|
||||||
export interface DashboardState {
|
export interface DashboardState {
|
||||||
countdownMs: number
|
countdownMs: number
|
||||||
featuredCellId: number | null
|
featuredCellId: number | null
|
||||||
|
jackpotPool: JackpotPoolState | null
|
||||||
onlinePlayers: number
|
onlinePlayers: number
|
||||||
tableLimitMax: number
|
tableLimitMax: number
|
||||||
tableLimitMin: number
|
tableLimitMin: number
|
||||||
@@ -332,6 +339,7 @@ export interface AnnouncementStateDto {
|
|||||||
export interface DashboardStateDto {
|
export interface DashboardStateDto {
|
||||||
countdown_ms: number
|
countdown_ms: number
|
||||||
featured_cell_id: number | null
|
featured_cell_id: number | null
|
||||||
|
jackpot_pool?: GameJackpotPoolDto | null
|
||||||
online_players: number
|
online_players: number
|
||||||
table_limit_max: number
|
table_limit_max: number
|
||||||
table_limit_min: number
|
table_limit_min: number
|
||||||
@@ -339,6 +347,11 @@ export interface DashboardStateDto {
|
|||||||
updated_at: string | null
|
updated_at: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GameJackpotPoolDto {
|
||||||
|
current: string
|
||||||
|
speed: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface ConnectionStateDto {
|
export interface ConnectionStateDto {
|
||||||
connected_at: string | null
|
connected_at: string | null
|
||||||
last_error: string | null
|
last_error: string | null
|
||||||
@@ -451,6 +464,7 @@ export interface GameLobbyStreakWinRewardDto {
|
|||||||
export interface GameLobbyInitDto {
|
export interface GameLobbyInitDto {
|
||||||
bet_config: GameLobbyBetConfigDto
|
bet_config: GameLobbyBetConfigDto
|
||||||
dictionary: GameLobbyDictionaryItemDto[]
|
dictionary: GameLobbyDictionaryItemDto[]
|
||||||
|
jackpot_pool?: GameJackpotPoolDto | null
|
||||||
period?: GameLobbyPeriodDto | null
|
period?: GameLobbyPeriodDto | null
|
||||||
runtime_enabled: boolean
|
runtime_enabled: boolean
|
||||||
server_time: number
|
server_time: number
|
||||||
|
|||||||
Reference in New Issue
Block a user