Skip to content

Commit fb1f739

Browse files
Merge pull request #227 from Advik-Gupta/starredPapers
Create mobile responsive frontend
2 parents e070766 + 49cbac8 commit fb1f739

31 files changed

+1080
-986
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
"start": "next start"
1111
},
1212
"dependencies": {
13-
"@google/genai": "^0.7.0",
1413
"@radix-ui/react-accordion": "^1.2.4",
1514
"@radix-ui/react-dialog": "^1.1.7",
1615
"@radix-ui/react-icons": "^1.3.2",

pnpm-lock.yaml

Lines changed: 8 additions & 207 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/api/ai-upload/route.ts

Lines changed: 25 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,15 @@
11
import { NextResponse } from "next/server";
22
import { PDFDocument } from "pdf-lib";
3-
import {
4-
campuses,
5-
exams,
6-
semesters,
7-
slots,
8-
years,
9-
} from "@/components/select_options";
103
import { connectToDatabase } from "@/lib/mongoose";
114
import cloudinary from "cloudinary";
12-
import type {
13-
ICourses,
14-
CloudinaryUploadResult,
15-
ExamDetail,
16-
IAdminPaper,
17-
} from "@/interface";
5+
import type { CloudinaryUploadResult } from "@/interface";
186
import { PaperAdmin } from "@/db/papers";
19-
import axios from "axios";
20-
import processAndAnalyze from "@/util/gemini";
21-
import Fuse from "fuse.js";
227

238
cloudinary.v2.config({
249
cloud_name: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME,
2510
api_key: process.env.CLOUDINARY_API_KEY,
2611
api_secret: process.env.CLOUDINARY_SECRET,
2712
});
28-
type SemesterType = IAdminPaper["semester"];
2913

3014
const config1 = {
3115
cloud_name: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME_1,
@@ -38,6 +22,7 @@ const config2 = {
3822
api_key: process.env.CLOUDINARY_API_KEY_2,
3923
api_secret: process.env.CLOUDINARY_SECRET_2,
4024
};
25+
4126
const cloudinaryConfigs = [config1, config2];
4227

4328
export async function POST(req: Request) {
@@ -68,66 +53,6 @@ export async function POST(req: Request) {
6853
const pdfBuffer = Buffer.from(pdfBytes);
6954
pdfData = pdfBuffer.toString("base64");
7055
}
71-
const tags = await processAndAnalyze({ pdfData });
72-
73-
console.log("tags generated:", tags);
74-
75-
const { data } = await axios.get<ICourses[]>(
76-
`${process.env.SERVER_URL}/api/course-list`,
77-
);
78-
const courses = data.map((course: { name: string }) => course.name);
79-
80-
const finalTags = await setTagsFromCurrentLists(tags, courses);
81-
console.log(" tags final:", finalTags);
82-
83-
const subject = finalTags.subject;
84-
const slot = finalTags.slot;
85-
const exam = finalTags.exam;
86-
const year = finalTags.year;
87-
const campus = formData.get("campus") as string;
88-
const semester = finalTags.semester;
89-
const answerKeyIncluded = finalTags.answerKeyIncluded;
90-
if (!courses.includes(subject)) {
91-
return NextResponse.json(
92-
{ message: "The course subject is invalid." },
93-
{ status: 400 },
94-
);
95-
}
96-
97-
if (!slots.includes(slot)) {
98-
return NextResponse.json(
99-
{ message: "The slot is invalid." },
100-
{ status: 400 },
101-
);
102-
}
103-
104-
if (!exam.includes(exam)) {
105-
return NextResponse.json(
106-
{ message: "The exam type is invalid." },
107-
{ status: 400 },
108-
);
109-
}
110-
111-
if (!years.includes(year)) {
112-
return NextResponse.json(
113-
{ message: "The year is invalid." },
114-
{ status: 400 },
115-
);
116-
}
117-
118-
if (!campuses.includes(campus)) {
119-
return NextResponse.json(
120-
{ message: `The ${campus} is invalid.` },
121-
{ status: 400 },
122-
);
123-
}
124-
125-
if (!semesters.includes(semester)) {
126-
return NextResponse.json(
127-
{ message: "The semester is invalid." },
128-
{ status: 400 },
129-
);
130-
}
13156

13257
let finalUrl: string | undefined = "";
13358
let public_id_cloudinary: string | undefined = "";
@@ -146,11 +71,15 @@ export async function POST(req: Request) {
14671
return;
14772
}
14873

74+
console.log("this is happening 1");
75+
14976
const mergedPdfBytes = await CreatePDF(files);
15077
[public_id_cloudinary, finalUrl] = await uploadPDFFile(
15178
mergedPdfBytes,
15279
uploadPreset,
15380
);
81+
82+
console.log("this is happening 2");
15483
} catch (error) {
15584
console.error("Error creating PDF:", error);
15685
return NextResponse.json(
@@ -159,33 +88,39 @@ export async function POST(req: Request) {
15988
);
16089
}
16190
} else {
91+
console.log("this is happening 3");
16292
[public_id_cloudinary, finalUrl] = await uploadPDFFile(
16393
files[0]!,
16494
uploadPreset,
16595
);
16696
}
167-
console.log(finalUrl);
97+
16898
const thumbnailResponse = cloudinary.v2.image(finalUrl!, {
16999
format: "jpg",
170100
});
171101
thumbnailUrl = thumbnailResponse
172102
.replace("pdf", "jpg")
173103
.replace("upload", "upload/w_400,h_400,c_fill")
174104
.replace(/<img src='|'\s*\/>/g, "");
105+
106+
console.log("this is happening 4");
107+
175108
const paper = new PaperAdmin({
176109
cloudinary_index: configIndex,
177110
public_id_cloudinary,
178-
answerKeyIncluded,
179111
finalUrl,
180112
thumbnailUrl,
181-
subject,
182-
slot,
183-
year,
184-
exam,
185-
campus,
186-
semester,
113+
subject: null,
114+
slot: null,
115+
year: null,
116+
exam: null,
117+
semester: null,
118+
campus: null,
187119
});
120+
121+
console.log("this is happening 5");
188122
await paper.save();
123+
console.log("this is happening 6");
189124
return NextResponse.json({ status: "success" }, { status: 201 });
190125
} catch (error) {
191126
console.error(error);
@@ -197,6 +132,7 @@ export async function POST(req: Request) {
197132
}
198133

199134
async function uploadPDFFile(file: File | ArrayBuffer, uploadPreset: string) {
135+
console.log("this is happening 7");
200136
let bytes;
201137
if (file instanceof File) {
202138
bytes = await file.arrayBuffer();
@@ -212,12 +148,16 @@ async function uploadFile(
212148
fileType: string,
213149
) {
214150
try {
151+
console.log("this is happening 8");
215152
const buffer = Buffer.from(bytes);
153+
console.log("this is happening 9");
216154
const dataUrl = `data:${fileType};base64,${buffer.toString("base64")}`;
155+
console.log("this is happening 10");
217156
const uploadResult = (await cloudinary.v2.uploader.unsigned_upload(
218157
dataUrl,
219158
uploadPreset,
220159
)) as CloudinaryUploadResult;
160+
console.log("this is happening 11");
221161
return [uploadResult.public_id, uploadResult.secure_url];
222162
} catch (e) {
223163
throw e;
@@ -252,62 +192,3 @@ async function CreatePDF(orderedFiles: File[]) {
252192
const mergedPdfBytes = await pdfDoc.save();
253193
return mergedPdfBytes;
254194
}
255-
256-
// Sets course-name to corresponding course name from our api
257-
async function setTagsFromCurrentLists(
258-
tags: ExamDetail | undefined,
259-
courses: string[],
260-
): Promise<ExamDetail> {
261-
if (!courses[0] || !slots[0] || !exams[0] || !semesters[0] || !years[0]) {
262-
throw Error("Cannot fetch default value for courses/slot/exam/sem/year!");
263-
}
264-
265-
const newTags: ExamDetail = {
266-
subject: courses[0],
267-
slot: slots[0],
268-
"course-code": "notInUse",
269-
exam: exams[0],
270-
semester: semesters[0] as SemesterType,
271-
year: years[0],
272-
answerKeyIncluded: false,
273-
};
274-
275-
const coursesFuzy = new Fuse(courses);
276-
if (!tags) {
277-
console.log("Anaylsis failed setting random courses as fields");
278-
return newTags;
279-
} else {
280-
const subjectSearch = coursesFuzy.search(tags.subject)[0];
281-
if (subjectSearch) {
282-
newTags.subject = subjectSearch.item;
283-
}
284-
const slotSearchResult = findMatch(slots, tags.slot);
285-
if (slotSearchResult) {
286-
newTags.slot = slotSearchResult;
287-
}
288-
const examSearchResult = findMatch(exams, tags.exam);
289-
if (examSearchResult) {
290-
newTags.exam = examSearchResult;
291-
}
292-
const semesterSearchResult = findMatch(semesters, tags.semester);
293-
if (semesterSearchResult) {
294-
newTags.semester = semesterSearchResult as SemesterType;
295-
}
296-
const yearSearchResult = findMatch(years, tags.year);
297-
298-
if (yearSearchResult) {
299-
newTags.year = yearSearchResult;
300-
}
301-
const answerkeySearchResults = tags.answerKeyIncluded ?? false;
302-
303-
if (yearSearchResult) {
304-
newTags.answerKeyIncluded = answerkeySearchResults;
305-
}
306-
}
307-
return newTags;
308-
}
309-
function findMatch<T>(arr: T[], value: string | undefined): T | undefined {
310-
if (!value) return undefined;
311-
const pattern = new RegExp(value, "i");
312-
return arr.find((item) => pattern.test(String(item)));
313-
}

0 commit comments

Comments
 (0)