diff --git a/src/app/api/monitoring/[[...slug]]/route.ts b/src/app/api/monitoring/[[...slug]]/route.ts index 18ba934..4176299 100644 --- a/src/app/api/monitoring/[[...slug]]/route.ts +++ b/src/app/api/monitoring/[[...slug]]/route.ts @@ -1682,6 +1682,60 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" }) } ) + .get("/peak-hours", async ({ query, set }) => { + const { idVillage } = query; + + try { + const data = await prisma.$queryRaw` + SELECT + EXTRACT(HOUR FROM ul."createdAt")::int AS hour, + COUNT(*)::int AS count + FROM "UserLog" ul + JOIN "User" u ON ul."idUser" = u."id" + WHERE (${idVillage ?? null}::text IS NULL OR u."idVillage" = ${idVillage ?? null}) + GROUP BY hour + ORDER BY hour + ` as { hour: number; count: number }[]; + + const map = new Map(data.map((d) => [d.hour, d.count])); + const result = Array.from({ length: 24 }, (_, i) => ({ + hour: i, + label: `${String(i).padStart(2, '0')}:00`, + count: map.get(i) ?? 0, + })); + + const peak = result.reduce((max, item) => (item.count > max.count ? item : max), result[0]); + + return { + success: true, + message: "Berhasil mendapatkan data", + data: { + hours: result, + peak, + }, + }; + } catch (error) { + console.error("[peak-hours] error:", error); + set.status = 500; + return { + success: false, + message: "Terjadi kesalahan pada server", + data: null, + }; + } + }, + { + query: t.Object({ + idVillage: t.Optional(t.String({ description: "ID desa (kosong = semua desa)" })), + }), + detail: { + summary: "Peak Hours", + description: "Mendapatkan distribusi aktivitas per jam dalam sehari (0-23) untuk desa tertentu atau semua desa.", + tags: ["villages"], + }, + } + ) + // ─── API KEY MANAGEMENT ────────────────────────────────────────────────── .get("/api-keys", async ({ set }) => {