From ee2842d68b40990a0e7933a09b1156c74a7e059a Mon Sep 17 00:00:00 2001 From: shubham-1806 Date: Sun, 11 Feb 2024 13:32:21 +0530 Subject: [PATCH 1/3] feat: tutorials --- docs/spec/CodeCharacter-API.yml | 150 +++++++++ packages/client/.openapi-generator/FILES | 1 + packages/client/src/apis/TutorialsApi.ts | 209 +++++++++++++ packages/client/src/apis/index.ts | 1 + packages/client/src/models/index.ts | 137 ++++++++ packages/renderer/src/RendererUtils.ts | 1 + src/assets/book (1).png:Zone.Identifier | 4 + src/assets/tutorial.png | Bin 0 -> 9968 bytes .../DashboardOptions/DashboardOptions.tsx | 2 +- src/components/Editor/Editor.tsx | 57 ++-- src/components/Editor/EditorTypes.ts | 2 + src/components/EditorInfo/EditorInfo.tsx | 10 +- src/components/MapDesigner/MapDesigner.tsx | 33 +- src/components/NavBar/NavBar.module.css | 53 ++++ src/components/NavBar/NavBar.tsx | 44 ++- .../TourIntroModal/TourIntroModal.tsx | 2 +- .../TutorialModals/TutorialModals.module.css | 52 ++++ .../TutorialModals/TutorialModalsTypes.ts | 5 + .../TutorialModals/ViewTutorial.tsx | 45 +++ src/components/Websocket/Websocket.tsx | 71 +++-- src/pages/Dashboard/Dashboard.module.css | 28 ++ src/pages/Dashboard/Dashboard.tsx | 293 ++++++++++++++++-- src/store/DailyChallenge/dailyChallenge.ts | 7 +- src/store/Tutorials/tutorials.ts | 120 +++++++ src/store/User/UserApi.ts | 2 + src/store/User/UserSlice.ts | 5 + src/store/store.ts | 3 +- 27 files changed, 1248 insertions(+), 89 deletions(-) create mode 100644 packages/client/src/apis/TutorialsApi.ts create mode 100644 src/assets/book (1).png:Zone.Identifier create mode 100644 src/assets/tutorial.png create mode 100644 src/components/TutorialModals/TutorialModals.module.css create mode 100644 src/components/TutorialModals/TutorialModalsTypes.ts create mode 100644 src/components/TutorialModals/ViewTutorial.tsx create mode 100644 src/store/Tutorials/tutorials.ts diff --git a/docs/spec/CodeCharacter-API.yml b/docs/spec/CodeCharacter-API.yml index 0e322f3..ed33ccf 100644 --- a/docs/spec/CodeCharacter-API.yml +++ b/docs/spec/CodeCharacter-API.yml @@ -699,6 +699,7 @@ paths: college: NITT avatarId: 1 tutorialLevel: 2 + codeTutorialLevel: 3 tier: TIER1 isProfileComplete: true isTutorialComplete: true @@ -1588,6 +1589,73 @@ paths: description: Gets all statistics for the current user parameters: [] + '/codetutorial/get/{codeTutorialNumber}': + get: + summary: Get tutorial by number + description: Get a single tutorial + operationId: getCodeTutorialByNumber + parameters: + - name: codeTutorialNumber + in: path + required: true + schema: + type: integer + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/TutorialsGetRequest' + 401: + description: Unauthorized + 403: + description: Forbidden + 404: + description: Not found + tags: + - Tutorials + + /codetutorial/submit: + post: + summary: Match Execution for Tutorials + description: Match making for Tutorials + operationId: createCodeTutorialMatch + responses: + '201': + description: Created + '400': + description: Bad Request + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + examples: + Example: + value: + message: Some field missing + '401': + description: Unauthorized + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CodeTutorialMatchRequest' + examples: + CodeExample: + value: + value: '#include' + language: CPP + codeTutorialNumber: 2 + MapExample: + value: + value: '[[0,0,0]]' + codeTutorialNumber: 6 + tags: + - Tutorials + components: schemas: UserMatchStats: @@ -2060,6 +2128,9 @@ components: tutorialLevel: type: integer example: 1 + codeTutorialLevel: + type: integer + example: 3 tier: $ref: '#/components/schemas/TierType' isProfileComplete: @@ -2077,6 +2148,7 @@ components: - college - avatarId - tutorialLevel + - codeTutorialLevel - isProfileComplete - isTutorialComplete UpdateCurrentUserProfile: @@ -2296,6 +2368,29 @@ components: - destruction - coinsUsed - status + TutorialGame: + title: Game + type: object + description: Game model + properties: + id: + type: string + format: uuid + example: 123e4567-e89b-12d3-a456-426614174000 + destruction: + type: number + example: 100 + coinsUsed: + type: integer + logs: + type: string + status: + $ref: '#/components/schemas/GameStatus' + required: + - id + - destruction + - coinsUsed + - status GameLog: type: string description: Game log model @@ -2351,6 +2446,45 @@ components: required: - user - stats + TutorialsGetRequest: + title: Get tutorials + description: Get the game tutorials + type: object + properties: + tutorialId: + type: integer + example: 1 + tutorialName: + type: string + example: Tutorial for Spawning attacker + tutorialType: + $ref: '#/components/schemas/ChallengeType' + description: + type: string + example: Brief description of how the code works + tutorialCodes: + $ref: '#/components/schemas/TutorialCodeObject' + required: + - tutorialId + - tutorialName + - tutorialCodes + + TutorialCodeObject: + title: Tutorial Code Object + description: The object containing the code for the tutorial + type: object + properties: + cpp: + type: string + example: This would have the cpp code for the tutorial + java: + type: string + example: This would have the java code for the tutorial + python: + type: string + example: This would have the python code for the tutorial + image: + type: string DailyChallengeGetRequest: title: Get daily challenge @@ -2417,6 +2551,22 @@ components: $ref: '#/components/schemas/Language' required: - value + CodeTutorialMatchRequest: + title: CodeTutorialMatchRequest + description: Request Model for the tutorial mode + type: object + properties: + value: + type: string + example: '#include' + language: + $ref: '#/components/schemas/Language' + codeTutorialNumber: + type: integer + nullable: false + required: + - value + - codeTutorialNumber GenericError: title: GenericError type: object diff --git a/packages/client/.openapi-generator/FILES b/packages/client/.openapi-generator/FILES index ed24da6..9931ed7 100644 --- a/packages/client/.openapi-generator/FILES +++ b/packages/client/.openapi-generator/FILES @@ -10,6 +10,7 @@ src/apis/MatchApi.ts src/apis/NotificationApi.ts src/apis/PvpGameApi.ts src/apis/StatsApi.ts +src/apis/TutorialsApi.ts src/apis/UserApi.ts src/apis/index.ts src/index.ts diff --git a/packages/client/src/apis/TutorialsApi.ts b/packages/client/src/apis/TutorialsApi.ts new file mode 100644 index 0000000..c3abb59 --- /dev/null +++ b/packages/client/src/apis/TutorialsApi.ts @@ -0,0 +1,209 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * CodeCharacter API + * Specification of the CodeCharacter API + * + * The version of the OpenAPI document: 2024.0.1 + * Contact: delta@nitt.edu + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import * as runtime from '../runtime'; +import type { + CodeTutorialMatchRequest, + GenericError, + TutorialsGetRequest, +} from '../models'; + +export interface CreateCodeTutorialMatchRequest { + codeTutorialMatchRequest: CodeTutorialMatchRequest; +} + +export interface GetCodeTutorialByNumberRequest { + codeTutorialNumber: number; +} + +/** + * TutorialsApi - interface + * + * @export + * @interface TutorialsApiInterface + */ +export interface TutorialsApiInterface { + /** + * Match making for Tutorials + * @summary Match Execution for Tutorials + * @param {CodeTutorialMatchRequest} codeTutorialMatchRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TutorialsApiInterface + */ + createCodeTutorialMatchRaw( + requestParameters: CreateCodeTutorialMatchRequest, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise>; + + /** + * Match making for Tutorials + * Match Execution for Tutorials + */ + createCodeTutorialMatch( + codeTutorialMatchRequest: CodeTutorialMatchRequest, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise; + + /** + * Get a single tutorial + * @summary Get tutorial by number + * @param {number} codeTutorialNumber + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TutorialsApiInterface + */ + getCodeTutorialByNumberRaw( + requestParameters: GetCodeTutorialByNumberRequest, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise>; + + /** + * Get a single tutorial + * Get tutorial by number + */ + getCodeTutorialByNumber( + codeTutorialNumber: number, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise; +} + +/** + * + */ +export class TutorialsApi + extends runtime.BaseAPI + implements TutorialsApiInterface +{ + /** + * Match making for Tutorials + * Match Execution for Tutorials + */ + async createCodeTutorialMatchRaw( + requestParameters: CreateCodeTutorialMatchRequest, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise> { + if ( + requestParameters.codeTutorialMatchRequest === null || + requestParameters.codeTutorialMatchRequest === undefined + ) { + throw new runtime.RequiredError( + 'codeTutorialMatchRequest', + 'Required parameter requestParameters.codeTutorialMatchRequest was null or undefined when calling createCodeTutorialMatch.', + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token('http-bearer', []); + + if (tokenString) { + headerParameters['Authorization'] = `Bearer ${tokenString}`; + } + } + const response = await this.request( + { + path: `/codetutorial/submit`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters.codeTutorialMatchRequest, + }, + initOverrides, + ); + + return new runtime.VoidApiResponse(response); + } + + /** + * Match making for Tutorials + * Match Execution for Tutorials + */ + async createCodeTutorialMatch( + codeTutorialMatchRequest: CodeTutorialMatchRequest, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise { + await this.createCodeTutorialMatchRaw( + { codeTutorialMatchRequest: codeTutorialMatchRequest }, + initOverrides, + ); + } + + /** + * Get a single tutorial + * Get tutorial by number + */ + async getCodeTutorialByNumberRaw( + requestParameters: GetCodeTutorialByNumberRequest, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise> { + if ( + requestParameters.codeTutorialNumber === null || + requestParameters.codeTutorialNumber === undefined + ) { + throw new runtime.RequiredError( + 'codeTutorialNumber', + 'Required parameter requestParameters.codeTutorialNumber was null or undefined when calling getCodeTutorialByNumber.', + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token('http-bearer', []); + + if (tokenString) { + headerParameters['Authorization'] = `Bearer ${tokenString}`; + } + } + const response = await this.request( + { + path: `/codetutorial/get/{codeTutorialNumber}`.replace( + `{${'codeTutorialNumber'}}`, + encodeURIComponent(String(requestParameters.codeTutorialNumber)), + ), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, + initOverrides, + ); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get a single tutorial + * Get tutorial by number + */ + async getCodeTutorialByNumber( + codeTutorialNumber: number, + initOverrides?: RequestInit | runtime.InitOverrideFunction, + ): Promise { + const response = await this.getCodeTutorialByNumberRaw( + { codeTutorialNumber: codeTutorialNumber }, + initOverrides, + ); + return await response.value(); + } +} diff --git a/packages/client/src/apis/index.ts b/packages/client/src/apis/index.ts index 71d785d..e99d3f8 100644 --- a/packages/client/src/apis/index.ts +++ b/packages/client/src/apis/index.ts @@ -11,4 +11,5 @@ export * from './MatchApi'; export * from './NotificationApi'; export * from './PvpGameApi'; export * from './StatsApi'; +export * from './TutorialsApi'; export * from './UserApi'; diff --git a/packages/client/src/models/index.ts b/packages/client/src/models/index.ts index 5fc4643..3fcd30f 100644 --- a/packages/client/src/models/index.ts +++ b/packages/client/src/models/index.ts @@ -122,6 +122,31 @@ export interface CodeRevision { */ codeType: CodeType; } +/** + * Request Model for the tutorial mode + * @export + * @interface CodeTutorialMatchRequest + */ +export interface CodeTutorialMatchRequest { + /** + * + * @type {string} + * @memberof CodeTutorialMatchRequest + */ + value: string; + /** + * + * @type {Language} + * @memberof CodeTutorialMatchRequest + */ + language?: Language; + /** + * + * @type {number} + * @memberof CodeTutorialMatchRequest + */ + codeTutorialNumber: number; +} /** * @@ -327,6 +352,12 @@ export interface CurrentUserProfile { * @memberof CurrentUserProfile */ tutorialLevel: number; + /** + * + * @type {number} + * @memberof CurrentUserProfile + */ + codeTutorialLevel: number; /** * * @type {TierType} @@ -1101,6 +1132,75 @@ export const TierType = { } as const; export type TierType = (typeof TierType)[keyof typeof TierType]; +/** + * The object containing the code for the tutorial + * @export + * @interface TutorialCodeObject + */ +export interface TutorialCodeObject { + /** + * + * @type {string} + * @memberof TutorialCodeObject + */ + cpp?: string; + /** + * + * @type {string} + * @memberof TutorialCodeObject + */ + java?: string; + /** + * + * @type {string} + * @memberof TutorialCodeObject + */ + python?: string; + /** + * + * @type {string} + * @memberof TutorialCodeObject + */ + image?: string; +} +/** + * Game model + * @export + * @interface TutorialGame + */ +export interface TutorialGame { + /** + * + * @type {string} + * @memberof TutorialGame + */ + id: string; + /** + * + * @type {number} + * @memberof TutorialGame + */ + destruction: number; + /** + * + * @type {number} + * @memberof TutorialGame + */ + coinsUsed: number; + /** + * + * @type {string} + * @memberof TutorialGame + */ + logs?: string; + /** + * + * @type {GameStatus} + * @memberof TutorialGame + */ + status: GameStatus; +} + /** * * @export @@ -1114,6 +1214,43 @@ export const TutorialUpdateType = { export type TutorialUpdateType = (typeof TutorialUpdateType)[keyof typeof TutorialUpdateType]; +/** + * Get the game tutorials + * @export + * @interface TutorialsGetRequest + */ +export interface TutorialsGetRequest { + /** + * + * @type {number} + * @memberof TutorialsGetRequest + */ + tutorialId: number; + /** + * + * @type {string} + * @memberof TutorialsGetRequest + */ + tutorialName: string; + /** + * + * @type {ChallengeType} + * @memberof TutorialsGetRequest + */ + tutorialType?: ChallengeType; + /** + * + * @type {string} + * @memberof TutorialsGetRequest + */ + description?: string; + /** + * + * @type {TutorialCodeObject} + * @memberof TutorialsGetRequest + */ + tutorialCodes: TutorialCodeObject; +} /** * Update current user profile request * @export diff --git a/packages/renderer/src/RendererUtils.ts b/packages/renderer/src/RendererUtils.ts index 5eb6c83..c8f0d48 100644 --- a/packages/renderer/src/RendererUtils.ts +++ b/packages/renderer/src/RendererUtils.ts @@ -3,6 +3,7 @@ import { events, RendererEvents } from './events/EventEmitter'; export class RendererUtils { static loadLog(log: string): void { + console.log('loadLog', log); events.emit(RendererEvents.LOAD_LOG, log); events.emit(RendererEvents.RESET_UI); } diff --git a/src/assets/book (1).png:Zone.Identifier b/src/assets/book (1).png:Zone.Identifier new file mode 100644 index 0000000..053138f --- /dev/null +++ b/src/assets/book (1).png:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://www.flaticon.com/free-icon/book_13637888?term=code+tutorials&page=1&position=1&origin=search&related_id=13637888 +HostUrl=https://www.flaticon.com/download/icon/edited diff --git a/src/assets/tutorial.png b/src/assets/tutorial.png new file mode 100644 index 0000000000000000000000000000000000000000..757b773492dff327abb2c43dffcc04e21e3de41e GIT binary patch literal 9968 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 { View Profile - Revisit Tutorial + Revisit Tour Logout diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index d20830c..f3a8063 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -55,6 +55,10 @@ import { dcCode, changeDcCode, } from '../../store/DailyChallenge/dailyChallenge'; +import { + changeTutorialCode, + tutorialCode, +} from '../../store/Tutorials/tutorials'; import { buildWorkerDefinition } from 'monaco-editor-workers'; import { Uri } from 'vscode'; @@ -66,17 +70,17 @@ buildWorkerDefinition( export default function CodeEditor(props: Editor.Props): JSX.Element { const divCodeEditor = useRef(null); - const userCode: string = - props.page == 'Dashboard' - ? useAppSelector(UserCode) - : useAppSelector(dcCode); const fontSize: number = useAppSelector(FontSize); const theme: string = useAppSelector(Theme); const autocomplete: boolean = useAppSelector(Autocomplete); const dispatch: React.Dispatch = useAppDispatch(); - const keyboardHandler = useAppSelector(KeyboardHandler); - + const userCode: string = + props.page == 'Dashboard' + ? useAppSelector(UserCode) + : props.page == 'DailyChallenge' + ? useAppSelector(dcCode) + : useAppSelector(tutorialCode); const language = props.language; monaco.languages.register({ @@ -169,6 +173,8 @@ export default function CodeEditor(props: Editor.Props): JSX.Element { dispatch(updateUserCode(codeNlanguage)); } else if (props.page == 'DailyChallenge') { dispatch(changeDcCode(codeNlanguage)); + } else if (props.page == 'Tutorials') { + dispatch(changeTutorialCode(codeNlanguage)); } }); @@ -178,24 +184,26 @@ export default function CodeEditor(props: Editor.Props): JSX.Element { }); //Keybinding for Simulate -> CTRL+ALT+N - editor.addCommand( - monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyN, - function () { - if (GameType.NORMAL) { - dispatch(isSelfMatchModalOpened(true)); - dispatch(codeCommitNameChanged('Current Code')); - dispatch(codeCommitIDChanged(null)); - dispatch(mapCommitNameChanged('Current Map')); - dispatch(mapCommitIDChanged(null)); - } else if (GameType.PVP) { - dispatch(isPvPSelfMatchModalOpened(true)); - dispatch(code1CommitNameChanged('Current Code')); - dispatch(code1CommitIDChanged(null)); - dispatch(code2CommitNameChanged('Current Code')); - dispatch(code2CommitIDChanged(null)); - } - }, - ); + if (props.page == 'Dashboard' || props.page == 'Tutorials') { + editor.addCommand( + monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyN, + function () { + if (GameType.NORMAL) { + dispatch(isSelfMatchModalOpened(true)); + dispatch(codeCommitNameChanged('Current Code')); + dispatch(codeCommitIDChanged(null)); + dispatch(mapCommitNameChanged('Current Map')); + dispatch(mapCommitIDChanged(null)); + } else if (GameType.PVP) { + dispatch(isPvPSelfMatchModalOpened(true)); + dispatch(code1CommitNameChanged('Current Code')); + dispatch(code1CommitIDChanged(null)); + dispatch(code2CommitNameChanged('Current Code')); + dispatch(code2CommitIDChanged(null)); + } + }, + ); + } //Keybinding for Commit -> CTRL+K editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK, function () { @@ -284,6 +292,7 @@ export default function CodeEditor(props: Editor.Props): JSX.Element { props.page, autocomplete, props.gameType, + props.tutorialNumber, ]); return
; diff --git a/src/components/Editor/EditorTypes.ts b/src/components/Editor/EditorTypes.ts index 84a659f..70d6157 100644 --- a/src/components/Editor/EditorTypes.ts +++ b/src/components/Editor/EditorTypes.ts @@ -5,6 +5,7 @@ interface PageType { Dashboard: 'Dashboard'; DailyChallenge: 'DailyChallenge'; PvP: 'PvP'; + Tutorials: 'Tutorials'; } export type Props = { @@ -13,6 +14,7 @@ export type Props = { SaveRef: RefObject; SubmitRef: RefObject; gameType: GameType; + tutorialNumber: number; }; export type Workspace = { diff --git a/src/components/EditorInfo/EditorInfo.tsx b/src/components/EditorInfo/EditorInfo.tsx index 2ae0a36..e3f3f50 100644 --- a/src/components/EditorInfo/EditorInfo.tsx +++ b/src/components/EditorInfo/EditorInfo.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import { Col, Modal, Row } from 'react-bootstrap'; import { IsInfoOpen, isInfoOpened } from '../../store/EditorSettings/settings'; @@ -9,11 +10,14 @@ import { dailyChallengePageState, dcDescription, } from '../../store/DailyChallenge/dailyChallenge'; +import { + tutorialDescription, + tutorialCode, +} from '../../store/Tutorials/tutorials'; const EditorInfo = (): JSX.Element => { const homePageState = useAppSelector(dailyChallengePageState); const dailyChallengeDescription = useAppSelector(dcDescription); - const isInfoOpen = useAppSelector(IsInfoOpen); const dispatch = useAppDispatch(); @@ -26,7 +30,7 @@ const EditorInfo = (): JSX.Element => { onHide={() => dispatch(isInfoOpened(false))} > - {homePageState == 'Dashboard' || homePageState == 'PvP' ? ( + {homePageState == 'Dashboard' || homePageState == 'Tutorials' ? ( Editor Shortcuts @@ -44,7 +48,7 @@ const EditorInfo = (): JSX.Element => { - {homePageState == 'Dashboard' || homePageState == 'PvP' ? ( + {homePageState == 'Dashboard' || homePageState == 'Tutorials' ? ( {shortcuts.map((shortcut, index) => ( diff --git a/src/components/MapDesigner/MapDesigner.tsx b/src/components/MapDesigner/MapDesigner.tsx index 1c884ec..4901e0d 100644 --- a/src/components/MapDesigner/MapDesigner.tsx +++ b/src/components/MapDesigner/MapDesigner.tsx @@ -7,6 +7,7 @@ import { MapApi, DailyChallengesApi, CurrentUserApi, + TutorialsApi, } from '@codecharacter-2024/client'; import Toast from 'react-hot-toast'; import styles from './MapDesigner.module.css'; @@ -15,7 +16,7 @@ import { Modal, Container, Row, Button } from 'react-bootstrap'; import { useTour } from '@reactour/tour'; interface MapDesignerProps { - pageType: 'MapDesigner' | 'DailyChallenge'; + pageType: 'MapDesigner' | 'DailyChallenge' | 'Tutorials'; } export default function MapDesigner(props: MapDesignerProps): JSX.Element { @@ -32,11 +33,14 @@ export default function MapDesigner(props: MapDesignerProps): JSX.Element { const mapAPI = new MapApi(apiConfig); const dcAPI = new DailyChallengesApi(apiConfig); const currentUserapi = new CurrentUserApi(apiConfig); + const tutorialAPI = new TutorialsApi(apiConfig); useEffect(() => { mapAPI .getLatestMap( - props.pageType == 'MapDesigner' ? 'NORMAL' : 'DAILY_CHALLENGE', + props.pageType == 'MapDesigner' || props.pageType == 'Tutorials' + ? 'NORMAL' + : 'DAILY_CHALLENGE', ) .then(mp => { setStagedMap(JSON.parse(mp.map)); @@ -102,7 +106,9 @@ export default function MapDesigner(props: MapDesignerProps): JSX.Element { mapAPI .updateLatestMap({ mapType: - props.pageType == 'MapDesigner' ? 'NORMAL' : 'DAILY_CHALLENGE', + props.pageType == 'MapDesigner' || props.pageType == 'Tutorials' + ? 'NORMAL' + : 'DAILY_CHALLENGE', mapImage: mapImg, map: JSON.stringify(stagedMap), lock: false, @@ -121,7 +127,9 @@ export default function MapDesigner(props: MapDesignerProps): JSX.Element { mapAPI .updateLatestMap({ mapType: - props.pageType == 'MapDesigner' ? 'NORMAL' : 'DAILY_CHALLENGE', + props.pageType == 'MapDesigner' || props.pageType == 'Tutorials' + ? 'NORMAL' + : 'DAILY_CHALLENGE', mapImage: mapImg, map: JSON.stringify(stagedMap), lock: true, @@ -150,6 +158,21 @@ export default function MapDesigner(props: MapDesignerProps): JSX.Element { } }); } + if (props.pageType == 'Tutorials') { + tutorialAPI + .createCodeTutorialMatch({ + value: JSON.stringify(stagedMap), + codeTutorialNumber: 4, + }) + .then(() => { + Toast.success('Code Tutorial submitted succesfully'); + }) + .catch(error => { + if (error instanceof ApiError) { + Toast.error(error.message); + } + }); + } break; case 'commit': if (!commitName) { @@ -180,7 +203,7 @@ export default function MapDesigner(props: MapDesignerProps): JSX.Element { useEffect(() => { MapDesignerUtils.setLocalStorageKey( - props.pageType == 'MapDesigner' + props.pageType == 'MapDesigner' || props.pageType == 'Tutorials' ? 'cc-map-designer-map' : 'dc-map-designer-map', ); diff --git a/src/components/NavBar/NavBar.module.css b/src/components/NavBar/NavBar.module.css index 5bc182b..3560abb 100644 --- a/src/components/NavBar/NavBar.module.css +++ b/src/components/NavBar/NavBar.module.css @@ -5,6 +5,8 @@ background-color: #232627; width: 100%; z-index: 1000; + padding-left: 1%; + padding-right: 1%; } .navBarContainer { @@ -60,6 +62,9 @@ .branding { position: relative; + display: flex; + flex-direction: row; + justify-content: space-between; } .profileIcons { @@ -119,6 +124,54 @@ opacity: 0.8; } +.tutorialIcon { + height: 37px; + width: auto; + margin-top: 5px; + position: relative; + margin-right: 2rem; +} + +.tutorialIcon:hover{ + cursor: pointer; + opacity: 0.8; +} + +.navbarTextButton { + background-color: #374043; + color: #fff; + border: none; + height: 50%; + width: max-content; + padding: 8px 10px; + font-size: 20px; + cursor: pointer; + border-radius: 5px; + margin-right: 40px; +} + +.navbarTextButton:hover { + background-color: #141515; +} +.codeContainer { + display: flex; + justify-content: center; + align-items: center; + height: 60px; +} +.codeTutorialHeading { + font-family: 'Bai Jamjuree', sans-serif; + color: #ffffff; + font-size: 28px; + margin: 0.5rem 1rem; +} +.notifIconContainer { + display: flex; + justify-content: center; + align-items: center; +} + + @media screen and (max-width:650px) { .navLogo { font-size: 20px; diff --git a/src/components/NavBar/NavBar.tsx b/src/components/NavBar/NavBar.tsx index 3a98a80..2efbf0c 100644 --- a/src/components/NavBar/NavBar.tsx +++ b/src/components/NavBar/NavBar.tsx @@ -17,18 +17,20 @@ import { apiConfig, ApiError } from '../../api/ApiConfig'; import Toast from 'react-hot-toast'; import DashboardOptions from '../DashboardOptions/DashboardOptions'; import { cookieDomain, dcEnable } from '../../config/config'; - import signUpIcon from '../../assets/sign_up.svg'; import signInIcon from '../../assets/sign_in.svg'; import challengeDone from '../../assets/challenge_done.png'; import challengeAvailable from '../../assets/challenge_available.png'; +import tutorialIcon from '../../assets/tutorial.png'; import DcCompleted from '../DcModals/DcCompleted'; import DcAvailable from '../DcModals/DcAvailable'; import { changePageState, changeSimulationState, dailyChallengeCompletionState, + dailyChallengePageState, } from '../../store/DailyChallenge/dailyChallenge'; +import ViewTutorial from '../TutorialModals/ViewTutorial'; const NavBar: React.FunctionComponent = () => { const dispatch = useAppDispatch(); @@ -37,6 +39,7 @@ const NavBar: React.FunctionComponent = () => { const loggedInUser = useAppSelector(user); const isLogged = useAppSelector(isloggedIn); const loadingAuth = useAppSelector(loading); + const pageState = useAppSelector(dailyChallengePageState); const dcCompletionstatus = useAppSelector(dailyChallengeCompletionState); useEffect(() => { const cookieValue = document.cookie; @@ -108,6 +111,18 @@ const NavBar: React.FunctionComponent = () => { setShowCompleted(false); }; + const [showTutorial, setShowTutorial] = useState(false); + const handleTutorialTake = () => { + dispatch(changePageState('Tutorials')); + navigate('/dashboard', { replace: true }); + setShowTutorial(false); + }; + const handleTutorialClose = () => { + dispatch(changePageState('Dashboard')); + navigate('/dashboard'); + setShowTutorial(false); + }; + return (
{ handleClose={handleCloseAvailable} handleTake={handleTake} /> +
{''}
+
+ {pageState == 'Tutorials' ? ( +
+ {'Code Tutorials'} +
+ ) : ( + <> + )} +
{(location.pathname === '/' || location.pathname === '/register') && @@ -159,6 +188,19 @@ const NavBar: React.FunctionComponent = () => { location.pathname != '/' ? (
+ {pageState == 'Dashboard' ? ( + { + setShowTutorial(true); + }} + /> + ) : ( + <> + )} + {dcEnable ? ( { updateTutorialLevel: 'SKIP', }) .then(() => { - Toast.success('Tutorial skipped'); + Toast.success('Tour skipped'); }) .catch(err => { if (err instanceof ApiError) Toast.error(err.message); diff --git a/src/components/TutorialModals/TutorialModals.module.css b/src/components/TutorialModals/TutorialModals.module.css new file mode 100644 index 0000000..da07fc0 --- /dev/null +++ b/src/components/TutorialModals/TutorialModals.module.css @@ -0,0 +1,52 @@ +.tutorialModal{ + background-color: #1e1e1e; + box-shadow: 0px 3px 6px 4px rgb(28 32 33 / 20%); + color: #aaaaaa; + font-family: 'Poppins'; + font-weight: 400; + font-size: 18px; + } + +.tutorialModal > *{ + border: 0; +} + +.headerText{ + font-family: 'Poppins'; + font-size: 28px; + color:#aaaaaa; + font-weight: bold; + } + +.tutorialModalHeader{ + background-color: #232627; + backdrop-filter: blur(100px); + height: 9vh; + border: 0px; +} + +.tutorialModalBtn{ + width: auto; + display: block; + border: 2px solid #aaaaaa; + margin-top: 15px; + padding: 2px 12px; + font-size: 18px; + font-family: 'Poppins'; + font-weight: 400; + color: #aaaaaa; + text-align: center; + margin-left: auto; + margin-right: auto; + margin-bottom: 10px; + background-color: transparent; +} + +.footer{ + display: flex; + flex-direction: row; + justify-content: space-evenly; + gap: 7rem; +} + + diff --git a/src/components/TutorialModals/TutorialModalsTypes.ts b/src/components/TutorialModals/TutorialModalsTypes.ts new file mode 100644 index 0000000..729c218 --- /dev/null +++ b/src/components/TutorialModals/TutorialModalsTypes.ts @@ -0,0 +1,5 @@ +export type TutorialProps = { + show: boolean; + handleTutorialClose: () => void; + handleTutorialTake?: () => void; +}; diff --git a/src/components/TutorialModals/ViewTutorial.tsx b/src/components/TutorialModals/ViewTutorial.tsx new file mode 100644 index 0000000..5843810 --- /dev/null +++ b/src/components/TutorialModals/ViewTutorial.tsx @@ -0,0 +1,45 @@ +import { Modal, Button } from 'react-bootstrap'; +import styles from './TutorialModals.module.css'; +import { TutorialProps } from './TutorialModalsTypes'; + +const ViewTutorial = (props: TutorialProps) => { + return ( + + + Code Tutorials + + + + Commander, we are here to help you started with some code tutorials of + the game. + + + + + + + ); +}; + +export default ViewTutorial; diff --git a/src/components/Websocket/Websocket.tsx b/src/components/Websocket/Websocket.tsx index ffe3975..f55dd30 100644 --- a/src/components/Websocket/Websocket.tsx +++ b/src/components/Websocket/Websocket.tsx @@ -4,7 +4,9 @@ import { Game, GameStatus, Notification, + TutorialGame, } from '@codecharacter-2024/client'; +import { RendererUtils } from '@codecharacter-2024/renderer'; import { apiConfig } from '../../api/ApiConfig'; import { Stomp } from '@stomp/stompjs'; import { useEffect, useState } from 'react'; @@ -13,13 +15,17 @@ import { getLogAction } from '../../store/rendererLogs/logSlice'; import { useAppDispatch, useAppSelector } from '../../store/hooks'; import { BASE_PATH } from '../../config/config'; import { CurrentGameType } from '../../store/editor/code'; -import { changeSimulationState } from '../../store/DailyChallenge/dailyChallenge'; +import { + changeSimulationState, + dailyChallengePageState, +} from '../../store/DailyChallenge/dailyChallenge'; export const Websocket: React.FunctionComponent = () => { const currentUserapi = new CurrentUserApi(apiConfig); const dispatch = useAppDispatch(); const gameType = useAppSelector(CurrentGameType); const [user, setUser] = useState(); + const pageType = useAppSelector(dailyChallengePageState); useEffect(() => { if (!user) return; @@ -29,34 +35,39 @@ export const Websocket: React.FunctionComponent = () => { wsClient.brokerURL = url; const handleConnect = () => { wsClient.subscribe(`/updates/${user.id}`, message => { - const game = JSON.parse(message.body) as Game; - switch (game.status) { - case GameStatus.Executing: - Toast.success('Executing now...'); - break; - case GameStatus.Executed: - Toast.success('Executed successfully!'); - // TODO: find non-hacky way to do this - dispatch(changeSimulationState(true)); - dispatch( - getLogAction({ - id: game.id, - callback: () => (window.location.href = './#/dashboard'), - gameType: gameType, - }), - ); - break; - case GameStatus.ExecuteError: - Toast.error('Execution error!'); - dispatch(changeSimulationState(true)); - dispatch( - getLogAction({ - id: game.id, - callback: () => (window.location.href = './#/dashboard'), - gameType: gameType, - }), - ); - break; + if (pageType === 'Tutorials') { + const game = JSON.parse(message.body) as TutorialGame; + RendererUtils.loadLog(game.logs ?? ''); + } else { + const game = JSON.parse(message.body) as Game; + switch (game.status) { + case GameStatus.Executing: + Toast.success('Executing now...'); + break; + case GameStatus.Executed: + Toast.success('Executed successfully!'); + // TODO: find non-hacky way to do this + dispatch(changeSimulationState(true)); + dispatch( + getLogAction({ + id: game.id, + callback: () => (window.location.href = './#/dashboard'), + gameType: gameType, + }), + ); + break; + case GameStatus.ExecuteError: + Toast.error('Execution error!'); + dispatch(changeSimulationState(true)); + dispatch( + getLogAction({ + id: game.id, + callback: () => (window.location.href = './#/dashboard'), + gameType: gameType, + }), + ); + break; + } } message.ack(); }); @@ -78,7 +89,7 @@ export const Websocket: React.FunctionComponent = () => { return () => { wsClient.deactivate(); }; - }, [user, gameType]); + }, [user, gameType, pageType]); useEffect(() => { if (localStorage.getItem('token') === null) return; diff --git a/src/pages/Dashboard/Dashboard.module.css b/src/pages/Dashboard/Dashboard.module.css index 6c16ef5..88873aa 100644 --- a/src/pages/Dashboard/Dashboard.module.css +++ b/src/pages/Dashboard/Dashboard.module.css @@ -49,6 +49,7 @@ .toolbarColumn { padding: 0px; + margin-right: 17px; } .toolbarColumn1 { @@ -109,6 +110,20 @@ outline: none; box-shadow: none; } +.toolbarTextButton { + background-color: #292929; + color: #fff; + border: none; + padding: 8px 10px; + font-size: 14px; + cursor: pointer; + border-radius: 5px; + margin-right: 10px; +} + +.toolbarTextButton:hover { + background-color: #141515; +} .toolbarButton2 { font-size: 0.9rem; @@ -255,3 +270,16 @@ color: #ffffff; transform: scale(1.15); } + +.codeContainer { + display: flex; + justify-content: center; + align-items: center; + height: 60px; + } +.codeTutorialHeading { +font-family: 'Bai Jamjuree', sans-serif; +color: #ffffff; +font-size: 17px; +margin: 0.5rem 1rem; +} diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx index 395e91f..e2a2bcf 100644 --- a/src/pages/Dashboard/Dashboard.tsx +++ b/src/pages/Dashboard/Dashboard.tsx @@ -4,6 +4,7 @@ import { DailyChallengesApi, CurrentUserApi, CodeType, + TutorialsApi, } from '@codecharacter-2024/client'; import { RendererComponent } from '@codecharacter-2024/renderer'; import Toast from 'react-hot-toast'; @@ -69,11 +70,18 @@ import { dailyChallengeState, initializeDailyChallengeState, dailyChallengePageState, - changeDcLanguage, dcCodeLanguage, dcCode, dcSimulation, + changeDcLanguage, } from '../../store/DailyChallenge/dailyChallenge'; +import { + initializeTutorialState, + changeTutorialLanguage, + tutorialCode, + tutorialCodeLanguage, + tutorialAllLanguagesCode, +} from '../../store/Tutorials/tutorials'; import Tour from '../../components/TourProvider/TourProvider'; import { EditorSteps } from '../../components/TourProvider/EditorSteps'; import { useNavigate } from 'react-router-dom'; @@ -134,13 +142,19 @@ export default function Dashboard(): JSX.Element { const pageState = useAppSelector(dailyChallengePageState); const dailyChallengeSimulationState = useAppSelector(dcSimulation); const currentGameType = useAppSelector(CurrentGameType); + const tutorialsCode = useAppSelector(tutorialCode); const userLanguage = pageState == 'Dashboard' ? useAppSelector(UserLanguage) - : useAppSelector(dcCodeLanguage); - + : pageState == 'DailyChallenge' + ? useAppSelector(dcCodeLanguage) + : useAppSelector(tutorialCodeLanguage); const codeAPI = new CodeApi(apiConfig); const dailyChallengeAPI = new DailyChallengesApi(apiConfig); + const tutorialAPI = new TutorialsApi(apiConfig); + const maxUserCodeTutorialLevel = useAppSelector(codeTutorialLevel); + const [codeTutorialNumber, setTutorialNumber] = useState(1); + const tutorialLanguagesCode = useAppSelector(tutorialAllLanguagesCode); useEffect(() => { const cookieValue = document.cookie; const bearerToken = cookieValue.split(';'); @@ -164,6 +178,17 @@ export default function Dashboard(): JSX.Element { }); } }, []); + useEffect(() => { + tutorialAPI + .getCodeTutorialByNumber(maxUserCodeTutorialLevel) + .then(response => { + setTutorialNumber(response.tutorialId ?? 1); + dispatch(initializeTutorialState(response)); + }) + .catch(err => { + if (err instanceof ApiError) Toast.error(err.message); + }); + }, []); useEffect(() => { if (localStorage.getItem('firstTime') === null) { @@ -206,6 +231,9 @@ export default function Dashboard(): JSX.Element { case 'DailyChallenge': dispatch(changeDcLanguage('c_cpp')); break; + case 'Tutorials': + dispatch(changeTutorialLanguage('c_cpp')); + break; default: dispatch(changeLanguage('c_cpp')); } @@ -213,17 +241,36 @@ export default function Dashboard(): JSX.Element { localStorage.setItem('languageChose', 'C++'); break; case 'Python': - pageState == 'Dashboard' - ? dispatch(changeLanguage('python')) - : dispatch(changeDcLanguage('python')); + switch (pageState) { + case 'Dashboard': + dispatch(changeLanguage('python')); + break; + case 'DailyChallenge': + dispatch(changeDcLanguage('python')); + break; + case 'Tutorials': + dispatch(changeTutorialLanguage('python')); + break; + default: + dispatch(changeLanguage('python')); + } setLanguageChose('Python'); localStorage.setItem('languageChose', 'Python'); break; case 'Java': - pageState == 'Dashboard' - ? dispatch(changeLanguage('java')) - : dispatch(changeDcLanguage('java')); - + switch (pageState) { + case 'Dashboard': + dispatch(changeLanguage('java')); + break; + case 'DailyChallenge': + dispatch(changeDcLanguage('java')); + break; + case 'Tutorials': + dispatch(changeTutorialLanguage('java')); + break; + default: + dispatch(changeLanguage('java')); + } setLanguageChose('Java'); localStorage.setItem('languageChose', 'Java'); break; @@ -252,7 +299,7 @@ export default function Dashboard(): JSX.Element { if (userLanguage === 'c_cpp') languageType = Language.Cpp; else if (userLanguage === 'python') languageType = Language.Python; else if (userLanguage === 'java') languageType = Language.Java; - + if(pageState == 'Tutorials') return; codeAPI .updateLatestCode({ codeType: @@ -309,13 +356,12 @@ export default function Dashboard(): JSX.Element { if (isInfoOpen === true) dispatch(isInfoOpened(false)); else dispatch(isInfoOpened(true)); } - const handleSubmit = () => { let languageType: Language = Language.Cpp; if (userLanguage === 'c_cpp') languageType = Language.Cpp; else if (userLanguage === 'python') languageType = Language.Python; else if (userLanguage === 'java') languageType = Language.Java; - + if(pageState!='Tutorials'){ codeAPI .updateLatestCode({ codeType: @@ -336,6 +382,7 @@ export default function Dashboard(): JSX.Element { .catch(err => { if (err instanceof ApiError) Toast.error(err.message); }); + } if (pageState == 'DailyChallenge') { dailyChallengeAPI @@ -350,13 +397,54 @@ export default function Dashboard(): JSX.Element { if (err instanceof ApiError) Toast.error(err.message); }); } + if (pageState == 'Tutorials') { + tutorialAPI + .createCodeTutorialMatch({ + value: tutorialsCode, + language: languageType, + codeTutorialNumber: codeTutorialNumber, + }) + .then(() => { + Toast.success('Code Tutorial Submitted'); + }) + .catch(err => { + if (err instanceof ApiError) Toast.error(err.message); + }); + } + }; + const handleNextTutorial = () => { + tutorialAPI + .getCodeTutorialByNumber(codeTutorialNumber + 1) + .then(response => { + dispatch(initializeTutorialState(response)); + setTutorialNumber(codeTutorialNumber + 1); + }) + .catch(err => { + // if (err.message == 'Complete the current tutorial first') { + // setTutorialNumber(tutorialNumber - 1); + // } + if (err instanceof ApiError) Toast.error(err.message); + }); + }; + // console.log(tutorialAllLanguagesCode[]); + const handlePrevTutorial = () => { + tutorialAPI + .getCodeTutorialByNumber(codeTutorialNumber - 1) + .then(response => { + dispatch(initializeTutorialState(response)); + setTutorialNumber(codeTutorialNumber - 1); + }) + .catch(err => { + if (err.message == 'Complete the current tutorial first') { + setTutorialNumber(codeTutorialNumber - 1); + } + if (err instanceof ApiError) Toast.error(err.message); + }); }; - const currentUserApi = new CurrentUserApi(apiConfig); const User = useAppSelector(user); const navigate = useNavigate(); - const setOpened = (opened: boolean) => { if (opened === false) { currentUserApi @@ -565,6 +653,142 @@ export default function Dashboard(): JSX.Element {
+ ) : pageState == 'Tutorials' ? ( + +
+ + handleLanguageChange(e.target.value)} + id="LanguageSelector" + > + {languages.map(language => ( + + ))} + + +
+ {codeTutorialNumber == 4 ? ( + <> + ) : ( + + + + )} + <> + {codeTutorialNumber == 1 ? ( + <> + ) : ( + + )} + {codeTutorialNumber == 4 ? ( + <> + ) : ( + + )} + +
+ {pageState == 'Tutorials' ? ( +
+ {'Tutorial Number '} + {codeTutorialNumber} +
+ ) : ( + <> + )} +
+
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
) : ( <>
@@ -596,13 +820,32 @@ export default function Dashboard(): JSX.Element { )}
{pageState == 'Dashboard' || - dailyChallenge.challType == 'MAP' ? ( + dailyChallenge.challType == 'MAP' || + (pageState == 'Tutorials' && codeTutorialNumber != 4) ? ( + ) : pageState == 'Tutorials' && codeTutorialNumber == 4 ? ( + ) : (
- {pageState == 'Dashboard' || dailyChallengeSimulationState ? ( + {pageState == 'Dashboard' || + (pageState == 'Tutorials' && codeTutorialNumber != 4) || + dailyChallengeSimulationState ? ( ) : dailyChallenge.challType == 'MAP' ? ( <> @@ -662,12 +911,16 @@ export default function Dashboard(): JSX.Element { >
+ ) : pageState == 'Tutorials' && codeTutorialNumber == 4 ? ( + ) : ( )}
- {pageState == 'Dashboard' || dailyChallengeSimulationState ? ( + {pageState == 'Dashboard' || + pageState == 'Tutorials' || + dailyChallengeSimulationState ? ( ) : ( <> diff --git a/src/store/DailyChallenge/dailyChallenge.ts b/src/store/DailyChallenge/dailyChallenge.ts index c44c8ba..49bf23f 100644 --- a/src/store/DailyChallenge/dailyChallenge.ts +++ b/src/store/DailyChallenge/dailyChallenge.ts @@ -14,7 +14,7 @@ import defaultJavaCode from '../../assets/codes/java/Run.java?raw'; export interface DailyChallengeStateType { dailyChallenge: DailyChallengeGetRequest; - pageType: 'Dashboard' | 'DailyChallenge'; + pageType: 'Dashboard' | 'DailyChallenge' | 'Tutorials'; dcCode: string; dcAllLanguagesCode: string[]; codeLanguage: string; @@ -67,7 +67,7 @@ export const dailyChallengeSlice = createSlice({ }, changePageState: ( state, - action: PayloadAction<'Dashboard' | 'DailyChallenge'>, + action: PayloadAction<'Dashboard' | 'DailyChallenge' | 'Tutorials'>, ) => { state.pageType = action.payload; }, @@ -116,7 +116,8 @@ export const dailyChallengeState = ( ): DailyChallengeGetRequest => state.dailyChallenge.dailyChallenge; export const dailyChallengePageState = ( state: RootState, -): 'Dashboard' | 'DailyChallenge' => state.dailyChallenge.pageType; +): 'Dashboard' | 'DailyChallenge' | 'Tutorials' => + state.dailyChallenge.pageType; export const dailyChallengeCompletionState = ( state: RootState, ): boolean | undefined => state.dailyChallenge.dailyChallenge.completionStatus; diff --git a/src/store/Tutorials/tutorials.ts b/src/store/Tutorials/tutorials.ts new file mode 100644 index 0000000..af24298 --- /dev/null +++ b/src/store/Tutorials/tutorials.ts @@ -0,0 +1,120 @@ +import { ChallengeType, TutorialsGetRequest } from '@codecharacter-2024/client'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { RootState } from '../store'; +import { CodeAndLanguage, languagesAvailable } from '../editor/code'; +import defaultCppCode from '../../assets/codes/cpp/run.cpp?raw'; +import defaultPythonCode from '../../assets/codes/python/run.py?raw'; +import defaultJavaCode from '../../assets/codes/java/Run.java?raw'; + +export interface TutorialStateType { + tutorials: TutorialsGetRequest; + tutorialCode: string | undefined; + tutorialAllLanguagesCode: string[]; + tutorialLanguage: string; + tutorialMap: Array>; + isCompleted: boolean; + tutorialId: number; +} + +const initialState: TutorialStateType = { + tutorials: { + tutorialName: '', + description: '', + tutorialType: '' as ChallengeType, + tutorialCodes: { + cpp: ' ', + java: ' ', + python: ' ', + image: ' ', + }, + }, + tutorialCode: defaultCppCode, + tutorialAllLanguagesCode: [ + defaultCppCode, + defaultPythonCode, + defaultJavaCode, + ], + tutorialLanguage: 'c_cpp', + tutorialMap: [], + isCompleted: false, + tutorialId: 1, +}; + +export const tutorialsSlice = createSlice({ + name: 'tutorialsState', + initialState, + reducers: { + initializeTutorialState: ( + state, + action: PayloadAction, + ) => { + state.tutorials.tutorialName = action.payload.tutorialName; + (state.tutorials.description = action.payload.description + ? action.payload.description + : ''), + (state.tutorials.tutorialCodes = action.payload.tutorialCodes); + state.tutorialCode = action.payload.tutorialCodes.cpp; + state.tutorialAllLanguagesCode[0] = action.payload.tutorialCodes.cpp; + state.tutorialAllLanguagesCode[1] = action.payload.tutorialCodes.python; + state.tutorialAllLanguagesCode[2] = action.payload.tutorialCodes.java; + state.isCompleted = false; + }, + changeTutorialCode: (state, action: PayloadAction) => { + const tempCurrentUserLanguage = action.payload.currentUserLanguage; + const desiredIndex = languagesAvailable.indexOf(tempCurrentUserLanguage); + const newCodeAndLanguage: CodeAndLanguage = { + currentUserCode: action.payload.currentUserCode, + currentUserLanguage: action.payload.currentUserLanguage, + }; + state.tutorialAllLanguagesCode[desiredIndex] = + newCodeAndLanguage.currentUserCode; + state.tutorialCode = newCodeAndLanguage.currentUserCode; + }, + changeTutorialLanguage: (state, action: PayloadAction) => { + const tempCurrentUserLanguage = action.payload; + const desiredIndex = languagesAvailable.indexOf(tempCurrentUserLanguage); + state.tutorialCode = state.tutorialAllLanguagesCode[desiredIndex]; + state.tutorialLanguage = action.payload; + }, + changeTutorialMap: (state, action: PayloadAction>>) => { + state.tutorialMap = action.payload; + }, + changeTutorialId: (state, action: PayloadAction) => { + if (action.payload == 1) { + state.tutorialId = state.tutorialId + 1; + } else { + state.tutorialId = state.tutorialId - 1; + } + }, + changeCompletionState: (state, action: PayloadAction) => { + state.isCompleted = action.payload; + }, + }, +}); + +export const { + initializeTutorialState, + changeTutorialCode, + changeTutorialLanguage, + changeTutorialMap, + changeCompletionState, + changeTutorialId, +} = tutorialsSlice.actions; +export const tutorialState = (state: RootState): TutorialsGetRequest => + state.tutorials.tutorials; +export const tutorialCode = (state: RootState): string => + state.tutorials.tutorialCode; +export const tutorialDescription = (state: RootState): string | undefined => + state.tutorials.tutorials.description; +export const tutorialId = (state: RootState): number => + state.tutorials.tutorialId; +export const tutorialCodeLanguage = (state: RootState): string => + state.tutorials.tutorialLanguage; +export const tutorialMap = (state: RootState): Array> => + state.tutorials.tutorialMap; +export const tutorialCompletion = (state: RootState): boolean => + state.tutorials.isCompleted; +export const tutorialAllLanguagesCode = (state: RootState): string[] => + state.tutorials.tutorialAllLanguagesCode; + +export default tutorialsSlice.reducer; diff --git a/src/store/User/UserApi.ts b/src/store/User/UserApi.ts index 5ff471e..8384eae 100644 --- a/src/store/User/UserApi.ts +++ b/src/store/User/UserApi.ts @@ -66,6 +66,7 @@ export const getUserDetails = (): Promise<{ country: string; avatarId: number; isTutorialComplete: boolean; + codeTutorialNumber: number | undefined; }> => { return new Promise((resolve, reject) => { const currentUserapi = new CurrentUserApi(apiConfig); @@ -82,6 +83,7 @@ export const getUserDetails = (): Promise<{ country: res.country, avatarId: res.avatarId, isTutorialComplete: res.isTutorialComplete, + codeTutorialNumber: res.codeTutorialLevel, }); }) .catch(error => { diff --git a/src/store/User/UserSlice.ts b/src/store/User/UserSlice.ts index fec847a..258840d 100644 --- a/src/store/User/UserSlice.ts +++ b/src/store/User/UserSlice.ts @@ -20,6 +20,7 @@ export interface User { college: string; avatarId: number; recaptchaCode: string; + codeTutorialNumber: number; } interface register { @@ -48,6 +49,7 @@ const initialState: register = { college: '', avatarId: 0, recaptchaCode: '', + codeTutorialNumber: 1, }, loading: false, isRegistered: false, @@ -203,6 +205,7 @@ export const UserSlice = createSlice({ state.user.country = action.payload.country; state.user.college = action.payload.college; state.user.avatarId = action.payload.avatarId; + state.user.codeTutorialNumber = action.payload.codeTutorialNumber; }) .addCase(getUserDetailsAction.rejected, state => { state.loading = false; @@ -259,5 +262,7 @@ export const isSuccess = (state: RootState): boolean => state.user.isSuccessCreditonals; export const isSuccessUser = (state: RootState): boolean => state.user.isSuccessUser; +export const codeTutorialLevel = (state: RootState): number => + state.user.user.codeTutorialNumber; export default UserSlice.reducer; diff --git a/src/store/store.ts b/src/store/store.ts index 44a51f0..3aa66be 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -14,7 +14,7 @@ import logReducer from './rendererLogs/logSlice'; import selfMatchModalReducer from './SelfMatchMakeModal/SelfMatchModal'; import PvPSelfMatchModalReducer from './PvPSelfMatchMakeModal/PvPSelfMatchModal'; import dailyChallengeReducer from './DailyChallenge/dailyChallenge'; - +import tutorialReducer from './Tutorials/tutorials'; const reducers = combineReducers({ editorState: editorReducer, settingsState: settingsReducer, @@ -38,6 +38,7 @@ export const store = configureStore({ selfMatchModal: selfMatchModalReducer, pvpSelfMatchModal: PvPSelfMatchModalReducer, dailyChallenge: dailyChallengeReducer, + tutorials: tutorialReducer, }, middleware: [thunk], }); From 7b2e6ff380af9be60331bef9cb7d6735fa7a052e Mon Sep 17 00:00:00 2001 From: shubham-1806 Date: Sun, 11 Feb 2024 16:29:13 +0530 Subject: [PATCH 2/3] fix: dashboard --- src/pages/Dashboard/Dashboard.tsx | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx index e2a2bcf..ece6e18 100644 --- a/src/pages/Dashboard/Dashboard.tsx +++ b/src/pages/Dashboard/Dashboard.tsx @@ -54,7 +54,7 @@ import { code2CommitNameChanged, isPvPSelfMatchModalOpened, } from '../../store/PvPSelfMatchMakeModal/PvPSelfMatchModal'; -import { loggedIn, user } from '../../store/User/UserSlice'; +import { codeTutorialLevel, loggedIn, user } from '../../store/User/UserSlice'; import { IsSettingsOpen, @@ -299,7 +299,7 @@ export default function Dashboard(): JSX.Element { if (userLanguage === 'c_cpp') languageType = Language.Cpp; else if (userLanguage === 'python') languageType = Language.Python; else if (userLanguage === 'java') languageType = Language.Java; - if(pageState == 'Tutorials') return; + if (pageState == 'Tutorials') return; codeAPI .updateLatestCode({ codeType: @@ -361,27 +361,27 @@ export default function Dashboard(): JSX.Element { if (userLanguage === 'c_cpp') languageType = Language.Cpp; else if (userLanguage === 'python') languageType = Language.Python; else if (userLanguage === 'java') languageType = Language.Java; - if(pageState!='Tutorials'){ - codeAPI - .updateLatestCode({ - codeType: - pageState == 'Dashboard' - ? currentGameType == GameType.NORMAL - ? 'NORMAL' - : 'PVP' - : 'DAILY_CHALLENGE', - code: pageState == 'Dashboard' ? userCode : dailyChallengeCode, - lock: true, - language: languageType, - }) - .then(() => { - if (pageState == 'Dashboard') { - Toast.success('Code Submitted'); - } - }) - .catch(err => { - if (err instanceof ApiError) Toast.error(err.message); - }); + if (pageState != 'Tutorials') { + codeAPI + .updateLatestCode({ + codeType: + pageState == 'Dashboard' + ? currentGameType == GameType.NORMAL + ? 'NORMAL' + : 'PVP' + : 'DAILY_CHALLENGE', + code: pageState == 'Dashboard' ? userCode : dailyChallengeCode, + lock: true, + language: languageType, + }) + .then(() => { + if (pageState == 'Dashboard') { + Toast.success('Code Submitted'); + } + }) + .catch(err => { + if (err instanceof ApiError) Toast.error(err.message); + }); } if (pageState == 'DailyChallenge') { From 32fcc2465bbda0403556f683f6bd1d22993d0d14 Mon Sep 17 00:00:00 2001 From: shubham-1806 Date: Sun, 11 Feb 2024 19:20:48 +0530 Subject: [PATCH 3/3] fix: pvpLeaderboard, battleaTV --- packages/renderer/src/RendererUtils.ts | 1 - src/components/BattleTV/BattleTV.tsx | 24 +++++++++++------------ src/components/Editor/Editor.tsx | 9 +++++++++ src/components/GraphToolTips/ToolTips.tsx | 11 ----------- src/pages/Dashboard/Dashboard.tsx | 1 - src/pages/Statistics/Statistics.tsx | 1 - 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/packages/renderer/src/RendererUtils.ts b/packages/renderer/src/RendererUtils.ts index c8f0d48..5eb6c83 100644 --- a/packages/renderer/src/RendererUtils.ts +++ b/packages/renderer/src/RendererUtils.ts @@ -3,7 +3,6 @@ import { events, RendererEvents } from './events/EventEmitter'; export class RendererUtils { static loadLog(log: string): void { - console.log('loadLog', log); events.emit(RendererEvents.LOAD_LOG, log); events.emit(RendererEvents.RESET_UI); } diff --git a/src/components/BattleTV/BattleTV.tsx b/src/components/BattleTV/BattleTV.tsx index 7339b74..58b36b3 100644 --- a/src/components/BattleTV/BattleTV.tsx +++ b/src/components/BattleTV/BattleTV.tsx @@ -153,11 +153,11 @@ function PaginatedItems({ battleTvType }: { battleTvType: BattleType }) { ? match.game.scorePlayer1 : [...match.games.values()][0].coinsUsed} - - {'game' in match - ? '----' - : [...match.games.values()][0].destruction.toFixed(2)} - + {'games' in match && ( + + {[...match.games.values()][0].destruction.toFixed(2)} + + )}
{ @@ -192,13 +192,13 @@ function PaginatedItems({ battleTvType }: { battleTvType: BattleType }) { [...match.games.values()].length === 1 ? 0 : 1 ].destruction.toFixed(2)} - - {'game' in match - ? '----' - : [...match.games.values()][ - [...match.games.values()].length === 1 ? 0 : 1 - ].coinsUsed} - + {'games' in match && ( + + {[...match.games.values()][ + [...match.games.values()].length === 1 ? 0 : 1 + ].destruction.toFixed(2)} + + )} {match.user2 !== null diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index f3a8063..e446088 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -61,6 +61,7 @@ import { } from '../../store/Tutorials/tutorials'; import { buildWorkerDefinition } from 'monaco-editor-workers'; import { Uri } from 'vscode'; +import toast from 'react-hot-toast'; buildWorkerDefinition( '../../node_modules/monaco-editor-workers/dist/workers', @@ -231,6 +232,14 @@ export default function CodeEditor(props: Editor.Props): JSX.Element { props.language == 'c_cpp' ? 'cpp' : props.language }`; wsClient = new WebSocket(url); + wsClient.onerror = () => { + toast.error('Error occured in lsp'); + editor = createEditor( + divCodeEditor.current as HTMLDivElement, + null, + null, + ); + }; wsClient.onopen = () => { const updater = { operation: 'fileUpdate', diff --git a/src/components/GraphToolTips/ToolTips.tsx b/src/components/GraphToolTips/ToolTips.tsx index 93a9a84..cb4ad68 100644 --- a/src/components/GraphToolTips/ToolTips.tsx +++ b/src/components/GraphToolTips/ToolTips.tsx @@ -1,7 +1,5 @@ import styles from './GraphToolTip.module.css'; export const BarChartToolTip = ({ active, payload }: ToolTipProps) => { - console.log(active); - console.log(payload); if (active && payload && payload.length) { return (
@@ -17,9 +15,6 @@ export const BarChartToolTip = ({ active, payload }: ToolTipProps) => { }; export const LineChartToolTip = ({ active, payload }: ToolTipProps) => { - console.log(active); - console.log(payload); - if (active && payload && payload.length) { return (
@@ -38,9 +33,6 @@ export const LineChartToolTip = ({ active, payload }: ToolTipProps) => { }; export const AreaChartToolTip = ({ active, payload }: ToolTipProps) => { - console.log(active); - console.log(payload); - if (active && payload && payload.length) { return (
@@ -61,9 +53,6 @@ export const AreaChartToolTip = ({ active, payload }: ToolTipProps) => { return null; }; export const DCToolTip = ({ active, payload }: ToolTipProps) => { - console.log(active); - console.log(payload); - if (active && payload && payload.length) { return (
diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx index ece6e18..21a849f 100644 --- a/src/pages/Dashboard/Dashboard.tsx +++ b/src/pages/Dashboard/Dashboard.tsx @@ -426,7 +426,6 @@ export default function Dashboard(): JSX.Element { if (err instanceof ApiError) Toast.error(err.message); }); }; - // console.log(tutorialAllLanguagesCode[]); const handlePrevTutorial = () => { tutorialAPI .getCodeTutorialByNumber(codeTutorialNumber - 1) diff --git a/src/pages/Statistics/Statistics.tsx b/src/pages/Statistics/Statistics.tsx index 39c331d..e5bf479 100644 --- a/src/pages/Statistics/Statistics.tsx +++ b/src/pages/Statistics/Statistics.tsx @@ -46,7 +46,6 @@ const Statistics = () => { } cdata.push(currentDataObject); } - console.log(cdata); setData(cdata); }) .catch(error => {