222 lines
6.4 KiB
TypeScript
222 lines
6.4 KiB
TypeScript
/* eslint-disable jsx-a11y/alt-text */
|
||
import React from "react";
|
||
import { Document, Page, View, Text, Image } from "@react-pdf/renderer";
|
||
import ProgressBar from "./progress.bar";
|
||
import { ModuleScore } from "@/interfaces/module.scores";
|
||
import { styles } from "./styles";
|
||
|
||
import { StyleSheet } from "@react-pdf/renderer";
|
||
|
||
const customStyles = StyleSheet.create({
|
||
testDetails: {
|
||
display: "flex",
|
||
gap: 4,
|
||
},
|
||
qrcode: {
|
||
width: "80px",
|
||
height: "80px",
|
||
},
|
||
});
|
||
|
||
interface Props {
|
||
date: string;
|
||
name: string;
|
||
email: string;
|
||
id: string;
|
||
gender?: string;
|
||
testDetails: ModuleScore[];
|
||
summary: string;
|
||
logo: string;
|
||
qrcode: string;
|
||
renderDetails: React.ReactNode;
|
||
title: string;
|
||
}
|
||
|
||
const PDFReport = ({
|
||
title,
|
||
date,
|
||
name,
|
||
email,
|
||
id,
|
||
gender,
|
||
testDetails,
|
||
summary,
|
||
logo,
|
||
qrcode,
|
||
renderDetails,
|
||
}: Props) => {
|
||
const defaultTextStyle = [styles.textFont, { fontSize: 8 }];
|
||
const defaultSkillsTextStyle = [styles.textFont, { fontSize: 8 }];
|
||
const defaultSkillsTitleStyle = [
|
||
styles.textFont,
|
||
styles.textColor,
|
||
styles.textBold,
|
||
{ fontSize: 7 },
|
||
];
|
||
return (
|
||
<Document>
|
||
<Page style={styles.body}>
|
||
<View style={styles.alignRightRow}>
|
||
<Image src={logo} fixed style={styles.image64} />
|
||
</View>
|
||
<View style={styles.titleView}>
|
||
<Text
|
||
style={[
|
||
styles.textFont,
|
||
styles.textBold,
|
||
styles.textColor,
|
||
styles.textUnderline,
|
||
styles.title,
|
||
{ fontSize: 14 },
|
||
]}
|
||
>
|
||
{title}
|
||
</Text>
|
||
</View>
|
||
<View style={styles.textPadding}>
|
||
<Text style={defaultTextStyle}>Date of Test: {date}</Text>
|
||
</View>
|
||
<Text style={[styles.textFont, styles.textBold, { fontSize: 11 }]}>
|
||
Candidate Information:
|
||
</Text>
|
||
<View style={styles.textPadding}>
|
||
<Text style={defaultTextStyle}>Name: {name}</Text>
|
||
<Text style={defaultTextStyle}>ID: {id}</Text>
|
||
<Text style={defaultTextStyle}>Email: {email}</Text>
|
||
<Text style={defaultTextStyle}>Gender: {gender}</Text>
|
||
</View>
|
||
<View style={{ flex: 1 }}>
|
||
<Text
|
||
style={[
|
||
styles.textFont,
|
||
styles.textBold,
|
||
styles.textColor,
|
||
{ fontSize: 12 },
|
||
]}
|
||
>
|
||
Test Details:
|
||
</Text>
|
||
<View>{renderDetails}</View>
|
||
</View>
|
||
<View>
|
||
<Text
|
||
style={[
|
||
styles.textFont,
|
||
styles.textBold,
|
||
styles.textColor,
|
||
{ fontSize: 12 },
|
||
]}
|
||
>
|
||
Performance Summary
|
||
</Text>
|
||
<View>
|
||
<Text style={[styles.textFont, { fontSize: 8 }]}>{summary}</Text>
|
||
</View>
|
||
</View>
|
||
<View style={[{ paddingTop: 30 }, styles.separator]}></View>
|
||
<View>
|
||
<Text
|
||
style={[
|
||
styles.textFont,
|
||
styles.textBold,
|
||
styles.textColor,
|
||
styles.textUnderline,
|
||
{ fontSize: 12, paddingTop: 10 },
|
||
]}
|
||
>
|
||
Skills Feedback
|
||
</Text>
|
||
<View
|
||
style={{
|
||
paddingTop: 10,
|
||
gap: 8,
|
||
}}
|
||
>
|
||
{testDetails
|
||
.filter(({ suggestions, evaluation }) => suggestions || evaluation)
|
||
.map(({ module, suggestions, evaluation }) => (
|
||
<View key={module} style={customStyles.testDetails}>
|
||
<Text style={[...defaultSkillsTitleStyle, styles.textBold]}>
|
||
{module}
|
||
</Text>
|
||
<Text style={defaultSkillsTextStyle}>{evaluation}</Text>
|
||
<Text style={defaultSkillsTextStyle}>{suggestions}</Text>
|
||
|
||
</View>
|
||
))}
|
||
</View>
|
||
<View style={styles.alignRightRow}>
|
||
<Image
|
||
src={qrcode}
|
||
style={customStyles.qrcode}
|
||
/>
|
||
</View>
|
||
</View>
|
||
<View style={[{ paddingBottom: 30 }, styles.separator]}></View>
|
||
{false && (
|
||
<View>
|
||
<ProgressBar
|
||
width={200}
|
||
height={18}
|
||
backgroundColor="#cc5b55"
|
||
progressColor="#fab7b0"
|
||
percentage={60}
|
||
/>
|
||
</View>
|
||
)}
|
||
<View style={{ flexGrow: 1 }}></View>
|
||
<View style={[{ paddingTop: 30, fontSize: 5 }, styles.textFont]}>
|
||
<View
|
||
style={[
|
||
styles.spacedRow,
|
||
{
|
||
paddingHorizontal: 10,
|
||
},
|
||
]}
|
||
>
|
||
<View>
|
||
<Text>Validity</Text>
|
||
<Text>
|
||
This report remains valid for a duration of three months from
|
||
the test date.
|
||
</Text>
|
||
</View>
|
||
<View>
|
||
<Text>Confidential – circulated for concern people</Text>
|
||
</View>
|
||
</View>
|
||
<View style={{ paddingTop: 10 }}>
|
||
<Text>Declaration</Text>
|
||
<Text style={{ paddingTop: 5 }}>
|
||
We hereby declare that exam results on our platform, assessed by
|
||
AI, are not the sole determinants of candidates' English
|
||
proficiency levels. While EnCoach provides feedback based on
|
||
assessments, we recognize that language proficiency encompasses
|
||
practical application, cultural understanding, and real-life
|
||
communication. We urge users to consider exam results as a measure
|
||
of progress and improvement, and we continuously enhance our
|
||
system to ensure accuracy and reliability.
|
||
</Text>
|
||
</View>
|
||
<View style={[styles.textColor, { paddingTop: 5 }]}>
|
||
<Text style={styles.textUnderline}>info@encoach.com</Text>
|
||
<Text>https://encoach.com</Text>
|
||
<View style={styles.spacedRow}>
|
||
<Text>Group ID: TRI64BNBOIU5043</Text>
|
||
<Text
|
||
// style={styles.pageNumber}
|
||
render={({ pageNumber, totalPages }) =>
|
||
`${pageNumber} / ${totalPages}`
|
||
}
|
||
fixed
|
||
/>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</Page>
|
||
</Document>
|
||
);
|
||
};
|
||
|
||
export default PDFReport;
|