Skip to content

Join Room button turns green when room code is entered#343

Open
Abhishek2005-ard wants to merge 24 commits into
AOSSIE-Org:mainfrom
Abhishek2005-ard:fix-join-room-ui
Open

Join Room button turns green when room code is entered#343
Abhishek2005-ard wants to merge 24 commits into
AOSSIE-Org:mainfrom
Abhishek2005-ard:fix-join-room-ui

Conversation

@Abhishek2005-ard

@Abhishek2005-ard Abhishek2005-ard commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Summary
Improves the Join Room UI by changing the button color to green when a room code is entered. This gives clear visual feedback to users that they can now join the room.

Problem
Previously, the Join Room button remained in the default grey color even after entering a room code.
This made it unclear whether the action was available or if the input was detected.

Solution
Added conditional styling to the Join Room button based on the roomCode state.

When roomCode is empty → button remains grey
When roomCode is entered → button turns green

This improves the user experience and provides clear visual feedback.

Changes
Updated frontend/src/components/DebatePopup.tsx
Added conditional button styling based on roomCode

Before Fix
The Join Room button stays grey even after entering a room code.
Before Fix

After Fix
The Join Room button turns green when a room code is entered.
After Fix

Impact
Improves UI clarity
Better user feedback
Small frontend-only change

close #342

Summary by CodeRabbit

  • New Features

    • ELO rating changes now show correctly in debate history.
  • Bug Fixes

    • Join button disabled when room code is empty to prevent invalid joins.
    • Judgment parsing improved with clearer error handling for malformed results.
  • Improvements

    • Speech recognition: robust auto-restart and better permission handling.
    • Dark-mode UI polish across debate room; high-contrast accessibility support.
    • Admin dashboard now requires authentication; protected routing reorganized.
  • UI/Style

    • Header styling unified with design tokens.
    • About page uses dynamic current year.

@coderabbitai

coderabbitai Bot commented Mar 6, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds EloChange tracking to debate transcripts (model, marshal, service, and controller call sites), updates profile to surface stored eloChange, introduces admin-protected routing, improves speech-recognition robustness, tweaks UI styling and high-contrast support, enables a disabled Join button when room code is empty, and switches DebateRoom judgment parsing to JSON5.

Changes

Cohort / File(s) Summary
ELO / Transcript Backend
backend/models/transcript.go, backend/services/transcriptservice.go, backend/controllers/transcript_controller.go, backend/controllers/debatevsbot_controller.go, backend/controllers/profile_controller.go
Added EloChange float64 to SavedDebateTranscript and its MarshalJSON; extended SaveDebateTranscript(..., eloChange float64) and updated all call sites to pass an eloChange value (including new 0.0 args in some controllers). Profile now reads transcript.EloChange.
Debate judgment & room UI
frontend/src/Pages/DebateRoom.tsx, frontend/src/components/DebatePopup.tsx, frontend/src/components/JudgementPopup.tsx
Replaced JSON.parse with JSON5 parsing for judgments, added concurrency guard for judging, navigate to /startDebate on popup close, added disabled styling for Join button when room code empty, and used botDesc in JudgementPopup.
Routing & Admin protection
frontend/src/App.tsx, frontend/src/components/ProtectedRoute.tsx
Introduced AdminProtectedRoute that checks localStorage for admin credentials; restructured protected routes and wrapped admin/dashboard with the admin-protected component.
Speech recognition
frontend/src/utils/speechTest.ts
Reworked speech recognition: async start(), permission checks, auto-restart with delay, restart/stop guards and improved error handling/logging; changed test helper to async.
Styling, tokens & accessibility
frontend/src/components/Header.tsx, frontend/src/components/ui/select.tsx, frontend/src/index.css, frontend/tailwind.config.js
Migrated to design-system color tokens, added high-contrast CSS variables and a Tailwind high-contrast variant, and updated SelectItem state styling.
Small frontend adjustments
frontend/src/Pages/About.tsx, frontend/src/Pages/StartDebate.tsx, frontend/src/Pages/TeamDebateRoom.tsx, frontend/src/components/Matchmaking.tsx
Dynamic copyright year, destructured auth isAuthenticated usage, minor formatting and whitespace changes, and small UI prop usage change.
Deps / package
frontend/package.json
Added json5 dependency (^2.2.3) to support relaxed JSON parsing for judgment results.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  %% Actors
  participant Client as Client (frontend)
  participant Controller as Controller (backend)
  participant Service as TranscriptService
  participant DB as Database

  Client->>Controller: Submit transcript + rating changes
  Controller->>Service: SaveDebateTranscript(..., eloChange)
  Service->>DB: Upsert SavedDebateTranscript (includes EloChange)
  DB-->>Service: OK
  Service-->>Controller: OK / error
  Controller-->>Client: Response (success/failure)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through structs and routes tonight,

