Skip to content

Conversation

@Arshadul-Monir
Copy link
Collaborator

Notion Ticket (use public link, not private)

https://codebloom.notion.site/1717c85563aa81e1b23cf2cbea8c7b7c?v=2427c85563aa8034b397000cca570fe1&p=2b67c85563aa80a683d5d4f53e3f337c&pm=s

Description of changes

  • I have done a thorough self-review of the PR
  • Copilot has reviewed my latest changes, and all comments have been fixed and/or closed.
  • If I have made database changes, I have made sure I followed all the db repo rules listed in the wiki here. (check if no db changes)
  • All tests have passed
  • I have successfully deployed this PR to staging
  • I have done manual QA in both dev (and staging if possible) and attached screenshots below.

Screenshots

Dev

Staging

Copilot AI review requested due to automatic review settings December 2, 2025 06:26
@Arshadul-Monir Arshadul-Monir added the WIP DO NOT MERGE Not ready for approval / may be abandoned at some point label Dec 2, 2025
@github-actions
Copy link

github-actions bot commented Dec 2, 2025

Overall Project 70.32% 🍏

There is no coverage information present for the Files changed

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces the initial user interface for creating and joining game lobbies in the duel feature. It establishes the basic routing, API layer, and UI components needed for lobby management, though several critical implementation details remain incomplete with placeholder code.

Key Changes:

  • Added /lobby route and LobbyEntryPage component with UI for creating/joining lobbies
  • Created API mutation hooks for lobby creation and joining operations
  • Implemented basic client-side validation for lobby codes

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 12 comments.

File Description
js/src/lib/router.tsx Added /lobby route to enable navigation to the lobby entry page (note: contains duplicate /privacy route that needs removal)
js/src/lib/api/queries/duel/lobby/index.ts Created mutation hooks for createLobby and joinLobby, but implementations are incomplete with placeholder lobby codes and missing parameter handling
js/src/app/duel/_components/lobby/LobbyEntry.page.tsx Implemented lobby entry UI with create/join options, but missing API integration for join functionality, error handling, and accessibility features

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

Comment on lines +163 to +175
<Button
radius="md"
color="green"
onClick={handleJoinLobby}
style={{
backgroundColor: "transparent",
border: "1px solid rgba(0,255,125,0.4)",
width: "100%",
color: "rgba(0,255,125,0.85)",
}}
>
Join
</Button>
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

Missing input validation feedback. When the join code is less than 4 characters and the user clicks "Join", nothing happens. Consider disabling the button or showing an error message when the input is invalid. For example, add a disabled prop to the Button: disabled={joinCode.trim().length < 4}.

Copilot uses AI. Check for mistakes.
Comment on lines +80 to +120
<Paper
withBorder
radius="md"
onClick={() =>
mutate(undefined, {
onSuccess: (data) => {
if (data?.lobbyCode) {
navigate(`/lobby/${data.lobbyCode}`);
}
},
})
}
style={{
cursor: "pointer",
width: "48%",
minHeight: "20vh",
borderColor: "rgba(0,255,125,0.4)",
transition: "0.2s",
}}
onMouseEnter={(e) =>
(e.currentTarget.style.boxShadow =
"0 0 1.5vw rgba(0,255,125,0.5)")
}
onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")}
>
<Center style={{ height: "100%" }}>
<Stack align="center" gap={4}>
<Title
order={3}
style={{
color: "white",
}}
>
Create Lobby
</Title>
<Text size="sm" c="dimmed">
Generate a new lobby code
</Text>
</Stack>
</Center>
</Paper>
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The "Create Lobby" Paper element uses onClick but is not keyboard accessible. Users navigating with a keyboard cannot activate this element. Consider using a Button component instead, or add role="button", tabIndex={0}, and onKeyDown handler to support keyboard navigation (Enter and Space keys).

