diff --git a/apps/backend/src/routes/assessments/route.ts b/apps/backend/src/routes/assessments/route.ts index 95333c0..fea0cb6 100644 --- a/apps/backend/src/routes/assessments/route.ts +++ b/apps/backend/src/routes/assessments/route.ts @@ -13,6 +13,7 @@ import authInfo from "../../middlewares/authInfo"; import checkPermission from "../../middlewares/checkPermission"; import path from "path"; import fs from 'fs'; +import { notFound } from "../../errors/DashboardError"; export const answerFormSchema = z.object({ optionId: z.string().min(1), @@ -30,12 +31,10 @@ async function saveFile(filePath: string, fileBuffer: Buffer): Promise { } // Function to update the filename in the database -async function updateFilenameInDatabase(answerId: string, flname: string): Promise { +async function updateFilenameInDatabase(answerId: string, filename: string): Promise { await db.update(answers) - .set({ - filename: flname, - }) + .set({ filename }) .where(eq(answers.id, answerId)); } @@ -76,23 +75,14 @@ const assessmentsRoute = new Hono() .get( "/getAllQuestions", checkPermission("assessments.readAllQuestions"), - requestValidator( - "query", - z.object({ - page: z.coerce.number().int().min(0).default(0), - limit: z.coerce.number().int().min(1).max(1000).default(1000), - q: z.string().default(""), - }) - ), async (c) => { - const { page, limit, q } = c.req.valid("query"); - const totalCountQuery = sql`(SELECT count(*) FROM ${options} LEFT JOIN ${questions} ON ${options.questionId} = ${questions.id} LEFT JOIN ${subAspects} ON ${questions.subAspectId} = ${subAspects.id} LEFT JOIN ${aspects} ON ${subAspects.aspectId} = ${aspects.id} + WHERE ${questions.deletedAt} IS NULL )`; const result = await db @@ -112,34 +102,15 @@ const assessmentsRoute = new Hono() .leftJoin(questions, eq(options.questionId, questions.id)) .leftJoin(subAspects, eq(questions.subAspectId, subAspects.id)) .leftJoin(aspects, eq(subAspects.aspectId, aspects.id)) - .where( - and( - q - ? or( - ilike(aspects.name, q), - ilike(subAspects.name, q), - ilike(questions.question, q), - ilike(options.text, q), - ilike(options.score, q), - eq(options.id, q), - - ) - : undefined - ) - ) - .offset(page * limit) - .limit(limit); + .where(sql`${questions.deletedAt} IS NULL`) return c.json({ - data: result.map((d) => ({ ...d, fullCount: undefined })), - _metadata: { - currentPage: page, - totalPages: Math.ceil( - (Number(result[0]?.fullCount) ?? 0) / limit - ), - totalItems: Number(result[0]?.fullCount) ?? 0, - perPage: limit, - }, + data: result.map((d) => ( + { + ...d, + fullCount: undefined + } + )), }); } ) @@ -165,7 +136,10 @@ const assessmentsRoute = new Hono() const { assessmentId, page, limit, q } = c.req.valid("query"); // Query to count total answers for the specific assessmentId - const totalCountQuery = sql`(SELECT count(*) FROM ${answers} WHERE ${answers.assessmentId} = ${assessmentId})`; + const totalCountQuery = + sql`(SELECT count(*) + FROM ${answers} + WHERE ${answers.assessmentId} = ${assessmentId})`; // Query to retrieve answers for the specific assessmentId const result = await db @@ -225,12 +199,11 @@ const assessmentsRoute = new Hono() .limit(1); if (!currentAnswer.length) { - return c.json( + throw notFound( { message: "Answer not found", - }, - 404 - ); + } + ) } // Toggle the isFlagged value @@ -246,12 +219,11 @@ const assessmentsRoute = new Hono() .returning(); if (!updatedAnswer.length) { - return c.json( + throw notFound( { message: "Failed to update answer", - }, - 500 - ); + } + ) } return c.json( @@ -270,7 +242,7 @@ const assessmentsRoute = new Hono() checkPermission("assessments.checkAnswer"), async (c) => { const { optionId, assessmentId } = await c.req.json(); - + const result = await db .select() .from(answers) @@ -278,16 +250,24 @@ const assessmentsRoute = new Hono() and(eq(answers.optionId, optionId), eq(answers.assessmentId, assessmentId)) ) .execute(); - + const existingAnswer = result[0]; - + let response; + if (existingAnswer) { - return c.json({ exists: true, answerId: existingAnswer.id }); + response = { + exists: true, + answerId: existingAnswer.id + }; } else { - return c.json({ exists: false }); + response = { + exists: false + }; } + + return c.json(response); } - ) + ) // Upload filename to the table answers and save the file on the local storage .post( @@ -297,22 +277,28 @@ const assessmentsRoute = new Hono() // Get the Content-Type header const contentType = c.req.header('content-type'); if (!contentType || !contentType.includes('multipart/form-data')) { - return c.json({ success: false, message: 'Invalid Content-Type' }); + throw notFound({ + message: "Invalid Content-Type", + }); } // Extract boundary const boundary = contentType.split('boundary=')[1]; if (!boundary) { - return c.json({ success: false, message: 'Boundary not found' }); + throw notFound({ + message: "Boundary not found", + }); } // Get the raw body const body = await c.req.arrayBuffer(); const bodyString = Buffer.from(body).toString(); - + // Split the body by the boundary const parts = bodyString.split(`--${boundary}`); - + + let fileUrl = null; + for (const part of parts) { if (part.includes('Content-Disposition: form-data;')) { // Extract file name @@ -321,30 +307,44 @@ const assessmentsRoute = new Hono() const fileName = match[1]; const fileContentStart = part.indexOf('\r\n\r\n') + 4; const fileContentEnd = part.lastIndexOf('\r\n'); - + // Extract file content as Buffer const fileBuffer = Buffer.from(part.slice(fileContentStart, fileContentEnd), 'binary'); - + // Define file path and save the file const filePath = path.join('images', Date.now() + '-' + fileName); await saveFile(filePath, fileBuffer); - + // Assuming answerId is passed as a query parameter or in the form-data const answerId = c.req.query('answerId'); - if (answerId) { - await updateFilenameInDatabase(answerId, path.basename(filePath)); + if (!answerId) { + throw notFound({ + message: "answerId is required", + }); } - - // Return the file URL - const fileUrl = `/images/${path.basename(filePath)}`; - return c.json({ success: true, imageUrl: fileUrl }); + + await updateFilenameInDatabase(answerId, path.basename(filePath)); + + // Set the file URL for the final response + fileUrl = `/images/${path.basename(filePath)}`; } } } - return c.json({ success: false, message: 'No file uploaded' }); + if (!fileUrl) { + throw notFound({ + message: 'No file uploaded', + }); + } + + return c.json( + { + success: true, + imageUrl: fileUrl + } + ); } - ) + ) // Submit option to table answers from use-form in frontend .post( @@ -384,6 +384,8 @@ const assessmentsRoute = new Hono() const answerId = c.req.param("id"); const answerData = c.req.valid("json"); + let response; + let statusCode; const updatedAnswer = await db .update(answers) .set({ @@ -393,23 +395,25 @@ const assessmentsRoute = new Hono() .returning(); if (!updatedAnswer.length) { - return c.json( - { - message: "Answer not found or update failed", - }, - 404 - ); + response = { + message: "Answer not found or update failed", + }; + statusCode = 404; + } else { + response = { + message: "Answer updated successfully", + answer: updatedAnswer[0], + }; + statusCode = 200; } return c.json( - { - message: "Answer updated successfully", - answer: updatedAnswer[0], - }, - 200 + response, + { + status: statusCode + } ); } - ) + ) export default assessmentsRoute; -