From 5efb96a92a09bab560c226dfdd2095814e3dfad9 Mon Sep 17 00:00:00 2001 From: amal Date: Wed, 8 Apr 2026 17:24:50 +0800 Subject: [PATCH] upd: api monitoring--user --- src/app/api/monitoring/[[...slug]]/route.ts | 1209 ++++++++++++++----- 1 file changed, 903 insertions(+), 306 deletions(-) diff --git a/src/app/api/monitoring/[[...slug]]/route.ts b/src/app/api/monitoring/[[...slug]]/route.ts index 63a79ef..9526706 100644 --- a/src/app/api/monitoring/[[...slug]]/route.ts +++ b/src/app/api/monitoring/[[...slug]]/route.ts @@ -25,77 +25,75 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) } })) - .get( - "/grid-overview", - async ({ query, set }) => { - try { - const version = await prisma.setting.findMany({ - select: { - id: true, - name: true, - value: true + .get("/grid-overview", async ({ query, set }) => { + try { + const version = await prisma.setting.findMany({ + select: { + id: true, + name: true, + value: true + } + }); + + const result_version = Object.fromEntries(version.map(item => [item.id, item.value])); + + const activity_today = await prisma.userLog.count({ + where: { + createdAt: { + gte: moment().subtract(1, 'days').toDate(), + lte: moment().toDate(), } - }); + } + }) - const result_version = Object.fromEntries(version.map(item => [item.id, item.value])); - - const activity_today = await prisma.userLog.count({ - where: { - createdAt: { - gte: moment().subtract(1, 'days').toDate(), - lte: moment().toDate(), - } + const activity_yesterday = await prisma.userLog.count({ + where: { + createdAt: { + gte: moment().subtract(2, 'days').toDate(), + lte: moment().subtract(1, 'days').toDate(), } - }) - - const activity_yesterday = await prisma.userLog.count({ - where: { - createdAt: { - gte: moment().subtract(2, 'days').toDate(), - lte: moment().subtract(1, 'days').toDate(), - } - } - }) + } + }) - const activity_increase = (activity_today - activity_yesterday); - const percentage_increase = (activity_increase / activity_yesterday) * 100 + const activity_increase = (activity_today - activity_yesterday); + const percentage_increase = (activity_increase / activity_yesterday) * 100 - const total_village = await prisma.village.findMany({ - where: { - isDummy: false - } - }) + const total_village = await prisma.village.findMany({ + where: { + isDummy: false + } + }) - const total_village_active = total_village.filter((item) => item.isActive).length - const total_village_inactive = total_village.filter((item) => !item.isActive).length - - return { - success: true, - message: "Berhasil mendapatkan data", - data: { - version: result_version, - activity: { - today: activity_today, - increase: _.isNaN(percentage_increase) ? 0 : percentage_increase.toFixed(2), - }, - village: { - active: total_village_active, - inactive: total_village_inactive, - }, + const total_village_active = total_village.filter((item) => item.isActive).length + const total_village_inactive = total_village.filter((item) => !item.isActive).length + return { + success: true, + message: "Berhasil mendapatkan data", + data: { + version: result_version, + activity: { + today: activity_today, + increase: _.isNaN(percentage_increase) ? 0 : percentage_increase.toFixed(2), }, - }; - } catch (error) { - console.error("[overview] grid-overview error:", error); - set.status = 500; - return { - success: false, - message: "Terjadi kesalahan pada server", - data: null, - }; - } - }, + village: { + active: total_village_active, + inactive: total_village_inactive, + }, + + }, + }; + } catch (error) { + console.error("[overview] grid-overview error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, { detail: { summary: "Grid Overview", @@ -104,28 +102,26 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) }, } ) - .get( - "/daily-activity", - async ({ query, set }) => { - try { - // const data = await prisma.userLog.findMany({ - // where: { - // User: { - // Village: { - // isDummy: false - // } - // }, - // createdAt: { - // gte: moment().subtract(7, 'days').toDate(), - // lte: moment().toDate(), - // } - // }, - // select: { - // createdAt: true, - // } - // }) + .get("/daily-activity", async ({ query, set }) => { + try { + // const data = await prisma.userLog.findMany({ + // where: { + // User: { + // Village: { + // isDummy: false + // } + // }, + // createdAt: { + // gte: moment().subtract(7, 'days').toDate(), + // lte: moment().toDate(), + // } + // }, + // select: { + // createdAt: true, + // } + // }) - const data = await prisma.$queryRaw` + const data = await prisma.$queryRaw` SELECT DATE(ul."createdAt") AS tanggal, COUNT(*) AS total @@ -137,42 +133,42 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) GROUP BY tanggal ORDER BY tanggal;` as any[]; - const result = []; + const result = []; - // ubah data ke map biar gampang lookup - const map = data.reduce((acc: any, item: any) => { - const key = moment(item.tanggal).format('YYYY-MM-DD'); - acc[key] = Number(item.total); - return acc; - }, {}); + // ubah data ke map biar gampang lookup + const map = data.reduce((acc: any, item: any) => { + const key = moment(item.tanggal).format('YYYY-MM-DD'); + acc[key] = Number(item.total); + return acc; + }, {}); - // generate 7 hari terakhir - for (let i = 6; i >= 0; i--) { - const date = moment().subtract(i, 'days'); + // generate 7 hari terakhir + for (let i = 6; i >= 0; i--) { + const date = moment().subtract(i, 'days'); - const key = date.format('YYYY-MM-DD'); + const key = date.format('YYYY-MM-DD'); - result.push({ - date: date.format('DD MMM'), - logs: map[key] || 0 - }); - } - - return { - success: true, - message: "Berhasil mendapatkan data", - data: result, - }; - } catch (error) { - console.error("[overview] daily-activity error:", error); - set.status = 500; - return { - success: false, - message: "Terjadi kesalahan pada server", - data: null, - }; + result.push({ + date: date.format('DD MMM'), + logs: map[key] || 0 + }); } - }, + + return { + success: true, + message: "Berhasil mendapatkan data", + data: result, + }; + } catch (error) { + console.error("[overview] daily-activity error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, { detail: { summary: "Daily Activity", @@ -181,11 +177,9 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) }, } ) - .get( - "/comparison-activity", - async ({ query, set }) => { - try { - const data = await prisma.$queryRaw` + .get("/comparison-activity", async ({ query, set }) => { + try { + const data = await prisma.$queryRaw` SELECT v."name", COUNT(ul."id") AS total_logs @@ -198,27 +192,27 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) ORDER BY total_logs DESC; ` as any[]; - const result = data.map(item => ({ - village: item.name, - activity: Number(item.total_logs) - })); + const result = data.map(item => ({ + village: item.name, + activity: Number(item.total_logs) + })); - return { - success: true, - message: "Berhasil mendapatkan data", - data: result, - }; - } catch (error) { - console.error("[overview] comparison-activity error:", error); - set.status = 500; - return { - success: false, - message: "Terjadi kesalahan pada server", - data: null, - }; - } - }, + return { + success: true, + message: "Berhasil mendapatkan data", + data: result, + }; + } catch (error) { + console.error("[overview] comparison-activity error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, { detail: { summary: "Comparison Activity", @@ -227,59 +221,117 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) }, } ) - .get( - "/get-villages", - async ({ query, set }) => { - const { search, page } = query; - const pageNum = Number(page ?? 1); - try { - const data = await prisma.village.findMany({ - where: { - isDummy: false, - ...(search && { name: { contains: search, mode: 'insensitive' } }) - }, - select: { - id: true, - name: true, - isActive: true, - createdAt: true, - User: { - where: { - idUserRole: "supadmin" - }, - select: { - name: true, - }, - take: 1, + .post("/version-update", async ({ body, set }) => { + try { + const { mobile_latest_version, mobile_minimum_version, mobile_maintenance, mobile_message_update } = body + + await prisma.$transaction([ + prisma.setting.update({ + where: { id: "mobile_latest_version" }, + data: { value: mobile_latest_version }, + }), + prisma.setting.update({ + where: { id: "mobile_minimum_version" }, + data: { value: mobile_minimum_version }, + }), + prisma.setting.update({ + where: { id: "mobile_maintenance" }, + data: { value: mobile_maintenance.toString() }, + }), + prisma.setting.update({ + where: { id: "mobile_message_update" }, + data: { value: mobile_message_update }, + }), + ]); + + return { + success: true, + message: "Berhasil update data", + }; + } catch (error) { + console.error("[overview] version-update error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + }; + } + }, + { + body: t.Object({ + mobile_latest_version: t.String({ + error: "mobile latest version harus diisi", + description: "mobile latest version yang ingin diupdate" + }), + mobile_minimum_version: t.String({ + error: "mobile minimum version harus diisi", + description: "mobile minimum version yang ingin diupdate" + }), + mobile_maintenance: t.Boolean({ + description: "status maintenance mobile app" + }), + mobile_message_update: t.String({ + description: "pesan update mobile app" + }), + }), + detail: { + summary: "Version Update", + description: "Menu Overview - Mengupdate data versi aplikasi.", + tags: ["overview"], + }, + } + ) + .get("/get-villages", async ({ query, set }) => { + const { search, page } = query; + const pageNum = Number(page ?? 1); + try { + const data = await prisma.village.findMany({ + where: { + isDummy: false, + ...(search && { name: { contains: search, mode: 'insensitive' } }) + }, + select: { + id: true, + name: true, + isActive: true, + createdAt: true, + User: { + where: { + idUserRole: "supadmin" }, + select: { + name: true, + }, + take: 1, }, - skip: (pageNum - 1) * 10, - take: 10, - }) + }, + skip: (pageNum - 1) * 10, + take: 10, + }) - const result = data.map((village) => ({ - id: village.id, - name: village.name, - isActive: village.isActive, - createdAt: formatDateTime(village.createdAt), - perbekel: village.User[0]?.name || null, - })); + const result = data.map((village) => ({ + id: village.id, + name: village.name, + isActive: village.isActive, + createdAt: formatDateTime(village.createdAt), + perbekel: village.User[0]?.name || null, + })); - return { - success: true, - message: "Berhasil mendapatkan data", - data: result, - }; - } catch (error) { - console.error("[villages] get-villages error:", error); - set.status = 500; - return { - success: false, - message: "Terjadi kesalahan pada server", - data: null, - }; - } - }, + return { + success: true, + message: "Berhasil mendapatkan data", + data: result, + }; + } catch (error) { + console.error("[villages] get-villages error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, { query: t.Object({ search: t.Optional(t.String({ description: "Kata kunci pencarian nama desa" })), @@ -292,64 +344,174 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) }, } ) - .get( - "/info-villages", - async ({ query, set }) => { - const { id } = query; - try { - const data = await prisma.village.findUnique({ - where: { - id: id, + .post("/create-villages", async ({ body, set }) => { + const { name, desc, username, phone, nik, email, gender } = body; + try { + const create_village = await prisma.village.create({ + data: { + name: name, + desc: desc, + isDummy: false, + }, + select: { + id: true + } + }) + + if (create_village) { + const create_group = await prisma.group.create({ + data: { + idVillage: create_village.id, + name: "Dinas", }, select: { - id: true, - name: true, - isActive: true, - createdAt: true, - User: { - where: { - idUserRole: "supadmin" - }, - select: { - name: true, - }, - take: 1, - }, - }, + id: true + } }) - if (!data) { - set.status = 404; + const create_position = await prisma.position.create({ + data: { + idGroup: create_group.id, + name: "Perbekel", + }, + select: { + id: true + } + }) + + const cek_user = await prisma.user.count({ + where: { + OR: [ + { nik: nik }, + { phone: phone }, + { email: email }, + ] + }, + }); + + if (cek_user > 0) { return { - success: false, - message: "Desa tidak ditemukan", - data: null, + success: true, + message: "Desa berhasil ditambahkan, namun user sudah terdaftar. Silahkan daftar user pada menu list user.", }; } - const result = data ? { - id: data?.id, - name: data?.name, - isActive: data?.isActive, - createdAt: data?.createdAt ? formatDateTime(data.createdAt) : null, - perbekel: data?.User[0]?.name || null, - } : null; + const create_user = await prisma.user.create({ + data: { + idUserRole: "supadmin", + idVillage: create_village.id, + idGroup: create_group.id, + idPosition: create_position.id, + nik: nik, + name: username, + phone: phone, + email: email, + gender: gender + }, + select: { + id: true + } + }) - return { - success: true, - message: "Berhasil mendapatkan data", - data: result, - }; - } catch (error) { - console.error("[detail-villages] info-villages error:", error); - set.status = 500; + if (create_user) { + return { + success: true, + message: "Desa dan user berhasil ditambahkan.", + }; + } else { + return { + success: true, + message: "Desa berhasil ditambahkan, namun user gagal ditambahkan. Silahkan daftar user pada menu list user.", + }; + } + } else { return { success: false, - message: "Terjadi kesalahan pada server", + message: "Gagal menambahkan data", + }; + } + } catch (error) { + console.error("[villages] create-villages error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + }; + } + }, + { + body: t.Object({ + name: t.String({ description: "Nama desa" }), + desc: t.String({ description: "Deskripsi desa" }), + username: t.String({ description: "Username" }), + phone: t.String({ description: "Nomor telepon" }), + nik: t.String({ description: "Nomor Induk Kependudukan" }), + email: t.String({ description: "Email" }), + gender: t.String({ description: "Jenis Kelamin" }), + }), + detail: { + summary: "Create Villages", + description: "Menu Villages - Membuat data desa.", + tags: ["villages"], + }, + } + ) + .get("/info-villages", async ({ query, set }) => { + const { id } = query; + try { + const data = await prisma.village.findUnique({ + where: { + id: id, + }, + select: { + id: true, + name: true, + isActive: true, + createdAt: true, + User: { + where: { + idUserRole: "supadmin" + }, + select: { + name: true, + }, + take: 1, + }, + }, + }) + + if (!data) { + set.status = 404; + return { + success: false, + message: "Desa tidak ditemukan", data: null, }; } - }, + + const result = data ? { + id: data?.id, + name: data?.name, + isActive: data?.isActive, + createdAt: data?.createdAt ? formatDateTime(data.createdAt) : null, + perbekel: data?.User[0]?.name || null, + } : null; + + return { + success: true, + message: "Berhasil mendapatkan data", + data: result, + }; + } catch (error) { + console.error("[detail-villages] info-villages error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, { query: t.Object({ id: t.Optional(t.String({ description: "ID desa" })), @@ -361,87 +523,85 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) }, } ) - .get( - "/grid-villages", - async ({ query, set }) => { - const { id } = query; + .get("/grid-villages", async ({ query, set }) => { + const { id } = query; - try { - const village = await prisma.village.findUnique({ - where: { id: id } - }); + try { + const village = await prisma.village.findUnique({ + where: { id: id } + }); - if (!village) { - set.status = 404; - return { - success: false, - message: "Desa tidak ditemukan", - data: null, - }; - } - - const dataUser = await prisma.user.findMany({ - where: { - idVillage: id, - NOT: { - idUserRole: "developer" - } - } - }) - - const dataGroup = await prisma.group.findMany({ - where: { - idVillage: id, - } - }) - - const dataDivision = await prisma.division.findMany({ - where: { - idVillage: id, - } - }) - - const dataProject = await prisma.project.findMany({ - where: { - idVillage: id - } - }) - - - const result = { - user: { - active: dataUser.filter((user) => user.isActive).length, - nonActive: dataUser.filter((user) => !user.isActive).length, - }, - group: { - active: dataGroup.filter((group) => group.isActive).length, - nonActive: dataGroup.filter((group) => !group.isActive).length, - }, - division: { - active: dataDivision.filter((division) => division.isActive).length, - nonActive: dataDivision.filter((division) => !division.isActive).length, - }, - project: { - active: dataProject.filter((project) => project.isActive).length, - nonActive: dataProject.filter((project) => !project.isActive).length, - } - }; - - return { - success: true, - message: "Berhasil mendapatkan data", - data: result, - }; - } catch (error) { - console.error("[detail-villages] grid-villages error:", error); - set.status = 500; + if (!village) { + set.status = 404; return { success: false, - message: "Terjadi kesalahan pada server", + message: "Desa tidak ditemukan", data: null, }; } - }, + + const dataUser = await prisma.user.findMany({ + where: { + idVillage: id, + NOT: { + idUserRole: "developer" + } + } + }) + + const dataGroup = await prisma.group.findMany({ + where: { + idVillage: id, + } + }) + + const dataDivision = await prisma.division.findMany({ + where: { + idVillage: id, + } + }) + + const dataProject = await prisma.project.findMany({ + where: { + idVillage: id + } + }) + + + const result = { + user: { + active: dataUser.filter((user) => user.isActive).length, + nonActive: dataUser.filter((user) => !user.isActive).length, + }, + group: { + active: dataGroup.filter((group) => group.isActive).length, + nonActive: dataGroup.filter((group) => !group.isActive).length, + }, + division: { + active: dataDivision.filter((division) => division.isActive).length, + nonActive: dataDivision.filter((division) => !division.isActive).length, + }, + project: { + active: dataProject.filter((project) => project.isActive).length, + nonActive: dataProject.filter((project) => !project.isActive).length, + } + }; + + return { + success: true, + message: "Berhasil mendapatkan data", + data: result, + }; + } catch (error) { + console.error("[detail-villages] grid-villages error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, { query: t.Object({ id: t.Optional(t.String({ description: "ID desa" })), @@ -621,6 +781,106 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) }, } ) + .post("/edit-villages", async ({ body, set }) => { + const { id, name, desc } = body; + + try { + const village = await prisma.village.findUnique({ + where: { id }, + }); + + if (!village) { + set.status = 404; + return { + success: false, + message: "Desa tidak ditemukan", + }; + } + + const upd = await prisma.village.update({ + where: { id }, + data: { + name, + desc, + }, + }); + + return { + success: true, + message: "Berhasil mengupdate data", + }; + } catch (error) { + console.error("[edit-villages] error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + }; + } + }, + { + body: t.Object({ + id: t.String({ description: "ID desa" }), + name: t.String({ description: "Nama desa" }), + desc: t.String({ description: "Deskripsi desa" }), + }), + detail: { + summary: "Edit Villages", + description: + "Mengupdate data desa", + tags: ["detail-villages"], + }, + } + ) + .post("/update-status-villages", async ({ body, set }) => { + const { id, active } = body; + + try { + const village = await prisma.village.findUnique({ + where: { id }, + }); + + if (!village) { + set.status = 404; + return { + success: false, + message: "Desa tidak ditemukan", + }; + } + + const upd = await prisma.village.update({ + where: { id }, + data: { + isActive: active, + }, + }); + + return { + success: true, + message: "Berhasil mengupdate data", + }; + } catch (error) { + console.error("[update-status-villages] error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + }; + } + }, + { + body: t.Object({ + id: t.String({ description: "ID desa" }), + active: t.Boolean({ description: "Status desa" }), + }), + detail: { + summary: "Update Status Villages", + description: + "Mengupdate status desa", + tags: ["detail-villages"], + }, + } + ) .get("/log-all-villages", async ({ query, set }) => { const { page = 1, search } = query; const pageNum = Number(page) || 1; @@ -745,7 +1005,344 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) tags: ["log-activity"], }, } - ); + ) + .get("/user", async ({ query, set }) => { + const { page = 1, search } = query; + const pageNum = Number(page) || 1; + const take = 25; + const skip = (pageNum - 1) * take; + + try { + const data = await prisma.user.findMany({ + where: { + ...(search && { + OR: [ + { + name: { + contains: search, + mode: "insensitive", + }, + }, + { + phone: { + contains: search, + mode: "insensitive", + }, + }, + { + email: { + contains: search, + mode: "insensitive", + }, + }, + { + nik: { + contains: search, + mode: "insensitive", + }, + }, + { + Village: { + name: { + contains: search, + mode: "insensitive", + }, + }, + }, + { + idUserRole: search, + }, + ], + }), + }, + select: { + id: true, + name: true, + nik: true, + phone: true, + email: true, + isWithoutOTP: true, + isActive: true, + UserRole: { + select: { + name: true, + }, + }, + Village: { + select: { + name: true, + }, + }, + Group: { + select: { + name: true, + }, + }, + Position: { + select: { + name: true, + }, + }, + }, + orderBy: { + createdAt: "desc", + }, + skip, + take, + }); + + const total = await prisma.user.count({ + where: { + ...(search && { + OR: [ + { + name: { + contains: search, + mode: "insensitive", + }, + }, + { + phone: { + contains: search, + mode: "insensitive", + }, + }, + { + email: { + contains: search, + mode: "insensitive", + }, + }, + { + nik: { + contains: search, + mode: "insensitive", + }, + }, + { + Village: { + name: { + contains: search, + mode: "insensitive", + }, + }, + }, + { + idUserRole: search, + }, + ], + }), + }, + }); + + const result = data.map((item) => ({ + id: item.id, + name: item.name, + nik: item.nik, + phone: item.phone, + email: item.email, + isWithoutOTP: item.isWithoutOTP, + isActive: item.isActive, + role: item.UserRole?.name, + village: item.Village?.name, + group: item.Group?.name, + position: item.Position?.name, + })); + + return { + success: true, + message: "Berhasil mendapatkan data", + data: { + user: result, + total, + totalPage: Math.ceil(total / take), + currentPage: pageNum, + }, + }; + } catch (error) { + console.error("[user] error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, + { + query: t.Object({ + page: t.Optional(t.String({ description: "Halaman" })), + search: t.Optional(t.String({ description: "Pencarian" })), + }), + detail: { + summary: "User", + description: + "Mendapatkan data user berdasarkan halaman dan pencarian", + tags: ["user"], + }, + } + ) + .post("/create-user", async ({ body, set }) => { + const { name, nik, phone, email, gender, idUserRole, idVillage, idGroup, idPosition } = body; + + try { + const cekUser = await prisma.user.findFirst({ + where: { + OR: [ + { nik }, + { phone }, + { email }, + ], + }, + }); + + if (cekUser) { + return { + success: false, + message: "User sudah ada", + }; + } + + const user = await prisma.user.create({ + data: { + name, + nik, + phone, + email, + gender, + idUserRole, + idVillage, + idGroup, + idPosition, + }, + }); + + return { + success: true, + message: "Berhasil membuat user", + }; + } catch (error) { + console.error("[create-user] error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + }; + } + }, + { + body: t.Object({ + name: t.String({ description: "Nama" }), + nik: t.String({ description: "NIK" }), + phone: t.String({ description: "Nomor Telepon" }), + email: t.String({ description: "Email" }), + gender: t.String({ description: "Jenis Kelamin" }), + idUserRole: t.String({ description: "ID Role" }), + idVillage: t.String({ description: "ID Desa" }), + idGroup: t.String({ description: "ID Group" }), + idPosition: t.Optional(t.String({ description: "ID Posisi" })), + }), + detail: { + summary: "Create User", + description: + "Membuat user", + tags: ["user"], + }, + } + ) + .post("/edit-user", async ({ body, set }) => { + const { id, name, nik, phone, email, gender, idUserRole, idVillage, idGroup, idPosition, isActive, isWithoutOTP } = body; + + try { + const cekId = await prisma.user.findFirst({ + where: { + id, + }, + }); + + if (!cekId) { + return { + success: false, + message: "User tidak ditemukan", + }; + } + + const cekUser = await prisma.user.findFirst({ + where: { + id: { + not: id, + }, + OR: [ + { nik }, + { phone }, + { email }, + ], + }, + }); + + if (cekUser) { + return { + success: false, + message: "User sudah ada", + }; + } + + const user = await prisma.user.update({ + where: { + id, + }, + data: { + name, + nik, + phone, + email, + gender, + idUserRole, + idVillage, + idGroup, + idPosition, + isActive, + isWithoutOTP, + }, + }); + + return { + success: true, + message: "Berhasil mengedit user", + }; + } catch (error) { + console.error("[edit-user] error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + }; + } + }, + { + body: t.Object({ + id: t.String({ description: "ID" }), + name: t.String({ description: "Nama" }), + nik: t.String({ description: "NIK" }), + phone: t.String({ description: "Nomor Telepon" }), + email: t.String({ description: "Email" }), + gender: t.String({ description: "Jenis Kelamin" }), + idUserRole: t.String({ description: "ID Role" }), + idVillage: t.String({ description: "ID Desa" }), + idGroup: t.String({ description: "ID Group" }), + idPosition: t.Optional(t.String({ description: "ID Posisi" })), + isActive: t.Boolean({ description: "Aktif" }), + isWithoutOTP: t.Boolean({ description: "Tanpa OTP" }), + }), + detail: { + summary: "Edit User", + description: + "Mengedit user", + tags: ["user"], + }, + } + ) + ; ;