Merge pull request 'amalia/21-jul-25' (#1) from amalia/21-jul-25 into join

Reviewed-on: bip/sistem-desa-mandiri#1
This commit is contained in:
2025-07-22 10:10:04 +08:00
434 changed files with 32414 additions and 19247 deletions

3
.env.test Normal file
View File

@@ -0,0 +1,3 @@
GOOGLE_PRIVATE_KEY_ID=764e1207d5acf4db2eac539256c8f1bf397c7d8f
GOOGLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCwCU9PBpAbXsOl\ntb1syvWrmH3FSDRyI4oOVWZJRqYX+j44UTNfzTjYySpNy7x1lr91uOC2GGHJeFvT\nLg5er6uvzFvzwg42A8Rz4+aqxlUhvhNXYRyfaaP7tbui5X9GEmhKYzvYd6T/6z1u\njo7LE1tBaiB8eB69tSJidGcr90yXOsbvKFgaPkpvlrseNR/t0PYDUaXHsxdKvCHI\ntK13KxhJCJrU9+/W1Wwr+45WGfK9m+jLVuOEZT9dd3FUgDn/0CFzykZLA0iHRLjx\neczahlrlvLVCtUIJjHbmsjG8vLZyl6/puh1l2OkEZyADb6m7OOxFVTo5ADZvj4nD\nVCCirdMVAgMBAAECggEAMF0mbnJBpltnSkA/vkOWsmHPcCOx0QgFloGM/CXOXTkR\n3hwlDrWN4DWIi14ltXLIwFmeVzkkqJsKM19scEQ4WbC+NJ7Ek79+Ok7LYXDjE8Wq\nf6+9EukNtgqMdikySfilsYZI+2SHrw4czyKYhZ+YS0USjs/btkgtHbqYW+JyJvv4\nlXAGp3129kbOHTc6+DBq6tn4XiRMKUdBNtcRHe9k+zAIuwbeAdsl4bock1ADnMIv\n/Q4FfOua+nJl8MUpPCZDvz14az+3j/rUVkR/wgDqQirFNRfFfpEPNM2oXVSjp0oK\nTC8NEy5mN4aj0DYS8U2x8barsAFDr5N4L9JxTtdlgwKBgQDkXK9iieIe1/yJFDw6\ntHbQu/bl+t82DESapss62++6ckh2mo+IScvVg/rCwXIag7IRQO40BHWwYTrOwTbj\nD1VUamn6UaqJHpIjDj/SK+As3DumuOTcb+kbJq9TpjLGeR2hj0aKcFXAjL5+B+yr\nBt7fVsB2uhouS9aD68HV8azsxwKBgQDFV2yRKgSf11vNRsxtJekpZ7ruF4h8OZPA\nHcq1kMDPRJcuVD9XwG7RAEgxcErKKS6NrrT/2Iaq5r+P3owgxZ6yB5pabGGvsgcg\nqrvsVEjzETsrrDbp5IevwE/MTwplakr6vJBnfAyjqMbDQSGSZPp+6S8M5JtZhJDL\n9Pqy6yxNQwKBgEE9ZXGuWKZdKC11VXukAOnDOVcco9ZKDPNtwVPQb52BdshDgcv6\n4Tvfl606HMIMa7vYI/VCbOj17hoRQv/9anBScnJsEF9aF3/iW0NM+591T6li2ydK\n5Xq3Q5GPQqRHB7sXNpzoWOdIjkdtNiTqMpP1sch5hG9DhUZs/RSFFdUTAoGBALyV\nyD2NXu/1WVh5cQBZe1FDPMMtIBQ+3bB5h+8tDuTEEomGnyXX0s7OKy97tS0uX7us\nGnJo1IDblHMDZPwofnh5hYsmCdBiHCeeoYm+HhyS+e3JXIz2BKjy6g8/9ZpnEpI8\nwu7yAA4iSxfq1Q9Win/fjUQP71mDsvAGA9IZpbOLAoGBAK57RjNemVh3oNB5ZaQs\n45WzfmPPjKoDQdMYLtohHz9HhPxYFLuvlDc/9OcWFCz3tZHtyDrUtXvv+vX+rG4Y\nemxXkqdg3lYo7nayw772myJb2w6QIfGyuSRx/C1/phmPhp+UkHk7B+KdvWhpPmCC\nBufws2LSn5VZzivO6LrwSCfR\n-----END PRIVATE KEY-----\n"
GOOGLE_CLIENT_EMAIL=firebase-adminsdk-fbsvc@mobile-darmasaba.iam.gserviceaccount.com

9
.gitignore vendored
View File

@@ -40,4 +40,11 @@ next-env.d.ts
# folder foto kandidat
/public/image/
/public/file/
/public/file/
certificates
test.png
test2.png
xxx.ts
key.json

View File

@@ -1,36 +1,83 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
# Sistem Desa Mandiri
## Getting Started
Sistem Desa Mandiri adalah aplikasi web yang dirancang untuk membantu pengelolaan administrasi dan informasi di tingkat desa. Dibangun dengan Next.js, aplikasi ini menyediakan berbagai fitur untuk mendukung kegiatan desa, mulai dari pengumuman, diskusi, manajemen proyek, hingga administrasi kependudukan.
First, run the development server:
## Fitur Utama
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
* **Manajemen Pengguna:** Mengelola data anggota dan hak akses.
* **Pengumuman:** Menyebarkan informasi penting kepada seluruh warga desa.
* **Diskusi:** Forum untuk berdiskusi antar warga atau perangkat desa.
* **Manajemen Proyek & Tugas:** Melacak kemajuan proyek dan tugas yang sedang berjalan di desa.
* **Dokumentasi:** Tempat terpusat untuk menyimpan dan mengelola dokumen-dokumen penting.
* **Notifikasi Push:** Mengirimkan notifikasi real-time ke perangkat pengguna.
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
## Teknologi yang Digunakan
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
* **Framework:** [Next.js](https://nextjs.org/)
* **UI Framework:** [Mantine](https://mantine.dev/)
* **Database ORM:** [Prisma](https://www.prisma.io/)
* **Styling:** [Tailwind CSS](https://tailwindcss.com/)
* **State Management:** [Hookstate](https://hookstate.js.org/)
* **Push Notifications:** [Web Push](https://www.npmjs.com/package/web-push)
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Memulai
## Learn More
### Persyaratan
To learn more about Next.js, take a look at the following resources:
* [Node.js](https://nodejs.org/) (versi 20.x atau lebih tinggi)
* [Bun](https://bun.sh/) (direkomendasikan) atau package manager lain seperti npm/yarn/pnpm.
* Database (misalnya PostgreSQL, MySQL, atau SQLite).
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
### Instalasi
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
1. **Clone repositori ini:**
```bash
git clone https://github.com/username/sistem-desa-mandiri.git
cd sistem-desa-mandiri
```
## Deploy on Vercel
2. **Install dependensi:**
```bash
bun install
```
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
3. **Setup Variabel Lingkungan:**
Salin file `.env.test` menjadi `.env` dan sesuaikan nilainya, terutama untuk koneksi database.
```bash
cp .env.test .env
```
Buka file `.env` dan isi variabel yang diperlukan, seperti `DATABASE_URL`.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
4. **Migrasi Database:**
Jalankan migrasi Prisma untuk membuat skema database.
```bash
npx prisma migrate dev
```
5. **Seed Database (Opsional):**
Jika Anda ingin mengisi database dengan data awal, jalankan perintah seed.
```bash
npx prisma db seed
```
6. **Jalankan Server Development:**
```bash
bun run dev
```
Aplikasi akan berjalan di [https://localhost:3000](https://localhost:3000).
## Skrip yang Tersedia
* `dev`: Menjalankan server development dengan HTTPS.
* `build`: Membuat build produksi dari aplikasi.
* `start`: Menjalankan server produksi.
* `lint`: Menjalankan linter untuk memeriksa kualitas kode.
* `prisma:seed`: Menjalankan skrip seed database.
## Kontribusi
Kontribusi dalam bentuk apapun sangat kami hargai. Jika Anda menemukan bug atau memiliki ide untuk fitur baru, silakan buat *issue* baru. Jika Anda ingin berkontribusi dalam kode, silakan buat *pull request*.
## Lisensi
Proyek ini dilisensikan di bawah [Lisensi ISC](LICENSE).

BIN
bun.lockb Executable file

Binary file not shown.

7204
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --experimental-https",
"build": "next build",
"start": "next start",
"lint": "next lint"
@@ -12,6 +12,8 @@
"seed": "npx tsx prisma/seed.ts"
},
"dependencies": {
"@elysiajs/cors": "^1.3.1",
"@elysiajs/swagger": "^1.3.0",
"@hookstate/core": "^4.0.1",
"@hookstate/localstored": "^4.0.2",
"@mantine/carousel": "^7.11.1",
@@ -29,18 +31,38 @@
"@mantine/tiptap": "^7.11.0",
"@prisma/client": "5.16.1",
"@tabler/icons-react": "^3.7.0",
"@tiptap/extension-color": "^2.11.7",
"@tiptap/extension-highlight": "^2.11.7",
"@tiptap/extension-link": "^2.4.0",
"@tiptap/extension-text-align": "^2.11.7",
"@tiptap/extension-underline": "^2.11.7",
"@tiptap/pm": "^2.11.7",
"@tiptap/react": "^2.4.0",
"@tiptap/starter-kit": "^2.4.0",
"@types/bun": "^1.2.17",
"@types/busboy": "^1.5.4",
"@types/crypto-js": "^4.2.2",
"@types/lodash": "^4.17.6",
"@types/minimist": "^1.2.5",
"@types/multer": "^1.4.12",
"@types/web-push": "^3.6.3",
"busboy": "^1.6.0",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.11",
"echarts": "^5.5.1",
"echarts-for-react": "^3.0.2",
"elysia": "^1.3.1",
"embla-carousel-autoplay": "^7.1.0",
"embla-carousel-react": "^7.1.0",
"firebase-admin": "^11.10.1",
"from": "^0.1.7",
"import": "^0.0.6",
"iron-session": "^8.0.2",
"jose": "^5.9.2",
"lodash": "^4.17.21",
"minimist": "^1.2.8",
"moment": "^2.30.1",
"multer": "^1.4.5-lts.2",
"next": "14.2.4",
"pdfjs-dist": "^4.6.82",
"prettier": "^3.3.2",
@@ -48,10 +70,17 @@
"react-dom": "^18",
"react-hot-toast": "^2.4.1",
"react-icons": "^5.2.1",
"react-simple-toasts": "^5.10.0",
"react-zoom-pan-pinch": "^3.7.0",
"readdirp": "^3.6.0",
"recharts": "2",
"rrule": "^2.8.1",
"sharp": "^0.33.5",
"supabase": "^1.192.5",
"tsx": "^4.20.3",
"web-push": "^3.6.7",
"wibu-cli": "^1.0.91",
"wibu-pkg": "^1.0.63",
"wibu-realtime": "bipproduction/wibu-realtime",
"yargs": "^17.7.2"
},
"devDependencies": {
@@ -66,7 +95,7 @@
"prisma": "^5.16.1",
"tailwindcss": "^3.4.1",
"ts-node": "^10.9.2",
"typescript": "^5.5.3"
"typescript": "^5.6.2"
},
"description": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).",
"main": "index.js",

View File

@@ -59,6 +59,8 @@ model Village {
Project Project[]
Division Division[]
ColorTheme ColorTheme[]
BannerImage BannerImage[]
Discussion Discussion[]
}
model Group {
@@ -74,6 +76,7 @@ model Group {
Project Project[]
Division Division[]
AnnouncementMember AnnouncementMember[]
Discussion Discussion[]
}
model Position {
@@ -95,8 +98,8 @@ model User {
idVillage String
Group Group @relation(fields: [idGroup], references: [id])
idGroup String
Position Position @relation(fields: [idPosition], references: [id])
idPosition String
Position Position? @relation(fields: [idPosition], references: [id])
idPosition String?
nik String @unique
name String
phone String @unique
@@ -121,6 +124,23 @@ model User {
DivisionDocumentFolderFile DivisionDocumentFolderFile[]
DivisionCalendar DivisionCalendar[]
DivisionCalendarMember DivisionCalendarMember[]
Notifications Notifications[] @relation("UserToUser")
Notifications2 Notifications[] @relation("UserFromUser")
Subscribe Subscribe?
Discussion Discussion[]
DiscussionMember DiscussionMember[]
DiscussionComment DiscussionComment[]
TokenDeviceUser TokenDeviceUser[]
}
model TokenDeviceUser {
id String @id @default(cuid())
User User @relation(fields: [idUser], references: [id])
idUser String
token String @db.Text
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model UserLog {
@@ -209,17 +229,18 @@ model ProjectFile {
}
model ProjectTask {
id String @id @default(cuid())
Project Project @relation(fields: [idProject], references: [id])
idProject String
title String
desc String?
status Int @default(0) // 0 = todo, 1 = done
dateStart DateTime @db.Date
dateEnd DateTime @db.Date
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id String @id @default(cuid())
Project Project @relation(fields: [idProject], references: [id])
idProject String
title String
desc String?
status Int @default(0) // 0 = todo, 1 = done
notifikasi Boolean @default(false)
dateStart DateTime @db.Date
dateEnd DateTime @db.Date
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ProjectComment {
@@ -299,6 +320,7 @@ model DivisionProjectTask {
title String
desc String? @db.Text
status Int @default(0) // 0 = todo, 1 = done
notifikasi Boolean @default(false)
dateStart DateTime @db.Date
dateEnd DateTime @db.Date
isActive Boolean @default(true)
@@ -478,3 +500,81 @@ model ColorTheme {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model BannerImage {
id String @id @default(cuid())
Village Village? @relation(fields: [idVillage], references: [id])
idVillage String?
title String
extension String
image String
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Notifications {
id String @id @default(cuid())
User1 User @relation("UserToUser", fields: [idUserTo], references: [id], map: "UserToUserMap")
idUserTo String
User2 User @relation("UserFromUser", fields: [idUserFrom], references: [id], map: "UserFromUserMap")
idUserFrom String
category String
idContent String
title String
desc String
isRead Boolean @default(false)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Subscribe {
id String @id @default(cuid())
User User @relation(fields: [idUser], references: [id])
idUser String @unique
subscription String @db.Text
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt
}
model Discussion {
id String @id @default(cuid())
Village Village @relation(fields: [idVillage], references: [id])
idVillage String
Group Group @relation(fields: [idGroup], references: [id])
idGroup String
title String?
desc String @db.Text
status Int @default(1) // 1 = open, 2 = close
isActive Boolean @default(true)
User User @relation(fields: [createdBy], references: [id])
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
DiscussionMember DiscussionMember[]
DiscussionComment DiscussionComment[]
}
model DiscussionMember {
id String @id @default(cuid())
Discussion Discussion @relation(fields: [idDiscussion], references: [id])
idDiscussion String
User User @relation(fields: [idUser], references: [id])
idUser String
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model DiscussionComment {
id String @id @default(cuid())
Discussion Discussion @relation(fields: [idDiscussion], references: [id])
idDiscussion String
User User @relation(fields: [idUser], references: [id])
idUser String
comment String @db.Text
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
public/icon-192x192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
public/icon-192x192.webp Normal file

Binary file not shown.

BIN
public/icon-512x512.webp Normal file

Binary file not shown.

BIN
public/icon2-192x192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

121
public/wibu-push-worker.js Normal file
View File

@@ -0,0 +1,121 @@
const log = false; // Ganti ke true untuk debugging
function printLog(text) {
if (log) {
const stack = new Error().stack;
const lineInfo = stack.split('\n')[2];
const match = lineInfo.match(/(\/.*:\d+:\d+)/);
const lineNumber = match ? match[1] : 'unknown line';
console.log(`[${lineNumber}] ==>`, text);
}
}
self.addEventListener('install', (event) => {
event.waitUntil(self.skipWaiting());
printLog('Service Worker installing...');
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
printLog('Service Worker activating...');
});
self.addEventListener('push', async function (event) {
let title = "Default Title";
let options = {
body: "Default notification body",
icon: '/icon-192x192.png',
badge: '/icon-192x192.png',
image: '/icon-192x192.png',
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: '2',
},
};
if (event.data) {
try {
const data = event.data.json();
title = data.title || title;
options.body = data.body || options.body;
options.data = {
...options.data,
...data,
};
printLog(`Push event data: ${JSON.stringify(options, null, 2)}`);
} catch (e) {
console.error("Error parsing push event data:", e);
}
} else {
console.warn("Push event has no data.");
}
event.waitUntil(
(async () => {
try {
const eventData = (options.data);
const clientList = await clients.matchAll({ type: 'window', includeUncontrolled: true });
let isClientFocused = false;
for (const client of clientList) {
client.postMessage({
type: 'PUSH_RECEIVED',
title: eventData.title,
body: eventData.body,
variant: eventData.variant,
createdAt: eventData.createdAt,
acceptedAt: Date.now(),
});
if (client.focused) {
isClientFocused = true;
break;
}
}
const subscription = await self.registration.pushManager.getSubscription();
const myEndpoint = subscription ? subscription.endpoint : null;
if (myEndpoint && eventData.endpoint === myEndpoint) {
printLog("Notification sent to self, skipping display.");
return;
}
if (eventData.variant === 'data') {
printLog('Type is data, skipping display.');
return;
}
if (!isClientFocused) {
await self.registration.showNotification(title, options);
} else {
printLog('Client is focused, notification not shown.');
}
} catch (err) {
console.error("Error displaying notification:", err);
}
})()
);
});
self.addEventListener('notificationclick', function (event) {
const clickedLink = event.notification.data.link;
event.notification.close();
event.waitUntil(
clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
for (const client of clientList) {
if (client.url.includes(clickedLink) && 'focus' in client) {
return client.focus();
}
}
if (clients.openWindow) {
return clients.openWindow(clickedLink);
}
}).catch(err => {
console.error("Error handling notification click:", err);
})
);
});
// wibu:1.0.87

214
sendMultiple.ts Normal file
View File

@@ -0,0 +1,214 @@
import "dotenv/config";
import { initializeApp, cert, App, ServiceAccount } from "firebase-admin/app";
import { getMessaging, Message } from "firebase-admin/messaging";
import path from "path";
// --- KONFIGURASI ---
const CONFIG = {
/**
* Konten notifikasi default yang akan dikirim.
*/
notificationPayload: {
title: "Sistem Desa Mandiri",
body: "Ada informasi baru untuk Anda, silakan periksa aplikasi.",
},
/**
* Pengaturan untuk mekanisme coba lagi (retry) jika terjadi kegagalan jaringan.
*/
retry: {
maxRetries: 3, // Jumlah maksimal percobaan ulang
delay: 2000, // Waktu tunda antar percobaan dalam milidetik (ms)
},
};
// --- AKHIR KONFIGURASI ---
/**
* Membangun objek service account dari variabel lingkungan.
*/
function getServiceAccount(): ServiceAccount {
const privateKey = process.env.GOOGLE_PRIVATE_KEY?.replace(/\n/g, '\n');
if (!process.env.GOOGLE_PROJECT_ID || !process.env.GOOGLE_CLIENT_EMAIL || !privateKey) {
console.error("KRITIS: Variabel lingkungan Firebase (PROJECT_ID, CLIENT_EMAIL, PRIVATE_KEY) tidak lengkap.");
process.exit(1);
}
return {
projectId: process.env.GOOGLE_PROJECT_ID,
clientEmail: process.env.GOOGLE_CLIENT_EMAIL,
privateKey,
};
}
/**
* Inisialisasi Firebase Admin SDK.
* Hanya akan menginisialisasi satu kali.
*/
let firebaseApp: App | null = null;
function initializeFirebase(): App {
if (firebaseApp) {
return firebaseApp;
}
try {
const serviceAccount = getServiceAccount();
firebaseApp = initializeApp({
credential: cert(serviceAccount),
});
console.log("Firebase Admin SDK berhasil diinisialisasi.");
return firebaseApp;
} catch (error: any) {
console.error("KRITIS: Gagal inisialisasi Firebase. Pastikan variabel lingkungan sudah benar.");
console.error(`Detail Error: ${error.message}`);
process.exit(1); // Keluar dari proses jika Firebase gagal diinisialisasi
}
}
/**
* Mengambil daftar token perangkat dari database.
* TODO: Ganti fungsi ini dengan logika untuk mengambil token dari database Anda.
* @returns {Promise<string[]>} Daftar token FCM.
*/
async function getDeviceTokens(): Promise<string[]> {
console.log("Mengambil token perangkat dari sumber data...");
// CONTOH: Ini adalah data dummy. Seharusnya Anda mengambilnya dari database.
// Misalnya: const users = await prisma.user.findMany({ where: { fcmToken: { not: null } } });
// return users.map(user => user.fcmToken);
const exampleTokens: string[] = [
"c89yuexsS_uc1tOErVPu5a:APA91bEb6tEKXAfReZjFVJ2mMyOzoW_RXryLSnSJTpbIVV3G0L_DCNkLuRvJ02Ip-Erz88QCQBAt-C2SN8eCRxu3-v1sBzXzKPtDv-huXpkjXsyrkifqvUo", // Valid
"cRz96GHKTRaQaRJ35e8Hxa:APA91bEUSxE0VPbqKSzseQ_zGhbYsDofMexKykRw7o_3z2aPM9YFmZbeA2enrmb3qjdZ2g4-QQtiNHAyaZqAT1ITOrwo9jVJlShTeABmEFYP5GLEUZ3dlLc", // Valid
"token_tidak_valid_ini_pasti_gagal_12345", // Contoh token tidak valid
];
console.log(`Berhasil mendapatkan ${exampleTokens.length} token.`);
return exampleTokens;
}
/**
* Membuat array pesan yang akan dikirim ke setiap token.
* @param {string[]} tokens - Daftar token FCM.
* @returns {Message[]} Array objek pesan untuk `sendEach`.
*/
function constructMessages(tokens: string[]): Message[] {
return tokens.map((token) => ({
token,
notification: {
title: CONFIG.notificationPayload.title,
body: CONFIG.notificationPayload.body,
},
data: {
// Anda bisa menambahkan data tambahan di sini
// Contoh: click_action: "FLUTTER_NOTIFICATION_CLICK"
timestamp: String(Date.now()),
},
android: {
priority: "high",
notification: {
sound: "default",
channelId: "default_channel", // Pastikan channel ini ada di aplikasi Android Anda
},
},
apns: {
payload: {
aps: {
sound: "default",
},
},
},
}));
}
/**
* Menangani respons dari `sendEach` untuk mencatat keberhasilan dan kegagalan.
* @param response - Objek respons dari `sendEach`.
* @param originalTokens - Daftar token asli yang dikirimi pesan.
*/
function handleSendResponse(response: any, originalTokens: string[]) {
console.log("Total notifikasi berhasil dikirim:", response.successCount);
console.log("Total notifikasi gagal:", response.failureCount);
const tokensToRemove: string[] = [];
response.responses.forEach((resp: any, index: number) => {
const token = originalTokens[index];
if (resp.success) {
// console.log(`Pesan ke token ...${token.slice(-6)} berhasil:`, resp.messageId);
} else {
console.error(`Pesan ke token ...${token.slice(-6)} GAGAL:`, resp.error.code);
// Jika token tidak lagi terdaftar, tandai untuk dihapus
if (
resp.error.code === "messaging/registration-token-not-registered" ||
resp.error.code === "messaging/invalid-registration-token"
) {
tokensToRemove.push(token);
}
}
});
if (tokensToRemove.length > 0) {
console.warn("Token berikut tidak valid dan harus dihapus dari database:");
tokensToRemove.forEach(token => console.log(`- ${token}`));
// TODO: Implementasikan logika untuk menghapus token-token di atas dari database Anda.
// Misalnya: await prisma.user.updateMany({ where: { fcmToken: { in: tokensToRemove } }, data: { fcmToken: null } });
}
}
/**
* Fungsi utama untuk mengirim notifikasi ke banyak perangkat dengan mekanisme retry.
* @param {Message[]} messages - Array pesan yang akan dikirim.
* @param {string[]} tokens - Daftar token asli untuk logging.
*/
async function sendNotifications(messages: Message[], tokens: string[]) {
let lastError: any;
for (let attempt = 1; attempt <= CONFIG.retry.maxRetries; attempt++) {
try {
const response = await getMessaging().sendEach(messages);
handleSendResponse(response, tokens);
return; // Berhasil, keluar dari fungsi
} catch (error: any) {
lastError = error;
console.error(`Percobaan pengiriman ke-${attempt} gagal:`, error.message);
// Hanya coba lagi jika error berhubungan dengan jaringan
const isNetworkError = error.code === "app/network-error" || error.code?.includes("network");
if (isNetworkError && attempt < CONFIG.retry.maxRetries) {
console.log(`Menunggu ${CONFIG.retry.delay}ms sebelum mencoba lagi...`);
await new Promise((resolve) => setTimeout(resolve, CONFIG.retry.delay));
} else {
// Jika bukan error jaringan atau sudah mencapai batas retry, lempar error
throw new Error(`Gagal mengirim notifikasi setelah ${attempt} percobaan: ${error.message}`);
}
}
}
throw lastError;
}
/**
* Fungsi orchestrator untuk menjalankan seluruh proses.
*/
export async function sendMultiple() {
try {
initializeFirebase();
const tokens = await getDeviceTokens();
if (tokens.length === 0) {
console.log("Tidak ada token perangkat yang ditemukan. Proses dihentikan.");
return;
}
const messages = constructMessages(tokens);
console.log(`
Mempersiapkan pengiriman ${messages.length} notifikasi...`);
await sendNotifications(messages, tokens);
console.log("Proses pengiriman notifikasi selesai.");
} catch (error: any) {
console.error("Terjadi error fatal dalam proses pengiriman:", error.message);
process.exit(1);
}
}
sendMultiple();

View File

@@ -0,0 +1,7 @@
import { CreateBanner } from "@/module/banner";
export default function Page() {
return (
<CreateBanner/>
);
}

View File

@@ -0,0 +1,7 @@
import { EditBanner } from "@/module/banner";
export default function Page() {
return (
<EditBanner />
);
}

View File

@@ -0,0 +1,11 @@
import { ListBanner, NavbarBanner } from "@/module/banner";
import { Box } from "@mantine/core";
export default function Page() {
return (
<Box>
<NavbarBanner />
<ListBanner />
</Box>
);
}

View File

@@ -0,0 +1,10 @@
import { ViewfileBanner } from '@/module/banner';
import React from 'react';
function Page() {
return (
<ViewfileBanner/>
);
}
export default Page;

View File

@@ -0,0 +1,9 @@
import { AddMemberDiscussionGeneral } from "@/module/discussion_general";
export default function Page() {
return (
<>
<AddMemberDiscussionGeneral />
</>
)
}

View File

@@ -0,0 +1,14 @@
import { LayoutNavbarNew } from "@/module/_global";
import { FormEditDiscussionGeneral } from "@/module/discussion_general";
import { Box } from "@mantine/core";
export default function Page() {
return (
<>
<Box>
<LayoutNavbarNew back="" title="Edit Diskusi Umum" menu={<></>} />
<FormEditDiscussionGeneral />
</Box>
</>
)
}

View File

@@ -0,0 +1,9 @@
import { MemberDiscussionGeneral } from "@/module/discussion_general";
export default function Page() {
return (
<>
<MemberDiscussionGeneral />
</>
)
}

View File

@@ -0,0 +1,9 @@
import { DetailDiscussionGeneral } from "@/module/discussion_general";
export default function Page() {
return (
<>
<DetailDiscussionGeneral />
</>
)
}

View File

@@ -0,0 +1,9 @@
import { FormCreateDiscussionGeneral } from "@/module/discussion_general";
export default function Page() {
return (
<>
<FormCreateDiscussionGeneral />
</>
)
}

View File

@@ -0,0 +1,16 @@
import { ViewFilter } from '@/module/_global';
import { NavbarDiscussionGeneral, TabListDiscussionGeneral } from '@/module/discussion_general';
function Page({ searchParams }: { searchParams: { page: string } }) {
if (searchParams.page == "filter")
return <ViewFilter linkFilter='discussion' />
return (
<div>
<NavbarDiscussionGeneral />
<TabListDiscussionGeneral />
</div>
);
}
export default Page;

View File

@@ -1,10 +1,9 @@
import { DetailEventDivision } from '@/module/calender';
import React from 'react';
function Page() {
return (
<>
<DetailEventDivision />
<DetailEventDivision />
</>
);
}

View File

@@ -1,11 +1,10 @@
import { ListDiscussion, NavbarListDiscussion } from '@/module/discussion';
import React from 'react';
import { NavbarListDiscussion, TabListDiscussion } from '@/module/discussion';
function Page({ params }: { params: { id: string } }) {
return (
<div>
<NavbarListDiscussion />
<ListDiscussion id={params.id} />
<TabListDiscussion />
</div>
);
}

View File

@@ -1,10 +1,6 @@
import { CreateTask, FileSave } from "@/module/task";
import { CreateTask } from "@/module/task";
function Page({ searchParams }: { searchParams: any }) {
// if (searchParams.page == "file-save")
// return <FileSave kategori="task" />
return <CreateTask />
}

View File

@@ -1,14 +1,18 @@
import { ViewFilter } from '@/module/_global';
import { CreateReport, ListDivision } from '@/module/division_new';
import React from 'react';
import { CreateReport, NavbarListDivision, TabListDivision } from '@/module/division_new';
import { Box } from '@mantine/core';
function Page({ searchParams }: { searchParams: { page: string } }) {
if (searchParams.page == "filter")
return <ViewFilter linkFilter='division'/>
return <ViewFilter linkFilter='division' />
if (searchParams.page == "report")
return <CreateReport />
return (
<ListDivision/>
<Box>
<NavbarListDivision />
<TabListDivision />
</Box>
);
}

View File

@@ -1,7 +1,9 @@
import { PushProvider } from "@/lib/PushProvider"
import { WrapLayout } from "@/module/_global"
import { funDetectCookies, funGetUserByCookies } from "@/module/auth"
import _ from "lodash"
import { redirect } from "next/navigation"
import '@mantine/tiptap/styles.css';
export default async function Layout({ children }: { children: React.ReactNode }) {
const cookies = await funDetectCookies()
@@ -10,7 +12,8 @@ export default async function Layout({ children }: { children: React.ReactNode }
const user = await funGetUserByCookies()
return (
<>
<WrapLayout role={user.idUserRole}>
{/* <PushProvider user={String(user.id)} /> */}
<WrapLayout role={user.idUserRole} theme={user.theme} user={user.id} village={user.idVillage}>
{children}
</WrapLayout>
</>

View File

@@ -0,0 +1,11 @@
import { WrapLayoutProject } from "@/module/project";
export default async function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<WrapLayoutProject>
{children}
</WrapLayoutProject>
</>
);
}

View File

@@ -1,4 +1,4 @@
import { ListAnggotaDetailProject, ListFileDetailProject, ListTugasDetailProject, NavbarDetailProject, ProgressDetailProject, ViewDetailProject } from '@/module/project';
import { ListAnggotaDetailProject, ListFileDetailProject, ListTugasDetailProject, NavbarDetailProject, ProgressDetailProject } from '@/module/project';
import { Box } from '@mantine/core';
import React from 'react';

View File

@@ -1,11 +1,7 @@
import { CreateProject, ViewFileSave } from "@/module/project";
import { CreateProject } from "@/module/project";
import React from "react";
function Page({ searchParams }: { searchParams: any }) {
// if (searchParams.page == "file-save")
// return <ViewFileSave kategori="project" />
return <CreateProject />;
}

View File

@@ -1,10 +1,14 @@
import { ViewFilter } from '@/module/_global';
import { TabProject, ViewProject } from '@/module/project';
import { ViewFilter, ViewFilterData } from '@/module/_global';
import { TabProject } from '@/module/project';
import React from 'react';
function Page({ searchParams }: { searchParams: { page: string } }) {
if (searchParams.page == 'filter')
return <ViewFilter linkFilter='project' />
if (searchParams.page == 'filter-data')
return <ViewFilterData linkFilter='project' />
return (
<TabProject />
);

View File

@@ -1,5 +1,4 @@
import { EditDetailTaskProject } from "@/module/project";
import React from "react";
function Page() {

View File

@@ -0,0 +1,17 @@
import { NotificationManager } from "@/module/_global/components/notification_manager";
const publicKey = process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!;
// console.log(
// process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY,
// process.env.VAPID_PRIVATE_KEY
// );
export default function Page() {
return (
<div>
{/* <PushNotificationManager publicKey={publicKey} /> */}
<NotificationManager publicKey={publicKey} />
</div>
);
}

View File

View File

@@ -5,7 +5,6 @@ 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 {
@@ -72,7 +71,9 @@ export async function GET(request: Request, context: { params: { id: string } })
division: v.Division.name
}))
const fixMember = Object.groupBy(formatMember, ({ group }) => group);
// const fixMember = Object.groupBy(formatMember, ({ group }) => group);
const fixMember = _.groupBy(formatMember, ({ group }) => group);
return NextResponse.json(
{
@@ -88,7 +89,7 @@ export async function GET(request: Request, context: { params: { id: string } })
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -140,7 +141,7 @@ export async function DELETE(request: Request, context: { params: { id: string }
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -217,7 +218,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeupdate pengumuman, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengeupdate pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,11 +1,10 @@
import { prisma } from "@/module/_global";
import { funSendWebPush, prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
import { createLogUser } from '@/module/user';
export const dynamic = 'force-dynamic'
@@ -23,6 +22,8 @@ export async function GET(request: Request) {
const groupId = user.idGroup
const { searchParams } = new URL(request.url);
const name = searchParams.get('search');
const page = searchParams.get('page');
const dataSkip = Number(page) * 10 - 10;
let kondisi: any = {
idVillage: String(villageId),
@@ -33,7 +34,7 @@ export async function GET(request: Request) {
}
}
if (roleUser != "supadmin") {
if (roleUser != "supadmin" && roleUser != "developer") {
if (roleUser == "cosupadmin" || roleUser == "admin") {
kondisi = {
idVillage: String(villageId),
@@ -75,6 +76,8 @@ export async function GET(request: Request) {
const announcements = await prisma.announcement.findMany({
skip: dataSkip,
take: 10,
where: kondisi,
select: {
id: true,
@@ -89,13 +92,13 @@ export async function GET(request: Request) {
const allData = announcements.map((v: any) => ({
..._.omit(v, ["createdAt"]),
createdAt: moment(v.createdAt).format("LL")
createdAt: moment(v.createdAt).format("ll")
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan pengumuman", data: allData, }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -112,6 +115,7 @@ export async function POST(request: Request) {
const { title, desc, groups } = (await request.json());
const villaId = user.idVillage
const userId = user.id
const userRoleLogin = user.idUserRole
const data = await prisma.announcement.create({
data: {
@@ -128,6 +132,7 @@ export async function POST(request: Request) {
let memberDivision = []
for (var i = 0, l = groups.length; i < l; i++) {
2
var obj = groups[i].Division;
for (let index = 0; index < obj.length; index++) {
const element = obj[index];
@@ -144,13 +149,98 @@ export async function POST(request: Request) {
data: memberDivision,
});
const memberNotif = await prisma.divisionMember.findMany({
where: {
Division: {
AnnouncementMember: {
some: {
idAnnouncement: data.id
}
}
}
},
select: {
idUser: true,
User: {
select: {
Subscribe: {
select: {
subscription: true
}
}
}
}
}
})
// mengirim notifikasi
// datanotif untuk realtime notifikasi
// datapush untuk web push notifikasi ketika aplikasi tidak aktif
const dataNotif = memberNotif.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe"]),
idUserTo: v.idUser,
idUserFrom: userId,
category: 'announcement',
idContent: data.id,
title: 'Pengumuman Baru',
desc: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.'
}))
const dataPush = memberNotif.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe"]),
idUser: v.idUser,
subscription: v.User.Subscribe?.subscription,
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: user.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
}
}
})
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'announcement',
idContent: data.id,
title: 'Pengumuman Baru',
desc: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: perbekel?.id,
subscription: perbekel?.Subscribe?.subscription
})
}
const pushNotif = dataPush.filter((item) => item.subscription != undefined)
const sendWebPush = await funSendWebPush({ sub: pushNotif, message: { title: 'Pengumuman Baru', body: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.' } })
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User membuat data pengumuman baru', table: 'announcement', data: data.id })
return NextResponse.json({ success: true, message: "Berhasil membuat pengumuman" }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil membuat pengumuman", notif: dataNotif }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal membuat pengumuman, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal membuat pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -23,9 +23,9 @@ export async function POST(req: NextRequest) {
phone: user.phone,
id: user.id,
});
} catch (error) {
console.error(error);
return Response.json({ message: "Internal Server Error", success: false });
return Response.json({ message: "Internal Server Error (error: 500)", success: false });
}
}

View File

@@ -0,0 +1,113 @@
import { DIR, funDeleteFile, funUploadFile, prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import { NextResponse } from "next/server";
// GET ONE BANNER
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
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 });
}
}
// DELETE BANNER
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const upd = await prisma.bannerImage.update({
where: {
id: String(id)
},
data: {
isActive: false
}
})
// create log user
const log = await createLogUser({ act: 'DELETE', desc: 'User menghapus banner', table: 'bannerImage', data: id })
return NextResponse.json({ success: true, message: "Berhasil menghapus banner" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menghapus banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// UPDATE BANNER
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const body = await request.formData()
const file = body.get("file") as File
const data = body.get("data")
const { title } = JSON.parse(data as string)
const upd = await prisma.bannerImage.update({
where: {
id: String(id)
},
data: {
title
},
select: {
image: true
}
})
if (String(file) != "undefined" && String(file) != "null") {
const fExt = file.name.split(".").pop()
const fileName = id + '.' + fExt;
const newFile = new File([file], fileName, { type: file.type });
await funDeleteFile({ fileId: String(upd.image) })
const upload = await funUploadFile({ file: newFile, dirId: DIR.banner })
await prisma.bannerImage.update({
where: {
id: id
},
data: {
image: upload.data.id
}
})
}
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data banner', table: 'bannerImage', data: user.id })
return NextResponse.json({ success: true, message: "Berhasil mengupdate banner" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengupdate banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,74 @@
import { DIR, funUploadFile, funViewDir, prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import { NextResponse } from "next/server";
// GET ALL BANNER
export async function GET() {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const data = await prisma.bannerImage.findMany({
where: {
isActive: true,
idVillage: user.idVillage
},
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 });
}
}
// CREATE BANNER
export async function POST(request: Request) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const body = await request.formData()
const file = body.get("file") as File;
const data = body.get("data");
const { title } = JSON.parse(data as string)
const fExt = file.name.split(".").pop()
const fName = file.name.replace("." + fExt, "")
const newFile = new File([file], file.name, { type: file.type });
const ini = funViewDir({ dirId: DIR.user })
const upload = await funUploadFile({ file: newFile, dirId: DIR.banner })
if (upload.success) {
const create = await prisma.bannerImage.create({
data: {
title: title,
idVillage: user.idVillage,
extension: String(fExt),
image: upload.data.id
}
})
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User menambah data banner baru', table: 'bannerImage', data: user.id })
return Response.json({ success: true, message: 'Sukses menambah data banner' }, { status: 200 });
} else {
return Response.json({ success: false, message: 'Gagal menambah data banner' }, { status: 200 });
}
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -26,7 +26,7 @@ export async function GET(request: Request, context: { params: { id: string } })
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan calender, data tidak ditemukan",
message: "Gagal mendapatkan kalender, data tidak ditemukan",
},
{ status: 404 }
);
@@ -56,15 +56,10 @@ export async function GET(request: Request, context: { params: { id: string } })
const result = { ...dataCalender, timeStart, timeEnd }
return NextResponse.json({ success: true, message: "Berhasil mendapatkan calender", data: result }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kalender", data: result }, { status: 200 });
} catch (error) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan calender, data tidak ditemukan",
},
{ status: 404 }
return NextResponse.json( { success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan (error: 500)", }, { status: 500 }
);
}
}
@@ -116,7 +111,7 @@ export async function POST(request: Request, context: { params: { id: string } }
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambah anggota, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal menambah anggota, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
@@ -171,6 +166,6 @@ export async function DELETE(request: Request, context: { params: { id: string }
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,7 +1,7 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _, { remove } from "lodash";
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
import { Frequency, RRule } from 'rrule';
@@ -100,16 +100,10 @@ export async function GET(request: Request, context: { params: { id: string } })
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan calender", data: dataFix }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kalender", data: dataFix, user: user.id }, { status: 200 });
} catch (error) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan calender, data tidak ditemukan",
},
{ status: 404 }
);
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan (error: 500)", }, { status: 500 });
}
}
@@ -145,21 +139,19 @@ export async function DELETE(request: Request, context: { params: { id: string }
},
data: {
isActive: false
},
select: {
dateStart: true
}
});
// create log user
const log = await createLogUser({ act: 'DELETE', desc: 'User menghapus data acara kalender', table: 'divisionCalendar', data: id })
return NextResponse.json({ success: true, message: "Berhasil menghapus acara kalender", data }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil menghapus acara kalender", data, user: user.id }, { status: 200 });
} catch (error) {
return NextResponse.json(
{
success: false,
message: "Gagal menghapus calender, coba lagi nanti",
},
{ status: 500 }
return NextResponse.json({ success: false, message: "Gagal menghapus kalender, coba lagi nanti (error: 500)", }, { status: 500 }
);
}
}
@@ -260,12 +252,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
return NextResponse.json({ success: true, message: "Berhasil mengedit acara" }, { status: 200 });
} catch (error) {
return NextResponse.json(
{
success: false,
message: "Gagal mengedit acara, coba lagi nanti",
},
{ status: 500 }
return NextResponse.json({ success: false, message: "Gagal mengedit acara, coba lagi nanti (error: 500)", }, { status: 500 }
);
}
}

View File

@@ -1,11 +1,11 @@
import moment from "moment";
import { NextResponse } from "next/server";
import "moment/locale/id";
import { funGetUserByCookies } from "@/module/auth";
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
// GET HSITORY
// GET HISTORY
export async function GET(request: Request) {
try {
const user = await funGetUserByCookies()
@@ -16,12 +16,14 @@ export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const idDivision = searchParams.get("division");
const name = searchParams.get('search');
const page = searchParams.get('page');
const dataSkip = Number(page) * 10 - 10;
if (idDivision != "null" && idDivision != null && idDivision != undefined) {
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
isActive: true
// isActive: true
}
})
@@ -30,9 +32,14 @@ export async function GET(request: Request) {
}
const data = await prisma.divisionCalendarReminder.findMany({
skip: dataSkip,
take: 10,
where: {
isActive: true,
idDivision: idDivision,
dateEnd: {
lte: new Date()
},
DivisionCalendar: {
title: {
contains: (name == undefined || name == "null") ? "" : name,
@@ -97,6 +104,6 @@ export async function GET(request: Request) {
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal mendapatkan riwayat acara kalender, coba lagi nanti" }, { status: 404 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan riwayat acara kalender, coba lagi nanti (error: 500)" }, { status: 404 });
}
}

View File

@@ -23,7 +23,7 @@ export async function GET(request: Request) {
const cekDivision = await prisma.division.count({
where: {
id: String(idDivision),
isActive: true
// isActive: true
}
})
@@ -54,7 +54,7 @@ export async function GET(request: Request) {
return NextResponse.json({ success: true, message: "Berhasil mendapatkan list acara", data: result }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan list acara" }, { status: 401 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan list acara (error: 500)" }, { status: 401 });
}
}

View File

@@ -1,10 +1,10 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from '@/module/user';
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
import "moment/locale/id";
import { createLogUser } from '@/module/user';
import { NextResponse } from "next/server";
import { Frequency, RRule } from 'rrule';
//GET ALL CALENDER
@@ -24,7 +24,7 @@ export async function GET(request: Request) {
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
isActive: true
// isActive: true
}
})
@@ -85,15 +85,15 @@ export async function GET(request: Request) {
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan calender", data: allOmit }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kalender", data: allOmit }, { status: 200 });
} else {
return NextResponse.json({ success: false, message: "Gagal mendapatkan calender, data tidak ditemukan" }, { status: 404 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan" }, { status: 404 });
}
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal mendapatkan calender, data tidak ditemukan" }, { status: 404 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan (error: 500)" }, { status: 404 });
}
}
@@ -191,6 +191,113 @@ export async function POST(request: Request) {
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal membuat acara kalender, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal membuat acara kalender, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// CEK TGL AVAILABLE
export async function PUT(request: Request) {
try {
const user = await funGetUserByCookies();
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { idDivision, title, desc, timeStart, timeEnd, dateStart, dateEnd, repeatEventTyper, member, linkMeet, repeatValue } = (await request.json());
const division = await prisma.division.findUnique({
where: {
id: idDivision
}
})
const y = new Date('1970-01-01 ' + timeStart)
const x = new Date('1970-01-01 ' + timeEnd)
const timeStartFix = new Date(y.getTime() - (y.getTimezoneOffset() * 60000)).toISOString()
const timeEndFix = new Date(x.getTime() - (x.getTimezoneOffset() * 60000)).toISOString()
const cek = await prisma.divisionCalendarReminder.findMany({
where: {
isActive: true,
Division: {
idGroup: division?.idGroup
},
OR: [
{
dateStart: new Date(dateStart),
DivisionCalendar: {
title: {
equals: title,
mode: "insensitive"
},
}
},
{
dateStart: new Date(dateStart),
OR: [
{
timeStart: { //13:00
lte: timeStartFix, //13:30
},
timeEnd: { //14:00
gt: timeStartFix, //13:30
}
},
{
timeStart: { //07:00
lt: timeEndFix, //07:30
},
timeEnd: { //08:00
gt: timeEndFix, //07:30
}
},
{
timeStart: { //07:00
gt: timeStartFix, //06:30
},
timeEnd: { //08:00
lte: timeEndFix, //09:30
}
}
]
}
]
},
select: {
id: true,
dateStart: true,
timeStart: true,
timeEnd: true,
DivisionCalendar: {
select: {
title: true,
}
},
Division: {
select: {
name: true
}
}
}
})
const dataSama = cek.map((v: any) => ({
..._.omit(v, ["DivisionCalendar", "Division"]),
title: v.DivisionCalendar.title,
divisi: v.Division.name
}))
if (cek.length > 0) {
return NextResponse.json({ success: false, message: "Tidak dapat membuat acara kalender, acara kalender sudah ada pada tanggal tersebut", data: dataSama }, { status: 400 });
} else {
return NextResponse.json({ success: true, message: "Berhasil membuat acara kalender" }, { status: 200 });
}
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal membuat acara kalender, coba lagi nanti (error: 500)" }, { status: 404 });
}
}

View File

@@ -0,0 +1,46 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import { NextResponse } from "next/server";
// KIRIM KOMENTAR DISKUSI UMUM
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { desc } = (await request.json());
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const cek = await prisma.discussion.count({
where: {
id,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal menambahkan komentar, data tidak ditemukan" }, { status: 404 });
}
const data = await prisma.discussionComment.create({
data: {
comment: desc,
idDiscussion: id,
idUser: user.id
}
})
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User menambah komentar pada diskusi umum', table: 'discussionComment', data: data.id })
return NextResponse.json({ success: true, message: "Berhasil menambah komentar" }, { status: 200 });
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal menambahkan komentar, coba lagi nanti (error: 500)" })
}
}

View File

@@ -0,0 +1,92 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import { NextResponse } from "next/server";
// ADD MEMBER DISCUSSION GENERAL
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params
const { member } = (await request.json())
const cek = await prisma.discussion.count({
where: {
id,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal menambahkan anggota, data tidak ditemukan" }, { status: 404 });
}
if (member.length > 0) {
const dataMember = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idDiscussion: id,
idUser: v.idUser
}))
const insertMember = await prisma.discussionMember.createMany({
data: dataMember
})
}
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User menambah anggota diskusi umum', table: 'discussion', data: String(id) })
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan anggota, coba lagi nanti (error : 500)" }, { status: 500 });
}
}
// MENGELUARKAN ANGGOTA
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params
const { idUser } = (await request.json());
const cek = await prisma.discussion.count({
where: {
id,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal, data tidak ditemukan" }, { status: 404 });
}
const deleteMember = await prisma.discussionMember.deleteMany({
where: {
idDiscussion: id,
idUser
}
})
// create log user
const log = await createLogUser({ act: 'DELETE', desc: 'User mengeluarkan anggota diskusi umum', table: 'discussion', data: String(id) })
return NextResponse.json({ success: true, message: "Berhasil mengeluarkan anggota diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota, coba lagi nanti (error : 500)" }, { status: 500 });
}
}

View File

@@ -0,0 +1,272 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
import "moment/locale/id";
// 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 user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const cek = await prisma.discussion.count({
where: {
id,
// isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, data tidak ditemukan" }, { status: 404 });
}
if (kategori == "detail") {
const data = await prisma.discussion.findUnique({
where: {
id,
// isActive: true
},
select: {
isActive: true,
id: true,
title: true,
idGroup: true,
desc: true,
status: true,
createdAt: true,
}
})
dataFix = {
id: data?.id,
isActive: data?.isActive,
idGroup: data?.idGroup,
title: data?.title,
desc: data?.desc,
status: data?.status,
createdAt: moment(data?.createdAt).format("ll"),
}
} else if (kategori == "komentar") {
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, ["createdAt", "User",]),
createdAt: moment(v.createdAt).format("lll").replace('pukul', ''),
username: v.User.name,
img: v.User.img
}))
} else if (kategori == "anggota") {
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 if (kategori == "cek-anggota") {
const cek = await prisma.discussionMember.count({
where: {
idDiscussion: id,
isActive: true,
idUser: user.id
}
})
if (cek > 0) {
dataFix = true
} else {
dataFix = false
}
}
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 });
}
}
// OPEN OR CLOSE DISKUSI UMUM
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params
const { status } = (await request.json());
let newStatus;
if (status === 1) {
newStatus = 2;
} else if (status === 2) {
newStatus = 1;
} else {
return NextResponse.json({ success: false, message: "Invalid status" }, { status: 400 });
}
const data = await prisma.discussion.count({
where: {
id: id
},
});
if (data == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, data tidak ditemukan" }, { status: 404 });
}
const result = await prisma.discussion.update({
where: {
id
},
data: {
status: newStatus
}
});
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate status diskusi umum', table: 'discussion', data: id })
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi umum, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// DELETE DISCUSSION
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params
const { active } = (await request.json());
const cek = await prisma.discussion.count({
where: {
id: id
},
});
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal menghapus diskusi umum, data tidak ditemukan" }, { status: 404 });
}
const data = await prisma.discussion.update({
where: {
id
},
data: {
isActive: active
}
});
// create log user
if (active) {
const log = await createLogUser({ act: 'DELETE', desc: 'User mengaktifkan data diskusi umum', table: 'disscussion', data: id })
return NextResponse.json({ success: true, message: "Berhasil mengaktifkan diskusi umum", user: user.id }, { status: 200 });
} else {
const log = await createLogUser({ act: 'DELETE', desc: 'User mengarsipkan data diskusi umum', table: 'disscussion', data: id })
return NextResponse.json({ success: true, message: "Berhasil mengarsipkan diskusi umum", user: user.id }, { status: 200 });
}
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah diskusi umum, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// EDIT DISCUSSION
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params
const { title, desc } = (await request.json());
const data = await prisma.discussion.count({
where: {
id: id
},
});
if (data == 0) {
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi umum, data tidak ditemukan" }, { status: 404 });
}
const update = await prisma.discussion.update({
where: {
id
},
data: {
desc,
title
}
});
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data diskusi umum', table: 'discussion', data: id })
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi umum, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,193 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
import "moment/locale/id";
// GET ALL DISCUSSION GENERAL
export async function GET(request: Request) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
let grup
const roleUser = user.idUserRole
const villageId = user.idVillage
const userId = user.id
const { searchParams } = new URL(request.url);
const idGroup = searchParams.get("group");
const search = searchParams.get('search');
const page = searchParams.get('page');
const status = searchParams.get('active');
const dataSkip = Number(page) * 10 - 10;
if (idGroup == "null" || idGroup == undefined || idGroup == "") {
grup = user.idGroup
} else {
grup = idGroup
}
const cek = await prisma.group.count({
where: {
id: grup,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan data kegiatan, data tidak ditemukan", }, { status: 404 });
}
const data = await prisma.discussion.findMany({
skip: dataSkip,
take: 10,
where: {
isActive: status == "false" ? false : true,
idVillage: String(villageId),
idGroup: grup,
title: {
contains: (search == undefined || search == "null") ? "" : search,
mode: "insensitive"
},
},
orderBy: [
{
status: 'desc'
},
{
createdAt: 'desc'
}
],
select: {
id: true,
title: true,
desc: true,
status: true,
createdAt: true,
DiscussionComment: {
select: {
id: true,
}
}
}
});
const fixData = data.map((v: any) => ({
..._.omit(v, ["DiscussionComment", "createdAt"]),
total_komentar: v.DiscussionComment.length,
createdAt: moment(v.createdAt).format("ll")
}))
const filter = await prisma.group.findUnique({
where: {
id: grup
},
select: {
id: true,
name: true
}
})
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: fixData, filter }, { 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 });
}
}
// CREATE DISCUSSION GENERALE
export async function POST(request: Request) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const userId = user.id
const userRoleLogin = user.idUserRole
const { idGroup, title, desc, member } = (await request.json());
const data = await prisma.discussion.create({
data: {
idVillage: String(user.idVillage),
idGroup: idGroup,
title: title,
desc: desc,
createdBy: String(userId),
},
select: {
id: true
}
});
const dataMember = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idDiscussion: data.id,
idUser: v.idUser,
}))
const insertMember = await prisma.discussionMember.createMany({
data: dataMember
})
const dataNotif = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idUserTo: v.idUser,
idUserFrom: userId,
category: 'discussion',
idContent: data.id,
title: 'Diskusi Umum Baru',
desc: 'Terdapat diskusi umum baru. Silahkan periksa detailnya.'
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: user.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
}
}
})
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'discussion',
idContent: data.id,
title: 'Diskusi Umum Baru',
desc: 'Terdapat diskusi umum baru. Silahkan periksa detailnya.'
})
}
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User membuat data diskusi umum', table: 'discussion', data: data.id })
return NextResponse.json({ success: true, message: "Berhasil menambahkan diskusi umum", notif: dataNotif }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -48,6 +48,6 @@ export async function POST(request: Request, context: { params: { id: string } }
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambah komentar, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal menambah komentar, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -36,6 +36,7 @@ export async function GET(request: Request, context: { params: { id: string } })
id: id
},
select: {
isActive: true,
id: true,
title: true,
desc: true,
@@ -87,11 +88,11 @@ export async function GET(request: Request, context: { params: { id: string } })
totalComments: comments.length,
};
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: response }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: response, user: user.id }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -140,7 +141,7 @@ export async function DELETE(request: Request, context: { params: { id: string }
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -152,7 +153,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params
const { active } = (await request.json());
const cek = await prisma.divisionDisscussion.count({
where: {
id: id
@@ -160,7 +161,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
});
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal menghapus diskusi, data tidak ditemukan" }, { status: 404 });
return NextResponse.json({ success: false, message: "Gagal mengarsipkan diskusi, data tidak ditemukan" }, { status: 404 });
}
@@ -169,16 +170,22 @@ export async function PUT(request: Request, context: { params: { id: string } })
id: id
},
data: {
isActive: false
isActive: active
}
});
// create log user
const log = await createLogUser({ act: 'DELETE', desc: 'User menghapus data diskusi', table: 'divisionDisscussion', data: id })
return NextResponse.json({ success: true, message: "Berhasil menghapus diskusi" }, { status: 200 });
// create log user
if (active) {
const log = await createLogUser({ act: 'DELETE', desc: 'User mengaktifkan data diskusi', table: 'divisionDisscussion', data: id })
return NextResponse.json({ success: true, message: "Berhasil mengaktifkan diskusi", user: user.id }, { status: 200 });
} else {
const log = await createLogUser({ act: 'DELETE', desc: 'User mengarsipkan data diskusi', table: 'divisionDisscussion', data: id })
return NextResponse.json({ success: true, message: "Berhasil mengarsipkan diskusi", user: user.id }, { status: 200 });
}
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menghapus diskusi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengubah diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -218,6 +225,6 @@ export async function POST(request: Request, context: { params: { id: string } }
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,10 +1,10 @@
import { prisma } from "@/module/_global";
import { funSendWebPush, prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
import "moment/locale/id";
import { createLogUser } from "@/module/user";
import { NextResponse } from "next/server";
// GET ALL DISCUSSION DIVISION ACTIVE = TRUE
@@ -18,13 +18,16 @@ export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const idDivision = searchParams.get("division");
const name = searchParams.get('search');
const page = searchParams.get('page');
const status = searchParams.get('active');
const dataSkip = Number(page) * 10 - 10;
if (idDivision != "null" && idDivision != null && idDivision != undefined) {
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
isActive: true
// isActive: true
}
})
@@ -33,15 +36,15 @@ export async function GET(request: Request) {
}
const data = await prisma.divisionDisscussion.findMany({
skip: dataSkip,
take: 10,
where: {
isActive: true,
isActive: status == "false" ? false : true,
idDivision: idDivision,
User: {
name: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
}
}
desc: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
},
},
orderBy: {
createdAt: 'desc'
@@ -84,7 +87,7 @@ export async function GET(request: Request) {
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -98,6 +101,9 @@ export async function POST(request: Request) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const userRoleLogin = user.idUserRole
const userId = user.id
const { idDivision, desc } = (await request.json());
const cekDivision = await prisma.division.count({
@@ -122,12 +128,121 @@ export async function POST(request: Request) {
}
});
const memberDivision = await prisma.divisionMember.findMany({
where: {
idDivision: idDivision
},
select: {
User: {
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
}
}
}
}
})
// mengirim notifikasi
// datanotif untuk realtime notifikasi
// datapush untuk web push notifikasi ketika aplikasi tidak aktif
const dataNotif = memberDivision.map((v: any) => ({
..._.omit(v, ["User", "Subscribe"]),
idUserTo: v.User.id,
idUserFrom: String(user.id),
category: 'division/' + idDivision + '/discussion',
idContent: data.id,
title: 'Diskusi Baru',
desc: 'Terdapat diskusi baru. Silahkan periksa detailnya.'
}))
const dataPush = memberDivision.map((v: any) => ({
..._.omit(v, ["User", "Subscribe"]),
idUser: v.User.id,
subscription: v.User.Subscribe?.subscription,
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: user.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
}
}
})
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'division/' + idDivision + '/discussion',
idContent: data.id,
title: 'Diskusi Baru',
desc: 'Terdapat diskusi baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: perbekel?.id,
subscription: perbekel?.Subscribe?.subscription
})
}
if (userRoleLogin != "cosupadmin") {
const ketuaGrup = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "cosupadmin",
idGroup: user.idGroup
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
}
}
})
dataNotif.push({
idUserTo: ketuaGrup?.id,
idUserFrom: userId,
category: 'division/' + idDivision + '/discussion',
idContent: data.id,
title: 'Diskusi Baru',
desc: 'Terdapat diskusi baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: ketuaGrup?.id,
subscription: ketuaGrup?.Subscribe?.subscription
})
}
const pushNotif = dataPush.filter((item) => item.subscription != undefined)
const sendWebPush = await funSendWebPush({ sub: pushNotif, message: { body: 'Terdapat diskusi baru. Silahkan periksa detailnya.', title: 'Diskusi Baru' } })
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User membuat data diskusi', table: 'divisionDisscussion', data: data.id })
return NextResponse.json({ success: true, message: "Berhasil menambahkan diskusi", data, }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil menambahkan diskusi", notif: dataNotif }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan diskusi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal menambahkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -23,7 +23,7 @@ export async function GET(request: Request, context: { params: { id: string } })
const data = await prisma.division.findUnique({
where: {
id: String(id),
isActive: true
// isActive: true
}
});
@@ -50,6 +50,17 @@ export async function GET(request: Request, context: { params: { id: string } })
}
})
const dokumenShare = await prisma.divisionDocumentShare.count({
where: {
idDivision: String(id),
isActive: true,
DivisionDocumentFolderFile: {
isActive: true,
category: "FILE"
}
}
})
const diskusi = await prisma.divisionDisscussion.count({
where: {
idDivision: String(id),
@@ -74,7 +85,7 @@ export async function GET(request: Request, context: { params: { id: string } })
allData = {
tugas: tugas,
dokumen: dokumen,
dokumen: dokumen + dokumenShare,
diskusi: diskusi,
kalender: kalender
}
@@ -86,23 +97,79 @@ export async function GET(request: Request, context: { params: { id: string } })
idDivision: String(id),
status: 0,
isActive: true,
dateStart: new Date()
dateStart: {
lte: new Date()
},
dateEnd: {
gte: new Date()
},
DivisionProject: {
status: {
lt: 3
}
}
},
select: {
id: true,
idProject: true,
title: true,
dateStart: true,
dateEnd: true,
DivisionProject: {
select: {
title: true
}
}
},
orderBy: {
dateEnd: "asc"
}
})
allData = tugas.map((v: any) => ({
..._.omit(v, ["dateStart", "dateEnd"]),
dateStart: moment(v.dateStart).format("LL"),
dateEnd: moment(v.dateEnd).format("LL")
..._.omit(v, ["dateStart", "dateEnd", "DivisionProject"]),
dateStart: moment(v.dateStart).format("ll"),
dateEnd: moment(v.dateEnd).format("ll"),
projectTitle: v.DivisionProject.title
}))
} else if (kategori == "new-file") {
allData = await prisma.divisionDocumentFolderFile.findMany({
const dataShare = await prisma.divisionDocumentShare.findMany({
skip: 0,
take: 5,
where: {
isActive: true,
idDivision: String(id),
DivisionDocumentFolderFile: {
isActive: true,
category: "FILE"
}
},
select: {
DivisionDocumentFolderFile: {
select: {
id: true,
name: true,
extension: true,
path: true,
}
},
createdAt: true
},
orderBy: {
createdAt: 'desc'
}
})
const fixShare = dataShare.map((v: any) => ({
..._.omit(v, ["DivisionDocumentFolderFile"]),
id: v.DivisionDocumentFolderFile.id,
name: v.DivisionDocumentFolderFile.name,
extension: v.DivisionDocumentFolderFile.extension,
path: 'home',
share: true
}))
const dataDokumen = await prisma.divisionDocumentFolderFile.findMany({
skip: 0,
take: 5,
where: {
@@ -114,11 +181,25 @@ export async function GET(request: Request, context: { params: { id: string } })
id: true,
name: true,
extension: true,
path: true,
createdAt: true
},
orderBy: {
createdAt: "desc"
}
})
const fixData = dataDokumen.map((v: any) => ({
..._.omit(v, [""]),
share: false
}))
if (fixShare.length > 0) {
fixData.push(...fixShare)
}
allData = _.orderBy(fixData, ['createdAt'], ['desc']);
} else if (kategori == "new-discussion") {
const diskusi = await prisma.divisionDisscussion.findMany({
skip: 0,
@@ -146,7 +227,7 @@ export async function GET(request: Request, context: { params: { id: string } })
allData = diskusi.map((v: any) => ({
..._.omit(v, ["createdAt", "User"]),
date: moment(v.dateStart).format("ll"),
date: moment(v.createdAt).format("ll"),
user: v.User.name
}))
}
@@ -158,7 +239,7 @@ export async function GET(request: Request, context: { params: { id: string } })
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -211,7 +292,7 @@ export async function DELETE(request: Request, context: { params: { id: string }
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -265,7 +346,7 @@ export async function PUT(request: Request, context: { params: { id: string } })
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah status admin divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengubah status admin divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -316,6 +397,6 @@ export async function POST(request: Request, context: { params: { id: string } }
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota divisi" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan anggota divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal menambahkan anggota divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -18,7 +18,7 @@ export async function GET(request: Request, context: { params: { id: string } })
const data = await prisma.division.findUnique({
where: {
id: String(id),
isActive: true,
// isActive: true,
}
});
@@ -65,6 +65,6 @@ export async function GET(request: Request, context: { params: { id: string } })
return NextResponse.json({ success: true, data: fixMember })
} catch (error) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan member, data tidak ditemukan", }, { status: 404 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan anggota, data tidak ditemukan (error: 500)", }, { status: 500 });
}
}

View File

@@ -17,7 +17,7 @@ export async function GET(request: Request, context: { params: { id: string } })
const data = await prisma.division.findUnique({
where: {
id: String(id),
isActive: true
// isActive: true
}
});
@@ -63,7 +63,7 @@ export async function GET(request: Request, context: { params: { id: string } })
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -117,6 +117,6 @@ export async function PUT(request: Request, context: { params: { id: string } })
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengedit divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,48 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import { NextResponse } from "next/server";
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params;
const { isActive } = (await request.json());
const data = await prisma.division.count({
where: {
id: id,
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Edit status divisi gagal, data tidak ditemukan",
},
{ status: 404 }
);
}
const update = await prisma.division.update({
where: {
id: id,
},
data: {
isActive: !isActive,
},
});
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengedit status data divisi', table: 'division', data: id })
return NextResponse.json({ success: true, message: "Status divisi berhasil diupdate", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah status divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,6 +1,5 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import _ from "lodash";
import { NextResponse } from "next/server";
// GET LIST DIVISI BY ID DIVISI (CONTOH : UNTUK SHARE DOKUMEN)
@@ -38,6 +37,9 @@ export async function GET(request: Request) {
select: {
id: true,
name: true,
},
orderBy: {
name: "asc"
}
});
@@ -45,6 +47,6 @@ export async function GET(request: Request) {
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -6,193 +6,372 @@ import { NextResponse } from "next/server";
export async function GET(request: Request) {
try {
const user = await funGetUserByCookies()
const { searchParams } = new URL(request.url)
const group = searchParams.get("group")
const idGroup = searchParams.get("group")
const division = searchParams.get("division")
const date = searchParams.get("date")
const dateAkhir = searchParams.get("date-end")
const kat = searchParams.get("cat")
let grup
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 })
}
// CHART PROGRESS
let kondisiProgress
if (division == "undefined") {
kondisiProgress = {
isActive: true,
updatedAt: {
lte: new Date(String(date))
},
Division: {
idGroup: String(group)
}
}
if (idGroup == "null" || idGroup == undefined || idGroup == "") {
grup = user.idGroup
} else {
kondisiProgress = {
isActive: true,
idDivision: String(division),
updatedAt: {
lte: new Date(String(date))
},
}
grup = idGroup
}
const data = await prisma.divisionProject.groupBy({
where: kondisiProgress,
by: ["status"],
_count: true
})
const dataStatus = [{ name: 'Segera dikerjakan', status: 0 }, { name: 'Dikerjakan', status: 1 }, { name: 'Selesai dikerjakan', 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)
input = {
name: dataStatus[index].name,
value: find
}
} else {
input = {
name: dataStatus[index].name,
value: 0
}
}
hasilProgres.push(input)
}
// CHART DOKUMEN
let kondisi
if (division == "undefined") {
kondisi = {
isActive: true,
category: 'FILE',
Division: {
idGroup: String(group)
},
createdAt: {
lte: new Date(String(date))
},
}
} else {
kondisi = {
isActive: true,
category: 'FILE',
idDivision: String(division),
createdAt: {
lte: new Date(String(date))
},
}
}
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 = [hasilImage, hasilFile]
// CHART EVENT
let kondisiEvent
if (division == "undefined") {
kondisiEvent = {
isActive: true,
Division: {
idGroup: String(group)
},
dateStart: new Date(String(date))
}
} else {
kondisiEvent = {
isActive: true,
idDivision: String(division),
dateStart: new Date(String(date))
}
}
const dataEvent = await prisma.divisionCalendar.findMany({
where: kondisiEvent,
select: {
id: true,
idDivision: true,
title: true,
desc: true,
status: true,
timeStart: true,
dateStart: true,
timeEnd: true,
dateEnd: true,
createdAt: true,
User: {
select: {
name: true
if (kat == "table-progress") {
let kondisiProgress
if (division == "undefined") {
kondisiProgress = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
} else {
kondisiProgress = {
isActive: true,
idDivision: String(division),
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
},
orderBy: {
createdAt: 'desc'
}
})
const hasilEvent = dataEvent.map((v: any) => ({
..._.omit(v, ["User"]),
user_name: v.User.name,
timeStart: moment.utc(v.timeStart).format('HH:mm'),
timeEnd: moment.utc(v.timeEnd).format('HH:mm')
}))
const allData = {
progress: hasilProgres,
dokumen: hasilDokumen,
event: hasilEvent
const data = await prisma.divisionProject.findMany({
where: kondisiProgress,
select: {
id: true,
title: true,
status: true,
DivisionProjectTask: {
where: {
isActive: true
},
select: {
title: true,
status: true
}
}
}
})
const dataFix = data.map((v: any) => ({
..._.omit(v, ["DivisionProjectTask"]),
progress: ceil((v.DivisionProjectTask.filter((i: any) => i.status == 1).length * 100) / v.DivisionProjectTask.length),
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
} else {
// CHART PROGRESS
let kondisiProgress
if (division == "undefined") {
kondisiProgress = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
} else {
kondisiProgress = {
isActive: true,
idDivision: String(division),
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
}
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)
}
// CHART DOKUMEN
let kondisi
if (division == "undefined") {
kondisi = {
isActive: true,
category: 'FILE',
Division: {
idGroup: String(grup)
},
createdAt: {
gte: new Date(String(date)),
lte: new Date(String(dateAkhir))
},
}
} else {
kondisi = {
isActive: true,
category: 'FILE',
idDivision: String(division),
createdAt: {
gte: new Date(String(date)),
lte: new Date(String(dateAkhir))
},
}
}
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 = [hasilImage, hasilFile]
// CHART EVENT
let kondisiEvent, kondisiSelesai, kondisiComingSoon
if (division == "undefined") {
// kondisiEvent = {
// isActive: true,
// Division: {
// idGroup: String(grup)
// },
// DivisionCalendarReminder: {
// some: {
// dateStart: {
// gte: new Date(String(date)),
// lte: new Date(String(dateAkhir))
// }
// }
// }
// }
kondisiSelesai = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionCalendarReminder: {
some: {
dateStart: {
gte: new Date(String(date)),
lte: new Date()
}
}
}
}
kondisiComingSoon = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionCalendarReminder: {
some: {
dateStart: {
gt: new Date(),
lte: new Date(String(dateAkhir))
}
}
}
}
} else {
// kondisiEvent = {
// isActive: true,
// idDivision: String(division),
// DivisionCalendarReminder: {
// some: {
// dateStart: {
// gte: new Date(String(date)),
// lte: new Date(String(dateAkhir))
// }
// }
// }
// }
kondisiSelesai = {
isActive: true,
idDivision: String(division),
DivisionCalendarReminder: {
some: {
dateStart: {
gte: new Date(String(date)),
lte: new Date()
}
}
}
}
kondisiComingSoon = {
isActive: true,
idDivision: String(division),
DivisionCalendarReminder: {
some: {
dateStart: {
gt: new Date(),
lte: new Date(String(dateAkhir))
}
}
}
}
}
const eventSelesai = await prisma.divisionCalendar.count({
where: kondisiSelesai
})
const eventComingSoon = await prisma.divisionCalendar.count({
where: kondisiComingSoon
})
const hasilEvent = [
{
name: 'Selesai',
value: eventSelesai
},
{
name: 'Akan Datang',
value: eventComingSoon
}
]
// const dataEvent = await prisma.divisionCalendar.findMany({
// where: kondisiEvent,
// select: {
// id: true,
// idDivision: true,
// title: true,
// desc: true,
// status: true,
// timeStart: true,
// dateStart: true,
// timeEnd: true,
// dateEnd: true,
// createdAt: true,
// User: {
// select: {
// name: true
// }
// }
// },
// orderBy: {
// createdAt: 'desc'
// }
// })
// const hasilEvent = dataEvent.map((v: any) => ({
// ..._.omit(v, ["User"]),
// user_name: v.User.name,
// timeStart: moment.utc(v.timeStart).format('HH:mm'),
// timeEnd: moment.utc(v.timeEnd).format('HH:mm')
// }))
const allData = {
progress: hasilProgres,
dokumen: hasilDokumen,
event: hasilEvent
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: allData }, { status: 200 });
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: allData }, { status: 200 });
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,8 +1,7 @@
import { prisma } from "@/module/_global";
import { funSendWebPush, prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import { revalidatePath, revalidateTag } from "next/cache";
import { NextResponse } from "next/server";
@@ -19,17 +18,22 @@ export async function GET(request: Request) {
const roleUser = user.idUserRole
const { searchParams } = new URL(request.url);
const idGroup = searchParams.get("group");
const kategori = searchParams.get("cat");
const name = searchParams.get('search');
const page = searchParams.get('page');
const active = searchParams.get("active");
const dataSkip = Number(page) * 10 - 10;
if (idGroup == "null" || idGroup == undefined) {
if (idGroup == "null" || idGroup == undefined || idGroup == "") {
grup = user.idGroup
} else {
grup = idGroup
}
// JIKA (ROLE BUKAN USER DAN COADMIN) ATAU SEMUA ROLE DG KATEGORI == SEMUA
let kondisi: any = {
isActive: true,
isActive: active == 'false' ? false : true,
idVillage: String(villaId),
idGroup: grup,
name: {
@@ -38,25 +42,35 @@ export async function GET(request: Request) {
}
}
if (roleUser != "supadmin" && roleUser != "cosupadmin" && roleUser != "admin") {
kondisi = {
isActive: true,
idVillage: String(villaId),
idGroup: grup,
name: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
},
DivisionMember: {
some: {
isActive: true,
idUser: String(user.id)
// JIKA ROLE = USER ATAU COADMIN DAN KATEGORI != SEMUA (DIVISI SAYA)
if (roleUser != "supadmin" && roleUser != "developer" && roleUser != "cosupadmin" && roleUser != "admin") {
if (kategori != "semua") {
kondisi = {
isActive: active == 'false' ? false : true,
idVillage: String(villaId),
idGroup: grup,
name: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
},
DivisionMember: {
some: {
isActive: true,
idUser: String(user.id)
}
}
}
}
}
const totalData = await prisma.division.count({
where: kondisi
})
const data = await prisma.division.findMany({
skip: dataSkip,
take: 10,
where: kondisi,
select: {
id: true,
@@ -70,6 +84,9 @@ export async function GET(request: Request) {
idUser: true
}
}
},
orderBy: {
createdAt: 'desc'
}
});
@@ -90,18 +107,16 @@ export async function GET(request: Request) {
})
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: allData, filter }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: allData, total: totalData, filter }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// CREATE DATA DIVISI
export async function POST(request: Request) {
try {
@@ -110,13 +125,24 @@ export async function POST(request: Request) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const sent = (await request.json());
const villaId = user.idVillage
const userId = user.id
const userRoleLogin = user.idUserRole
const sent = (await request.json())
let fixGroup
if (sent.data.idGroup == "null" || sent.data.idGroup == undefined || sent.data.idGroup == "") {
fixGroup = user.idGroup
} else {
fixGroup = sent.data.idGroup
}
const data = await prisma.division.create({
data: {
name: sent.data.name,
idVillage: String(user.idVillage),
idGroup: sent.data.idGroup,
idGroup: fixGroup,
desc: sent.data.desc,
createdBy: String(user.id)
},
@@ -137,16 +163,134 @@ export async function POST(request: Request) {
data: dataMember
})
revalidatePath('/api/divisi/', "page")
revalidatePath('/divisi', 'page')
revalidateTag('divisi')
// mengirim notifikasi
// datanotif untuk realtime notifikasi
// datapush untuk web push notifikasi ketika aplikasi tidak aktif
const dataNotif = sent.member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idUserTo: v.idUser,
idUserFrom: userId,
category: 'division',
idContent: data.id,
title: 'Divisi Baru',
desc: 'Terdapat divisi baru. Silahkan periksa detailnya.'
}))
const selectUser = await prisma.divisionMember.findMany({
where: {
isActive: true,
idDivision: data.id
},
select: {
idUser: true,
User: {
select: {
Subscribe: {
select: {
subscription: true
}
}
}
}
}
})
const dataPush = selectUser.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe"]),
idUser: v.idUser,
subscription: v.User.Subscribe?.subscription,
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: user.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
}
}
})
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'division',
idContent: data.id,
title: 'Divisi Baru',
desc: 'Terdapat divisi baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: perbekel?.id,
subscription: perbekel?.Subscribe?.subscription
})
} else {
const atasanGroup = await prisma.user.findMany({
where: {
isActive: true,
idGroup: sent.data.idGroup,
AND: {
OR: [
{ idUserRole: 'cosupadmin' },
{ idUserRole: 'admin' },
]
}
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
}
}
})
const omitData = atasanGroup.map((v: any) => ({
..._.omit(v, ["id", "Subscribe"]),
idUserTo: v.id,
idUserFrom: userId,
category: 'division',
idContent: data.id,
title: 'Divisi Baru',
desc: 'Terdapat divisi baru. Silahkan periksa detailnya.'
}))
const omitPush = atasanGroup.map((v: any) => ({
..._.omit(v, ["id", "Subscribe"]),
idUser: v.id,
subscription: v.Subscribe?.subscription,
}))
dataNotif.push(...omitData)
dataPush.push(...omitPush)
}
const pushNotif = dataPush.filter((item) => item.subscription != undefined)
const sendWebPush = await funSendWebPush({ sub: pushNotif, message: { title: 'Divisi Baru', body: 'Terdapat divisi baru. Silahkan periksa detailnya.' } })
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User membuat data divisi', table: 'division', data: data.id })
return NextResponse.json({ success: true, message: "Berhasil menambahkan divisi", data, }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil menambahkan divisi", notif: dataNotif, }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal menambahkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -2,7 +2,9 @@ import { DIR, funCopyFile, prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
import "moment/locale/id";
// MOVE ITEM
@@ -73,7 +75,7 @@ export async function POST(request: Request) {
return NextResponse.json({ success: true, message: "Berhasil memindahkan item" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal memindahkan item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal memindahkan item, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};
@@ -157,7 +159,7 @@ export async function PUT(request: Request) {
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal salin item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal salin item, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};
@@ -190,13 +192,109 @@ export async function DELETE(request: Request) {
data: omitData
})
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User membagikan item', table: 'divisionDocumentShare', data: dataItem[i].id })
}
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User membagikan item', table: 'divisionDocumentShare', data: '' })
return NextResponse.json({ success: true, message: "Berhasil membagikan item" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal membagikan item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal membagikan item, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};
};
// GET INFO ITEM
export async function GET(request: Request) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { searchParams } = new URL(request.url);
const idItem = searchParams.get("item");
const category = searchParams.get("cat");
const cekItem = await prisma.divisionDocumentFolderFile.count({
where: {
id: String(idItem),
}
})
if (cekItem == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan dokumen, data tidak ditemukan" }, { status: 404 });
}
let fixData
if (category == 'share') {
const share = await prisma.divisionDocumentShare.findMany({
where: {
idDocument: String(idItem),
isActive: true
},
select: {
idDivision: true,
Division: {
select: {
name: true
}
}
}
})
fixData = share.map((v: any) => ({
..._.omit(v, ["idDivision", "Division"]),
id: v.idDivision,
name: v.Division.name
}))
} else {
const data = await prisma.divisionDocumentFolderFile.findUnique({
where: {
id: String(idItem),
},
select: {
category: true,
name: true,
extension: true,
createdAt: true,
path: true,
Division: {
select: {
name: true
}
},
User: {
select: {
name: true
}
}
}
})
const dataPath = await prisma.divisionDocumentFolderFile.findUnique({
where: {
id: data?.path
}
})
fixData = {
category: data?.category,
name: data?.name,
extension: data?.extension,
createdAt: moment(data?.createdAt).format('DD MMMM YYYY'),
path: (dataPath?.name !== undefined && dataPath?.name !== null && dataPath?.name !== '') ? dataPath.name : "home",
division: data?.Division?.name,
createdBy: data?.User?.name
}
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan item", data: fixData }, { 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 });
}
}

