Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export function useSocket(
onMessage(message);
}
},
share: true,
Copy link
Member Author

Choose a reason for hiding this comment

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

what this do

});

// handle how a message is sent
Expand Down
26 changes: 15 additions & 11 deletions src/client/game/game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { ChessEngine } from "../../common/chess-engine";
import type { Move } from "../../common/game-types";
import { NonIdealState, Spinner } from "@blueprintjs/core";
import { AcceptDrawDialog, OfferDrawDialog } from "./draw-dialog";
import { Sidebar } from "../setup/sidebar";
import { bgColor } from "../check-dark-mode";
import "../colors.css";

Expand Down Expand Up @@ -166,17 +167,20 @@ export function Game(): JSX.Element {
aiDifficulty={data.aiDifficulty}
setRotation={setRotation}
/>
<div id="body-container" className={bgColor()}>
<ChessboardWrapper
side={side}
chess={chess}
onMove={handleMove}
rotation={rotation ? rotation : 0}
/>
{gameEndDialog}
{gameOfferDialog}
{gameAcceptDialog}
<Outlet />
<Sidebar top={50} />
<div className="main-dialog">
<div id="body-container" className={bgColor()}>
<ChessboardWrapper
side={side}
chess={chess}
onMove={handleMove}
rotation={rotation ? rotation : 0}
/>
{gameEndDialog}
{gameOfferDialog}
{gameAcceptDialog}
<Outlet />
</div>
</div>
</>
);
Expand Down
62 changes: 62 additions & 0 deletions src/client/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,65 @@
position: absolute;
// border: 3px solid blue;
}

.sidebar {
//w3 schools for the win
width: 20%;
height: 100%;
position: fixed; /* Fixed Sidebar (stay in place on scroll) */
z-index: 1; /* Stay on top */
top: 0; /* Stay at the top */
left: 0;
overflow-x: hidden; /* Disable horizontal scroll */
padding-top: 20px;
}

.main-dialog {
margin-left: 20%;
position: fixed;
width: 80%;
height: 100%;
padding-top: 50px;
}

.flex-container {
display: flex;
flex-direction: column;
padding: 5px;
background-color: #eee;
}

.button-container {
display: flex;
flex-direction: column;
gap: 5px;
margin-bottom: 5px;
margin-top: auto;
}

@media (max-width: 500px) {
.flex-container {
flex-direction: row;
}

.button-container {
margin-right: 5px;
margin-left: auto;
margin-bottom: auto;
margin-top: 0px;
}

.sidebar {
width: 100%;
height: 20%;
bottom: 0;
top: auto;
padding-top: 10px !important;
}

.main-dialog {
width: 100%;
margin-left: auto;
padding-top: 0px;
}
}
26 changes: 22 additions & 4 deletions src/client/setup/lobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useNavigate, Navigate } from "react-router-dom";
import { GameStartedMessage } from "../../common/message/game-message";
import { useSocket, useEffectQuery, get } from "../api";
import { ClientType } from "../../common/client-types";
import { ThemeButtons } from "./setup";

/**
* check for an active game and waits for one or forwards to setup
Expand Down Expand Up @@ -41,10 +42,27 @@ export function Lobby() {
} else {
return (
<SetupBase>
<NonIdealState
title="Waiting For Game to Start"
icon={<Spinner intent="primary" />}
/>
<>
<NonIdealState
title={
data.clientType === ClientType.CLIENT ?
"Waiting For Host to Start"
: "Waiting in line"
Comment on lines +48 to +50
Copy link

Copilot AI Sep 30, 2025

Choose a reason for hiding this comment

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

[nitpick] The ternary operator formatting is inconsistent. Either use standard format (condition ? value1 : value2) or align the colons properly for better readability.

Suggested change
data.clientType === ClientType.CLIENT ?
"Waiting For Host to Start"
: "Waiting in line"
data.clientType === ClientType.CLIENT
? "Waiting For Host to Start"
: "Waiting in line"

Copilot uses AI. Check for mistakes.
}
icon={<Spinner intent="primary" />}
/>
<div
style={{
alignItems: "center",
display: "flex",
flex: "1 0 auto",
flexDirection: "column",
justifyContent: "space-around",
}}
>
<ThemeButtons />
</div>
</>
</SetupBase>
);
}
Expand Down
48 changes: 27 additions & 21 deletions src/client/setup/setup-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ChessboardWrapper } from "../chessboard/chessboard-wrapper";
import type { PropsWithChildren, ReactNode } from "react";
import { ChessEngine } from "../../common/chess-engine";
import { Side } from "../../common/game-types";
import { Sidebar } from "./sidebar";
import { bgColor } from "../check-dark-mode";
import "../colors.css";

Expand All @@ -20,27 +21,32 @@ interface SetupBaseProps extends PropsWithChildren {
export function SetupBase(props: SetupBaseProps): JSX.Element {
return (
<>
<Outlet />
<ChessboardWrapper
chess={new ChessEngine()}
side={Side.WHITE}
onMove={() => {}}
rotation={0}
/>
<Dialog
style={{
backgroundColor: "transparent",
boxShadow: "none",
}}
isOpen
canEscapeKeyClose={false}
canOutsideClickClose={false}
>
<div className={bgColor() + " " + "roundedBorder"}>
<DialogBody>{props.children}</DialogBody>
<DialogFooter minimal actions={props.actions} />
</div>
</Dialog>
<div className="main-dialog">
<Outlet />
<ChessboardWrapper
chess={new ChessEngine()}
side={Side.WHITE}
onMove={() => {}}
rotation={0}
/>
<Dialog
style={{
backgroundColor: "transparent",
boxShadow: "none",
}}
isOpen
canEscapeKeyClose={false}
canOutsideClickClose={false}
usePortal={false}
enforceFocus={false}
>
<div className={bgColor() + " " + "roundedBorder"}>
<DialogBody>{props.children}</DialogBody>
<DialogFooter minimal actions={props.actions} />
</div>
</Dialog>
</div>
<Sidebar />
</>
);
}
38 changes: 24 additions & 14 deletions src/client/setup/setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,7 @@ function SetupMain(props: SetupMainProps) {
onClick={() => props.onPageChange(SetupType.PUZZLE)}
className={buttonColor()}
/>
<h3 className={textColor()}>Display Settings:</h3>
<ButtonGroup variant="outlined">
{allSettings.map((item, idx) => (
<Button
key={item[0]}
textClassName={textColor()}
//changed for better visibility
icon={item[1]}
text={item[0]}
active={getUserSetting() === idx}
onClick={() => setUserSetting(idx)}
/>
))}
</ButtonGroup>
<ThemeButtons />
</>
);

Expand All @@ -163,8 +150,31 @@ function SetupMain(props: SetupMainProps) {
}}
>
<H3 className={textColor()}>Welcome to Chess Bot!</H3>

{actions}
</div>
</>
);
}

export function ThemeButtons(props): JSX.Element {
props;
Comment on lines +160 to +161
Copy link
Member Author

Choose a reason for hiding this comment

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

Remove props, since we don't use them.

Comment on lines +160 to +161
Copy link

Copilot AI Sep 30, 2025

Choose a reason for hiding this comment

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

The props parameter should be typed (e.g., props: Record<string, never> for empty props) and the no-op statement props; should be removed or replaced with void props; if needed to suppress warnings.

Suggested change
export function ThemeButtons(props): JSX.Element {
props;
export function ThemeButtons(props: Record<string, never>): JSX.Element {
// no props expected

Copilot uses AI. Check for mistakes.
return (
<>
<h3 className={textColor()}>Display Settings:</h3>
<ButtonGroup variant="outlined">
{allSettings.map((item, idx) => (
<Button
key={item[0]}
textClassName={textColor()}
//changed for better visibility
icon={item[1]}
text={item[0]}
active={getUserSetting() === idx}
onClick={() => setUserSetting(idx)}
/>
))}
</ButtonGroup>
</>
);
}
106 changes: 106 additions & 0 deletions src/client/setup/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Button, NonIdealState } from "@blueprintjs/core";
import type { Dispatch } from "react";
import { useState } from "react";
import type { MessageHandler } from "../../common/message/message";
import { JoinQueue, UpdateQueue } from "../../common/message/game-message";
import { get, useEffectQuery, useSocket } from "../api";
import {
bgColor,
buttonColor,
textBoxColor,
textColor,
} from "../check-dark-mode";

function getMessageHandler(setQueue: Dispatch<string[]>): MessageHandler {
return (message) => {
if (message instanceof UpdateQueue) {
setQueue(message.queue.slice());
}
};
}

interface sidebarProps {
top?: number | undefined;
}

/**
* Creates a sidebar to hold the queue elements
* @returns sidebar container
*/
export function Sidebar(props: sidebarProps): JSX.Element {
const [queue, setQueue] = useState<string[]>([]);
const [name, setName] = useState<string>(
"player " + Math.floor(Math.random() * 10000),
);

const sendMessage = useSocket(getMessageHandler(setQueue));
const { isPending, data, isError } = useEffectQuery(
"get-queue",
async () => {
return get("/get-queue").then((newQueue) => {
setQueue(newQueue);
Copy link
Member Author

Choose a reason for hiding this comment

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

I might not be reading this right, but I don't get why we store the queue information twice, once in the useState hook and once in data associated with this useEffectQuery hook.

return newQueue;
});
},
true,
);

const names = useEffectQuery(
"get-name",
async () => {
return get("/get-name").then((name) => {
if (name.message) setName(name.message);
return name;
});
},
true,
);

if (names.isError) {
console.log(names.isError);
}
//ts wanted me to do something with my data
data;
Copy link

Copilot AI Sep 30, 2025

Choose a reason for hiding this comment

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

This is a no-op statement that serves no purpose. If the intent is to satisfy TypeScript's unused variable warning, use void data; or remove the variable assignment altogether.

Suggested change
data;
void data;

Copilot uses AI. Check for mistakes.
if (isPending || names.isPending) {
return <NonIdealState />;
} else if (isError) {
console.log(isError);
}

return (
<div
Copy link
Member Author

Choose a reason for hiding this comment

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

is there any way we can do this with mostly blueprint js components? just for visual consistency

className={"sidebar flex-container " + bgColor()}
style={{ paddingTop: props.top }}
>
<h3 className={textColor()}>Player Queue</h3>
<ul style={{ listStyle: "decimal" }}>
{queue.map(function (data) {
return (
<li className={textColor()} key={data}>
{data}
</li>
);
})}
</ul>
<div className={"button-container"}>
<label className={textColor()}>Name:</label>
<input
className={textBoxColor() + " " + textColor()}
value={name}
maxLength={30}
onChange={(e) => setName(e.target.value)}
/>
<Button
type="submit"
style={{ textAlign: "start" }}
onClick={async () => {
sendMessage(new JoinQueue(name));
}}
className={buttonColor()}
>
Join queue
</Button>
</div>
</div>
);
}
Loading