Compare commits
15 Commits
amalia/11-
...
amalia/20-
| Author | SHA1 | Date | |
|---|---|---|---|
| 10457e96e8 | |||
| 9ad934c99f | |||
| 5bfcde32ed | |||
| 8240d608ad | |||
| fd7d08d38a | |||
| b95fd9543c | |||
| 7622c58ce4 | |||
| d1b90b63e9 | |||
| 387a86f17e | |||
| b749b333f6 | |||
| ac6db48a5a | |||
| d8e17340aa | |||
| b6e1f59945 | |||
| 0e9fa756cb | |||
| e6702ba01e |
@@ -48,6 +48,12 @@ WS_APIKEY="your-websocket-api-key"
|
|||||||
# API key untuk akses endpoint /api/monitoring (header: x-api-key)
|
# API key untuk akses endpoint /api/monitoring (header: x-api-key)
|
||||||
MONITORING_API_KEY="your-monitoring-api-key"
|
MONITORING_API_KEY="your-monitoring-api-key"
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# AI API
|
||||||
|
# ===========================================
|
||||||
|
# API key untuk akses endpoint /api/ai/* (header: x-api-key)
|
||||||
|
AI_API_KEY="your-ai-api-key"
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
# APPLICATION SETTINGS
|
# APPLICATION SETTINGS
|
||||||
# ===========================================
|
# ===========================================
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sistem-desa-mandiri",
|
"name": "sistem-desa-mandiri",
|
||||||
"version": "0.1.10",
|
"version": "0.1.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --experimental-https",
|
"dev": "next dev --experimental-https",
|
||||||
|
|||||||
1
prisma/migrations/20260512091824_auto/migration.sql
Normal file
1
prisma/migrations/20260512091824_auto/migration.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-- This is an empty migration.
|
||||||
14
prisma/migrations/20260513060219_add_api_key/migration.sql
Normal file
14
prisma/migrations/20260513060219_add_api_key/migration.sql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "ApiKey" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"key" TEXT NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "ApiKey_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "ApiKey_key_key" ON "ApiKey"("key");
|
||||||
1
prisma/migrations/20260515030040_auto/migration.sql
Normal file
1
prisma/migrations/20260515030040_auto/migration.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-- This is an empty migration.
|
||||||
1
prisma/migrations/20260515031651_auto/migration.sql
Normal file
1
prisma/migrations/20260515031651_auto/migration.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-- This is an empty migration.
|
||||||
1
prisma/migrations/20260518071507_auto/migration.sql
Normal file
1
prisma/migrations/20260518071507_auto/migration.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-- This is an empty migration.
|
||||||
1
prisma/migrations/20260519080535_auto/migration.sql
Normal file
1
prisma/migrations/20260519080535_auto/migration.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-- This is an empty migration.
|
||||||
@@ -729,3 +729,12 @@ model DivisionProjectTaskApproval {
|
|||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model ApiKey {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
name String
|
||||||
|
key String @unique
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|||||||
1439
src/app/api/ai/[[...slug]]/route.ts
Normal file
1439
src/app/api/ai/[[...slug]]/route.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ONE PENGUMUMAN, UNTUK TAMPIL DETAIL PENGUMUMAN
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
const { id } = context.params;
|
|
||||||
|
|
||||||
const data = await prisma.announcement.count({
|
|
||||||
where: {
|
|
||||||
id: id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data == 0) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
success: false,
|
|
||||||
message: "Gagal mendapatkan pengumuman, data tidak ditemukan",
|
|
||||||
},
|
|
||||||
{ status: 404 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const announcement = await prisma.announcement.findUnique({
|
|
||||||
where: {
|
|
||||||
id: id,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
desc: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!announcement) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
success: false,
|
|
||||||
message: "Gagal mendapatkan pengumuman, data tidak ditemukan",
|
|
||||||
},
|
|
||||||
{ status: 404 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let dataFix = { ...announcement, member: {} };
|
|
||||||
|
|
||||||
const announcementMember = await prisma.announcementMember.findMany({
|
|
||||||
where: {
|
|
||||||
idAnnouncement: id,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
idGroup: true,
|
|
||||||
idDivision: true,
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Division: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const formatMember = announcementMember.map((v: any) => ({
|
|
||||||
..._.omit(v, ["Group", "Division"]),
|
|
||||||
idGroup: v.idGroup,
|
|
||||||
idDivision: v.idDivision,
|
|
||||||
group: v.Group.name,
|
|
||||||
division: v.Division.name
|
|
||||||
}))
|
|
||||||
|
|
||||||
dataFix.member = formatMember
|
|
||||||
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
success: true,
|
|
||||||
message: "Berhasil mendapatkan pengumuman",
|
|
||||||
data: dataFix,
|
|
||||||
},
|
|
||||||
{ status: 200 }
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import "moment/locale/id";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
export const dynamic = 'force-dynamic'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL PENGUMUMAN
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const judul = searchParams.get('search');
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const get = searchParams.get('get');
|
|
||||||
const villageId = searchParams.get('desa');
|
|
||||||
const active = searchParams.get('active');
|
|
||||||
|
|
||||||
let getFix = 0;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
idVillage: String(villageId),
|
|
||||||
isActive: (active == "false" || active == undefined) ? false : true,
|
|
||||||
title: {
|
|
||||||
contains: (judul == undefined || judul == null) ? "" : judul,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await prisma.announcement.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan pengumuman", data, }, { status: 200 });
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ONE BANNER
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
const { id } = context.params;
|
|
||||||
|
|
||||||
const data = await prisma.bannerImage.findUnique({
|
|
||||||
where: {
|
|
||||||
id: String(id)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan banner", data }, { status: 200 });
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL BANNER
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const judul = searchParams.get('search');
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const get = searchParams.get('get');
|
|
||||||
const villageId = searchParams.get('desa');
|
|
||||||
const active = searchParams.get('active');
|
|
||||||
|
|
||||||
let getFix = 0;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
idVillage: String(villageId),
|
|
||||||
isActive: (active == "false" || active == undefined) ? false : true,
|
|
||||||
title: {
|
|
||||||
contains: (judul == undefined || judul == null) ? "" : judul,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await prisma.bannerImage.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan banner", data }, { status: 200 });
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan data banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import moment from "moment";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
// GET ONE CALENDER BY ID KALENDER REMINDER
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
const { id } = context.params
|
|
||||||
|
|
||||||
const cek = await prisma.divisionCalendarReminder.count({
|
|
||||||
where: {
|
|
||||||
id: id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (cek == 0) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
success: false,
|
|
||||||
message: "Gagal mendapatkan acara, data tidak ditemukan",
|
|
||||||
},
|
|
||||||
{ status: 404 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data: any = await prisma.divisionCalendarReminder.findUnique({
|
|
||||||
where: {
|
|
||||||
id: id
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
timeStart: true,
|
|
||||||
dateStart: true,
|
|
||||||
timeEnd: true,
|
|
||||||
createdAt: true,
|
|
||||||
DivisionCalendar: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
desc: true,
|
|
||||||
linkMeet: true,
|
|
||||||
repeatEventTyper: true,
|
|
||||||
repeatValue: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const { DivisionCalendar, ...dataCalender } = data
|
|
||||||
const timeStart = moment.utc(dataCalender?.timeStart).format("HH:mm")
|
|
||||||
const timeEnd = moment.utc(dataCalender?.timeEnd).format("HH:mm")
|
|
||||||
const idCalendar = data?.DivisionCalendar.id
|
|
||||||
const title = data?.DivisionCalendar?.title
|
|
||||||
const desc = data?.DivisionCalendar?.desc
|
|
||||||
const linkMeet = data?.DivisionCalendar?.linkMeet
|
|
||||||
const repeatEventTyper = data?.DivisionCalendar?.repeatEventTyper
|
|
||||||
const repeatValue = data?.DivisionCalendar?.repeatValue
|
|
||||||
|
|
||||||
|
|
||||||
const result = { ...dataCalender, timeStart, timeEnd, title, desc, linkMeet, repeatEventTyper, repeatValue }
|
|
||||||
|
|
||||||
|
|
||||||
const member = await prisma.divisionCalendarMember.findMany({
|
|
||||||
where: {
|
|
||||||
idCalendar
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idUser: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
email: true,
|
|
||||||
img: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const fixMember = member.map((v: any) => ({
|
|
||||||
..._.omit(v, ["User"]),
|
|
||||||
name: v.User.name,
|
|
||||||
email: v.User.email,
|
|
||||||
img: v.User.img
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
const dataFix = {
|
|
||||||
...result,
|
|
||||||
member: fixMember,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kalender", data: dataFix }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan (error: 500)", }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import moment from "moment";
|
|
||||||
import "moment/locale/id";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
//GET ALL CALENDER
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idDivision = searchParams.get("division");
|
|
||||||
const isDate = searchParams.get("date")
|
|
||||||
const villageId = searchParams.get("desa")
|
|
||||||
const active = searchParams.get("active")
|
|
||||||
const search = searchParams.get("search")
|
|
||||||
const page = searchParams.get("page")
|
|
||||||
const get = searchParams.get("get")
|
|
||||||
|
|
||||||
let getFix = 0;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
|
|
||||||
let kondisi: any = {}
|
|
||||||
|
|
||||||
if (idDivision != "" && idDivision != null && idDivision != undefined) {
|
|
||||||
if (isDate != null && isDate != undefined && isDate != "") {
|
|
||||||
kondisi = {
|
|
||||||
idDivision: String(idDivision),
|
|
||||||
dateStart: new Date(String(isDate)),
|
|
||||||
DivisionCalendar: {
|
|
||||||
title: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
isActive: (active == "false" || active == undefined) ? false : true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
kondisi = {
|
|
||||||
idDivision: String(idDivision),
|
|
||||||
DivisionCalendar: {
|
|
||||||
title: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
isActive: (active == "false" || active == undefined) ? false : true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isDate != null && isDate != undefined && isDate != "") {
|
|
||||||
kondisi = {
|
|
||||||
dateStart: new Date(String(isDate)),
|
|
||||||
DivisionCalendar: {
|
|
||||||
title: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
isActive: (active == "false" || active == undefined) ? false : true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
kondisi = {
|
|
||||||
DivisionCalendar: {
|
|
||||||
title: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
isActive: (active == "false" || active == undefined) ? false : true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await prisma.divisionCalendarReminder.findMany({
|
|
||||||
where: kondisi,
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
dateStart: true,
|
|
||||||
timeStart: true,
|
|
||||||
timeEnd: true,
|
|
||||||
createdAt: true,
|
|
||||||
DivisionCalendar: {
|
|
||||||
select: {
|
|
||||||
isActive: true,
|
|
||||||
title: true,
|
|
||||||
desc: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: [
|
|
||||||
{
|
|
||||||
dateStart: 'asc'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timeStart: 'asc'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timeEnd: 'asc'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const allOmit = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["DivisionCalendar", "User"]),
|
|
||||||
title: v.DivisionCalendar.title,
|
|
||||||
desc: v.DivisionCalendar.desc,
|
|
||||||
createdBy: v.DivisionCalendar.User.name,
|
|
||||||
isActive: v.DivisionCalendar.isActive,
|
|
||||||
timeStart: moment.utc(v.timeStart).format('HH:mm'),
|
|
||||||
timeEnd: moment.utc(v.timeEnd).format('HH:mm')
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kalender", data: allOmit }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan (error: 500)" }, { status: 404 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ONE DETAIL DISKUSI UMUM
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
let dataFix
|
|
||||||
const { id } = context.params
|
|
||||||
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const kategori = searchParams.get("cat");
|
|
||||||
const idVillage = searchParams.get("desa");
|
|
||||||
|
|
||||||
const cek = await prisma.discussion.count({
|
|
||||||
where: {
|
|
||||||
id,
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (cek == 0) {
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, data tidak ditemukan" }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kategori == "comment") {
|
|
||||||
const data = await prisma.discussionComment.findMany({
|
|
||||||
where: {
|
|
||||||
idDiscussion: id,
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
comment: true,
|
|
||||||
createdAt: true,
|
|
||||||
idUser: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
img: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
dataFix = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["User",]),
|
|
||||||
username: v.User.name,
|
|
||||||
img: v.User.img
|
|
||||||
}))
|
|
||||||
|
|
||||||
} else if (kategori == "member") {
|
|
||||||
const data = await prisma.discussionMember.findMany({
|
|
||||||
where: {
|
|
||||||
idDiscussion: id,
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
idUser: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
img: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
dataFix = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["User",]),
|
|
||||||
name: v.User.name,
|
|
||||||
img: v.User.img
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
const data = await prisma.discussion.findUnique({
|
|
||||||
where: {
|
|
||||||
id,
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
isActive: true,
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
idGroup: true,
|
|
||||||
desc: true,
|
|
||||||
status: true,
|
|
||||||
createdAt: true,
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
dataFix = {
|
|
||||||
id: data?.id,
|
|
||||||
isActive: data?.isActive,
|
|
||||||
idGroup: data?.idGroup,
|
|
||||||
group: data?.Group.name,
|
|
||||||
title: data?.title,
|
|
||||||
desc: data?.desc,
|
|
||||||
status: data?.status == 1 ? "Open" : "Close",
|
|
||||||
createdAt: data?.createdAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: dataFix }, { status: 200 });
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import "moment/locale/id";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL DISCUSSION GENERAL
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idGroup = searchParams.get("group");
|
|
||||||
const idVillage = searchParams.get("desa");
|
|
||||||
const search = searchParams.get('search');
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const status = searchParams.get('status');
|
|
||||||
const active = searchParams.get('active');
|
|
||||||
const get = searchParams.get('get')
|
|
||||||
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: active == "false" ? false : true,
|
|
||||||
status: status == "close" ? 2 : 1,
|
|
||||||
idVillage: String(idVillage),
|
|
||||||
title: {
|
|
||||||
contains: (search == undefined || search == "null") ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idGroup != "null" && idGroup != undefined && idGroup != "") {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const data = await prisma.discussion.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
orderBy: [
|
|
||||||
{
|
|
||||||
status: 'desc'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
createdAt: 'desc'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
desc: true,
|
|
||||||
status: true,
|
|
||||||
createdAt: true,
|
|
||||||
DiscussionComment: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixData = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["DiscussionComment", "status", "Group"]),
|
|
||||||
totalKomentar: v.DiscussionComment.length,
|
|
||||||
status: v.status == 1 ? "Open" : "Close",
|
|
||||||
group: v.Group.name,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: fixData }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
// GET ONE DISCUSSION BY ID
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
const { id } = context.params
|
|
||||||
|
|
||||||
const cek = await prisma.divisionDisscussion.count({
|
|
||||||
where: { id }
|
|
||||||
})
|
|
||||||
|
|
||||||
if (cek == 0) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{ success: false, message: "Gagal mendapatkan diskusi, data tidak ditemukan" },
|
|
||||||
{ status: 404 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await prisma.divisionDisscussion.findUnique({
|
|
||||||
where: { id },
|
|
||||||
select: {
|
|
||||||
isActive: true,
|
|
||||||
id: true,
|
|
||||||
desc: true,
|
|
||||||
status: true,
|
|
||||||
createdAt: true,
|
|
||||||
idDivision: true,
|
|
||||||
Division: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
User: { select: { name: true, img: true } },
|
|
||||||
DivisionDisscussionComment: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
comment: true,
|
|
||||||
createdAt: true,
|
|
||||||
User: { select: { name: true, img: true } }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{ success: false, message: "Diskusi tidak ditemukan" },
|
|
||||||
{ status: 404 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ambil nama creator
|
|
||||||
const createdBy = data.User.name;
|
|
||||||
const status = data.status == 1 ? "Open" : "Close"
|
|
||||||
const division = data.Division.name
|
|
||||||
|
|
||||||
// mapping komentar → hilangkan nested User
|
|
||||||
const komentar = data.DivisionDisscussionComment.map((comment: any) => ({
|
|
||||||
id: comment.id,
|
|
||||||
comment: comment.comment,
|
|
||||||
createdAt: comment.createdAt,
|
|
||||||
username: comment.User.name,
|
|
||||||
userimg: comment.User.img,
|
|
||||||
}));
|
|
||||||
|
|
||||||
// bentuk hasil akhir sesuai request
|
|
||||||
const result = {
|
|
||||||
id: data.id,
|
|
||||||
idDivision: data.idDivision,
|
|
||||||
division,
|
|
||||||
isActive: data.isActive,
|
|
||||||
desc: data.desc,
|
|
||||||
status,
|
|
||||||
createdAt: data.createdAt,
|
|
||||||
createdBy,
|
|
||||||
komentar,
|
|
||||||
};
|
|
||||||
|
|
||||||
return NextResponse.json(
|
|
||||||
{ success: true, message: "Berhasil mendapatkan diskusi", data: result },
|
|
||||||
{ status: 200 }
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import "moment/locale/id";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL DISCUSSION DIVISION ACTIVE = TRUE
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idDivision = searchParams.get("division");
|
|
||||||
const search = searchParams.get('search');
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const status = searchParams.get('status');
|
|
||||||
const isActive = searchParams.get('active');
|
|
||||||
const villageId = searchParams.get('desa');
|
|
||||||
const get = searchParams.get('get');
|
|
||||||
|
|
||||||
let getFix = 0;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: isActive == "false" ? false : true,
|
|
||||||
status: status == "close" ? 2 : 1,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
},
|
|
||||||
desc: {
|
|
||||||
contains: (search == undefined || search == "null") ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (idDivision != "null" && idDivision != null && idDivision != undefined) {
|
|
||||||
kondisi = {
|
|
||||||
isActive: isActive == "false" ? false : true,
|
|
||||||
status: status == "close" ? 2 : 1,
|
|
||||||
idDivision: idDivision,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
},
|
|
||||||
desc: {
|
|
||||||
contains: (search == undefined || search == "null") ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await prisma.divisionDisscussion.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc'
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
desc: true,
|
|
||||||
status: true,
|
|
||||||
createdAt: true,
|
|
||||||
idDivision: true,
|
|
||||||
Division: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DivisionDisscussionComment: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixData = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["DivisionDisscussionComment", "status", "Division"]),
|
|
||||||
totalKomentar: v.DivisionDisscussionComment.length,
|
|
||||||
status: v.status == 1 ? "Open" : "Close",
|
|
||||||
division: v.Division.name
|
|
||||||
}))
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: fixData, }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ONE DATA DIVISI :: UNTUK TAMPIL DATA DI HALAMAN EDIT DAN INFO
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
const { id } = context.params;
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idVillage = searchParams.get("desa");
|
|
||||||
|
|
||||||
const data = await prisma.division.findUnique({
|
|
||||||
where: {
|
|
||||||
id: String(id),
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan", }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const member = await prisma.divisionMember.findMany({
|
|
||||||
where: {
|
|
||||||
idDivision: String(id),
|
|
||||||
isActive: true,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
isAdmin: true,
|
|
||||||
idUser: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
img: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
isAdmin: 'desc',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const fixMember = member.map((v: any) => ({
|
|
||||||
..._.omit(v, ["User"]),
|
|
||||||
name: v.User.name,
|
|
||||||
img: v.User.img
|
|
||||||
}))
|
|
||||||
|
|
||||||
const dataFix = {
|
|
||||||
...data,
|
|
||||||
member: fixMember
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: dataFix, }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,269 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url)
|
|
||||||
const idVillage = searchParams.get("desa")
|
|
||||||
const idGroup = searchParams.get("group")
|
|
||||||
const division = searchParams.get("division")
|
|
||||||
const date = searchParams.get("date-start")
|
|
||||||
const dateAkhir = searchParams.get("date-end")
|
|
||||||
const kat = searchParams.get("cat")
|
|
||||||
|
|
||||||
|
|
||||||
// CHART PROGRESS
|
|
||||||
if (kat == "dokumen") {
|
|
||||||
// CHART DOKUMEN
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: true,
|
|
||||||
category: 'FILE',
|
|
||||||
Division: {
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
gte: new Date(String(date)),
|
|
||||||
lte: new Date(String(dateAkhir))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idGroup != undefined && idGroup != null && idGroup != "") {
|
|
||||||
kondisi = {
|
|
||||||
isActive: true,
|
|
||||||
category: 'FILE',
|
|
||||||
Division: {
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
gte: new Date(String(date)),
|
|
||||||
lte: new Date(String(dateAkhir))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (division != undefined && division != null && division != "") {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idDivision: String(division)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const dataDokumen = await prisma.divisionDocumentFolderFile.findMany({
|
|
||||||
where: kondisi,
|
|
||||||
})
|
|
||||||
|
|
||||||
const groupData = _.map(_.groupBy(dataDokumen, "extension"), (v: any) => ({
|
|
||||||
file: v[0].extension,
|
|
||||||
jumlah: v.length,
|
|
||||||
}))
|
|
||||||
|
|
||||||
const image = ['jpg', 'jpeg', 'png', 'heic']
|
|
||||||
|
|
||||||
let hasilImage = {
|
|
||||||
name: 'Gambar',
|
|
||||||
value: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
let hasilFile = {
|
|
||||||
name: 'Dokumen',
|
|
||||||
value: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
groupData.map((v: any) => {
|
|
||||||
if (image.some((i: any) => i == v.file)) {
|
|
||||||
hasilImage = {
|
|
||||||
name: 'Gambar',
|
|
||||||
value: hasilImage.value + v.jumlah
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hasilFile = {
|
|
||||||
name: 'Dokumen',
|
|
||||||
value: hasilFile.value + v.jumlah
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const hasilDokumen = { gambar: hasilImage.value, dokumen: hasilFile.value }
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: hasilDokumen }, { status: 200 });
|
|
||||||
} else if (kat == "event") {
|
|
||||||
// CHART EVENT
|
|
||||||
let kondisiSelesai: any = {
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
},
|
|
||||||
DivisionCalendarReminder: {
|
|
||||||
some: {
|
|
||||||
dateStart: {
|
|
||||||
gte: new Date(String(date)),
|
|
||||||
lte: new Date()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let kondisiComingSoon: any = {
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
},
|
|
||||||
DivisionCalendarReminder: {
|
|
||||||
some: {
|
|
||||||
dateStart: {
|
|
||||||
gt: new Date(),
|
|
||||||
lte: new Date(String(dateAkhir))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idGroup != undefined && idGroup != null && idGroup != "") {
|
|
||||||
kondisiSelesai = {
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
},
|
|
||||||
DivisionCalendarReminder: {
|
|
||||||
some: {
|
|
||||||
dateStart: {
|
|
||||||
gte: new Date(String(date)),
|
|
||||||
lte: new Date()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kondisiComingSoon = {
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
},
|
|
||||||
DivisionCalendarReminder: {
|
|
||||||
some: {
|
|
||||||
dateStart: {
|
|
||||||
gt: new Date(),
|
|
||||||
lte: new Date(String(dateAkhir))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (division != undefined && division != null && division != "") {
|
|
||||||
kondisiSelesai = {
|
|
||||||
...kondisiSelesai,
|
|
||||||
idDivision: String(division)
|
|
||||||
}
|
|
||||||
|
|
||||||
kondisiComingSoon = {
|
|
||||||
...kondisiComingSoon,
|
|
||||||
idDivision: String(division)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventSelesai = await prisma.divisionCalendar.count({
|
|
||||||
where: kondisiSelesai
|
|
||||||
})
|
|
||||||
|
|
||||||
const eventComingSoon = await prisma.divisionCalendar.count({
|
|
||||||
where: kondisiComingSoon
|
|
||||||
})
|
|
||||||
|
|
||||||
const hasilEvent = {
|
|
||||||
selesai: eventSelesai,
|
|
||||||
akan_datang: eventComingSoon
|
|
||||||
}
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: hasilEvent }, { status: 200 });
|
|
||||||
|
|
||||||
} else {
|
|
||||||
let kondisiProgress: any = {
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
},
|
|
||||||
DivisionProjectTask: {
|
|
||||||
some: {
|
|
||||||
dateStart: {
|
|
||||||
gte: new Date(String(date))
|
|
||||||
},
|
|
||||||
dateEnd: {
|
|
||||||
lte: new Date(String(dateAkhir))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idGroup != undefined && idGroup != null && idGroup != "") {
|
|
||||||
kondisiProgress = {
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
},
|
|
||||||
DivisionProjectTask: {
|
|
||||||
some: {
|
|
||||||
dateStart: {
|
|
||||||
gte: new Date(String(date))
|
|
||||||
},
|
|
||||||
dateEnd: {
|
|
||||||
lte: new Date(String(dateAkhir))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (division != undefined && division != null && division != "") {
|
|
||||||
kondisiProgress = {
|
|
||||||
...kondisiProgress,
|
|
||||||
idDivision: String(division)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await prisma.divisionProject.groupBy({
|
|
||||||
where: kondisiProgress,
|
|
||||||
by: ["status"],
|
|
||||||
_count: true
|
|
||||||
})
|
|
||||||
|
|
||||||
const dataStatus = [{ name: 'Segera', status: 0 }, { name: 'Dikerjakan', status: 1 }, { name: 'Selesai', status: 2 }, { name: 'Dibatalkan', status: 3 }]
|
|
||||||
const hasilProgres: any[] = []
|
|
||||||
let input
|
|
||||||
for (let index = 0; index < dataStatus.length; index++) {
|
|
||||||
const cek = data.some((i: any) => i.status == dataStatus[index].status)
|
|
||||||
if (cek) {
|
|
||||||
const find = ((Number(data.find((i: any) => i.status == dataStatus[index].status)?._count) * 100) / data.reduce((n, { _count }) => n + _count, 0)).toFixed(2)
|
|
||||||
const fix = find != "100.00" ? find.substr(-2, 2) == "00" ? find.substr(0, 2) : find : "100"
|
|
||||||
input = {
|
|
||||||
name: dataStatus[index].name,
|
|
||||||
value: fix
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
input = {
|
|
||||||
name: dataStatus[index].name,
|
|
||||||
value: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hasilProgres.push(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataFixProgress = hasilProgres.reduce((acc: any, curr: any) => {
|
|
||||||
acc[curr.name] = curr.value
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFixProgress }, { status: 200 });
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL DATA DIVISI == LIST DATA DIVISI
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idVillage = searchParams.get("desa");
|
|
||||||
const idGroup = searchParams.get("group");
|
|
||||||
const name = searchParams.get('search');
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const active = searchParams.get("active");
|
|
||||||
const get = searchParams.get('get')
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: active == 'false' ? false : true,
|
|
||||||
idVillage: String(idVillage),
|
|
||||||
name: {
|
|
||||||
contains: (name == undefined || name == "null") ? "" : name,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idGroup != "null" && idGroup != undefined && idGroup != "") {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const data = await prisma.division.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
desc: true,
|
|
||||||
idGroup: true,
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DivisionMember: {
|
|
||||||
where: {
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
idUser: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const allData = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["DivisionMember", "Group"]),
|
|
||||||
group: v.Group.name,
|
|
||||||
jumlahMember: v.DivisionMember.length,
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: allData }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import moment from "moment";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL DOCUMENT
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idDivision = searchParams.get("division");
|
|
||||||
const villageId = searchParams.get("desa");
|
|
||||||
const path = searchParams.get("path");
|
|
||||||
const active = searchParams.get("active");
|
|
||||||
const search = searchParams.get("search");
|
|
||||||
const page = searchParams.get("page");
|
|
||||||
const get = searchParams.get("get");
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
},
|
|
||||||
isActive: active == 'false' ? false : true,
|
|
||||||
path: (path == "undefined" || path == "null" || path == "" || path == null || path == undefined) ? "home" : path,
|
|
||||||
name: {
|
|
||||||
contains: (search == undefined || search == "null") ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idDivision != "null" && idDivision != undefined && idDivision != "") {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idDivision: String(idDivision)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let formatDataShare: any[] = [];
|
|
||||||
|
|
||||||
if (path == "home" || path == "null" || path == "undefined" || path == null || path == undefined || path == "") {
|
|
||||||
const dataShare = await prisma.divisionDocumentShare.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idDivision: String(idDivision),
|
|
||||||
DivisionDocumentFolderFile: {
|
|
||||||
isActive: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
DivisionDocumentFolderFile: {
|
|
||||||
select: {
|
|
||||||
idStorage: true,
|
|
||||||
id: true,
|
|
||||||
category: true,
|
|
||||||
name: true,
|
|
||||||
extension: true,
|
|
||||||
path: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
createdAt: true,
|
|
||||||
updatedAt: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
DivisionDocumentFolderFile: {
|
|
||||||
createdAt: 'desc'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
formatDataShare = dataShare.map((v: any) => ({
|
|
||||||
..._.omit(v, ["DivisionDocumentFolderFile"]),
|
|
||||||
idStorage: v.DivisionDocumentFolderFile.idStorage,
|
|
||||||
id: v.DivisionDocumentFolderFile.id,
|
|
||||||
category: v.DivisionDocumentFolderFile.category,
|
|
||||||
name: v.DivisionDocumentFolderFile.name,
|
|
||||||
extension: v.DivisionDocumentFolderFile.extension,
|
|
||||||
path: v.DivisionDocumentFolderFile.path,
|
|
||||||
createdBy: v.DivisionDocumentFolderFile.User.name,
|
|
||||||
createdAt: v.DivisionDocumentFolderFile.createdAt,
|
|
||||||
updatedAt: v.DivisionDocumentFolderFile.updatedAt,
|
|
||||||
share: true
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const data = await prisma.divisionDocumentFolderFile.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
category: true,
|
|
||||||
name: true,
|
|
||||||
extension: true,
|
|
||||||
idStorage: true,
|
|
||||||
path: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
createdAt: true,
|
|
||||||
updatedAt: true
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const allData = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["User", "createdAt", "updatedAt"]),
|
|
||||||
createdBy: v.User.name,
|
|
||||||
createdAt: v.createdAt,
|
|
||||||
updatedAt: v.updatedAt,
|
|
||||||
share: false
|
|
||||||
}))
|
|
||||||
|
|
||||||
if (formatDataShare.length > 0) {
|
|
||||||
allData.push(...formatDataShare)
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatData = _.orderBy(allData, ['category', 'createdAt'], ['desc', 'desc']);
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan item", data: formatData }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan item, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const villageId = searchParams.get("desa");
|
|
||||||
const isActive = searchParams.get("active");
|
|
||||||
const search = searchParams.get('search');
|
|
||||||
const page = searchParams.get('page')
|
|
||||||
const get = searchParams.get('get')
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
const data = await prisma.group.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: {
|
|
||||||
isActive: isActive == 'false' ? false : true,
|
|
||||||
idVillage: String(villageId),
|
|
||||||
name: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
name: 'asc'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan grup", data, }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL POSITION
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idVillage = searchParams.get("desa");
|
|
||||||
const idGroup = searchParams.get("group");
|
|
||||||
const active = searchParams.get('active');
|
|
||||||
const search = searchParams.get('search')
|
|
||||||
const page = searchParams.get('page')
|
|
||||||
const get = searchParams.get('get')
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: active == 'false' ? false : true,
|
|
||||||
Group: {
|
|
||||||
idVillage: String(idVillage)
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idGroup != "null" && idGroup != undefined && idGroup != "") {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const positions = await prisma.position.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
idGroup: true,
|
|
||||||
isActive: true,
|
|
||||||
createdAt: true,
|
|
||||||
updatedAt: true,
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
name: 'asc'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const allData = positions.map((v: any) => ({
|
|
||||||
..._.omit(v, ["Group"]),
|
|
||||||
group: v.Group.name
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan jabatan", data: allData }, { status: 200 });
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan jabatan, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import moment from "moment";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET DETAIL PROJECT / GET ONE PROJECT
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
let allData
|
|
||||||
const { id } = context.params;
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const kategori = searchParams.get("cat");
|
|
||||||
|
|
||||||
const data = await prisma.project.findUnique({
|
|
||||||
where: {
|
|
||||||
id: String(id),
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idVillage: true,
|
|
||||||
idGroup: true,
|
|
||||||
title: true,
|
|
||||||
status: true,
|
|
||||||
desc: true,
|
|
||||||
reason: true,
|
|
||||||
report: true,
|
|
||||||
isActive: true,
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan kegiatan, data tidak ditemukan", }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (kategori == "data") {
|
|
||||||
const dataProgress = await prisma.projectTask.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
updatedAt: 'desc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const semua = dataProgress.length
|
|
||||||
const selesai = _.filter(dataProgress, { status: 1 }).length
|
|
||||||
const progress = Math.ceil((selesai / semua) * 100)
|
|
||||||
|
|
||||||
allData = {
|
|
||||||
id: data.id,
|
|
||||||
idVillage: data.idVillage,
|
|
||||||
idGroup: data.idGroup,
|
|
||||||
group: data.Group.name,
|
|
||||||
title: data.title,
|
|
||||||
status: data.status == 3 ? "batal" : data.status == 2 ? "selesai" : data.status == 1 ? "dikerjakan" : "segera",
|
|
||||||
desc: data.desc,
|
|
||||||
reason: data.reason,
|
|
||||||
report: data.report,
|
|
||||||
isActive: data.isActive,
|
|
||||||
progress: (_.isNaN(progress)) ? 0 : progress,
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (kategori == "task") {
|
|
||||||
const dataProgress = await prisma.projectTask.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
desc: true,
|
|
||||||
status: true,
|
|
||||||
dateStart: true,
|
|
||||||
dateEnd: true,
|
|
||||||
createdAt: true
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'asc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const formatData = dataProgress.map((v: any) => ({
|
|
||||||
..._.omit(v, ["dateStart", "dateEnd", "createdAt", "status"]),
|
|
||||||
status: v.status == 1 ? "selesai" : "belum selesai",
|
|
||||||
dateStart: moment(v.dateStart).format("DD-MM-YYYY"),
|
|
||||||
dateEnd: moment(v.dateEnd).format("DD-MM-YYYY"),
|
|
||||||
createdAt: moment(v.createdAt).format("DD-MM-YYYY HH:mm"),
|
|
||||||
}))
|
|
||||||
const dataFix = _.orderBy(formatData, 'createdAt', 'asc')
|
|
||||||
allData = dataFix
|
|
||||||
|
|
||||||
} else if (kategori == "file") {
|
|
||||||
const dataFile = await prisma.projectFile.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'asc'
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
extension: true,
|
|
||||||
idStorage: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
allData = dataFile
|
|
||||||
|
|
||||||
} else if (kategori == "member") {
|
|
||||||
const dataMember = await prisma.projectMember.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idUser: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
email: true,
|
|
||||||
img: true,
|
|
||||||
Position: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const fix = dataMember.map((v: any) => ({
|
|
||||||
..._.omit(v, ["User"]),
|
|
||||||
name: v.User.name,
|
|
||||||
email: v.User.email,
|
|
||||||
img: v.User.img,
|
|
||||||
position: v.User.Position.name
|
|
||||||
}))
|
|
||||||
|
|
||||||
allData = fix
|
|
||||||
} else if (kategori == "link") {
|
|
||||||
const dataLink = await prisma.projectLink.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'asc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
allData = dataLink
|
|
||||||
}
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kegiatan", data: allData }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan kegiatan, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _, { ceil } from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL DATA PROJECT
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const idVillage = searchParams.get('desa');
|
|
||||||
const name = searchParams.get('search');
|
|
||||||
const status = searchParams.get('status');
|
|
||||||
const idGroup = searchParams.get("group");
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const get = searchParams.get('get');
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: true,
|
|
||||||
idVillage: String(idVillage),
|
|
||||||
title: {
|
|
||||||
contains: (name == undefined || name == "null") ? "" : name,
|
|
||||||
mode: "insensitive"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != "null" && status != undefined && status != "") {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
status: status == "segera" ? 0 : status == "dikerjakan" ? 1 : status == "selesai" ? 2 : status == "batal" ? 3 : 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (idGroup != "null" && idGroup != undefined && idGroup != "") {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const data = await prisma.project.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idGroup: true,
|
|
||||||
title: true,
|
|
||||||
desc: true,
|
|
||||||
status: true,
|
|
||||||
ProjectMember: {
|
|
||||||
where: {
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
idUser: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ProjectTask: {
|
|
||||||
where: {
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
title: true,
|
|
||||||
status: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const omitData = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["ProjectMember", "ProjectTask", "status", "Group"]),
|
|
||||||
group: v.Group.name,
|
|
||||||
status: v.status == 1 ? "dikerjakan" : v.status == 2 ? "selesai" : v.status == 3 ? "batal" : "segera",
|
|
||||||
progress: ceil((v.ProjectTask.filter((i: any) => i.status == 1).length * 100) / v.ProjectTask.length),
|
|
||||||
member: v.ProjectMember.length
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kegiatan", data: omitData }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan kegiatan, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import moment from "moment";
|
|
||||||
import "moment/locale/id";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET DETAIL TASK DIVISI / GET ONE
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
let allData
|
|
||||||
const { id } = context.params;
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const kategori = searchParams.get("cat");
|
|
||||||
|
|
||||||
const data = await prisma.divisionProject.findUnique({
|
|
||||||
where: {
|
|
||||||
id: String(id),
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idDivision: true,
|
|
||||||
title: true,
|
|
||||||
status: true,
|
|
||||||
desc: true,
|
|
||||||
reason: true,
|
|
||||||
report: true,
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan kegiatan, data tidak ditemukan", }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kategori == "data") {
|
|
||||||
const dataProgress = await prisma.divisionProjectTask.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
updatedAt: 'desc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const semua = dataProgress.length
|
|
||||||
const selesai = _.filter(dataProgress, { status: 1 }).length
|
|
||||||
const progress = Math.ceil((selesai / semua) * 100)
|
|
||||||
|
|
||||||
|
|
||||||
allData = {
|
|
||||||
id: data.id,
|
|
||||||
idDivision: data.idDivision,
|
|
||||||
division: data.Division.name,
|
|
||||||
title: data.title,
|
|
||||||
status: data.status == 3 ? "batal" : data.status == 2 ? "selesai" : data.status == 1 ? "dikerjakan" : "segera",
|
|
||||||
desc: data.desc,
|
|
||||||
reason: data.reason,
|
|
||||||
report: data.report,
|
|
||||||
isActive: data.isActive,
|
|
||||||
progress: progress,
|
|
||||||
}
|
|
||||||
} else if (kategori == "task") {
|
|
||||||
const dataProgress = await prisma.divisionProjectTask.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
status: true,
|
|
||||||
dateStart: true,
|
|
||||||
dateEnd: true,
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'asc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const fix = dataProgress.map((v: any) => ({
|
|
||||||
..._.omit(v, ["dateStart", "dateEnd", "status"]),
|
|
||||||
status: v.status == 1 ? "selesai" : "belum selesai",
|
|
||||||
dateStart: moment(v.dateStart).format("DD-MM-YYYY"),
|
|
||||||
dateEnd: moment(v.dateEnd).format("DD-MM-YYYY"),
|
|
||||||
}))
|
|
||||||
|
|
||||||
allData = fix
|
|
||||||
|
|
||||||
} else if (kategori == "file") {
|
|
||||||
const dataFile = await prisma.divisionProjectFile.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
ContainerFileDivision: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
extension: true,
|
|
||||||
idStorage: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const fix = dataFile.map((v: any) => ({
|
|
||||||
..._.omit(v, ["ContainerFileDivision"]),
|
|
||||||
nameInStorage: v.ContainerFileDivision.id,
|
|
||||||
name: v.ContainerFileDivision.name,
|
|
||||||
extension: v.ContainerFileDivision.extension,
|
|
||||||
idStorage: v.ContainerFileDivision.idStorage,
|
|
||||||
}))
|
|
||||||
|
|
||||||
allData = fix
|
|
||||||
|
|
||||||
} else if (kategori == "member") {
|
|
||||||
const dataMember = await prisma.divisionProjectMember.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idUser: true,
|
|
||||||
User: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
email: true,
|
|
||||||
img: true,
|
|
||||||
Position: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const fix = dataMember.map((v: any) => ({
|
|
||||||
..._.omit(v, ["User"]),
|
|
||||||
name: v.User.name,
|
|
||||||
email: v.User.email,
|
|
||||||
img: v.User.img,
|
|
||||||
position: v.User.Position.name
|
|
||||||
}))
|
|
||||||
|
|
||||||
allData = fix
|
|
||||||
} else if (kategori == "link") {
|
|
||||||
const dataLink = await prisma.divisionProjectLink.findMany({
|
|
||||||
where: {
|
|
||||||
isActive: true,
|
|
||||||
idProject: String(id)
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'asc'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
allData = dataLink
|
|
||||||
}
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan tugas divisi", data: allData }, { status: 200 });
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan tugas divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _, { ceil } from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
|
|
||||||
// GET ALL DATA TUGAS DIVISI
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const villageId = searchParams.get('desa');
|
|
||||||
const division = searchParams.get('division');
|
|
||||||
const search = searchParams.get('search');
|
|
||||||
const status = searchParams.get('status');
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const get = searchParams.get('get');
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: true,
|
|
||||||
Division: {
|
|
||||||
idVillage: String(villageId)
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
contains: (search == undefined || search == "null") ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != "null" && status != undefined && status != "" && status != null) {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
status: status == "segera" ? 0 : status == "dikerjakan" ? 1 : status == "selesai" ? 2 : status == "batal" ? 3 : 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (division != "null" && division != undefined && division != "" && division != null) {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idDivision: String(division)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const data = await prisma.divisionProject.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idDivision: true,
|
|
||||||
title: true,
|
|
||||||
desc: true,
|
|
||||||
status: true,
|
|
||||||
DivisionProjectTask: {
|
|
||||||
where: {
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
title: true,
|
|
||||||
status: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DivisionProjectMember: {
|
|
||||||
where: {
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
idUser: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Division: {
|
|
||||||
select: {
|
|
||||||
name: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: "desc"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const formatData = data.map((v: any) => ({
|
|
||||||
..._.omit(v, ["DivisionProjectTask", "DivisionProjectMember", "status", "Division"]),
|
|
||||||
division: v.Division.name,
|
|
||||||
status: v.status == 1 ? "dikerjakan" : v.status == 2 ? "selesai" : v.status == 3 ? "batal" : "segera",
|
|
||||||
progress: ceil((v.DivisionProjectTask.filter((i: any) => i.status == 1).length * 100) / v.DivisionProjectTask.length),
|
|
||||||
member: v.DivisionProjectMember.length,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: formatData }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
// GET ONE MEMBER / USER
|
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
|
||||||
try {
|
|
||||||
const { id } = context.params;
|
|
||||||
|
|
||||||
const users = await prisma.user.findUnique({
|
|
||||||
where: {
|
|
||||||
id: id,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
nik: true,
|
|
||||||
name: true,
|
|
||||||
phone: true,
|
|
||||||
email: true,
|
|
||||||
gender: true,
|
|
||||||
img: true,
|
|
||||||
idGroup: true,
|
|
||||||
isActive: true,
|
|
||||||
idPosition: true,
|
|
||||||
createdAt: true,
|
|
||||||
updatedAt: true,
|
|
||||||
UserRole: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
id: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Position: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
id: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
id: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const { ...userData } = users;
|
|
||||||
const group = users?.Group.name
|
|
||||||
const position = users?.Position?.name
|
|
||||||
const idUserRole = users?.UserRole.id
|
|
||||||
const phone = '+62' + users?.phone
|
|
||||||
const role = users?.UserRole.name
|
|
||||||
const gender = users?.gender == "F" ? "Perempuan" : "Laki-Laki"
|
|
||||||
|
|
||||||
const result = { ...userData, gender, group, position, idUserRole, phone, role };
|
|
||||||
|
|
||||||
const omitData = _.omit(result, ["Group", "Position", "UserRole"]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
success: true,
|
|
||||||
message: "Berhasil mendapatkan anggota",
|
|
||||||
data: omitData,
|
|
||||||
},
|
|
||||||
{ status: 200 }
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan anggota, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
// GET ALL MEMBER / USER
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const search = searchParams.get('search')
|
|
||||||
const idVillage = searchParams.get("desa");
|
|
||||||
const idGroup = searchParams.get("group");
|
|
||||||
const active = searchParams.get("active");
|
|
||||||
const page = searchParams.get('page');
|
|
||||||
const get = searchParams.get('get');
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
let kondisi: any = {
|
|
||||||
isActive: active == 'false' ? false : true,
|
|
||||||
idVillage: String(idVillage),
|
|
||||||
name: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive",
|
|
||||||
},
|
|
||||||
NOT: {
|
|
||||||
idUserRole: 'developer'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idGroup != "null" && idGroup != undefined && idGroup != "" && idGroup != null) {
|
|
||||||
kondisi = {
|
|
||||||
...kondisi,
|
|
||||||
idGroup: String(idGroup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const users = await prisma.user.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: kondisi,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
idUserRole: true,
|
|
||||||
isActive: true,
|
|
||||||
nik: true,
|
|
||||||
name: true,
|
|
||||||
phone: true,
|
|
||||||
Position: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Group: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
name: 'asc'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const allData = users.map((v: any) => ({
|
|
||||||
..._.omit(v, ["phone", "gender", "Group", "Position"]),
|
|
||||||
gender: v.gender == "F" ? "Perempuan" : "Laki-Laki",
|
|
||||||
phone: "+" + v.phone,
|
|
||||||
group: v.Group.name,
|
|
||||||
position: v?.Position?.name
|
|
||||||
}))
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil member", data: allData }, { status: 200 });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan anggota, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import { prisma } from "@/module/_global";
|
|
||||||
import _ from "lodash";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const isActive = searchParams.get("active");
|
|
||||||
const search = searchParams.get('search');
|
|
||||||
const page = searchParams.get('page')
|
|
||||||
const get = searchParams.get('get')
|
|
||||||
|
|
||||||
let getFix = 10;
|
|
||||||
if (get == null || get == undefined || get == "" || _.isNaN(Number(get))) {
|
|
||||||
getFix = 10;
|
|
||||||
} else {
|
|
||||||
getFix = Number(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSkip = page == null || page == undefined ? 0 : Number(page) * getFix - getFix;
|
|
||||||
|
|
||||||
const data = await prisma.village.findMany({
|
|
||||||
skip: dataSkip,
|
|
||||||
take: getFix,
|
|
||||||
where: {
|
|
||||||
isActive: isActive == 'false' ? false : true,
|
|
||||||
name: {
|
|
||||||
contains: (search == undefined || search == null) ? "" : search,
|
|
||||||
mode: "insensitive"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
isActive: true,
|
|
||||||
createdAt: true,
|
|
||||||
updatedAt: true
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
name: 'asc'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan desa", data, }, { status: 200 });
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan desa, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -96,13 +96,13 @@ async function sendNotification({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getApproversInVillage(idVillage: string): Promise<NotifTarget[]> {
|
async function getApproversInVillage(idVillage: string, idGroup: string): Promise<NotifTarget[]> {
|
||||||
const approvers = await prisma.user.findMany({
|
const approvers = await prisma.user.findMany({
|
||||||
where: {
|
where: {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
idVillage,
|
idVillage,
|
||||||
OR: [
|
OR: [
|
||||||
{ isApprover: true },
|
{ isApprover: true, idGroup },
|
||||||
{ UserRole: { id: 'supadmin' } }
|
{ UserRole: { id: 'supadmin' } }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -198,7 +198,10 @@ export async function POST(request: Request, context: { params: { id: string } }
|
|||||||
|
|
||||||
const task = await prisma.projectTask.findUnique({
|
const task = await prisma.projectTask.findUnique({
|
||||||
where: { id, isActive: true },
|
where: { id, isActive: true },
|
||||||
select: { id: true, status: true, idProject: true, title: true }
|
select: {
|
||||||
|
id: true, status: true, title: true,
|
||||||
|
Project: { select: { id: true, idGroup: true } }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!task) {
|
if (!task) {
|
||||||
@@ -227,14 +230,14 @@ export async function POST(request: Request, context: { params: { id: string } }
|
|||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await recalculateProjectStatus(task.idProject);
|
await recalculateProjectStatus(task.Project.id);
|
||||||
|
|
||||||
// Notifikasi ke semua approver
|
// Notifikasi ke semua approver di desa dan group yang sama
|
||||||
const approverTargets = await getApproversInVillage(String(userMobile.idVillage));
|
const approverTargets = await getApproversInVillage(String(userMobile.idVillage), task.Project.idGroup);
|
||||||
await sendNotification({
|
await sendNotification({
|
||||||
targets: approverTargets,
|
targets: approverTargets,
|
||||||
idUserFrom: userMobile.id,
|
idUserFrom: userMobile.id,
|
||||||
idContent: task.idProject,
|
idContent: task.Project.id,
|
||||||
title: 'Pengajuan Penyelesaian Tugas',
|
title: 'Pengajuan Penyelesaian Tugas',
|
||||||
desc: task.title,
|
desc: task.title,
|
||||||
});
|
});
|
||||||
@@ -271,7 +274,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
|||||||
|
|
||||||
const task = await prisma.projectTask.findUnique({
|
const task = await prisma.projectTask.findUnique({
|
||||||
where: { id, isActive: true },
|
where: { id, isActive: true },
|
||||||
select: { id: true, status: true, idProject: true, title: true }
|
select: { id: true, status: true, title: true, Project: { select: { id: true } } }
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!task) {
|
if (!task) {
|
||||||
@@ -304,7 +307,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
|||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await recalculateProjectStatus(task.idProject);
|
await recalculateProjectStatus(task.Project.id);
|
||||||
|
|
||||||
// Notifikasi ke submitter
|
// Notifikasi ke submitter
|
||||||
const submitterTarget = await getUserNotifTarget(pendingApproval.idUser);
|
const submitterTarget = await getUserNotifTarget(pendingApproval.idUser);
|
||||||
@@ -312,7 +315,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
|||||||
await sendNotification({
|
await sendNotification({
|
||||||
targets: [submitterTarget],
|
targets: [submitterTarget],
|
||||||
idUserFrom: userMobile.id,
|
idUserFrom: userMobile.id,
|
||||||
idContent: task.idProject,
|
idContent: task.Project.id,
|
||||||
title: 'Tugas Disetujui',
|
title: 'Tugas Disetujui',
|
||||||
desc: task.title,
|
desc: task.title,
|
||||||
});
|
});
|
||||||
@@ -339,7 +342,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
|||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await recalculateProjectStatus(task.idProject);
|
await recalculateProjectStatus(task.Project.id);
|
||||||
|
|
||||||
// Notifikasi ke submitter
|
// Notifikasi ke submitter
|
||||||
const submitterTarget = await getUserNotifTarget(pendingApproval.idUser);
|
const submitterTarget = await getUserNotifTarget(pendingApproval.idUser);
|
||||||
@@ -347,7 +350,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
|||||||
await sendNotification({
|
await sendNotification({
|
||||||
targets: [submitterTarget],
|
targets: [submitterTarget],
|
||||||
idUserFrom: userMobile.id,
|
idUserFrom: userMobile.id,
|
||||||
idContent: task.idProject,
|
idContent: task.Project.id,
|
||||||
title: 'Tugas Ditolak',
|
title: 'Tugas Ditolak',
|
||||||
desc: task.title,
|
desc: task.title,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export async function GET(request: Request, context: { params: { id: string } })
|
|||||||
where: {
|
where: {
|
||||||
id: String(id),
|
id: String(id),
|
||||||
isActive: true
|
isActive: true
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
Division: { select: { idGroup: true } }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -33,7 +36,7 @@ export async function GET(request: Request, context: { params: { id: string } })
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kategori == "data") {
|
if (kategori == "data") {
|
||||||
allData = data
|
allData = { ...data, idGroup: data.Division.idGroup }
|
||||||
} else if (kategori == "progress") {
|
} else if (kategori == "progress") {
|
||||||
const dataProgress = await prisma.divisionProjectTask.findMany({
|
const dataProgress = await prisma.divisionProjectTask.findMany({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -96,13 +96,19 @@ async function sendNotification({
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getApproversForDivision(idVillage: string, idDivision: string): Promise<NotifTarget[]> {
|
async function getApproversForDivision(idVillage: string, idDivision: string): Promise<NotifTarget[]> {
|
||||||
|
const division = await prisma.division.findUnique({
|
||||||
|
where: { id: idDivision },
|
||||||
|
select: { idGroup: true }
|
||||||
|
});
|
||||||
|
const idGroup = division?.idGroup;
|
||||||
|
|
||||||
const [globalApprovers, divisionAdmins] = await Promise.all([
|
const [globalApprovers, divisionAdmins] = await Promise.all([
|
||||||
prisma.user.findMany({
|
prisma.user.findMany({
|
||||||
where: {
|
where: {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
idVillage,
|
idVillage,
|
||||||
OR: [
|
OR: [
|
||||||
{ isApprover: true },
|
{ isApprover: true, idGroup },
|
||||||
{ UserRole: { id: 'supadmin' } }
|
{ UserRole: { id: 'supadmin' } }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -285,23 +291,35 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
|||||||
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
|
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const canApprove = await getApproverStatus(userMobile.id);
|
const taskForAuth = await prisma.divisionProjectTask.findUnique({
|
||||||
if (!canApprove) {
|
where: { id, isActive: true },
|
||||||
// Check if division admin
|
select: { idDivision: true }
|
||||||
const task = await prisma.divisionProjectTask.findUnique({
|
});
|
||||||
where: { id, isActive: true },
|
if (!taskForAuth) {
|
||||||
select: { idDivision: true }
|
return NextResponse.json({ success: false, message: "Tugas tidak ditemukan" }, { status: 200 });
|
||||||
});
|
}
|
||||||
if (task) {
|
|
||||||
const isDivAdmin = await prisma.divisionMember.count({
|
const [division, userFull, isDivAdmin] = await Promise.all([
|
||||||
where: { idDivision: task.idDivision, idUser: userMobile.id, isAdmin: true, isActive: true }
|
prisma.division.findUnique({
|
||||||
});
|
where: { id: taskForAuth.idDivision },
|
||||||
if (isDivAdmin === 0) {
|
select: { idGroup: true, idVillage: true }
|
||||||
return NextResponse.json({ success: false, message: "Anda tidak memiliki izin untuk menyetujui atau menolak tugas" }, { status: 200 });
|
}),
|
||||||
}
|
prisma.user.findUnique({
|
||||||
} else {
|
where: { id: userMobile.id },
|
||||||
return NextResponse.json({ success: false, message: "Tugas tidak ditemukan" }, { status: 200 });
|
select: { isApprover: true, idGroup: true, idVillage: true, UserRole: { select: { id: true } } }
|
||||||
}
|
}),
|
||||||
|
prisma.divisionMember.count({
|
||||||
|
where: { idDivision: taskForAuth.idDivision, idUser: userMobile.id, isAdmin: true, isActive: true }
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
const isSupadmin = APPROVER_ROLES.includes(userFull?.UserRole?.id ?? '');
|
||||||
|
const isGroupApprover = !!(userFull?.isApprover &&
|
||||||
|
userFull.idVillage === division?.idVillage &&
|
||||||
|
userFull.idGroup === division?.idGroup);
|
||||||
|
|
||||||
|
if (!isSupadmin && !isGroupApprover && isDivAdmin === 0) {
|
||||||
|
return NextResponse.json({ success: false, message: "Anda tidak memiliki izin untuk menyetujui atau menolak tugas" }, { status: 200 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const task = await prisma.divisionProjectTask.findUnique({
|
const task = await prisma.divisionProjectTask.findUnique({
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import "moment/locale/id";
|
|||||||
const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
||||||
.use(cors({
|
.use(cors({
|
||||||
origin: "*",
|
origin: "*",
|
||||||
methods: ["GET", "POST", "OPTIONS"],
|
methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
|
||||||
allowedHeaders: ["Content-Type", "Authorization"]
|
allowedHeaders: ["Content-Type", "Authorization"]
|
||||||
}))
|
}))
|
||||||
.use(swagger({
|
.use(swagger({
|
||||||
@@ -311,13 +311,13 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
try {
|
try {
|
||||||
const data = await prisma.village.findMany({
|
const data = await prisma.village.findMany({
|
||||||
where: {
|
where: {
|
||||||
isDummy: false,
|
|
||||||
...(search && { name: { contains: search, mode: 'insensitive' } })
|
...(search && { name: { contains: search, mode: 'insensitive' } })
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
name: true,
|
name: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
|
isDummy: true,
|
||||||
createdAt: true,
|
createdAt: true,
|
||||||
User: {
|
User: {
|
||||||
where: {
|
where: {
|
||||||
@@ -335,7 +335,6 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
|
|
||||||
const count = await prisma.village.count({
|
const count = await prisma.village.count({
|
||||||
where: {
|
where: {
|
||||||
isDummy: false,
|
|
||||||
...(search && { name: { contains: search, mode: 'insensitive' } })
|
...(search && { name: { contains: search, mode: 'insensitive' } })
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -344,6 +343,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
id: village.id,
|
id: village.id,
|
||||||
name: village.name,
|
name: village.name,
|
||||||
isActive: village.isActive,
|
isActive: village.isActive,
|
||||||
|
isDummy: village.isDummy,
|
||||||
createdAt: formatDateTime(village.createdAt),
|
createdAt: formatDateTime(village.createdAt),
|
||||||
perbekel: village.User[0]?.name || null,
|
perbekel: village.User[0]?.name || null,
|
||||||
}));
|
}));
|
||||||
@@ -501,6 +501,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
id: true,
|
id: true,
|
||||||
name: true,
|
name: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
|
isDummy: true,
|
||||||
createdAt: true,
|
createdAt: true,
|
||||||
updatedAt: true,
|
updatedAt: true,
|
||||||
desc: true,
|
desc: true,
|
||||||
@@ -529,6 +530,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name,
|
name: data?.name,
|
||||||
isActive: data?.isActive,
|
isActive: data?.isActive,
|
||||||
|
isDummy: data?.isDummy,
|
||||||
desc: data?.desc,
|
desc: data?.desc,
|
||||||
createdAt: data?.createdAt ? formatDateTime(data.createdAt) : null,
|
createdAt: data?.createdAt ? formatDateTime(data.createdAt) : null,
|
||||||
updatedAt: data?.updatedAt ? formatDateTime(data.updatedAt) : null,
|
updatedAt: data?.updatedAt ? formatDateTime(data.updatedAt) : null,
|
||||||
@@ -957,7 +959,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.post("/edit-villages", async ({ body, set }) => {
|
.post("/edit-villages", async ({ body, set }) => {
|
||||||
const { id, name, desc } = body;
|
const { id, name, desc, isDummy } = body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const village = await prisma.village.findUnique({
|
const village = await prisma.village.findUnique({
|
||||||
@@ -977,6 +979,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
data: {
|
data: {
|
||||||
name,
|
name,
|
||||||
desc,
|
desc,
|
||||||
|
isDummy,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -998,6 +1001,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
id: t.String({ description: "ID desa" }),
|
id: t.String({ description: "ID desa" }),
|
||||||
name: t.String({ description: "Nama desa" }),
|
name: t.String({ description: "Nama desa" }),
|
||||||
desc: t.String({ description: "Deskripsi desa" }),
|
desc: t.String({ description: "Deskripsi desa" }),
|
||||||
|
isDummy: t.Boolean({ description: "Apakah desa dummy" }),
|
||||||
}),
|
}),
|
||||||
detail: {
|
detail: {
|
||||||
summary: "Edit Villages",
|
summary: "Edit Villages",
|
||||||
@@ -1238,6 +1242,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
email: true,
|
email: true,
|
||||||
isWithoutOTP: true,
|
isWithoutOTP: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
|
isApprover: true,
|
||||||
idUserRole: true,
|
idUserRole: true,
|
||||||
idVillage: true,
|
idVillage: true,
|
||||||
idGroup: true,
|
idGroup: true,
|
||||||
@@ -1324,6 +1329,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
gender: item.gender,
|
gender: item.gender,
|
||||||
isWithoutOTP: item.isWithoutOTP,
|
isWithoutOTP: item.isWithoutOTP,
|
||||||
isActive: item.isActive,
|
isActive: item.isActive,
|
||||||
|
isApprover: item.isApprover,
|
||||||
role: item.UserRole?.name,
|
role: item.UserRole?.name,
|
||||||
village: item.Village?.name,
|
village: item.Village?.name,
|
||||||
group: item.Group?.name,
|
group: item.Group?.name,
|
||||||
@@ -1436,7 +1442,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.post("/edit-user", async ({ body, set }) => {
|
.post("/edit-user", async ({ body, set }) => {
|
||||||
const { id, name, nik, phone, email, gender, idUserRole, idVillage, idGroup, idPosition, isActive, isWithoutOTP } = body;
|
const { id, name, nik, phone, email, gender, idUserRole, idVillage, idGroup, idPosition, isActive, isWithoutOTP, isApprover } = body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const cekId = await prisma.user.findFirst({
|
const cekId = await prisma.user.findFirst({
|
||||||
@@ -1488,6 +1494,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
idPosition,
|
idPosition,
|
||||||
isActive,
|
isActive,
|
||||||
isWithoutOTP,
|
isWithoutOTP,
|
||||||
|
isApprover,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1518,6 +1525,7 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
idPosition: t.Optional(t.Union([t.String(), t.Null()], { description: "ID Posisi" })),
|
idPosition: t.Optional(t.Union([t.String(), t.Null()], { description: "ID Posisi" })),
|
||||||
isActive: t.Boolean({ description: "Aktif" }),
|
isActive: t.Boolean({ description: "Aktif" }),
|
||||||
isWithoutOTP: t.Boolean({ description: "Tanpa OTP" }),
|
isWithoutOTP: t.Boolean({ description: "Tanpa OTP" }),
|
||||||
|
isApprover: t.Boolean({ description: "Approver" }),
|
||||||
}),
|
}),
|
||||||
detail: {
|
detail: {
|
||||||
summary: "Edit User",
|
summary: "Edit User",
|
||||||
@@ -1527,11 +1535,79 @@ const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
;
|
|
||||||
|
|
||||||
;
|
// ─── API KEY MANAGEMENT ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.get("/api-keys", async ({ set }) => {
|
||||||
|
try {
|
||||||
|
const keys = await prisma.apiKey.findMany({ orderBy: { createdAt: "desc" } });
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil mendapatkan API keys",
|
||||||
|
data: keys.map((k) => ({ ...k, key: k.key.slice(0, 8) + "••••••••" + k.key.slice(-4) })),
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
set.status = 500;
|
||||||
|
return { success: false, message: "Gagal mendapatkan API keys" };
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
detail: { summary: "List API Keys", tags: ["api-key"] },
|
||||||
|
})
|
||||||
|
|
||||||
|
.post("/api-keys", async ({ body, set }) => {
|
||||||
|
try {
|
||||||
|
const rawKey = "ak_" + crypto.randomUUID().replace(/-/g, "");
|
||||||
|
const key = await prisma.apiKey.create({ data: { name: body.name, key: rawKey } });
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "API key berhasil dibuat",
|
||||||
|
data: { ...key, key: rawKey },
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
set.status = 500;
|
||||||
|
return { success: false, message: "Gagal membuat API key" };
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
body: t.Object({ name: t.String({ description: "Nama key" }) }),
|
||||||
|
detail: { summary: "Buat API Key", tags: ["api-key"] },
|
||||||
|
})
|
||||||
|
|
||||||
|
.patch("/api-keys/:id", async ({ params, body, set }) => {
|
||||||
|
try {
|
||||||
|
const key = await prisma.apiKey.update({
|
||||||
|
where: { id: params.id },
|
||||||
|
data: { isActive: body.isActive },
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "API key berhasil diupdate",
|
||||||
|
data: { ...key, key: key.key.slice(0, 8) + "••••••••" + key.key.slice(-4) },
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
set.status = 500;
|
||||||
|
return { success: false, message: "Gagal mengupdate API key" };
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
params: t.Object({ id: t.String() }),
|
||||||
|
body: t.Object({ isActive: t.Boolean({ description: "Status aktif" }) }),
|
||||||
|
detail: { summary: "Toggle API Key", tags: ["api-key"] },
|
||||||
|
})
|
||||||
|
|
||||||
|
.delete("/api-keys/:id", async ({ params, set }) => {
|
||||||
|
try {
|
||||||
|
await prisma.apiKey.delete({ where: { id: params.id } });
|
||||||
|
return { success: true, message: "API key berhasil dihapus" };
|
||||||
|
} catch (error) {
|
||||||
|
set.status = 500;
|
||||||
|
return { success: false, message: "Gagal menghapus API key" };
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
params: t.Object({ id: t.String() }),
|
||||||
|
detail: { summary: "Hapus API Key", tags: ["api-key"] },
|
||||||
|
});
|
||||||
|
|
||||||
export const GET = MonitoringServer.handle;
|
export const GET = MonitoringServer.handle;
|
||||||
export const POST = MonitoringServer.handle;
|
export const POST = MonitoringServer.handle;
|
||||||
|
export const PATCH = MonitoringServer.handle;
|
||||||
|
export const DELETE = MonitoringServer.handle;
|
||||||
export const OPTIONS = MonitoringServer.handle;
|
export const OPTIONS = MonitoringServer.handle;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { isValidApiKey } from "@/lib/apiKey";
|
||||||
import { prisma } from "@/module/_global";
|
import { prisma } from "@/module/_global";
|
||||||
import cors from "@elysiajs/cors";
|
import cors from "@elysiajs/cors";
|
||||||
import { swagger } from "@elysiajs/swagger";
|
import { swagger } from "@elysiajs/swagger";
|
||||||
@@ -11,20 +12,40 @@ const NocServer = new Elysia({ prefix: "/api/noc" })
|
|||||||
.use(cors({
|
.use(cors({
|
||||||
origin: "*",
|
origin: "*",
|
||||||
methods: ["GET", "POST", "OPTIONS"],
|
methods: ["GET", "POST", "OPTIONS"],
|
||||||
|
allowedHeaders: ["Content-Type", "x-api-key"],
|
||||||
}))
|
}))
|
||||||
.use(swagger({
|
.use(swagger({
|
||||||
path: "/docs", // Karena prefix instance adalah /api/noc, maka ini akan diakses di /api/noc/docs
|
path: "/docs",
|
||||||
documentation: {
|
documentation: {
|
||||||
info: {
|
info: {
|
||||||
title: "Sistem Desa Mandiri - NOC API",
|
title: "Sistem Desa Mandiri - NOC API",
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
description: "API Khusus untuk kebutuhan NOC (Network Operation Center) dan Monitoring Desa",
|
description: "API Khusus untuk kebutuhan NOC (Network Operation Center) dan Monitoring Desa",
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
securitySchemes: {
|
||||||
|
ApiKeyAuth: {
|
||||||
|
type: "apiKey",
|
||||||
|
in: "header",
|
||||||
|
name: "x-api-key",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
security: [{ ApiKeyAuth: [] }],
|
||||||
tags: [
|
tags: [
|
||||||
{ name: "NOC", description: "Endpoint khusus monitoring" }
|
{ name: "NOC", description: "Endpoint khusus monitoring" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.onBeforeHandle(async ({ request, set, path }) => {
|
||||||
|
if (path.startsWith("/api/noc/docs")) return;
|
||||||
|
|
||||||
|
const incoming = request.headers.get("x-api-key");
|
||||||
|
if (!incoming || !(await isValidApiKey(incoming))) {
|
||||||
|
set.status = 401;
|
||||||
|
return { success: false, message: "Unauthorized" };
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// ── GET /api/noc/active-divisions ──────────────────────────────────────────
|
// ── GET /api/noc/active-divisions ──────────────────────────────────────────
|
||||||
.get(
|
.get(
|
||||||
|
|||||||
15
src/lib/apiKey.ts
Normal file
15
src/lib/apiKey.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { prisma } from "@/module/_global";
|
||||||
|
|
||||||
|
const CACHE_TTL_MS = 60_000;
|
||||||
|
let apiKeyCache: Set<string> = new Set();
|
||||||
|
let cacheExpiresAt = 0;
|
||||||
|
|
||||||
|
export async function isValidApiKey(incoming: string): Promise<boolean> {
|
||||||
|
const now = Date.now();
|
||||||
|
if (now > cacheExpiresAt) {
|
||||||
|
const rows = await prisma.apiKey.findMany({ where: { isActive: true }, select: { key: true } });
|
||||||
|
apiKeyCache = new Set(rows.map((r) => r.key));
|
||||||
|
cacheExpiresAt = now + CACHE_TTL_MS;
|
||||||
|
}
|
||||||
|
return apiKeyCache.has(incoming);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user