Skip to content

Commit

Permalink
feat: better url param get reqs; fetch similar papers; i am crying; i…
Browse files Browse the repository at this point in the history
… hate get requests, everything should be post with json body
  • Loading branch information
harshkhandeparkar committed Oct 7, 2024
1 parent 34b73ee commit 9b60fc6
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 19 deletions.
68 changes: 57 additions & 11 deletions frontend/src/components/Common/PaperEditModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import toast from "react-hot-toast";
import { MdCancel } from "react-icons/md";
import Fuse from 'fuse.js';

import { validate } from "../../utils/validateInput";
import { validate, validateCourseCode, validateExam, validateSemester, validateYear } from "../../utils/validateInput";
import { Exam, IAdminDashboardQP, IErrorMessage, IQuestionPaperFile, Semester } from "../../types/question_paper";
import { extractDetailsFromText, extractTextFromPDF, getCodeFromCourse, getCourseFromCode, IExtractedDetails } from "../../utils/autofillData";
import './styles/paper_edit_modal.scss';
Expand All @@ -13,6 +13,9 @@ import Spinner from "../Spinner/Spinner";
import { FormGroup, RadioGroup, NumberInput, SuggestionTextInput } from "./Form";

import COURSE_CODE_MAP from "../../data/courses.json";
import { makeRequest } from "../../utils/backend";
import { IEndpointTypes } from "../../types/backend";
import { useAuthContext } from "../../utils/auth";

