@devrongx/games 0.4.11 → 0.4.12

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrongx/games",
3
- "version": "0.4.11",
3
+ "version": "0.4.12",
4
4
  "description": "Game UI components for sports prediction markets",
5
5
  "license": "MIT",
6
6
  "main": "./src/index.ts",
@@ -16,7 +16,6 @@ import { GamePopupShell } from "../../core/GamePopupShell";
16
16
  import { PreMatchIntro } from "./PreMatchIntro";
17
17
  import { PreMatchQuestions } from "./PreMatchQuestions";
18
18
  import { PreMatchGame } from "./PreMatchGame";
19
- import { PreMatchSubmitted } from "./PreMatchSubmitted";
20
19
  import { PreMatchLive } from "./PreMatchLive";
21
20
  import { PreMatchResults } from "./PreMatchResults";
22
21
  import { FullLeaderboard } from "./FullLeaderboard";
@@ -34,7 +33,7 @@ const GAME_ID = "pre-match";
34
33
  // ─── View logic ────────────────────────────────────────────────────────────────
35
34
 
36
35
  type UserFlowState = "intro" | "questions" | "game";
37
- type ActiveView = UserFlowState | "submitted" | "live" | "results";
36
+ type ActiveView = UserFlowState | "live" | "results";
38
37
 
39
38
  function getActiveView(
40
39
  poolStatus: number | undefined,
@@ -44,8 +43,7 @@ function getActiveView(
44
43
  if (poolStatus === undefined) return userFlowState;
45
44
  if (poolStatus === TDPoolStatus.COMPLETE || poolStatus === TDPoolStatus.CANCELLED) return "results";
46
45
  if (poolStatus === TDPoolStatus.CLOSED || poolStatus === TDPoolStatus.RESOLVING) return hasEntry ? "live" : "results";
47
- // Pool is open
48
- if (hasEntry) return "submitted";
46
+ // Pool is open — user can keep editing regardless
49
47
  return userFlowState;
50
48
  }
51
49
 
@@ -123,6 +121,31 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
123
121
  const [submitting, setSubmitting] = useState(false);
124
122
  const [submitError, setSubmitError] = useState<string | null>(null);
125
123
 
124
+ // ── Real bets restore: when user has submitted bets, load them into game state ─
125
+ const realBetsRestoredRef = useRef(false);
126
+ useEffect(() => {
127
+ if (!poolId || !config || !entryData || realBetsRestoredRef.current) return;
128
+ if (entryData.bets.length === 0) return;
129
+ const loaded: IUserBets = {};
130
+ const pickers: Record<number, number> = {};
131
+ for (const bet of entryData.bets) {
132
+ if (bet.parlay_id !== null) continue;
133
+ const mIdx = config.markets.findIndex((m) => m.backendChallengeId === bet.challenge_id);
134
+ if (mIdx < 0) continue;
135
+ const oIdx = config.markets[mIdx].options.findIndex(
136
+ (o) => o.label.toLowerCase().replace(/\s+/g, "_") === bet.selected_option,
137
+ );
138
+ if (oIdx < 0) continue;
139
+ loaded[mIdx] = { optionIdx: oIdx, amount: bet.coin_amount, parlaySlot: null };
140
+ pickers[mIdx] = oIdx;
141
+ }
142
+ if (Object.keys(loaded).length === 0) return;
143
+ setBets(loaded);
144
+ setExpandedPicker(pickers);
145
+ setUserFlowState("game");
146
+ realBetsRestoredRef.current = true;
147
+ }, [poolId, config, entryData]);
148
+
126
149
  // ── Draft restore: when entry + config load, seed bets from draft_selections ─
127
150
  const draftRestoredRef = useRef(false);
128
151
  const [restoredSelections, setRestoredSelections] = useState<IUserBets | undefined>(undefined);
@@ -276,24 +299,6 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
276
299
  }
277
300
  }, [poolId, config, bets, hasEntry, refetchEntry, refetchLB, refetchPool]);
278
301
 
279
- const handleAdjust = useCallback(async () => {
280
- // Load server bets back into local state
281
- if (entryData?.bets && config) {
282
- const loaded: IUserBets = {};
283
- for (const bet of entryData.bets) {
284
- if (bet.parlay_id !== null) continue; // skip parlays for now
285
- const mIdx = config.markets.findIndex((m) => m.backendChallengeId === bet.challenge_id);
286
- if (mIdx >= 0) {
287
- // Find option by matching the stored key to a label approximation
288
- // (we store selected_option as the label key from the pool option)
289
- const oIdx = config.markets[mIdx].options.findIndex((_, i) => i === 0); // fallback: first option
290
- loaded[mIdx] = { optionIdx: oIdx, amount: bet.coin_amount, parlaySlot: null };
291
- }
292
- }
293
- setBets(loaded);
294
- }
295
- setUserFlowState("game");
296
- }, [entryData, config]);
297
302
 
298
303
  // ── Loading ────────────────────────────────────────────────────────────────
299
304
  if (poolId && (poolLoading || (!config && !poolLoading))) {
@@ -353,17 +358,6 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
353
358
  />
354
359
  )}
355
360
 
356
- {activeView === "submitted" && (
357
- <PreMatchSubmitted
358
- config={config}
359
- poolId={poolId!}
360
- entryData={entryData}
361
- rankings={rankings}
362
- onAdjust={handleAdjust}
363
- onViewLeaderboard={() => setShowFullLeaderboard(true)}
364
- />
365
- )}
366
-
367
361
  {activeView === "live" && (
368
362
  <PreMatchLive
369
363
  config={config}