@sensiblestats/widget-react 0.49.0 → 0.50.1
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/CHANGELOG.md +12 -0
- package/dist/index.cjs +1713 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1708 -81
- package/dist/index.js.map +1 -1
- package/dist/styles.css +305 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/StatsWidget.tsx
|
|
39
|
-
var
|
|
39
|
+
var import_react39 = require("react");
|
|
40
40
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/kickoff.ts
|
|
@@ -1908,7 +1908,7 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
|
|
|
1908
1908
|
}
|
|
1909
1909
|
|
|
1910
1910
|
// src/components/ChatPanel.tsx
|
|
1911
|
-
var
|
|
1911
|
+
var import_react38 = require("react");
|
|
1912
1912
|
|
|
1913
1913
|
// src/components/ChatHeader.tsx
|
|
1914
1914
|
var import_react11 = require("react");
|
|
@@ -4011,7 +4011,7 @@ function TodayPanel({ discovery, ui, monitor }) {
|
|
|
4011
4011
|
}
|
|
4012
4012
|
|
|
4013
4013
|
// src/components/GamesPanel.tsx
|
|
4014
|
-
var
|
|
4014
|
+
var import_react36 = require("react");
|
|
4015
4015
|
|
|
4016
4016
|
// src/components/GamesLoginWall.tsx
|
|
4017
4017
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
@@ -4123,64 +4123,1385 @@ function GamesHub({
|
|
|
4123
4123
|
}
|
|
4124
4124
|
|
|
4125
4125
|
// src/components/GameScreenHost.tsx
|
|
4126
|
+
var import_react35 = require("react");
|
|
4127
|
+
|
|
4128
|
+
// src/useGamePlay.ts
|
|
4129
|
+
var import_react28 = require("react");
|
|
4130
|
+
function toSubmitResult(payload) {
|
|
4131
|
+
return {
|
|
4132
|
+
// 'pending' means the play is recorded but awaiting resolution (fixture games)
|
|
4133
|
+
alreadyPlayed: payload.status === "played" || payload.status === "graded" || payload.status === "pending",
|
|
4134
|
+
score: payload.score,
|
|
4135
|
+
isCorrect: payload.isCorrect,
|
|
4136
|
+
clientStateJson: payload.clientStateJson,
|
|
4137
|
+
attemptsUsed: payload.attemptsUsed
|
|
4138
|
+
};
|
|
4139
|
+
}
|
|
4140
|
+
function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
4141
|
+
const [result, setResult] = (0, import_react28.useState)(null);
|
|
4142
|
+
const [submitting, setSubmitting] = (0, import_react28.useState)(false);
|
|
4143
|
+
const [rawStatus, setRawStatus] = (0, import_react28.useState)(null);
|
|
4144
|
+
const inFlightRef = (0, import_react28.useRef)(false);
|
|
4145
|
+
const convRef = (0, import_react28.useRef)(conversation);
|
|
4146
|
+
convRef.current = conversation;
|
|
4147
|
+
const optsRef = (0, import_react28.useRef)({ gameId, gameDay, fixtureId, refresh });
|
|
4148
|
+
optsRef.current = { gameId, gameDay, fixtureId, refresh };
|
|
4149
|
+
const submit = (0, import_react28.useCallback)(async (answerJson) => {
|
|
4150
|
+
const conv = convRef.current;
|
|
4151
|
+
if (!conv || inFlightRef.current) return;
|
|
4152
|
+
inFlightRef.current = true;
|
|
4153
|
+
setSubmitting(true);
|
|
4154
|
+
try {
|
|
4155
|
+
const opts = optsRef.current;
|
|
4156
|
+
const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId);
|
|
4157
|
+
if (playResult !== null) {
|
|
4158
|
+
setResult(playResult);
|
|
4159
|
+
if (playResult.pointsDelta != null) {
|
|
4160
|
+
opts.refresh?.();
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
} catch {
|
|
4164
|
+
} finally {
|
|
4165
|
+
inFlightRef.current = false;
|
|
4166
|
+
setSubmitting(false);
|
|
4167
|
+
}
|
|
4168
|
+
}, []);
|
|
4169
|
+
const hydrate = (0, import_react28.useCallback)(() => {
|
|
4170
|
+
const conv = convRef.current;
|
|
4171
|
+
if (!conv) return;
|
|
4172
|
+
const opts = optsRef.current;
|
|
4173
|
+
void (async () => {
|
|
4174
|
+
try {
|
|
4175
|
+
const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay);
|
|
4176
|
+
if (payload !== null) {
|
|
4177
|
+
setResult(toSubmitResult(payload));
|
|
4178
|
+
setRawStatus(payload.status);
|
|
4179
|
+
}
|
|
4180
|
+
} catch {
|
|
4181
|
+
}
|
|
4182
|
+
})();
|
|
4183
|
+
}, []);
|
|
4184
|
+
return { result, submitting, submit, hydrate, rawStatus };
|
|
4185
|
+
}
|
|
4186
|
+
|
|
4187
|
+
// src/components/games/MysteryTigerGame.tsx
|
|
4188
|
+
var import_react29 = require("react");
|
|
4126
4189
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4127
|
-
function
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4190
|
+
function parseClientState(json) {
|
|
4191
|
+
if (!json) return null;
|
|
4192
|
+
try {
|
|
4193
|
+
return JSON.parse(json);
|
|
4194
|
+
} catch {
|
|
4195
|
+
return null;
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
var ATTR_LABELS = {
|
|
4199
|
+
position: "Pos",
|
|
4200
|
+
nationality: "Nat",
|
|
4201
|
+
age: "Age",
|
|
4202
|
+
shirtNumber: "Kit",
|
|
4203
|
+
apps: "Apps"
|
|
4204
|
+
};
|
|
4205
|
+
var ATTR_KEYS = [
|
|
4206
|
+
"position",
|
|
4207
|
+
"nationality",
|
|
4208
|
+
"age",
|
|
4209
|
+
"shirtNumber",
|
|
4210
|
+
"apps"
|
|
4211
|
+
];
|
|
4212
|
+
function MysteryTigerGame({
|
|
4213
|
+
config,
|
|
4214
|
+
result,
|
|
4215
|
+
submitting,
|
|
4216
|
+
onSubmit
|
|
4217
|
+
}) {
|
|
4218
|
+
const [query, setQuery] = (0, import_react29.useState)("");
|
|
4219
|
+
const inputId = (0, import_react29.useId)();
|
|
4220
|
+
const clientState = parseClientState(result?.clientStateJson);
|
|
4221
|
+
const alreadyGuessedIds = new Set(
|
|
4222
|
+
clientState?.guessResults.map((g) => g.playerId) ?? []
|
|
4223
|
+
);
|
|
4224
|
+
const isOver = result?.alreadyPlayed === true || clientState?.solved === true || clientState?.failed === true;
|
|
4225
|
+
const filtered = config && !isOver ? config.squadPlayers.filter(
|
|
4226
|
+
(p) => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase())
|
|
4227
|
+
) : [];
|
|
4228
|
+
function handleSelect(playerId) {
|
|
4229
|
+
if (!config || isOver || submitting) return;
|
|
4230
|
+
const prevGuesses = clientState?.guessResults.map((g) => g.playerId) ?? [];
|
|
4231
|
+
const newGuesses = [...prevGuesses, playerId];
|
|
4232
|
+
setQuery("");
|
|
4233
|
+
onSubmit(JSON.stringify({ guesses: newGuesses }));
|
|
4234
|
+
}
|
|
4235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "ss-w-gt", "data-testid": "game-screen-mystery-tiger", children: [
|
|
4236
|
+
!config && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4237
|
+
config && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
|
|
4238
|
+
isOver && clientState && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: `ss-w-gt-banner ss-w-gt-banner--${clientState.solved ? "solved" : "failed"}`, children: [
|
|
4239
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gt-banner-label", children: clientState.solved ? "\u{1F42F} You found them!" : "\u{1F614} Better luck tomorrow" }),
|
|
4240
|
+
clientState.revealedPlayerName && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gt-banner-name", children: clientState.revealedPlayerName })
|
|
4241
|
+
] }),
|
|
4242
|
+
!isOver && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "ss-w-gtta", children: [
|
|
4243
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4244
|
+
"input",
|
|
4245
|
+
{
|
|
4246
|
+
id: inputId,
|
|
4247
|
+
type: "text",
|
|
4248
|
+
role: "textbox",
|
|
4249
|
+
className: "ss-w-gtta-i",
|
|
4250
|
+
placeholder: "Search squad players\u2026",
|
|
4251
|
+
value: query,
|
|
4252
|
+
disabled: submitting || isOver,
|
|
4253
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4254
|
+
autoComplete: "off",
|
|
4255
|
+
"aria-label": "Search for a player",
|
|
4256
|
+
"aria-autocomplete": "list"
|
|
4257
|
+
}
|
|
4258
|
+
),
|
|
4259
|
+
query.length > 0 && filtered.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gtta-drop", role: "listbox", children: filtered.map((p) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4260
|
+
"div",
|
|
4261
|
+
{
|
|
4262
|
+
className: "ss-w-gtta-opt",
|
|
4263
|
+
role: "option",
|
|
4264
|
+
"aria-selected": false,
|
|
4265
|
+
onClick: () => handleSelect(p.id),
|
|
4266
|
+
onKeyDown: (e) => {
|
|
4267
|
+
if (e.key === "Enter") handleSelect(p.id);
|
|
4268
|
+
},
|
|
4269
|
+
tabIndex: 0,
|
|
4270
|
+
children: p.name
|
|
4271
|
+
},
|
|
4272
|
+
p.id
|
|
4273
|
+
)) })
|
|
4274
|
+
] }),
|
|
4275
|
+
clientState && clientState.guessResults.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { children: [
|
|
4276
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "ss-w-gthdr", children: [
|
|
4277
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gthdr-c ss-w-gthdr-c--name", children: "Player" }),
|
|
4278
|
+
ATTR_KEYS.map((key) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gthdr-c", children: ATTR_LABELS[key] }, key))
|
|
4279
|
+
] }),
|
|
4280
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gtrows", children: clientState.guessResults.map((gr, i) => {
|
|
4281
|
+
const player = config.squadPlayers.find((p) => p.id === gr.playerId);
|
|
4282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "ss-w-gtrow", children: [
|
|
4283
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gtrow-nm", children: player?.name ?? `#${gr.playerId}` }),
|
|
4284
|
+
ATTR_KEYS.map((key) => {
|
|
4285
|
+
const v = gr[key];
|
|
4286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4287
|
+
"div",
|
|
4288
|
+
{
|
|
4289
|
+
className: `ss-w-gtile ss-w-gtile--${v.verdict}`,
|
|
4290
|
+
"data-testid": `verdict-${key}-${i}`,
|
|
4291
|
+
"data-verdict": v.verdict,
|
|
4292
|
+
"aria-label": `${ATTR_LABELS[key]}: ${v.verdict}${v.direction ? ` ${v.direction}` : ""}`,
|
|
4293
|
+
children: v.direction && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "ss-w-gtile-dir", "aria-hidden": "true", children: v.direction === "up" ? "\u2191" : "\u2193" })
|
|
4294
|
+
},
|
|
4295
|
+
key
|
|
4296
|
+
);
|
|
4297
|
+
})
|
|
4298
|
+
] }, gr.playerId);
|
|
4299
|
+
}) })
|
|
4300
|
+
] }),
|
|
4301
|
+
clientState?.hintLine && !isOver && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gt-hint", children: clientState.hintLine }),
|
|
4302
|
+
!isOver && clientState && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "ss-w-gt-hint", children: [
|
|
4303
|
+
clientState.guessesRemaining,
|
|
4304
|
+
" guess",
|
|
4305
|
+
clientState.guessesRemaining !== 1 ? "es" : "",
|
|
4306
|
+
" remaining"
|
|
4307
|
+
] })
|
|
4308
|
+
] })
|
|
4309
|
+
] });
|
|
4310
|
+
}
|
|
4311
|
+
|
|
4312
|
+
// src/components/games/HigherOrLowerGame.tsx
|
|
4313
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
4314
|
+
function parseClientState2(json) {
|
|
4315
|
+
if (!json) return null;
|
|
4316
|
+
try {
|
|
4317
|
+
return JSON.parse(json);
|
|
4318
|
+
} catch {
|
|
4319
|
+
return null;
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
function AnsweredRow({
|
|
4323
|
+
answered,
|
|
4324
|
+
pair
|
|
4325
|
+
}) {
|
|
4326
|
+
const cls = `ss-w-hlrrow ss-w-hlrrow--${answered.wasCorrect ? "correct" : "wrong"}`;
|
|
4327
|
+
const icon = answered.wasCorrect ? "\u2713" : "\u2717";
|
|
4328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: cls, children: [
|
|
4329
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "ss-w-hlrrow-names", children: [
|
|
4330
|
+
pair?.playerAName ?? "?",
|
|
4331
|
+
" vs ",
|
|
4332
|
+
pair?.playerBName ?? "?"
|
|
4333
|
+
] }),
|
|
4334
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "ss-w-hlrrow-pick", children: answered.pick }),
|
|
4335
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "ss-w-hlrrow-icon", children: icon })
|
|
4336
|
+
] });
|
|
4337
|
+
}
|
|
4338
|
+
function HigherOrLowerGame({
|
|
4339
|
+
config,
|
|
4340
|
+
result,
|
|
4341
|
+
submitting,
|
|
4342
|
+
onSubmit
|
|
4343
|
+
}) {
|
|
4344
|
+
const clientState = parseClientState2(result?.clientStateJson);
|
|
4345
|
+
const answeredCount = clientState?.answeredPairs.length ?? 0;
|
|
4346
|
+
const runEndedWrong = clientState?.answeredPairs.some((p) => !p.wasCorrect) ?? false;
|
|
4347
|
+
const allPairsAnswered = config != null && answeredCount >= config.pairs.length;
|
|
4348
|
+
const isOver = result?.alreadyPlayed === true || runEndedWrong || allPairsAnswered;
|
|
4349
|
+
const currentPair = config && !isOver ? config.pairs[answeredCount] ?? null : null;
|
|
4350
|
+
function handlePick(pick) {
|
|
4351
|
+
if (!config || isOver || submitting || !currentPair) return;
|
|
4352
|
+
const prevAnswers = clientState?.answeredPairs.map((p) => ({ pairIndex: p.pairIndex, pick: p.pick })) ?? [];
|
|
4353
|
+
const newAnswers = [...prevAnswers, { pairIndex: currentPair.pairIndex, pick }];
|
|
4354
|
+
onSubmit(JSON.stringify({ answers: newAnswers }));
|
|
4355
|
+
}
|
|
4356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hl", "data-testid": "game-screen-higher-or-lower", children: [
|
|
4357
|
+
!config && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4358
|
+
config && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
4359
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlctx", children: [
|
|
4360
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "ss-w-hlctx-fam", children: config.statLabel }),
|
|
4361
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "ss-w-hlctx-szn", children: config.seasonLabel })
|
|
4362
|
+
] }),
|
|
4363
|
+
currentPair && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlpair", children: [
|
|
4364
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlpc", children: [
|
|
4365
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlpc-name", children: currentPair.playerAName }),
|
|
4366
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlpc-val", children: currentPair.playerAValue })
|
|
4367
|
+
] }),
|
|
4368
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlpc ss-w-hlpc--b", children: [
|
|
4369
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlpc-name", children: currentPair.playerBName }),
|
|
4370
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlpc-val ss-w-hlpc-val--hidden", children: "?" })
|
|
4371
|
+
] })
|
|
4372
|
+
] }),
|
|
4373
|
+
!isOver && currentPair && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlbtns", children: [
|
|
4374
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4375
|
+
"button",
|
|
4376
|
+
{
|
|
4377
|
+
type: "button",
|
|
4378
|
+
className: "ss-w-hlbtn",
|
|
4379
|
+
disabled: submitting,
|
|
4380
|
+
onClick: () => handlePick("higher"),
|
|
4381
|
+
children: "Higher"
|
|
4382
|
+
}
|
|
4383
|
+
),
|
|
4384
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4385
|
+
"button",
|
|
4386
|
+
{
|
|
4387
|
+
type: "button",
|
|
4388
|
+
className: "ss-w-hlbtn",
|
|
4389
|
+
disabled: submitting,
|
|
4390
|
+
onClick: () => handlePick("lower"),
|
|
4391
|
+
children: "Lower"
|
|
4392
|
+
}
|
|
4393
|
+
)
|
|
4394
|
+
] }),
|
|
4395
|
+
clientState && clientState.answeredPairs.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlresults", children: clientState.answeredPairs.map((answered) => {
|
|
4396
|
+
const pair = config.pairs.find((p) => p.pairIndex === answered.pairIndex);
|
|
4397
|
+
const vCls = `ss-w-hlpc-val ss-w-hlpc-val--${answered.wasCorrect ? "correct" : "wrong"}`;
|
|
4398
|
+
const badgeCls = `ss-w-hlpc-badge ss-w-hlpc-badge--${answered.wasCorrect ? "correct" : "wrong"}`;
|
|
4399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlrrow", children: [
|
|
4400
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlpair", children: [
|
|
4401
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlpc", children: [
|
|
4402
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlpc-name", children: pair?.playerAName ?? "?" }),
|
|
4403
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlpc-val", children: pair?.playerAValue })
|
|
4404
|
+
] }),
|
|
4405
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "ss-w-hlpc ss-w-hlpc--b", children: [
|
|
4406
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "ss-w-hlpc-name", children: pair?.playerBName ?? "?" }),
|
|
4407
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: vCls, children: answered.playerBValue }),
|
|
4408
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: badgeCls, children: answered.wasCorrect ? "\u2713" : "\u2717" })
|
|
4409
|
+
] })
|
|
4410
|
+
] }),
|
|
4411
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(AnsweredRow, { answered, pair })
|
|
4412
|
+
] }, answered.pairIndex);
|
|
4413
|
+
}) })
|
|
4414
|
+
] })
|
|
4415
|
+
] });
|
|
4416
|
+
}
|
|
4417
|
+
|
|
4418
|
+
// src/components/games/CareerPathGame.tsx
|
|
4419
|
+
var import_react30 = require("react");
|
|
4420
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
4421
|
+
function parseClientState3(json) {
|
|
4422
|
+
if (!json) return null;
|
|
4423
|
+
try {
|
|
4424
|
+
return JSON.parse(json);
|
|
4425
|
+
} catch {
|
|
4426
|
+
return null;
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
function SpellYear({ spell }) {
|
|
4430
|
+
const parts = [];
|
|
4431
|
+
if (spell.startYear) parts.push(String(spell.startYear));
|
|
4432
|
+
if (spell.endYear) parts.push(String(spell.endYear));
|
|
4433
|
+
if (parts.length === 0) return null;
|
|
4434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "ss-w-cpath-spell-yr", children: parts.join(" \u2013 ") });
|
|
4435
|
+
}
|
|
4436
|
+
function ClubSpellCard({ spell }) {
|
|
4437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: `ss-w-cpath-club${spell.isLoan ? " ss-w-cpath-club--loan" : ""}`, children: [
|
|
4438
|
+
spell.crestUrl ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
4439
|
+
"img",
|
|
4440
|
+
{
|
|
4441
|
+
src: spell.crestUrl,
|
|
4442
|
+
alt: spell.clubName,
|
|
4443
|
+
className: "ss-w-cpath-crest",
|
|
4444
|
+
loading: "lazy"
|
|
4445
|
+
}
|
|
4446
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "ss-w-cpath-crest ss-w-cpath-crest--fallback", "aria-hidden": "true" }),
|
|
4447
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "ss-w-cpath-club-info", children: [
|
|
4448
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "ss-w-cpath-club-name", children: spell.clubName }),
|
|
4449
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(SpellYear, { spell }),
|
|
4450
|
+
spell.isLoan && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "ss-w-cpath-loan-badge", children: "Loan" })
|
|
4451
|
+
] })
|
|
4452
|
+
] });
|
|
4453
|
+
}
|
|
4454
|
+
function CareerPathGame({
|
|
4455
|
+
config,
|
|
4456
|
+
result,
|
|
4457
|
+
submitting,
|
|
4458
|
+
onSubmit
|
|
4459
|
+
}) {
|
|
4460
|
+
const [query, setQuery] = (0, import_react30.useState)("");
|
|
4461
|
+
const inputId = (0, import_react30.useId)();
|
|
4462
|
+
const clientState = parseClientState3(result?.clientStateJson);
|
|
4463
|
+
const alreadyGuessedIds = new Set(
|
|
4464
|
+
clientState?.guessResults.map((g) => g.playerId) ?? []
|
|
4465
|
+
);
|
|
4466
|
+
const isOver = result?.alreadyPlayed === true || clientState?.solved === true || clientState?.failed === true;
|
|
4467
|
+
const visiblePath = clientState?.visiblePath ?? config?.initialPath ?? [];
|
|
4468
|
+
const filtered = config && !isOver ? config.typeaheadPool.filter(
|
|
4469
|
+
(p) => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase())
|
|
4470
|
+
) : [];
|
|
4471
|
+
function handleSelect(playerId) {
|
|
4472
|
+
if (!config || isOver || submitting) return;
|
|
4473
|
+
const prevGuesses = clientState?.guessResults.map((g) => g.playerId) ?? [];
|
|
4474
|
+
const newGuesses = [...prevGuesses, playerId];
|
|
4475
|
+
setQuery("");
|
|
4476
|
+
onSubmit(JSON.stringify({ guesses: newGuesses }));
|
|
4477
|
+
}
|
|
4478
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "ss-w-cpath", "data-testid": "game-screen-career-path", children: [
|
|
4479
|
+
!config && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4480
|
+
config && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
|
|
4481
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "ss-w-cpath-ctx", children: [
|
|
4482
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "ss-w-cpath-ctx-label", children: "Career clubs" }),
|
|
4483
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "ss-w-cpath-ctx-count", children: [
|
|
4484
|
+
config.totalClubs,
|
|
4485
|
+
" clubs total"
|
|
4486
|
+
] })
|
|
4487
|
+
] }),
|
|
4488
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "ss-w-cpath-path", children: [
|
|
4489
|
+
visiblePath.map((spell, i) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ClubSpellCard, { spell }, `${spell.clubName}-${i}`)),
|
|
4490
|
+
(clientState?.totalClubs ?? config.totalClubs) > visiblePath.length && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "ss-w-cpath-hidden", children: [
|
|
4491
|
+
"+",
|
|
4492
|
+
(clientState?.totalClubs ?? config.totalClubs) - visiblePath.length,
|
|
4493
|
+
" more clubs hidden"
|
|
4494
|
+
] })
|
|
4495
|
+
] }),
|
|
4496
|
+
isOver && clientState && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: `ss-w-cpath-banner ss-w-cpath-banner--${clientState.solved ? "solved" : "failed"}`, children: [
|
|
4497
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "ss-w-cpath-banner-label", children: clientState.solved ? "Career traced!" : "Better luck tomorrow" }),
|
|
4498
|
+
clientState.revealedPlayerName && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "ss-w-cpath-banner-name", children: clientState.revealedPlayerName })
|
|
4499
|
+
] }),
|
|
4500
|
+
!isOver && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "ss-w-gtta", children: [
|
|
4501
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
4502
|
+
"input",
|
|
4503
|
+
{
|
|
4504
|
+
id: inputId,
|
|
4505
|
+
type: "text",
|
|
4506
|
+
role: "textbox",
|
|
4507
|
+
className: "ss-w-gtta-i",
|
|
4508
|
+
placeholder: "Search players\u2026",
|
|
4509
|
+
value: query,
|
|
4510
|
+
disabled: submitting || isOver,
|
|
4511
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4512
|
+
autoComplete: "off",
|
|
4513
|
+
"aria-label": "Search for a player",
|
|
4514
|
+
"aria-autocomplete": "list"
|
|
4515
|
+
}
|
|
4516
|
+
),
|
|
4517
|
+
query.length > 0 && filtered.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "ss-w-gtta-drop", role: "listbox", children: filtered.map((p) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
4518
|
+
"div",
|
|
4519
|
+
{
|
|
4520
|
+
className: "ss-w-gtta-opt",
|
|
4521
|
+
role: "option",
|
|
4522
|
+
"aria-selected": false,
|
|
4523
|
+
onClick: () => handleSelect(p.id),
|
|
4524
|
+
onKeyDown: (e) => {
|
|
4525
|
+
if (e.key === "Enter") handleSelect(p.id);
|
|
4526
|
+
},
|
|
4527
|
+
tabIndex: 0,
|
|
4528
|
+
children: p.name
|
|
4529
|
+
},
|
|
4530
|
+
p.id
|
|
4531
|
+
)) })
|
|
4532
|
+
] }),
|
|
4533
|
+
clientState?.hintLine && !isOver && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "ss-w-cpath-hint", children: clientState.hintLine }),
|
|
4534
|
+
!isOver && clientState && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "ss-w-cpath-hint", children: [
|
|
4535
|
+
clientState.guessesRemaining,
|
|
4536
|
+
" guess",
|
|
4537
|
+
clientState.guessesRemaining !== 1 ? "es" : "",
|
|
4538
|
+
" remaining"
|
|
4539
|
+
] })
|
|
4540
|
+
] })
|
|
4541
|
+
] });
|
|
4542
|
+
}
|
|
4543
|
+
|
|
4544
|
+
// src/components/games/BeatTheGridGame.tsx
|
|
4545
|
+
var import_react31 = __toESM(require("react"), 1);
|
|
4546
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
4547
|
+
function parseClientState4(json) {
|
|
4548
|
+
if (!json) return null;
|
|
4549
|
+
try {
|
|
4550
|
+
return JSON.parse(json);
|
|
4551
|
+
} catch {
|
|
4552
|
+
return null;
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
function findCellResult(cells, row, col) {
|
|
4556
|
+
return cells.find((c) => c.row === row && c.col === col);
|
|
4557
|
+
}
|
|
4558
|
+
function SearchSheet({
|
|
4559
|
+
row,
|
|
4560
|
+
col,
|
|
4561
|
+
rowLabel,
|
|
4562
|
+
colLabel,
|
|
4563
|
+
playerPool,
|
|
4564
|
+
alreadyFilledIds,
|
|
4565
|
+
onPick,
|
|
4566
|
+
onDismiss
|
|
4567
|
+
}) {
|
|
4568
|
+
const [query, setQuery] = (0, import_react31.useState)("");
|
|
4569
|
+
const inputId = (0, import_react31.useId)();
|
|
4570
|
+
const filtered = playerPool.filter(
|
|
4571
|
+
(p) => !alreadyFilledIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase())
|
|
4572
|
+
);
|
|
4573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "ss-w-btg-sheet", "data-testid": "btg-search-sheet", children: [
|
|
4574
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "ss-w-btg-sheet-hdr", children: [
|
|
4575
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "ss-w-btg-sheet-ctx", children: [
|
|
4576
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-sheet-row", children: rowLabel }),
|
|
4577
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-sheet-sep", children: "\xD7" }),
|
|
4578
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-sheet-col", children: colLabel })
|
|
4579
|
+
] }),
|
|
4580
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
4581
|
+
"button",
|
|
4582
|
+
{
|
|
4583
|
+
type: "button",
|
|
4584
|
+
className: "ss-w-btg-sheet-close",
|
|
4585
|
+
"data-testid": "btg-sheet-dismiss",
|
|
4586
|
+
"aria-label": "Dismiss",
|
|
4587
|
+
onClick: onDismiss,
|
|
4588
|
+
children: "\u2715"
|
|
4589
|
+
}
|
|
4590
|
+
)
|
|
4591
|
+
] }),
|
|
4592
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "ss-w-gtta", children: [
|
|
4593
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
4594
|
+
"input",
|
|
4595
|
+
{
|
|
4596
|
+
id: inputId,
|
|
4597
|
+
type: "text",
|
|
4598
|
+
role: "textbox",
|
|
4599
|
+
className: "ss-w-gtta-i",
|
|
4600
|
+
placeholder: "Search players\u2026",
|
|
4601
|
+
value: query,
|
|
4602
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4603
|
+
autoComplete: "off",
|
|
4604
|
+
"aria-label": `Search player for ${rowLabel} \xD7 ${colLabel}`,
|
|
4605
|
+
"aria-autocomplete": "list",
|
|
4606
|
+
autoFocus: true
|
|
4607
|
+
}
|
|
4608
|
+
),
|
|
4609
|
+
query.length > 0 && filtered.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "ss-w-gtta-drop ss-w-btg-ta-list", role: "listbox", children: filtered.map((p) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
4610
|
+
"div",
|
|
4611
|
+
{
|
|
4612
|
+
className: "ss-w-gtta-opt",
|
|
4613
|
+
role: "option",
|
|
4614
|
+
"aria-selected": false,
|
|
4615
|
+
onClick: () => onPick(row, col, p.id),
|
|
4616
|
+
onKeyDown: (e) => {
|
|
4617
|
+
if (e.key === "Enter") onPick(row, col, p.id);
|
|
4618
|
+
},
|
|
4619
|
+
tabIndex: 0,
|
|
4620
|
+
children: p.name
|
|
4621
|
+
},
|
|
4622
|
+
p.id
|
|
4623
|
+
)) })
|
|
4624
|
+
] })
|
|
4625
|
+
] });
|
|
4626
|
+
}
|
|
4627
|
+
function BeatTheGridGame({
|
|
4628
|
+
config,
|
|
4629
|
+
result,
|
|
4630
|
+
submitting,
|
|
4631
|
+
onSubmit,
|
|
4632
|
+
playerPool
|
|
4633
|
+
}) {
|
|
4634
|
+
const [activeCell, setActiveCell] = (0, import_react31.useState)(null);
|
|
4635
|
+
const clientState = parseClientState4(result?.clientStateJson);
|
|
4636
|
+
const filledCells = clientState?.cells ?? [];
|
|
4637
|
+
const isLocked2 = result?.alreadyPlayed === true || clientState?.isComplete === true;
|
|
4638
|
+
const alreadyFilledIds = new Set(filledCells.map((c) => c.playerId));
|
|
4639
|
+
function handleCellClick(row, col) {
|
|
4640
|
+
if (isLocked2 || submitting) return;
|
|
4641
|
+
const alreadyFilled = findCellResult(filledCells, row, col);
|
|
4642
|
+
if (alreadyFilled) return;
|
|
4643
|
+
setActiveCell({ row, col });
|
|
4644
|
+
}
|
|
4645
|
+
function handlePick(row, col, playerId) {
|
|
4646
|
+
setActiveCell(null);
|
|
4647
|
+
const prevCells = filledCells.map((c) => ({ row: c.row, col: c.col, playerId: c.playerId }));
|
|
4648
|
+
const newCells = [...prevCells, { row, col, playerId }];
|
|
4649
|
+
onSubmit(JSON.stringify({ cells: newCells }));
|
|
4650
|
+
}
|
|
4651
|
+
if (!config) {
|
|
4652
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "ss-w-btg", "data-testid": "game-screen-beat-the-grid", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
4653
|
+
}
|
|
4654
|
+
const rows = config.rows;
|
|
4655
|
+
const cols = config.cols;
|
|
4656
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "ss-w-btg", "data-testid": "game-screen-beat-the-grid", children: [
|
|
4657
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "ss-w-btg-ctx", children: [
|
|
4658
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "ss-w-btg-ctx-score", children: [
|
|
4659
|
+
"Score: ",
|
|
4660
|
+
clientState?.totalScore ?? 0
|
|
4661
|
+
] }),
|
|
4662
|
+
!isLocked2 && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "ss-w-btg-ctx-left", children: [
|
|
4663
|
+
config.maxGuesses - filledCells.length,
|
|
4664
|
+
" cell",
|
|
4665
|
+
config.maxGuesses - filledCells.length !== 1 ? "s" : "",
|
|
4666
|
+
" left"
|
|
4667
|
+
] }),
|
|
4668
|
+
isLocked2 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-ctx-done", children: "Complete" })
|
|
4669
|
+
] }),
|
|
4670
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
4671
|
+
"div",
|
|
4672
|
+
{
|
|
4673
|
+
className: "ss-w-btg-grid",
|
|
4674
|
+
style: { gridTemplateColumns: `auto repeat(${cols.length}, 1fr)` },
|
|
4675
|
+
role: "grid",
|
|
4676
|
+
children: [
|
|
4677
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "ss-w-btg-gc ss-w-btg-gc--corner" }),
|
|
4678
|
+
cols.map((col) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "ss-w-btg-gc ss-w-btg-gc--colhdr", children: col }, col)),
|
|
4679
|
+
rows.map((rowLabel, rowIdx) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_react31.default.Fragment, { children: [
|
|
4680
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "ss-w-btg-gc ss-w-btg-gc--rowhdr", children: rowLabel }),
|
|
4681
|
+
cols.map((colLabel, colIdx) => {
|
|
4682
|
+
const filled = findCellResult(filledCells, rowIdx, colIdx);
|
|
4683
|
+
const isActive = activeCell?.row === rowIdx && activeCell?.col === colIdx;
|
|
4684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
4685
|
+
"button",
|
|
4686
|
+
{
|
|
4687
|
+
type: "button",
|
|
4688
|
+
"data-testid": `btg-cell-${rowIdx}-${colIdx}`,
|
|
4689
|
+
"aria-label": `${rowLabel} ${colLabel}`,
|
|
4690
|
+
className: [
|
|
4691
|
+
"ss-w-btg-gc ss-w-btg-cell",
|
|
4692
|
+
filled ? filled.isCorrect ? "ss-w-btg-cell--correct" : "ss-w-btg-cell--wrong" : "",
|
|
4693
|
+
isActive ? "ss-w-btg-cell--active" : ""
|
|
4694
|
+
].filter(Boolean).join(" "),
|
|
4695
|
+
disabled: isLocked2 || submitting,
|
|
4696
|
+
onClick: () => handleCellClick(rowIdx, colIdx),
|
|
4697
|
+
children: filled ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
|
|
4698
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-cell-score", children: filled.rarityScore }),
|
|
4699
|
+
filled.isCorrect && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-cell-check", "aria-hidden": "true", children: "\u2713" })
|
|
4700
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-cell-empty", "aria-hidden": "true", children: "+" })
|
|
4701
|
+
},
|
|
4702
|
+
`cell-${rowIdx}-${colIdx}`
|
|
4703
|
+
);
|
|
4704
|
+
})
|
|
4705
|
+
] }, rowIdx))
|
|
4706
|
+
]
|
|
4707
|
+
}
|
|
4708
|
+
),
|
|
4709
|
+
activeCell !== null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
4710
|
+
SearchSheet,
|
|
4711
|
+
{
|
|
4712
|
+
row: activeCell.row,
|
|
4713
|
+
col: activeCell.col,
|
|
4714
|
+
rowLabel: rows[activeCell.row] ?? "",
|
|
4715
|
+
colLabel: cols[activeCell.col] ?? "",
|
|
4716
|
+
playerPool,
|
|
4717
|
+
alreadyFilledIds,
|
|
4718
|
+
onPick: handlePick,
|
|
4719
|
+
onDismiss: () => setActiveCell(null)
|
|
4720
|
+
}
|
|
4721
|
+
)
|
|
4722
|
+
] });
|
|
4723
|
+
}
|
|
4724
|
+
|
|
4725
|
+
// src/components/games/GuessTheXiGame.tsx
|
|
4726
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
4727
|
+
function parseClientState5(json) {
|
|
4728
|
+
if (!json) return null;
|
|
4729
|
+
try {
|
|
4730
|
+
return JSON.parse(json);
|
|
4731
|
+
} catch {
|
|
4732
|
+
return null;
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
function RevealCard({ reveal }) {
|
|
4736
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-reveal", "data-reveal-type": reveal.type ?? "", children: [
|
|
4737
|
+
reveal.slot && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-reveal-slot", children: reveal.slot }),
|
|
4738
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-reveal-val", children: reveal.value })
|
|
4739
|
+
] });
|
|
4740
|
+
}
|
|
4741
|
+
function GuessTheXiGame({
|
|
4742
|
+
config,
|
|
4743
|
+
result,
|
|
4744
|
+
submitting,
|
|
4745
|
+
onSubmit
|
|
4746
|
+
}) {
|
|
4747
|
+
const clientState = parseClientState5(result?.clientStateJson);
|
|
4748
|
+
const isOver = result?.alreadyPlayed === true || clientState?.status === "solved" || clientState?.status === "failed";
|
|
4749
|
+
function handlePick(teamId) {
|
|
4750
|
+
if (!config || isOver || submitting) return;
|
|
4751
|
+
const prevGuesses = clientState?.guessHistory.map((g) => ({ teamId: g.teamId })) ?? [];
|
|
4752
|
+
const newGuesses = [...prevGuesses, { teamId }];
|
|
4753
|
+
onSubmit(JSON.stringify({ guesses: newGuesses }));
|
|
4754
|
+
}
|
|
4755
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi", "data-testid": "game-screen-guess-the-xi", children: [
|
|
4756
|
+
!config && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4757
|
+
config && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
|
|
4758
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-ctx", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-ctx-label", children: config.poolLabel }) }),
|
|
4759
|
+
config.positions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-pitch", children: config.positions.map((pos) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-pslot", children: [
|
|
4760
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-pslot-pos", children: pos.slot }),
|
|
4761
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-pslot-nat", children: pos.nationality })
|
|
4762
|
+
] }, pos.slot)) }),
|
|
4763
|
+
clientState && clientState.earnedReveals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-reveals", children: clientState.earnedReveals.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RevealCard, { reveal: r }, i)) }),
|
|
4764
|
+
isOver && clientState && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: `ss-w-gxi-banner ss-w-gxi-banner--${clientState.status}`, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-banner-label", children: clientState.status === "solved" ? `Solved! ${clientState.score} pts` : "Better luck tomorrow" }) }),
|
|
4765
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-pool", children: config.teamPool.map((team) => {
|
|
4766
|
+
const guessRecord = clientState?.guessHistory.find((g) => g.teamId === team.teamId);
|
|
4767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
4768
|
+
"button",
|
|
4769
|
+
{
|
|
4770
|
+
type: "button",
|
|
4771
|
+
className: [
|
|
4772
|
+
"ss-w-gxi-team-btn",
|
|
4773
|
+
guessRecord ? guessRecord.wasCorrect ? "ss-w-gxi-team-btn--correct" : "ss-w-gxi-team-btn--wrong" : ""
|
|
4774
|
+
].filter(Boolean).join(" "),
|
|
4775
|
+
disabled: isOver || submitting,
|
|
4776
|
+
onClick: () => handlePick(team.teamId),
|
|
4777
|
+
children: team.teamName
|
|
4778
|
+
},
|
|
4779
|
+
team.teamId
|
|
4780
|
+
);
|
|
4781
|
+
}) }),
|
|
4782
|
+
!isOver && clientState && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-hint", children: [
|
|
4783
|
+
"Guess ",
|
|
4784
|
+
clientState.guessesUsed + 1,
|
|
4785
|
+
" of 6"
|
|
4786
|
+
] })
|
|
4787
|
+
] })
|
|
4788
|
+
] });
|
|
4789
|
+
}
|
|
4790
|
+
|
|
4791
|
+
// src/components/games/DailyQuizGame.tsx
|
|
4792
|
+
var import_react32 = require("react");
|
|
4793
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
4794
|
+
function parseClientState6(json) {
|
|
4795
|
+
if (!json) return null;
|
|
4796
|
+
try {
|
|
4797
|
+
return JSON.parse(json);
|
|
4798
|
+
} catch {
|
|
4799
|
+
return null;
|
|
4800
|
+
}
|
|
4801
|
+
}
|
|
4802
|
+
function findResult(results, index) {
|
|
4803
|
+
return results.find((r) => r.index === index);
|
|
4804
|
+
}
|
|
4805
|
+
function DailyQuizGame({
|
|
4806
|
+
config,
|
|
4807
|
+
result,
|
|
4808
|
+
submitting,
|
|
4809
|
+
onSubmit
|
|
4810
|
+
}) {
|
|
4811
|
+
const [selections, setSelections] = (0, import_react32.useState)(/* @__PURE__ */ new Map());
|
|
4812
|
+
const clientState = parseClientState6(result?.clientStateJson);
|
|
4813
|
+
const isRevealed = (clientState?.results.length ?? 0) > 0 || result?.alreadyPlayed === true;
|
|
4814
|
+
const allAnswered = config != null && selections.size === config.questions.length;
|
|
4815
|
+
function handleSelect(questionIndex, optionIndex) {
|
|
4816
|
+
if (isRevealed || submitting) return;
|
|
4817
|
+
setSelections((prev) => new Map(prev).set(questionIndex, optionIndex));
|
|
4818
|
+
}
|
|
4819
|
+
function handleSubmit() {
|
|
4820
|
+
if (!config || !allAnswered || isRevealed || submitting) return;
|
|
4821
|
+
const answers = config.questions.map((q) => ({
|
|
4822
|
+
index: q.index,
|
|
4823
|
+
selectedOptionIndex: selections.get(q.index) ?? 0
|
|
4824
|
+
}));
|
|
4825
|
+
onSubmit(JSON.stringify({ answers }));
|
|
4826
|
+
}
|
|
4827
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-dq", "data-testid": "game-screen-daily-quiz", children: [
|
|
4828
|
+
!config && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4829
|
+
config && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
|
|
4830
|
+
isRevealed && result?.score != null && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-dq-score", children: [
|
|
4831
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "ss-w-dq-score-val", children: result.score }),
|
|
4832
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "ss-w-dq-score-label", children: "pts" })
|
|
4833
|
+
] }),
|
|
4834
|
+
!isRevealed && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-dq-prog", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
4835
|
+
"div",
|
|
4836
|
+
{
|
|
4837
|
+
className: "ss-w-dq-prog-fill",
|
|
4838
|
+
style: { width: `${Math.round(selections.size / config.questions.length * 100)}%` }
|
|
4839
|
+
}
|
|
4840
|
+
) }),
|
|
4841
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-dq-questions", children: config.questions.map((q) => {
|
|
4842
|
+
const qResult = clientState ? findResult(clientState.results, q.index) : void 0;
|
|
4843
|
+
const selectedIdx = selections.get(q.index);
|
|
4844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-dq-q", children: [
|
|
4845
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-dq-qstem", children: q.stem }),
|
|
4846
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-dq-opts", children: q.options.map((opt, optIdx) => {
|
|
4847
|
+
let optCls = "ss-w-dq-qopt";
|
|
4848
|
+
if (qResult) {
|
|
4849
|
+
if (optIdx === qResult.correctOptionIndex) {
|
|
4850
|
+
optCls += " ss-w-dq-qopt--correct";
|
|
4851
|
+
} else if (optIdx === selectedIdx && !qResult.isCorrect) {
|
|
4852
|
+
optCls += " ss-w-dq-qopt--wrong";
|
|
4853
|
+
}
|
|
4854
|
+
} else if (optIdx === selectedIdx) {
|
|
4855
|
+
optCls += " ss-w-dq-qopt--selected";
|
|
4856
|
+
}
|
|
4857
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
4858
|
+
"button",
|
|
4859
|
+
{
|
|
4860
|
+
type: "button",
|
|
4861
|
+
className: optCls,
|
|
4862
|
+
disabled: isRevealed || submitting,
|
|
4863
|
+
onClick: () => handleSelect(q.index, optIdx),
|
|
4864
|
+
children: [
|
|
4865
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "ss-w-dq-qopt-letter", children: String.fromCharCode(65 + optIdx) }),
|
|
4866
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "ss-w-dq-qopt-text", children: opt })
|
|
4867
|
+
]
|
|
4868
|
+
},
|
|
4869
|
+
optIdx
|
|
4870
|
+
);
|
|
4871
|
+
}) }),
|
|
4872
|
+
qResult?.revealText && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: `ss-w-dq-qwhy ss-w-dq-qwhy--${qResult.isCorrect ? "correct" : "wrong"}`, children: qResult.revealText })
|
|
4873
|
+
] }, q.index);
|
|
4874
|
+
}) }),
|
|
4875
|
+
!isRevealed && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
4876
|
+
"button",
|
|
4877
|
+
{
|
|
4878
|
+
type: "button",
|
|
4879
|
+
className: "ss-w-dq-submit",
|
|
4880
|
+
disabled: !allAnswered || submitting,
|
|
4881
|
+
onClick: handleSubmit,
|
|
4882
|
+
"aria-label": "Submit answers",
|
|
4883
|
+
children: submitting ? "Submitting\u2026" : "Submit"
|
|
4884
|
+
}
|
|
4885
|
+
)
|
|
4886
|
+
] })
|
|
4887
|
+
] });
|
|
4888
|
+
}
|
|
4889
|
+
|
|
4890
|
+
// src/components/games/MatchdayPredictorGame.tsx
|
|
4891
|
+
var import_react33 = require("react");
|
|
4892
|
+
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
4893
|
+
function parseClientState7(json) {
|
|
4894
|
+
if (!json) return null;
|
|
4895
|
+
try {
|
|
4896
|
+
return JSON.parse(json);
|
|
4897
|
+
} catch {
|
|
4898
|
+
return null;
|
|
4899
|
+
}
|
|
4900
|
+
}
|
|
4901
|
+
function isLocked(kickoffUtc) {
|
|
4902
|
+
try {
|
|
4903
|
+
return new Date(kickoffUtc).getTime() <= Date.now();
|
|
4904
|
+
} catch {
|
|
4905
|
+
return true;
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
function MatchdayPredictorGame({
|
|
4909
|
+
config,
|
|
4910
|
+
result,
|
|
4911
|
+
submitting,
|
|
4912
|
+
onSubmit
|
|
4913
|
+
}) {
|
|
4914
|
+
const [homeScore, setHomeScore] = (0, import_react33.useState)(0);
|
|
4915
|
+
const [awayScore, setAwayScore] = (0, import_react33.useState)(0);
|
|
4916
|
+
const [firstScorerPlayerId, setFirstScorerPlayerId] = (0, import_react33.useState)(null);
|
|
4917
|
+
const clientState = parseClientState7(result?.clientStateJson);
|
|
4918
|
+
const alreadyPlayed = result?.alreadyPlayed === true;
|
|
4919
|
+
if (alreadyPlayed && clientState) {
|
|
4920
|
+
if (!clientState.graded) {
|
|
4921
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: [
|
|
4922
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-live", children: [
|
|
4923
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-live-score", children: [
|
|
4924
|
+
clientState.predictedHomeScore,
|
|
4925
|
+
" \u2013 ",
|
|
4926
|
+
clientState.predictedAwayScore
|
|
4927
|
+
] }),
|
|
4928
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-live-label", children: "Locked in \u2014 awaiting result" })
|
|
4929
|
+
] }),
|
|
4930
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-fun", children: "For fun \u2014 not in the leaderboard" })
|
|
4931
|
+
] });
|
|
4932
|
+
}
|
|
4933
|
+
const r = clientState.result;
|
|
4934
|
+
const actualScore = `${r.homeScore} \u2013 ${r.awayScore}`;
|
|
4935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: [
|
|
4936
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-live", children: [
|
|
4937
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-live-score", children: actualScore }),
|
|
4938
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-live-label", children: "Full-time result" }),
|
|
4939
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-live-outcome", children: [
|
|
4940
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: `ss-w-mp-live-row${clientState.exactScoreCorrect ? " ss-w-mp-live-row--correct" : ""}`, children: [
|
|
4941
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-live-row-key", children: "Exact score" }),
|
|
4942
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-live-row-val", children: clientState.exactScoreCorrect ? "\u2713" : "\u2717" })
|
|
4943
|
+
] }),
|
|
4944
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: `ss-w-mp-live-row${clientState.outcomeCorrect ? " ss-w-mp-live-row--correct" : ""}`, children: [
|
|
4945
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-live-row-key", children: "Result (W/D/L)" }),
|
|
4946
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-live-row-val", children: clientState.outcomeCorrect ? "\u2713" : "\u2717" })
|
|
4947
|
+
] }),
|
|
4948
|
+
!clientState.firstScorerVoid && /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: `ss-w-mp-live-row${clientState.firstScorerCorrect ? " ss-w-mp-live-row--correct" : ""}`, children: [
|
|
4949
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-live-row-key", children: "First scorer" }),
|
|
4950
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "ss-w-mp-live-row-val", children: [
|
|
4951
|
+
clientState.firstScorerCorrect ? "\u2713" : "\u2717",
|
|
4952
|
+
r.firstScorerName ? ` ${r.firstScorerName}` : ""
|
|
4953
|
+
] })
|
|
4954
|
+
] })
|
|
4955
|
+
] })
|
|
4956
|
+
] }),
|
|
4957
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-fun", children: "For fun \u2014 not in the leaderboard" })
|
|
4958
|
+
] });
|
|
4959
|
+
}
|
|
4960
|
+
if (!config) {
|
|
4961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
4962
|
+
}
|
|
4963
|
+
const locked = isLocked(config.kickoffUtc);
|
|
4964
|
+
const disabled = locked || submitting;
|
|
4965
|
+
function handleSubmit() {
|
|
4966
|
+
if (disabled || !config) return;
|
|
4967
|
+
onSubmit(
|
|
4968
|
+
JSON.stringify({
|
|
4969
|
+
homeScore,
|
|
4970
|
+
awayScore,
|
|
4971
|
+
...firstScorerPlayerId !== null ? { firstScorerPlayerId } : {}
|
|
4972
|
+
})
|
|
4973
|
+
);
|
|
4974
|
+
}
|
|
4975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: [
|
|
4976
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-pred-score", children: [
|
|
4977
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-team", children: [
|
|
4978
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-team-name", children: config.homeTeam.name }),
|
|
4979
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-stepper", children: [
|
|
4980
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
4981
|
+
"button",
|
|
4982
|
+
{
|
|
4983
|
+
type: "button",
|
|
4984
|
+
className: "ss-w-mp-stepper-btn",
|
|
4985
|
+
"aria-label": "-",
|
|
4986
|
+
disabled: disabled || homeScore <= 0,
|
|
4987
|
+
onClick: () => setHomeScore((s) => Math.max(0, s - 1)),
|
|
4988
|
+
children: "\u2212"
|
|
4989
|
+
}
|
|
4990
|
+
),
|
|
4991
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-stepper-val", children: homeScore }),
|
|
4992
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
4993
|
+
"button",
|
|
4994
|
+
{
|
|
4995
|
+
type: "button",
|
|
4996
|
+
className: "ss-w-mp-stepper-btn",
|
|
4997
|
+
"aria-label": "+",
|
|
4998
|
+
disabled,
|
|
4999
|
+
onClick: () => setHomeScore((s) => s + 1),
|
|
5000
|
+
children: "+"
|
|
5001
|
+
}
|
|
5002
|
+
)
|
|
5003
|
+
] })
|
|
5004
|
+
] }),
|
|
5005
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-sep", children: "\u2013" }),
|
|
5006
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-team", children: [
|
|
5007
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-team-name", children: config.awayTeam.name }),
|
|
5008
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-stepper", children: [
|
|
5009
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
5010
|
+
"button",
|
|
5011
|
+
{
|
|
5012
|
+
type: "button",
|
|
5013
|
+
className: "ss-w-mp-stepper-btn",
|
|
5014
|
+
"aria-label": "-",
|
|
5015
|
+
disabled: disabled || awayScore <= 0,
|
|
5016
|
+
onClick: () => setAwayScore((s) => Math.max(0, s - 1)),
|
|
5017
|
+
children: "\u2212"
|
|
5018
|
+
}
|
|
5019
|
+
),
|
|
5020
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "ss-w-mp-stepper-val", children: awayScore }),
|
|
5021
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
5022
|
+
"button",
|
|
5023
|
+
{
|
|
5024
|
+
type: "button",
|
|
5025
|
+
className: "ss-w-mp-stepper-btn",
|
|
5026
|
+
"aria-label": "+",
|
|
5027
|
+
disabled,
|
|
5028
|
+
onClick: () => setAwayScore((s) => s + 1),
|
|
5029
|
+
children: "+"
|
|
5030
|
+
}
|
|
5031
|
+
)
|
|
5032
|
+
] })
|
|
5033
|
+
] })
|
|
5034
|
+
] }),
|
|
5035
|
+
config.scorerPool.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "ss-w-mp-scorer", children: [
|
|
5036
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-scorer-label", children: "First scorer (optional)" }),
|
|
5037
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-scorer-list", children: config.scorerPool.map((p) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
5038
|
+
"button",
|
|
5039
|
+
{
|
|
5040
|
+
type: "button",
|
|
5041
|
+
className: `ss-w-mp-scorer-opt${firstScorerPlayerId === p.playerId ? " ss-w-mp-scorer-opt--selected" : ""}`,
|
|
5042
|
+
disabled,
|
|
5043
|
+
onClick: () => setFirstScorerPlayerId((id) => id === p.playerId ? null : p.playerId),
|
|
5044
|
+
children: p.playerName
|
|
5045
|
+
},
|
|
5046
|
+
p.playerId
|
|
5047
|
+
)) })
|
|
5048
|
+
] }),
|
|
5049
|
+
locked && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-live-label", children: "Submissions are now closed" }),
|
|
5050
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
5051
|
+
"button",
|
|
5052
|
+
{
|
|
5053
|
+
type: "button",
|
|
5054
|
+
className: "ss-w-mp-savebtn",
|
|
5055
|
+
disabled,
|
|
5056
|
+
onClick: handleSubmit,
|
|
5057
|
+
"aria-label": "Save prediction",
|
|
5058
|
+
children: submitting ? "Saving\u2026" : "Save prediction"
|
|
5059
|
+
}
|
|
5060
|
+
),
|
|
5061
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "ss-w-mp-fun", children: "For fun \u2014 not in the leaderboard" })
|
|
5062
|
+
] });
|
|
5063
|
+
}
|
|
5064
|
+
|
|
5065
|
+
// src/components/games/StartingXiGame.tsx
|
|
5066
|
+
var import_react34 = require("react");
|
|
5067
|
+
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
5068
|
+
function parseClientState8(json) {
|
|
5069
|
+
if (!json) return null;
|
|
5070
|
+
try {
|
|
5071
|
+
return JSON.parse(json);
|
|
5072
|
+
} catch {
|
|
5073
|
+
return null;
|
|
5074
|
+
}
|
|
5075
|
+
}
|
|
5076
|
+
function parseFormationRows(formation) {
|
|
5077
|
+
const parts = formation.split("-").map(Number).filter((n) => n > 0);
|
|
5078
|
+
if (parts.length === 0) return [1, 4, 3, 3];
|
|
5079
|
+
return [1, ...parts];
|
|
5080
|
+
}
|
|
5081
|
+
function StartingXiGame({
|
|
5082
|
+
config,
|
|
5083
|
+
result,
|
|
5084
|
+
submitting,
|
|
5085
|
+
onSubmit
|
|
5086
|
+
}) {
|
|
5087
|
+
const [picked, setPicked] = (0, import_react34.useState)([]);
|
|
5088
|
+
const clientState = parseClientState8(result?.clientStateJson);
|
|
5089
|
+
const alreadyPlayed = result?.alreadyPlayed === true;
|
|
5090
|
+
if (alreadyPlayed) {
|
|
5091
|
+
if (!clientState) {
|
|
5092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-status", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-status-label", children: "This game has been voided" }) }) });
|
|
5093
|
+
}
|
|
5094
|
+
if (clientState.status === "pending") {
|
|
5095
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-status", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ss-w-sxi-status-label", children: [
|
|
5096
|
+
"Prediction locked in (",
|
|
5097
|
+
clientState.predictedCount,
|
|
5098
|
+
" players) \u2014 awaiting result"
|
|
5099
|
+
] }) }) });
|
|
5100
|
+
}
|
|
5101
|
+
if (clientState.status === "graded") {
|
|
5102
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ss-w-sxi-status ss-w-sxi-status--graded", children: [
|
|
5103
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-status-score", children: clientState.score }),
|
|
5104
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ss-w-sxi-status-label", children: [
|
|
5105
|
+
clientState.correctCount,
|
|
5106
|
+
" correct starters"
|
|
5107
|
+
] })
|
|
5108
|
+
] }) });
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
5111
|
+
if (!config) {
|
|
5112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
5113
|
+
}
|
|
5114
|
+
const formationRows = parseFormationRows(config.formation);
|
|
5115
|
+
const pickedSet = new Set(picked);
|
|
5116
|
+
const canSubmit = picked.length === 11 && !submitting;
|
|
5117
|
+
function togglePlayer(playerId) {
|
|
5118
|
+
if (submitting) return;
|
|
5119
|
+
setPicked((prev) => {
|
|
5120
|
+
if (prev.includes(playerId)) {
|
|
5121
|
+
return prev.filter((id) => id !== playerId);
|
|
5122
|
+
}
|
|
5123
|
+
if (prev.length >= 11) return prev;
|
|
5124
|
+
return [...prev, playerId];
|
|
5125
|
+
});
|
|
5126
|
+
}
|
|
5127
|
+
function handleSubmit() {
|
|
5128
|
+
if (!canSubmit) return;
|
|
5129
|
+
onSubmit(JSON.stringify({ predictedPlayerIds: picked }));
|
|
5130
|
+
}
|
|
5131
|
+
let slotIndex = 0;
|
|
5132
|
+
const pitchRows = formationRows.map((count, rowIdx) => {
|
|
5133
|
+
const rowSlots = picked.slice(slotIndex, slotIndex + count);
|
|
5134
|
+
slotIndex += count;
|
|
5135
|
+
return { rowIdx, count, rowSlots };
|
|
5136
|
+
});
|
|
5137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: [
|
|
5138
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-formation", children: config.formation }),
|
|
5139
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-pitch", children: pitchRows.map(({ rowIdx, count, rowSlots }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-pitch-row", children: Array.from({ length: count }).map((_, i) => {
|
|
5140
|
+
const playerId = rowSlots[i];
|
|
5141
|
+
const player = playerId != null ? config.squadSheet.find((p) => p.playerId === playerId) : void 0;
|
|
5142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
5143
|
+
"div",
|
|
5144
|
+
{
|
|
5145
|
+
className: `ss-w-sxi-pslot${player ? " ss-w-sxi-pslot--filled" : ""}`,
|
|
5146
|
+
onClick: () => {
|
|
5147
|
+
if (player) togglePlayer(player.playerId);
|
|
5148
|
+
},
|
|
5149
|
+
onKeyDown: (e) => {
|
|
5150
|
+
if (e.key === "Enter" && player) togglePlayer(player.playerId);
|
|
5151
|
+
},
|
|
5152
|
+
tabIndex: player ? 0 : -1,
|
|
5153
|
+
role: player ? "button" : void 0,
|
|
5154
|
+
"aria-label": player ? `Remove ${player.playerName ?? ""}` : void 0,
|
|
5155
|
+
children: [
|
|
5156
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-pslot-num", children: player?.jerseyNumber ?? (rowIdx === 0 ? "GK" : "?") }),
|
|
5157
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-pslot-name", children: player?.playerName ?? "" })
|
|
5158
|
+
]
|
|
5159
|
+
},
|
|
5160
|
+
i
|
|
5161
|
+
);
|
|
5162
|
+
}) }, rowIdx)) }),
|
|
5163
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "ss-w-sxi-squad", children: config.squadSheet.map((p) => {
|
|
5164
|
+
const isPicked = pickedSet.has(p.playerId);
|
|
5165
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
5166
|
+
"div",
|
|
5167
|
+
{
|
|
5168
|
+
className: `ss-w-sxi-squad-row${isPicked ? " ss-w-sxi-squad-row--picked" : ""}`,
|
|
5169
|
+
onClick: () => togglePlayer(p.playerId),
|
|
5170
|
+
onKeyDown: (e) => {
|
|
5171
|
+
if (e.key === "Enter") togglePlayer(p.playerId);
|
|
5172
|
+
},
|
|
5173
|
+
tabIndex: 0,
|
|
5174
|
+
role: "button",
|
|
5175
|
+
"aria-pressed": isPicked,
|
|
5176
|
+
children: [
|
|
5177
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ss-w-sxi-squad-name", children: p.playerName }),
|
|
5178
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "ss-w-sxi-squad-pos", children: p.positionName })
|
|
5179
|
+
]
|
|
5180
|
+
},
|
|
5181
|
+
p.playerId
|
|
5182
|
+
);
|
|
5183
|
+
}) }),
|
|
5184
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
5185
|
+
"button",
|
|
5186
|
+
{
|
|
5187
|
+
type: "button",
|
|
5188
|
+
className: "ss-w-sxi-savebtn",
|
|
5189
|
+
disabled: !canSubmit,
|
|
5190
|
+
onClick: handleSubmit,
|
|
5191
|
+
"aria-label": "Predict XI",
|
|
5192
|
+
children: submitting ? "Submitting\u2026" : `Predict XI (${picked.length}/11)`
|
|
5193
|
+
}
|
|
5194
|
+
)
|
|
5195
|
+
] });
|
|
5196
|
+
}
|
|
5197
|
+
|
|
5198
|
+
// src/components/games/StatLadderGame.tsx
|
|
5199
|
+
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
5200
|
+
function parseClientState9(json) {
|
|
5201
|
+
if (!json) return null;
|
|
5202
|
+
try {
|
|
5203
|
+
return JSON.parse(json);
|
|
5204
|
+
} catch {
|
|
5205
|
+
return null;
|
|
5206
|
+
}
|
|
5207
|
+
}
|
|
5208
|
+
function StatLadderGame({
|
|
5209
|
+
config,
|
|
5210
|
+
result,
|
|
5211
|
+
submitting,
|
|
5212
|
+
onSubmit
|
|
5213
|
+
}) {
|
|
5214
|
+
const clientState = parseClientState9(result?.clientStateJson);
|
|
5215
|
+
const revealed = clientState != null;
|
|
5216
|
+
if (!config) {
|
|
5217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "ss-w-sl", "data-testid": "game-screen-stat-ladder", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
5218
|
+
}
|
|
5219
|
+
const mysteryName = revealed ? clientState.revealedRank2.playerName : null;
|
|
5220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "ss-w-sl", "data-testid": "game-screen-stat-ladder", children: [
|
|
5221
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "ss-w-sl-title", children: config.statLabel }),
|
|
5222
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "ss-w-sl-ladder", children: config.ladder.map((rung) => {
|
|
5223
|
+
const isMystery = rung.rank === 2;
|
|
5224
|
+
let rowCls = "ss-w-sl-lrow";
|
|
5225
|
+
if (isMystery) rowCls += " ss-w-sl-mystery";
|
|
5226
|
+
if (isMystery && revealed) {
|
|
5227
|
+
rowCls = rowCls.replace(" ss-w-sl-mystery", "");
|
|
5228
|
+
rowCls += clientState.isCorrect ? " ss-w-sl-lrow--correct" : " ss-w-sl-lrow--wrong";
|
|
5229
|
+
}
|
|
5230
|
+
const displayName = isMystery ? revealed ? mysteryName : "?" : rung.playerName ?? "?";
|
|
5231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: rowCls, children: [
|
|
5232
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "ss-w-sl-lrow-rank", children: [
|
|
5233
|
+
"#",
|
|
5234
|
+
rung.rank
|
|
5235
|
+
] }),
|
|
5236
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "ss-w-sl-lrow-name", children: displayName }),
|
|
5237
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "ss-w-sl-lrow-stat", children: rung.statValue })
|
|
5238
|
+
] }, rung.rank);
|
|
5239
|
+
}) }),
|
|
5240
|
+
revealed && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: `ss-w-sl-reveal ss-w-sl-reveal--${clientState.isCorrect ? "correct" : "wrong"}`, children: clientState.isCorrect ? "Correct!" : `Wrong \u2014 it was ${clientState.revealedRank2.playerName}` }),
|
|
5241
|
+
!revealed && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "ss-w-sl-picker", children: config.playerPool.map((p) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
5242
|
+
"button",
|
|
5243
|
+
{
|
|
5244
|
+
type: "button",
|
|
5245
|
+
className: "ss-w-sl-picker-opt",
|
|
5246
|
+
disabled: submitting,
|
|
5247
|
+
"aria-label": p.playerName,
|
|
5248
|
+
onClick: () => onSubmit(JSON.stringify({ guessedPlayerId: p.playerId })),
|
|
5249
|
+
children: p.playerName
|
|
5250
|
+
},
|
|
5251
|
+
p.playerId
|
|
5252
|
+
)) })
|
|
5253
|
+
] });
|
|
5254
|
+
}
|
|
5255
|
+
|
|
5256
|
+
// src/components/games/FanMotmGame.tsx
|
|
5257
|
+
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
5258
|
+
function parseClientState10(json) {
|
|
5259
|
+
if (!json) return null;
|
|
5260
|
+
try {
|
|
5261
|
+
return JSON.parse(json);
|
|
5262
|
+
} catch {
|
|
5263
|
+
return null;
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5266
|
+
function FanMotmGame({
|
|
5267
|
+
config,
|
|
5268
|
+
result,
|
|
5269
|
+
submitting,
|
|
5270
|
+
onSubmit
|
|
5271
|
+
}) {
|
|
5272
|
+
const clientState = parseClientState10(result?.clientStateJson);
|
|
5273
|
+
const alreadyVoted = result?.alreadyPlayed === true;
|
|
5274
|
+
if (!config) {
|
|
5275
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "ss-w-motm", "data-testid": "game-screen-fan-motm", children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
5276
|
+
}
|
|
5277
|
+
const pickedId = clientState?.pickedPlayerId ?? null;
|
|
5278
|
+
function handleVote(candidateId) {
|
|
5279
|
+
if (alreadyVoted || submitting) return;
|
|
5280
|
+
onSubmit(JSON.stringify({ pickedPlayerId: candidateId }));
|
|
5281
|
+
}
|
|
5282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "ss-w-motm", "data-testid": "game-screen-fan-motm", children: [
|
|
5283
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "ss-w-motm-title", children: "Man of the Match \u2014 your vote" }),
|
|
5284
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "ss-w-motm-votes", children: config.candidates.map((c) => {
|
|
5285
|
+
const isVoted = alreadyVoted && pickedId === c.playerId;
|
|
5286
|
+
const rowCls = `ss-w-motm-vrow${isVoted ? " ss-w-motm-vrow--voted" : ""}${alreadyVoted ? " ss-w-motm-vrow--result" : ""}`;
|
|
5287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
5288
|
+
"button",
|
|
5289
|
+
{
|
|
5290
|
+
type: "button",
|
|
5291
|
+
className: rowCls,
|
|
5292
|
+
"data-testid": `motm-candidate-${c.playerId}`,
|
|
5293
|
+
disabled: alreadyVoted || submitting,
|
|
5294
|
+
onClick: () => handleVote(c.playerId),
|
|
5295
|
+
children: [
|
|
5296
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "ss-w-motm-vfill", style: { width: isVoted ? "100%" : "0%" } }),
|
|
5297
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "ss-w-motm-vrow-name", children: c.playerName })
|
|
5298
|
+
]
|
|
5299
|
+
},
|
|
5300
|
+
c.playerId
|
|
5301
|
+
);
|
|
5302
|
+
}) }),
|
|
5303
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "ss-w-motm-fun", children: "For fun \u2014 unranked community vote" })
|
|
5304
|
+
] });
|
|
5305
|
+
}
|
|
5306
|
+
|
|
5307
|
+
// src/components/GameScreenHost.tsx
|
|
5308
|
+
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
5309
|
+
var FIXTURE_GAME_IDS = /* @__PURE__ */ new Set([
|
|
5310
|
+
"matchday-predictor",
|
|
5311
|
+
"starting-xi",
|
|
5312
|
+
"stat-ladder",
|
|
5313
|
+
"fan-motm"
|
|
5314
|
+
]);
|
|
5315
|
+
var PENDING_POLL_INTERVAL_MS = 3e4;
|
|
5316
|
+
function safeParseConfig(json) {
|
|
5317
|
+
if (!json) return null;
|
|
5318
|
+
try {
|
|
5319
|
+
return JSON.parse(json);
|
|
5320
|
+
} catch {
|
|
5321
|
+
return null;
|
|
4132
5322
|
}
|
|
4133
5323
|
}
|
|
4134
5324
|
function GameScreenHost({
|
|
4135
5325
|
selected,
|
|
4136
5326
|
onBack,
|
|
5327
|
+
conversation,
|
|
4137
5328
|
ui
|
|
4138
5329
|
}) {
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
5330
|
+
const { gameId, fixtureId, gameDay = "" } = selected;
|
|
5331
|
+
const [configJson, setConfigJson] = (0, import_react35.useState)(null);
|
|
5332
|
+
(0, import_react35.useEffect)(() => {
|
|
5333
|
+
setConfigJson(null);
|
|
5334
|
+
if (!conversation) return;
|
|
5335
|
+
let cancelled = false;
|
|
5336
|
+
void (async () => {
|
|
5337
|
+
try {
|
|
5338
|
+
const payload = await conversation.getGameConfig(gameId, fixtureId, gameDay || void 0);
|
|
5339
|
+
if (!cancelled && payload?.configJson) {
|
|
5340
|
+
setConfigJson(payload.configJson);
|
|
5341
|
+
}
|
|
5342
|
+
} catch {
|
|
5343
|
+
}
|
|
5344
|
+
})();
|
|
5345
|
+
return () => {
|
|
5346
|
+
cancelled = true;
|
|
5347
|
+
};
|
|
5348
|
+
}, [conversation, gameId, fixtureId, gameDay]);
|
|
5349
|
+
const { result, submitting, submit, hydrate, rawStatus } = useGamePlay(conversation, {
|
|
5350
|
+
gameId,
|
|
5351
|
+
gameDay,
|
|
5352
|
+
fixtureId: fixtureId || void 0
|
|
5353
|
+
});
|
|
5354
|
+
(0, import_react35.useEffect)(() => {
|
|
5355
|
+
if (conversation) hydrate();
|
|
5356
|
+
}, [conversation, gameId]);
|
|
5357
|
+
const hydrateRef = (0, import_react35.useRef)(hydrate);
|
|
5358
|
+
hydrateRef.current = hydrate;
|
|
5359
|
+
(0, import_react35.useEffect)(() => {
|
|
5360
|
+
if (!FIXTURE_GAME_IDS.has(gameId)) return;
|
|
5361
|
+
if (rawStatus !== "pending") return;
|
|
5362
|
+
const timerId = setInterval(() => {
|
|
5363
|
+
hydrateRef.current();
|
|
5364
|
+
}, PENDING_POLL_INTERVAL_MS);
|
|
5365
|
+
return () => clearInterval(timerId);
|
|
5366
|
+
}, [gameId, rawStatus]);
|
|
5367
|
+
const sharedProps = {
|
|
5368
|
+
result,
|
|
5369
|
+
submitting,
|
|
5370
|
+
onSubmit: submit,
|
|
5371
|
+
ui
|
|
5372
|
+
};
|
|
5373
|
+
function renderScreen() {
|
|
5374
|
+
switch (gameId) {
|
|
5375
|
+
case "mystery-tiger":
|
|
5376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5377
|
+
MysteryTigerGame,
|
|
5378
|
+
{
|
|
5379
|
+
...sharedProps,
|
|
5380
|
+
config: safeParseConfig(configJson)
|
|
5381
|
+
}
|
|
5382
|
+
);
|
|
5383
|
+
case "higher-or-lower":
|
|
5384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5385
|
+
HigherOrLowerGame,
|
|
5386
|
+
{
|
|
5387
|
+
...sharedProps,
|
|
5388
|
+
config: safeParseConfig(configJson)
|
|
5389
|
+
}
|
|
5390
|
+
);
|
|
5391
|
+
case "career-path":
|
|
5392
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5393
|
+
CareerPathGame,
|
|
5394
|
+
{
|
|
5395
|
+
...sharedProps,
|
|
5396
|
+
config: safeParseConfig(configJson)
|
|
5397
|
+
}
|
|
5398
|
+
);
|
|
5399
|
+
case "beat-the-grid":
|
|
5400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5401
|
+
BeatTheGridGame,
|
|
5402
|
+
{
|
|
5403
|
+
...sharedProps,
|
|
5404
|
+
config: safeParseConfig(configJson),
|
|
5405
|
+
playerPool: []
|
|
5406
|
+
}
|
|
5407
|
+
);
|
|
5408
|
+
case "guess-the-xi":
|
|
5409
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5410
|
+
GuessTheXiGame,
|
|
5411
|
+
{
|
|
5412
|
+
...sharedProps,
|
|
5413
|
+
config: safeParseConfig(configJson)
|
|
5414
|
+
}
|
|
5415
|
+
);
|
|
5416
|
+
case "daily-quiz":
|
|
5417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5418
|
+
DailyQuizGame,
|
|
5419
|
+
{
|
|
5420
|
+
...sharedProps,
|
|
5421
|
+
config: safeParseConfig(configJson)
|
|
5422
|
+
}
|
|
5423
|
+
);
|
|
5424
|
+
case "matchday-predictor":
|
|
5425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5426
|
+
MatchdayPredictorGame,
|
|
5427
|
+
{
|
|
5428
|
+
...sharedProps,
|
|
5429
|
+
config: safeParseConfig(configJson)
|
|
5430
|
+
}
|
|
5431
|
+
);
|
|
5432
|
+
case "starting-xi":
|
|
5433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5434
|
+
StartingXiGame,
|
|
5435
|
+
{
|
|
5436
|
+
...sharedProps,
|
|
5437
|
+
config: safeParseConfig(configJson)
|
|
5438
|
+
}
|
|
5439
|
+
);
|
|
5440
|
+
case "stat-ladder":
|
|
5441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5442
|
+
StatLadderGame,
|
|
5443
|
+
{
|
|
5444
|
+
...sharedProps,
|
|
5445
|
+
config: safeParseConfig(configJson)
|
|
5446
|
+
}
|
|
5447
|
+
);
|
|
5448
|
+
case "fan-motm":
|
|
5449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
5450
|
+
FanMotmGame,
|
|
5451
|
+
{
|
|
5452
|
+
...sharedProps,
|
|
5453
|
+
config: safeParseConfig(configJson)
|
|
5454
|
+
}
|
|
5455
|
+
);
|
|
5456
|
+
default:
|
|
5457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "ss-w-gscreen-body", "data-testid": `game-screen-${gameId}`, children: gameId });
|
|
5458
|
+
}
|
|
5459
|
+
}
|
|
5460
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "ss-w-gscreen", children: [
|
|
5461
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("button", { type: "button", className: "ss-w-gscreen-back", onClick: onBack, children: [
|
|
5462
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "ss-w-gscreen-back-arrow", "aria-hidden": "true", children: "\u2039" }),
|
|
4142
5463
|
ui.back
|
|
4143
5464
|
] }),
|
|
4144
|
-
|
|
5465
|
+
renderScreen()
|
|
4145
5466
|
] });
|
|
4146
5467
|
}
|
|
4147
5468
|
|
|
4148
5469
|
// src/components/GamesPanel.tsx
|
|
4149
|
-
var
|
|
5470
|
+
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
4150
5471
|
function GamesPanel({
|
|
4151
5472
|
loggedIn,
|
|
4152
5473
|
games,
|
|
4153
5474
|
ui,
|
|
4154
5475
|
conversation
|
|
4155
5476
|
}) {
|
|
4156
|
-
const [selected, setSelected] = (0,
|
|
4157
|
-
if (!loggedIn) return /* @__PURE__ */ (0,
|
|
5477
|
+
const [selected, setSelected] = (0, import_react36.useState)(null);
|
|
5478
|
+
if (!loggedIn) return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(GamesLoginWall, { ui });
|
|
4158
5479
|
if (selected !== null) {
|
|
4159
|
-
return /* @__PURE__ */ (0,
|
|
5480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
4160
5481
|
GameScreenHost,
|
|
4161
5482
|
{
|
|
4162
5483
|
selected,
|
|
4163
5484
|
onBack: () => setSelected(null),
|
|
4164
|
-
conversation,
|
|
5485
|
+
conversation: conversation ?? null,
|
|
4165
5486
|
ui
|
|
4166
5487
|
}
|
|
4167
5488
|
) });
|
|
4168
5489
|
}
|
|
4169
|
-
return /* @__PURE__ */ (0,
|
|
5490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "ss-w-mon-list", "data-testid": "games-hub", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
4170
5491
|
GamesHub,
|
|
4171
5492
|
{
|
|
4172
5493
|
games,
|
|
4173
|
-
onOpen: (g) => setSelected({ gameId: g.gameId, fixtureId: g.fixtureId }),
|
|
5494
|
+
onOpen: (g) => setSelected({ gameId: g.gameId, fixtureId: g.fixtureId, gameDay: g.gameDay }),
|
|
4174
5495
|
ui
|
|
4175
5496
|
}
|
|
4176
5497
|
) });
|
|
4177
5498
|
}
|
|
4178
5499
|
|
|
4179
5500
|
// src/components/Leaderboard.tsx
|
|
4180
|
-
var
|
|
5501
|
+
var import_react37 = require("react");
|
|
4181
5502
|
|
|
4182
5503
|
// src/components/LeaderboardRow.tsx
|
|
4183
|
-
var
|
|
5504
|
+
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
4184
5505
|
function formatPoints(n) {
|
|
4185
5506
|
return n.toLocaleString("en");
|
|
4186
5507
|
}
|
|
@@ -4189,14 +5510,14 @@ function LeaderboardWeeklyRow({
|
|
|
4189
5510
|
isMe
|
|
4190
5511
|
}) {
|
|
4191
5512
|
const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? " ss-w-lb2-rank--top3" : ""}`;
|
|
4192
|
-
return /* @__PURE__ */ (0,
|
|
4193
|
-
/* @__PURE__ */ (0,
|
|
5513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: `ss-w-lb2-row${isMe ? " ss-w-lb2-row--you" : ""}`, children: [
|
|
5514
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: rankClass, children: [
|
|
4194
5515
|
"#",
|
|
4195
5516
|
row.rank
|
|
4196
5517
|
] }),
|
|
4197
|
-
/* @__PURE__ */ (0,
|
|
4198
|
-
/* @__PURE__ */ (0,
|
|
4199
|
-
row.currentStreak > 0 && /* @__PURE__ */ (0,
|
|
5518
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "ss-w-lb2-handle", children: row.handle }),
|
|
5519
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "ss-w-lb2-points", children: formatPoints(row.points) }),
|
|
5520
|
+
row.currentStreak > 0 && /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "ss-w-lb2-streak", children: [
|
|
4200
5521
|
"\u{1F525} ",
|
|
4201
5522
|
row.currentStreak
|
|
4202
5523
|
] })
|
|
@@ -4207,28 +5528,28 @@ function LeaderboardAllTimeRow({
|
|
|
4207
5528
|
isMe
|
|
4208
5529
|
}) {
|
|
4209
5530
|
const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? " ss-w-lb2-rank--top3" : ""}`;
|
|
4210
|
-
return /* @__PURE__ */ (0,
|
|
4211
|
-
/* @__PURE__ */ (0,
|
|
5531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: `ss-w-lb2-row${isMe ? " ss-w-lb2-row--you" : ""}`, children: [
|
|
5532
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: rankClass, children: [
|
|
4212
5533
|
"#",
|
|
4213
5534
|
row.rank
|
|
4214
5535
|
] }),
|
|
4215
|
-
/* @__PURE__ */ (0,
|
|
4216
|
-
/* @__PURE__ */ (0,
|
|
5536
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "ss-w-lb2-handle", children: row.handle }),
|
|
5537
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "ss-w-lb2-points", children: formatPoints(row.allTimePoints) })
|
|
4217
5538
|
] });
|
|
4218
5539
|
}
|
|
4219
5540
|
|
|
4220
5541
|
// src/components/Leaderboard.tsx
|
|
4221
|
-
var
|
|
5542
|
+
var import_jsx_runtime68 = require("react/jsx-runtime");
|
|
4222
5543
|
function Leaderboard({
|
|
4223
5544
|
data,
|
|
4224
5545
|
ui
|
|
4225
5546
|
}) {
|
|
4226
|
-
const [segment, setSegment] = (0,
|
|
5547
|
+
const [segment, setSegment] = (0, import_react37.useState)("weekly");
|
|
4227
5548
|
const myRow = segment === "weekly" ? data.myWeeklyRow : data.myAllTimeRow;
|
|
4228
5549
|
const offBoard = myRow !== null && myRow !== void 0 && myRow.rank === -1;
|
|
4229
|
-
return /* @__PURE__ */ (0,
|
|
4230
|
-
/* @__PURE__ */ (0,
|
|
4231
|
-
/* @__PURE__ */ (0,
|
|
5550
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb2", children: [
|
|
5551
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-seg", children: [
|
|
5552
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
4232
5553
|
"button",
|
|
4233
5554
|
{
|
|
4234
5555
|
type: "button",
|
|
@@ -4238,7 +5559,7 @@ function Leaderboard({
|
|
|
4238
5559
|
children: ui.leaderboardThisWeek
|
|
4239
5560
|
}
|
|
4240
5561
|
),
|
|
4241
|
-
/* @__PURE__ */ (0,
|
|
5562
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
4242
5563
|
"button",
|
|
4243
5564
|
{
|
|
4244
5565
|
type: "button",
|
|
@@ -4249,14 +5570,14 @@ function Leaderboard({
|
|
|
4249
5570
|
}
|
|
4250
5571
|
)
|
|
4251
5572
|
] }),
|
|
4252
|
-
/* @__PURE__ */ (0,
|
|
5573
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb2-rows", children: segment === "weekly" ? data.weeklyTop.map((row) => /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
4253
5574
|
LeaderboardWeeklyRow,
|
|
4254
5575
|
{
|
|
4255
5576
|
row,
|
|
4256
5577
|
isMe: row.operatorUserId === data.myWeeklyRow?.operatorUserId
|
|
4257
5578
|
},
|
|
4258
5579
|
row.operatorUserId
|
|
4259
|
-
)) : data.allTimeTop.map((row) => /* @__PURE__ */ (0,
|
|
5580
|
+
)) : data.allTimeTop.map((row) => /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
4260
5581
|
LeaderboardAllTimeRow,
|
|
4261
5582
|
{
|
|
4262
5583
|
row,
|
|
@@ -4264,29 +5585,29 @@ function Leaderboard({
|
|
|
4264
5585
|
},
|
|
4265
5586
|
row.operatorUserId
|
|
4266
5587
|
)) }),
|
|
4267
|
-
/* @__PURE__ */ (0,
|
|
4268
|
-
myRow != null && (offBoard ? /* @__PURE__ */ (0,
|
|
4269
|
-
segment === "weekly" && data.myWeeklyRow && /* @__PURE__ */ (0,
|
|
4270
|
-
segment === "alltime" && data.myAllTimeRow && /* @__PURE__ */ (0,
|
|
5588
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-kitline", children: "\u{1F3BD}" }),
|
|
5589
|
+
myRow != null && (offBoard ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lbgap", children: ui.leaderboardOffBoard }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb2-rows", children: [
|
|
5590
|
+
segment === "weekly" && data.myWeeklyRow && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(LeaderboardWeeklyRow, { row: data.myWeeklyRow, isMe: true }),
|
|
5591
|
+
segment === "alltime" && data.myAllTimeRow && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(LeaderboardAllTimeRow, { row: data.myAllTimeRow, isMe: true })
|
|
4271
5592
|
] })),
|
|
4272
|
-
segment === "alltime" && data.myAllTimeRow && !offBoard && /* @__PURE__ */ (0,
|
|
5593
|
+
segment === "alltime" && data.myAllTimeRow && !offBoard && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb2-rows", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb2-row", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-lb2-handle", children: formatPoints(data.allTimeTop.reduce((s, r) => s + r.allTimePoints, 0)) }) }) })
|
|
4273
5594
|
] });
|
|
4274
5595
|
}
|
|
4275
5596
|
|
|
4276
5597
|
// src/components/LeaderboardPanel.tsx
|
|
4277
|
-
var
|
|
5598
|
+
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
4278
5599
|
function LeaderboardPanel({ loggedIn, data, ui }) {
|
|
4279
|
-
if (!loggedIn) return /* @__PURE__ */ (0,
|
|
4280
|
-
if (data === null) return /* @__PURE__ */ (0,
|
|
4281
|
-
return /* @__PURE__ */ (0,
|
|
5600
|
+
if (!loggedIn) return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(GamesLoginWall, { ui });
|
|
5601
|
+
if (data === null) return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-mon-list" });
|
|
5602
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Leaderboard, { data, ui }) });
|
|
4282
5603
|
}
|
|
4283
5604
|
|
|
4284
5605
|
// src/components/ChatPanel.tsx
|
|
4285
|
-
var
|
|
5606
|
+
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
4286
5607
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
4287
5608
|
function useIsModal() {
|
|
4288
|
-
const [modal, setModal] = (0,
|
|
4289
|
-
(0,
|
|
5609
|
+
const [modal, setModal] = (0, import_react38.useState)(false);
|
|
5610
|
+
(0, import_react38.useEffect)(() => {
|
|
4290
5611
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
4291
5612
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
4292
5613
|
const sync = () => setModal(mql.matches);
|
|
@@ -4296,10 +5617,10 @@ function useIsModal() {
|
|
|
4296
5617
|
}, []);
|
|
4297
5618
|
return modal;
|
|
4298
5619
|
}
|
|
4299
|
-
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn }) {
|
|
5620
|
+
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation }) {
|
|
4300
5621
|
const { state, close, stop, send, reset } = controller;
|
|
4301
5622
|
const isModal = useIsModal();
|
|
4302
|
-
(0,
|
|
5623
|
+
(0, import_react38.useEffect)(() => {
|
|
4303
5624
|
const onKey = (e) => {
|
|
4304
5625
|
if (e.key === "Escape") close();
|
|
4305
5626
|
};
|
|
@@ -4310,11 +5631,11 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
4310
5631
|
monitor?.setActiveTab("chat");
|
|
4311
5632
|
send(text);
|
|
4312
5633
|
};
|
|
4313
|
-
(0,
|
|
5634
|
+
(0, import_react38.useEffect)(() => {
|
|
4314
5635
|
if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
|
|
4315
5636
|
}, [monitor, state.isStreaming, state.messages.length]);
|
|
4316
|
-
return /* @__PURE__ */ (0,
|
|
4317
|
-
/* @__PURE__ */ (0,
|
|
5637
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
5638
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
|
|
4318
5639
|
ChatHeader,
|
|
4319
5640
|
{
|
|
4320
5641
|
onClose: close,
|
|
@@ -4327,7 +5648,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
4327
5648
|
moreOptionsLabel: ui.moreOptions
|
|
4328
5649
|
}
|
|
4329
5650
|
),
|
|
4330
|
-
monitor && /* @__PURE__ */ (0,
|
|
5651
|
+
monitor && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
|
|
4331
5652
|
TabBar,
|
|
4332
5653
|
{
|
|
4333
5654
|
monitor,
|
|
@@ -4339,19 +5660,19 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
4339
5660
|
gamesEnabled: gamesResult?.enabled ?? false
|
|
4340
5661
|
}
|
|
4341
5662
|
),
|
|
4342
|
-
/* @__PURE__ */ (0,
|
|
5663
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
|
|
4343
5664
|
"div",
|
|
4344
5665
|
{
|
|
4345
5666
|
style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
|
|
4346
|
-
children: /* @__PURE__ */ (0,
|
|
5667
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(MessageList, { controller, ui, slip, onDashboardTap, monitor })
|
|
4347
5668
|
}
|
|
4348
5669
|
),
|
|
4349
|
-
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0,
|
|
4350
|
-
monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0,
|
|
4351
|
-
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0,
|
|
4352
|
-
monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ (0,
|
|
4353
|
-
monitor && monitor.activeTab === "leaderboard" && leaderboardResult && /* @__PURE__ */ (0,
|
|
4354
|
-
/* @__PURE__ */ (0,
|
|
5670
|
+
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(TodayPanel, { discovery, ui, monitor }),
|
|
5671
|
+
monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(MatchesPanel, { monitor, ui, slip }),
|
|
5672
|
+
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(OddsPanel, { monitor, ui, slip }),
|
|
5673
|
+
monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(GamesPanel, { loggedIn: !!loggedIn, games: gamesResult.games, ui, conversation }),
|
|
5674
|
+
monitor && monitor.activeTab === "leaderboard" && leaderboardResult && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(LeaderboardPanel, { loggedIn: !!loggedIn, data: leaderboardResult.data, ui }),
|
|
5675
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
4355
5676
|
] });
|
|
4356
5677
|
}
|
|
4357
5678
|
|
|
@@ -5304,10 +6625,315 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
5304
6625
|
|
|
5305
6626
|
/* Off-board treatment: dashed pill indicating rank is outside top N */
|
|
5306
6627
|
.ss-w-lbgap { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 12px; font-size: 11.5px; color: var(--ss-w-faint); border: 1px dashed var(--ss-w-line); border-radius: 10px; }
|
|
6628
|
+
|
|
6629
|
+
/* ---- Mystery Tiger game screen (D3) ---- */
|
|
6630
|
+
.ss-w-gt { display: flex; flex-direction: column; gap: 10px; }
|
|
6631
|
+
/* Typeahead wrapper: relative so the dropdown can position under it */
|
|
6632
|
+
.ss-w-gtta { position: relative; }
|
|
6633
|
+
.ss-w-gtta-i { width: 100%; box-sizing: border-box; padding: 9px 12px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); color: var(--ss-w-ink); font: inherit; font-size: 13px; outline: none; transition: border-color .12s; }
|
|
6634
|
+
.ss-w-gtta-i:focus { border-color: var(--ss-w-accent); }
|
|
6635
|
+
.ss-w-gtta-i:disabled { opacity: .5; cursor: not-allowed; }
|
|
6636
|
+
.ss-w-gtta-drop { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 10; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 10px; max-height: 180px; overflow-y: auto; box-shadow: 0 4px 16px rgba(0,0,0,.12); }
|
|
6637
|
+
.ss-w-gtta-opt { padding: 9px 12px; font-size: 13px; cursor: pointer; color: var(--ss-w-ink); border-bottom: 1px solid var(--ss-w-line); }
|
|
6638
|
+
.ss-w-gtta-opt:last-child { border-bottom: none; }
|
|
6639
|
+
.ss-w-gtta-opt:hover { background: var(--ss-w-bubble); }
|
|
6640
|
+
/* Column header labels: one cell per attribute */
|
|
6641
|
+
.ss-w-gthdr { display: grid; grid-template-columns: 1fr repeat(5, 36px); gap: 4px; padding: 0 2px; }
|
|
6642
|
+
.ss-w-gthdr-c { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6643
|
+
.ss-w-gthdr-c--name { text-align: left; }
|
|
6644
|
+
/* Guess rows */
|
|
6645
|
+
.ss-w-gtrows { display: flex; flex-direction: column; gap: 4px; }
|
|
6646
|
+
.ss-w-gtrow { display: grid; grid-template-columns: 1fr repeat(5, 36px); gap: 4px; align-items: center; }
|
|
6647
|
+
.ss-w-gtrow-nm { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: 4px; }
|
|
6648
|
+
/* Verdict tiles */
|
|
6649
|
+
.ss-w-gtile { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 36px; border-radius: 8px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; gap: 1px; transition: transform .1s; }
|
|
6650
|
+
.ss-w-gtile--exact { background: var(--ss-w-correct); color: #fff; }
|
|
6651
|
+
.ss-w-gtile--near { background: var(--ss-w-cta); color: var(--ss-w-cta-ink, #fff); }
|
|
6652
|
+
.ss-w-gtile--miss { background: var(--ss-w-bubble); color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); }
|
|
6653
|
+
.ss-w-gtile-dir { font-size: 11px; line-height: 1; }
|
|
6654
|
+
/* Hint line */
|
|
6655
|
+
.ss-w-gt-hint { font-size: 11.5px; color: var(--ss-w-faint); text-align: center; padding: 2px 0; font-style: italic; }
|
|
6656
|
+
/* Outcome banner: shown when solved or failed */
|
|
6657
|
+
.ss-w-gt-banner { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 12px; border-radius: 12px; text-align: center; }
|
|
6658
|
+
.ss-w-gt-banner--solved { background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6659
|
+
.ss-w-gt-banner--failed { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); }
|
|
6660
|
+
.ss-w-gt-banner-name { font-size: 16px; font-weight: 750; color: var(--ss-w-ink); }
|
|
6661
|
+
.ss-w-gt-banner-label { font-size: 12px; color: var(--ss-w-faint); }
|
|
6662
|
+
|
|
6663
|
+
/* ---- Higher or Lower game screen (D3) ---- */
|
|
6664
|
+
.ss-w-hl { display: flex; flex-direction: column; gap: 12px; }
|
|
6665
|
+
/* Stat context header: family name + season */
|
|
6666
|
+
.ss-w-hlctx { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
|
|
6667
|
+
.ss-w-hlctx-fam { font-size: 14px; font-weight: 750; color: var(--ss-w-ink); }
|
|
6668
|
+
.ss-w-hlctx-szn { font-size: 11.5px; color: var(--ss-w-faint); font-weight: 500; }
|
|
6669
|
+
/* Score chip */
|
|
6670
|
+
.ss-w-hl-score { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 11%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 22%, var(--ss-w-line)); border-radius: 999px; padding: 3px 10px; }
|
|
6671
|
+
/* Pair card: two player cards + divider */
|
|
6672
|
+
.ss-w-hlpair { display: flex; align-items: stretch; gap: 0; border-radius: 14px; border: 1.5px solid var(--ss-w-line); overflow: hidden; background: var(--ss-w-panel); }
|
|
6673
|
+
/* Player card */
|
|
6674
|
+
.ss-w-hlpc { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 10px; text-align: center; }
|
|
6675
|
+
.ss-w-hlpc--b { border-left: 1px solid var(--ss-w-line); }
|
|
6676
|
+
.ss-w-hlpc-name { font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.25; word-break: break-word; min-width: 0; }
|
|
6677
|
+
.ss-w-hlpc-val { font-size: 22px; font-weight: 800; color: var(--ss-w-accent); font-variant-numeric: tabular-nums; line-height: 1; }
|
|
6678
|
+
.ss-w-hlpc-val--hidden { color: var(--ss-w-faint); font-size: 26px; }
|
|
6679
|
+
.ss-w-hlpc-val--correct { color: var(--ss-w-correct); }
|
|
6680
|
+
.ss-w-hlpc-val--wrong { color: var(--ss-w-cta); }
|
|
6681
|
+
.ss-w-hlpc-badge { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; border-radius: 999px; padding: 2px 8px; }
|
|
6682
|
+
.ss-w-hlpc-badge--correct { color: #fff; background: var(--ss-w-correct); }
|
|
6683
|
+
.ss-w-hlpc-badge--wrong { color: var(--ss-w-cta-ink, #fff); background: var(--ss-w-cta); }
|
|
6684
|
+
/* Higher / Lower buttons */
|
|
6685
|
+
.ss-w-hlbtns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
|
6686
|
+
.ss-w-hlbtn { padding: 11px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); color: var(--ss-w-ink); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; transition: background .1s, border-color .1s, color .1s; }
|
|
6687
|
+
.ss-w-hlbtn:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); color: var(--ss-w-accent); }
|
|
6688
|
+
.ss-w-hlbtn:disabled { opacity: .5; cursor: not-allowed; }
|
|
6689
|
+
/* Answered pair result rows */
|
|
6690
|
+
.ss-w-hlresults { display: flex; flex-direction: column; gap: 4px; }
|
|
6691
|
+
.ss-w-hlrrow { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 8px; font-size: 12px; background: var(--ss-w-bubble); }
|
|
6692
|
+
.ss-w-hlrrow--correct { background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); }
|
|
6693
|
+
.ss-w-hlrrow--wrong { background: color-mix(in srgb, var(--ss-w-cta) 8%, var(--ss-w-panel)); }
|
|
6694
|
+
.ss-w-hlrrow-names { flex: 1; min-width: 0; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6695
|
+
.ss-w-hlrrow-pick { font-size: 11px; font-weight: 700; text-transform: uppercase; color: var(--ss-w-faint); }
|
|
6696
|
+
.ss-w-hlrrow-icon { font-size: 14px; flex: none; }
|
|
6697
|
+
|
|
6698
|
+
/* ---- Career Path game screen (D3) ---- */
|
|
6699
|
+
.ss-w-cpath { display: flex; flex-direction: column; gap: 12px; }
|
|
6700
|
+
/* Context header */
|
|
6701
|
+
.ss-w-cpath-ctx { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px; }
|
|
6702
|
+
.ss-w-cpath-ctx-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }
|
|
6703
|
+
.ss-w-cpath-ctx-count { font-size: 12px; font-weight: 600; color: var(--ss-w-accent); }
|
|
6704
|
+
/* Career path: vertical timeline of club spells */
|
|
6705
|
+
.ss-w-cpath-path { display: flex; flex-direction: column; gap: 4px; }
|
|
6706
|
+
/* Single club card */
|
|
6707
|
+
.ss-w-cpath-club { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 10px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); }
|
|
6708
|
+
.ss-w-cpath-club--loan { border-style: dashed; }
|
|
6709
|
+
/* Crest image / fallback */
|
|
6710
|
+
.ss-w-cpath-crest { width: 30px; height: 30px; object-fit: contain; flex: none; border-radius: 4px; }
|
|
6711
|
+
.ss-w-cpath-crest--fallback { background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; }
|
|
6712
|
+
/* Club info: name + years */
|
|
6713
|
+
.ss-w-cpath-club-info { display: flex; flex: 1; min-width: 0; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
6714
|
+
.ss-w-cpath-club-name { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6715
|
+
.ss-w-cpath-spell-yr { font-size: 11px; color: var(--ss-w-faint); font-weight: 500; white-space: nowrap; }
|
|
6716
|
+
.ss-w-cpath-loan-badge { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; padding: 1px 7px; border-radius: 999px; background: color-mix(in srgb, var(--ss-w-cta) 15%, var(--ss-w-panel)); color: var(--ss-w-cta-ink, #1b1300); border: 1px solid color-mix(in srgb, var(--ss-w-cta) 30%, var(--ss-w-line)); flex: none; }
|
|
6717
|
+
/* Hidden clubs indicator */
|
|
6718
|
+
.ss-w-cpath-hidden { font-size: 11.5px; color: var(--ss-w-faint); font-style: italic; text-align: center; padding: 6px 0 2px; }
|
|
6719
|
+
/* Hint line */
|
|
6720
|
+
.ss-w-cpath-hint { font-size: 11.5px; color: var(--ss-w-faint); text-align: center; padding: 2px 0; font-style: italic; }
|
|
6721
|
+
/* Outcome banner */
|
|
6722
|
+
.ss-w-cpath-banner { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 12px; border-radius: 12px; text-align: center; }
|
|
6723
|
+
.ss-w-cpath-banner--solved { background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6724
|
+
.ss-w-cpath-banner--failed { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); }
|
|
6725
|
+
.ss-w-cpath-banner-name { font-size: 16px; font-weight: 750; color: var(--ss-w-ink); }
|
|
6726
|
+
.ss-w-cpath-banner-label { font-size: 12px; color: var(--ss-w-faint); }
|
|
6727
|
+
|
|
6728
|
+
/* ---- Beat the Grid game screen (D3) ---- */
|
|
6729
|
+
.ss-w-btg { display: flex; flex-direction: column; gap: 10px; }
|
|
6730
|
+
/* Score/context row */
|
|
6731
|
+
.ss-w-btg-ctx { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
|
|
6732
|
+
.ss-w-btg-ctx-score { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }
|
|
6733
|
+
.ss-w-btg-ctx-left { font-size: 12px; color: var(--ss-w-faint); font-weight: 500; }
|
|
6734
|
+
.ss-w-btg-ctx-done { font-size: 12px; font-weight: 700; color: var(--ss-w-correct); }
|
|
6735
|
+
/* Grid layout \u2014 col count driven inline via style */
|
|
6736
|
+
.ss-w-btg-grid { display: grid; gap: 4px; width: 100%; }
|
|
6737
|
+
/* Generic grid cell */
|
|
6738
|
+
.ss-w-btg-gc { display: flex; align-items: center; justify-content: center; text-align: center; border-radius: 8px; min-height: 42px; padding: 4px; font-size: 11px; word-break: break-word; line-height: 1.2; }
|
|
6739
|
+
/* Corner placeholder */
|
|
6740
|
+
.ss-w-btg-gc--corner { background: none; }
|
|
6741
|
+
/* Column header */
|
|
6742
|
+
.ss-w-btg-gc--colhdr { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); }
|
|
6743
|
+
/* Row header */
|
|
6744
|
+
.ss-w-btg-gc--rowhdr { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); writing-mode: horizontal-tb; }
|
|
6745
|
+
/* Interactive cells */
|
|
6746
|
+
.ss-w-btg-cell { flex-direction: column; gap: 2px; cursor: pointer; background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-line); transition: border-color .12s, background .12s; }
|
|
6747
|
+
.ss-w-btg-cell:hover:not(:disabled) { border-color: var(--ss-w-accent); background: var(--ss-w-bubble); }
|
|
6748
|
+
.ss-w-btg-cell:disabled { cursor: not-allowed; opacity: .75; }
|
|
6749
|
+
.ss-w-btg-cell--correct { background: color-mix(in srgb, var(--ss-w-correct) 14%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 35%, var(--ss-w-line)); }
|
|
6750
|
+
.ss-w-btg-cell--wrong { background: color-mix(in srgb, var(--ss-w-wrong) 10%, var(--ss-w-panel)); }
|
|
6751
|
+
.ss-w-btg-cell--active { border-color: var(--ss-w-accent); }
|
|
6752
|
+
.ss-w-btg-cell-score { font-size: 14px; font-weight: 800; color: var(--ss-w-ink); font-variant-numeric: tabular-nums; }
|
|
6753
|
+
.ss-w-btg-cell-check { font-size: 12px; color: var(--ss-w-correct); line-height: 1; }
|
|
6754
|
+
.ss-w-btg-cell-empty { font-size: 16px; color: var(--ss-w-faint); }
|
|
6755
|
+
/* Scoped search sheet: slides up over the grid */
|
|
6756
|
+
.ss-w-btg-sheet { display: flex; flex-direction: column; gap: 10px; padding: 12px; background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-line); border-radius: 14px; box-shadow: 0 4px 20px rgba(0,0,0,.1); }
|
|
6757
|
+
.ss-w-btg-sheet-hdr { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
6758
|
+
.ss-w-btg-sheet-ctx { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
|
|
6759
|
+
.ss-w-btg-sheet-row { font-size: 12.5px; font-weight: 700; color: var(--ss-w-ink); }
|
|
6760
|
+
.ss-w-btg-sheet-sep { font-size: 13px; color: var(--ss-w-faint); font-weight: 500; }
|
|
6761
|
+
.ss-w-btg-sheet-col { font-size: 12.5px; font-weight: 700; color: var(--ss-w-accent); }
|
|
6762
|
+
.ss-w-btg-sheet-close { background: none; border: none; cursor: pointer; font-size: 14px; color: var(--ss-w-faint); padding: 2px 6px; border-radius: 6px; line-height: 1; font: inherit; }
|
|
6763
|
+
.ss-w-btg-sheet-close:hover { color: var(--ss-w-ink); background: var(--ss-w-bubble); }
|
|
6764
|
+
|
|
6765
|
+
/* ---- Guess the XI game screen (D3) ---- */
|
|
6766
|
+
.ss-w-gxi { display: flex; flex-direction: column; gap: 12px; }
|
|
6767
|
+
/* Context label (pool label) */
|
|
6768
|
+
.ss-w-gxi-ctx { display: flex; align-items: center; }
|
|
6769
|
+
.ss-w-gxi-ctx-label { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .05em; }
|
|
6770
|
+
/* Positions pitch: compact slot grid */
|
|
6771
|
+
.ss-w-gxi-pitch { display: flex; flex-wrap: wrap; gap: 5px; }
|
|
6772
|
+
.ss-w-gxi-pslot { display: flex; flex-direction: column; align-items: center; gap: 2px; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 6px 10px; min-width: 52px; }
|
|
6773
|
+
.ss-w-gxi-pslot-pos { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-accent); }
|
|
6774
|
+
.ss-w-gxi-pslot-nat { font-size: 10px; color: var(--ss-w-faint); font-weight: 500; text-align: center; line-height: 1.2; }
|
|
6775
|
+
/* Earned reveals */
|
|
6776
|
+
.ss-w-gxi-reveals { display: flex; flex-direction: column; gap: 4px; }
|
|
6777
|
+
.ss-w-gxi-reveal { display: flex; align-items: center; gap: 6px; padding: 7px 10px; background: color-mix(in srgb, var(--ss-w-cta) 8%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-cta) 22%, var(--ss-w-line)); border-radius: 8px; }
|
|
6778
|
+
.ss-w-gxi-reveal-slot { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-cta-ink, #1b1300); background: var(--ss-w-cta); border-radius: 6px; padding: 1px 6px; flex: none; }
|
|
6779
|
+
.ss-w-gxi-reveal-val { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
|
|
6780
|
+
/* Team pool: responsive flex grid of buttons */
|
|
6781
|
+
.ss-w-gxi-pool { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
6782
|
+
.ss-w-gxi-team-btn { font: inherit; font-size: 12.5px; font-weight: 650; border-radius: 10px; padding: 9px 14px; cursor: pointer; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); color: var(--ss-w-ink); transition: background .1s, border-color .1s; }
|
|
6783
|
+
.ss-w-gxi-team-btn:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6784
|
+
.ss-w-gxi-team-btn:disabled { opacity: .5; cursor: not-allowed; }
|
|
6785
|
+
.ss-w-gxi-team-btn--correct { background: color-mix(in srgb, var(--ss-w-correct) 14%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 35%, var(--ss-w-line)); color: var(--ss-w-correct); }
|
|
6786
|
+
.ss-w-gxi-team-btn--wrong { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); text-decoration: line-through; opacity: .65; }
|
|
6787
|
+
/* Outcome banner */
|
|
6788
|
+
.ss-w-gxi-banner { display: flex; align-items: center; justify-content: center; padding: 10px 12px; border-radius: 10px; }
|
|
6789
|
+
.ss-w-gxi-banner--solved { background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6790
|
+
.ss-w-gxi-banner--failed { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); }
|
|
6791
|
+
.ss-w-gxi-banner-label { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }
|
|
6792
|
+
/* Hint line */
|
|
6793
|
+
.ss-w-gxi-hint { font-size: 11.5px; color: var(--ss-w-faint); text-align: center; font-style: italic; }
|
|
6794
|
+
|
|
6795
|
+
/* ---- Daily Quiz game screen (D3) ---- */
|
|
6796
|
+
.ss-w-dq { display: flex; flex-direction: column; gap: 14px; }
|
|
6797
|
+
/* Score banner (post-reveal) */
|
|
6798
|
+
.ss-w-dq-score { display: flex; align-items: baseline; justify-content: center; gap: 4px; padding: 10px; background: color-mix(in srgb, var(--ss-w-correct) 10%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); border-radius: 12px; }
|
|
6799
|
+
.ss-w-dq-score-val { font-size: 26px; font-weight: 800; color: var(--ss-w-correct); font-variant-numeric: tabular-nums; }
|
|
6800
|
+
.ss-w-dq-score-label { font-size: 13px; font-weight: 650; color: var(--ss-w-faint); }
|
|
6801
|
+
/* Progress bar */
|
|
6802
|
+
.ss-w-dq-prog { height: 4px; border-radius: 999px; background: var(--ss-w-bubble); overflow: hidden; }
|
|
6803
|
+
.ss-w-dq-prog-fill { height: 100%; border-radius: 999px; background: var(--ss-w-accent); transition: width .25s ease; }
|
|
6804
|
+
/* Questions list */
|
|
6805
|
+
.ss-w-dq-questions { display: flex; flex-direction: column; gap: 16px; }
|
|
6806
|
+
/* Single question */
|
|
6807
|
+
.ss-w-dq-q { display: flex; flex-direction: column; gap: 8px; }
|
|
6808
|
+
.ss-w-dq-qstem { font-size: 13.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.4; }
|
|
6809
|
+
/* Options grid: 2 across */
|
|
6810
|
+
.ss-w-dq-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
|
|
6811
|
+
.ss-w-dq-qopt { display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 12.5px; cursor: pointer; text-align: left; color: var(--ss-w-ink); transition: background .1s, border-color .1s; }
|
|
6812
|
+
.ss-w-dq-qopt:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6813
|
+
.ss-w-dq-qopt:disabled { cursor: not-allowed; }
|
|
6814
|
+
.ss-w-dq-qopt--selected { border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); }
|
|
6815
|
+
.ss-w-dq-qopt--correct { border-color: var(--ss-w-correct); background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); color: var(--ss-w-correct); }
|
|
6816
|
+
.ss-w-dq-qopt--wrong { border-color: color-mix(in srgb, var(--ss-w-cta) 50%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-cta) 8%, var(--ss-w-panel)); opacity: .75; }
|
|
6817
|
+
/* Option letter badge */
|
|
6818
|
+
.ss-w-dq-qopt-letter { flex: none; width: 20px; height: 20px; border-radius: 50%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); font-size: 10px; font-weight: 800; display: flex; align-items: center; justify-content: center; color: var(--ss-w-faint); }
|
|
6819
|
+
.ss-w-dq-qopt-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6820
|
+
/* Why/reveal text */
|
|
6821
|
+
.ss-w-dq-qwhy { font-size: 11.5px; padding: 6px 10px; border-radius: 8px; line-height: 1.4; }
|
|
6822
|
+
.ss-w-dq-qwhy--correct { background: color-mix(in srgb, var(--ss-w-correct) 9%, var(--ss-w-panel)); color: var(--ss-w-correct); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 22%, var(--ss-w-line)); }
|
|
6823
|
+
.ss-w-dq-qwhy--wrong { background: var(--ss-w-bubble); color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); }
|
|
6824
|
+
/* Submit button */
|
|
6825
|
+
.ss-w-dq-submit { width: 100%; padding: 13px; border-radius: 12px; border: none; background: var(--ss-w-accent); color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: opacity .15s; }
|
|
6826
|
+
.ss-w-dq-submit:disabled { opacity: .4; cursor: not-allowed; }
|
|
6827
|
+
.ss-w-dq-submit:hover:not(:disabled) { opacity: .88; }
|
|
6828
|
+
|
|
6829
|
+
/* \u2500\u2500 Matchday Predictor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6830
|
+
.ss-w-mp { display: flex; flex-direction: column; gap: 14px; }
|
|
6831
|
+
/* Score prediction row */
|
|
6832
|
+
.ss-w-mp-pred-score { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 12px 0; }
|
|
6833
|
+
.ss-w-mp-team { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1; min-width: 0; }
|
|
6834
|
+
.ss-w-mp-team-name { font-size: 12px; font-weight: 650; color: var(--ss-w-ink); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
|
|
6835
|
+
.ss-w-mp-stepper { display: flex; align-items: center; gap: 8px; }
|
|
6836
|
+
.ss-w-mp-stepper-btn { width: 32px; height: 32px; border-radius: 50%; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 18px; font-weight: 700; color: var(--ss-w-ink); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background .1s; }
|
|
6837
|
+
.ss-w-mp-stepper-btn:hover:not(:disabled) { background: var(--ss-w-bubble); }
|
|
6838
|
+
.ss-w-mp-stepper-btn:disabled { opacity: .35; cursor: not-allowed; }
|
|
6839
|
+
.ss-w-mp-stepper-val { font-size: 26px; font-weight: 800; color: var(--ss-w-ink); min-width: 28px; text-align: center; font-variant-numeric: tabular-nums; }
|
|
6840
|
+
.ss-w-mp-sep { font-size: 22px; font-weight: 700; color: var(--ss-w-faint); padding: 0 4px; }
|
|
6841
|
+
/* First-scorer picker */
|
|
6842
|
+
.ss-w-mp-scorer { display: flex; flex-direction: column; gap: 6px; }
|
|
6843
|
+
.ss-w-mp-scorer-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }
|
|
6844
|
+
.ss-w-mp-scorer-list { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
6845
|
+
.ss-w-mp-scorer-opt { padding: 6px 12px; border-radius: 999px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 12px; font-weight: 600; color: var(--ss-w-ink); cursor: pointer; transition: background .1s, border-color .1s; }
|
|
6846
|
+
.ss-w-mp-scorer-opt:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6847
|
+
.ss-w-mp-scorer-opt--selected { border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); color: var(--ss-w-accent); }
|
|
6848
|
+
.ss-w-mp-scorer-opt:disabled { opacity: .35; cursor: not-allowed; }
|
|
6849
|
+
/* Save button */
|
|
6850
|
+
.ss-w-mp-savebtn { width: 100%; padding: 13px; border-radius: 12px; border: none; background: var(--ss-w-accent); color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: opacity .15s; }
|
|
6851
|
+
.ss-w-mp-savebtn:disabled { opacity: .4; cursor: not-allowed; }
|
|
6852
|
+
.ss-w-mp-savebtn:hover:not(:disabled) { opacity: .88; }
|
|
6853
|
+
/* Live / pending state */
|
|
6854
|
+
.ss-w-mp-live { display: flex; flex-direction: column; gap: 10px; align-items: center; text-align: center; padding: 14px 0; }
|
|
6855
|
+
.ss-w-mp-live-score { font-size: 30px; font-weight: 800; color: var(--ss-w-ink); font-variant-numeric: tabular-nums; }
|
|
6856
|
+
.ss-w-mp-live-label { font-size: 12px; color: var(--ss-w-faint); font-style: italic; }
|
|
6857
|
+
.ss-w-mp-live-outcome { display: flex; flex-direction: column; gap: 6px; width: 100%; }
|
|
6858
|
+
.ss-w-mp-live-row { display: flex; align-items: center; justify-content: space-between; padding: 7px 12px; border-radius: 10px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); font-size: 12.5px; }
|
|
6859
|
+
.ss-w-mp-live-row--correct { border-color: color-mix(in srgb, var(--ss-w-correct) 40%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); }
|
|
6860
|
+
.ss-w-mp-live-row-key { color: var(--ss-w-faint); font-weight: 600; }
|
|
6861
|
+
.ss-w-mp-live-row-val { font-weight: 700; color: var(--ss-w-ink); }
|
|
6862
|
+
.ss-w-mp-live-row--correct .ss-w-mp-live-row-val { color: var(--ss-w-correct); }
|
|
6863
|
+
/* For-fun note */
|
|
6864
|
+
.ss-w-mp-fun { font-size: 11px; color: var(--ss-w-faint); text-align: center; font-style: italic; }
|
|
6865
|
+
|
|
6866
|
+
/* \u2500\u2500 Starting XI \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6867
|
+
.ss-w-sxi { display: flex; flex-direction: column; gap: 14px; }
|
|
6868
|
+
.ss-w-sxi-formation { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; }
|
|
6869
|
+
/* Formation pitch area */
|
|
6870
|
+
.ss-w-sxi-pitch { display: flex; flex-direction: column; gap: 10px; padding: 12px 8px; border-radius: 12px; background: color-mix(in srgb, var(--ss-w-accent) 4%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); min-height: 260px; }
|
|
6871
|
+
.ss-w-sxi-pitch-row { display: flex; justify-content: center; gap: 6px; flex-wrap: wrap; }
|
|
6872
|
+
/* Player slot */
|
|
6873
|
+
.ss-w-sxi-pslot { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 64px; cursor: pointer; }
|
|
6874
|
+
.ss-w-sxi-pslot-num { width: 36px; height: 36px; border-radius: 50%; border: 2px dashed var(--ss-w-line); background: var(--ss-w-bubble); display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; color: var(--ss-w-faint); transition: border-color .1s, background .1s; }
|
|
6875
|
+
.ss-w-sxi-pslot--filled .ss-w-sxi-pslot-num { border-style: solid; border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); color: var(--ss-w-accent); }
|
|
6876
|
+
.ss-w-sxi-pslot-name { font-size: 9.5px; font-weight: 600; color: var(--ss-w-ink); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
|
|
6877
|
+
/* Squad picker */
|
|
6878
|
+
.ss-w-sxi-squad { display: flex; flex-direction: column; gap: 4px; max-height: 200px; overflow-y: auto; }
|
|
6879
|
+
.ss-w-sxi-squad-row { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; border-radius: 8px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); cursor: pointer; transition: background .1s; }
|
|
6880
|
+
.ss-w-sxi-squad-row:hover:not(.ss-w-sxi-squad-row--picked) { background: var(--ss-w-bubble); }
|
|
6881
|
+
.ss-w-sxi-squad-row--picked { background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); border-color: var(--ss-w-accent); }
|
|
6882
|
+
.ss-w-sxi-squad-name { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
|
|
6883
|
+
.ss-w-sxi-squad-pos { font-size: 10.5px; color: var(--ss-w-faint); }
|
|
6884
|
+
.ss-w-sxi-savebtn { width: 100%; padding: 13px; border-radius: 12px; border: none; background: var(--ss-w-accent); color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: opacity .15s; }
|
|
6885
|
+
.ss-w-sxi-savebtn:disabled { opacity: .4; cursor: not-allowed; }
|
|
6886
|
+
.ss-w-sxi-savebtn:hover:not(:disabled) { opacity: .88; }
|
|
6887
|
+
/* Pending / graded states */
|
|
6888
|
+
.ss-w-sxi-status { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 14px 12px; border-radius: 12px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); text-align: center; }
|
|
6889
|
+
.ss-w-sxi-status--graded { background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6890
|
+
.ss-w-sxi-status-score { font-size: 28px; font-weight: 800; color: var(--ss-w-correct); font-variant-numeric: tabular-nums; }
|
|
6891
|
+
.ss-w-sxi-status-label { font-size: 12.5px; color: var(--ss-w-faint); }
|
|
6892
|
+
|
|
6893
|
+
/* \u2500\u2500 Stat Ladder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6894
|
+
.ss-w-sl { display: flex; flex-direction: column; gap: 14px; }
|
|
6895
|
+
.ss-w-sl-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; }
|
|
6896
|
+
/* Ladder list */
|
|
6897
|
+
.ss-w-sl-ladder { display: flex; flex-direction: column; gap: 6px; }
|
|
6898
|
+
.ss-w-sl-lrow { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); }
|
|
6899
|
+
.ss-w-sl-lrow-rank { font-size: 11px; font-weight: 800; color: var(--ss-w-faint); width: 18px; flex: none; text-align: center; }
|
|
6900
|
+
.ss-w-sl-lrow-name { flex: 1; font-size: 13px; font-weight: 650; color: var(--ss-w-ink); }
|
|
6901
|
+
.ss-w-sl-lrow-stat { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); font-variant-numeric: tabular-nums; }
|
|
6902
|
+
/* Mystery rung */
|
|
6903
|
+
.ss-w-sl-mystery { border: 1.5px dashed var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 5%, var(--ss-w-panel)); }
|
|
6904
|
+
.ss-w-sl-mystery .ss-w-sl-lrow-name { color: var(--ss-w-faint); font-style: italic; }
|
|
6905
|
+
/* Reveal overlay: correct / wrong */
|
|
6906
|
+
.ss-w-sl-lrow--correct { border-color: color-mix(in srgb, var(--ss-w-correct) 40%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); }
|
|
6907
|
+
.ss-w-sl-lrow--wrong { border-color: color-mix(in srgb, var(--ss-w-wrong, #e05050) 30%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-wrong, #e05050) 6%, var(--ss-w-panel)); }
|
|
6908
|
+
/* Player picker */
|
|
6909
|
+
.ss-w-sl-picker { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
6910
|
+
.ss-w-sl-picker-opt { padding: 6px 12px; border-radius: 999px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 12px; font-weight: 600; color: var(--ss-w-ink); cursor: pointer; transition: background .1s, border-color .1s; }
|
|
6911
|
+
.ss-w-sl-picker-opt:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6912
|
+
.ss-w-sl-picker-opt:disabled { opacity: .35; cursor: not-allowed; }
|
|
6913
|
+
.ss-w-sl-reveal { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 12px; border-radius: 12px; text-align: center; font-size: 13px; font-weight: 650; color: var(--ss-w-ink); }
|
|
6914
|
+
.ss-w-sl-reveal--correct { background: color-mix(in srgb, var(--ss-w-correct) 10%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); color: var(--ss-w-correct); }
|
|
6915
|
+
.ss-w-sl-reveal--wrong { background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); }
|
|
6916
|
+
|
|
6917
|
+
/* \u2500\u2500 Fan MOTM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6918
|
+
.ss-w-motm { display: flex; flex-direction: column; gap: 14px; }
|
|
6919
|
+
.ss-w-motm-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; }
|
|
6920
|
+
/* Vote candidate list */
|
|
6921
|
+
.ss-w-motm-votes { display: flex; flex-direction: column; gap: 6px; }
|
|
6922
|
+
.ss-w-motm-vrow { display: flex; align-items: center; gap: 10px; padding: 11px 14px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); cursor: pointer; transition: background .1s, border-color .1s; position: relative; overflow: hidden; }
|
|
6923
|
+
.ss-w-motm-vrow:hover:not(.ss-w-motm-vrow--voted):not(.ss-w-motm-vrow--result) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6924
|
+
.ss-w-motm-vrow--voted { border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); cursor: default; }
|
|
6925
|
+
.ss-w-motm-vrow--result { cursor: default; }
|
|
6926
|
+
.ss-w-motm-vrow-name { flex: 1; font-size: 13px; font-weight: 650; color: var(--ss-w-ink); position: relative; z-index: 1; }
|
|
6927
|
+
.ss-w-motm-vrow-pct { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); position: relative; z-index: 1; font-variant-numeric: tabular-nums; }
|
|
6928
|
+
/* Share fill bar (behind content) */
|
|
6929
|
+
.ss-w-motm-vfill { position: absolute; top: 0; left: 0; height: 100%; background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); transition: width .4s ease; pointer-events: none; }
|
|
6930
|
+
.ss-w-motm-vrow--voted .ss-w-motm-vfill { background: color-mix(in srgb, var(--ss-w-accent) 18%, var(--ss-w-panel)); }
|
|
6931
|
+
/* For-fun note */
|
|
6932
|
+
.ss-w-motm-fun { font-size: 11px; color: var(--ss-w-faint); text-align: center; font-style: italic; }
|
|
5307
6933
|
`;
|
|
5308
6934
|
|
|
5309
6935
|
// src/StatsWidget.tsx
|
|
5310
|
-
var
|
|
6936
|
+
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
5311
6937
|
function buildClient(props) {
|
|
5312
6938
|
try {
|
|
5313
6939
|
if ("client" in props && props.client) {
|
|
@@ -5332,23 +6958,23 @@ function injectStyles(root) {
|
|
|
5332
6958
|
function StatsWidget(props) {
|
|
5333
6959
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
5334
6960
|
const cfg = props.config;
|
|
5335
|
-
const built = (0,
|
|
5336
|
-
const logger = (0,
|
|
6961
|
+
const built = (0, import_react39.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
6962
|
+
const logger = (0, import_react39.useMemo)(
|
|
5337
6963
|
() => built ? built.client.createEventLogger({
|
|
5338
6964
|
operatorUserId: cfg?.userContext?.operatorUserId,
|
|
5339
6965
|
anonymousUserId: cfg?.userContext?.anonymousUserId
|
|
5340
6966
|
}) : null,
|
|
5341
6967
|
[built?.client]
|
|
5342
6968
|
);
|
|
5343
|
-
const ui = (0,
|
|
5344
|
-
const rootRef = (0,
|
|
5345
|
-
const introDoneRef = (0,
|
|
5346
|
-
const markIntroDone = (0,
|
|
6969
|
+
const ui = (0, import_react39.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
6970
|
+
const rootRef = (0, import_react39.useRef)(null);
|
|
6971
|
+
const introDoneRef = (0, import_react39.useRef)(false);
|
|
6972
|
+
const markIntroDone = (0, import_react39.useCallback)(() => {
|
|
5347
6973
|
introDoneRef.current = true;
|
|
5348
6974
|
}, []);
|
|
5349
6975
|
const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
|
|
5350
6976
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
|
|
5351
|
-
const [hasToday, setHasToday] = (0,
|
|
6977
|
+
const [hasToday, setHasToday] = (0, import_react39.useState)(false);
|
|
5352
6978
|
const monitor = useLiveMonitor({
|
|
5353
6979
|
getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
|
|
5354
6980
|
getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
|
|
@@ -5356,15 +6982,15 @@ function StatsWidget(props) {
|
|
|
5356
6982
|
isOpen: controller.state.isOpen,
|
|
5357
6983
|
hasToday
|
|
5358
6984
|
});
|
|
5359
|
-
const getSchedule = (0,
|
|
6985
|
+
const getSchedule = (0, import_react39.useCallback)(
|
|
5360
6986
|
(localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),
|
|
5361
6987
|
[built]
|
|
5362
6988
|
);
|
|
5363
|
-
const getStates = (0,
|
|
6989
|
+
const getStates = (0, import_react39.useCallback)(
|
|
5364
6990
|
(matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
|
|
5365
6991
|
[built]
|
|
5366
6992
|
);
|
|
5367
|
-
const pinnedMatchIds = (0,
|
|
6993
|
+
const pinnedMatchIds = (0, import_react39.useMemo)(
|
|
5368
6994
|
() => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
|
|
5369
6995
|
[monitor.pins]
|
|
5370
6996
|
);
|
|
@@ -5376,19 +7002,19 @@ function StatsWidget(props) {
|
|
|
5376
7002
|
pinnedMatchIds
|
|
5377
7003
|
});
|
|
5378
7004
|
const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0;
|
|
5379
|
-
(0,
|
|
7005
|
+
(0, import_react39.useEffect)(() => {
|
|
5380
7006
|
setHasToday(todayHasContent);
|
|
5381
7007
|
}, [todayHasContent]);
|
|
5382
7008
|
const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab });
|
|
5383
7009
|
const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab });
|
|
5384
7010
|
const markTodayActivity = monitor.markTodayActivity;
|
|
5385
|
-
const prevLiveCountRef = (0,
|
|
5386
|
-
(0,
|
|
7011
|
+
const prevLiveCountRef = (0, import_react39.useRef)(0);
|
|
7012
|
+
(0, import_react39.useEffect)(() => {
|
|
5387
7013
|
const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
|
|
5388
7014
|
prevLiveCountRef.current = discovery.liveCount;
|
|
5389
7015
|
if (rose) markTodayActivity();
|
|
5390
7016
|
}, [discovery.liveCount, markTodayActivity]);
|
|
5391
|
-
const slip = (0,
|
|
7017
|
+
const slip = (0, import_react39.useMemo)(
|
|
5392
7018
|
() => {
|
|
5393
7019
|
const handler = props.config?.onAddToSlip;
|
|
5394
7020
|
return {
|
|
@@ -5411,18 +7037,18 @@ function StatsWidget(props) {
|
|
|
5411
7037
|
},
|
|
5412
7038
|
[props.config?.onAddToSlip, controller.state.conversationId, built, monitor.markInSlip]
|
|
5413
7039
|
);
|
|
5414
|
-
const onDashboardTap = (0,
|
|
7040
|
+
const onDashboardTap = (0, import_react39.useMemo)(
|
|
5415
7041
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : void 0,
|
|
5416
7042
|
[built, logger]
|
|
5417
7043
|
);
|
|
5418
7044
|
const operatorUserId = cfg?.userContext?.operatorUserId;
|
|
5419
7045
|
const anonymousUserId = cfg?.userContext?.anonymousUserId;
|
|
5420
7046
|
const conversationId = controller.state.conversationId ?? void 0;
|
|
5421
|
-
(0,
|
|
7047
|
+
(0, import_react39.useEffect)(() => {
|
|
5422
7048
|
if (!logger) return;
|
|
5423
7049
|
logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
|
|
5424
7050
|
}, [logger, operatorUserId, anonymousUserId, conversationId]);
|
|
5425
|
-
(0,
|
|
7051
|
+
(0, import_react39.useEffect)(() => {
|
|
5426
7052
|
if (!logger) return;
|
|
5427
7053
|
const onHide = () => {
|
|
5428
7054
|
logger.flushOnHide();
|
|
@@ -5439,14 +7065,14 @@ function StatsWidget(props) {
|
|
|
5439
7065
|
logger.dispose();
|
|
5440
7066
|
};
|
|
5441
7067
|
}, [logger]);
|
|
5442
|
-
(0,
|
|
7068
|
+
(0, import_react39.useEffect)(() => {
|
|
5443
7069
|
if (!built || !ui.injectStyles) return;
|
|
5444
7070
|
const node = rootRef.current?.getRootNode();
|
|
5445
7071
|
if (node) injectStyles(node);
|
|
5446
7072
|
}, [built, ui.injectStyles]);
|
|
5447
7073
|
if (!built) return null;
|
|
5448
7074
|
const attrs = themeAttrs(ui);
|
|
5449
|
-
return /* @__PURE__ */ (0,
|
|
7075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(EventLogContext.Provider, { value: logger, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { ref: rootRef, className: "ss-w-root", "data-ss-w-theme": attrs["data-ss-w-theme"], "data-ss-w-pos": attrs["data-ss-w-pos"], style: attrs.style, children: controller.state.isOpen ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
5450
7076
|
ChatPanel,
|
|
5451
7077
|
{
|
|
5452
7078
|
controller,
|
|
@@ -5457,9 +7083,10 @@ function StatsWidget(props) {
|
|
|
5457
7083
|
discovery,
|
|
5458
7084
|
gamesResult,
|
|
5459
7085
|
leaderboardResult,
|
|
5460
|
-
loggedIn: !!operatorUserId
|
|
7086
|
+
loggedIn: !!operatorUserId,
|
|
7087
|
+
conversation: built?.conversation ?? null
|
|
5461
7088
|
}
|
|
5462
|
-
) : /* @__PURE__ */ (0,
|
|
7089
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
5463
7090
|
ChatFab,
|
|
5464
7091
|
{
|
|
5465
7092
|
label: ui.launcherLabel,
|