EloChange tucked in JSON just right,
Admin doors now guard the golden key,
Speech restarts hum — the mic sings free,
A join-button glows — hop in, delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning PR title narrowly describes a single UI component change but omits other substantial changes including backend ELO tracking, routing restructuring, JSON5 parsing, and speech recognition enhancements. Revise title to reflect the full scope of changes, such as 'Add ELO tracking to debate transcripts and improve UI/UX across multiple components', or create separate focused PRs for different concerns.
Out of Scope Changes check ⚠️ Warning Multiple out-of-scope changes detected: backend ELO/rating persistence (transcript.go, transcriptservice.go), routing architecture restructuring (App.tsx), JSON5 parsing (DebateRoom.tsx), speech recognition enhancements (speechTest.ts), high-contrast accessibility features (index.css, select.tsx, tailwind.config.js), and various unrelated refactoring. Separate changes into focused PRs: one for the Join Room button UI (addressing #342), another for ELO tracking backend changes, another for routing updates, and separate PRs for other features like JSON5 parsing and accessibility improvements.
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed PR successfully implements the linked issue #342 requirement by adding conditional styling to the Join Room button that changes to green when room code is entered.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 5

🧹 Nitpick comments (4)
frontend/src/components/Matchmaking.tsx (1)

27-28: Inconsistent with PR objectives: unrelated whitespace-only change.

The PR objectives state this PR should modify frontend/src/components/DebatePopup.tsx to add conditional styling for the Join Room button based on roomCode state. However, this file (Matchmaking.tsx) contains only whitespace formatting changes (two blank lines) and is unrelated to the Join Room feature.

Additionally, the high-level AI summary mentions "addresses the room code validation issue by disabling the join button when no valid code is entered," but this file contains no such logic.

Recommendation: Consider whether this whitespace-only change should be part of this PR, or if it was included unintentionally. If the Join Room button changes are in DebatePopup.tsx, ensure that file is included in the review.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/Matchmaking.tsx` around lines 27 - 28, This change
introduces only whitespace in the Matchmaking component which is unrelated to
the PR objective of adding conditional styling to the Join Room button; revert
the whitespace-only edits in the Matchmaking component (Matchmaking) and ensure
the actual functional changes are present in the DebatePopup component logic
that manages roomCode and the Join Room button (e.g., the roomCode state and the
button render/disabled/class logic in DebatePopup). Remove the accidental
whitespace-only commit from this PR or move it to a separate formatting-only PR,
and confirm DebatePopup contains the conditional styling/disabled behavior for
the Join Room button based on roomCode before marking this PR ready.
frontend/src/App.tsx (1)

111-112: Minor: Inconsistent closing tag indentation.

The </Routes> closing tag appears to be misaligned with its opening tag.

♻️ Suggested fix
         <Route path="*" element={<Navigate to="/" replace />} />
-  </Routes>
+      </Routes>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/App.tsx` around lines 111 - 112, The closing </Routes> tag in
App.tsx is misindented relative to its opening <Routes> block; fix by aligning
the </Routes> indentation to match the opening <Routes> tag so the <Route
path="*" element={<Navigate to="/" replace />} /> line and the </Routes> tag
share the same indentation level, ensuring consistent JSX formatting for the
Routes, Route and Navigate elements.
frontend/src/utils/speechTest.ts (1)

62-72: Auto-restart timeout stored but type may cause issues on cleanup.

The restartTimeout is typed as number | null, which is correct for window.setTimeout. However, if this code runs in a Node.js environment (e.g., SSR or tests), setTimeout returns a Timeout object, not a number. Consider using ReturnType<typeof setTimeout> for cross-environment compatibility.

♻️ Optional fix for type safety
-  private restartTimeout: number | null = null;
+  private restartTimeout: ReturnType<typeof setTimeout> | null = null;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/utils/speechTest.ts` around lines 62 - 72, The restartTimeout
field currently typed as number | null can break in Node/SSR where setTimeout
returns a Timeout object; change the type of restartTimeout to ReturnType<typeof
setTimeout> | null (and update any uses like clearTimeout(this.restartTimeout)
to accept that type) so the window.setTimeout call and cleanup work across
environments; update the declaration of restartTimeout and any TypeScript
annotations in the class/method that uses this.restartTimeout (the block that
calls this.restartTimeout = window.setTimeout(...) and the cleanup that clears
it).
frontend/src/Pages/DebateRoom.tsx (1)

811-814: Inconsistent dark mode styling between panels.

The bot section (Line 767) includes dark mode classes (dark:bg-zinc-900 border border-gray-200 dark:border-zinc-700), but the user section retains only light mode styling. This creates visual inconsistency in dark mode.

♻️ Suggested fix to add dark mode classes to user section
         <div
           className={`relative w-full md:w-1/2 ${
             !state.isBotTurn && !state.isDebateEnded ? "animate-glow" : ""
-          } bg-white border border-gray-200 shadow-md h-[540px] flex flex-col`}
+          } bg-white dark:bg-zinc-900 border border-gray-200 dark:border-zinc-700 shadow-md h-[540px] flex flex-col`}
         >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/Pages/DebateRoom.tsx` around lines 811 - 814, The user panel div
that renders when !state.isBotTurn (the JSX block with className starting
"relative w-full md:w-1/2 ... bg-white border border-gray-200 shadow-md
h-[540px]") lacks dark-mode classes, causing inconsistent styling with the bot
panel; update that component's className (the user panel div) to mirror the bot
panel by adding dark:bg-zinc-900 and dark:border-zinc-700 (and any other
dark-variants used by the bot panel) so the panel background and border switch
correctly in dark mode.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/services/transcriptservice.go`:
- Around line 181-207: The transcript saves pass a hardcoded 0.0 for Elo change
causing transcript.EloChange to remain zero; change the flow so UpdateRatings()
runs (or compute the rating deltas) before calling SaveDebateTranscript and pass
the actual deltas (use debateRecord.RatingChange for the "forUser" save and
opponentRecord.RatingChange for the "againstUser" save) into the corresponding
SaveDebateTranscript calls instead of 0.0 so transcript.EloChange reflects real
rating changes.
- Around line 667-668: SaveDebateTranscript's signature gained a trailing
eloChange parameter but two callers still pass only eight arguments; update the
call sites that invoke SaveDebateTranscript in transcript_controller and
debatevsbot_controller to supply the new eloChange float64 argument (compute and
pass the actual Elo delta available in their context or, if not applicable yet,
pass 0.0) so the calls match the function signature; ensure you reference the
SaveDebateTranscript call expressions and propagate any needed local variable or
computation that yields the eloChange value.

