Skip to content

refactor: Convert several components to functional components#196

Open
ShrimpCryptid wants to merge 5 commits into
developmentfrom
refactor/function-components
Open

refactor: Convert several components to functional components#196
ShrimpCryptid wants to merge 5 commits into
developmentfrom
refactor/function-components

Conversation

@ShrimpCryptid

Copy link
Copy Markdown
Owner

Refactors several class components into functional components, and adds Prettier to the project.

@ShrimpCryptid ShrimpCryptid requested a review from Copilot April 14, 2026 05:49
@ShrimpCryptid ShrimpCryptid self-assigned this Apr 14, 2026
@ShrimpCryptid ShrimpCryptid added the frontend Pull requests that update frontend Javascript/Typescript code label Apr 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors parts of the frontend UI from legacy class-based JavaScript components into TypeScript functional components, while introducing a typed DeckType enum and adding Prettier as a dev dependency.

Changes:

  • Replace Deck, Board, and MaxLengthTextField JS class components with TSX functional equivalents.
  • Add DeckType enum to the shared frontend types and update App to use it when rendering decks.
  • Add Prettier to frontend devDependencies and update lockfile; remove a backend debug System.out.println.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
frontend/src/util/MaxLengthTextField.tsx New TSX functional MaxLengthTextField implementation with typed props and input normalization.
frontend/src/util/MaxLengthTextField.js Removes legacy JS class component version.
frontend/src/types/game.ts Adds DeckType enum for typed deck selection.
frontend/src/board/Deck.tsx New TSX functional Deck with animation logic using hooks/state.
frontend/src/board/Deck.js Removes legacy JS class component version.
frontend/src/board/Board.tsx New TSX functional Board implementation and helpers.
frontend/src/board/Board.js Removes legacy JS class component version.
frontend/src/App.tsx Imports/uses DeckType and applies formatting updates consistent with Prettier-style output.
frontend/package.json Adds Prettier to devDependencies.
frontend/package-lock.json Adds Prettier package resolution/metadata.
backend/src/main/java/server/util/GameToJSONConverter.java Removes debug console output.
Files not reviewed (1)
  • frontend/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,94 @@
import React, { Component } from "react";

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Component is imported but never used in this functional component. This will trigger lint/TS "unused import" warnings; remove it from the import list.

Suggested change
import React, { Component } from "react";
import React from "react";

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +59
* @effects Calls {@code this.props.onChange} with the modified text of the event, where any whitespace (' ' or '\t') from
* the front of the text is removed and the text length is trimmed to be {@literal <=} {@code this.props.maxLength}
*/
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
let text = event.target.value;
text = collapseSpaces(text.trim());
if (props.maxLength !== -1) {

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says only leading whitespace is removed, but text.trim() removes both leading and trailing whitespace. Either update the doc to match the behavior or use trimStart() (or equivalent) if trailing whitespace should be preserved.

Copilot uses AI. Check for mistakes.
>
<img
id="board"
src={getFascistBoard(props.numFascistPolicies)}

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getFascistBoard is being called with props.numFascistPolicies, but the helper (and its doc) expects numPlayers. This will select the wrong Fascist board image whenever policy count differs from player count. Pass props.numPlayers instead.

Suggested change
src={getFascistBoard(props.numFascistPolicies)}
src={getFascistBoard(props.numPlayers)}

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +95
useEffect(() => {
if (lastCardCountRef.current === props.cardCount || isPlayingAnimation) {
return;
}
// Number of cards has changed, play an animation.
setIsPlayingAnimation(true);
let perCardDelayMs = 150;
let totalDelayMs = 0;
const oldCount = lastCardCountRef.current;
const newCount = props.cardCount;

if (newCount < oldCount) {
// Cards were taken out of the deck
const difference = oldCount - newCount;
perCardDelayMs = difference <= 3 ? 350 : 150;
for (let i = oldCount - 1; i >= newCount; i--) {
setTimeout(() => {
animateCardVisibility(i, false);
}, totalDelayMs);
totalDelayMs += perCardDelayMs;
}
} else {
// Cards were added to the deck
perCardDelayMs = 150;
for (let i = oldCount; i < newCount; i++) {
setTimeout(() => {
animateCardVisibility(i, true);
}, totalDelayMs);
totalDelayMs += perCardDelayMs;
}
}
// Reset animation state after all animations complete.
setTimeout(() => {
setIsPlayingAnimation(false);
}, totalDelayMs);
lastCardCountRef.current = props.cardCount;

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This effect schedules multiple setTimeout calls but never cancels them on unmount or when a new animation supersedes an in-flight one. That can cause state updates after unmount (React warning) and unnecessary work. Track timeout IDs (e.g., in a ref) and clear them in the effect cleanup before scheduling new ones.

Copilot uses AI. Check for mistakes.
Comment on lines +125 to +126
<p id={"deck-card-count"}>{props.cardCount}</p>
<img

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The displayed card count is now always props.cardCount, so it will jump immediately even though the card hide/show animation is staggered. Previously the UI count updated in sync with each card transition. If that behavior is still desired, keep an internal "animated" count and update it alongside the per-card timeouts.

Copilot uses AI. Check for mistakes.
<p id={"deck-card-count"}>{props.cardCount}</p>
<img
id={"deck-base"}
src={props.deckType === "DRAW" ? DrawDeck : DiscardDeck}

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deckType is a DeckType enum, but the render logic compares it to a string literal ("DRAW"). Use DeckType.DRAW/DeckType.DISCARD for type safety and to avoid silent breakage if the enum values change.

Suggested change
src={props.deckType === "DRAW" ? DrawDeck : DiscardDeck}
src={props.deckType === DeckType.DRAW ? DrawDeck : DiscardDeck}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend Pull requests that update frontend Javascript/Typescript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants