From 4448c2019e94c93a032d9a438a7893db1aa54cbf Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Tue, 16 Jan 2024 18:48:01 +0000 Subject: [PATCH 1/4] Added some bold text to PDF footer --- src/exams/pdf/styles.ts | 3 +++ src/exams/pdf/test.report.footer.tsx | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/exams/pdf/styles.ts b/src/exams/pdf/styles.ts index 0440c37f..0a0d7e4b 100644 --- a/src/exams/pdf/styles.ts +++ b/src/exams/pdf/styles.ts @@ -28,6 +28,9 @@ export const styles = StyleSheet.create({ fontFamily: "Helvetica-Bold", fontWeight: "bold", }, + textNormal: { + fontWeight: "normal", + }, textColor: { color: "#4e4969", }, diff --git a/src/exams/pdf/test.report.footer.tsx b/src/exams/pdf/test.report.footer.tsx index 884ad2f0..3771fee7 100644 --- a/src/exams/pdf/test.report.footer.tsx +++ b/src/exams/pdf/test.report.footer.tsx @@ -18,18 +18,18 @@ const TestReportFooter = () => ( > - Validity + Validity This report remains valid for a duration of three months from the test date. - Confidential – circulated for concern people + Confidential – circulated for concern people - Declaration + Declaration We hereby declare that exam results on our platform, assessed by AI, are not the sole determinants of candidates' English proficiency From 31d3232f19ab7b77807cd8e03172458b424bf190 Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Tue, 16 Jan 2024 19:24:19 +0000 Subject: [PATCH 2/4] Added passport id to PDF --- src/exams/pdf/group.test.report.tsx | 3 +++ src/exams/pdf/test.report.tsx | 3 +++ src/pages/api/assignments/[id]/export.tsx | 7 ++++--- src/pages/api/stats/[id]/export.tsx | 6 ++++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/exams/pdf/group.test.report.tsx b/src/exams/pdf/group.test.report.tsx index 4b865494..24d25ca0 100644 --- a/src/exams/pdf/group.test.report.tsx +++ b/src/exams/pdf/group.test.report.tsx @@ -33,6 +33,7 @@ interface Props { summaryPNG: string; summaryScore: string; groupScoreSummary: any[]; + passportId: string; } const customStyles = StyleSheet.create({ @@ -81,6 +82,7 @@ const GroupTestReport = ({ summaryPNG, summaryScore, groupScoreSummary, + passportId, }: Props) => { const defaultTextStyle = [styles.textFont, { fontSize: 8 }]; return ( @@ -114,6 +116,7 @@ const GroupTestReport = ({ ID: {id} Email: {email} Gender: {gender} + Passport ID: {passportId} Total Number of Students: {numberOfStudents} diff --git a/src/exams/pdf/test.report.tsx b/src/exams/pdf/test.report.tsx index 5b72feaf..9c409554 100644 --- a/src/exams/pdf/test.report.tsx +++ b/src/exams/pdf/test.report.tsx @@ -27,6 +27,7 @@ interface Props { title: string; summaryPNG: string; summaryScore: string; + passportId: string; } const TestReport = ({ @@ -43,6 +44,7 @@ const TestReport = ({ renderDetails, summaryPNG, summaryScore, + passportId, }: Props) => { const defaultTextStyle = [styles.textFont, { fontSize: 8 }]; const defaultSkillsTextStyle = [styles.textFont, { fontSize: 8 }]; @@ -83,6 +85,7 @@ const TestReport = ({ ID: {id} Email: {email} Gender: {gender} + Passport ID: {passportId} ); diff --git a/src/pages/api/stats/[id]/export.tsx b/src/pages/api/stats/[id]/export.tsx index b7a103db..0ff4d5a9 100644 --- a/src/pages/api/stats/[id]/export.tsx +++ b/src/pages/api/stats/[id]/export.tsx @@ -15,7 +15,7 @@ import { sessionOptions } from "@/lib/session"; import ReactPDF from "@react-pdf/renderer"; import TestReport from "@/exams/pdf/test.report"; import { ref, uploadBytes, getDownloadURL } from "firebase/storage"; -import { User } from "@/interfaces/user"; +import { DemographicInformation, User } from "@/interfaces/user"; import { Module } from "@/interfaces"; import { ModuleScore } from "@/interfaces/module.scores"; import { SkillExamDetails } from "@/exams/pdf/details/skill.exam"; @@ -304,6 +304,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) { const { title, details } = getCustomData(); + const demographicInformation = user.demographicInformation as DemographicInformation; const pdfStream = await ReactPDF.renderToStream( ); From 8002c71b9122861e4d77c134baa40780d2a06c65 Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Tue, 16 Jan 2024 22:22:55 +0000 Subject: [PATCH 3/4] Fixed issue with 100% being hyphenized --- src/exams/pdf/group.test.report.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exams/pdf/group.test.report.tsx b/src/exams/pdf/group.test.report.tsx index 24d25ca0..6d98cd8a 100644 --- a/src/exams/pdf/group.test.report.tsx +++ b/src/exams/pdf/group.test.report.tsx @@ -206,7 +206,7 @@ const GroupTestReport = ({ percentage={percent} /> - + {percent}% {description} From 6bcc303b740e685c7c20414bd9f4a49e2ffa3cd2 Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Tue, 16 Jan 2024 22:24:08 +0000 Subject: [PATCH 4/4] Fixed institution print --- src/pages/api/assignments/[id]/export.tsx | 74 +++++++++++++++++++++-- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/src/pages/api/assignments/[id]/export.tsx b/src/pages/api/assignments/[id]/export.tsx index 4a3a3e52..cfbbcc58 100644 --- a/src/pages/api/assignments/[id]/export.tsx +++ b/src/pages/api/assignments/[id]/export.tsx @@ -16,7 +16,7 @@ import { sessionOptions } from "@/lib/session"; import ReactPDF from "@react-pdf/renderer"; import GroupTestReport from "@/exams/pdf/group.test.report"; import { ref, uploadBytes, getDownloadURL } from "firebase/storage"; -import { Stat } from "@/interfaces/user"; +import { Stat, CorporateUser } from "@/interfaces/user"; import { User, DemographicInformation } from "@/interfaces/user"; import { Module } from "@/interfaces"; import { ModuleScore, StudentData } from "@/interfaces/module.scores"; @@ -28,6 +28,7 @@ import { getRadialProgressPNG, streamToBuffer, } from "@/utils/pdf"; +import { Group } from "@/interfaces/user"; interface GroupScoreSummaryHelper { score: [number, number]; @@ -345,8 +346,73 @@ async function post(req: NextApiRequest, res: NextApiResponse) { return result; }; + const getInstitution = async () => { + try { + // due to database inconsistencies, I'll be overprotective here + const assignerUserSnap = await getDoc( + doc(db, "users", data.assigner) + ); + if (assignerUserSnap.exists()) { + // we'll need the user in order to get the user data (name, email, focus, etc); + const assignerUser = assignerUserSnap.data() as User; + + if (assignerUser.type === "teacher") { + // also search for groups where this user belongs + const queryGroups = query( + collection(db, "groups"), + where("participants", "array-contains", assignerUser.id) + ); + const groupSnapshot = await getDocs(queryGroups); + + const groups = groupSnapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) as Group[]; + + if (groups.length > 0) { + const adminQuery = query( + collection(db, "users"), + where( + documentId(), + "in", + groups.map((g) => g.admin) + ) + ); + const adminUsersSnap = await getDocs(adminQuery); + + const admins = adminUsersSnap.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) as CorporateUser[]; + + const adminData = admins.find( + (a) => a.corporateInformation?.companyInformation?.name + ); + if (adminData) { + return adminData.corporateInformation.companyInformation + .name; + } + } + } + + if ( + assignerUser.type === "corporate" && + assignerUser.corporateInformation?.companyInformation?.name + ) { + return assignerUser.corporateInformation.companyInformation + .name; + } + } + } catch (err) { + console.error(err); + } + return ""; + }; + + const institution = await getInstitution(); const groupScoreSummary = getGroupScoreSummary(); - const demographicInformation = user.demographicInformation as DemographicInformation; + const demographicInformation = + user.demographicInformation as DemographicInformation; const pdfStream = await ReactPDF.renderToStream( );