In `@frontend/src/components/DebatePopup.tsx`:
- Around line 128-135: The button enables based on roomCode.trim(), but
handleJoinRoom still uses the raw roomCode, causing routes like "/room/ ABC123 "
to be generated; update handleJoinRoom to compute a normalized value (e.g.,
const normalized = roomCode.trim()) and use that for validation and routing
(return early if normalized is empty, then navigate using normalized), ensuring
any route generation or API calls reference normalized instead of raw roomCode
and keeping the existing disabled logic in sync.

In `@frontend/src/components/ProtectedRoute.tsx`:
- Around line 7-13: AdminProtectedRoute is reading
localStorage.getItem("adminData") but AdminSignup.tsx stores the admin payload
under "admin", causing the guard to always redirect; update AdminProtectedRoute
to check the same key used when saving (replace
localStorage.getItem("adminData") with localStorage.getItem("admin")) or
alternatively change AdminSignup.tsx to set "adminData"—ensure the keys for
admin payload (admin or adminData) and the token (adminToken) match across
AdminSignup.tsx and AdminProtectedRoute so the check in AdminProtectedRoute
succeeds.

In `@frontend/tailwind.config.js`:
- Around line 65-68: The high-contrast Tailwind variant added via
addVariant('high-contrast', '@media (prefers-contrast: more)') assumes CSS
custom properties are available, but --hc-hover-bg and --hc-hover-text are only
defined under a .high-contrast class in frontend/src/index.css; move or
duplicate those custom property definitions into a `@media` (prefers-contrast:
more) block in frontend/src/index.css (or add both the media query and the
.high-contrast selector) so that the properties are defined when the media query
activates without requiring the .high-contrast class.