View File

@@ -23,7 +23,7 @@ export async function GET(request: Request) {
const cekDivision = await prisma.division.count({
where: {
id: String(idDivision),
isActive: true
// isActive: true
}
})
@@ -46,7 +46,10 @@ export async function GET(request: Request) {
where: {
isActive: true,
idDivision: String(idDivision),
idDocument: String(path)
idDocument: String(path),
DivisionDocumentFolderFile: {
isActive: true
}
}
})
@@ -106,10 +109,14 @@ export async function GET(request: Request) {
where: {
isActive: true,
idDivision: String(idDivision),
DivisionDocumentFolderFile: {
isActive: true
}
},
select: {
DivisionDocumentFolderFile: {
select: {
idStorage: true,
id: true,
category: true,
name: true,
@@ -124,20 +131,25 @@ export async function GET(request: Request) {
updatedAt: true
}
}
},
orderBy: {
DivisionDocumentFolderFile: {
createdAt: 'desc'
}
}
})
formatDataShare = dataShare.map((v: any) => ({
..._.omit(v, ["DivisionDocumentFolderFile"]),
idStorage: '',
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: moment(v.DivisionDocumentFolderFile.createdAt).format("DD-MM-YYYY HH:mm"),
updatedAt: moment(v.DivisionDocumentFolderFile.updatedAt).format("DD-MM-YYYY HH:mm"),
createdAt: v.DivisionDocumentFolderFile.createdAt,
updatedAt: v.DivisionDocumentFolderFile.updatedAt,
share: true
}))
@@ -168,15 +180,15 @@ export async function GET(request: Request) {
updatedAt: true
},
orderBy: {
name: 'asc'
createdAt: 'desc'
}
})
const allData = data.map((v: any) => ({
..._.omit(v, ["User", "createdAt", "updatedAt"]),
createdBy: v.User.name,
createdAt: moment(v.createdAt).format("DD-MM-YYYY HH:mm"),
updatedAt: moment(v.updatedAt).format("DD-MM-YYYY HH:mm"),
createdAt: v.createdAt,
updatedAt: v.updatedAt,
share: false
}))
@@ -184,7 +196,13 @@ export async function GET(request: Request) {
allData.push(...formatDataShare)
}
const formatData = _.orderBy(allData, ['category', 'name'], ['desc', 'asc']);
const formatData = _.orderBy(allData, ['category', 'createdAt'], ['desc', 'desc']);
const fixData = formatData.map((v: any) => ({
..._.omit(v, ["createdAt", "updatedAt"]),
createdAt: moment(v.createdAt).format("DD-MM-YYYY HH:mm"),
updatedAt: moment(v.updatedAt).format("DD-MM-YYYY HH:mm"),
}))
let pathNow = path
let jalur = []
@@ -215,11 +233,11 @@ export async function GET(request: Request) {
jalur.push({ id: 'home', name: 'home' })
jalur = [...jalur].reverse()
return NextResponse.json({ success: true, message: "Berhasil mendapatkan item", data: formatData, jalur }, { status: 200 });
return NextResponse.json({ success: true, message: "Berhasil mendapatkan item", data: fixData, jalur }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan item, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -295,7 +313,7 @@ export async function POST(request: Request) {
return NextResponse.json({ success: true, message: "Berhasil membuat folder baru" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal membuat folder, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal membuat folder, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};
@@ -355,7 +373,7 @@ export async function PUT(request: Request) {
return NextResponse.json({ success: true, message: "Berhasil mengubah nama item" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah nama item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengubah nama item (error: 500), coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
}
};
@@ -389,6 +407,6 @@ export async function DELETE(request: Request) {
return NextResponse.json({ success: true, message: "Berhasil menghapus item" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menghapus item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal menghapus item, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -1,10 +1,8 @@
import { DIR, funUploadFile, prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import { NextResponse } from "next/server";
import fs from "fs";
import path from "path";
import { createLogUser } from "@/module/user";
// UPLOAD FILE
@@ -95,6 +93,6 @@ export async function POST(request: Request) {
}
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal upload file, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal upload file, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -5,6 +5,7 @@ import { NextResponse } from "next/server";
export const dynamic = 'force-dynamic'
export const revalidate = true
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
@@ -39,7 +40,7 @@ export async function GET(request: Request, context: { params: { id: string } })
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -79,11 +80,11 @@ export async function DELETE(request: Request, context: { params: { id: string }
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengedit status data grup', table: 'group', data: id })
return NextResponse.json( { success: true, message: "Grup berhasil diedit", data, }, { status: 200 } );
return NextResponse.json({ success: true, message: "Grup berhasil diedit", data, }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengedit grup, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -124,10 +125,10 @@ export async function PUT(request: Request, context: { params: { id: string } })
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengedit data grup', table: 'group', data: id })
return NextResponse.json( { success: true, message: "Grup berhasil diedit", data, }, { status: 200 } );
return NextResponse.json({ success: true, message: "Grup berhasil diedit", data, }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mengedit grup, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,9 +1,10 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { NextResponse } from "next/server";
export const dynamic = 'force-dynamic'
export const revalidate = true
export async function GET(request: Request) {
try {
const user = await funGetUserByCookies()
@@ -18,7 +19,7 @@ export async function GET(request: Request) {
idVillage: String(villaId)
}
if (role != "supadmin") {
if (role != "supadmin" && role != "developer") {
kondisi = {
isActive: true,
idVillage: String(villaId),
@@ -32,6 +33,9 @@ export async function GET(request: Request) {
id: true,
name: true,
Division: {
where: {
isActive: true
},
select: {
id: true,
name: true
@@ -44,6 +48,6 @@ export async function GET(request: Request) {
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -6,6 +6,7 @@ import { NextResponse } from "next/server";
export const dynamic = 'force-dynamic'
export const revalidate = true
export async function GET(request: Request) {
try {
const user = await funGetUserByCookies()
@@ -31,6 +32,9 @@ export async function GET(request: Request) {
id: true,
name: true,
isActive: true
},
orderBy: {
name: 'asc'
}
});
@@ -38,7 +42,7 @@ export async function GET(request: Request) {
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
@@ -74,6 +78,6 @@ export async function POST(request: Request) {
return NextResponse.json({ success: true, message: "Berhasil menambahkan grup", data, }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal menambahkan grup, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -0,0 +1,125 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
// GET ALL NOTIFIKASI
export async function GET(request: Request) {
try {
const user = await funGetUserByCookies();
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { searchParams } = new URL(request.url);
const page = searchParams.get('page');
const dataSkip = Number(page) * 10 - 10;
const announcements = await prisma.notifications.findMany({
skip: dataSkip,
take: 10,
where: {
isActive: true,
idUserTo: user.id
},
orderBy: [
{
isRead: 'asc'
},
{
createdAt: 'desc'
}
]
});
const allData = announcements.map((v: any) => ({
..._.omit(v, ["createdAt"]),
createdAt: moment(v.createdAt).format("ll")
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan notifikasi", data: allData, }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan notifikasi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// UPDATE READ NOTIFIKASI
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = await request.json();
const data = await prisma.notifications.count({
where: {
id: id,
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan data, data tidak ditemukan",
},
{ status: 404 }
);
}
const result = await prisma.notifications.update({
where: {
id: id,
},
data: {
isRead: true,
},
});
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User membaca notifikasi', table: 'notifications', data: id })
return NextResponse.json({ success: true, message: "Berhasil mendapatkan notifikasi", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan notifikasi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// UPDATE READ ALL NOTIFICATION
export async function POST(request: Request) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const upd = await prisma.notifications.updateMany({
where: {
idUserTo: user.id,
isRead: false
},
data: {
isRead: true
}
})
// create log user
const log = await createLogUser({ act: 'UPDATE', desc: 'User menandai semua notifikasi', table: 'notifications', data: '' })
return NextResponse.json({ success: true, message: "Berhasil mengupdate notifikasi", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengupdate notifikasi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,3 +1,4 @@
import { DivisionProject } from './../../../../node_modules/.prisma/client/index.d';
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import _, { ceil } from "lodash";
@@ -26,8 +27,8 @@ export async function GET(request: Request) {
if (kategori == "kegiatan") {
let kondisi
// klo perbekel == semua grup
if (roleUser == "supadmin") {
// klo perbekel/developer == semua grup
if (roleUser == "supadmin" || roleUser == "developer") {
kondisi = {
isActive: true,
idVillage: idVillage,
@@ -35,11 +36,21 @@ export async function GET(request: Request) {
isActive: true,
}
}
} else {
} else if (roleUser == "admin" || roleUser == "cosupadmin") {
kondisi = {
isActive: true,
idGroup: idGroup
}
} else {
kondisi = {
isActive: true,
idGroup: idGroup,
ProjectMember: {
some: {
idUser: user.id
}
}
}
}
const data = await prisma.project.findMany({
@@ -76,8 +87,8 @@ export async function GET(request: Request) {
} else if (kategori == "division") {
let kondisi
// klo perbekel == semua grup
if (roleUser == "supadmin") {
// klo perbekel/developer == semua grup
if (roleUser == "supadmin" || roleUser == "developer") {
kondisi = {
isActive: true,
idVillage: idVillage,
@@ -85,11 +96,21 @@ export async function GET(request: Request) {
isActive: true,
}
}
} else {
} else if (roleUser == "admin" || roleUser == "cosupadmin") {
kondisi = {
isActive: true,
idGroup: idGroup
}
} else {
kondisi = {
isActive: true,
idGroup: idGroup,
DivisionMember: {
some: {
idUser: user.id
}
}
}
}
const data = await prisma.division.findMany({
@@ -118,22 +139,36 @@ export async function GET(request: Request) {
} else if (kategori == "progress") {
let kondisi
// klo perbekel == semua grup
if (roleUser == "supadmin") {
// klo perbekel/developer == semua grup
if (roleUser == "supadmin" || roleUser == "developer") {
kondisi = {
isActive: true,
Division: {
isActive: true,
idVillage: idVillage,
Group: {
isActive: true,
}
}
}
} else if (roleUser == "admin" || roleUser == "cosupadmin") {
kondisi = {
isActive: true,
Division: {
isActive: true,
idGroup: idGroup
}
}
} else {
kondisi = {
isActive: true,
Division: {
idGroup: idGroup
isActive: true,
DivisionMember: {
some: {
idUser: user.id
}
}
}
}
}
@@ -151,9 +186,10 @@ export async function GET(request: Request) {
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: find
value: fix
}
} else {
input = {
@@ -169,24 +205,39 @@ export async function GET(request: Request) {
} else if (kategori == "dokumen") {
let kondisi
// klo perbekel == semua grup
if (roleUser == "supadmin") {
// klo perbekel/developer == semua grup
if (roleUser == "supadmin" || roleUser == "developer") {
kondisi = {
isActive: true,
category: 'FILE',
Division: {
isActive: true,
idVillage: idVillage,
Group: {
isActive: true,
}
}
}
} else if (roleUser == "admin" || roleUser == "cosupadmin") {
kondisi = {
isActive: true,
category: 'FILE',
Division: {
isActive: true,
idGroup: idGroup
}
}
} else {
kondisi = {
isActive: true,
category: 'FILE',
Division: {
idGroup: idGroup
isActive: true,
DivisionMember: {
some: {
idUser: user.id
}
}
}
}
}
@@ -232,12 +283,13 @@ export async function GET(request: Request) {
} else if (kategori == "event") {
let kondisi
// klo perbekel == semua grup
if (roleUser == "supadmin") {
// klo perbekel/developer == semua grup
if (roleUser == "supadmin" || roleUser == "developer") {
kondisi = {
isActive: true,
dateStart: new Date(),
Division: {
isActive: true,
idVillage: idVillage,
Group: {
isActive: true,
@@ -252,6 +304,7 @@ export async function GET(request: Request) {
isActive: true,
dateStart: new Date(),
Division: {
isActive: true,
idGroup: idGroup
},
DivisionCalendar: {
@@ -274,6 +327,7 @@ export async function GET(request: Request) {
dateEnd: true,
createdAt: true,
status: true,
idDivision: true,
DivisionCalendar: {
select: {
title: true,
@@ -310,24 +364,39 @@ export async function GET(request: Request) {
} else if (kategori == "discussion") {
let kondisi
// klo perbekel == semua grup
if (roleUser == "supadmin") {
// klo perbekel/developer == semua grup
if (roleUser == "supadmin" || roleUser == "developer") {
kondisi = {
isActive: true,
status: 1,
Division: {
isActive: true,
idVillage: idVillage,
Group: {
isActive: true,
}
}
}
} else if (roleUser == "admin" || roleUser == "cosupadmin") {
kondisi = {
isActive: true,
status: 1,
Division: {
idGroup: idGroup,
isActive: true
}
}
} else {
kondisi = {
isActive: true,
status: 1,
Division: {
idGroup: idGroup
isActive: true,
DivisionMember: {
some: {
idUser: user.id
}
}
}
}
}
@@ -355,9 +424,156 @@ export async function GET(request: Request) {
allData = data.map((v: any) => ({
..._.omit(v, ["createdAt", "User"]),
date: moment(v.dateStart).format("ll"),
date: moment(v.createdAt).format("ll"),
user: v.User.name
}))
} else if (kategori == "header") {
const total = await prisma.notifications.count({
where: {
isActive: true,
isRead: false,
idUserTo: user.id
}
})
const desa = await prisma.village.findUnique({
where: {
id: idVillage
}
})
allData = {
totalNotif: total,
village: desa?.name
}
} else if (kategori == "check-late-project") {
const supadmin = await prisma.user.findFirst({
where: {
idUserRole: "supadmin",
idVillage: idVillage
}
})
const dataUmum = await prisma.projectTask.findMany({
where: {
Project: {
idVillage: idVillage,
isActive: true,
status: {
not: {
in: [2, 3]
}
}
},
notifikasi: false,
isActive: true,
status: 0,
dateEnd: {
lt: new Date()
}
},
select: {
id: true,
title: true,
dateEnd: true,
Project: {
select: {
id: true,
},
}
}
})
for (let index = 0; index < dataUmum.length; index++) {
await prisma.projectTask.update({
where: {
id: dataUmum[index].id
},
data: {
notifikasi: true
}
})
}
const pertama = dataUmum.map((v: any) => ({
..._.omit(v, ["Project", "title", "id", "dateEnd"]),
idUserTo: String(supadmin?.id),
idUserFrom: String(user.id),
category: 'project',
idContent: v.Project.id,
title: `Tugas ${v.title} Telah Melewati Batas Waktu`,
desc: `Tugas dengan deadline ${moment(v.dateEnd).format('DD-MM-yyyy')} telah berakhir. Silakan segera melakukan tindakan yang diperlukan.`
}))
const insertNotif = await prisma.notifications.createMany({
data: pertama
})
const dataDivisi = await prisma.divisionProjectTask.findMany({
where: {
Division: {
idVillage: idVillage,
isActive: true
},
DivisionProject: {
isActive: true,
status: {
not: {
in: [2, 3]
}
}
},
notifikasi: false,
isActive: true,
status: 0,
dateEnd: {
lt: new Date()
}
},
select: {
id: true,
title: true,
dateEnd: true,
DivisionProject: {
select: {
id: true,
idDivision: true
},
}
}
})
for (let index = 0; index < dataDivisi.length; index++) {
await prisma.divisionProjectTask.update({
where: {
id: dataDivisi[index].id
},
data: {
notifikasi: true
}
})
}
const kedua = dataDivisi.map((v: any) => ({
..._.omit(v, ["DivisionProject", "title", "id", "dateEnd"]),
idUserTo: String(supadmin?.id),
idUserFrom: String(user.id),
category: 'division/' + v.DivisionProject.idDivision + '/task',
idContent: v.DivisionProject.id,
title: `Tugas ${v.title} Telah Melewati Batas Waktu`,
desc: `Tugas dengan deadline ${moment(v.dateEnd).format('DD-MM-yyyy')} telah berakhir. Silakan segera melakukan tindakan yang diperlukan.`
}))
const insertNotif2 = await prisma.notifications.createMany({
data: kedua
})
const merge = [...pertama, ...kedua]
allData = merge
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: allData }, { status: 200 });
@@ -365,6 +581,6 @@ export async function GET(request: Request) {
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti 99", reason: (error as Error).message, }, { status: 500 });
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,12 +1,9 @@
// SEARCH USER, DIVISION, PROJECT
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import _ from "lodash";
import { NextResponse } from "next/server";
// SEARCH USER, DIVISION, PROJECT
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url)
@@ -16,11 +13,26 @@ export async function GET(request: Request) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
let kondisi: any, kondisiProject: any
let kondisi: any, kondisiProject: any, kondisiDivision: any
// klo perbekel == semua grup
if (userId.idUserRole == "supadmin") {
// klo perbekel/developer == semua grup
if (userId.idUserRole == "supadmin" || userId.idUserRole == "developer") {
kondisi = {
isActive: true,
idVillage: userId.idVillage,
Group: {
isActive: true,
},
name: {
contains: (search == undefined || search == null) ? "" : search,
mode: "insensitive"
},
NOT: {
idUserRole: "developer"
}
}
kondisiDivision = {
isActive: true,
idVillage: userId.idVillage,
Group: {
@@ -45,6 +57,19 @@ export async function GET(request: Request) {
}
} else {
kondisi = {
idVillage: userId.idVillage,
isActive: true,
idGroup: userId.idGroup,
name: {
contains: (search == undefined || search == null) ? "" : search,
mode: "insensitive"
},
NOT: {
idUserRole: "developer"
}
}
kondisiDivision = {
idVillage: userId.idVillage,
isActive: true,
idGroup: userId.idGroup,
@@ -87,12 +112,12 @@ export async function GET(request: Request) {
const userOmit = user.map((v: any) => ({
..._.omit(v, ["Position", "Group"]),
position: v.Position.name,
position: v.Position?.name,
group: v.Group.name
}))
const divisions = await prisma.division.findMany({
where: kondisi,
where: kondisiDivision,
select: {
id: true,
name: true,
@@ -136,6 +161,7 @@ export async function GET(request: Request) {
return NextResponse.json({ success: true, data: allDataSearch }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: error }, { status: 500 });
console.error(error)
return NextResponse.json({ success: false, message: 'Gagal mendapatkan data, coba lagi nanti (error: 500)' }, { status: 500 });
}
}

View File

@@ -0,0 +1,70 @@
import { prisma } from "@/module/_global";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const idVillage = searchParams.get("village");
const dStart = searchParams.get('dateStart');
const dEnd = searchParams.get('dateEnd');
const awalDate = moment(dStart).format('YYYY-MM-DD') + ' 00:00:01'
const akhirDate = moment(dEnd).format('YYYY-MM-DD') + ' 23:59:59'
const data = await prisma.userLog.findMany({
where: {
User: {
idVillage: String(idVillage)
},
createdAt: {
gte: new Date(awalDate),
lte: new Date(akhirDate),
}
},
select: {
User: {
select: {
name: true,
img: true,
UserRole: {
select: {
name: true
}
},
Group: {
select: {
name: true
}
}
}
},
id: true,
createdAt: true,
idUser: true,
action: true,
desc: true,
idContent: true,
tbContent: true,
}
})
const fixData = data.map((v: any) => ({
..._.omit(v, ["createdAt", "User"]),
createdAt: moment(v.createdAt).format("lll").replace("pukul", ""),
userName: v.User.name,
userImg: v.User.img,
userRole: v.User.UserRole.name,
userGroup: v.User.Group.name
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: fixData }, { 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 });
}
}

View File

@@ -0,0 +1,226 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
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 { searchParams } = new URL(request.url);
const user = searchParams.get('user');
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
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,
},
});
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
}))
// const fixMember = Object.groupBy(formatMember, ({ group }) => group);
const fixMember = _.groupBy(formatMember, ({ group }) => group);
return NextResponse.json(
{
success: true,
message: "Berhasil mendapatkan pengumuman",
data: announcement,
member: fixMember
},
{ 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 });
}
}
// HAPUS PENGUMUMAN
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.announcement.count({
where: {
id: id,
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Hapus pengumuman gagal, data tidak ditemukan",
},
{ status: 200 }
);
}
const update = await prisma.announcement.update({
where: {
id: id,
},
data: {
isActive: false,
},
});
// create log user
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User menghapus data pengumuman', table: 'announcement', data: id, user: userMobile.id })
return NextResponse.json(
{
success: true,
message: "Pengumuman berhasil dihapus",
},
{ 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 });
}
}
// EDIT PENGUMUMAN
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const { title, desc, groups, user } = (await request.json());
const { id } = context.params;
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.announcement.count({
where: {
id: id,
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Edit pengumuman gagal, data tidak ditemukan",
},
{ status: 404 }
);
}
const update = await prisma.announcement.update({
where: {
id: id
},
data: {
title,
desc,
},
});
// hapus semua member divisi pengumuman
const hapus = await prisma.announcementMember.deleteMany({
where: {
idAnnouncement: id
}
})
let memberDivision = []
for (var i = 0, l = groups.length; i < l; i++) {
var obj = groups[i].Division;
for (let index = 0; index < obj.length; index++) {
const element = obj[index];
const fix = {
idAnnouncement: id,
idGroup: groups[i].id,
idDivision: element.id
}
memberDivision.push(fix)
}
}
const announcementMember = await prisma.announcementMember.createMany({
data: memberDivision,
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data pengumuman', table: 'announcement', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengupdate pengumuman" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeupdate pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,282 @@
import { funSendWebPush, prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from '@/module/user';
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
import { sendFCMNotificationMany } from "../../../../../xsendMany";
export const dynamic = 'force-dynamic'
// GET ALL PENGUMUMAN
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const name = searchParams.get('search');
const page = searchParams.get('page');
const user = searchParams.get('user');
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const villageId = userMobile.idVillage
const roleUser = userMobile.idUserRole
const groupId = userMobile.idGroup
const dataSkip = Number(page) * 10 - 10;
let kondisi: any = {
idVillage: String(villageId),
isActive: true,
title: {
contains: (name == undefined || name == null) ? "" : name,
mode: "insensitive"
}
}
if (roleUser != "supadmin" && roleUser != "developer") {
if (roleUser == "cosupadmin" || roleUser == "admin") {
kondisi = {
idVillage: String(villageId),
isActive: true,
title: {
contains: (name == undefined || name == null) ? "" : name,
mode: "insensitive"
},
AnnouncementMember: {
some: {
idGroup: String(groupId)
}
}
}
} else {
kondisi = {
idVillage: String(villageId),
isActive: true,
title: {
contains: (name == undefined || name == null) ? "" : name,
mode: "insensitive"
},
AnnouncementMember: {
some: {
idGroup: String(groupId),
Division: {
DivisionMember: {
some: {
idUser: String(userMobile.id)
}
}
}
}
}
}
}
}
const announcements = await prisma.announcement.findMany({
skip: dataSkip,
take: 10,
where: kondisi,
select: {
id: true,
title: true,
desc: true,
createdAt: true,
},
orderBy: {
createdAt: 'desc'
}
});
const allData = announcements.map((v: any) => ({
..._.omit(v, ["createdAt"]),
createdAt: moment(v.createdAt).format("ll")
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan pengumuman", data: allData, }, { 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 });
}
}
// CREATE PENGUMUMAN
export async function POST(request: Request) {
try {
const { title, desc, groups, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const villaId = userMobile.idVillage
const userId = userMobile.id
const userRoleLogin = userMobile.idUserRole
const data = await prisma.announcement.create({
data: {
title,
desc,
idVillage: String(villaId),
createdBy: String(userId),
},
select: {
id: true,
}
});
let memberDivision = []
for (var i = 0, l = groups.length; i < l; i++) {
2
var obj = groups[i].Division;
for (let index = 0; index < obj.length; index++) {
const element = obj[index];
const fix = {
idAnnouncement: data.id,
idGroup: groups[i].id,
idDivision: element.id
}
memberDivision.push(fix)
}
}
const announcementMember = await prisma.announcementMember.createMany({
data: memberDivision,
});
const memberNotif = await prisma.divisionMember.findMany({
where: {
Division: {
AnnouncementMember: {
some: {
idAnnouncement: data.id
}
}
}
},
select: {
idUser: true,
User: {
select: {
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
}
}
})
// mengirim notifikasi
// dataFCM untuk push notifikasi mobile
// datanotif untuk realtime notifikasi
// datapush untuk web push notifikasi ketika aplikasi tidak aktif
const dataFCM = memberNotif.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]),
tokens: v.User.TokenDeviceUser.map((v: any) => v.token)
}))
const tokenDup = dataFCM.filter((v: any) => v.tokens.length > 0).map((v: any) => v.tokens).flat();
const dataNotif = memberNotif.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]),
idUserTo: v.idUser,
idUserFrom: userId,
category: 'announcement',
idContent: data.id,
title: 'Pengumuman Baru',
desc: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.'
}))
const dataPush = memberNotif.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]),
idUser: v.idUser,
subscription: v.User.Subscribe?.subscription,
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: user.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
})
tokenDup.push(perbekel?.TokenDeviceUser.map((v: any) => v.token).flat())
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'announcement',
idContent: data.id,
title: 'Pengumuman Baru',
desc: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: perbekel?.id,
subscription: perbekel?.Subscribe?.subscription
})
}
const pushNotif = dataPush.filter((item) => item.subscription != undefined)
const sendWebPush = await funSendWebPush({ sub: pushNotif, message: { title: 'Pengumuman Baru', body: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.' } })
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
const tokenUnique = [...new Set(tokenDup.flat())];
await sendFCMNotificationMany({
token: tokenUnique,
title: "Pengumuman Baru",
body: "Anda memiliki pengumuman baru. Silahkan periksa detailnya.",
data: { id: data.id, category: "announcement", content: data.id }
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User membuat data pengumuman baru', table: 'announcement', data: data.id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil membuat pengumuman" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal membuat pengumuman, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,68 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import { NextResponse } from "next/server";
export async function POST(request: Request) {
try {
const { token, user } = (await request.json());
const userMobile = await funGetUserById({ id: user })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.tokenDeviceUser.count({
where: {
idUser: userMobile.id,
token
}
})
// create log user
const log = await createLogUserMobile({ act: 'LOGIN', desc: 'User login', table: 'user', data: '', user: userMobile.id })
if (cek == 0) {
const data = await prisma.tokenDeviceUser.create({
data: {
token,
idUser: userMobile.id
}
});
return NextResponse.json({ success: true, message: "Berhasil mendaftarkan token" }, { status: 200 });
}
return NextResponse.json({ success: true, message: "Token sudah terdaftar" }, { status: 200 })
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan token, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};
export async function PUT(request: Request) {
try {
const { token, user } = (await request.json());
const userMobile = await funGetUserById({ id: user })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.tokenDeviceUser.deleteMany({
where: {
token,
idUser: userMobile.id
}
});
// create log user
const log = await createLogUserMobile({ act: 'LOGOUT', desc: 'User logout', table: 'user', data: '', user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil menghapus token", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menghapus token, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -0,0 +1,118 @@
import { DIR, funDeleteFile, funUploadFile, prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import { NextResponse } from "next/server";
// GET ONE BANNER
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const { searchParams } = new URL(request.url);
const user = searchParams.get("user")
const userLogin = await funGetUserById({ id: String(user) })
if (userLogin.id == "null" || userLogin.id == undefined || userLogin.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
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 });
}
}
// DELETE BANNER
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const { user } = (await request.json());
const userLogin = await funGetUserById({ id: user })
if (userLogin.id == "null" || userLogin.id == undefined || userLogin.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const upd = await prisma.bannerImage.update({
where: {
id: String(id)
},
data: {
isActive: false
}
})
// create log user
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User menghapus banner', table: 'bannerImage', data: id, user: String(userLogin.id) })
return NextResponse.json({ success: true, message: "Berhasil menghapus banner" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menghapus banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// UPDATE BANNER
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const body = await request.formData()
const file = body.get("file") as File
const data = body.get("data")
const { title, user } = JSON.parse(data as string)
const userLogin = await funGetUserById({ id: user })
if (userLogin.id == "null" || userLogin.id == undefined || userLogin.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const upd = await prisma.bannerImage.update({
where: {
id: String(id)
},
data: {
title
},
select: {
image: true
}
})
if (String(file) != "undefined" && String(file) != "null") {
const fExt = file.name.split(".").pop()
const fileName = id + '.' + fExt;
const newFile = new File([file], fileName, { type: file.type });
await funDeleteFile({ fileId: String(upd.image) })
const upload = await funUploadFile({ file: newFile, dirId: DIR.banner })
await prisma.bannerImage.update({
where: {
id: id
},
data: {
image: upload.data.id
}
})
}
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data banner', table: 'bannerImage', data: id, user: String(userLogin.id) })
return NextResponse.json({ success: true, message: "Berhasil mengupdate banner" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengupdate banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,80 @@
import { DIR, funUploadFile, prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import { NextResponse } from "next/server";
// GET ALL BANNER
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url)
const userMobile = searchParams.get("user")
if (userMobile == "null" || userMobile == undefined || userMobile == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const user = await funGetUserById({ id: userMobile })
const data = await prisma.bannerImage.findMany({
where: {
isActive: true,
idVillage: user.idVillage
},
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 });
}
}
// CREATE BANNER
export async function POST(request: Request) {
try {
const body = await request.formData()
const file = body.get("file") as File;
const data = body.get("data");
const { title, user } = JSON.parse(data as string)
const userLogin = await funGetUserById({ id: user })
if (userLogin.id == "null" || userLogin.id == undefined || userLogin.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const fExt = file.name.split(".").pop()
const newFile = new File([file], file.name, { type: file.type });
const upload = await funUploadFile({ file: newFile, dirId: DIR.banner })
if (upload.success) {
const create = await prisma.bannerImage.create({
data: {
title: title,
idVillage: userLogin.idVillage,
extension: String(fExt),
image: upload.data.id
},
select: {
id: true,
}
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User menambah data banner baru', table: 'bannerImage', data: String(create.id), user: String(userLogin.id) })
return Response.json({ success: true, message: 'Sukses menambah data banner' }, { status: 200 });
} else {
return Response.json({ success: false, message: 'Gagal menambah data banner' }, { status: 200 });
}
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan banner, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,174 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
// GET ONE DATA KALENDER BY ID KALENDER
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { searchParams } = new URL(request.url);
const user = searchParams.get("user");
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.divisionCalendar.count({
where: {
id: id
}
})
if (cek == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan kalender, data tidak ditemukan",
},
{ status: 200 }
);
}
const data = await prisma.divisionCalendar.findUnique({
where: {
id: id
},
select: {
id: true,
title: true,
desc: true,
timeStart: true,
dateStart: true,
timeEnd: true,
createdAt: true,
linkMeet: true,
repeatValue: true,
repeatEventTyper: true,
}
});
const { ...dataCalender } = data
const timeStart = moment.utc(dataCalender?.timeStart).format("HH:mm")
const timeEnd = moment.utc(dataCalender?.timeEnd).format("HH:mm")
const result = { ...dataCalender, timeStart, timeEnd }
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kalender", data: result }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan (error: 500)", }, { status: 500 }
);
}
}
// TAMBAH MEMBER KALENDER
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { member, user } = await request.json()
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.divisionCalendar.count({
where: {
id: id
}
})
if (cek == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal menambahkan anggota, data tidak ditemukan",
},
{ status: 200 }
);
}
if (member.length > 0) {
const dataMember = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idCalendar: id,
idUser: v.idUser,
}))
const insertMember = await prisma.divisionCalendarMember.createMany({
data: dataMember
})
}
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User menambah anggota kalender', table: 'divisionCalendar', data: String(id), user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambah anggota, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// MENGELUARKAN ANGGOTA
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const { idUser, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.divisionCalendar.count({
where: {
id: id,
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal mengeluarkan anggota, data tidak ditemukan",
},
{ status: 200 }
);
}
const del = await prisma.divisionCalendarMember.deleteMany({
where: {
idUser: idUser,
idCalendar: id
}
})
// create log user
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User mengeluarkan anggota acara kalender', table: 'divisionCalendar', data: String(id), user: userMobile.id })
return NextResponse.json(
{
success: true,
message: "Berhasil mengeluarkan anggota",
},
{ status: 200 }
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,267 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
import { Frequency, RRule } from 'rrule';
// GET ONE CALENDER BY ID KALENDER REMINDER
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { searchParams } = new URL(request.url);
const user = searchParams.get("user");
const kategori = searchParams.get("cat");
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
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: 200 }
);
}
let dataFix
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,
}
}
}
});
if (kategori == "data") {
const { DivisionCalendar, ...dataCalender } = data
const timeStart = moment.utc(dataCalender?.timeStart).format("HH:mm")
const timeEnd = moment.utc(dataCalender?.timeEnd).format("HH:mm")
const dateStart = moment.utc(dataCalender?.dateStart).format("LL")
const dateStartFormat = moment.utc(dataCalender?.dateStart).format("DD-MM-YYYY")
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
dataFix = { ...dataCalender, timeStart, timeEnd, dateStart, dateStartFormat, idCalendar, title, desc, linkMeet, repeatEventTyper, repeatValue }
} else if (kategori == "member") {
const member = await prisma.divisionCalendarMember.findMany({
where: {
idCalendar: data?.DivisionCalendar.id
},
select: {
id: true,
idUser: true,
User: {
select: {
id: true,
name: true,
email: true,
img: true
}
}
}
})
dataFix = member.map((v: any) => ({
..._.omit(v, ["User"]),
name: v.User.name,
email: v.User.email,
img: v.User.img
}))
}
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 });
}
}
// DELETE CALENDER BY ID
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { user } = (await request.json())
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.divisionCalendar.count({
where: {
id: id
}
})
if (cek == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal menghapus acara kalender, data tidak ditemukan",
},
{ status: 200 }
);
}
const data = await prisma.divisionCalendar.update({
where: {
id: id
},
data: {
isActive: false
},
select: {
dateStart: true
}
});
// create log user
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User menghapus data acara kalender', table: 'divisionCalendar', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil menghapus acara kalender", data, user: user.id }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: "Gagal menghapus kalender, coba lagi nanti (error: 500)", }, { status: 500 }
);
}
}
// EDIT CALENDER BY IDKALENDER
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { title, desc, timeStart, dateStart, timeEnd, linkMeet, repeatEventTyper, repeatValue, user } = await request.json()
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const userId = userMobile.id
const cek = await prisma.divisionCalendar.count({
where: {
id: id
}
})
if (cek == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal mengedit acara, data tidak ditemukan",
},
{ status: 200 }
);
}
const dateStartFix = moment(dateStart, 'DD-MM-YYYY').format('YYYY-MM-DD')
const y = new Date('1970-01-01 ' + timeStart)
const x = new Date('1970-01-01 ' + timeEnd)
const timeStartFix = new Date(y.getTime() - (y.getTimezoneOffset() * 60000)).toISOString()
const timeEndFix = new Date(x.getTime() - (x.getTimezoneOffset() * 60000)).toISOString()
const statusCalender = 0
const data = await prisma.divisionCalendar.update({
where: {
id: id
},
data: {
title: title,
desc: desc,
createdBy: String(userId),
timeStart: timeStartFix,
dateStart: new Date(dateStartFix),
timeEnd: timeEndFix,
linkMeet: linkMeet,
repeatEventTyper: repeatEventTyper,
status: statusCalender,
repeatValue: Number(repeatValue)
},
select: {
idDivision: true
}
});
const freq: Frequency = repeatEventTyper === "yearly" ? RRule.YEARLY :
repeatEventTyper === "monthly" ? RRule.MONTHLY :
repeatEventTyper === "weekly" ? RRule.WEEKLY :
repeatEventTyper === "daily" ? RRule.DAILY :
repeatEventTyper === "hourly" ? RRule.HOURLY :
repeatEventTyper === "minutely" ? RRule.MINUTELY :
RRule.SECONDLY;
const rule = new RRule({
freq,
interval: 1,
dtstart: new Date(dateStartFix),
count: repeatValue
});
const hasil = rule.all().map(recurrenceDate => ({
idDivision: data.idDivision,
idCalendar: id,
dateStart: recurrenceDate,
timeStart: timeStartFix,
timeEnd: timeEndFix,
dateEnd: recurrenceDate
}));
const deleteReminder = await prisma.divisionCalendarReminder.deleteMany({
where: {
idCalendar: id
}
})
const insertReminder = await prisma.divisionCalendarReminder.createMany({
data: hasil
})
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data acara kalender', table: 'divisionCalendar', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengedit acara" }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: "Gagal mengedit acara, coba lagi nanti (error: 500)", }, { status: 500 }
);
}
}

View File

@@ -0,0 +1,115 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
// GET HISTORY
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const idDivision = searchParams.get("division");
const name = searchParams.get('search');
const page = searchParams.get('page');
const user = searchParams.get('user');
const dataSkip = Number(page) * 10 - 10;
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
if (idDivision != "null" && idDivision != null && idDivision != undefined && idDivision != "" && idDivision != "undefined") {
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
// isActive: true
}
})
if (cekDivision == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 200 });
}
const data = await prisma.divisionCalendarReminder.findMany({
skip: dataSkip,
take: 10,
where: {
isActive: true,
idDivision: idDivision,
dateEnd: {
lte: new Date()
},
DivisionCalendar: {
title: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
},
isActive: true
}
},
select: {
id: true,
timeStart: true,
dateStart: true,
timeEnd: true,
DivisionCalendar: {
select: {
title: true,
}
}
},
orderBy: [
{
dateStart: 'desc'
},
{
timeStart: 'asc'
},
{
timeEnd: 'asc'
}
]
});
const allOmit = data.map((v: any) => ({
..._.omit(v, ["DivisionCalendar", "dateStart"]),
dateStart: moment.utc(v.dateStart).format("DD MMM"),
year: moment.utc(v.dateStart).format("YYYY"),
title: v.DivisionCalendar.title,
}))
// groupBy untuk dateStart
const groupByDateStart = _.groupBy(allOmit, 'dateStart');
const result = Object.keys(groupByDateStart).map(key => {
const obj = groupByDateStart[key];
const year = obj[0].year
const data = obj.map((v: any) => ({
id: v.id,
title: v.title,
timeEnd: moment.utc(v.timeEnd).format('HH:mm'),
timeStart: moment.utc(v.timeStart).format('HH:mm')
}))
return {
dateStart: key,
year: year,
data: data
}
})
return NextResponse.json({ success: true, message: "Berhasil mendapatkan riwayat acara kalender", data: result }, { status: 200 });
} else {
return NextResponse.json({ success: false, message: "Gagal mendapatkan riwayat acara kalender, coba lagi nanti" }, { status: 200 });
}
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal mendapatkan riwayat acara kalender, coba lagi nanti (error: 500)" }, { status: 500 });
}
}

View File

@@ -0,0 +1,68 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const idDivision = searchParams.get("division");
const date = searchParams.get("date");
const user = searchParams.get("user");
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const awalDate = moment(date).format('YYYY-MM') + '-01'
const akhirDate = moment(awalDate).add(1, 'M').format('YYYY-MM-DD')
const cekDivision = await prisma.division.count({
where: {
id: String(idDivision),
// isActive: true
}
})
if (cekDivision == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 200 });
}
const data = await prisma.divisionCalendarReminder.findMany({
where: {
isActive: true,
idDivision: String(idDivision),
dateStart: {
gte: new Date(awalDate),
lte: new Date(akhirDate),
},
DivisionCalendar: {
isActive: true
}
}
})
const dataGroup = _.map(_.groupBy(data, "dateStart"), (v: any) => ({
dateContent: v[0].dateStart
}))
const result = dataGroup.map(a => moment(a.dateContent).format('YYYY-MM-DD'));
return NextResponse.json({ success: true, message: "Berhasil mendapatkan list acara", data: result }, { status: 200 });
} catch (error) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan list acara (error: 500)" }, { status: 500 });
}
}

View File

@@ -0,0 +1,310 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from '@/module/user';
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
import { Frequency, RRule } from 'rrule';
//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 user = searchParams.get("user")
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
if (idDivision != "null" && idDivision != null && idDivision != undefined && idDivision != "") {
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
// isActive: true
}
})
if (cekDivision == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 200 });
}
const data = await prisma.divisionCalendarReminder.findMany({
where: {
isActive: true,
idDivision: idDivision,
dateStart: new Date(String(isDate)),
DivisionCalendar: {
isActive: true
}
},
select: {
id: true,
idCalendar: true,
timeStart: true,
dateStart: true,
timeEnd: true,
dateEnd: true,
createdAt: true,
status: true,
DivisionCalendar: {
select: {
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,
user_name: v.DivisionCalendar.User.name,
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 });
} else {
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan" }, { status: 200 });
}
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal mendapatkan kalender, data tidak ditemukan (error: 500)" }, { status: 500 });
}
}
//CREATE CALENDER
export async function POST(request: Request) {
try {
const { idDivision, title, desc, timeStart, timeEnd, dateStart, dateEnd, repeatEventType, member, linkMeet, repeatValue, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const userId = userMobile.id
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
isActive: true
}
})
if (cekDivision == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 200 });
}
const y = new Date('1970-01-01 ' + timeStart)
const x = new Date('1970-01-01 ' + timeEnd)
const timeStartFix = new Date(y.getTime() - (y.getTimezoneOffset() * 60000)).toISOString()
const timeEndFix = new Date(x.getTime() - (x.getTimezoneOffset() * 60000)).toISOString()
const dateStartFix = moment(dateStart, 'DD-MM-YYYY').format('YYYY-MM-DD')
const data = await prisma.divisionCalendar.create({
data: {
idDivision,
createdBy: String(userId),
title,
dateStart: new Date(dateStartFix),
timeStart: timeStartFix,
timeEnd: timeEndFix,
linkMeet,
repeatEventTyper: repeatEventType,
desc,
repeatValue: Number(repeatValue)
},
select: {
id: true,
}
});
const freq: Frequency = repeatEventType === "yearly" ? RRule.YEARLY :
repeatEventType === "monthly" ? RRule.MONTHLY :
repeatEventType === "weekly" ? RRule.WEEKLY :
repeatEventType === "daily" ? RRule.DAILY :
repeatEventType === "hourly" ? RRule.HOURLY :
repeatEventType === "minutely" ? RRule.MINUTELY :
RRule.SECONDLY;
const rule = new RRule({
freq,
interval: 1,
dtstart: new Date(dateStartFix),
count: repeatValue
});
const hasil = rule.all().map(recurrenceDate => ({
idDivision: idDivision,
idCalendar: data.id,
dateStart: recurrenceDate,
timeStart: timeStartFix,
timeEnd: timeEndFix,
dateEnd: recurrenceDate
}));
const insertReminder = await prisma.divisionCalendarReminder.createMany({
data: hasil
})
const omitMember = member.map((v: any) => ({
..._.omit(v, ["name", "idUser", "img"]),
idCalendar: data.id,
idUser: v.idUser
}))
const insertMember = await prisma.divisionCalendarMember.createMany({
data: omitMember
});
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User membuat data acara kalender', table: 'divisionCalendar', data: data.id, user: String(userId) })
return NextResponse.json({ success: true, message: "Berhasil membuat acara kalender" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal membuat acara kalender, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// CEK TGL AVAILABLE
export async function PUT(request: Request) {
try {
const { idDivision, title, desc, timeStart, timeEnd, dateStart, dateEnd, repeatEventTyper, member, linkMeet, repeatValue, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const userId = userMobile.id
const division = await prisma.division.findUnique({
where: {
id: idDivision
}
})
const y = new Date('1970-01-01 ' + timeStart)
const x = new Date('1970-01-01 ' + timeEnd)
const timeStartFix = new Date(y.getTime() - (y.getTimezoneOffset() * 60000)).toISOString()
const timeEndFix = new Date(x.getTime() - (x.getTimezoneOffset() * 60000)).toISOString()
const cek = await prisma.divisionCalendarReminder.findMany({
where: {
isActive: true,
Division: {
idGroup: division?.idGroup
},
OR: [
{
dateStart: new Date(dateStart),
DivisionCalendar: {
title: {
equals: title,
mode: "insensitive"
},
}
},
{
dateStart: new Date(dateStart),
OR: [
{
timeStart: { //13:00
lte: timeStartFix, //13:30
},
timeEnd: { //14:00
gt: timeStartFix, //13:30
}
},
{
timeStart: { //07:00
lt: timeEndFix, //07:30
},
timeEnd: { //08:00
gt: timeEndFix, //07:30
}
},
{
timeStart: { //07:00
gt: timeStartFix, //06:30
},
timeEnd: { //08:00
lte: timeEndFix, //09:30
}
}
]
}
]
},
select: {
id: true,
dateStart: true,
timeStart: true,
timeEnd: true,
DivisionCalendar: {
select: {
title: true,
}
},
Division: {
select: {
name: true
}
}
}
})
const dataSama = cek.map((v: any) => ({
..._.omit(v, ["DivisionCalendar", "Division"]),
title: v.DivisionCalendar.title,
divisi: v.Division.name
}))
if (cek.length > 0) {
return NextResponse.json({ success: false, message: "Tidak dapat membuat acara kalender, acara kalender sudah ada pada tanggal tersebut", data: dataSama }, { status: 400 });
} else {
return NextResponse.json({ success: true, message: "Berhasil membuat acara kalender" }, { status: 200 });
}
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal membuat acara kalender, coba lagi nanti (error: 500)" }, { status: 500 });
}
}

View File

@@ -0,0 +1,46 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import { NextResponse } from "next/server";
// KIRIM KOMENTAR DISKUSI UMUM
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { desc, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.discussion.count({
where: {
id,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal menambahkan komentar, data tidak ditemukan" }, { status: 200 });
}
const data = await prisma.discussionComment.create({
data: {
comment: desc,
idDiscussion: id,
idUser: userMobile.id
}
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User menambah komentar pada diskusi umum', table: 'discussionComment', data: data.id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil menambah komentar" }, { status: 200 });
} catch (error) {
console.error(error)
return NextResponse.json({ success: false, message: "Gagal menambahkan komentar, coba lagi nanti (error: 500)" })
}
}

View File

@@ -0,0 +1,94 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import { NextResponse } from "next/server";
// ADD MEMBER DISCUSSION GENERAL
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { member, user } = (await request.json())
const userMobile = await funGetUserById({ id: user })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.discussion.count({
where: {
id,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal menambahkan anggota, data tidak ditemukan" }, { status: 200 });
}
if (member.length > 0) {
const dataMember = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idDiscussion: id,
idUser: v.idUser
}))
const insertMember = await prisma.discussionMember.createMany({
data: dataMember
})
}
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User menambah anggota diskusi umum', table: 'discussion', data: String(id), user: String(userMobile.id) })
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan anggota, coba lagi nanti (error : 500)" }, { status: 500 });
}
}
// MENGELUARKAN ANGGOTA
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { idUser, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.discussion.count({
where: {
id,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal, data tidak ditemukan" }, { status: 200 });
}
const deleteMember = await prisma.discussionMember.deleteMany({
where: {
idDiscussion: id,
idUser
}
})
// create log user
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User mengeluarkan anggota diskusi umum', table: 'discussion', data: String(id), user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengeluarkan anggota diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota, coba lagi nanti (error : 500)" }, { status: 500 });
}
}

View File

@@ -0,0 +1,280 @@
import { countTime, prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
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 userMobile = searchParams.get("user");
const user = await funGetUserById({ id: String(userMobile) })
if (user.id == "null" || user.id == undefined || user.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const cek = await prisma.discussion.count({
where: {
id
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, data tidak ditemukan" }, { status: 404 });
}
if (kategori == "detail") {
const data = await prisma.discussion.findUnique({
where: {
id,
},
select: {
isActive: true,
id: true,
title: true,
idGroup: true,
desc: true,
status: true,
createdAt: true,
}
})
dataFix = {
id: data?.id,
isActive: data?.isActive,
idGroup: data?.idGroup,
title: data?.title,
desc: data?.desc,
status: data?.status,
createdAt: moment(data?.createdAt).format("ll"),
}
} else if (kategori == "komentar") {
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, ["createdAt", "User",]),
createdAt: countTime(v.createdAt),
username: v.User.name,
img: v.User.img
}))
} else if (kategori == "anggota") {
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 if (kategori == "cek-anggota") {
const cek = await prisma.discussionMember.count({
where: {
idDiscussion: id,
isActive: true,
idUser: user.id
}
})
if (cek > 0) {
dataFix = true
} else {
dataFix = false
}
}
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 });
}
}
// OPEN OR CLOSE DISKUSI UMUM
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { status, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
let newStatus;
if (status === 1) {
newStatus = 2;
} else if (status === 2) {
newStatus = 1;
} else {
return NextResponse.json({ success: false, message: "Invalid status" }, { status: 200 });
}
const data = await prisma.discussion.count({
where: {
id: id
},
});
if (data == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, data tidak ditemukan" }, { status: 200 });
}
const result = await prisma.discussion.update({
where: {
id
},
data: {
status: newStatus
}
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate status diskusi umum', table: 'discussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi umum, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// DELETE DISCUSSION
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { active, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.discussion.count({
where: {
id: id
},
});
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal menghapus diskusi umum, data tidak ditemukan" }, { status: 200 });
}
const data = await prisma.discussion.update({
where: {
id
},
data: {
isActive: active
}
});
// create log user
if (active) {
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User mengaktifkan data diskusi umum', table: 'disscussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengaktifkan diskusi umum", user: user.id }, { status: 200 });
} else {
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User mengarsipkan data diskusi umum', table: 'disscussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengarsipkan diskusi umum", user: user.id }, { status: 200 });
}
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah diskusi umum, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// EDIT DISCUSSION
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { title, desc, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.discussion.count({
where: {
id: id
},
});
if (data == 0) {
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi umum, data tidak ditemukan" }, { status: 200 });
}
const update = await prisma.discussion.update({
where: {
id
},
data: {
desc,
title
}
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data diskusi umum', table: 'discussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi umum" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi umum, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,233 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
import { sendFCMNotificationMany } from "../../../../../xsendMany";
// GET ALL DISCUSSION GENERAL
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const user = searchParams.get("user")
if (user == "null" || user == undefined || user == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const userMobile = await funGetUserById({ id: user })
let grup
const villageId = userMobile.idVillage
const idGroup = searchParams.get("group");
const search = searchParams.get('search');
const page = searchParams.get('page');
const status = searchParams.get('active');
const dataSkip = Number(page) * 10 - 10;
if (idGroup == "null" || idGroup == undefined || idGroup == "" || idGroup == "undefined") {
grup = userMobile.idGroup
} else {
grup = idGroup
}
const cek = await prisma.group.count({
where: {
id: grup,
isActive: true
}
})
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan data kegiatan, data tidak ditemukan", }, { status: 200 });
}
const data = await prisma.discussion.findMany({
skip: dataSkip,
take: 10,
where: {
isActive: status == "false" ? false : true,
idVillage: String(villageId),
idGroup: grup,
title: {
contains: (search == undefined || search == "null") ? "" : search,
mode: "insensitive"
},
},
orderBy: [
{
status: 'desc'
},
{
createdAt: 'desc'
}
],
select: {
id: true,
title: true,
desc: true,
status: true,
createdAt: true,
DiscussionComment: {
select: {
id: true,
}
}
}
});
const fixData = data.map((v: any) => ({
..._.omit(v, ["DiscussionComment", "createdAt"]),
total_komentar: v.DiscussionComment.length,
createdAt: moment(v.createdAt).format("ll")
}))
const filter = await prisma.group.findUnique({
where: {
id: grup
},
select: {
id: true,
name: true
}
})
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: fixData, filter }, { 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 });
}
}
// CREATE DISCUSSION GENERALE
export async function POST(request: Request) {
try {
const { idGroup, user, title, desc, member } = await request.json();
if (user == "null" || user == undefined || user == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const userMobile = await funGetUserById({ id: user })
const userId = user
const userRoleLogin = userMobile.idUserRole
const data = await prisma.discussion.create({
data: {
idVillage: String(userMobile.idVillage),
idGroup: idGroup,
title: title,
desc: desc,
createdBy: String(userId),
},
select: {
id: true
}
});
const dataMember = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idDiscussion: data.id,
idUser: v.idUser,
}))
const insertMember = await prisma.discussionMember.createMany({
data: dataMember
})
const memberNotifMobile = await prisma.discussionMember.findMany({
where: {
idDiscussion: data.id
},
select: {
User: {
select: {
TokenDeviceUser: {
select: {
token: true
}
}
}
}
}
})
const dataFCM = memberNotifMobile.map((v: any) => ({
..._.omit(v, ["User", "TokenDeviceUser"]),
tokens: v.User.TokenDeviceUser.map((v: any) => v.token)
}))
const tokenDup = dataFCM.filter((v: any) => v.tokens.length > 0).map((v: any) => v.tokens).flat();
const dataNotif = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idUserTo: v.idUser,
idUserFrom: userId,
category: 'discussion',
idContent: data.id,
title: 'Diskusi Umum Baru',
desc: 'Terdapat diskusi umum baru. Silahkan periksa detailnya.'
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: user.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
})
tokenDup.push(perbekel?.TokenDeviceUser.map((v: any) => v.token).flat())
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'discussion',
idContent: data.id,
title: 'Diskusi Umum Baru',
desc: 'Terdapat diskusi umum baru. Silahkan periksa detailnya.'
})
}
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
const tokenUnique = [...new Set(tokenDup.flat())];
await sendFCMNotificationMany({
token: tokenUnique,
title: "Diskusi Umum Baru",
body: "Anda memiliki diskusi umum baru. Silahkan periksa detailnya.",
data: { id: data.id, category: "discussion", content: data.id }
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User membuat data diskusi umum', table: 'discussion', data: data.id, user })
return NextResponse.json({ success: true, message: "Berhasil menambahkan diskusi umum", notif: dataNotif }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,54 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import { NextResponse } from "next/server";
// CREATE COMENT BY ID KOMENTAR
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { comment, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "User tidak ditemukan" }, { status: 200 });
}
const cek = await prisma.divisionDisscussion.count({
where: {
id: id
}
})
if (cek == 0) {
return NextResponse.json(
{
success: false,
message: "Tambah komentar gagal, data tidak ditemukan",
},
{ status: 200 }
);
}
const data = await prisma.divisionDisscussionComment.create({
data: {
comment: comment,
idDisscussion: id,
createdBy: userMobile.id
},
select: {
id: true
}
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User menambah komentar pada diskusi', table: 'divisionDisscussionComment', data: data.id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil menambah komentar" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambah komentar, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,241 @@
import { countTime, prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
// GET ONE DISCUSSION BY ID
export async function GET(request: Request, context: { params: { id: string } }) {
const { id } = context.params
const { searchParams } = new URL(request.url);
const user = searchParams.get("user");
const cat = searchParams.get("cat");
const userMobile = await funGetUserById({ id: String(user) })
try {
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.divisionDisscussion.count({
where: {
id: id
}
})
if (cek == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan diskusi, data tidak ditemukan",
},
{ status: 404 }
);
}
if (cat == "comment") {
const data = await prisma.divisionDisscussionComment.findMany({
where: {
idDisscussion: id
},
select: {
id: true,
comment: true,
createdAt: true,
User: {
select: {
name: true,
img: true
}
}
}
})
const omitMember = data.map((v: any) => ({
..._.omit(v, ["User", "createdAt"]),
username: v.User.name,
img: v.User.img,
createdAt: countTime(v.createdAt),
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan komentar", data: omitMember }, { status: 200 });
} else {
const data = await prisma.divisionDisscussion.findUnique({
where: {
id: id
},
select: {
isActive: true,
id: true,
title: true,
desc: true,
status: true,
createdAt: true,
createdBy: true,
User: {
select: {
name: true,
img: true
}
}
}
});
const { ...userMember } = _.omit(data, ["User", "createdAt"])
const username = data?.User.name
const user_img = data?.User.img
const createdAt = moment(data?.createdAt).format("ll")
const isCreator = data?.createdBy == userMobile.id
const result = { ...userMember, username, createdAt, user_img, isCreator }
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 });
}
}
// OPEN OR CLOSE DISCUSSION
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { status, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
let newStatus;
if (status === 1) {
newStatus = 2;
} else if (status === 2) {
newStatus = 1;
} else {
return NextResponse.json({ success: false, message: "Invalid status" }, { status: 200 });
}
const data = await prisma.divisionDisscussion.count({
where: {
id: id
},
});
if (data == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan diskusi, data tidak ditemukan" }, { status: 404 });
}
const result = await prisma.divisionDisscussion.update({
where: {
id: id
},
data: {
status: newStatus
}
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate status diskusi', table: 'divisionDisscussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// DELETE DISCUSSION
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { active, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const cek = await prisma.divisionDisscussion.count({
where: {
id: id
},
});
if (cek == 0) {
return NextResponse.json({ success: false, message: "Gagal mengarsipkan diskusi, data tidak ditemukan" }, { status: 200 });
}
const data = await prisma.divisionDisscussion.update({
where: {
id: id
},
data: {
isActive: active
}
});
// create log user
if (active) {
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User mengaktifkan data diskusi', table: 'divisionDisscussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengaktifkan diskusi", user: userMobile.id }, { status: 200 });
} else {
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User mengarsipkan data diskusi', table: 'divisionDisscussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengarsipkan diskusi", user: userMobile.id }, { status: 200 });
}
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// EDIT DISCUSSION
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const { title, desc, user } = (await request.json())
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.divisionDisscussion.count({
where: {
id: id
},
});
if (data == 0) {
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi, data tidak ditemukan" }, { status: 200 });
}
const update = await prisma.divisionDisscussion.update({
where: {
id: id
},
data: {
desc: desc
}
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data diskusi', table: 'divisionDisscussion', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,287 @@
import { funSendWebPush, prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
import { sendFCMNotificationMany } from "../../../../../xsendMany";
// 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 name = searchParams.get('search');
const page = searchParams.get('page');
const status = searchParams.get('active');
const user = searchParams.get('user');
const dataSkip = Number(page) * 10 - 10;
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
if (idDivision != "null" && idDivision != null && idDivision != undefined) {
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
// isActive: true
}
})
if (cekDivision == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 404 });
}
const data = await prisma.divisionDisscussion.findMany({
skip: dataSkip,
take: 10,
where: {
isActive: status == "false" ? false : true,
idDivision: idDivision,
desc: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
},
},
orderBy: {
createdAt: 'desc'
},
select: {
id: true,
title: true,
desc: true,
status: true,
createdAt: true,
User: {
select: {
name: true,
img: true
}
},
DivisionDisscussionComment: {
select: {
id: true,
}
}
}
});
const fixData = data.map((v: any) => ({
..._.omit(v, ["User", "DivisionDisscussionComment", "createdAt"]),
user_name: v.User.name,
img: v.User.img,
total_komentar: v.DivisionDisscussionComment.length,
createdAt: moment(v.createdAt).format("ll")
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: fixData, }, { status: 200 });
} else {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { 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 });
}
}
// CREATE DISCUSSION
export async function POST(request: Request) {
try {
const { idDivision, desc, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const userRoleLogin = userMobile.idUserRole
const userId = userMobile.id
const cekDivision = await prisma.division.count({
where: {
id: idDivision,
isActive: true
}
})
if (cekDivision == 0) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 404 });
}
const data = await prisma.divisionDisscussion.create({
data: {
idDivision,
desc,
createdBy: userId
},
select: {
id: true
}
});
const memberDivision = await prisma.divisionMember.findMany({
where: {
idDivision: idDivision
},
select: {
User: {
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
}
}
})
// mengirim notifikasi
// dataFCM untuk push notifikasi mobile
// datanotif untuk realtime notifikasi
// datapush untuk web push notifikasi ketika aplikasi tidak aktif
const dataFCM = memberDivision.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]),
tokens: v.User.TokenDeviceUser.map((v: any) => v.token)
}))
const tokenDup = dataFCM.filter((v: any) => v.tokens.length > 0).map((v: any) => v.tokens).flat();
const dataNotif = memberDivision.map((v: any) => ({
..._.omit(v, ["User", "Subscribe", "TokenDeviceUser"]),
idUserTo: v.User.id,
idUserFrom: String(userId),
category: 'division/' + idDivision + '/discussion',
idContent: data.id,
title: 'Diskusi Baru',
desc: 'Terdapat diskusi baru. Silahkan periksa detailnya.'
}))
const dataPush = memberDivision.map((v: any) => ({
..._.omit(v, ["User", "Subscribe", "TokenDeviceUser"]),
idUser: v.User.id,
subscription: v.User.Subscribe?.subscription,
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: userMobile.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
})
tokenDup.push(perbekel?.TokenDeviceUser.map((v: any) => v.token).flat())
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'division/' + idDivision + '/discussion',
idContent: data.id,
title: 'Diskusi Baru',
desc: 'Terdapat diskusi baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: perbekel?.id,
subscription: perbekel?.Subscribe?.subscription
})
}
if (userRoleLogin != "cosupadmin") {
const ketuaGrup = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "cosupadmin",
idGroup: userMobile.idGroup
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
})
tokenDup.push(ketuaGrup?.TokenDeviceUser.map((v: any) => v.token).flat())
dataNotif.push({
idUserTo: ketuaGrup?.id,
idUserFrom: userId,
category: 'division/' + idDivision + '/discussion',
idContent: data.id,
title: 'Diskusi Baru',
desc: 'Terdapat diskusi baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: ketuaGrup?.id,
subscription: ketuaGrup?.Subscribe?.subscription
})
}
const pushNotif = dataPush.filter((item) => item.subscription != undefined)
const sendWebPush = await funSendWebPush({ sub: pushNotif, message: { body: 'Terdapat diskusi baru. Silahkan periksa detailnya.', title: 'Diskusi Baru' } })
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
const tokenUnique = [...new Set(tokenDup.flat())];
await sendFCMNotificationMany({
token: tokenUnique,
title: "Diskusi Baru",
body: "Anda memiliki diskusi baru. Silahkan periksa detailnya.",
data: { id: data.id, category: "division/" + idDivision + "/discussion", content: data.id }
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User membuat data diskusi', table: 'divisionDisscussion', data: data.id, user: userId })
return NextResponse.json({ success: true, message: "Berhasil menambahkan diskusi", notif: dataNotif }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan diskusi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -0,0 +1,421 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";
import { NextResponse } from "next/server";
// GET ONE DATA DIVISI :: UNTUK TAMPIL DETAIL DIVISI (FITUR DIVISI) PADA HALAMAN DETAIL
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 user = searchParams.get("user");
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.findUnique({
where: {
id: String(id),
// isActive: true
}
});
if (!data) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan", }, { status: 200 });
}
if (kategori == "jumlah") {
const tugas = await prisma.divisionProject.count({
where: {
idDivision: String(id),
status: {
lte: 1
},
isActive: true
}
})
const dokumen = await prisma.divisionDocumentFolderFile.count({
where: {
idDivision: String(id),
isActive: true,
category: "FILE"
}
})
const dokumenShare = await prisma.divisionDocumentShare.count({
where: {
idDivision: String(id),
isActive: true,
DivisionDocumentFolderFile: {
isActive: true,
category: "FILE"
}
}
})
const diskusi = await prisma.divisionDisscussion.count({
where: {
idDivision: String(id),
isActive: true,
status: 1
}
})
const kalender = await prisma.divisionCalendarReminder.count({
where: {
idDivision: String(id),
isActive: true,
dateStart: {
lte: new Date()
},
DivisionCalendar: {
isActive: true
}
}
})
allData = {
tugas: tugas,
dokumen: dokumen + dokumenShare,
diskusi: diskusi,
kalender: kalender
}
} else if (kategori == "today-task") {
const tugas = await prisma.divisionProjectTask.findMany({
skip: 0,
take: 5,
where: {
idDivision: String(id),
status: 0,
isActive: true,
dateStart: {
lte: new Date()
},
dateEnd: {
gte: new Date()
},
DivisionProject: {
status: {
lt: 3
}
}
},
select: {
id: true,
idProject: true,
title: true,
dateStart: true,
dateEnd: true,
DivisionProject: {
select: {
title: true
}
}
},
orderBy: {
dateEnd: "asc"
}
})
allData = tugas.map((v: any) => ({
..._.omit(v, ["dateStart", "dateEnd", "DivisionProject"]),
dateStart: moment(v.dateStart).format("ll"),
dateEnd: moment(v.dateEnd).format("ll"),
projectTitle: v.DivisionProject.title
}))
} else if (kategori == "new-file") {
const dataShare = await prisma.divisionDocumentShare.findMany({
skip: 0,
take: 4,
where: {
isActive: true,
idDivision: String(id),
DivisionDocumentFolderFile: {
isActive: true,
category: "FILE"
}
},
select: {
DivisionDocumentFolderFile: {
select: {
id: true,
name: true,
extension: true,
path: true,
}
},
createdAt: true
},
orderBy: {
createdAt: 'desc'
}
})
const fixShare = dataShare.map((v: any) => ({
..._.omit(v, ["DivisionDocumentFolderFile"]),
id: v.DivisionDocumentFolderFile.id,
name: v.DivisionDocumentFolderFile.name,
extension: v.DivisionDocumentFolderFile.extension,
path: 'home',
share: true
}))
const dataDokumen = await prisma.divisionDocumentFolderFile.findMany({
skip: 0,
take: 5,
where: {
idDivision: String(id),
isActive: true,
category: "FILE"
},
select: {
id: true,
name: true,
extension: true,
path: true,
createdAt: true
},
orderBy: {
createdAt: "desc"
}
})
const fixData = dataDokumen.map((v: any) => ({
..._.omit(v, [""]),
share: false
}))
if (fixShare.length > 0) {
fixData.push(...fixShare)
}
allData = _.orderBy(fixData, ['createdAt'], ['desc']);
} else if (kategori == "new-discussion") {
const diskusi = await prisma.divisionDisscussion.findMany({
skip: 0,
take: 5,
where: {
idDivision: String(id),
isActive: true,
status: 1
},
select: {
id: true,
title: true,
desc: true,
createdAt: true,
User: {
select: {
name: true
}
}
},
orderBy: {
createdAt: "desc"
}
})
allData = diskusi.map((v: any) => ({
..._.omit(v, ["createdAt", "User"]),
date: moment(v.createdAt).format("ll"),
user: v.User.name
}))
} else if (kategori == "check-member") {
const member = await prisma.divisionMember.findFirst({
where: {
idDivision: String(id),
idUser: userMobile.id
},
})
allData = member ? true : false
} else if (kategori == "check-admin") {
const member = await prisma.divisionMember.findFirst({
where: {
idDivision: String(id),
idUser: userMobile.id,
isAdmin: true
},
})
allData = member ? true : false
}
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 });
}
}
// MENGELUARKAN ANGGOTA DARI DIVISI
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const idDivision = context.params.id
const { id, user } = (await request.json())
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.count({
where: {
id: idDivision,
isActive: true
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Hapus anggota divisi gagal, data tidak ditemukan",
},
{ status: 200 }
);
}
const update = await prisma.divisionMember.delete({
where: {
id: id,
},
});
// create log user
const log = await createLogUserMobile({ act: 'DELETE', desc: 'User mengeluarkan anggota divisi', table: 'division', data: idDivision, user: userMobile.id })
return NextResponse.json(
{
success: true,
message: "Anggota divisi berhasil dihapus",
},
{ status: 200 }
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// MENGGANTI STATUS ADMIN DIVISI
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const idDivision = context.params.id;
const { id, isAdmin, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.count({
where: {
id: idDivision,
isActive: true
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Perubahan status admin gagal, data tidak ditemukan",
},
{ status: 200 }
);
}
const update = await prisma.divisionMember.update({
where: {
id: id,
},
data: {
isAdmin: !isAdmin
}
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate status anggota divisi', table: 'division', data: idDivision, user: userMobile.id })
return NextResponse.json(
{
success: true,
message: "Status admin berhasil diupdate",
},
{ status: 200 }
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah status admin divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// TAMBAH ANGGOTA DIVISI
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { member, user } = await request.json()
const idDivision = context.params.id
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.count({
where: {
id: idDivision,
isActive: true
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Tambah anggota divisi gagal, data tidak ditemukan",
},
{ status: 200 }
);
}
const dataMember = member.map((v: any) => ({
..._.omit(v, ["name", "img"]),
idUser: v.idUser,
idDivision: idDivision,
}))
const insertMember = await prisma.divisionMember.createMany({
data: dataMember
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User menambah anggota divisi', table: 'division', data: idDivision, user: userMobile.id })
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota divisi" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan anggota divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

View File

@@ -0,0 +1,70 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import _ from "lodash";
import { NextResponse } from "next/server";
// GET MEMBER BY ID
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const { searchParams } = new URL(request.url);
const name = searchParams.get('search')
const user = searchParams.get('user')
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.findUnique({
where: {
id: String(id),
}
});
if (!data) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 200 });
}
const member = await prisma.divisionMember.findMany({
where: {
idDivision: String(id),
isActive: true,
User: {
name: {
contains: (name == undefined || name == null) ? "" : name,
mode: "insensitive",
}
}
},
select: {
id: true,
isAdmin: true,
isLeader: 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
}))
return NextResponse.json({ success: true, data: fixMember })
} catch (error) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan anggota, data tidak ditemukan (error: 500)", }, { status: 500 });
}
}

View File

@@ -0,0 +1,134 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
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 user = searchParams.get("user");
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.findUnique({
where: {
id: String(id),
// isActive: true
}
});
if (!data) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan", }, { status: 200 });
}
const member = await prisma.divisionMember.findMany({
where: {
idDivision: String(id),
isActive: true,
},
select: {
id: true,
isAdmin: true,
isLeader: true,
idUser: true,
User: {
select: {
name: true,
img: true
}
}
},
orderBy: [
{
isAdmin: 'desc',
},
{
User: {
name: 'asc'
}
}
]
})
const fixMember = member.map((v: any) => ({
..._.omit(v, ["User"]),
name: v.User.name,
img: v.User.img
}))
const dataFix = {
division: 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 });
}
}
// EDIT DATA DIVISI
export async function PUT(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const { name, desc, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.count({
where: {
id: id,
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Edit divisi gagal, data tidak ditemukan",
},
{ status: 200 }
);
}
const update = await prisma.division.update({
where: {
id: id,
},
data: {
name: name,
desc: desc
},
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data divisi', table: 'division', data: id, user: userMobile.id })
return NextResponse.json(
{
success: true,
message: "Divisi berhasil diedit",
},
{ status: 200 }
);
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengedit divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,50 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import { NextResponse } from "next/server";
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params;
const { isActive, user } = (await request.json());
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const data = await prisma.division.count({
where: {
id: id,
},
});
if (data == 0) {
return NextResponse.json(
{
success: false,
message: "Edit status divisi gagal, data tidak ditemukan",
},
{ status: 200 }
);
}
const update = await prisma.division.update({
where: {
id: id,
},
data: {
isActive: !isActive,
},
});
// create log user
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengedit status data divisi', table: 'division', data: id, user: userMobile.id })
return NextResponse.json({ success: true, message: "Status divisi berhasil diupdate", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mengubah status divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,53 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { NextResponse } from "next/server";
// GET LIST DIVISI BY ID DIVISI (CONTOH : UNTUK SHARE DOKUMEN)
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const idDivision = searchParams.get("division");
const name = searchParams.get('search');
const user = searchParams.get('user');
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const dataDivision = await prisma.division.findUnique({
where: {
id: String(idDivision),
isActive: true
}
})
if (!dataDivision) {
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan", }, { status: 200 });
}
const data = await prisma.division.findMany({
where: {
isActive: true,
idGroup: dataDivision.idGroup,
name: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
}
},
select: {
id: true,
name: true,
},
orderBy: {
name: "asc"
}
});
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data }, { 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 });
}
}

View File

@@ -0,0 +1,383 @@
import { prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import _, { ceil } from "lodash";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url)
const idGroup = searchParams.get("group")
const division = searchParams.get("division")
const date = searchParams.get("date")
const dateAkhir = searchParams.get("date-end")
const kat = searchParams.get("cat")
const user = searchParams.get("user")
let grup
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
if (idGroup == "null" || idGroup == undefined || idGroup == "" || idGroup == null || idGroup == "undefined") {
grup = userMobile.idGroup
} else {
grup = idGroup
}
if (kat == "table-progress") {
let kondisiProgress
if (division == "undefined") {
kondisiProgress = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
} else {
kondisiProgress = {
isActive: true,
idDivision: String(division),
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
}
const data = await prisma.divisionProject.findMany({
where: kondisiProgress,
select: {
id: true,
title: true,
status: true,
DivisionProjectTask: {
where: {
isActive: true
},
select: {
title: true,
status: true
}
}
}
})
const dataFix = data.map((v: any) => ({
..._.omit(v, ["DivisionProjectTask"]),
progress: ceil((v.DivisionProjectTask.filter((i: any) => i.status == 1).length * 100) / v.DivisionProjectTask.length),
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
} else {
// CHART PROGRESS
let kondisiProgress
if (division == "undefined") {
kondisiProgress = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
} else {
kondisiProgress = {
isActive: true,
idDivision: String(division),
DivisionProjectTask: {
some: {
dateStart: {
gte: new Date(String(date))
},
dateEnd: {
lte: new Date(String(dateAkhir))
}
}
}
}
}
const data = await prisma.divisionProject.groupBy({
where: kondisiProgress,
by: ["status"],
_count: true
})
const dataStatus = [{ name: 'Segera', status: 0, color: '#177AD5' }, { name: 'Dikerjakan', status: 1, color: '#fac858' }, { name: 'Selesai', status: 2, color: '#92cc76' }, { name: 'Dibatalkan', status: 3, color: '#ED6665' }]
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 = {
tooltipText: dataStatus[index].name,
value: Number(fix),
text:`${fix}%`,
color:dataStatus[index].color
}
} else {
input = {
tooltipText: dataStatus[index].name,
value: 0,
text:`0%`,
color:dataStatus[index].color
}
}
hasilProgres.push(input)
}
// CHART DOKUMEN
let kondisi
if (division == "undefined") {
kondisi = {
isActive: true,
category: 'FILE',
Division: {
idGroup: String(grup)
},
createdAt: {
gte: new Date(String(date)),
lte: new Date(String(dateAkhir))
},
}
} else {
kondisi = {
isActive: true,
category: 'FILE',
idDivision: String(division),
createdAt: {
gte: new Date(String(date)),
lte: new Date(String(dateAkhir))
},
}
}
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 = {
label: 'Gambar',
value: 0
}
let hasilFile = {
label: 'Dokumen',
value: 0
}
groupData.map((v: any) => {
if (image.some((i: any) => i == v.file)) {
hasilImage = {
label: 'Gambar',
value: hasilImage.value + v.jumlah
}
} else {
hasilFile = {
label: 'Dokumen',
value: hasilFile.value + v.jumlah
}
}
})
const hasilDokumen = [hasilImage, hasilFile]
// CHART EVENT
let kondisiEvent, kondisiSelesai, kondisiComingSoon
if (division == "undefined") {
// kondisiEvent = {
// isActive: true,
// Division: {
// idGroup: String(grup)
// },
// DivisionCalendarReminder: {
// some: {
// dateStart: {
// gte: new Date(String(date)),
// lte: new Date(String(dateAkhir))
// }
// }
// }
// }
kondisiSelesai = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionCalendarReminder: {
some: {
dateStart: {
gte: new Date(String(date)),
lte: new Date()
}
}
}
}
kondisiComingSoon = {
isActive: true,
Division: {
idGroup: String(grup)
},
DivisionCalendarReminder: {
some: {
dateStart: {
gt: new Date(),
lte: new Date(String(dateAkhir))
}
}
}
}
} else {
// kondisiEvent = {
// isActive: true,
// idDivision: String(division),
// DivisionCalendarReminder: {
// some: {
// dateStart: {
// gte: new Date(String(date)),
// lte: new Date(String(dateAkhir))
// }
// }
// }
// }
kondisiSelesai = {
isActive: true,
idDivision: String(division),
DivisionCalendarReminder: {
some: {
dateStart: {
gte: new Date(String(date)),
lte: new Date()
}
}
}
}
kondisiComingSoon = {
isActive: true,
idDivision: String(division),
DivisionCalendarReminder: {
some: {
dateStart: {
gt: new Date(),
lte: new Date(String(dateAkhir))
}
}
}
}
}
const eventSelesai = await prisma.divisionCalendar.count({
where: kondisiSelesai
})
const eventComingSoon = await prisma.divisionCalendar.count({
where: kondisiComingSoon
})
const hasilEvent = [
{
label: 'Selesai',
value: eventSelesai
},
{
label: 'Akan Datang',
value: eventComingSoon
}
]
// const dataEvent = await prisma.divisionCalendar.findMany({
// where: kondisiEvent,
// select: {
// id: true,
// idDivision: true,
// title: true,
// desc: true,
// status: true,
// timeStart: true,
// dateStart: true,
// timeEnd: true,
// dateEnd: true,
// createdAt: true,
// User: {
// select: {
// name: true
// }
// }
// },
// orderBy: {
// createdAt: 'desc'
// }
// })
// const hasilEvent = dataEvent.map((v: any) => ({
// ..._.omit(v, ["User"]),
// user_name: v.User.name,
// timeStart: moment.utc(v.timeStart).format('HH:mm'),
// timeEnd: moment.utc(v.timeEnd).format('HH:mm')
// }))
const allData = {
progress: hasilProgres,
dokumen: hasilDokumen,
event: hasilEvent
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: allData }, { 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 });
}
}

View File

@@ -0,0 +1,340 @@
import { funSendWebPush, prisma } from "@/module/_global";
import { funGetUserById } from "@/module/auth";
import { createLogUserMobile } from "@/module/user";
import _ from "lodash";
import { NextResponse } from "next/server";
import { sendFCMNotificationMany } from "../../../../../xsendMany";
// GET ALL DATA DIVISI == LIST DATA DIVISI
export async function GET(request: Request) {
try {
let grup
const { searchParams } = new URL(request.url);
const idGroup = searchParams.get("group");
const kategori = searchParams.get("cat");
const name = searchParams.get('search');
const page = searchParams.get('page');
const active = searchParams.get("active");
const user = searchParams.get('user');
const dataSkip = Number(page) * 10 - 10;
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const villaId = userMobile.idVillage
const roleUser = userMobile.idUserRole
if (idGroup == "null" || idGroup == undefined || idGroup == "" || idGroup == "undefined" || idGroup == null) {
grup = userMobile.idGroup
} else {
grup = idGroup
}
// JIKA (ROLE BUKAN USER DAN COADMIN) ATAU SEMUA ROLE DG KATEGORI == SEMUA
let kondisi: any = {
isActive: active == 'false' ? false : true,
idVillage: String(villaId),
idGroup: grup,
name: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
}
}
// JIKA ROLE = USER ATAU COADMIN DAN KATEGORI != SEMUA (DIVISI SAYA)
if (roleUser != "supadmin" && roleUser != "developer" && roleUser != "cosupadmin" && roleUser != "admin") {
if (kategori != "semua") {
kondisi = {
isActive: active == 'false' ? false : true,
idVillage: String(villaId),
idGroup: grup,
name: {
contains: (name == undefined || name == "null") ? "" : name,
mode: "insensitive"
},
DivisionMember: {
some: {
isActive: true,
idUser: String(userMobile.id)
}
}
}
}
}
const totalData = await prisma.division.count({
where: kondisi
})
const data = await prisma.division.findMany({
skip: dataSkip,
take: 10,
where: kondisi,
select: {
id: true,
name: true,
desc: true,
DivisionMember: {
where: {
isActive: true
},
select: {
idUser: true
}
}
},
orderBy: {
createdAt: 'desc'
}
});
const allData = data.map((v: any) => ({
..._.omit(v, ["DivisionMember"]),
jumlah_member: v.DivisionMember.length
}))
const filter = await prisma.group.findUnique({
where: {
id: grup
},
select: {
id: true,
name: true
}
})
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: allData, total: totalData, filter }, { 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 });
}
}
// CREATE DATA DIVISI
export async function POST(request: Request) {
try {
const sent = (await request.json())
const user = sent.user
const userMobile = await funGetUserById({ id: String(user) })
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
}
const userId = userMobile.id
const userRoleLogin = userMobile.idUserRole
let fixGroup
if (sent.data.idGroup == "null" || sent.data.idGroup == undefined || sent.data.idGroup == "") {
fixGroup = userMobile.idGroup
} else {
fixGroup = sent.data.idGroup
}
const data = await prisma.division.create({
data: {
name: sent.data.name,
idVillage: String(userMobile.idVillage),
idGroup: fixGroup,
desc: sent.data.desc,
createdBy: String(userMobile.id)
},
select: {
id: true
}
})
const dataMember = sent.member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idUser: v.idUser,
idDivision: data.id,
isAdmin: sent.admin.some((i: any) => i == v.idUser)
}))
const insertMember = await prisma.divisionMember.createMany({
data: dataMember
})
// mengirim notifikasi
// dataFCM untuk push notifikasi mobile
// datanotif untuk realtime notifikasi
// datapush untuk web push notifikasi ketika aplikasi tidak aktif
const dataNotif = sent.member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idUserTo: v.idUser,
idUserFrom: userId,
category: 'division',
idContent: data.id,
title: 'Divisi Baru',
desc: 'Terdapat divisi baru. Silahkan periksa detailnya.'
}))
const selectUser = await prisma.divisionMember.findMany({
where: {
isActive: true,
idDivision: data.id
},
select: {
idUser: true,
User: {
select: {
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
}
}
})
const dataFCM = selectUser.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]),
tokens: v.User.TokenDeviceUser.map((v: any) => v.token)
}))
const tokenDup = dataFCM.filter((v: any) => v.tokens.length > 0).map((v: any) => v.tokens).flat();
const dataPush = selectUser.map((v: any) => ({
..._.omit(v, ["idUser", "User", "Subscribe"]),
idUser: v.idUser,
subscription: v.User.Subscribe?.subscription,
}))
if (userRoleLogin != "supadmin") {
const perbekel = await prisma.user.findFirst({
where: {
isActive: true,
idUserRole: "supadmin",
idVillage: user.idVillage
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
})
tokenDup.push(perbekel?.TokenDeviceUser.map((v: any) => v.token).flat())
dataNotif.push({
idUserTo: perbekel?.id,
idUserFrom: userId,
category: 'division',
idContent: data.id,
title: 'Divisi Baru',
desc: 'Terdapat divisi baru. Silahkan periksa detailnya.'
})
dataPush.push({
idUser: perbekel?.id,
subscription: perbekel?.Subscribe?.subscription
})
} else {
const atasanGroup = await prisma.user.findMany({
where: {
isActive: true,
idGroup: sent.data.idGroup,
AND: {
OR: [
{ idUserRole: 'cosupadmin' },
{ idUserRole: 'admin' },
]
}
},
select: {
id: true,
Subscribe: {
select: {
subscription: true
}
},
TokenDeviceUser: {
select: {
token: true
}
}
}
})
const omitFCM = atasanGroup.map((v: any) => ({
..._.omit(v, ["id", "Subscribe", "TokenDeviceUser"]),
tokens: v.TokenDeviceUser.map((v: any) => v.token)
}))
const omitData = atasanGroup.map((v: any) => ({
..._.omit(v, ["id", "Subscribe", "TokenDeviceUser"]),
idUserTo: v.id,
idUserFrom: userId,
category: 'division',
idContent: data.id,
title: 'Divisi Baru',
desc: 'Terdapat divisi baru. Silahkan periksa detailnya.'
}))
const omitPush = atasanGroup.map((v: any) => ({
..._.omit(v, ["id", "Subscribe", "TokenDeviceUser"]),
idUser: v.id,
subscription: v.Subscribe?.subscription,
}))
dataNotif.push(...omitData)
dataPush.push(...omitPush)
tokenDup.push(...omitFCM.map((v: any) => v.tokens).flat())
}
const pushNotif = dataPush.filter((item) => item.subscription != undefined)
const sendWebPush = await funSendWebPush({ sub: pushNotif, message: { title: 'Divisi Baru', body: 'Terdapat divisi baru. Silahkan periksa detailnya.' } })
const insertNotif = await prisma.notifications.createMany({
data: dataNotif
})
const tokenUnique = [...new Set(tokenDup.flat())];
await sendFCMNotificationMany({
token: tokenUnique,
title: "Divisi Baru",
body: "Anda memiliki divisi baru. Silahkan periksa detailnya.",
data: { id: data.id, category: "division", content: data.id }
})
// create log user
const log = await createLogUserMobile({ act: 'CREATE', desc: 'User membuat data divisi', table: 'division', data: data.id, user: userId })
return NextResponse.json({ success: true, message: "Berhasil menambahkan divisi" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambahkan divisi, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
};

Some files were not shown because too many files have changed in this diff Show More