From d31197505a08c0bd662beeb4c1f2d8b0bc66a16d Mon Sep 17 00:00:00 2001 From: kdj309 Date: Sun, 9 Nov 2025 11:05:59 +0530 Subject: [PATCH 1/6] backend code submission integration --- src/components/Pages/Problem/Index.tsx | 51 +++++++++++++++----------- src/services/addSubmission.ts | 7 ++-- src/services/batchwiseSubmission.ts | 17 +++++---- src/services/getSubmissionStatus.ts | 2 +- src/services/sumbitCode.ts | 21 +++++++---- src/services/updateSubmission.ts | 12 ++++-- src/utils/types.ts | 18 ++++++++- 7 files changed, 82 insertions(+), 46 deletions(-) diff --git a/src/components/Pages/Problem/Index.tsx b/src/components/Pages/Problem/Index.tsx index ec65019..6f5dd0e 100644 --- a/src/components/Pages/Problem/Index.tsx +++ b/src/components/Pages/Problem/Index.tsx @@ -18,7 +18,6 @@ import { Problem as ProblemType, problemsubmissionstatus, submission, user } fro import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord'; import { useUserSlice } from '../../../store/user'; import SkeletonResultsLoader from '../../UI/SkeletonResultsLoader'; -import addSubmission from '../../../services/addSubmission'; import batchwiseSubmission from '../../../services/batchwiseSubmission'; import ProblemSubmissions from './ProblemSubmissions'; import SettingsOverscanOutlinedIcon from '@mui/icons-material/SettingsOverscanOutlined'; @@ -36,6 +35,7 @@ import { useCodeStorage } from '../../../db'; import OpenInFullOutlinedIcon from '@mui/icons-material/OpenInFullOutlined'; import RestoreOutlinedIcon from '@mui/icons-material/RestoreOutlined'; import useFullScreen from '../../../hooks/useFullScreen'; +import updateSubmission from '../../../services/updateSubmission'; export default function Problem() { const { problemname } = useParams(); @@ -155,15 +155,15 @@ export default function Problem() { monacoinstance.editor.defineTheme('mydarkTheme', darktheme as theme); }); }, [colorMode]); - const { mutateAsync } = useMutation({ + const { mutateAsync:submitProblem } = useMutation({ mutationKey: ['codesubmission'], mutationFn: submitCode, }); - const { mutateAsync: updateSubmitMutateAsync } = useMutation({ - mutationKey: ['updatesubmission'], - mutationFn: addSubmission, - }); + const { mutateAsync: updateUserSubmissionById } = useMutation({ + mutationKey: ['updatesubmissionById'], + mutationFn: updateSubmission, + }); const firstPanelTabLabels = useMemo(() => ['Description', 'Submissions'], []); const secondPanelTabLabels = useMemo(() => ['Code', 'Test Results', 'Output'], []); const handleClose = () => { @@ -265,14 +265,18 @@ export default function Problem() { setCurrentTab(1); const testcases = problemInfo?.testCases; const [firsttestcase] = testcases; - const response = await mutateAsync({ + const response = await submitProblem({ code, expected_output: firsttestcase.output, - input: firsttestcase.input, + stdin: firsttestcase.input, language_id: language, + userId:user?._id as string }); - setSubmissionId(response?.data.token); - await getSubmission(response?.data.token); + console.log(response) + setSubmissionId(response?.data?.data); + const problemSubmissionData=await getSubmission(response?.data?.data); + + console.log({problemSubmissionData}) } catch (error) { setIsSumbitted(false); console.log(error); @@ -305,11 +309,12 @@ export default function Problem() { try { setCurrentTab(2); setProblemSubmissionLoading(true); - const batchwiseresponse = await batchwiseSubmission(submissionbatch); + const batchwiseresponses = await batchwiseSubmission(user?._id as string,submissionbatch); // @ts-ignore const batchwiseresponsepromises = []; - batchwiseresponse?.forEach((submission) => { - batchwiseresponsepromises.push(getSubmission(submission.token)); + setSubmissionId(batchwiseresponses?._id as string); + batchwiseresponses?.submissionIds.forEach((submissiontoken) => { + batchwiseresponsepromises.push(getSubmission(submissiontoken)) }); // @ts-ignore const batchwiseresults = await Promise.all(batchwiseresponsepromises); @@ -325,13 +330,14 @@ export default function Problem() { problemId: problemname?.slice(0, 24) as string, languageId: language, status: status ? 'Accepted' : 'Wrong Answer', - submissionId: submissionId, + submissionId: batchwiseresponses?._id as string, submittedAt: new Date(), + actual_output:batchwiseresults.map((r)=>r.stdout), + memoryUsed:batchwiseresults.map((r)=>r.memory), + executionTime:batchwiseresults.map((r)=>r.time) }; - const submissionupdateResponse = await updateSubmitMutateAsync({ - id: user?._id as string, - newsubmission: updatesubmissionbody, - }); + const submissionUpdateResponse= await updateUserSubmissionById({submissionId:batchwiseresponses?._id as string,userId:user?._id as string,updateduser:updatesubmissionbody}); + console.log(submissionUpdateResponse) setProblemSubmissions((prev) => [...prev, updatesubmissionbody]); setUser({ ...(user as user), @@ -339,7 +345,7 @@ export default function Problem() { ...(user?.submissions ?? []), { problemId: problemname?.slice(0, 24) as string, - submissionId: submissionupdateResponse?.data._id as string, + submissionId: batchwiseresponses?._id as string, languageId: language, status: status ? 'Accepted' : 'Wrong Answer', submittedAt: new Date(), @@ -349,9 +355,10 @@ export default function Problem() { } catch (error) { setProblemSubmissionLoading(false); setProblemSubmissionStatus('Rejected'); - await updateSubmitMutateAsync({ - id: user?._id as string, - newsubmission: { + await updateUserSubmissionById({ + submissionId, + userId:user?._id as string, + updateduser: { problemId: problemname?.slice(0, 24) as string, languageId: language, status: 'Wrong Answer', diff --git a/src/services/addSubmission.ts b/src/services/addSubmission.ts index 51645f2..3bd145a 100644 --- a/src/services/addSubmission.ts +++ b/src/services/addSubmission.ts @@ -1,9 +1,10 @@ import { protectedapi } from '../API/Index'; import { submissionprops, updateUserType } from '../utils/types'; -const addSubmission = async (updateUserProps: { id: string; newsubmission: submissionprops }) => { +// +const runCode = async (updateUserProps: { id: string; newsubmission: submissionprops }) => { try { const response = await protectedapi.patch( - `/users/${updateUserProps.id}/submission`, + `/users/${updateUserProps.id}/submission/${updateUserProps.newsubmission.submissionId}`, updateUserProps.newsubmission ); if (response.data.status === 'Failure') { @@ -17,4 +18,4 @@ const addSubmission = async (updateUserProps: { id: string; newsubmission: submi } }; -export default addSubmission; +export default runCode; diff --git a/src/services/batchwiseSubmission.ts b/src/services/batchwiseSubmission.ts index ce99e6d..c8e4a48 100644 --- a/src/services/batchwiseSubmission.ts +++ b/src/services/batchwiseSubmission.ts @@ -1,11 +1,14 @@ -import judgeapi from '../API/judge0'; -import { batchsubmission } from '../utils/types'; -async function batchwiseSubmission(problems: T) { +import { protectedapi } from '../API/Index'; +import { batchSubmissionResponse } from '../utils/types'; +async function batchwiseSubmission(userId:string,problems: T) { try { - const response = await judgeapi.post(`/submissions/batch`, { - submissions: problems, - }); - return response.data; + const response = await protectedapi.post( + `users/${userId}/submissions/batch`, + { + submissions: problems, + }, + ); + return response.data.data; } catch (error) { if (error instanceof Error) { throw new Error(error.message); diff --git a/src/services/getSubmissionStatus.ts b/src/services/getSubmissionStatus.ts index fb9ec5b..1fe50f5 100644 --- a/src/services/getSubmissionStatus.ts +++ b/src/services/getSubmissionStatus.ts @@ -11,7 +11,7 @@ export default async function getStatus(submissionId: string) { }; stdout: null | string; stderr: null | string; - }>(`/submissions/${submissionId}?fields=stdout,stderr,language_id,stdin,status,expected_output`); + }>(`/submissions/${submissionId}?fields=stdout,stderr,language_id,stdin,status,expected_output,memory,time`); return response.data; } catch (error) { if (error instanceof Error) { diff --git a/src/services/sumbitCode.ts b/src/services/sumbitCode.ts index ffdf577..cca1bfb 100644 --- a/src/services/sumbitCode.ts +++ b/src/services/sumbitCode.ts @@ -1,18 +1,23 @@ -import judgeapi from '../API/judge0'; +import { protectedapi } from '../API/Index'; interface submitCodeArgs { code: string; language_id: number; - input: string; + stdin: string; expected_output: string; + userId:string } async function submitCode(params: submitCodeArgs) { try { - const response = await judgeapi.post('/submissions', { - source_code: params.code, - language_id: params.language_id, - stdin: params.input.replace('\\n', '\n'), - expected_output: params.expected_output, - }); + const response = await protectedapi.post( + `users/${params.userId}/submissions`, + { + source_code: params.code, + language_id: params.language_id, + stdin: params?.stdin?.replace('\\n', '\n'), + expected_output: params.expected_output, + userId:params.userId + }, + ); return response; } catch (error) { if (error instanceof Error) { diff --git a/src/services/updateSubmission.ts b/src/services/updateSubmission.ts index e227de4..aaed184 100644 --- a/src/services/updateSubmission.ts +++ b/src/services/updateSubmission.ts @@ -1,9 +1,13 @@ import { protectedapi } from '../API/Index'; -import { updateuser, updateUserType } from '../utils/types'; -const updateSubmission = async (updateUserProps: { id: string; updateduser: updateuser }) => { +import { IupdateSubmission, updateUserType } from '../utils/types'; +const updateSubmission = async (updateUserProps: { + submissionId: string; + userId: string; + updateduser: IupdateSubmission; +}) => { try { - const response = await protectedapi.patch( - `/users/${updateUserProps.id}`, + const response = await protectedapi.put( + `/users/${updateUserProps.userId}/submissions/${updateUserProps.submissionId}`, updateUserProps.updateduser ); if (response.data.status === 'Failure') { diff --git a/src/utils/types.ts b/src/utils/types.ts index 956ea8e..380a957 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -59,6 +59,13 @@ export interface validateSessionRes extends Omit { data: { user: user | null; isExipred: boolean }; } +export interface batchSubmissionResponse extends Omit { + data: { + submissionIds: string[]; + _id:string + }; +} + export interface metadata { input_format: string; output_format: string; @@ -102,7 +109,16 @@ export interface user { submissions: problemsubmission[]; } export interface createUser extends Partial {} -export interface updateuser extends Partial {} +export interface IupdateSubmission { + submissionId: string; + status: string; + actual_output?: string[]; + memoryUsed?: number[]; + executionTime?: number[]; + problemId:string; + languageId: number; + submittedAt?:Date +} export type status = 'Accepted' | 'Wrong Answer' | 'Processing'; export interface submissionprops { problemId: string; From e2d77abf943d2cc6b91a5d292250f06f0ffa99ca Mon Sep 17 00:00:00 2001 From: Kartik Joshi Date: Sun, 23 Nov 2025 19:18:08 +0530 Subject: [PATCH 2/6] submission payload changes --- src/components/Pages/Problem/Index.tsx | 4 +++- src/utils/types.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/Pages/Problem/Index.tsx b/src/components/Pages/Problem/Index.tsx index 6f5dd0e..6f6bffe 100644 --- a/src/components/Pages/Problem/Index.tsx +++ b/src/components/Pages/Problem/Index.tsx @@ -302,6 +302,7 @@ export default function Problem() { source_code: code, stdin: input, expected_output: output, + problemId: problemname?.slice(0, 24) as string, }); } } @@ -334,7 +335,8 @@ export default function Problem() { submittedAt: new Date(), actual_output:batchwiseresults.map((r)=>r.stdout), memoryUsed:batchwiseresults.map((r)=>r.memory), - executionTime:batchwiseresults.map((r)=>r.time) + executionTime:batchwiseresults.map((r)=>r.time), + difficulty:problemInfo.difficulty, }; const submissionUpdateResponse= await updateUserSubmissionById({submissionId:batchwiseresponses?._id as string,userId:user?._id as string,updateduser:updatesubmissionbody}); console.log(submissionUpdateResponse) diff --git a/src/utils/types.ts b/src/utils/types.ts index 380a957..ab94995 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -117,7 +117,8 @@ export interface IupdateSubmission { executionTime?: number[]; problemId:string; languageId: number; - submittedAt?:Date + submittedAt?:Date; + difficulty?:string; } export type status = 'Accepted' | 'Wrong Answer' | 'Processing'; export interface submissionprops { From 7c10cdc498642ef9f0d1c2151af993995e8f4edb Mon Sep 17 00:00:00 2001 From: Kartik Joshi Date: Sat, 21 Mar 2026 00:18:11 +0530 Subject: [PATCH 3/6] milestone1-leaderboard-page --- index.html | 6 +- src/API/Index.ts | 16 +- src/components/Pages/Home/HomeNavbar.tsx | 43 +- .../Pages/LeaderBoard/LeaderBoard.tsx | 71 +++ .../Pages/LeaderBoard/LeaderBoardFilters.tsx | 42 ++ .../Pages/LeaderBoard/LeaderBoardTable.tsx | 238 ++++++++++ .../LeaderBoardTablePagination.tsx | 76 +++ .../Pages/LeaderBoard/UserStats.tsx | 106 +++++ src/components/route.tsx | 5 + src/services/getLeaderBoardPagination.ts | 64 +++ src/services/retryToken.ts | 4 + src/store/index.tsx | 8 + src/store/leaderboardSlice/index.ts | 432 ++++++++++++++++++ src/store/leaderboardSlice/leaderboard.ts | 2 + src/utils/types.ts | 101 ++++ 15 files changed, 1208 insertions(+), 6 deletions(-) create mode 100644 src/components/Pages/LeaderBoard/LeaderBoard.tsx create mode 100644 src/components/Pages/LeaderBoard/LeaderBoardFilters.tsx create mode 100644 src/components/Pages/LeaderBoard/LeaderBoardTable.tsx create mode 100644 src/components/Pages/LeaderBoard/LeaderBoardTablePagination.tsx create mode 100644 src/components/Pages/LeaderBoard/UserStats.tsx create mode 100644 src/services/getLeaderBoardPagination.ts create mode 100644 src/store/leaderboardSlice/index.ts create mode 100644 src/store/leaderboardSlice/leaderboard.ts diff --git a/index.html b/index.html index 730d787..265b152 100644 --- a/index.html +++ b/index.html @@ -9,14 +9,16 @@
- --> diff --git a/src/API/Index.ts b/src/API/Index.ts index 1874517..eea864c 100644 --- a/src/API/Index.ts +++ b/src/API/Index.ts @@ -1,13 +1,17 @@ import axios, { AxiosError } from 'axios'; import refreshToken from '../services/retryToken'; + const api = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, }); + export const protectedapi = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, withCredentials: true, }); + export default api; + protectedapi.interceptors.response.use( (response) => { return response; @@ -21,9 +25,15 @@ protectedapi.interceptors.response.use( try { await refreshToken(); return protectedapi(originalRequest); - } catch (error) { - // window.location.href = '/signin'; - return Promise.reject(error); + } catch (refreshError) { + // Refresh failed - clear cookies and redirect to signin + document.cookie = 'access-token=; max-age=0; path=/;'; + document.cookie = 'refresh-token=; max-age=0; path=/;'; + document.cookie = 'session-token=; max-age=0; path=/;'; + document.cookie = 'id=; max-age=0; path=/;'; + + window.location.href = '/signin'; + return Promise.reject(refreshError); } } return Promise.reject(error); diff --git a/src/components/Pages/Home/HomeNavbar.tsx b/src/components/Pages/Home/HomeNavbar.tsx index c3800b0..e155d08 100644 --- a/src/components/Pages/Home/HomeNavbar.tsx +++ b/src/components/Pages/Home/HomeNavbar.tsx @@ -1,4 +1,4 @@ -import { Link as ReactLink } from 'react-router-dom'; +import { Link as ReactLink, useLocation } from 'react-router-dom'; import darklogo from '../../../assets/images/logo-dark.26900637.svg'; import lightlogo from '../../../assets/images/logo-light.5034df26.svg'; import { usethemeUtils } from '../../../context/ThemeWrapper'; @@ -11,6 +11,7 @@ import Profile from '../../UI/Profile'; export default function HomeNavbar() { const { colorMode, toggleColorMode } = usethemeUtils(); const isLogedIn = useAuthSlice((state) => state.isLogedIn); + const location = useLocation(); return (