type UpdateQPHandler<T> = (qp: T) => void;
interface IPaperEditModalProps<T> {
Expand All @@ -22,13 +25,18 @@ interface IPaperEditModalProps<T> {
};

function PaperEditModal<T extends IQuestionPaperFile | IAdminDashboardQP>(props: IPaperEditModalProps<T>) {
const auth = useAuthContext();

const [data, setData] = useState(props.qPaper);
const [validationErrors, setValidationErrors] = useState<IErrorMessage>(validate(props.qPaper));
const [isDataValid, setIsDataValid] = useState<boolean>(false);

const [ocrDetails, setOcrDetails] = useState<IExtractedDetails | null>(null);
const [awaitingOcr, setAwaitingOcr] = useState<boolean>(false);

const [similarPapers, setSimilarPapers] = useState<IAdminDashboardQP[]>([]);
const [awaitingSimilarPapers, setAwaitingSimilarPapers] = useState<boolean>(false);

const changeData = <K extends keyof T>(property: K, value: T[K]) => {
setData((prev_data) => {
return {
Expand Down Expand Up @@ -72,11 +80,43 @@ function PaperEditModal<T extends IQuestionPaperFile | IAdminDashboardQP>(props:
setAwaitingOcr(false);
}

useEffect(() => {
if ('filelink' in props.qPaper) {
getOcrData(props.qPaper.filelink);
if ('filelink' in props.qPaper) {
useEffect(() => {
if ('filelink' in props.qPaper) {
getOcrData(props.qPaper.filelink);
}
}, [])
}

const getSimilarPapers = async (details: IEndpointTypes['similar']['request']) => {
setAwaitingSimilarPapers(true);
const response = await makeRequest('similar', 'get', details, auth.jwt);

if (response.status === "success") {
setSimilarPapers(response.data);
} else {
toast.error(`Error getting similar papers: ${response.message} (${response.status_code})`);
}
}, [])

setAwaitingSimilarPapers(false);
};

if ('filelink' in props.qPaper) {
useEffect(() => {
if (validateCourseCode(data.course_code)) {
const similarityDetails: IEndpointTypes['similar']['request'] = {
course_code: data.course_code
}

if (validateYear(data.year)) similarityDetails['year'] = data.year;
if (validateExam(data.exam) && data.exam !== 'unknown' && data.exam !== 'ct') similarityDetails['exam'] = data.exam;
if (validateSemester(data.semester)) similarityDetails['semester'] = data.semester;

getSimilarPapers(similarityDetails);
}

}, [data.course_code, data.year, data.exam, data.semester])
}

const courseCodes = Object.keys(COURSE_CODE_MAP);
const courseNames = Object.values(COURSE_CODE_MAP);
Expand Down Expand Up @@ -154,7 +194,7 @@ function PaperEditModal<T extends IQuestionPaperFile | IAdminDashboardQP>(props:
value={data.course_code}
onValueChange={(value) => changeData('course_code', value.toUpperCase())}
suggestions={trimSuggestions(courseCodes.filter((code) => code.startsWith(data.course_code)))}
inputProps={{required: true}}
inputProps={{ required: true }}
/>
</FormGroup>
<FormGroup
Expand All @@ -174,11 +214,11 @@ function PaperEditModal<T extends IQuestionPaperFile | IAdminDashboardQP>(props:
validationError={validationErrors.courseNameErr}
>
<SuggestionTextInput
value={data.course_name}
onValueChange={(value) => changeData('course_name', value.toUpperCase())}
suggestions={trimSuggestions(courseNamesFuse.search(data.course_name).map((result) => result.item))}
inputProps={{required: true}}
/>
value={data.course_name}
onValueChange={(value) => changeData('course_name', value.toUpperCase())}
suggestions={trimSuggestions(courseNamesFuse.search(data.course_name).map((result) => result.item))}
inputProps={{ required: true }}
/>
</FormGroup>
<FormGroup
label="Exam:"
Expand Down Expand Up @@ -267,6 +307,12 @@ function PaperEditModal<T extends IQuestionPaperFile | IAdminDashboardQP>(props:
{'filelink' in data &&
<div className="modal">
<h2>Similar Papers</h2>
{
awaitingSimilarPapers ? <div style={{ justifyContent: 'center', display: 'flex' }}><Spinner /></div> :
<div>

</div>
}
</div>
}
</div>;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Search/SearchForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function CourseSearchForm() {
params.append("exam", exam);

setAwaitingResponse(true);
const response = await makeRequest(`search?${params}`, 'get');
const response = await makeRequest('search', 'get', {course: query, exam});

if (response.status === 'success') {
const data: ISearchResult[] = response.data;
Expand Down
18 changes: 15 additions & 3 deletions frontend/src/types/backend.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IAdminDashboardQP, ISearchResult } from "./question_paper";
import { Exam, IAdminDashboardQP, ISearchResult, Semester } from "./question_paper";

export type AllowedBackendMethods = "get" | "post";

Expand All @@ -18,8 +18,11 @@ export type BackendResponse<T> = IOkResponse<T> | IErrorResponse;


export interface IEndpointTypes {
[route: `search?${string}`]: {
request: null,
search: {
request: {
course: string;
exam: Exam | "";
},
response: ISearchResult[]
},
oauth: {
Expand Down Expand Up @@ -61,5 +64,14 @@ export interface IEndpointTypes {
response: {
username: string;
}
},
similar: {
request: {
course_code: string;
year?: number;
semester?: Semester;
exam?: Exam;
},
response: IAdminDashboardQP[];
}
}
20 changes: 16 additions & 4 deletions frontend/src/utils/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ import { AllowedBackendMethods, BackendResponse, IEndpointTypes } from "../types

export const BACKEND_URL: string = import.meta.env.VITE_BACKEND_URL;

async function makeBackendRequest(
interface IBodyTypes {
get: Object;
post: Object | FormData;
}

async function makeBackendRequest<M extends AllowedBackendMethods>(
endpoint: string,
method: AllowedBackendMethods,
method: M,
jwt: string | null,
body: Object | FormData | null,
body: IBodyTypes[M] | null
): Promise<Response> {
const headers: {
"Content-Type"?: string;
Expand All @@ -23,7 +28,12 @@ async function makeBackendRequest(

switch (method) {
case "get":
return await fetch(`${BACKEND_URL}/${endpoint}`, {
const requestURL = new URL(`${BACKEND_URL}/${endpoint}`);
if (body !== null) {
Object.entries(body).map(([key, value]) => requestURL.searchParams.set(key, value));
}

return await fetch(requestURL, {
method: "get",
headers,
});
Expand All @@ -33,6 +43,8 @@ async function makeBackendRequest(
headers,
body: body instanceof FormData ? body : JSON.stringify(body ?? {}),
});
default:
throw 'This should not happen';
}
}

Expand Down

0 comments on commit 9b60fc6

Please sign in to comment.