Copilot uses AI. Check for mistakes.
Comment on lines +138 to +176
<Stack align="center" gap={12} style={{ width: "100%" }}>
<Title
order={3}
style={{
color: "white",
fontSize: "clamp(1rem, 2.5vw, 1.6rem)",
}}
>
Join Lobby
</Title>
<TextInput
placeholder="Enter lobby code"
value={joinCode}
onChange={(e) => setJoinCode(e.target.value)}
radius="md"
styles={{
input: {
backgroundColor: "rgba(255,255,255,0.03)",
border: "1px solid rgba(0,255,125,0.4)",
color: "white",
textAlign: "center",
},
}}
style={{ width: "100%" }}
/>
<Button
radius="md"
color="green"
onClick={handleJoinLobby}
style={{
backgroundColor: "transparent",
border: "1px solid rgba(0,255,125,0.4)",
width: "100%",
color: "rgba(0,255,125,0.85)",
}}
>
Join
</Button>
</Stack>
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The "Join Lobby" TextInput doesn't support pressing Enter to submit. Users expect to press Enter after typing a lobby code. Consider adding onKeyDown={(e) => { if (e.key === 'Enter') handleJoinLobby(); }} to the TextInput, or wrap the input and button in a <form> element with onSubmit.

Suggested change
<Stack align="center" gap={12} style={{ width: "100%" }}>
<Title
order={3}
style={{
color: "white",
fontSize: "clamp(1rem, 2.5vw, 1.6rem)",
}}
>
Join Lobby
</Title>
<TextInput
placeholder="Enter lobby code"
value={joinCode}
onChange={(e) => setJoinCode(e.target.value)}
radius="md"
styles={{
input: {
backgroundColor: "rgba(255,255,255,0.03)",
border: "1px solid rgba(0,255,125,0.4)",
color: "white",
textAlign: "center",
},
}}
style={{ width: "100%" }}
/>
<Button
radius="md"
color="green"
onClick={handleJoinLobby}
style={{
backgroundColor: "transparent",
border: "1px solid rgba(0,255,125,0.4)",
width: "100%",
color: "rgba(0,255,125,0.85)",
}}
>
Join
</Button>
</Stack>
<form
onSubmit={(e) => {
e.preventDefault();
handleJoinLobby();
}}
style={{ width: "100%" }}
>
<Stack align="center" gap={12} style={{ width: "100%" }}>
<Title
order={3}
style={{
color: "white",
fontSize: "clamp(1rem, 2.5vw, 1.6rem)",
}}
>
Join Lobby
</Title>
<TextInput
placeholder="Enter lobby code"
value={joinCode}
onChange={(e) => setJoinCode(e.target.value)}
radius="md"
styles={{
input: {
backgroundColor: "rgba(255,255,255,0.03)",
border: "1px solid rgba(0,255,125,0.4)",
color: "white",
textAlign: "center",
},
}}
style={{ width: "100%" }}
/>
<Button
type="submit"
radius="md"
color="green"
style={{
backgroundColor: "transparent",
border: "1px solid rgba(0,255,125,0.4)",
width: "100%",
color: "rgba(0,255,125,0.85)",
}}
>
Join
</Button>
</Stack>
</form>

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +47
async function joinLobby() {
const { url, method, res } = ApiURL.create("/api/duel/lobby/join", {
method: "POST",
});
const response = await fetch(url, {
method
});

const json = res(await response.json());

if (json.success) {
return {
lobbyCode: "0XXXX" // Placeholder
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The joinLobby function doesn't accept a lobbyCode parameter, but this is required to join a specific lobby. The function should accept an argument like { lobbyCode: string } and pass it to the API endpoint in the request body using the req() function, similar to how other mutations in the codebase handle parameters (e.g., verifyPassword in js/src/lib/api/queries/club/index.ts).

Suggested change
async function joinLobby() {
const { url, method, res } = ApiURL.create("/api/duel/lobby/join", {
method: "POST",
});
const response = await fetch(url, {
method
});
const json = res(await response.json());
if (json.success) {
return {
lobbyCode: "0XXXX" // Placeholder
async function joinLobby({ lobbyCode }: { lobbyCode: string }) {
const { url, method, res } = ApiURL.create("/api/duel/lobby/join", {
method: "POST",
});
const response = await fetch(url, {
method,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ lobbyCode })
});
const json = res(await response.json());
if (json.success) {
return {
lobbyCode: json.lobbyCode || lobbyCode

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +23
if (json.success) {
return {
lobbyCode: "0XXXX" // Placeholder
};
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

Both createLobby and joinLobby functions return a hardcoded placeholder "0XXXX" instead of the actual lobby code from the API response. The lobby code should be extracted from json.payload (e.g., json.payload.lobbyCode or similar field based on the API response structure). See js/src/lib/api/queries/auth/index.ts lines 24-29 for an example of extracting data from the API response payload.

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +36
const { url, method, res } = ApiURL.create("/api/duel/party/create", {
method: "POST",
});
const response = await fetch(url, {
method
});

const json = res(await response.json());

if (json.success) {
return {
lobbyCode: "0XXXX" // Placeholder
};
}

return { lobbyCode: "" };
}

export const useJoinLobbyMutation = () => {
return useMutation({
mutationFn: joinLobby,
});
}

async function joinLobby() {
const { url, method, res } = ApiURL.create("/api/duel/lobby/join", {
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The API endpoint paths are inconsistent: createLobby uses /api/duel/party/create while joinLobby uses /api/duel/lobby/join. For consistency and clarity, both should use either "party" or "lobby" terminology. Consider using /api/duel/lobby/create and /api/duel/lobby/join to maintain a consistent naming pattern.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +90
onClick={() =>
mutate(undefined, {
onSuccess: (data) => {
if (data?.lobbyCode) {
navigate(`/lobby/${data.lobbyCode}`);
}
},
})
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

Missing error handling for the createLobby mutation. If the API call fails or returns an error, the user receives no feedback. Consider adding an onError callback to show an error notification using notifications.show(), similar to the pattern used in js/src/app/club/[clubSlug]/_components/ClubSignUpForm.tsx lines 64-77.

Copilot uses AI. Check for mistakes.
Comment on lines +148 to +162
<TextInput
placeholder="Enter lobby code"
value={joinCode}
onChange={(e) => setJoinCode(e.target.value)}
radius="md"
styles={{
input: {
backgroundColor: "rgba(255,255,255,0.03)",
border: "1px solid rgba(0,255,125,0.4)",
color: "white",
textAlign: "center",
},
}}
style={{ width: "100%" }}
/>
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The TextInput for entering the lobby code is missing accessibility attributes. Consider adding aria-label="Lobby code" or an id with a corresponding label element to improve screen reader support.

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +51
}

export const useJoinLobbyMutation = () => {
return useMutation({
mutationFn: joinLobby,
});
}

async function joinLobby() {
const { url, method, res } = ApiURL.create("/api/duel/lobby/join", {
method: "POST",
});
const response = await fetch(url, {
method
});

const json = res(await response.json());

if (json.success) {
return {
lobbyCode: "0XXXX" // Placeholder
};
}

return { lobbyCode: "" };
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The useJoinLobbyMutation hook is never used in the UI. The component uses handleJoinLobby which directly navigates without calling the join API. Either remove this unused hook or integrate it into the handleJoinLobby function to actually call the join endpoint before navigation.

Suggested change
}
export const useJoinLobbyMutation = () => {
return useMutation({
mutationFn: joinLobby,
});
}
async function joinLobby() {
const { url, method, res } = ApiURL.create("/api/duel/lobby/join", {
method: "POST",
});
const response = await fetch(url, {
method
});
const json = res(await response.json());
if (json.success) {
return {
lobbyCode: "0XXXX" // Placeholder
};
}
return { lobbyCode: "" };

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +27
const handleJoinLobby = () => {
if (joinCode.trim().length >= 4) {
navigate(`/lobby/${joinCode.trim().toUpperCase()}`);
}
};
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The handleJoinLobby function only validates that the join code has at least 4 characters, but it doesn't actually call the useJoinLobbyMutation to verify the lobby code with the backend before navigating. This means users can navigate to invalid lobby codes. The function should call the join mutation and only navigate on successful validation, similar to how mutate is used for creating a lobby on lines 84-90.

Copilot uses AI. Check for mistakes.
@tahminator tahminator added FROZEN This PR is currently frozen - likely due to a team-wide hiatus and removed WIP DO NOT MERGE Not ready for approval / may be abandoned at some point labels Dec 2, 2025
@github-actions
Copy link

github-actions bot commented Dec 8, 2025

Overall Project 70.52% 🍏

There is no coverage information present for the Files changed

@github-actions
Copy link

github-actions bot commented Dec 9, 2025

Overall Project 70.52% 🍏

There is no coverage information present for the Files changed

@Arshadul-Monir Arshadul-Monir force-pushed the create-join-lobby branch 2 times, most recently from 14d30ed to 3d23ff7 Compare January 1, 2026 23:50
@github-actions
Copy link

github-actions bot commented Jan 1, 2026

Overall Project 72.25% 🍏

There is no coverage information present for the Files changed

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

Labels

FROZEN This PR is currently frozen - likely due to a team-wide hiatus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants