Skip to content
Merged
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
14 changes: 12 additions & 2 deletions apps/web-chess/src/app/api/model/GameViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@ export type GameViewModel = {
result?: GameResultV1;
status: GameStatusTypeV1;
players: {
white?: { username: string; avatar?: string };
black?: { username: string; avatar?: string };
white?: {
username: string;
avatar?: string;
rating?: string;
ratingDiff?: string;
};
black?: {
username: string;
avatar?: string;
rating?: string;
ratingDiff?: string;
};
};
startedAt?: Date;
clock?: CountdownClock;
Expand Down
16 changes: 16 additions & 0 deletions apps/web-chess/src/app/api/service/GameService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ export class GameService {
}

toGameViewModel(gameDetails: GameDetailsV1): GameViewModel {
const whiteRatingDiff = gameDetails.players.white?.ratingDiff;
const whiteRatingDiffText = whiteRatingDiff
? whiteRatingDiff > 0
? `+ ${whiteRatingDiff}`
: `- ${Math.abs(whiteRatingDiff)}`
: undefined;
const blackRatingDiff = gameDetails.players.black?.ratingDiff;
const blackRatingDiffText = blackRatingDiff
? blackRatingDiff > 0
? `+ ${blackRatingDiff}`
: `- ${Math.abs(blackRatingDiff)}`
: undefined;
return {
status: gameDetails.status,
moves: gameDetails.moves.map((m) => Move.fromUci(m.uci)),
Expand All @@ -62,12 +74,16 @@ export class GameService {
? {
username: gameDetails.players.white.name,
avatar: undefined,
rating: gameDetails.players.white.rating?.toString(),
ratingDiff: whiteRatingDiffText,
}
: undefined,
black: gameDetails.players.black
? {
username: gameDetails.players.black.name,
avatar: undefined,
rating: gameDetails.players.black.rating?.toString(),
ratingDiff: blackRatingDiffText,
}
: undefined,
},
Expand Down
17 changes: 6 additions & 11 deletions apps/web-chess/src/app/features/game/RemoteGameContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,10 @@ export const RemoteGameContainer = ({
isPeeking,
} = usePeekBoardState(chessboard);
const { auth } = useAuth();
const {
players,
playerSide,
result,
isReadOnly,
actionOptions,
clock,
status,
} = gameState;
const { players, playerSide, result, isReadOnly, actionOptions, clock } =
gameState;
orientation = playerSide !== 'spectator' ? playerSide : orientation;

const isInProgress = status === 'IN_PROGRESS';

const blackPlayer = { ...players.black, color: Color.Black };
const whitePlayer = { ...players.white, color: Color.White };
const currentOrientation = orientation || Color.White;
Expand Down Expand Up @@ -74,6 +65,8 @@ export const RemoteGameContainer = ({
username={topPlayer?.username}
avatar={topPlayer?.avatar}
color={topPlayer.color}
rating={topPlayer?.rating}
ratingDiff={topPlayer?.ratingDiff}
isPlayerTurn={chessboard.position.turn === topPlayer.color}
isLoading={isLoadingInitial}
/>
Expand All @@ -100,6 +93,8 @@ export const RemoteGameContainer = ({
username={bottomPlayer?.username}
avatar={bottomPlayer?.avatar}
color={bottomPlayer.color}
rating={bottomPlayer?.rating}
ratingDiff={bottomPlayer?.ratingDiff}
isPlayerTurn={chessboard.position.turn === bottomPlayer.color}
isLoading={isLoadingInitial}
/>
Expand Down
41 changes: 30 additions & 11 deletions apps/web-chess/src/app/features/game/components/PlayerInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Color } from '@michess/core-board';
import { Avatar, Badge, Flex, Skeleton, Text } from '@radix-ui/themes';
import { Avatar, Badge, Box, Flex, Skeleton, Text } from '@radix-ui/themes';
import React from 'react';
import { CountdownClock } from '../../../api/model/CountdownClock';
import { Clock } from './Clock';
Expand All @@ -13,6 +13,8 @@ type PlayerInfoProps = {
isPlayerTurn?: boolean;
isLoading?: boolean;
clock?: CountdownClock;
rating?: string;
ratingDiff?: string;
};

export const PlayerInfo: React.FC<PlayerInfoProps> = ({
Expand All @@ -23,6 +25,8 @@ export const PlayerInfo: React.FC<PlayerInfoProps> = ({
avatar,
isPlayerTurn = false,
clock,
rating,
ratingDiff,
isLoading,
}) => {
const getInitials = (name: string): string => {
Expand Down Expand Up @@ -52,16 +56,31 @@ export const PlayerInfo: React.FC<PlayerInfoProps> = ({
</Skeleton>
<Flex direction="column" gap="2">
<Skeleton loading={isLoading}>
<Text
size="3"
weight="bold"
color="gray"
highContrast
trim="both"
title={displayUsername}
>
{displayUsername}
</Text>
<Flex align={'center'} gap={'2'}>
<Text
size="3"
weight="bold"
color="gray"
highContrast
trim="both"
title={displayUsername}
>
{displayUsername}
</Text>
<Box>
{rating !== undefined ? (
<Text color={'gray'}>{rating}</Text>
) : undefined}
{ratingDiff !== undefined ? (
<Text
ml={'1'}
color={ratingDiff.startsWith('+') ? 'green' : 'red'}
>
{ratingDiff}
</Text>
) : undefined}
</Box>
</Flex>
</Skeleton>

<Flex align="center" gap="1">
Expand Down
3 changes: 2 additions & 1 deletion apps/web-chess/src/app/features/lobby/GameLobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ export const GameLobby: React.FC<Props> = ({ onCreateGame, onJoinGame }) => {
<Flex align="center" gap="4">
<Box style={{ minWidth: '120px' }}>
<Text weight="medium" size="3">
{game.opponent.name}
{game.opponent.name}{' '}
{game.opponent.rating ? `(${game.opponent.rating})` : ''}
</Text>
</Box>
<Flex align="center" gap="2" style={{ minWidth: '100px' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { http, HttpResponse, server } from '../../../../test/mocks/node-chess';
import {
render,
socketClient,
within,
} from '../../../../test/utils/custom-testing-library';
import { GameLobby } from '../GameLobby';

Expand All @@ -15,7 +16,7 @@ describe('GameLobby', () => {
expect(getByText('+ Create Game')).toBeTruthy();
});

it('should call onCreateGame when create button is clicked', async () => {
it('should call onCreateGame when a game is created', async () => {
const user = userEvent.setup();
const onCreateGame = vi.fn();
const gameDetailsMockV1: GameDetailsV1 = {
Expand Down Expand Up @@ -43,6 +44,11 @@ describe('GameLobby', () => {

await user.click(createButton);

const dialog = await findByRole('dialog');
const createGameButton = within(dialog).getByRole('button', {
name: 'Create Game',
});
await user.click(createGameButton);
expect(onCreateGame).toHaveBeenCalledTimes(1);
});

Expand Down
9 changes: 9 additions & 0 deletions apps/web-chess/src/test/utils/setup-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import '@testing-library/jest-dom/vitest';
import { fetch } from 'cross-fetch';
import { server } from '../mocks/node-chess';
global.fetch = fetch;
// Mock the ResizeObserver
const ResizeObserverMock = vi.fn(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}));

// Stub the global ResizeObserver
vi.stubGlobal('ResizeObserver', ResizeObserverMock);
vi.mock('socket.io-client', async () => {
return {
io: vi.fn(() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const apiMock: Api = {
{} as never,
{} as never,
{} as never,
{} as never,
),
auth: new AuthService({} as never, {} as never, {} as never, {
google: { clientId: '', clientSecret: '' },
Expand Down
1 change: 1 addition & 0 deletions libs/api-schema/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export * from './lib/player/PlayerGameInfoPageResponseV1';
export * from './lib/player/PlayerGameInfoQueryV1';
export * from './lib/player/PlayerGameInfoQueryV1Schema';
export * from './lib/player/PlayerGameInfoV1';
export * from './lib/player/PlayerInfoV1';
export * from './lib/ServerToClientEvents';
2 changes: 2 additions & 0 deletions libs/api-schema/src/lib/player/PlayerInfoV1Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ import { z } from 'zod';

export const PlayerInfoV1Schema = z.object({
id: z.string(),
rating: z.number().min(0).optional(),
ratingDiff: z.number().optional(),
name: z.string().min(1).max(100),
});
8 changes: 8 additions & 0 deletions libs/api-service/src/lib/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AuthService } from './auth/service/AuthService';
import { GamesService } from './games/service/GamesService';
import { LockService } from './lock/service/LockService';
import { UsageMetricsService } from './metrics/UsageMetricsService';
import { RatingsService } from './user/service/RatingsService';

export type Api = {
games: GamesService;
Expand All @@ -22,11 +23,18 @@ const from = (
): Api => {
const processId = randomUUID();
const lockService = new LockService(repos.cache.client);
const ratingsService = new RatingsService(
repos.rating,
repos.game,
repos.cache,
lockService,
);
const gamesService = new GamesService(
repos.game,
repos.move,
repos.action,
repos.cache,
ratingsService,
lockService,
);
const authService = new AuthService(
Expand Down
Loading