@mblinkov/whats-missing 20.0.9 → 20.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/whats-missing.cjs.js +3 -38
- package/dist/whats-missing.es.js +248 -293
- package/package.json +9 -3
- package/src/Game.tsx +220 -263
package/src/Game.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo } from "react";
|
|
1
|
+
import { useState, useEffect, useMemo, useRef } from "react";
|
|
2
2
|
import { themes } from "./themes";
|
|
3
3
|
import { styles } from "./Game.styles";
|
|
4
4
|
import type { Theme } from "./themes";
|
|
@@ -11,55 +11,20 @@ type RoundResult = {
|
|
|
11
11
|
result: "correct" | "almost" | "wrong";
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
// ✅
|
|
14
|
+
// ✅ Минимальный reset — без вмешательства в body
|
|
15
15
|
const globalReset = () => {
|
|
16
16
|
const style = document.createElement("style");
|
|
17
17
|
style.textContent = `
|
|
18
|
-
html, body {
|
|
19
|
-
margin: 0;
|
|
20
|
-
padding: 0;
|
|
21
|
-
width: 100%;
|
|
22
|
-
height: 100%;
|
|
23
|
-
overflow-x: hidden;
|
|
24
|
-
background: linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%);
|
|
25
|
-
background-repeat: no-repeat;
|
|
26
|
-
background-attachment: fixed;
|
|
27
|
-
background-size: cover;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
#whats-missing-root {
|
|
31
|
-
all: unset;
|
|
32
|
-
display: block;
|
|
33
|
-
position: relative;
|
|
34
|
-
left: 0;
|
|
35
|
-
top: 0;
|
|
36
|
-
overflow: hidden;
|
|
37
|
-
width: 100%;
|
|
38
|
-
min-height: 100vh;
|
|
39
|
-
margin: 0;
|
|
40
|
-
padding: 0;
|
|
41
|
-
color: #1f2937;
|
|
42
|
-
text-align: center;
|
|
43
|
-
background: linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%);
|
|
44
|
-
background-size: cover;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
18
|
#whats-missing-root, #whats-missing-root * {
|
|
48
19
|
box-sizing: border-box;
|
|
49
20
|
font-family: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
|
50
21
|
}
|
|
51
|
-
|
|
52
22
|
#whats-missing-root img {
|
|
53
23
|
max-width: 100%;
|
|
54
24
|
height: auto;
|
|
55
25
|
display: block;
|
|
56
26
|
user-select: none;
|
|
57
27
|
}
|
|
58
|
-
|
|
59
|
-
@keyframes spin {
|
|
60
|
-
from { transform: rotate(0deg); }
|
|
61
|
-
to { transform: rotate(360deg); }
|
|
62
|
-
}
|
|
63
28
|
`;
|
|
64
29
|
document.head.appendChild(style);
|
|
65
30
|
};
|
|
@@ -80,8 +45,13 @@ const levenshtein = (a: string, b: string) => {
|
|
|
80
45
|
};
|
|
81
46
|
|
|
82
47
|
export default function Game() {
|
|
48
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
49
|
+
|
|
83
50
|
useEffect(() => {
|
|
84
51
|
globalReset();
|
|
52
|
+
return () => {
|
|
53
|
+
document.body.style.overflow = "";
|
|
54
|
+
};
|
|
85
55
|
}, []);
|
|
86
56
|
|
|
87
57
|
const [theme, setTheme] = useState<Theme | null>(null);
|
|
@@ -92,7 +62,7 @@ export default function Game() {
|
|
|
92
62
|
const [hiddenIndex, setHiddenIndex] = useState<number | null>(null);
|
|
93
63
|
const [phase, setPhase] = useState<"ready" | "memorize" | "guess">("ready");
|
|
94
64
|
const [readyTime, setReadyTime] = useState(3);
|
|
95
|
-
const [memorizeTime, setMemorizeTime] = useState(
|
|
65
|
+
const [memorizeTime, setMemorizeTime] = useState(10);
|
|
96
66
|
const [timeLeft, setTimeLeft] = useState(20);
|
|
97
67
|
const [score, setScore] = useState(0);
|
|
98
68
|
const [finished, setFinished] = useState(false);
|
|
@@ -147,27 +117,25 @@ export default function Game() {
|
|
|
147
117
|
if (isFirst) {
|
|
148
118
|
setPhase("ready");
|
|
149
119
|
setReadyTime(3);
|
|
150
|
-
setMemorizeTime(
|
|
120
|
+
setMemorizeTime(10);
|
|
151
121
|
} else {
|
|
152
122
|
setPhase("memorize");
|
|
153
|
-
setMemorizeTime(
|
|
123
|
+
setMemorizeTime(10);
|
|
154
124
|
}
|
|
155
125
|
};
|
|
156
126
|
|
|
157
127
|
useEffect(() => {
|
|
158
128
|
if (!started || finished || answered) return;
|
|
159
129
|
if (phase === "ready") {
|
|
160
|
-
if (readyTime <= 0)
|
|
161
|
-
|
|
162
|
-
} else {
|
|
130
|
+
if (readyTime <= 0) setPhase("memorize");
|
|
131
|
+
else {
|
|
163
132
|
const t = setTimeout(() => setReadyTime((r) => r - 1), 1000);
|
|
164
133
|
return () => clearTimeout(t);
|
|
165
134
|
}
|
|
166
135
|
}
|
|
167
136
|
if (phase === "memorize") {
|
|
168
|
-
if (memorizeTime <= 0)
|
|
169
|
-
|
|
170
|
-
} else {
|
|
137
|
+
if (memorizeTime <= 0) setPhase("guess");
|
|
138
|
+
else {
|
|
171
139
|
const t = setTimeout(() => setMemorizeTime((m) => m - 1), 1000);
|
|
172
140
|
return () => clearTimeout(t);
|
|
173
141
|
}
|
|
@@ -186,19 +154,7 @@ export default function Game() {
|
|
|
186
154
|
const t = setTimeout(() => setTimeLeft((s) => s - 1), 1000);
|
|
187
155
|
return () => clearTimeout(t);
|
|
188
156
|
}
|
|
189
|
-
}, [
|
|
190
|
-
phase,
|
|
191
|
-
readyTime,
|
|
192
|
-
memorizeTime,
|
|
193
|
-
timeLeft,
|
|
194
|
-
started,
|
|
195
|
-
finished,
|
|
196
|
-
answered,
|
|
197
|
-
files,
|
|
198
|
-
hiddenIndex,
|
|
199
|
-
currentRound,
|
|
200
|
-
inputValue,
|
|
201
|
-
]);
|
|
157
|
+
}, [phase, readyTime, memorizeTime, timeLeft, started, finished, answered, files, hiddenIndex, currentRound, inputValue]);
|
|
202
158
|
|
|
203
159
|
const checkAnswer = () => {
|
|
204
160
|
if (hiddenIndex === null || animating) return;
|
|
@@ -217,10 +173,7 @@ export default function Game() {
|
|
|
217
173
|
setResult("wrong");
|
|
218
174
|
roundResult = "wrong";
|
|
219
175
|
}
|
|
220
|
-
setResultsTable((prev) => [
|
|
221
|
-
...prev,
|
|
222
|
-
{ round: currentRound, answer: userAnswer, correct, result: roundResult },
|
|
223
|
-
]);
|
|
176
|
+
setResultsTable((prev) => [...prev, { round: currentRound, answer: userAnswer, correct, result: roundResult }]);
|
|
224
177
|
setAnimating(true);
|
|
225
178
|
setTimeout(() => {
|
|
226
179
|
setAnimating(false);
|
|
@@ -229,9 +182,7 @@ export default function Game() {
|
|
|
229
182
|
};
|
|
230
183
|
|
|
231
184
|
const nextRound = () =>
|
|
232
|
-
currentRound < rounds
|
|
233
|
-
? (setCurrentRound((r) => r + 1), startRound())
|
|
234
|
-
: setFinished(true);
|
|
185
|
+
currentRound < rounds ? (setCurrentRound((r) => r + 1), startRound()) : setFinished(true);
|
|
235
186
|
|
|
236
187
|
const exitGame = () => {
|
|
237
188
|
setStarted(false);
|
|
@@ -239,226 +190,232 @@ export default function Game() {
|
|
|
239
190
|
setTheme(null);
|
|
240
191
|
};
|
|
241
192
|
|
|
242
|
-
// ✅ логотип с fallback SVG → PNG
|
|
243
193
|
const MemoizedLogo = useMemo(
|
|
244
194
|
() => (
|
|
245
195
|
<div style={styles.gmLogoFixed}>
|
|
246
196
|
<picture>
|
|
247
|
-
<source
|
|
248
|
-
|
|
249
|
-
type="image/svg+xml"
|
|
250
|
-
/>
|
|
251
|
-
<img
|
|
252
|
-
src={window.origin + "/cloud/speakid/games/whatsmissing/logo.png"}
|
|
253
|
-
alt="SPEAKID Logo"
|
|
254
|
-
style={styles.gmLogoImg}
|
|
255
|
-
loading="lazy"
|
|
256
|
-
/>
|
|
197
|
+
<source srcSet={window.origin + "/cloud/speakid/games/whatsmissing/logo.svg"} type="image/svg+xml" />
|
|
198
|
+
<img src={window.origin + "/cloud/speakid/games/whatsmissing/logo.png"} alt="SPEAKID Logo" style={styles.gmLogoImg} loading="lazy" />
|
|
257
199
|
</picture>
|
|
258
200
|
</div>
|
|
259
201
|
),
|
|
260
202
|
[]
|
|
261
203
|
);
|
|
262
204
|
|
|
205
|
+
// ✅ Новый контейнер для защиты от zoom
|
|
263
206
|
return (
|
|
264
|
-
<div
|
|
265
|
-
{
|
|
207
|
+
<div
|
|
208
|
+
ref={containerRef}
|
|
209
|
+
style={{
|
|
210
|
+
display: "flex",
|
|
211
|
+
justifyContent: "center",
|
|
212
|
+
alignItems: "center",
|
|
213
|
+
width: "100%",
|
|
214
|
+
height: "100%",
|
|
215
|
+
overflow: "hidden",
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
<div
|
|
219
|
+
style={{
|
|
220
|
+
width: window.innerWidth > window.innerHeight ? "90vh" : "90vw",
|
|
221
|
+
height: window.innerWidth > window.innerHeight ? "90vh" : "90vw",
|
|
222
|
+
display: "flex",
|
|
223
|
+
justifyContent: "center",
|
|
224
|
+
alignItems: "center",
|
|
225
|
+
flexDirection: "column",
|
|
226
|
+
borderRadius: "20px",
|
|
227
|
+
background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
|
|
228
|
+
}}
|
|
229
|
+
>
|
|
230
|
+
<div id="whats-missing-root">
|
|
231
|
+
{!isMobile && MemoizedLogo}
|
|
266
232
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
233
|
+
{!theme && !started && (
|
|
234
|
+
<div style={styles.gmCenterScreen}>
|
|
235
|
+
<h1 style={styles.gmHeadline1}>WHAT'S MISSING?</h1>
|
|
236
|
+
<p style={styles.gmBodyM}>Select a theme:</p>
|
|
237
|
+
<div style={{ display: "flex", gap: 16 }}>
|
|
238
|
+
{["animals", "food", "toys"].map((t) => (
|
|
239
|
+
<button key={t} style={styles.gmButton} onClick={() => setTheme(t as Theme)}>
|
|
240
|
+
{t === "animals" ? "🐶 Animals" : t === "food" ? "🍎 Food" : "🧸 Toys"}
|
|
241
|
+
</button>
|
|
242
|
+
))}
|
|
243
|
+
</div>
|
|
244
|
+
<div style={{ marginTop: 24 }}>
|
|
245
|
+
<p style={styles.gmBodyS}>Choose number of rounds:</p>
|
|
246
|
+
<div style={{ display: "flex", gap: 12, marginTop: 8 }}>
|
|
247
|
+
{[3, 4, 5].map((n) => (
|
|
248
|
+
<button
|
|
249
|
+
key={n}
|
|
250
|
+
style={{
|
|
251
|
+
...styles.gmButton,
|
|
252
|
+
...(rounds === n ? styles.gmButtonActive : {}),
|
|
253
|
+
}}
|
|
254
|
+
onClick={() => setRounds(n)}
|
|
255
|
+
>
|
|
256
|
+
{n}
|
|
257
|
+
</button>
|
|
258
|
+
))}
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
293
261
|
</div>
|
|
294
|
-
|
|
295
|
-
</div>
|
|
296
|
-
)}
|
|
297
|
-
|
|
298
|
-
{theme && !started && (
|
|
299
|
-
<div style={styles.gmCenterScreen}>
|
|
300
|
-
<h1 style={styles.gmHeadline1}>Theme selected: {theme}</h1>
|
|
301
|
-
<p style={styles.gmBodyM}>Rounds: {rounds}</p>
|
|
302
|
-
<button style={styles.gmButton} onClick={startGame}>
|
|
303
|
-
▶ Start game
|
|
304
|
-
</button>
|
|
305
|
-
</div>
|
|
306
|
-
)}
|
|
262
|
+
)}
|
|
307
263
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
<th>Round</th>
|
|
318
|
-
<th>Your Answer</th>
|
|
319
|
-
<th>Correct</th>
|
|
320
|
-
<th>Result</th>
|
|
321
|
-
</tr>
|
|
322
|
-
</thead>
|
|
323
|
-
<tbody>
|
|
324
|
-
{resultsTable.map((r, i) => (
|
|
325
|
-
<tr key={i}>
|
|
326
|
-
<td style={styles.gmTableCell}>{r.round}</td>
|
|
327
|
-
<td style={styles.gmTableCell}>{r.answer || "—"}</td>
|
|
328
|
-
<td style={styles.gmTableCell}>{r.correct}</td>
|
|
329
|
-
<td style={styles.gmTableCell}>
|
|
330
|
-
{r.result === "correct"
|
|
331
|
-
? "✔ Correct"
|
|
332
|
-
: r.result === "almost"
|
|
333
|
-
? "◐ Almost (0.5)"
|
|
334
|
-
: "✘ Wrong"}
|
|
335
|
-
</td>
|
|
336
|
-
</tr>
|
|
337
|
-
))}
|
|
338
|
-
</tbody>
|
|
339
|
-
</table>
|
|
340
|
-
<div style={{ display: "flex", gap: 12, marginTop: 24 }}>
|
|
341
|
-
<button style={styles.gmButton} onClick={startGame}>
|
|
342
|
-
🔁 Play again
|
|
343
|
-
</button>
|
|
344
|
-
<button style={styles.gmButton} onClick={exitGame}>
|
|
345
|
-
⬅️ Choose theme
|
|
346
|
-
</button>
|
|
347
|
-
</div>
|
|
348
|
-
</div>
|
|
349
|
-
)}
|
|
264
|
+
{theme && !started && (
|
|
265
|
+
<div style={styles.gmCenterScreen}>
|
|
266
|
+
<h1 style={styles.gmHeadline1}>Theme selected: {theme}</h1>
|
|
267
|
+
<p style={styles.gmBodyM}>Rounds: {rounds}</p>
|
|
268
|
+
<button style={styles.gmButton} onClick={startGame}>
|
|
269
|
+
▶ Start game
|
|
270
|
+
</button>
|
|
271
|
+
</div>
|
|
272
|
+
)}
|
|
350
273
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
alignItems: "center",
|
|
360
|
-
}}
|
|
361
|
-
>
|
|
362
|
-
{phase === "ready" && (
|
|
363
|
-
<>
|
|
364
|
-
<h1 style={{ ...styles.gmHeadline1, color: "#ec4c44" }}>GET READY</h1>
|
|
365
|
-
<div style={styles.gmHourglass}>⏳</div>
|
|
366
|
-
</>
|
|
367
|
-
)}
|
|
368
|
-
{phase === "memorize" && (
|
|
369
|
-
<p style={{ ...styles.gmBodyM, color: "#10b981" }}>
|
|
370
|
-
MEMORIZE ({memorizeTime})
|
|
274
|
+
{finished && (
|
|
275
|
+
<div style={styles.gmCenterScreen}>
|
|
276
|
+
<h1 style={styles.gmHeadline1}>Results</h1>
|
|
277
|
+
<h2 style={styles.gmHeadline3}>
|
|
278
|
+
Your score: {score} / {rounds}
|
|
279
|
+
</h2>
|
|
280
|
+
<p style={{ ...styles.gmBodyM, color: "#10b981", marginTop: 12 }}>
|
|
281
|
+
Yahoo! You did it! 🍬✨
|
|
371
282
|
</p>
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
283
|
+
<table style={styles.gmTable}>
|
|
284
|
+
<thead>
|
|
285
|
+
<tr>
|
|
286
|
+
<th>Round</th>
|
|
287
|
+
<th>Your Answer</th>
|
|
288
|
+
<th>Correct</th>
|
|
289
|
+
<th>Result</th>
|
|
290
|
+
</tr>
|
|
291
|
+
</thead>
|
|
292
|
+
<tbody>
|
|
293
|
+
{resultsTable.map((r, i) => (
|
|
294
|
+
<tr key={i}>
|
|
295
|
+
<td style={styles.gmTableCell}>{r.round}</td>
|
|
296
|
+
<td style={styles.gmTableCell}>{r.answer || "—"}</td>
|
|
297
|
+
<td style={styles.gmTableCell}>{r.correct}</td>
|
|
298
|
+
<td style={styles.gmTableCell}>
|
|
299
|
+
{r.result === "correct"
|
|
300
|
+
? "✔ Correct"
|
|
301
|
+
: r.result === "almost"
|
|
302
|
+
? "◐ Almost (0.5)"
|
|
303
|
+
: "✘ Wrong"}
|
|
304
|
+
</td>
|
|
305
|
+
</tr>
|
|
306
|
+
))}
|
|
307
|
+
</tbody>
|
|
308
|
+
</table>
|
|
309
|
+
<div style={{ display: "flex", gap: 12, marginTop: 24 }}>
|
|
310
|
+
<button style={styles.gmButton} onClick={startGame}>
|
|
311
|
+
🔁 Play again
|
|
312
|
+
</button>
|
|
313
|
+
<button style={styles.gmButton} onClick={exitGame}>
|
|
314
|
+
⬅️ Choose theme
|
|
315
|
+
</button>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
)}
|
|
377
319
|
|
|
378
|
-
{
|
|
379
|
-
<div
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
<
|
|
420
|
-
|
|
421
|
-
alt={file.name}
|
|
320
|
+
{started && !finished && (
|
|
321
|
+
<div style={styles.gmGameLayout}>
|
|
322
|
+
<div
|
|
323
|
+
style={{
|
|
324
|
+
minHeight: 160,
|
|
325
|
+
display: "flex",
|
|
326
|
+
flexDirection: "column",
|
|
327
|
+
justifyContent: "center",
|
|
328
|
+
alignItems: "center",
|
|
329
|
+
}}
|
|
330
|
+
>
|
|
331
|
+
{phase === "ready" && (
|
|
332
|
+
<>
|
|
333
|
+
<h1 style={{ ...styles.gmHeadline1, color: "#ec4c44" }}>GET READY</h1>
|
|
334
|
+
<div style={styles.gmHourglass}>⏳</div>
|
|
335
|
+
</>
|
|
336
|
+
)}
|
|
337
|
+
{phase === "memorize" && (
|
|
338
|
+
<p style={{ ...styles.gmBodyM, color: "#10b981" }}>
|
|
339
|
+
MEMORIZE ({memorizeTime})
|
|
340
|
+
</p>
|
|
341
|
+
)}
|
|
342
|
+
{phase === "guess" && !answered && (
|
|
343
|
+
<p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>
|
|
344
|
+
)}
|
|
345
|
+
</div>
|
|
346
|
+
|
|
347
|
+
{phase !== "ready" && (
|
|
348
|
+
<div
|
|
349
|
+
style={{
|
|
350
|
+
...styles.gmGrid,
|
|
351
|
+
gridTemplateColumns: isMobile ? "repeat(2, 1fr)" : "repeat(3, 210px)",
|
|
352
|
+
gridAutoRows: isMobile ? "150px" : "210px",
|
|
353
|
+
gap: isMobile ? "12px" : "20px",
|
|
354
|
+
justifyItems: "center",
|
|
355
|
+
}}
|
|
356
|
+
>
|
|
357
|
+
{files.map((file, i) => {
|
|
358
|
+
const isHidden =
|
|
359
|
+
hiddenIndex === i && phase === "guess" && !answered;
|
|
360
|
+
return (
|
|
361
|
+
<div
|
|
362
|
+
key={i}
|
|
422
363
|
style={{
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
364
|
+
...styles.gmCard,
|
|
365
|
+
...(result === "correct" && hiddenIndex === i
|
|
366
|
+
? styles.gmCorrect
|
|
367
|
+
: {}),
|
|
368
|
+
...(result === "wrong" && hiddenIndex === i
|
|
369
|
+
? styles.gmWrong
|
|
370
|
+
: {}),
|
|
426
371
|
}}
|
|
427
|
-
|
|
428
|
-
|
|
372
|
+
>
|
|
373
|
+
{!isHidden && (
|
|
374
|
+
<img
|
|
375
|
+
src={file.src}
|
|
376
|
+
alt={file.name}
|
|
377
|
+
style={{
|
|
378
|
+
width: "100%",
|
|
379
|
+
height: "100%",
|
|
380
|
+
objectFit: "cover",
|
|
381
|
+
}}
|
|
382
|
+
/>
|
|
383
|
+
)}
|
|
384
|
+
</div>
|
|
385
|
+
);
|
|
386
|
+
})}
|
|
387
|
+
</div>
|
|
388
|
+
)}
|
|
389
|
+
|
|
390
|
+
<div style={{ marginTop: 16, height: 80 }}>
|
|
391
|
+
{phase === "guess" && !answered && (
|
|
392
|
+
<div>
|
|
393
|
+
<input
|
|
394
|
+
type="text"
|
|
395
|
+
placeholder="Type the missing word"
|
|
396
|
+
value={inputValue}
|
|
397
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
398
|
+
style={styles.gmInput}
|
|
399
|
+
/>
|
|
400
|
+
<button
|
|
401
|
+
style={{ ...styles.gmButton, marginLeft: 8 }}
|
|
402
|
+
onClick={checkAnswer}
|
|
403
|
+
disabled={animating}
|
|
404
|
+
>
|
|
405
|
+
{animating ? "..." : "Check"}
|
|
406
|
+
</button>
|
|
429
407
|
</div>
|
|
430
|
-
)
|
|
431
|
-
|
|
408
|
+
)}
|
|
409
|
+
{answered && (
|
|
410
|
+
<button style={styles.gmButton} onClick={nextRound}>
|
|
411
|
+
Next round
|
|
412
|
+
</button>
|
|
413
|
+
)}
|
|
414
|
+
</div>
|
|
432
415
|
</div>
|
|
433
416
|
)}
|
|
434
|
-
|
|
435
|
-
<div style={{ marginTop: 16, height: 80 }}>
|
|
436
|
-
{phase === "guess" && !answered && (
|
|
437
|
-
<div>
|
|
438
|
-
<input
|
|
439
|
-
type="text"
|
|
440
|
-
placeholder="Type the missing word"
|
|
441
|
-
value={inputValue}
|
|
442
|
-
onChange={(e) => setInputValue(e.target.value)}
|
|
443
|
-
style={styles.gmInput}
|
|
444
|
-
/>
|
|
445
|
-
<button
|
|
446
|
-
style={{ ...styles.gmButton, marginLeft: 8 }}
|
|
447
|
-
onClick={checkAnswer}
|
|
448
|
-
disabled={animating}
|
|
449
|
-
>
|
|
450
|
-
{animating ? "..." : "Check"}
|
|
451
|
-
</button>
|
|
452
|
-
</div>
|
|
453
|
-
)}
|
|
454
|
-
{answered && (
|
|
455
|
-
<button style={styles.gmButton} onClick={nextRound}>
|
|
456
|
-
Next round
|
|
457
|
-
</button>
|
|
458
|
-
)}
|
|
459
|
-
</div>
|
|
460
417
|
</div>
|
|
461
|
-
|
|
418
|
+
</div>
|
|
462
419
|
</div>
|
|
463
420
|
);
|
|
464
421
|
}
|