import { Hono } from "hono"; import { HTTPException } from "hono/http-exception"; import db from "../../drizzle"; import { respondents } from "../../drizzle/schema/respondents"; import { users } from "../../drizzle/schema/users"; import { rolesToUsers } from "../../drizzle/schema/rolesToUsers"; import { hashPassword } from "../../utils/passwordUtils"; import requestValidator from "../../utils/requestValidator"; import authInfo from "../../middlewares/authInfo"; import checkPermission from "../../middlewares/checkPermission"; import { and, eq, or } from "drizzle-orm"; import { z } from "zod"; import HonoEnv from "../../types/HonoEnv"; const registerFormSchema = z.object({ name: z.string().min(1).max(255), username: z.string().min(1).max(255), email: z.string().email().optional(), password: z.string().min(6), companyName: z.string().min(1).max(255), position: z.string().min(1).max(255), workExperience: z.string().min(1).max(255), address: z.string().min(1), phoneNumber: z.string().min(1).max(13), isEnabled: z.string().default("false"), roles: z .string() .refine( (data) => { try { const parsed = JSON.parse(data); return Array.isArray(parsed); } catch { return false; } }, { message: "Roles must be an array", } ) .optional(), }); const respondentsRoute = new Hono() .use(authInfo) .post( "/", checkPermission("register.create"), requestValidator("json", registerFormSchema), async (c) => { const formData = c.req.valid("json"); console.log("Form Data:", formData); // Build conditions based on available formData const conditions = []; if (formData.email) { conditions.push(eq(users.email, formData.email)); } conditions.push(eq(users.username, formData.username)); const existingUser = await db .select() .from(users) .where(or(...conditions)); console.log("Existing Users:", existingUser); const existingRespondent = await db .select() .from(respondents) .where(eq(respondents.phoneNumber, formData.phoneNumber)); console.log("Existing Respondents:", existingRespondent); if (existingUser.length > 0) { throw new HTTPException(400, { message: "Email atau username sudah terdaftar", }); } if (existingRespondent.length > 0) { throw new HTTPException(400, { message: "Nomor HP sudah terdaftar", }); } // Hash the password const hashedPassword = await hashPassword(formData.password); console.log("Hashed Password:", hashedPassword); // Start a transaction try { const result = await db.transaction(async (trx) => { // Create user const [newUser] = await trx .insert(users) .values({ name: formData.name, username: formData.username, email: formData.email, password: hashedPassword, isEnabled: formData.isEnabled?.toLowerCase() === "true" || true, }) .returning(); console.log("New User:", newUser); // Create respondent await trx.insert(respondents).values({ companyName: formData.companyName, position: formData.position, workExperience: formData.workExperience, address: formData.address, phoneNumber: formData.phoneNumber, userId: newUser.id, }); console.log("Respondent Created for User ID:", newUser.id); // If roles are included in the request, add to rolesToUsers if (formData.roles) { try { const roles = JSON.parse(formData.roles) as string[]; if (roles.length) { await trx.insert(rolesToUsers).values( roles.map((role) => ({ userId: newUser.id, roleId: role, })) ); } } catch (error) { console.error("Error parsing roles:", error); throw new HTTPException(400, { message: "Invalid roles format", }); } } return newUser; }); return c.json({ message: "User and respondent created successfully", }, 201); } catch (error) { console.error("Error creating user and respondent:", error); throw new HTTPException(500, { message: "Error creating user and respondent", }); } } ); export default respondentsRoute;