Skip to content

Commit 8a3a5a4

Browse files
committed
merge: main
2 parents ba9bb99 + ba8b2d0 commit 8a3a5a4

File tree

14 files changed

+214
-11
lines changed

14 files changed

+214
-11
lines changed

README.md

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
1-
# Castled Front
2-
3-
- [translations](src/i18n/translations.md)
4-
5-
// TODO: Complete readme
1+
# Castled Frontend
2+
## Overview
3+
This project is a frontend application built using TypeScript and React. It interacts with various APIs to provide a seamless user experience. The project uses modern web development tools and practices, including Tailwind CSS for styling and Axios for HTTP requests.
4+
### Technologies Used
5+
- TypeScript: A strongly typed programming language that builds on JavaScript.
6+
- React: A JavaScript library for building user interfaces.
7+
- Axios: A promise-based HTTP client for making requests.
8+
- Tailwind CSS: A utility-first CSS framework for rapid UI development.
9+
- Autoprefixer: A PostCSS plugin to parse CSS and add vendor prefixes.
10+
### Project Structure
11+
- `src/api`: Contains API interaction logic.
12+
- `src/pages`: Contains React components for different pages.
13+
- `src/store`: Contains state management logic.
14+
- `postcss.config.js`: Configuration for PostCSS plugins.
15+
### Setup
16+
- Clone the repository
17+
- Navigate to the project directory:
18+
```bash
19+
cd Front
20+
```
21+
- Install dependencies:
22+
```bash
23+
npm install
24+
```
25+
- Start the development server:
26+
```bash
27+
npm start
28+
```

