-
Notifications
You must be signed in to change notification settings - Fork 0
Implement UI screen creation features #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement UI screen creation features #6
Conversation
- Replace language dropdown with icon-based selection using Iconify - Add language icons for all supported programming languages (JS, PHP, Ruby, Java, Dart) - Implement level 1 problem cycling: stay on level 1 until all problems are solved - Update game button: show "Skip" initially, change to "Next" after first success - Remove unused home.tsx route
WalkthroughRemoves the Changes
Sequence Diagram(s)sequenceDiagram
participant U as User
participant Play as PlayRoute
participant Logic as LevelLogic
participant Btn as SkipNextButton
note over Play,Logic `#eef2ff`: initialize (lang, codeLanguage, usedIds, currentLevel)
U->>Play: Open play route
Play->>Logic: allLevelProblemsUsed(codeLanguage, currentLevel, usedIds)?
alt level not exhausted
Logic-->>Play: false
Play->>Btn: Render "Skip" (localized) when no issues found
Play->>Play: constrain next selection to same level
else level exhausted
Logic-->>Play: true
Play->>Logic: selectNextProblemWithLevelAdvance(...)
Logic-->>Play: nextProblem (may advance level or probe higher levels)
Play->>Btn: Render "Next" (localized) when issues found
end
U->>Play: report foundIssuesCount
Play->>Btn: update label/style accordingly
U->>Btn: click Skip/Next
Btn->>Play: call selectNextProblemWithLevelAdvance(...)
Play->>Play: update usedIds, set currentLevel = returned nextLevel
Play-->>U: render next problem or end game if none available
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/welcome/welcome.tsx (1)
89-129: Remove unused code.The
resourcesarray is defined but never referenced in the component. Dead code should be removed to improve maintainability.Apply this diff to remove the unused code:
- -const resources = [ - { - href: 'https://reactrouter.com/docs', - text: 'React Router Docs', - icon: ( - <svg - xmlns="http://www.w3.org/2000/svg" - width="24" - height="20" - viewBox="0 0 20 20" - fill="none" - className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300" - > - <path - d="M9.99981 10.0751V9.99992M17.4688 17.4688C15.889 19.0485 11.2645 16.9853 7.13958 12.8604C3.01467 8.73546 0.951405 4.11091 2.53116 2.53116C4.11091 0.951405 8.73546 3.01467 12.8604 7.13958C16.9853 11.2645 19.0485 15.889 17.4688 17.4688ZM2.53132 17.4688C0.951566 15.8891 3.01483 11.2645 7.13974 7.13963C11.2647 3.01471 15.8892 0.951453 17.469 2.53121C19.0487 4.11096 16.9854 8.73551 12.8605 12.8604C8.73562 16.9853 4.11107 19.0486 2.53132 17.4688Z" - strokeWidth="1.5" - strokeLinecap="round" - /> - </svg> - ), - }, - { - href: 'https://rmx.as/discord', - text: 'Join Discord', - icon: ( - <svg - xmlns="http://www.w3.org/2000/svg" - width="24" - height="20" - viewBox="0 0 24 20" - fill="none" - className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300" - > - <path - d="M15.0686 1.25995L14.5477 1.17423L14.2913 1.63578C14.1754 1.84439 14.0545 2.08275 13.9422 2.31963C12.6461 2.16488 11.3406 2.16505 10.0445 2.32014C9.92822 2.08178 9.80478 1.84975 9.67412 1.62413L9.41449 1.17584L8.90333 1.25995C7.33547 1.51794 5.80717 1.99419 4.37748 2.66939L4.19 2.75793L4.07461 2.93019C1.23864 7.16437 0.46302 11.3053 0.838165 15.3924L0.868838 15.7266L1.13844 15.9264C2.81818 17.1714 4.68053 18.1233 6.68582 18.719L7.18892 18.8684L7.50166 18.4469C7.96179 17.8268 8.36504 17.1824 8.709 16.4944L8.71099 16.4904C10.8645 17.0471 13.128 17.0485 15.2821 16.4947C15.6261 17.1826 16.0293 17.8269 16.4892 18.4469L16.805 18.8725L17.3116 18.717C19.3056 18.105 21.1876 17.1751 22.8559 15.9238L23.1224 15.724L23.1528 15.3923C23.5873 10.6524 22.3579 6.53306 19.8947 2.90714L19.7759 2.73227L19.5833 2.64518C18.1437 1.99439 16.6386 1.51826 15.0686 1.25995ZM16.6074 10.7755L16.6074 10.7756C16.5934 11.6409 16.0212 12.1444 15.4783 12.1444C14.9297 12.1444 14.3493 11.6173 14.3493 10.7877C14.3493 9.94885 14.9378 9.41192 15.4783 9.41192C16.0471 9.41192 16.6209 9.93851 16.6074 10.7755ZM8.49373 12.1444C7.94513 12.1444 7.36471 11.6173 7.36471 10.7877C7.36471 9.94885 7.95323 9.41192 8.49373 9.41192C9.06038 9.41192 9.63892 9.93712 9.6417 10.7815C9.62517 11.6239 9.05462 12.1444 8.49373 12.1444Z" - strokeWidth="1.5" - /> - </svg> - ), - }, -];
🧹 Nitpick comments (1)
app/welcome/welcome.tsx (1)
60-72: Add accessibility attributes to language selection buttons.The language selection buttons should include proper ARIA attributes to improve accessibility for screen reader users.
Apply this diff to add accessibility attributes:
<button key={item.value} type="button" onClick={() => setCodeLanguage(item.value as CodeLanguageOrAll)} + aria-label={`${t('label.select', lang)} ${item.label}`} + aria-pressed={codeLanguage === item.value} className={`flex flex-col items-center justify-center p-3 rounded-lg border-2 transition-all ${ codeLanguage === item.value ? 'border-sky-500 bg-sky-50 dark:bg-sky-900/30' : 'border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-800 hover:border-sky-300 dark:hover:border-sky-700' }`} >Note: This assumes
label.selectexists in your translations. If not, add it or use a hardcoded string.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
app/routes/$lang.$codeLanguage.play.tsx(3 hunks)app/routes/home.tsx(0 hunks)app/welcome/welcome.tsx(2 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (1)
- app/routes/home.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
app/welcome/welcome.tsx (2)
app/locales/index.ts (1)
t(21-24)app/problems/index.ts (1)
CodeLanguageOrAll(6-6)
app/routes/$lang.$codeLanguage.play.tsx (2)
app/problems/index.ts (2)
CodeLanguageOrAll(6-6)getProblems(58-66)app/locales/index.ts (1)
t(21-24)
🔇 Additional comments (5)
app/routes/$lang.$codeLanguage.play.tsx (3)
66-75: LGTM! Clean helper function for level progression.The
allLevel1ProblemsUsedhelper correctly determines when to advance from level 1 by checking if all level 1 problems have been used. The logic properly handles the case whereusedIdsmay contain problems from multiple levels.
220-235: LGTM! Level progression logic correctly implements PR objectives.The new level progression correctly implements the requirement to stay at level 1 until all level 1 problems are solved, then advance to level 2, and finally level 3. The logic is clear and handles all cases appropriately.
409-424: LGTM! Dynamic button behavior matches PR objectives.The Skip/Next button correctly changes its text and styling based on whether issues have been found, matching the PR requirement: "show 'Skip' initially, change to 'Next' after first success." The localization and conditional styling are properly implemented.
package.json (1)
19-19: Version 6.0.2 of@iconify/reactis valid and has no known security vulnerabilities.The verification confirms that version 6.0.2 exists on the npm registry as the latest available version, and no security advisories are currently reported for this package.
app/welcome/welcome.tsx (1)
52-58: All Iconify icon identifiers are valid and available.The icon identifiers mdi:code-braces, vscode-icons:file-type-js-official, vscode-icons:file-type-php, vscode-icons:file-type-ruby, vscode-icons:file-type-java, and vscode-icons:file-type-dartlang are all available via Iconify. No action required.
- Remove 'All' option from language selection
- Add Python to supported code languages
- Make language icons direct links to game (/{locale}/{language}/play)
- Remove START button - users click language icons directly
- Update route validation to include Python and remove 'all'
- Add Python translations to localization files
…sted - Add selectNextProblemWithLevelAdvance helper function - Automatically progress from level 1→2→3 when problems run out - Try next levels if current level has no available problems - Prevents "No problems available" error by advancing levels
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/routes/$lang.$codeLanguage.play.tsx (1)
419-423: Use localization function for "Next" label.The button label uses hardcoded strings ('Next' and '次へ') instead of the
t()localization function, which is inconsistent with the "Skip" label pattern.Add localization entries to both locale files:
app/locales/en.json:
"button.start": "Start", "button.skip": "Skip", + "button.next": "Next", "label.score": "Score",app/locales/ja.json:
"button.start": "スタート", "button.skip": "スキップ", + "button.next": "次へ", "label.score": "スコア",Then update the button label logic:
- {foundIssuesCount > 0 - ? lang === 'ja' - ? '次へ' - : 'Next' - : t('button.skip', lang)} + {foundIssuesCount > 0 ? t('button.next', lang) : t('button.skip', lang)}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
app/locales/en.json(1 hunks)app/locales/ja.json(1 hunks)app/problems/index.ts(1 hunks)app/routes/$lang.$codeLanguage.play.tsx(4 hunks)app/welcome/welcome.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/welcome/welcome.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
app/routes/$lang.$codeLanguage.play.tsx (2)
app/problems/index.ts (2)
CodeLanguageOrAll(6-6)getProblems(58-66)app/locales/index.ts (1)
t(21-24)
🔇 Additional comments (5)
app/locales/ja.json (1)
14-14: LGTM!The Python localization entry is properly formatted and consistent with other language entries.
app/locales/en.json (1)
14-14: LGTM!The Python localization entry is consistent with the Japanese locale and follows the established pattern.
app/routes/$lang.$codeLanguage.play.tsx (3)
36-36: LGTM!The Python language is correctly added to the validation array, consistent with the
CodeLanguagetype extension inapp/problems/index.ts.
66-75: LGTM!The helper function correctly determines if all level 1 problems for a given language have been used. The logic is sound and uses
Array.every()appropriately.
220-235: LGTM!The level progression logic correctly implements the requirement to stay at level 1 until all level 1 problems are solved. The use of
usedProblemIdsin the check is appropriate since the current problem is already included, ensuring accurate progression to level 2.
- Automatically end game when no more problems are available - Show game over screen instead of "No problems available" message - Improves user experience by providing proper game completion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
app/routes/$lang.$codeLanguage.play.tsx (2)
36-44: Consider narrowing the return type for clarity.The validation excludes
'all'from valid code languages, but the return type casts toCodeLanguageOrAll. While technically safe (sinceCodeLanguageis part of the union), it's semantically misleading—at runtime,codeLanguagewill never be'all'after this validation.Apply this diff to improve type accuracy:
return { lang: lang as SupportedLanguage, - codeLanguage: codeLanguage as CodeLanguageOrAll, + codeLanguage: codeLanguage as CodeLanguage, };Note: You may need to update function signatures downstream (e.g.,
allLevel1ProblemsUsed,selectNextProblemWithLevelAdvance) to acceptCodeLanguageinstead ofCodeLanguageOrAll, or add explicit runtime type guards when callinggetProblems.
438-454: Use consistent localization for button labels.The button label switches between "Next" and "Skip" based on
foundIssuesCount. However, "Next" uses inline localization (lines 449–451) while "Skip" usest('button.skip', lang)(line 452). This is inconsistent.Apply this diff to use a translation key for "Next":
{foundIssuesCount > 0 - ? lang === 'ja' - ? '次へ' - : 'Next' + ? t('button.next', lang) : t('button.skip', lang)}Ensure
button.nextis defined in your locale files (e.g.,app/locales/en.jsonandapp/locales/ja.json):{ "button.next": "Next" }{ "button.next": "次へ" }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/routes/$lang.$codeLanguage.play.tsx(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/routes/$lang.$codeLanguage.play.tsx (2)
app/problems/index.ts (3)
CodeLanguageOrAll(6-6)getProblems(58-66)Problem(20-26)app/locales/index.ts (1)
t(21-24)
🔇 Additional comments (3)
app/routes/$lang.$codeLanguage.play.tsx (3)
66-75: Function logic is correct.The implementation correctly checks whether all level 1 problems have been shown (tracked in
usedIds). Note that this checks "shown at least once" rather than "fully solved with all issues found"—which aligns with howusedProblemIdsis managed throughout the component.
261-280: Integration with new level progression logic looks correct.The refactoring properly uses
selectNextProblemWithLevelAdvanceto determine both the next problem and level, and updatesusedProblemIdsonly when a problem is available. The dependency array (line 281) correctly includesusedProblemIds.
77-116: Level 1 fallback logic is safe in practice, but other languages lack problem definitions.The original concern about bypassing the level 1 restriction has minimal risk given current data:
- JavaScript (only language with problems): 3 level 1 problems available
- When
allLevel1ProblemsUsed()returns false (not all used),selectRandomProblem()will find available level 1 problems- The fallback only triggers if no level 1 problem is available, which contradicts the false check
- In practice: edge case unlikely to occur with 3 available level 1 problems
However, a broader issue exists: Other languages (python, php, ruby, java, dart) have no problem files, yet the game supports them. The glob pattern in
app/problems/index.ts:27only loads JavaScript:'./javascript/level*/*.json'This means for any non-JavaScript language,
getProblems()returns an empty array, causingselectRandomProblem()to always return null regardless of level. The fallback advances through levels 2 and 3 (also null), leaving the game unable to select any problem.Recommendation: Either add problem definitions for other languages or restrict game language options to JavaScript only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/routes/$lang.$codeLanguage.play.tsx (1)
36-44: Consider refining the return type to match validation.The validation explicitly excludes
'all'and only accepts specific code languages, but the return type is cast toCodeLanguageOrAllwhich includes'all'. While this is type-safe, it's semantically misleading.Consider narrowing the type:
return { lang: lang as SupportedLanguage, - codeLanguage: codeLanguage as CodeLanguageOrAll, + codeLanguage: codeLanguage as Exclude<CodeLanguageOrAll, 'all'>, };Or update the type usage throughout the file to use
CodeLanguagedirectly where'all'is never valid.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/routes/$lang.$codeLanguage.play.tsx(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/routes/$lang.$codeLanguage.play.tsx (2)
app/problems/index.ts (3)
CodeLanguageOrAll(6-6)getProblems(58-66)Problem(20-26)app/locales/index.ts (1)
t(21-24)
🔇 Additional comments (3)
app/routes/$lang.$codeLanguage.play.tsx (3)
77-116: Well-structured level advancement logic.The function correctly implements the requirement to cycle through level 1 until all problems are used before advancing. The fallback logic (lines 104-113) gracefully handles exhausted problem pools by attempting higher levels.
261-272: Clean integration of level advancement logic.The updated skip handler correctly integrates the new level advancement function, properly managing state updates for both the problem and level, and gracefully handling the end-game scenario.
441-456: Improved button UX with dynamic styling and labels.The button now appropriately changes its appearance and label based on player progress, providing clear visual feedback. The styling emphasizes "Next" as a primary action when issues are found, encouraging continued play.
- Change glob from './javascript/level*/*.json' to support multiple languages - Pattern now matches: javascript, python, php, ruby, java, dart - Fixes inconsistency between CodeLanguage type and actual file imports - Allows future addition of problem files for other languages
- Replace level-specific logic with generic allLevelProblemsUsed function - Stay at current level until all problems of that level are exhausted - Only advance to next level after completing all problems - Fixes premature level advancement (level 2→3 after just 1 problem) - Ensures all 3 level 1 problems are played before advancing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/routes/$lang.$codeLanguage.play.tsx(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/routes/$lang.$codeLanguage.play.tsx (2)
app/problems/index.ts (3)
CodeLanguageOrAll(6-6)getProblems(59-67)Problem(20-26)app/locales/index.ts (1)
t(21-24)
🔇 Additional comments (3)
app/routes/$lang.$codeLanguage.play.tsx (3)
66-76: LGTM! Empty array issue correctly addressed.The
levelProblems.length > 0guard preventsArray.every()from returningtruefor empty arrays, ensuring that languages without problem definitions won't immediately advance levels.
78-113: LGTM! Level advancement logic is sound.The function correctly handles all edge cases:
- Advances levels only when all problems are exhausted
- Falls back to higher levels when current level has no available problems
- Returns
nullwhen no problems exist at any level, which is handled byhandleSkip(lines 267-270) to end the game
258-280: LGTM! handleSkip correctly integrates level advancement.The function properly uses
selectNextProblemWithLevelAdvanceand handles the end-of-game scenario when no more problems are available.
|
|
||
| // Validate code language parameter | ||
| const validCodeLanguages = ['all', 'javascript', 'php', 'ruby', 'java', 'dart']; | ||
| const validCodeLanguages = ['javascript', 'python', 'php', 'ruby', 'java', 'dart']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify Python problem definitions exist.
Per the past review, Python was added but lacked problem files, causing immediate level advancement. Since this was marked as addressed in commit 4ab40e7, please verify that Python problem definitions now exist to prevent the empty array issue from recurring.
🏁 Script executed:
#!/bin/bash
# Verify Python problem files exist and are loadable
echo "=== Checking for Python problem directories ==="
fd -t d "python" app/problems/
echo ""
echo "=== Checking for Python problem files ==="
fd -e json -e ts "." app/problems/python/ 2>/dev/null || echo "No Python problem files found"
echo ""
echo "=== Verifying problem files for all supported languages ==="
for lang in javascript python php ruby java dart; do
count=$(fd -e json -e ts "." "app/problems/$lang/" 2>/dev/null | wc -l)
echo "$lang: $count files"
doneLength of output: 272
Critical issue: Python (and other languages) lack problem definitions.
The verification reveals that Python has 0 problem files in app/problems/python/, despite being added to validCodeLanguages on line 36. The past review noted this exact issue was addressed, but the filesystem scan confirms it was not—only JavaScript has 8 problem files, while Python, PHP, Ruby, Java, and Dart all have 0 files.
The workaround in allLevelProblemsUsed() (lines 66–76) masks the symptom by advancing levels when problems are empty, but the root cause persists: players selecting these languages encounter no problems at all. This renders the game unplayable for 5 of the 6 supported languages.
Either provide problem definitions for all listed languages or remove unsupported languages from validCodeLanguages.
🤖 Prompt for AI Agents
In app/routes/$lang.$codeLanguage.play.tsx around line 36, validCodeLanguages
includes ['javascript', 'python', 'php', 'ruby', 'java', 'dart'] but the
repository only contains problem files for JavaScript, so players selecting
Python, PHP, Ruby, Java or Dart get no problems; fix by either (A) adding the
missing problem definition files into app/problems/{language}/ for each listed
language (ensure directory names match the language keys and include the same
level file structure and exports as the JavaScript problems), or (B) remove the
unsupported language keys from validCodeLanguages so only languages with
existing problem sets are selectable; after making the change, run the
filesystem check and update any related logic (e.g., allLevelProblemsUsed) to
avoid fallback level-skipping behavior masking missing data.
| {/* Skip/Next button */} | ||
| <div className="px-4 py-3 border-t border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900"> | ||
| <button | ||
| onClick={handleSkip} | ||
| className="w-full py-2 rounded-md bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 transition text-sm font-medium" | ||
| className={`w-full py-2 rounded-md transition text-sm font-medium ${ | ||
| foundIssuesCount > 0 | ||
| ? 'bg-sky-500 text-white hover:bg-sky-600 active:bg-sky-700' | ||
| : 'bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600' | ||
| }`} | ||
| > | ||
| {t('button.skip', lang)} | ||
| {foundIssuesCount > 0 | ||
| ? lang === 'ja' | ||
| ? '次へ' | ||
| : 'Next' | ||
| : t('button.skip', lang)} | ||
| </button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use localization function for "Next" button text.
The "Next" button text is hardcoded in both languages, while the "Skip" text uses t('button.skip', lang). This creates an inconsistent localization pattern.
Apply this diff to use consistent localization:
- {foundIssuesCount > 0
- ? lang === 'ja'
- ? '次へ'
- : 'Next'
- : t('button.skip', lang)}
+ {foundIssuesCount > 0 ? t('button.next', lang) : t('button.skip', lang)}Note: Ensure button.next key exists in app/locales/en.json and app/locales/ja.json.
🤖 Prompt for AI Agents
In app/routes/$lang.$codeLanguage.play.tsx around lines 438-453, the "Next"
button text is hardcoded for English and Japanese instead of using the
localization helper; replace the inline conditional that returns '次へ' or 'Next'
with t('button.next', lang) so the component consistently uses the translation
function, and verify that app/locales/en.json and app/locales/ja.json contain
the "button.next" key (add translations if missing).
- Change feedback message from document flow to fixed positioning - Position at top center of screen (top-20 left-1/2 -translate-x-1/2) - Add z-50 to ensure it appears above all content - Add shadow and rounded corners for better visual appeal - Add slide-in animation for smooth appearance - Prevents code area from shifting when feedback appears/disappears - Fixes accidental taps caused by layout shifts
…tate - Merge usedProblemIds into GameState to avoid state synchronization issues - Previously, usedProblemIds was a separate state causing race conditions - When handleSkip was called, it used stale usedProblemIds values - This caused premature level advancement before all problems were solved - Now usedProblemIds is part of gameState, ensuring consistency - Use prev.usedProblemIds in setGameState for accurate state updates - Remove dependency on external usedProblemIds state
Summary by CodeRabbit
New Features
Improvements
Removed
Chores
✏️ Tip: You can customize this high-level summary in your review settings.