Skip to content
Open
102 changes: 52 additions & 50 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,57 +50,59 @@ function AppRoutes() {
}
const { isAuthenticated } = authContext;
return (
<Routes>
{/* Public routes */}
<Route
path='/'
element={
isAuthenticated ? <Navigate to='/startDebate' replace /> : <Home />
}
/>
<Route path='/auth' element={<Authentication />} />
<Route path='/admin/login' element={<AdminSignup />} />
<Route path='/admin/dashboard' element={<AdminDashboard />} />
{/* Protected routes with layout */}
<Route element={<ProtectedRoute />}>
<Route path='/' element={<Layout />}>
<Route path='startDebate' element={<StartDebate />} />
<Route path='leaderboard' element={<Leaderboard />} />
<Route path='profile' element={<Profile />} />
<Route path='community' element={<CommunityFeed />} />
<Route path='about' element={<About />} />
<Route path='team-builder' element={<TeamBuilder />} />
<Route path='game/:userId' element={<DebateApp />} />
<Route path='bot-selection' element={<BotSelection />} />
<Route path='/tournaments' element={<TournamentHub />} />
<Route path='/coach' element={<CoachPage />} />
<Route
path='/tournament/:id/bracket'
element={<TournamentDetails />}
/>
<Route
path='coach/strengthen-argument'
element={<StrengthenArgument />}
/>
<Route path='/coach' element={<CoachPage />} />
<Route
path='coach/strengthen-argument'
element={<StrengthenArgument />}
/>{' '}
{/* Add this route */}
<Route path='coach/pros-cons' element={<ProsConsChallenge />} />
<Routes>
{/* Public routes */}
<Route
path="/"
element={
isAuthenticated ? <Navigate to="/startDebate" replace /> : <Home />
}
/>
<Route path="/auth" element={<Authentication />} />
<Route path="/admin/login" element={<AdminSignup />} />
<Route path="/admin/dashboard" element={<AdminDashboard />} />

{/* Protected routes */}
<Route element={<ProtectedRoute />}>
<Route element={<Layout />}>
<Route path="startDebate" element={<StartDebate />} />
<Route path="leaderboard" element={<Leaderboard />} />
<Route path="profile" element={<Profile />} />
<Route path="community" element={<CommunityFeed />} />
<Route path="about" element={<About />} />
<Route path="team-builder" element={<TeamBuilder />} />
<Route path="game/:userId" element={<DebateApp />} />
<Route path="bot-selection" element={<BotSelection />} />
<Route path="tournaments" element={<TournamentHub />} />
<Route
path="tournament/:id/bracket"
element={<TournamentDetails />}
/>

{/* Coach routes */}
<Route path="coach" element={<CoachPage />}>
<Route
path="strengthen-argument"
element={<StrengthenArgument />}
/>
<Route path="pros-cons" element={<ProsConsChallenge />} />
</Route>
</Route>

{/* Debate routes (outside layout) */}
<Route path="debate/:roomId" element={<DebateRoom />} />
<Route path="debate-room/:roomId" element={<OnlineDebateRoom />} />
<Route path="team-debate/:debateId" element={<TeamDebateRoom />} />
<Route path="spectator/:roomId" element={<ChatRoom />} />
<Route path="debate/:debateID/view" element={<ViewDebate />} />
<Route path="view-debate/:debateID" element={<ViewDebate />} />
<Route path="speech-test" element={<SpeechTest />} />
</Route>
<Route path='/debate/:roomId' element={<DebateRoom />} />
<Route path='/debate-room/:roomId' element={<OnlineDebateRoom />} />
<Route path='/team-debate/:debateId' element={<TeamDebateRoom />} />
<Route path='/spectator/:roomId' element={<ChatRoom />} />
<Route path='/debate/:debateID/view' element={<ViewDebate />} />
<Route path='/view-debate/:debateID' element={<ViewDebate />} />
<Route path='/speech-test' element={<SpeechTest />} />
</Route>
{/* Redirect unknown routes */}
<Route path='*' element={<Navigate to='/' replace />} />
</Routes>

{/* Redirect unknown routes */}
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>

);
}