---

Nitpick comments:
In `@frontend/src/App.tsx`:
- Around line 111-112: The closing </Routes> tag in App.tsx is misindented
relative to its opening <Routes> block; fix by aligning the </Routes>
indentation to match the opening <Routes> tag so the <Route path="*"
element={<Navigate to="/" replace />} /> line and the </Routes> tag share the
same indentation level, ensuring consistent JSX formatting for the Routes, Route
and Navigate elements.

In `@frontend/src/components/Matchmaking.tsx`:
- Around line 27-28: This change introduces only whitespace in the Matchmaking
component which is unrelated to the PR objective of adding conditional styling
to the Join Room button; revert the whitespace-only edits in the Matchmaking
component (Matchmaking) and ensure the actual functional changes are present in
the DebatePopup component logic that manages roomCode and the Join Room button
(e.g., the roomCode state and the button render/disabled/class logic in
DebatePopup). Remove the accidental whitespace-only commit from this PR or move
it to a separate formatting-only PR, and confirm DebatePopup contains the
conditional styling/disabled behavior for the Join Room button based on roomCode
before marking this PR ready.

In `@frontend/src/Pages/DebateRoom.tsx`:
- Around line 811-814: The user panel div that renders when !state.isBotTurn
(the JSX block with className starting "relative w-full md:w-1/2 ... bg-white
border border-gray-200 shadow-md h-[540px]") lacks dark-mode classes, causing
inconsistent styling with the bot panel; update that component's className (the
user panel div) to mirror the bot panel by adding dark:bg-zinc-900 and
dark:border-zinc-700 (and any other dark-variants used by the bot panel) so the
panel background and border switch correctly in dark mode.

In `@frontend/src/utils/speechTest.ts`:
- Around line 62-72: The restartTimeout field currently typed as number | null
can break in Node/SSR where setTimeout returns a Timeout object; change the type
of restartTimeout to ReturnType<typeof setTimeout> | null (and update any uses
like clearTimeout(this.restartTimeout) to accept that type) so the
window.setTimeout call and cleanup work across environments; update the
declaration of restartTimeout and any TypeScript annotations in the class/method
that uses this.restartTimeout (the block that calls this.restartTimeout =
window.setTimeout(...) and the cleanup that clears it).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 03cae5e6-0e79-4b79-a094-152e03833d6d

📥 Commits

Reviewing files that changed from the base of the PR and between 90fb523 and 2cd928d.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • backend/controllers/debatevsbot_controller.go
  • backend/controllers/profile_controller.go
  • backend/models/transcript.go
  • backend/services/transcriptservice.go
  • frontend/package.json
  • frontend/src/App.tsx
  • frontend/src/Pages/About.tsx
  • frontend/src/Pages/DebateRoom.tsx
  • frontend/src/Pages/StartDebate.tsx
  • frontend/src/Pages/TeamDebateRoom.tsx
  • frontend/src/components/DebatePopup.tsx
  • frontend/src/components/Header.tsx
  • frontend/src/components/JudgementPopup.tsx
  • frontend/src/components/Matchmaking.tsx
  • frontend/src/components/ProtectedRoute.tsx
  • frontend/src/components/ui/select.tsx
  • frontend/src/index.css
  • frontend/src/utils/speechTest.ts
  • frontend/tailwind.config.js

Comment thread backend/services/transcriptservice.go
Comment thread backend/services/transcriptservice.go
Comment thread frontend/src/components/DebatePopup.tsx
Comment thread frontend/src/components/ProtectedRoute.tsx
Comment thread frontend/tailwind.config.js

@coderabbitai coderabbitai Bot 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.

♻️ Duplicate comments (1)
backend/services/transcriptservice.go (1)

181-207: ⚠️ Potential issue | 🔴 Critical

Compute ratings before these transcript saves.

Lines 190 and 206 read debateRecord / opponentRecord before Line 222 creates them, and Line 197’s err = err = ... is invalid Go syntax. Move UpdateRatings(...) ahead of both SaveDebateTranscript(...) calls, then pass the returned RatingChange values into each save.

