Added integration with backend to fetch skills feedback
This commit is contained in:
@@ -3,6 +3,7 @@ import {Module} from "@/interfaces";
|
|||||||
export interface ModuleScore {
|
export interface ModuleScore {
|
||||||
score: number;
|
score: number;
|
||||||
total: number;
|
total: number;
|
||||||
|
code: Module;
|
||||||
module: Module | 'Overall';
|
module: Module | 'Overall';
|
||||||
feedback?: string,
|
feedback?: string,
|
||||||
png?: string,
|
png?: string,
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ import { ModuleScore } from "@/interfaces/module.scores";
|
|||||||
import qrcode from "qrcode";
|
import qrcode from "qrcode";
|
||||||
import { SkillExamDetails } from "@/exams/pdf/details/skill.exam";
|
import { SkillExamDetails } from "@/exams/pdf/details/skill.exam";
|
||||||
import { LevelExamDetails } from "@/exams/pdf/details/level.exam";
|
import { LevelExamDetails } from "@/exams/pdf/details/level.exam";
|
||||||
|
import { calculateBandScore } from "@/utils/score";
|
||||||
|
import axios from "axios";
|
||||||
|
import { moduleLabels } from "@/utils/moduleUtils";
|
||||||
|
|
||||||
const db = getFirestore(app);
|
const db = getFirestore(app);
|
||||||
|
|
||||||
export default withIronSessionApiRoute(handler, sessionOptions);
|
export default withIronSessionApiRoute(handler, sessionOptions);
|
||||||
@@ -115,6 +119,36 @@ const getFeedback = (module: Module) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface SkillsFeedbackRequest {
|
||||||
|
code: Module;
|
||||||
|
name: string;
|
||||||
|
grade: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SkillsFeedbackResponse extends SkillsFeedbackRequest {
|
||||||
|
evaluation: string;
|
||||||
|
suggestions: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSkillsFeedback = async (sections: SkillsFeedbackRequest[]) => {
|
||||||
|
try {
|
||||||
|
const backendRequest = await axios.post(
|
||||||
|
`${process.env.BACKEND_URL}/grading_summary`,
|
||||||
|
{ sections },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.BACKEND_JWT}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return backendRequest.data?.sections;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const generateQRCode = async (link: string) => {
|
const generateQRCode = async (link: string) => {
|
||||||
try {
|
try {
|
||||||
const qrCodeDataURL = await qrcode.toDataURL(link);
|
const qrCodeDataURL = await qrcode.toDataURL(link);
|
||||||
@@ -125,14 +159,18 @@ const generateQRCode = async (link: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type RADIAL_PROGRESS_COLOR = 'laranja' | 'azul';
|
type RADIAL_PROGRESS_COLOR = "laranja" | "azul";
|
||||||
|
|
||||||
const getRadialProgressPNG = (color: RADIAL_PROGRESS_COLOR, score: number, total: number) => {
|
const getRadialProgressPNG = (
|
||||||
|
color: RADIAL_PROGRESS_COLOR,
|
||||||
|
score: number,
|
||||||
|
total: number
|
||||||
|
) => {
|
||||||
const percent = (score / total) * 100;
|
const percent = (score / total) * 100;
|
||||||
const remainder = percent % 10;
|
const remainder = percent % 10;
|
||||||
const roundedPercent = percent - remainder;
|
const roundedPercent = percent - remainder;
|
||||||
return `public/radial_progress/${color}_${roundedPercent}.png`;
|
return `public/radial_progress/${color}_${roundedPercent}.png`;
|
||||||
}
|
};
|
||||||
|
|
||||||
async function post(req: NextApiRequest, res: NextApiResponse) {
|
async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||||
if (req.session.user) {
|
if (req.session.user) {
|
||||||
@@ -163,7 +201,8 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
const user = docUser.data() as User;
|
const user = docUser.data() as User;
|
||||||
|
|
||||||
const stats = docsSnap.docs.map((d) => d.data());
|
const stats = docsSnap.docs.map((d) => d.data());
|
||||||
const results = (stats.reduce((accm: ModuleScore[], { module, score }) => {
|
const results = (
|
||||||
|
stats.reduce((accm: ModuleScore[], { module, score }) => {
|
||||||
const fixedModuleStr = module[0].toUpperCase() + module.substring(1);
|
const fixedModuleStr = module[0].toUpperCase() + module.substring(1);
|
||||||
if (accm.find((e: ModuleScore) => e.module === fixedModuleStr)) {
|
if (accm.find((e: ModuleScore) => e.module === fixedModuleStr)) {
|
||||||
return accm.map((e: ModuleScore) => {
|
return accm.map((e: ModuleScore) => {
|
||||||
@@ -186,14 +225,48 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
score: score.correct,
|
score: score.correct,
|
||||||
total: score.total,
|
total: score.total,
|
||||||
feedback: getFeedback(module),
|
feedback: getFeedback(module),
|
||||||
|
code: module,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, []) as ModuleScore[]).map((moduleScore) => {
|
}, []) as ModuleScore[]
|
||||||
|
).map((moduleScore) => {
|
||||||
const { score, total } = moduleScore;
|
const { score, total } = moduleScore;
|
||||||
|
const bandScore = calculateBandScore(
|
||||||
|
score,
|
||||||
|
total,
|
||||||
|
moduleScore.code as Module,
|
||||||
|
user.focus
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...moduleScore,
|
...moduleScore,
|
||||||
png: getRadialProgressPNG('azul', score, total),
|
png: getRadialProgressPNG("azul", score, total),
|
||||||
|
bandScore,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const skillsFeedback =
|
||||||
|
(await getSkillsFeedback(
|
||||||
|
results.map(({ code, bandScore }) => ({
|
||||||
|
code,
|
||||||
|
name: moduleLabels[code],
|
||||||
|
grade: bandScore,
|
||||||
|
}))
|
||||||
|
)) || ([] as SkillsFeedbackResponse[]);
|
||||||
|
|
||||||
|
const finalResults = results.map((result) => {
|
||||||
|
const feedback = skillsFeedback.find(
|
||||||
|
(f: SkillsFeedbackResponse) => f.code === result.module
|
||||||
|
);
|
||||||
|
|
||||||
|
if (feedback) {
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
feedback: feedback?.evaluation + " " + feedback?.suggestions,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
const [stat] = stats as Stat[];
|
const [stat] = stats as Stat[];
|
||||||
@@ -211,9 +284,9 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
module: "Overall",
|
module: "Overall",
|
||||||
score: overallScore,
|
score: overallScore,
|
||||||
total: overallTotal,
|
total: overallTotal,
|
||||||
png: getRadialProgressPNG('laranja', overallScore, overallTotal),
|
png: getRadialProgressPNG("laranja", overallScore, overallTotal),
|
||||||
} as ModuleScore;
|
} as ModuleScore;
|
||||||
const testDetails = [overallDetail, ...results];
|
const testDetails = [overallDetail, ...finalResults];
|
||||||
const renderDetails = () => {
|
const renderDetails = () => {
|
||||||
if (stats[0].module === "level") {
|
if (stats[0].module === "level") {
|
||||||
return <LevelExamDetails detail={overallDetail} />;
|
return <LevelExamDetails detail={overallDetail} />;
|
||||||
|
|||||||
Reference in New Issue
Block a user