Expand Down
54 changes: 35 additions & 19 deletions frontend/src/Pages/DebateRoom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ const extractJSON = (response: string): string => {
};

const DebateRoom: React.FC = () => {
const judgingRef = useRef(false);
const navigate = useNavigate();
const location = useLocation();
const navigate = useNavigate();
const debateData = location.state as DebateProps;
Expand Down Expand Up @@ -574,50 +576,56 @@ const DebateRoom: React.FC = () => {
}
};

const judgeDebateResult = async (messages: Message[]) => {
const judgeDebateResult = async (messages: Message[]) => {
if (judgingRef.current) {
console.log("Judging already in progress, skipping duplicate call");
return;
}

judgingRef.current = true;

try {
console.log("Starting judgment with messages:", messages);
const { result } = await judgeDebate({
history: messages,
userId: debateData.userId,
});

console.log("Raw judge result:", result);

const jsonString = extractJSON(result);
console.log("Extracted JSON string:", jsonString);

let judgment: JudgmentData;
try {
judgment = JSON.parse(jsonString);
} catch (parseError) {
console.error("JSON parse error:", parseError, "Trying to fix JSON...");
// Try to fix common JSON issues
const fixedJson = jsonString
.replace(/'/g, '"') // Replace single quotes with double quotes
.replace(/(\w+):/g, '"$1":') // Add quotes to keys
.replace(/,\s*}/g, '}') // Remove trailing commas
.replace(/,\s*]/g, ']'); // Remove trailing commas in arrays
try {
judgment = JSON.parse(fixedJson);
} catch (e) {
throw new Error(`Failed to parse JSON: ${e}`);
}
.replace(/'/g, '"')
.replace(/(\w+):/g, '"$1":')
.replace(/,\s*}/g, '}')
.replace(/,\s*]/g, ']');

judgment = JSON.parse(fixedJson);
}

console.log("Parsed judgment:", judgment);
setJudgmentData(judgment);
setPopup({ show: false, message: "" });
setShowJudgment(true);

} catch (error) {
console.error("Judging error:", error);
// Show error to user

setPopup({
show: true,
message: `Judgment error: ${error instanceof Error ? error.message : "Unknown error"}. Showing default results.`,
message: `Judgment error: ${
error instanceof Error ? error.message : "Unknown error"
}. Showing default results.`,
isJudging: false,
});

// Set default judgment data

setJudgmentData({
opening_statement: {
user: { score: 0, reason: "Error occurred during judgment" },
Expand All @@ -643,13 +651,18 @@ const DebateRoom: React.FC = () => {
opponent_analysis: "",
},
});

setTimeout(() => {
setPopup({ show: false, message: "" });
setShowJudgment(true);
}, 3000);

} finally {
judgingRef.current = false;
}
};