eslint.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export default [
1313
'@typescript-eslint/no-redundant-type-constituents': 'off',
1414
'@typescript-eslint/no-unsafe-assignment': 'off',
1515
'@typescript-eslint/no-unsafe-member-access': 'off',
16+
'@typescript-eslint/prefer-promise-reject-errors': 'off',
17+
'@typescript-eslint/no-unsafe-return': 'off',
1618
},
1719
languageOptions: {
1820
globals: { ...globals.browser, React: 'writable' },

src/api/analysis.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,22 @@
22
import { Analysis } from '@/types/analysis.ts';
33
import { useAuthStore } from '@/store/auth.ts';
44

5+
/**
6+
* Creates a new analysis by sending a POST request to the API.
7+
* @param {Analysis} analysis - The analysis data to be created.
8+
* @returns {Promise<any>} A promise that resolves to the response of the API call.
9+
*/
510
export const createAnalysis = async (analysis: Analysis) => {
611
const token = useAuthStore.getState().accessToken;
712

813
return await apiAuthenticated.post(`/api/v1/analysis`, analysis, { headers: { Authorization: `Bearer ${token}` } });
914
};
1015

16+
/**
17+
* Retrieves an analysis by its ID by sending a GET request to the API.
18+
* @param {string} id - The ID of the analysis to retrieve.
19+
* @returns {Promise<any>} A promise that resolves to the response of the API call.
20+
*/
1121
export const getAnalysisById = async (id: string) => {
1222
const token = useAuthStore.getState().accessToken;
1323

src/api/auth.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import { RegisterSchema, LoginResponseSchema, LoginSchema } from '@/schema/auth.
33
import { z } from 'zod';
44
import { useAuthStore } from '@/store/auth.ts';
55

6+
/**
7+
* Logs in a user by sending a POST request to the API.
8+
* @param {z.infer<typeof LoginSchema>} data - The login data to be sent to the API.
9+
* @returns {Promise<void>} A promise that resolves when the login process is complete.
10+
*/
611
export const login = async (data: z.infer<typeof LoginSchema>) => {
712
const loginCall = await api.post('/api/v1/auth/login', data);
813

@@ -13,6 +18,11 @@ export const login = async (data: z.infer<typeof LoginSchema>) => {
1318
useAuthStore.getState().setUser(user);
1419
};
1520

21+
/**
22+
* Registers a new user by sending a POST request to the API.
23+
* @param {z.infer<typeof RegisterSchema>} data - The registration data to be sent to the API.
24+
* @returns {Promise<void>} A promise that resolves when the registration process is complete.
25+
*/
1626
export const register = async (data: z.infer<typeof RegisterSchema>) => {
1727
const registerCall = await api.post('/api/v1/auth/register', data);
1828

@@ -27,6 +37,10 @@ export const register = async (data: z.infer<typeof RegisterSchema>) => {
2737
useAuthStore.getState().setUser(user);
2838
};
2939

40+
/**
41+
* Refreshes the authentication tokens by sending a POST request to the API.
42+
* @returns {Promise<any>} A promise that resolves to the response of the API call.
43+
*/
3044
export const refreshTokens = async () => {
3145
const refreshToken = useAuthStore.getState().refreshToken;
3246

src/api/chesscom.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@
22
import { DateRange } from 'react-day-picker';
33
import { ChessComGame } from '@/pages/start-analysis/chesscom-select.tsx';
44

5-
export const getUserGames = async (username: string, dateRange: DateRange | undefined) => {
5+
/**
6+
* Fetches the user's games from Chess.com within a specified date range.
7+
*
8+
* @param {string} username - The Chess.com username.
9+
* @param {DateRange | undefined} dateRange - The date range for fetching games.
10+
* @returns {Promise<ChessComGame[]>} - A promise that resolves to an array of ChessComGame objects.
11+
*/
12+
export const getUserGames = async (username: string, dateRange: DateRange | undefined): Promise<ChessComGame[]> => {
13+
// Return an empty array if the date range is not defined or invalid
614
if (!dateRange || !dateRange?.from || !dateRange?.to) {
715
return [];
816
}
917

18+
// Adjust the end date to the current date if it matches today's date
1019
if (dateRange.to.toDateString() === new Date().toDateString()) {
1120
dateRange.to = new Date();
1221
}
@@ -17,6 +26,7 @@ export const getUserGames = async (username: string, dateRange: DateRange | unde
1726
const startMonth = dateRange.from.getMonth();
1827
const endMonth = dateRange.to.getMonth();
1928

29+
// Loop through each year and month within the date range
2030
for (let year = startYear; year <= endYear; year++) {
2131
const monthStart = year === startYear ? startMonth : 0;
2232
const monthEnd = year === endYear ? endMonth : 11;
@@ -29,6 +39,7 @@ export const getUserGames = async (username: string, dateRange: DateRange | unde
2939
`https://api.chess.com/pub/player/${username}/games/${year}/${formattedMonth}`,
3040
);
3141

42+
// Filter and add games within the specified date range
3243
fetchedGames.push(
3344
...games.filter(
3445
(g) => g.end_time >= dateRange.from!.getTime() / 1000 && g.end_time <= dateRange.to!.getTime() / 1000,

src/api/history.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { apiAuthenticated } from './index';
22
import { useAuthStore } from '@/store/auth.ts';
33

4+
/**
5+
* Fetches the analysis history for the authenticated user.
6+
*
7+
* @returns {Promise<any[]>} - A promise that resolves to an array of analysis history items.
8+
* @throws {Promise<string>} - A promise that rejects with an error message if no access token is available.
9+
*/
410
export const getHistory = async () => {
511
const accessToken = useAuthStore.getState().accessToken;
612

@@ -17,6 +23,13 @@ export const getHistory = async () => {
1723
return data.data.items;
1824
};
1925

26+
/**
27+
* Fetches a specific game analysis by its ID.
28+
*
29+
* @param {string} id - The ID of the game analysis to fetch.
30+
* @returns {Promise<any>} - A promise that resolves to the game analysis data.
31+
* @throws {Promise<string>} - A promise that rejects with an error message if no access token is available.
32+
*/
2033
export const getGame = async (id: string) => {
2134
const accessToken = useAuthStore.getState().accessToken;
2235

@@ -33,6 +46,13 @@ export const getGame = async (id: string) => {
3346
return data.data;
3447
};
3548

49+
/**
50+
* Deletes a specific game analysis by its ID.
51+
*
52+
* @param {string} id - The ID of the game analysis to delete.
53+
* @returns {Promise<void>} - A promise that resolves when the game analysis is deleted.
54+
* @throws {Promise<string>} - A promise that rejects with an error message if no access token is available.
55+
*/
3656
export const deleteGame = async (id: string) => {
3757
const accessToken = useAuthStore.getState().accessToken;
3858

src/api/lichessorg.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,27 @@
22
import { DateRange } from 'react-day-picker';
33
import { LichessOrgGame } from '@/pages/start-analysis/lichessorg-select.tsx';
44

5+
/**
6+
* Fetches autocomplete suggestions for usernames from Lichess.org.
7+
*
8+
* @param {string} query - The query string to search for usernames.
9+
* @returns {Promise<string[]>} - A promise that resolves to an array of suggested usernames.
10+
*/
511
export const autoCompleteUsernames = async (query: string) => {
612
const { data }: { data: string[] } = await api.get(`https://lichess.org/api/player/autocomplete?term=${query}`);
713

814
return data;
915
};
16+
17+
/**
18+
* Fetches the user's games from Lichess.org within a specified date range and processes each game.
19+
*
20+
* @param {string} username - The Lichess.org username.
21+
* @param {DateRange | undefined} dateRange - The date range for fetching games.
22+
* @param {function} onMessage - Callback function to process each game.
23+
* @param {function} onComplete - Callback function to call when the fetching is complete.
24+
* @returns {Promise<void>} - A promise that resolves when the fetching is complete.
25+
*/
1026
export const getUserGames = (
1127
username: string,
1228
dateRange: DateRange | undefined,
@@ -33,8 +49,12 @@ export const getUserGames = (
3349
stream.then(readStream(onMessage)).then(onComplete);
3450
};
3551

36-
// https://gist.github.com/ornicar/a097406810939cf7be1df8ea30e94f3e
37-
/* eslint-disable */
52+
/**
53+
* Reads a stream of newline-delimited JSON (NDJSON) and processes each line.
54+
*
55+
* @param {function} processLine - Callback function to process each line of the stream.
56+
* @returns {function} - A function that takes a response and reads the stream.
57+
*/
3858
const readStream = (processLine: any) => (response: any) => {
3959
const stream = response.body.getReader();
4060
const matcher = /\r?\n/;
@@ -60,4 +80,3 @@ const readStream = (processLine: any) => (response: any) => {
6080

6181
return loop();
6282
};
63-
/* eslint-enable */

src/lib/analysis.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export const Engines: Engine[] = [
4646
},
4747
];
4848

49+
/**
50+
* Retrieves the cached engines.
51+
* @returns {Promise<Engine[]>} A promise that resolves to an array of cached engines.
52+
*/
4953
export const getCachedEngines = async () => {
5054
const cachedEngines: Engine[] = [];
5155

@@ -58,6 +62,11 @@ export const getCachedEngines = async () => {
5862
return cachedEngines;
5963
};
6064

65+
/**
66+
* Analyzes the moves locally using the Stockfish engine.
67+
* @param {AnalyseMovesLocalParams} params - The parameters for analyzing moves.
68+
* @returns {Promise<AnalysisMove>[]} An array of promises that resolve to analysis moves.
69+
*/
6170
export const analyseMovesLocal = ({
6271
moves,
6372
data,
@@ -101,10 +110,22 @@ export const analyseMovesLocal = ({
101110
);
102111
};
103112

113+
/**
114+
* Classifies the moves based on the analysis results.
115+
* @param {AnalysisMove[]} moves - The array of analysis moves.
116+
* @returns {AnalysisMove[]} The array of classified analysis moves.
117+
*/
104118
export const classifyMoves = (moves: AnalysisMove[]): AnalysisMove[] => {
105119
return moves.map(classifyRegular);
106120
};
107121

122+
/**
123+
* Classifies a single move based on the analysis results.
124+
* @param {AnalysisMove} move - The analysis move to classify.
125+
* @param {number} index - The index of the move in the array.
126+
* @param {AnalysisMove[]} moves - The array of analysis moves.
127+
* @returns {AnalysisMove} The classified analysis move.
128+
*/
108129
export const classifyRegular = (move: AnalysisMove, index: number, moves: AnalysisMove[]) => {
109130
const next = moves[index + 1]?.engineResults.sort((a, b) => b.depth! - a.depth!)?.[0];
110131
const current = move?.engineResults.sort((a, b) => b.depth! - a.depth!)?.[0];
@@ -115,6 +136,13 @@ export const classifyRegular = (move: AnalysisMove, index: number, moves: Analys
115136
else return { ...move, classification: classifyWithWinChance(move.move, next, current) };
116137
};
117138

139+
/**
140+
* Classifies a move based on mate evaluation.
141+
* @param {Move} move - The move to classify.
142+
* @param {number} next - The next mate evaluation.
143+
* @param {number} current - The current mate evaluation.
144+
* @returns {AnalysisMoveClassification} The classification of the move.
145+
*/
118146
const classifyWithMate = (move: Move, next: InfoResult, current: InfoResult): AnalysisMoveClassification => {
119147
if (next.mate === null || current.mate === null) return AnalysisMoveClassification.None;
120148

@@ -132,6 +160,13 @@ const classifyWithMate = (move: Move, next: InfoResult, current: InfoResult): An
132160
return classification;
133161
};
134162

163+
/**
164+
* Classifies a move based on win chance evaluation.
165+
* @param {Move} move - The move to classify.
166+
* @param {number} next - The next win chance evaluation.
167+
* @param {number} current - The current win chance evaluation.
168+
* @returns {AnalysisMoveClassification} The classification of the move.
169+
*/
135170
const classifyWithWinChance = (move: Move, next: InfoResult, current: InfoResult): AnalysisMoveClassification => {
136171
if (!next.winChance || !current.winChance) return AnalysisMoveClassification.None;
137172

src/lib/opening.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ const worker = new Worker(new URL('../workers/opening.ts', import.meta.url), {
44
type: 'module',
55
});
66

7+
/**
8+
* Finds the opening based on the provided PGN string.
9+
* @param {string} pgn - The PGN (Portable Game Notation) string of the chess game.
10+
* @returns {Promise<Opening | undefined>} A promise that resolves to the opening or undefined if not found.
11+
*/
712
export const findOpening = (pgn: string): Promise<Opening | undefined> =>
813
new Promise<Opening | undefined>((resolve) => {
914
worker.onmessage = (message: MessageEvent) => {

src/lib/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { clsx, type ClassValue } from 'clsx';
22
import { twMerge } from 'tailwind-merge';
33

4+
/**
5+
* Combines class names using `clsx` and merges Tailwind CSS classes using `twMerge`.
6+
* @param {...ClassValue[]} inputs - The class values to be combined and merged.
7+
* @returns {string} The combined and merged class names.
8+
*/
49
export function cn(...inputs: ClassValue[]) {
510
return twMerge(clsx(inputs));
611
}

0 commit comments

Comments
 (0)