@devrongx/games 0.4.14 → 0.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -115,7 +115,6 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
|
|
|
115
115
|
|
|
116
116
|
// ── Bet state ─────────────────────────────────────────────────────────────
|
|
117
117
|
const [bets, setBets] = useState<IUserBets>({});
|
|
118
|
-
const [expandedPicker, setExpandedPicker] = useState<Record<number, number>>({});
|
|
119
118
|
const [userFlowState, setUserFlowState] = useState<UserFlowState>("intro");
|
|
120
119
|
const [showFullLeaderboard, setShowFullLeaderboard] = useState(false);
|
|
121
120
|
const [submitting, setSubmitting] = useState(false);
|
|
@@ -128,7 +127,6 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
|
|
|
128
127
|
if (!poolId || !config || !entryData || realBetsRestoredRef.current) return;
|
|
129
128
|
if (entryData.bets.length === 0) return;
|
|
130
129
|
const loaded: IUserBets = {};
|
|
131
|
-
const pickers: Record<number, number> = {};
|
|
132
130
|
for (const bet of entryData.bets) {
|
|
133
131
|
if (bet.parlay_id !== null) continue;
|
|
134
132
|
const mIdx = config.markets.findIndex((m) => m.backendChallengeId === bet.challenge_id);
|
|
@@ -138,12 +136,10 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
|
|
|
138
136
|
);
|
|
139
137
|
if (oIdx < 0) continue;
|
|
140
138
|
loaded[mIdx] = { optionIdx: oIdx, amount: bet.coin_amount, parlaySlot: null };
|
|
141
|
-
pickers[mIdx] = oIdx;
|
|
142
139
|
}
|
|
143
140
|
if (Object.keys(loaded).length === 0) return;
|
|
144
141
|
setBets(loaded);
|
|
145
142
|
setSubmittedBets(loaded);
|
|
146
|
-
setExpandedPicker(pickers);
|
|
147
143
|
setUserFlowState("game");
|
|
148
144
|
realBetsRestoredRef.current = true;
|
|
149
145
|
}, [poolId, config, entryData]);
|
|
@@ -238,11 +234,6 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
|
|
|
238
234
|
// ── Handlers ─────────────────────────────────────────────────────────────
|
|
239
235
|
const handleQuestionsComplete = useCallback((selections: IUserBets) => {
|
|
240
236
|
setBets(selections);
|
|
241
|
-
const pickers: Record<number, number> = {};
|
|
242
|
-
for (const [mIdxStr, entry] of Object.entries(selections)) {
|
|
243
|
-
pickers[Number(mIdxStr)] = entry.optionIdx;
|
|
244
|
-
}
|
|
245
|
-
setExpandedPicker(pickers);
|
|
246
237
|
setUserFlowState("game");
|
|
247
238
|
}, []);
|
|
248
239
|
|
|
@@ -252,10 +243,8 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
|
|
|
252
243
|
if (existing?.optionIdx === oIdx) {
|
|
253
244
|
const next = { ...prev };
|
|
254
245
|
delete next[mIdx];
|
|
255
|
-
setExpandedPicker((p) => { const n = { ...p }; delete n[mIdx]; return n; });
|
|
256
246
|
return next;
|
|
257
247
|
}
|
|
258
|
-
setExpandedPicker((p) => ({ ...p, [mIdx]: oIdx }));
|
|
259
248
|
return {
|
|
260
249
|
...prev,
|
|
261
250
|
[mIdx]: { optionIdx: oIdx, amount: existing?.amount ?? 0, parlaySlot: existing?.parlaySlot ?? null },
|
|
@@ -358,7 +347,6 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
|
|
|
358
347
|
config={config}
|
|
359
348
|
bets={bets}
|
|
360
349
|
onBetsChange={setBets}
|
|
361
|
-
expandedPicker={expandedPicker}
|
|
362
350
|
onOptionClick={handleOptionClick}
|
|
363
351
|
onAmountSelect={handleAmountSelect}
|
|
364
352
|
betSummary={betSummary}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @devrongx/games — games/prematch-bets/PreMatchGame.tsx
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
|
-
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
4
|
+
import { useState, useEffect, useMemo, useCallback, useRef } from "react";
|
|
5
5
|
import Image from "next/image";
|
|
6
6
|
import { motion, AnimatePresence, useSpring, useTransform, useMotionValue } from "framer-motion";
|
|
7
7
|
import { ChevronDown, Info, X, Play, Check, Loader2 } from "lucide-react";
|
|
@@ -30,7 +30,6 @@ interface PreMatchGameProps {
|
|
|
30
30
|
config: IChallengeConfig;
|
|
31
31
|
bets: IUserBets;
|
|
32
32
|
onBetsChange?: (bets: IUserBets) => void;
|
|
33
|
-
expandedPicker: Record<number, number>; // mIdx → oIdx for open pickers
|
|
34
33
|
onOptionClick: (mIdx: number, oIdx: number) => void;
|
|
35
34
|
onAmountSelect: (mIdx: number, oIdx: number, amount: number) => void;
|
|
36
35
|
betSummary: IBetSummary;
|
|
@@ -50,7 +49,7 @@ interface PreMatchGameProps {
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
export const PreMatchGame = ({ config, bets, onBetsChange,
|
|
52
|
+
export const PreMatchGame = ({ config, bets, onBetsChange, onOptionClick, onAmountSelect, betSummary, leaderboardRows, marketsOnly, onSubmit, submittedBets, onViewLeaderboard, parlayEnabled = false, submitting = false }: PreMatchGameProps) => {
|
|
54
53
|
const { selectedCount, compoundMultiplier, totalEntry, compoundedReward, remainingBalance, riskPercent } = betSummary;
|
|
55
54
|
|
|
56
55
|
// Button state: fresh (no prior submit), saved (submitted, no changes), changed (submitted, user modified)
|
|
@@ -87,6 +86,16 @@ export const PreMatchGame = ({ config, bets, onBetsChange, expandedPicker, onOpt
|
|
|
87
86
|
});
|
|
88
87
|
}, []);
|
|
89
88
|
|
|
89
|
+
// One-time: when bets are restored with amounts already set, auto-collapse those markets
|
|
90
|
+
const collapseInitializedRef = useRef(false);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (collapseInitializedRef.current) return;
|
|
93
|
+
const withAmounts = Object.entries(bets).filter(([, b]) => b.amount > 0);
|
|
94
|
+
if (withAmounts.length === 0) return;
|
|
95
|
+
setCollapsedMarkets(new Set(withAmounts.map(([k]) => Number(k))));
|
|
96
|
+
collapseInitializedRef.current = true;
|
|
97
|
+
}, [bets]);
|
|
98
|
+
|
|
90
99
|
// Parlay edit mode: which slot is being edited (null = none)
|
|
91
100
|
const [editingParlay, setEditingParlay] = useState<number | null>(null);
|
|
92
101
|
// Parlay info popup: which slot's breakdown is shown (null = none)
|
|
@@ -175,7 +184,7 @@ export const PreMatchGame = ({ config, bets, onBetsChange, expandedPicker, onOpt
|
|
|
175
184
|
<div className="flex flex-col gap-3">
|
|
176
185
|
{config.markets.map((market, mIdx) => {
|
|
177
186
|
const selection = bets[mIdx];
|
|
178
|
-
const isPickerOpenForMarket = mIdx
|
|
187
|
+
const isPickerOpenForMarket = !collapsedMarkets.has(mIdx) && selection !== undefined;
|
|
179
188
|
const showCategoryHeader = categoryFirstIndices.has(mIdx);
|
|
180
189
|
|
|
181
190
|
// Available balance for picker: remaining + current bet on this market (it would be freed)
|
|
@@ -316,7 +325,7 @@ export const PreMatchGame = ({ config, bets, onBetsChange, expandedPicker, onOpt
|
|
|
316
325
|
<div className="grid grid-cols-2 gap-1.5 px-1 pt-0.5 pb-1">
|
|
317
326
|
{market.options.map((opt, j) => {
|
|
318
327
|
const isSelected = selection?.optionIdx === j;
|
|
319
|
-
const isPickerOpen = isPickerOpenForMarket &&
|
|
328
|
+
const isPickerOpen = isPickerOpenForMarket && selection?.optionIdx === j;
|
|
320
329
|
const showPickerRow = isPickerOpenForMarket;
|
|
321
330
|
const displayReward = calcDisplayReward(opt, compoundMultiplier, isSelected, selectedCount, isSelected ? selection.amount : undefined);
|
|
322
331
|
const baseReward = optionReward(opt);
|
|
@@ -407,11 +416,11 @@ export const PreMatchGame = ({ config, bets, onBetsChange, expandedPicker, onOpt
|
|
|
407
416
|
<div className="flex items-center gap-1.5 overflow-x-auto scrollbar-hide py-1 px-0.5">
|
|
408
417
|
<span className="text-[8px] text-white/60 font-semibold flex-shrink-0" style={OUTFIT}>Bet:</span>
|
|
409
418
|
{Array.from({ length: chipCount }, (_, i) => (i + 1) * config.parlayConfig.stakeIncrements).map(amt => {
|
|
410
|
-
const isChipSelected = selection?.
|
|
419
|
+
const isChipSelected = selection?.amount === amt;
|
|
411
420
|
return (
|
|
412
421
|
<div
|
|
413
422
|
key={amt}
|
|
414
|
-
onClick={() => onAmountSelect(mIdx,
|
|
423
|
+
onClick={() => onAmountSelect(mIdx, selection!.optionIdx, amt)}
|
|
415
424
|
className="flex-shrink-0 flex items-center gap-0.5 px-2 py-[3px] rounded cursor-pointer transition-colors relative overflow-hidden"
|
|
416
425
|
style={isChipSelected ? {
|
|
417
426
|
background: "linear-gradient(135deg, #22E3E8, #9945FF, #f83cc5)",
|