Proposed fix
-				// Save transcript for "for" user
-				err = SaveDebateTranscript(
-				forUser.ID,
-				forUser.Email,
-				"user_vs_user",
-				topic,
-				againstUser.Email,
-				resultFor,
-				[]models.Message{},
-				forSubmission.Transcripts,
-				debateRecord.RatingChange, 
-			)
-			if err != nil {
-				log.Println("Error saving transcript for user:", err)
-			}
-
-			// Save transcript for "against" user
-			err = err = SaveDebateTranscript(
-				againstUser.ID,
-				againstUser.Email,
-				"user_vs_user",
-				topic,
-				forUser.Email,
-				resultAgainst,
-				[]models.Message{},
-				againstSubmission.Transcripts,
-				opponentRecord.RatingChange,
-			)
-			if err != nil {
-				log.Println("Error saving transcript for opponent:", err)
-			}
-
 				// Update ratings based on the result
 				outcomeFor := 0.5
 				switch strings.ToLower(resultFor) {
 				case "win":
 					outcomeFor = 1.0
@@
 				debateRecord, opponentRecord, ratingErr := UpdateRatings(forUser.ID, againstUser.ID, outcomeFor, time.Now())
 				if ratingErr != nil {
 				} else {
+					err = SaveDebateTranscript(
+						forUser.ID,
+						forUser.Email,
+						"user_vs_user",
+						topic,
+						againstUser.Email,
+						resultFor,
+						[]models.Message{},
+						forSubmission.Transcripts,
+						debateRecord.RatingChange,
+					)
+					if err != nil {
+						log.Println("Error saving transcript for user:", err)
+					}
+
+					err = SaveDebateTranscript(
+						againstUser.ID,
+						againstUser.Email,
+						"user_vs_user",
+						topic,
+						forUser.Email,
+						resultAgainst,
+						[]models.Message{},
+						againstSubmission.Transcripts,
+						opponentRecord.RatingChange,
+					)
+					if err != nil {
+						log.Println("Error saving transcript for opponent:", err)
+					}
+
 					debateRecord.Topic = topic
 					debateRecord.Result = resultFor
 					opponentRecord.Topic = topic
#!/bin/bash
# Verify that the Elo deltas are referenced before they are declared and that the
# second save call contains invalid syntax.
rg -n -C2 'debateRecord\.RatingChange|opponentRecord\.RatingChange|err = err = SaveDebateTranscript|UpdateRatings\(' backend/services/transcriptservice.go
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/services/transcriptservice.go` around lines 181 - 207, The code calls
SaveDebateTranscript using debateRecord.RatingChange and
opponentRecord.RatingChange before those rating changes are computed and also
has an invalid assignment "err = err = SaveDebateTranscript"; move the
UpdateRatings(...) call (the function that returns debateRecord and
opponentRecord or their RatingChange values) to run before both
SaveDebateTranscript(...) calls, capture its returned RatingChange values (e.g.,
debateDelta, opponentDelta) and pass those into the two SaveDebateTranscript
calls instead of debateRecord.RatingChange/opponentRecord.RatingChange, and fix
the duplicated assignment by using a single "err =" when assigning the
SaveDebateTranscript result.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@backend/services/transcriptservice.go`:
- Around line 181-207: The code calls SaveDebateTranscript using
debateRecord.RatingChange and opponentRecord.RatingChange before those rating
changes are computed and also has an invalid assignment "err = err =
SaveDebateTranscript"; move the UpdateRatings(...) call (the function that
returns debateRecord and opponentRecord or their RatingChange values) to run
before both SaveDebateTranscript(...) calls, capture its returned RatingChange
values (e.g., debateDelta, opponentDelta) and pass those into the two
SaveDebateTranscript calls instead of
debateRecord.RatingChange/opponentRecord.RatingChange, and fix the duplicated
assignment by using a single "err =" when assigning the SaveDebateTranscript
result.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b733582-d787-4a11-99a6-ae6aed74dd7d

📥 Commits

Reviewing files that changed from the base of the PR and between 2cd928d and 1554eb4.

📒 Files selected for processing (4)
  • backend/controllers/debatevsbot_controller.go
  • backend/controllers/transcript_controller.go
  • backend/services/transcriptservice.go
  • frontend/src/index.css
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/index.css
  • backend/controllers/debatevsbot_controller.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Join Room button does not indicate valid room code

1 participant