From dfa3cd9f03ac3b0cbdf0662df3519737a4e1ee3d Mon Sep 17 00:00:00 2001 From: falendikategar Date: Wed, 9 Oct 2024 16:09:36 +0700 Subject: [PATCH] update: changes to backend endpoints in orderBy and search query usage --- .../assessmentRequestManagement/route.ts | 340 +++++++++--------- 1 file changed, 179 insertions(+), 161 deletions(-) diff --git a/apps/backend/src/routes/assessmentRequestManagement/route.ts b/apps/backend/src/routes/assessmentRequestManagement/route.ts index 802c702..8822f31 100644 --- a/apps/backend/src/routes/assessmentRequestManagement/route.ts +++ b/apps/backend/src/routes/assessmentRequestManagement/route.ts @@ -1,173 +1,191 @@ - import { and, eq, ilike, or, sql } from "drizzle-orm"; - import { Hono } from "hono"; - import checkPermission from "../../middlewares/checkPermission"; - import { z } from "zod"; - import { HTTPException } from "hono/http-exception"; - import db from "../../drizzle"; - import { assessments } from "../../drizzle/schema/assessments"; - import { respondents } from "../../drizzle/schema/respondents"; - import { users } from "../../drizzle/schema/users"; - import HonoEnv from "../../types/HonoEnv"; - import requestValidator from "../../utils/requestValidator"; - import authInfo from "../../middlewares/authInfo"; +import { and, eq, ilike, or, sql, desc } from "drizzle-orm"; +import { Hono } from "hono"; +import checkPermission from "../../middlewares/checkPermission"; +import { z } from "zod"; +import { HTTPException } from "hono/http-exception"; +import db from "../../drizzle"; +import { assessments } from "../../drizzle/schema/assessments"; +import { respondents } from "../../drizzle/schema/respondents"; +import { users } from "../../drizzle/schema/users"; +import HonoEnv from "../../types/HonoEnv"; +import requestValidator from "../../utils/requestValidator"; +import authInfo from "../../middlewares/authInfo"; - export const assessmentFormSchema = z.object({ - respondentId: z.string().min(1), - status: z.enum(["menunggu konfirmasi", "diterima", "ditolak", "selesai"]), - reviewedBy: z.string().min(1), - validatedBy: z.string().min(1), - validatedAt: z.string().optional(), - }); +export const assessmentFormSchema = z.object({ + respondentId: z.string().min(1), + status: z.enum(["menunggu konfirmasi", "diterima", "ditolak", "selesai"]), + reviewedBy: z.string().min(1), + validatedBy: z.string().min(1), + validatedAt: z.string().optional(), +}); - export const assessmentUpdateSchema = assessmentFormSchema.extend({ - validatedAt: z.string().optional().or(z.literal("")), - }); +export const assessmentUpdateSchema = assessmentFormSchema.extend({ + validatedAt: z.string().optional().or(z.literal("")), +}); - const assessmentsRequestManagementRoutes = new Hono() - .use(authInfo) - /** - * Get All Assessments (With Metadata) - * - * Query params: - * - withMetadata: boolean - */ - .get( - "/", - checkPermission("assessmentRequestManagement.readAll"), - requestValidator( - "query", - z.object({ - withMetadata: z - .string() - .optional() - .transform((v) => v?.toLowerCase() === "true"), - page: z.coerce.number().int().min(0).default(0), - limit: z.coerce.number().int().min(1).max(1000).default(10), - q: z.string().default(""), +const assessmentsRequestManagementRoutes = new Hono() + .use(authInfo) + /** + * Get All Assessments (With Metadata) + * + * Query params: + * - withMetadata: boolean + */ + .get( + "/", + checkPermission("assessmentRequestManagement.readAll"), + requestValidator( + "query", + z.object({ + withMetadata: z + .string() + .optional() + .transform((v) => v?.toLowerCase() === "true"), + page: z.coerce.number().int().min(0).default(0), + limit: z.coerce.number().int().min(1).max(1000).default(10), + q: z.string().default(""), + }) + ), + async (c) => { + const { page, limit, q } = c.req.valid("query"); + + // Query untuk menghitung total jumlah item (totalCountQuery) + const assessmentCountQuery = await db + .select({ + count: sql`count(*)`, }) - ), - async (c) => { - const { page, limit, q } = c.req.valid("query"); - - const totalCountQuery = sql`(SELECT count(*) FROM ${assessments})`; - - const result = await db - .select({ - idPermohonan: assessments.id, - namaResponden: users.name, - namaPerusahaan: respondents.companyName, - status: assessments.status, - tanggal: assessments.createdAt, - fullCount: totalCountQuery, - }) - .from(assessments) - .leftJoin(respondents, eq(assessments.respondentId, respondents.id)) - .leftJoin(users, eq(respondents.userId, users.id)) - .where( - q - ? or( - ilike(users.name, `%${q}%`), - ilike(respondents.companyName, `%${q}%`), - eq(assessments.id, q) - ) - : undefined + .from(assessments) + .leftJoin(respondents, eq(assessments.respondentId, respondents.id)) + .leftJoin(users, eq(respondents.userId, users.id)) + .where( + q + ? or( + ilike(users.name, `%${q}%`), + ilike(respondents.companyName, `%${q}%`), + sql`CAST(${assessments.status} AS TEXT) ILIKE ${'%' + q + '%'}`, + eq(assessments.id, q) ) - .offset(page * limit) - .limit(limit); + : undefined + ); - return c.json({ - data: result.map((d) => ({ - idPermohonan: d.idPermohonan, - namaResponden: d.namaResponden, - namaPerusahaan: d.namaPerusahaan, - status: d.status, - tanggal: d.tanggal, - })), - _metadata: { - currentPage: page, - totalPages: Math.ceil( - (Number(result[0]?.fullCount) ?? 0) / limit - ), - totalItems: Number(result[0]?.fullCount) ?? 0, - perPage: limit, - }, - }); - } - ) + const totalItems = Number(assessmentCountQuery[0]?.count) || 0; - // Get assessment by id - .get( - "/:id", - checkPermission("assessmentRequestManagement.read"), - async (c) => { - const assessmentId = c.req.param("id"); - - const queryResult = await db - .select({ - // id: assessments.id, - tanggal: assessments.createdAt, - nama: users.name, - posisi: respondents.position, - pengalamanKerja: respondents.workExperience, - email: users.email, - namaPerusahaan: respondents.companyName, - alamat: respondents.address, - nomorTelepon: respondents.phoneNumber, - username: users.username, - status: assessments.status, - }) - .from(assessments) - .leftJoin(respondents, eq(assessments.respondentId, respondents.id)) - .leftJoin(users, eq(respondents.userId, users.id)) - .where(eq(assessments.id, assessmentId)); - - if (!queryResult.length) - throw new HTTPException(404, { - message: "The assessment does not exist", - }); - - const assessmentData = queryResult[0]; - - return c.json(assessmentData); - } - ) - - .patch( - "/:id", - checkPermission("assessmentRequestManagement.update"), - requestValidator( - "json", - z.object({ - status: z.enum(["menunggu konfirmasi", "diterima", "ditolak", "selesai"]), + // Query utama untuk mendapatkan data permohonan assessment + const result = await db + .select({ + idPermohonan: assessments.id, + namaResponden: users.name, + namaPerusahaan: respondents.companyName, + status: assessments.status, + tanggal: assessments.createdAt, }) - ), - async (c) => { - const assessmentId = c.req.param("id"); - const { status } = c.req.valid("json"); - - const assessment = await db - .select() - .from(assessments) - .where(and(eq(assessments.id, assessmentId),)); - - if (!assessment[0]) throw new HTTPException(404, { - message: "Assessment tidak ditemukan.", - }); - - await db - .update(assessments) - .set({ - status, - }) - .where(eq(assessments.id, assessmentId)); - - return c.json({ - message: "Status assessment berhasil diperbarui.", - }); - } - ) + .from(assessments) + .leftJoin(respondents, eq(assessments.respondentId, respondents.id)) + .leftJoin(users, eq(respondents.userId, users.id)) + .where( + q + ? or( + ilike(users.name, `%${q}%`), + ilike(respondents.companyName, `%${q}%`), + sql`CAST(${assessments.status} AS TEXT) ILIKE ${'%' + q + '%'}`, + eq(assessments.id, q) + ) + : undefined + ) + .orderBy(desc(assessments.createdAt)) + .offset(page * limit) + .limit(limit); + return c.json({ + data: result.map((d) => ({ + idPermohonan: d.idPermohonan, + namaResponden: d.namaResponden, + namaPerusahaan: d.namaPerusahaan, + status: d.status, + tanggal: d.tanggal, + })), + _metadata: { + currentPage: page, + totalPages: Math.ceil(totalItems / limit), + totalItems, + perPage: limit, + }, + }); + } + ) + + // Get assessment by id + .get( + "/:id", + checkPermission("assessmentRequestManagement.read"), + async (c) => { + const assessmentId = c.req.param("id"); + const queryResult = await db + .select({ + tanggal: assessments.createdAt, + nama: users.name, + posisi: respondents.position, + pengalamanKerja: respondents.workExperience, + email: users.email, + namaPerusahaan: respondents.companyName, + alamat: respondents.address, + nomorTelepon: respondents.phoneNumber, + username: users.username, + status: assessments.status, + }) + .from(assessments) + .leftJoin(respondents, eq(assessments.respondentId, respondents.id)) + .leftJoin(users, eq(respondents.userId, users.id)) + .where(eq(assessments.id, assessmentId)); + + if (!queryResult.length) + throw new HTTPException(404, { + message: "The assessment does not exist", + }); + + const assessmentData = queryResult[0]; + + return c.json(assessmentData); + } + ) + + .patch( + "/:id", + checkPermission("assessmentRequestManagement.update"), + requestValidator( + "json", + z.object({ + status: z.enum(["menunggu konfirmasi", "diterima", "ditolak", "selesai"]), + }) + ), + async (c) => { + const assessmentId = c.req.param("id"); + const { status } = c.req.valid("json"); + + const assessment = await db + .select() + .from(assessments) + .where(and(eq(assessments.id, assessmentId),)); + + if (!assessment[0]) throw new HTTPException(404, { + message: "Assessment tidak ditemukan.", + }); + + await db + .update(assessments) + .set({ + status, + }) + .where(eq(assessments.id, assessmentId)); + + return c.json({ + message: "Status assessment berhasil diperbarui.", + }); + } + ) - export default assessmentsRequestManagementRoutes; + + +export default assessmentsRequestManagementRoutes;