const formatTime = (seconds: number) => {
const timeStr = `${Math.floor(seconds / 60)}:${(seconds % 60)
.toString()
Expand Down Expand Up @@ -747,7 +760,10 @@ const DebateRoom: React.FC = () => {
userStance={state.userStance}
botStance={state.botStance}
botDesc={bot.desc}
onClose={() => setShowJudgment(false)}
onClose={() => {
setShowJudgment(false);
navigate("/");
}}
/>
)}

Expand Down
29 changes: 18 additions & 11 deletions frontend/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,11 @@ function Header() {

return (
<>
<header className="flex items-center justify-between h-16 px-4 border-b border-gray-200">
<div className="text-lg font-semibold">{getBreadcrumbs()}</div>
<header className="flex items-center justify-between h-16 px-4 border-b border-border bg-background">
<div className="text-lg font-semibold text-foreground">
{getBreadcrumbs()}
</div>

<div className="flex items-center gap-4">
<Popover open={isNotificationsOpen} onOpenChange={setIsNotificationsOpen}>
<PopoverTrigger asChild>
Expand Down Expand Up @@ -239,7 +242,7 @@ function Header() {

<button
onClick={toggleDrawer}
className="md:hidden p-2 rounded-md text-gray-600 hover:bg-gray-100"
className="md:hidden p-2 rounded-md text-muted-foreground hover:bg-muted"
aria-label="Open menu"
>
<Menu className="h-6 w-6" />
Expand All @@ -250,13 +253,14 @@ function Header() {
{isDrawerOpen && (
<div className="fixed inset-0 z-[1000] md:hidden">
<div
className="absolute inset-0 bg-black bg-opacity-50"
className="absolute inset-0 bg-black/50"
onClick={toggleDrawer}
></div>
<div className="relative w-64 h-full bg-white shadow-lg transform transition-transform duration-300 ease-in-out translate-x-0 ml-auto">
<div className="flex items-center justify-between h-16 px-4 border-b border-gray-200">
/>

<div className="relative w-64 h-full bg-background border-l border-border shadow-lg ml-auto">
<div className="flex items-center justify-between h-16 px-4 border-b border-border">
<div className="flex items-center gap-2">
<span className="text-xl font-bold text-gray-900">
<span className="text-xl font-bold text-foreground">
DebateAI by
</span>
<img
Expand All @@ -265,14 +269,16 @@ function Header() {
className="h-8 w-auto object-contain"
/>
</div>

<button
onClick={toggleDrawer}
className="p-2 text-gray-600 hover:text-gray-900"
className="p-2 text-muted-foreground hover:text-foreground"
aria-label="Close menu"
>
<X className="h-6 w-6" />
</button>
</div>

<nav className="flex-1 px-2 py-4 space-y-2">
<NavItem
to="/startDebate"
Expand Down Expand Up @@ -321,8 +327,8 @@ function NavItem({ to, label, icon, onClick }: NavItemProps) {
className={({ isActive }) =>
`group flex items-center px-2 py-2 text-sm font-medium rounded-md ${
isActive
? "bg-gray-200 text-gray-900"
: "text-gray-600 hover:bg-gray-100 hover:text-gray-900"
? "bg-muted text-foreground"
: "text-muted-foreground hover:bg-muted hover:text-foreground"
}`
}
>
Expand All @@ -332,4 +338,5 @@ function NavItem({ to, label, icon, onClick }: NavItemProps) {
);
}


export default Header;
1 change: 1 addition & 0 deletions frontend/src/components/JudgementPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ const JudgmentPopup: React.FC<JudgmentPopupProps> = ({
botName,
userStance,
botStance,
botDesc,
forRole,
againstRole,
localRole = null,
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/components/Matchmaking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ interface MatchmakingMessage {
error?: string;
}



const Matchmaking: React.FC = () => {
const [pool, setPool] = useState<MatchmakingPool[]>([]);
const [isConnected, setIsConnected] = useState(false);
Expand All @@ -33,6 +35,13 @@ const Matchmaking: React.FC = () => {
const wsRef = useRef<WebSocket | null>(null);
const navigate = useNavigate();

// Reset matchmaking UI state on page refresh
useEffect(() => {
setIsInPool(false);
setWaitTime(0);
}, []);


useEffect(() => {
// If still loading, wait
if (isLoading) {
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/components/ui/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none",
"text-foreground",
"data-[highlighted]:bg-muted data-[highlighted]:text-foreground",
"high-contrast:data-[highlighted]:bg-[hsl(var(--hc-hover-bg))]",
"high-contrast:data-[highlighted]:text-[hsl(var(--hc-hover-text))]",
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
Expand All @@ -125,11 +130,16 @@ const SelectItem = React.forwardRef<
<CheckIcon className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>

<SelectPrimitive.ItemText>
{children}
</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName



const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
--chart-5: 180 100% 50%;
}
}
.high-contrast {
--hc-hover-bg: 48 100% 50%;
--hc-hover-text: 0 0% 0%;
}

@layer base {
* {
Expand Down