@@ -112,11 +112,6 @@ const GroupTestReport = ({
|
|||||||
Candidate Information:
|
Candidate Information:
|
||||||
</Text>
|
</Text>
|
||||||
<View style={styles.textMargin}>
|
<View style={styles.textMargin}>
|
||||||
<Text style={defaultTextStyle}>Name: {name}</Text>
|
|
||||||
<Text style={defaultTextStyle}>ID: {id}</Text>
|
|
||||||
<Text style={defaultTextStyle}>Email: {email}</Text>
|
|
||||||
<Text style={defaultTextStyle}>Gender: {gender}</Text>
|
|
||||||
<Text style={defaultTextStyle}>Passport ID: {passportId}</Text>
|
|
||||||
<Text style={defaultTextStyle}>
|
<Text style={defaultTextStyle}>
|
||||||
Total Number of Students: {numberOfStudents}
|
Total Number of Students: {numberOfStudents}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -242,10 +237,10 @@ const GroupTestReport = ({
|
|||||||
Sr
|
Sr
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={customStyles.tableCell}>Candidate Name</Text>
|
<Text style={customStyles.tableCell}>Candidate Name</Text>
|
||||||
<Text style={customStyles.tableCell}>Email ID</Text>
|
<Text style={customStyles.tableCell}>
|
||||||
<Text style={[customStyles.tableCell, { maxWidth: "48px" }]}>
|
Passport ID
|
||||||
Gender
|
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text style={customStyles.tableCell}>Email ID</Text>
|
||||||
<Text style={[customStyles.tableCell, { maxWidth: "64px" }]}>
|
<Text style={[customStyles.tableCell, { maxWidth: "64px" }]}>
|
||||||
Date of test
|
Date of test
|
||||||
</Text>
|
</Text>
|
||||||
@@ -255,7 +250,19 @@ const GroupTestReport = ({
|
|||||||
{showLevel && <Text style={customStyles.tableCell}>Level</Text>}
|
{showLevel && <Text style={customStyles.tableCell}>Level</Text>}
|
||||||
</View>
|
</View>
|
||||||
{studentsData.map(
|
{studentsData.map(
|
||||||
({ id, name, email, gender, date, result, level }, index) => (
|
(
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
gender,
|
||||||
|
date,
|
||||||
|
result,
|
||||||
|
level,
|
||||||
|
passportId: studentPassportId,
|
||||||
|
},
|
||||||
|
index
|
||||||
|
) => (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
customStyles.tableRow,
|
customStyles.tableRow,
|
||||||
@@ -273,10 +280,8 @@ const GroupTestReport = ({
|
|||||||
{index + 1}
|
{index + 1}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={customStyles.tableCell}>{name}</Text>
|
<Text style={customStyles.tableCell}>{name}</Text>
|
||||||
|
<Text style={customStyles.tableCell}>{studentPassportId}</Text>
|
||||||
<Text style={customStyles.tableCell}>{email}</Text>
|
<Text style={customStyles.tableCell}>{email}</Text>
|
||||||
<Text style={[customStyles.tableCell, { maxWidth: "48px" }]}>
|
|
||||||
{gender}
|
|
||||||
</Text>
|
|
||||||
<Text style={[customStyles.tableCell, { maxWidth: "64px" }]}>
|
<Text style={[customStyles.tableCell, { maxWidth: "64px" }]}>
|
||||||
{date}
|
{date}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import React from "react";
|
|||||||
import { styles } from "./styles";
|
import { styles } from "./styles";
|
||||||
import { View, Text } from "@react-pdf/renderer";
|
import { View, Text } from "@react-pdf/renderer";
|
||||||
|
|
||||||
const TestReportFooter = () => (
|
interface Props {
|
||||||
|
userId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TestReportFooter = ({ userId }: Props) => (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
@@ -25,10 +29,23 @@ const TestReportFooter = () => (
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
<Text style={styles.textBold}>Confidential – <Text style={[styles.textFont, styles.textNormal]}>circulated for concern people</Text></Text>
|
<Text style={styles.textBold}>
|
||||||
|
Confidential –{" "}
|
||||||
|
<Text style={[styles.textFont, styles.textNormal]}>
|
||||||
|
circulated for concern people
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ paddingTop: 10 }}>
|
{userId && (
|
||||||
|
<View>
|
||||||
|
<Text style={styles.textBold}>
|
||||||
|
User ID:{" "}
|
||||||
|
<Text style={[styles.textFont, styles.textNormal]}>{userId}</Text>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
<View style={{ paddingTop: 4 }}>
|
||||||
<Text style={styles.textBold}>Declaration</Text>
|
<Text style={styles.textBold}>Declaration</Text>
|
||||||
<Text style={{ paddingTop: 5 }}>
|
<Text style={{ paddingTop: 5 }}>
|
||||||
We hereby declare that exam results on our platform, assessed by AI, are
|
We hereby declare that exam results on our platform, assessed by AI, are
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ const TestReport = ({
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={[{ paddingTop: 30 }, styles.separator]}></View>
|
<View style={[{ paddingTop: 30 }, styles.separator]}></View>
|
||||||
<TestReportFooter />
|
<TestReportFooter userId={id}/>
|
||||||
</Page>
|
</Page>
|
||||||
<Page style={styles.body}>
|
<Page style={styles.body}>
|
||||||
<View>
|
<View>
|
||||||
@@ -165,7 +165,7 @@ const TestReport = ({
|
|||||||
</View>
|
</View>
|
||||||
<View style={[{ paddingBottom: 30 }, styles.separator]}></View>
|
<View style={[{ paddingBottom: 30 }, styles.separator]}></View>
|
||||||
<View style={{ flexGrow: 1 }}></View>
|
<View style={{ flexGrow: 1 }}></View>
|
||||||
<TestReportFooter />
|
<TestReportFooter userId={id}/>
|
||||||
</Page>
|
</Page>
|
||||||
</Document>
|
</Document>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,4 +19,5 @@ export interface StudentData {
|
|||||||
result: string;
|
result: string;
|
||||||
level?: string;
|
level?: string;
|
||||||
bandScore: number;
|
bandScore: number;
|
||||||
|
passportId?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function getServerSideProps({query, res}: {query: {oobCode: string; mode:
|
|||||||
code: query.oobCode,
|
code: query.oobCode,
|
||||||
mode: query.mode,
|
mode: query.mode,
|
||||||
apiKey: query.apiKey,
|
apiKey: query.apiKey,
|
||||||
continueUrl: query.continueUrl,
|
...query.continueUrl ? { continueUrl: query.continueUrl } : {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,10 +113,6 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.assigner !== req.session.user.id) {
|
|
||||||
res.status(401).json({ok: false});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.pdf) {
|
if (data.pdf) {
|
||||||
// if it does, return the pdf url
|
// if it does, return the pdf url
|
||||||
const fileRef = ref(storage, data.pdf);
|
const fileRef = ref(storage, data.pdf);
|
||||||
@@ -239,6 +235,8 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
|
|
||||||
const result = exams.length === 0 ? "N/A" : `${correct}/${total}`;
|
const result = exams.length === 0 ? "N/A" : `${correct}/${total}`;
|
||||||
|
|
||||||
|
const userDemographicInformation = user?.demographicInformation as DemographicInformation;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
name: user?.name || "N/A",
|
name: user?.name || "N/A",
|
||||||
@@ -248,6 +246,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
result,
|
result,
|
||||||
level: showLevel ? getLevelScoreForUserExams(bandScore) : undefined,
|
level: showLevel ? getLevelScoreForUserExams(bandScore) : undefined,
|
||||||
bandScore,
|
bandScore,
|
||||||
|
passportId: userDemographicInformation?.passport_id || ""
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -126,6 +126,15 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
const stats = docsSnap.docs.map((d) => d.data());
|
const stats = docsSnap.docs.map((d) => d.data());
|
||||||
// verify if the stats already have a pdf generated
|
// verify if the stats already have a pdf generated
|
||||||
const hasPDF = stats.find((s) => s.pdf);
|
const hasPDF = stats.find((s) => s.pdf);
|
||||||
|
// find the user that generated the stats
|
||||||
|
const statIndex = stats.findIndex((s) => s.user);
|
||||||
|
|
||||||
|
if(statIndex === -1) {
|
||||||
|
res.status(401).json({ok: false});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const userId = stats[statIndex].user;
|
||||||
|
|
||||||
|
|
||||||
if (hasPDF) {
|
if (hasPDF) {
|
||||||
// if it does, return the pdf url
|
// if it does, return the pdf url
|
||||||
@@ -138,7 +147,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// generate the pdf report
|
// generate the pdf report
|
||||||
const docUser = await getDoc(doc(db, "users", req.session.user.id));
|
const docUser = await getDoc(doc(db, "users", userId));
|
||||||
|
|
||||||
if (docUser.exists()) {
|
if (docUser.exists()) {
|
||||||
// we'll need the user in order to get the user data (name, email, focus, etc);
|
// we'll need the user in order to get the user data (name, email, focus, etc);
|
||||||
@@ -269,7 +278,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
.format("ll HH:mm:ss")}
|
.format("ll HH:mm:ss")}
|
||||||
name={user.name}
|
name={user.name}
|
||||||
email={user.email}
|
email={user.email}
|
||||||
id={user.id}
|
id={userId}
|
||||||
gender={demographicInformation?.gender}
|
gender={demographicInformation?.gender}
|
||||||
summary={performanceSummary}
|
summary={performanceSummary}
|
||||||
testDetails={testDetails}
|
testDetails={testDetails}
|
||||||
|
|||||||
Reference in New Issue
Block a user