Compare commits

...

20 Commits

Author SHA1 Message Date
f103ae93ad chore(release): 1.5.39 2026-01-30 17:16:05 +08:00
1c9459dcf3 Fix comment forum
Forum API (Mobile)
- src/app/api/mobile/forum/[id]/comment/route.ts

### No Issue
2026-01-29 17:41:21 +08:00
8b54f5ca65 Fix send whatsapp
Auth API
- src/app/api/auth/login/route.ts
- src/app/api/auth/mobile-login/route.ts
- src/app/api/auth/mobile-register/route.ts
- src/app/api/auth/resend/route.ts

User API (Mobile)
- src/app/api/mobile/user/route.ts
- src/app/api/mobile/admin/user/[id]/route.ts

Utility
- src/lib/code-otp-sender.ts

### No issue
2026-01-29 15:04:40 +08:00
c94da645f3 API – Donation (Admin & User)
- src/app/api/mobile/admin/donation/[id]/disbursement/route.ts
- src/app/api/mobile/donation/[id]/news/route.ts
- src/app/api/mobile/donation/route.ts

Donation Helper / Logic
- src/lib/mobile/donation/

### No Issue
2026-01-27 16:59:31 +08:00
da0477102e chore(release): 1.5.38 2026-01-27 16:57:22 +08:00
70db97f5bb chore(release): 1.5.37 2026-01-23 17:05:04 +08:00
8ccf1f2b6e API – Donation (Admin & User)
- src/app/api/mobile/admin/donation/[id]/route.ts
- src/app/api/mobile/admin/donation/[id]/invoice/route.ts
- src/app/api/mobile/donation/route.ts
- src/app/api/mobile/donation/[id]/invoice/route.ts

Routing Helper
- src/lib/mobile/route-page-mobile.ts

### No Issue
2026-01-23 17:04:43 +08:00
048b7b6094 API Rgister component sender
Legal Documents & Registration
- public/privacy-policy.html
- public/terms-of-service.html
- src/app/api/auth/mobile-register/route.ts

### No Issue;
2026-01-23 14:46:44 +08:00
fc23e01275 Notification investasi mobile done
### No Issue
2026-01-22 17:53:35 +08:00
20d05c1cc7 component sender wa to all device ( apps & web ) 2026-01-22 11:58:37 +08:00
2c269db250 API – Investment (Admin & User)
- src/app/api/mobile/admin/investment/[id]/route.ts
- src/app/api/mobile/admin/investment/[id]/invoice/route.ts
- src/app/api/mobile/investment/[id]/invoice/route.ts
- src/app/api/mobile/investment/[id]/document/route.ts

Routing Helper
- src/lib/mobile/route-page-mobile.ts

### No Issue
2026-01-21 15:34:19 +08:00
fea94df7bb refactor(invesment): penyesuaian endpoint admin, invoice, dan navigasi mobile
- src/app/api/mobile/admin/investment/[id]/route.ts
- src/app/api/mobile/investment/[id]/invoice/route.ts
- src/app/api/mobile/investment/route.ts
- src/lib/mobile/route-page-mobile.ts

### No Issue
2026-01-20 17:48:42 +08:00
3c6dde6204 Fix API notification to report comment
Fix:
- src/app/api/mobile/admin/forum/[id]/comment/route.ts
- src/app/api/mobile/admin/forum/[id]/route.ts
- src/app/api/mobile/forum/[id]/preview-report-posting/route.ts
- src/app/api/mobile/forum/[id]/report-commentar/route.ts
- src/app/api/mobile/forum/[id]/report-posting/route.ts
- src/lib/mobile/route-page-mobile.ts
- tsconfig.json

Deleted:
- src/app/api/mobile/forum/[id]/report-comment/route.ts

Add:
- src/app/api/mobile/forum/[id]/preview-report-comment/
- src/app/api/mobile/forum/[id]/report-comment-del-soon/

### No Issue
2026-01-19 17:38:15 +08:00
cb0845e264 Fix notification forum
Fix:
modified:   src/app/api/mobile/admin/forum/[id]/route.ts
modified:   src/app/api/mobile/forum/[id]/comment/route.ts
modified:   src/app/api/mobile/forum/[id]/report-posting/route.ts
modified:   src/app/api/mobile/forum/route.ts
modified:   src/lib/mobile/route-page-mobile.ts

Add:
src/app/api/mobile/forum/[id]/preview-report-posting/

### No Issue
2026-01-17 16:00:46 +08:00
d09e30c049 Voting notifikasi for mobile
Fix:
- src/app/api/mobile/admin/voting/[id]/route.ts
- src/app/api/mobile/event/route.ts
- src/app/api/mobile/voting/[id]/route.ts
- src/app/api/mobile/voting/route.ts
- src/lib/mobile/route-page-mobile.ts

### No Issue
2026-01-15 17:38:33 +08:00
c8bd928c33 Fix notifikasi join dari event
Fix:
 modified:   src/app/api/mobile/event/[id]/participants/route.ts
        modified:   src/bin/seeder/user_seeder.json

### No Issue
2026-01-15 13:57:00 +08:00
3a558cec8e chore(release): 1.5.36 2026-01-13 17:45:58 +08:00
b9354cb6bf Penerapan notifikasi pada event
Fix:
- src/app/api/mobile/admin/event/[id]/route.ts
- src/app/api/mobile/admin/job/[id]/route.ts
- src/app/api/mobile/event/route.ts
- src/app/api/mobile/job/route.ts
- src/app/api/mobile/notification/[id]/route.ts
- src/lib/mobile/notification/send-notification.ts
- src/lib/mobile/route-page-mobile.ts
- types/type-mobile-notification.ts

### No Issue
2026-01-13 17:45:37 +08:00
7cdde6b5a9 chore(release): 1.5.35 2026-01-12 17:35:50 +08:00
e77e5eb3ac Fix notification reuse component
Fix:
- modified:   src/app/api/auth/mobile-register/route.ts
- modified:   src/lib/mobile/notification/send-notification.ts

### No Issue
2026-01-12 17:35:27 +08:00
48 changed files with 1583 additions and 438 deletions

View File

@@ -2,6 +2,16 @@
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
## [1.5.39](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.38...v1.5.39) (2026-01-30)
## [1.5.38](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.37...v1.5.38) (2026-01-27)
## [1.5.37](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.36...v1.5.37) (2026-01-23)
## [1.5.36](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.35...v1.5.36) (2026-01-13)
## [1.5.35](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.34...v1.5.35) (2026-01-12)
## [1.5.34](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.33...v1.5.34) (2026-01-09) ## [1.5.34](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.33...v1.5.34) (2026-01-09)
## [1.5.33](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.32...v1.5.33) (2026-01-06) ## [1.5.33](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.32...v1.5.33) (2026-01-06)

View File

@@ -1,6 +1,6 @@
{ {
"name": "hipmi", "name": "hipmi",
"version": "1.5.34", "version": "1.5.39",
"private": true, "private": true,
"prisma": { "prisma": {
"seed": "bun prisma/seed.ts" "seed": "bun prisma/seed.ts"

View File

@@ -295,7 +295,7 @@
<p>You have the right to request access to the personal information we collect from you, details about how we have processed it, correct inaccuracies, or delete your personal information. You may also have the right to withdraw your consent to our processing of your personal information. These rights may be limited in some circumstances by applicable law.</p> <p>You have the right to request access to the personal information we collect from you, details about how we have processed it, correct inaccuracies, or delete your personal information. You may also have the right to withdraw your consent to our processing of your personal information. These rights may be limited in some circumstances by applicable law.</p>
<p>To make a request, please contact us at <a href="mailto:bip.baliinteraktifperkasa@gmail.com">bip.baliinteraktifperkasa@gmail.com</a>.</p> <p>To make a request, please contact us at <a href="mailto:bip.baliinteraktifperkasa@gmail.com">bip.baliinteraktifperkasa@gmail.com</a>.</p>
<hr style="margin: 30px 0; border: 0; border-top: 1px solid #eee;"> <hr style="margin: 30px 0; border: 0; border-top: 1px solid #eee;">
<p>© 2025 Bali Interaktif Perkasa. All rights reserved.</p> <p>© 2026 Bali Interaktif Perkasa. All rights reserved.</p>
</body> </body>
</html> </html>

View File

@@ -104,7 +104,7 @@
</p> </p>
<footer> <footer>
<p>© 2025 Bali Interaktif Perkasa. All rights reserved.</p> <p>© 2026 Bali Interaktif Perkasa. All rights reserved.</p>
</footer> </footer>
</body> </body>
</html> </html>

View File

@@ -2,12 +2,13 @@ import { prisma } from "@/lib";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp"; import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import backendLogger from "@/util/backendLogger"; import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { funSendToWhatsApp } from "@/lib/code-otp-sender";
export async function POST(req: Request) { export async function POST(req: Request) {
if (req.method !== "POST") { if (req.method !== "POST") {
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Method Not Allowed" }, { success: false, message: "Method Not Allowed" },
{ status: 405 } { status: 405 },
); );
} }
@@ -26,29 +27,21 @@ export async function POST(req: Request) {
if (!createOtpId) if (!createOtpId)
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Gagal mengirim kode OTP" }, { success: false, message: "Gagal mengirim kode OTP" },
{ status: 400 } { status: 400 },
); );
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%5Cn%5Cn%3E%3E%20Kode%20OTP%20anda%3A%20${codeOtp}.`; const resSendCode = await funSendToWhatsApp({
// const encodedMsg = encodeURIComponent(msg); nomor,
codeOtp: codeOtp.toString(),
});
const res = await fetch( if (resSendCode.status !== 200)
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${msg}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
}
);
if (res.status !== 200)
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" }, { success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 } { status: 400 },
); );
const sendWa = await res.text(); const sendWa = await resSendCode.text();
console.log("WA Response:", sendWa); console.log("WA Response:", sendWa);
return NextResponse.json( return NextResponse.json(
@@ -57,7 +50,7 @@ export async function POST(req: Request) {
message: "Kode verifikasi terkirim", message: "Kode verifikasi terkirim",
kodeId: createOtpId.id, kodeId: createOtpId.id,
}, },
{ status: 200 } { status: 200 },
); );
} catch (error) { } catch (error) {
backendLogger.log("Error Login", error); backendLogger.log("Error Login", error);
@@ -67,7 +60,7 @@ export async function POST(req: Request) {
message: "Terjadi masalah saat login", message: "Terjadi masalah saat login",
reason: error as Error, reason: error as Error,
}, },
{ status: 500 } { status: 500 },
); );
} }
} }

View File

@@ -1,6 +1,7 @@
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp"; import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { funSendToWhatsApp } from "@/lib/code-otp-sender";
export async function POST(req: Request) { export async function POST(req: Request) {
try { try {
@@ -31,30 +32,21 @@ export async function POST(req: Request) {
if (!createOtpId) if (!createOtpId)
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Gagal mengirim kode OTP" }, { success: false, message: "Gagal mengirim kode OTP" },
{ status: 400 } { status: 400 },
); );
// const msg = `HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPAADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya.\n\n\n> Kode OTP anda: ${codeOtp}.`; const resSendCode = await funSendToWhatsApp({
// const encodedMsg = encodeURIComponent(msg); nomor,
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%20Kode%20OTP%20anda%3A%20${codeOtp}.`; codeOtp: codeOtp.toString(),
});
const res = await fetch( if (resSendCode.status !== 200)
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${msg}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
}
);
if (res.status !== 200)
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" }, { success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 } { status: 400 },
); );
const sendWa = await res.text(); const sendWa = await resSendCode.text();
console.log("WA Response:", sendWa); console.log("WA Response:", sendWa);
return NextResponse.json( return NextResponse.json(
@@ -64,7 +56,7 @@ export async function POST(req: Request) {
kodeId: createOtpId.id, kodeId: createOtpId.id,
isAcceptTerms: user.termsOfServiceAccepted, isAcceptTerms: user.termsOfServiceAccepted,
}, },
{ status: 200 } { status: 200 },
); );
} catch (error) { } catch (error) {
return NextResponse.json( return NextResponse.json(
@@ -73,7 +65,7 @@ export async function POST(req: Request) {
message: "Terjadi masalah saat login", message: "Terjadi masalah saat login",
reason: error as Error, reason: error as Error,
}, },
{ status: 500 } { status: 500 },
); );
} }
} }

View File

@@ -1,8 +1,13 @@
import { sessionCreate } from "@/app/(auth)/_lib/session_create";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp"; import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import { adminMessaging } from "@/lib/firebase-admin"; import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../types/type-mobile-notification";
import { funSendToWhatsApp } from "@/lib/code-otp-sender";
export async function POST(req: Request) { export async function POST(req: Request) {
if (req.method !== "POST") { if (req.method !== "POST") {
@@ -65,31 +70,29 @@ export async function POST(req: Request) {
{ status: 400 } { status: 400 }
); );
// const msg = `HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPAADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya.\n\n\n> Kode OTP anda: ${codeOtp}.`; const resSendCode = await funSendToWhatsApp({
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%20Kode%20OTP%20anda%3A%20${codeOtp}.`; nomor: data.nomor,
// // const encodedMsg = encodeURIComponent(msg); codeOtp: codeOtp.toString(),
});
const res = await fetch( if (resSendCode.status !== 200)
`https://wa.wibudev.com/code?nom=${data.nomor}&text=${msg}`,
{ cache: "no-cache" }
);
const sendWa = await res.json();
if (sendWa.status !== "success")
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" }, { success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 } { status: 400 },
); );
const sendWa = await resSendCode.text();
console.log("WA Response:", sendWa);
// =========== START SEND NOTIFICATION =========== // // =========== START SEND NOTIFICATION =========== //
const findAllUserBySendTo = await prisma.user.findMany({ const adminUsers = await prisma.user.findMany({
where: { masterUserRoleId: "2" }, where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
select: { id: true }, select: { id: true },
}); });
console.log("Users to notify:", findAllUserBySendTo); console.log("Users to notify:", adminUsers);
const dataNotification = { const dataNotification = {
title: "Pendaftaran Baru", title: "Pendaftaran Baru",
@@ -101,63 +104,17 @@ export async function POST(req: Request) {
senderId: createUser.id, senderId: createUser.id,
}; };
for (let a of findAllUserBySendTo) { await sendNotificationMobileToManyUser({
const createdNotification = await prisma.notifikasi.create({ recipientIds: adminUsers.map((user) => user.id),
data: { senderId: data.authorId,
...dataNotification, payload: {
recipientId: a.id, title: "Pendaftaran User Baru" as NotificationMobileTitleType,
}, body: "User baru telah melakukan registrasi. Ayo cek dan verifikasi!" as NotificationMobileBodyType,
}); type: "announcement",
deepLink: routeAdminMobile.userAccess({ id: createUser.id }),
if (createdNotification) { kategoriApp: "OTHER",
const deviceToken = await prisma.tokenUserDevice.findMany({ },
where: { });
userId: a.id,
isActive: true,
},
});
for (let i of deviceToken) {
const message = {
token: i.token,
notification: {
title: dataNotification.title,
body: dataNotification.pesan,
},
data: {
sentAt: new Date().toISOString(), // ✅ Simpan metadata di data
id: createdNotification.id,
deepLink: dataNotification.deepLink,
},
// Konfigurasi Android untuk prioritas tinggi
android: {
priority: "high" as const, // Kirim secepatnya, bahkan di doze mode untuk notifikasi penting
notification: {
channelId: "default", // Sesuaikan dengan channel yang kamu buat di Android
},
ttl: 0 as const, // Kirim secepatnya, jangan tunda
},
// Opsional: tambahkan untuk iOS juga
apns: {
payload: {
aps: {
sound: "default" as const,
// 'content-available': 1 as const, // jika butuh silent push
},
},
},
};
try {
const response = await adminMessaging.send(message);
console.log("✅ FCM sent successfully", "Response:", response);
} catch (error: any) {
console.error("❌ FCM send failed:", error);
// Lanjutkan ke token berikutnya meski satu gagal
}
}
}
}
// =========== END SEND NOTIFICATION =========== // // =========== END SEND NOTIFICATION =========== //

View File

@@ -2,12 +2,13 @@ import { prisma } from "@/lib";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp"; import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import backendLogger from "@/util/backendLogger"; import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { funSendToWhatsApp } from "@/lib/code-otp-sender";
export async function POST(req: Request) { export async function POST(req: Request) {
if (req.method !== "POST") { if (req.method !== "POST") {
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Method Not Allowed" }, { success: false, message: "Method Not Allowed" },
{ status: 405 } { status: 405 },
); );
} }
@@ -16,25 +17,18 @@ export async function POST(req: Request) {
const body = await req.json(); const body = await req.json();
const { nomor } = body; const { nomor } = body;
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%5Cn%5Cn%3E%3E%20Kode%20OTP%20anda%3A%20${codeOtp}.`; const resSendCode = await funSendToWhatsApp({
nomor,
codeOtp: codeOtp.toString(),
});
const res = await fetch( if (resSendCode.status !== 200)
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${msg}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
}
);
if (res.status !== 200)
return NextResponse.json( return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" }, { success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 } { status: 400 },
); );
const sendWa = await res.text(); const sendWa = await resSendCode.text();
console.log("WA Response:", sendWa); console.log("WA Response:", sendWa);
const createOtpId = await prisma.kodeOtp.create({ const createOtpId = await prisma.kodeOtp.create({
@@ -50,7 +44,7 @@ export async function POST(req: Request) {
success: false, success: false,
message: "Gagal Membuat Kode OTP", message: "Gagal Membuat Kode OTP",
}, },
{ status: 400 } { status: 400 },
); );
return NextResponse.json( return NextResponse.json(
@@ -59,7 +53,7 @@ export async function POST(req: Request) {
message: "Kode Verifikasi Dikirim", message: "Kode Verifikasi Dikirim",
kodeId: createOtpId.id, kodeId: createOtpId.id,
}, },
{ status: 200 } { status: 200 },
); );
} catch (error) { } catch (error) {
backendLogger.error(" Error Resend OTP", error); backendLogger.error(" Error Resend OTP", error);
@@ -68,7 +62,7 @@ export async function POST(req: Request) {
success: false, success: false,
message: "Server Whatsapp Error !!", message: "Server Whatsapp Error !!",
}, },
{ status: 500 } { status: 500 },
); );
} finally { } finally {
await prisma.$disconnect(); await prisma.$disconnect();

View File

@@ -1,11 +1,22 @@
import { funFindDonaturList } from "@/lib/mobile/donation/find-donatur-list";
import {
sendNotificationMobileToManyUser,
sendNotificationMobileToOneUser,
} from "@/lib/mobile/notification/send-notification";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET }; export { POST, GET };
async function POST(request: Request, { params }: { params: { id: string } }) { async function POST(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { title, nominalCair, deskripsi, imageId, authorId } = data;
try { try {
const dataDonasi = await prisma.donasi.findUnique({ const dataDonasi = await prisma.donasi.findUnique({
@@ -22,19 +33,19 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
return NextResponse.json( return NextResponse.json(
{ {
success: false, success: false,
message: "Pencarian Donasi Gagal", message: "DataPencarian Donasi Gagal",
reason: "Pencarian Donasi Gagal", reason: "Data Pencarian Donasi Gagal",
}, },
{ status: 400 } { status: 400 },
); );
const createPencairan = await prisma.donasi_PencairanDana.create({ const createPencairan = await prisma.donasi_PencairanDana.create({
data: { data: {
donasiId: id, donasiId: id,
nominalCair: +data.nominalCair, nominalCair: +nominalCair,
deskripsi: data.deskripsi, deskripsi: deskripsi,
title: data.title, title: title,
imageId: data.imageId, imageId: imageId,
}, },
}); });
@@ -45,11 +56,11 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
message: "Pencairan Dana Gagal", message: "Pencairan Dana Gagal",
reason: "Pencairan Dana Gagal", reason: "Pencairan Dana Gagal",
}, },
{ status: 400 } { status: 400 },
); );
const hasilTotalPencairan = const hasilTotalPencairan =
Number(dataDonasi.totalPencairan) + Number(data.nominalCair); Number(dataDonasi.totalPencairan) + Number(nominalCair);
// const hasilAkumulasiPencairan = Number(dataDonasi.akumulasiPencairan) + 1; // const hasilAkumulasiPencairan = Number(dataDonasi.akumulasiPencairan) + 1;
const countPencairan = await prisma.donasi_PencairanDana.count({ const countPencairan = await prisma.donasi_PencairanDana.count({
@@ -66,8 +77,47 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
akumulasiPencairan: countPencairan, akumulasiPencairan: countPencairan,
totalPencairan: hasilTotalPencairan, totalPencairan: hasilTotalPencairan,
}, },
select: {
authorId: true,
title: true,
},
}); });
// ================= START SEND NOTIFICATION =================
await sendNotificationMobileToOneUser({
recipientId: updateDonasi?.authorId!,
senderId: authorId,
payload: {
title: "Pencairan Dana Berhasil" as NotificationMobileTitleType,
body: `Telah dilaksanakan pencairan dana untuk ${updateDonasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationDetailPublish({
id: id,
}),
},
});
const recipientIds = await funFindDonaturList(id);
if (recipientIds.length > 0) {
await sendNotificationMobileToManyUser({
recipientIds,
senderId: authorId,
payload: {
title: "Pencarian Dana" as NotificationMobileTitleType,
body: `Update pencarian dana pada ${updateDonasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationDetailPublish({
id: id,
}),
},
});
}
// ================= END SEND NOTIFICATION =================
if (!updateDonasi) if (!updateDonasi)
return NextResponse.json( return NextResponse.json(
{ {
@@ -75,7 +125,7 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
message: "Update Donasi Gagal", message: "Update Donasi Gagal",
reason: "Update Donasi Gagal", reason: "Update Donasi Gagal",
}, },
{ status: 400 } { status: 400 },
); );
return NextResponse.json( return NextResponse.json(
@@ -84,7 +134,7 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
message: "Pencairan Dana Berhasil", message: "Pencairan Dana Berhasil",
// data: data, // data: data,
}, },
{ status: 200 } { status: 200 },
); );
} catch (error) { } catch (error) {
console.error("[ERROR]", error); console.error("[ERROR]", error);
@@ -94,7 +144,7 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
message: "Pencairan Dana Gagal", message: "Pencairan Dana Gagal",
reason: (error as Error).message, reason: (error as Error).message,
}, },
{ status: 500 } { status: 500 },
); );
} }
} }
@@ -110,7 +160,6 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
console.log("[CATEGORY]", category); console.log("[CATEGORY]", category);
let fixData; let fixData;
try { try {
if (category === "get-all") { if (category === "get-all") {
fixData = await prisma.donasi_PencairanDana.findMany({ fixData = await prisma.donasi_PencairanDana.findMany({
take: page ? takeData : undefined, take: page ? takeData : undefined,
@@ -140,7 +189,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
message: "Category tidak ditemukan", message: "Category tidak ditemukan",
reason: "Category tidak ditemukan", reason: "Category tidak ditemukan",
}, },
{ status: 400 } { status: 400 },
); );
} }
@@ -150,7 +199,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
message: "Success get data disbursement", message: "Success get data disbursement",
data: fixData, data: fixData,
}, },
{ status: 200 } { status: 200 },
); );
} catch (error) { } catch (error) {
console.error("[ERROR]", error); console.error("[ERROR]", error);
@@ -160,7 +209,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
message: "Gagal mendapatkan data disbursement", message: "Gagal mendapatkan data disbursement",
reason: (error as Error).message, reason: (error as Error).message,
}, },
{ status: 500 } { status: 500 },
); );
} }
} }

View File

@@ -1,6 +1,9 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import _ from "lodash"; import _ from "lodash";
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import { NotificationMobileBodyType, NotificationMobileTitleType } from "../../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, PUT }; export { GET, PUT };
@@ -50,6 +53,7 @@ async function GET(req: Request, { params }: { params: { id: string } }) {
interface DataType { interface DataType {
donationId: string; donationId: string;
nominal: number; nominal: number;
senderId: string;
} }
async function PUT(req: Request, { params }: { params: { id: string } }) { async function PUT(req: Request, { params }: { params: { id: string } }) {
@@ -111,6 +115,9 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
data: { data: {
donasiMaster_StatusInvoiceId: checkStatusTransaksi.id, donasiMaster_StatusInvoiceId: checkStatusTransaksi.id,
}, },
select: {
authorId: true,
},
}); });
if (!updateInvoice) { if (!updateInvoice) {
@@ -154,6 +161,38 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
); );
} }
// SEND NOTIFICATION: to donatur
await sendNotificationMobileToOneUser({
recipientId: updateInvoice?.authorId as string,
senderId: data?.senderId || "",
payload: {
title: "Transaksi Berhasil" as NotificationMobileTitleType,
body: `Selamat anda menjadi donatur pada ${updateDonasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationTransaction,
},
});
// SEND NOTIFICATION: to creator
await sendNotificationMobileToOneUser({
recipientId: updateDonasi?.authorId as any,
senderId: data?.senderId || "",
payload: {
title: "Ada Donatur Baru !" as NotificationMobileTitleType,
body: `Cek daftar donatur pada ${updateDonasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationDetailPublish({
id: updateDonasi?.id as string,
}),
},
});
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,

View File

@@ -1,6 +1,15 @@
import {
sendNotificationMobileToManyUser,
sendNotificationMobileToOneUser,
} from "@/lib/mobile/notification/send-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import _ from "lodash"; import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
export { GET, PUT }; export { GET, PUT };
@@ -48,7 +57,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
DonasiMaster_StatusInvoice: { DonasiMaster_StatusInvoice: {
name: "Berhasil", name: "Berhasil",
}, },
}, },
}); });
return NextResponse.json( return NextResponse.json(
@@ -60,7 +69,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
donatur: successInvoice, donatur: successInvoice,
}, },
}, },
{ status: 200 } { status: 200 },
); );
} catch (error) { } catch (error) {
return NextResponse.json( return NextResponse.json(
@@ -69,7 +78,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
message: "Error get detail Investasi", message: "Error get detail Investasi",
reason: (error as Error).message, reason: (error as Error).message,
}, },
{ status: 500 } { status: 500 },
); );
} }
} }
@@ -77,6 +86,10 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function PUT(request: Request, { params }: { params: { id: string } }) { async function PUT(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { catatan, senderId } = data;
console.log("[PUT CATATAN]", catatan);
console.log("[PUT SENDER ID]", senderId);
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const status = searchParams.get("status"); const status = searchParams.get("status");
const fixStatus = _.startCase(status as string); const fixStatus = _.startCase(status as string);
@@ -102,7 +115,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
message: "Error update data event", message: "Error update data event",
reason: "Status not found", reason: "Status not found",
}, },
{ status: 500 } { status: 500 },
); );
if (fixStatus === "Reject") { if (fixStatus === "Reject") {
@@ -111,11 +124,24 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
id: id, id: id,
}, },
data: { data: {
catatan: data, catatan: catatan,
donasiMaster_StatusDonasiId: checkStatus.id, donasiMaster_StatusDonasiId: checkStatus.id,
}, },
}); });
// SEND NOTIFICATION
await sendNotificationMobileToOneUser({
recipientId: updateData.authorId as any,
senderId: senderId,
payload: {
title: "Pengajuan Review Ditolak",
body: "Mohon perbaiki data sesuai catatan penolakan !",
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationByStatus({ status: "reject" }),
},
});
fixData = updateData; fixData = updateData;
} else if (fixStatus === "Publish") { } else if (fixStatus === "Publish") {
const updateData = await prisma.donasi.update({ const updateData = await prisma.donasi.update({
@@ -128,6 +154,39 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
// SEND NOTIFICAtION
await sendNotificationMobileToOneUser({
recipientId: updateData.authorId as any,
senderId: senderId,
payload: {
title: "Review Selesai",
body: `Donasi kamu telah dipublikasikan ! ${updateData.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationByStatus({ status: "publish" }),
},
});
const allUsers = await prisma.user.findMany({
where: {
NOT: { id: updateData.authorId as any },
active: true,
},
select: { id: true },
});
await sendNotificationMobileToManyUser({
recipientIds: allUsers.map((user) => user.id),
senderId: senderId,
payload: {
title: "Ayo Cek Donasi Terbaru" as NotificationMobileTitleType,
body: `${updateData.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationDetailPublish({ id: id }),
},
});
fixData = updateData; fixData = updateData;
} }
@@ -137,7 +196,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
message: "Data Donasi Berhasil Diambil", message: "Data Donasi Berhasil Diambil",
data: data, data: data,
}, },
{ status: 200 } { status: 200 },
); );
} catch (error) { } catch (error) {
return NextResponse.json( return NextResponse.json(
@@ -146,7 +205,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
message: "Error get detail Investasi", message: "Error get detail Investasi",
reason: (error as Error).message, reason: (error as Error).message,
}, },
{ status: 500 } { status: 500 },
); );
} }
} }

View File

@@ -1,6 +1,15 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import _ from "lodash"; import _ from "lodash";
import {
sendNotificationMobileToManyUser,
sendNotificationMobileToOneUser,
} from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, PUT }; export { GET, PUT };
@@ -57,6 +66,8 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function PUT(request: Request, { params }: { params: { id: string } }) { async function PUT(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { catatan, senderId } = data;
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const status = searchParams.get("status"); const status = searchParams.get("status");
const fixStatus = _.startCase(status as string); const fixStatus = _.startCase(status as string);
@@ -89,11 +100,23 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
id: id, id: id,
}, },
data: { data: {
catatan: data, catatan: catatan,
eventMaster_StatusId: checkStatus.id, eventMaster_StatusId: checkStatus.id,
}, },
}); });
await sendNotificationMobileToOneUser({
recipientId: updateData.authorId as any,
senderId: senderId,
payload: {
title: "Pengajuan Review Ditolak",
body: "Mohon perbaiki data sesuai catatan penolakan !",
type: "announcement",
kategoriApp: "EVENT",
deepLink: routeUserMobile.eventByStatus({status: "reject"}),
},
});
fixData = updateData; fixData = updateData;
} else if (fixStatus === "Publish") { } else if (fixStatus === "Publish") {
const updateData = await prisma.event.update({ const updateData = await prisma.event.update({
@@ -105,6 +128,38 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
await sendNotificationMobileToOneUser({
recipientId: updateData.authorId as any,
senderId: senderId,
payload: {
title: "Review Selesai",
body: "Event kamu telah dipublikasikan !" as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "EVENT",
deepLink: routeUserMobile.eventByStatus({status: "publish"}),
},
});
const adminUsers = await prisma.user.findMany({
where: {
masterUserRoleId: "1",
NOT: { id: updateData.authorId as any },
},
select: { id: true },
});
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: senderId,
payload: {
title: "Event Baru" as NotificationMobileTitleType,
body: `${updateData.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "EVENT",
deepLink: routeUserMobile.eventDetailPublised({ id: id }),
},
});
fixData = updateData; fixData = updateData;
} }

View File

@@ -1,6 +1,12 @@
import _ from "lodash"; import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, PUT }; export { GET, PUT };
@@ -82,21 +88,43 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function PUT(request: Request, { params }: { params: { id: string } }) { async function PUT(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const data = await request.json();
console.log("SENDER Comment", data);
try { try {
const deleteData = await prisma.forum_Komentar.update({ const deactiveComment = await prisma.forum_Komentar.update({
where: { where: {
id: id, id: id,
}, },
data: { data: {
isActive: false, isActive: false,
}, },
select: {
authorId: true,
komentar: true,
},
}); });
// SEND NOTIFICATION
await sendNotificationMobileToOneUser({
recipientId: deactiveComment?.authorId as string,
senderId: data?.senderId,
payload: {
title: "Penghapusan Komentar" as NotificationMobileTitleType,
body: `Komentar anda telah dilaporkan: ${deactiveComment?.komentar}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeUserMobile.forumPreviewReportComment({ id: id }),
},
});
console.log("[DEACTIVATE COMMENT]");
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,
message: "Success deactivate comment", message: "Success deactivate comment",
data: deleteData, // data: deactiveComment,
}, },
{ status: 200 } { status: 200 }
); );

View File

@@ -1,6 +1,12 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import _ from "lodash"; import _ from "lodash";
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, PUT }; export { GET, PUT };
@@ -78,14 +84,23 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function PUT(request: Request, { params }: { params: { id: string } }) { async function PUT(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const data = await request.json();
const { senderId } = data;
console.log("SENDER POSTING", data);
try { try {
const data = await prisma.forum_Posting.update({ const deactivePosting = await prisma.forum_Posting.update({
where: { where: {
id: id, id: id,
}, },
data: { data: {
isActive: false, isActive: false,
}, },
select: {
authorId: true,
diskusi: true,
},
}); });
const deactivateComment = await prisma.forum_Komentar.updateMany({ const deactivateComment = await prisma.forum_Komentar.updateMany({
@@ -97,12 +112,25 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
console.log("[DEACTIVATE COMMENT]", deactivateComment); // SEND NOTIFICATION
await sendNotificationMobileToOneUser({
recipientId: deactivePosting?.authorId as string,
senderId: senderId,
payload: {
title: "Penghapusan Postingan" as NotificationMobileTitleType,
body: `Postingan anda telah dilaporkan: ${deactivePosting?.diskusi}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeUserMobile.forumPreviewReportPosting({ id: id }),
},
});
console.log("[DEACTIVATE POSTINGAN & COMMENT]", deactivateComment);
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,
message: "Success deactivate posting", message: "Success deactivate posting",
data: data, data: deactivePosting,
}, },
{ status: 200 } { status: 200 }
); );

View File

@@ -1,5 +1,11 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, PUT }; export { GET, PUT };
@@ -65,19 +71,39 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
data: { data: {
statusInvoiceId: "4", statusInvoiceId: "4",
}, },
// select: { select: {
// StatusInvoice: true, Investasi: {
// authorId: true, select: {
// }, title: true,
},
},
authorId: true,
},
});
// SEND NOTIFICAtION
await sendNotificationMobileToOneUser({
recipientId: updt?.authorId as string,
senderId: data?.senderId || "",
payload: {
title: "Transaksi Tertolak" as NotificationMobileTitleType,
body: `Maaf transaksi kamu telah ditolak ! ${updt?.Investasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentTransaction,
},
}); });
fixData = updt; fixData = updt;
} else if (category === "accept") { } else if (category === "accept") {
const dataInvestasi: any = await prisma.investasi.findFirst({ const findInvestasi = await prisma.investasi.findFirst({
where: { where: {
id: data.investasiId, id: data.investasiId,
}, },
select: { select: {
id: true,
title: true,
authorId: true,
totalLembar: true, totalLembar: true,
sisaLembar: true, sisaLembar: true,
lembarTerbeli: true, lembarTerbeli: true,
@@ -85,30 +111,33 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
}); });
// Hitung TOTAL SISA LEMBAR // Hitung TOTAL SISA LEMBAR
const investasi_sisaLembar = Number(dataInvestasi?.sisaLembar); const investasi_sisaLembar = Number(findInvestasi?.sisaLembar);
const invoice_lembarTerbeli = Number(data.lembarTerbeli); const invoice_lembarTerbeli = Number(data.lembarTerbeli);
const resultSisaLembar = investasi_sisaLembar - invoice_lembarTerbeli; const resultSisaLembar = investasi_sisaLembar - invoice_lembarTerbeli;
// TAMBAH LEMBAR TERBELI // TAMBAH LEMBAR TERBELI
const investasi_lembarTerbeli = Number(dataInvestasi?.lembarTerbeli); const investasi_lembarTerbeli = Number(findInvestasi?.lembarTerbeli);
const resultLembarTerbeli = const resultLembarTerbeli =
investasi_lembarTerbeli + invoice_lembarTerbeli; investasi_lembarTerbeli + invoice_lembarTerbeli;
// Progress // Progress
const investasi_totalLembar = Number(dataInvestasi?.totalLembar); const investasi_totalLembar = Number(findInvestasi?.totalLembar);
const progress = (resultLembarTerbeli / investasi_totalLembar) * 100; const progress = (resultLembarTerbeli / investasi_totalLembar) * 100;
const resultProgres = Number(progress).toFixed(2); const resultProgres = Number(progress).toFixed(2);
const updt = await prisma.investasi_Invoice.update({ const updateInvoice = await prisma.investasi_Invoice.update({
where: { where: {
id: id, id: id,
}, },
data: { data: {
statusInvoiceId: "1", statusInvoiceId: "1",
}, },
select: {
authorId: true,
},
}); });
if (!updt) { if (!updateInvoice) {
return NextResponse.json( return NextResponse.json(
{ {
success: false, success: false,
@@ -144,7 +173,35 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
); );
} }
fixData = updt; // SEND NOTIFICATION: to investor
await sendNotificationMobileToOneUser({
recipientId: updateInvoice?.authorId as string,
senderId: data?.senderId || "",
payload: {
title: "Transaksi Berhasil" as NotificationMobileTitleType,
body: `Selamat anda menjadi investor pada investasi ${findInvestasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentTransaction,
},
});
// SEND NOTIFICATION: to creator
await sendNotificationMobileToOneUser({
recipientId: findInvestasi?.authorId as any,
senderId: data?.senderId || "",
payload: {
title: "Ada Investor Baru !" as NotificationMobileTitleType,
body: `Cek daftar investor pada ${findInvestasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({
id: findInvestasi?.id as string,
}),
},
});
fixData = updateInvoice;
} else { } else {
return NextResponse.json( return NextResponse.json(
{ {

View File

@@ -1,11 +1,20 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import {
sendNotificationMobileToManyUser,
sendNotificationMobileToOneUser,
} from "@/lib/mobile/notification/send-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
export { GET, PUT }; export { GET, PUT };
async function GET(request: Request, { params }: { params: { id: string } }) { async function GET(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
try { try {
const data = await prisma.investasi.findUnique({ const data = await prisma.investasi.findUnique({
where: { where: {
@@ -78,14 +87,19 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function PUT(request: Request, { params }: { params: { id: string } }) { async function PUT(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { catatan, senderId } = data;
console.log("[DATA]", data);
console.log("[CATATAN]", catatan);
console.log("[SENDER ID]", senderId);
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const status = searchParams.get("status"); const status = searchParams.get("status");
console.log("[=======Start Investment console=======]"); // console.log("[=======Start Investment console=======]");
console.log("[ID]", id); // console.log("[ID]", id);
console.log("[DATA]", data); // console.log("[STATUS]", status);
console.log("[STATUS]", status); // console.log("[=======End Investment console=======]");
console.log("[=======End Investment console=======]");
const publishTime = new Date(); const publishTime = new Date();
@@ -96,9 +110,26 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
id: id, id: id,
}, },
data: { data: {
catatan: data, catatan: catatan,
masterStatusInvestasiId: "4", masterStatusInvestasiId: "4",
}, },
select: {
authorId: true,
title: true,
},
});
// SEND NOTIFICATION
await sendNotificationMobileToOneUser({
recipientId: updatedData.authorId as any,
senderId: senderId,
payload: {
title: "Pengajuan Review Ditolak",
body: "Mohon perbaiki data sesuai catatan penolakan !",
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentPortofolioByStatus({ status: "reject" }),
},
}); });
console.log("[UPDATE REJECT]", updatedData); console.log("[UPDATE REJECT]", updatedData);
@@ -114,6 +145,39 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
// SEND NOTIFICAtION
await sendNotificationMobileToOneUser({
recipientId: updatedData.authorId as any,
senderId: senderId,
payload: {
title: "Review Selesai",
body: `Investasi kamu telah dipublikasikan ! ${updatedData.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentPortofolioByStatus({ status: "publish" }),
},
});
const allUsers = await prisma.user.findMany({
where: {
NOT: { id: updatedData.authorId as any },
active: true,
},
select: { id: true },
});
await sendNotificationMobileToManyUser({
recipientIds: allUsers.map((user) => user.id),
senderId: senderId,
payload: {
title: "Ayo Cek Investasi Terbaru" as NotificationMobileTitleType,
body: `${updatedData.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({ id: id }),
},
});
console.log("[UPDATE PUBLISH]", updatedData); console.log("[UPDATE PUBLISH]", updatedData);
} }

View File

@@ -6,7 +6,7 @@ import {
sendNotificationMobileToOneUser, sendNotificationMobileToOneUser,
} from "@/lib/mobile/notification/send-notification"; } from "@/lib/mobile/notification/send-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile"; import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
import { NotificationMobileBodyType } from "../../../../../../../types/type-mobile-notification"; import { NotificationMobileBodyType, NotificationMobileTitleType } from "../../../../../../../types/type-mobile-notification";
export { GET, PUT }; export { GET, PUT };
@@ -110,8 +110,8 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
recipientId: updt.authorId as any, recipientId: updt.authorId as any,
senderId: senderId, senderId: senderId,
payload: { payload: {
title: "Pengajuan Review", title: "Pengajuan Review Ditolak",
body: "Pengajuan data anda telah di tolak !", body: "Mohon perbaiki data sesuai catatan penolakan !",
type: "announcement", type: "announcement",
kategoriApp: "JOB", kategoriApp: "JOB",
deepLink: routeUserMobile.jobByStatus({ status: "reject" }), deepLink: routeUserMobile.jobByStatus({ status: "reject" }),
@@ -143,7 +143,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
recipientId: updt.authorId as any, recipientId: updt.authorId as any,
senderId: senderId, senderId: senderId,
payload: { payload: {
title: "Pengajuan Review", title: "Review Selesai",
body: "Selamat data anda telah terpublikasi", body: "Selamat data anda telah terpublikasi",
type: "announcement", type: "announcement",
kategoriApp: "JOB", kategoriApp: "JOB",
@@ -160,7 +160,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
recipientIds: adminUsers.map((user) => user.id), recipientIds: adminUsers.map((user) => user.id),
senderId: data.authorId, senderId: data.authorId,
payload: { payload: {
title: "Ada lowongan kerja baru", title: "Ada Lowongan Kerja Baru" as NotificationMobileTitleType,
body: `${updt.title}` as NotificationMobileBodyType, body: `${updt.title}` as NotificationMobileBodyType,
type: "announcement", type: "announcement",
deepLink: routeUserMobile.jobDetailPublised({ id: id }), deepLink: routeUserMobile.jobDetailPublised({ id: id }),

View File

@@ -1,4 +1,5 @@
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import { funSendToWhatsApp } from "@/lib/code-otp-sender";
import _ from "lodash"; import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
@@ -50,8 +51,25 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
data: { data: {
active: data.active, active: data.active,
}, },
select: {
nomor: true,
},
}); });
if (data.active) {
const resSendCode = await funSendToWhatsApp({
nomor: updateData.nomor,
newMessage:
"Halo sahabat HIConnect, \nSelamat akun anda telah aktif ! \n\n*Pesan ini di kirim secara otomatis, tidak perlu di balas.",
});
} else {
const resSendCode = await funSendToWhatsApp({
nomor: updateData.nomor,
newMessage:
"Halo sahabat HIConnect, \nMohon maaf akun anda telah dinonaktifkan ! Hubungi admin untuk informasi lebih lanjut. \n\n*Pesan ini di kirim secara otomatis, tidak perlu di balas.",
});
}
console.log("[Update Active Berhasil]", updateData); console.log("[Update Active Berhasil]", updateData);
} else if (category === "role") { } else if (category === "role") {
const fixName = _.startCase(data.role.replace(/_/g, " ")); const fixName = _.startCase(data.role.replace(/_/g, " "));

View File

@@ -1,8 +1,17 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import _ from "lodash"; import _ from "lodash";
import {
sendNotificationMobileToManyUser,
sendNotificationMobileToOneUser,
} from "@/lib/mobile/notification/send-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
export { GET , PUT}; export { GET, PUT };
async function GET(request: Request, { params }: { params: { id: string } }) { async function GET(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
@@ -41,12 +50,16 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function PUT(request: Request, { params }: { params: { id: string } }) { async function PUT(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { catatan, senderId } = data;
console.log("catatan", catatan);
console.log("senderId", senderId);
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const status = searchParams.get("status"); const status = searchParams.get("status");
const fixStatus = _.startCase(status as string); const fixStatus = _.startCase(status as string);
let fixData; let fixData;
try { try {
const checkStatus = await prisma.voting_Status.findFirst({ const checkStatus = await prisma.voting_Status.findFirst({
where: { where: {
@@ -71,9 +84,23 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}, },
data: { data: {
voting_StatusId: checkStatus.id, voting_StatusId: checkStatus.id,
catatan: data, catatan: catatan,
}, },
}); });
// SEND NOTIFICATION
await sendNotificationMobileToOneUser({
recipientId: updateStatus.authorId as any,
senderId: senderId,
payload: {
title: "Pengajuan Review Ditolak",
body: "Mohon perbaiki data sesuai catatan penolakan !",
type: "announcement",
kategoriApp: "VOTING",
deepLink: routeUserMobile.votingByStatus({ status: "reject" }),
},
});
fixData = updateStatus; fixData = updateStatus;
} else if (fixStatus === "Publish") { } else if (fixStatus === "Publish") {
const updateStatus = await prisma.voting.update({ const updateStatus = await prisma.voting.update({
@@ -84,6 +111,39 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
voting_StatusId: checkStatus.id, voting_StatusId: checkStatus.id,
}, },
}); });
await sendNotificationMobileToOneUser({
recipientId: updateStatus.authorId as any,
senderId: senderId,
payload: {
title: "Review Selesai",
body: "Voting kamu telah dipublikasikan !" as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "VOTING",
deepLink: routeUserMobile.votingByStatus({ status: "publish" }),
},
});
const adminUsers = await prisma.user.findMany({
where: {
masterUserRoleId: "1",
NOT: { id: updateStatus.authorId as any },
},
select: { id: true },
});
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: senderId,
payload: {
title: "Cek Voting Baru Terpublikasi" as NotificationMobileTitleType,
body: `${updateStatus.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "VOTING",
deepLink: routeUserMobile.votingDetailPublised({ id: id }),
},
});
fixData = updateStatus; fixData = updateStatus;
} }

View File

@@ -1,6 +1,12 @@
import _ from "lodash"; import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET, PUT }; export { POST, GET, PUT };
@@ -33,6 +39,14 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
if (!create) {
return NextResponse.json({
status: 500,
success: false,
message: "Gagal membuat invoice",
});
}
return NextResponse.json({ return NextResponse.json({
status: 201, status: 201,
success: true, success: true,
@@ -48,7 +62,7 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
reason: (error as Error).message, reason: (error as Error).message,
}); });
} }
} }
async function GET(request: Request, { params }: { params: { id: string } }) { async function GET(request: Request, { params }: { params: { id: string } }) {
try { try {
@@ -65,7 +79,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
createdAt: true, createdAt: true,
donasiMaster_BankId: true, donasiMaster_BankId: true,
donasiMaster_StatusInvoiceId: true, donasiMaster_StatusInvoiceId: true,
MasterBank: true, MasterBank: true,
Donasi: { Donasi: {
select: { select: {
id: true, id: true,
@@ -139,7 +153,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}); });
} }
const update = await prisma.donasi_Invoice.update({ const updated = await prisma.donasi_Invoice.update({
where: { where: {
id: id, id: id,
}, },
@@ -164,7 +178,40 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
console.log("[UPDATE INVOICE]", update); if (!updated) {
return NextResponse.json({
status: 500,
success: false,
message: "Gagal memperbarui data",
});
}
const findUsers = await prisma.user.findMany({
where: {
masterUserRoleId: "2",
active: true,
NOT: { id: updated?.Donasi?.authorId as string },
},
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: findUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Ada Donasi Baru !" as NotificationMobileTitleType,
body: `Cek data investor pada ${updated?.Donasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeAdminMobile.donationDetailPublish({
id: updated?.Donasi?.id as string,
status: "publish",
}),
},
});
console.log("[UPDATE INVOICE]", updated);
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,

View File

@@ -1,25 +1,39 @@
import { NextRequest, NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import _ from "lodash"; import _ from "lodash";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
import { funFindDonaturList } from "@/lib/mobile/donation/find-donatur-list";
export { POST, GET, PUT, DELETE }; export { POST, GET, PUT, DELETE };
async function POST( async function POST(
request: NextRequest, request: NextRequest,
{ params }: { params: { id: string } } { params }: { params: { id: string } },
) { ) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { title, deskripsi, imageId } = data;
const senderId = await prisma.donasi.findUnique({
where: { id: id },
select: {
authorId: true,
},
});
try { try {
if (data && data?.imageId) { if (data && data?.imageId) {
const createWithFile = await prisma.donasi_Kabar.create({ const createWithFile = await prisma.donasi_Kabar.create({
data: { data: {
title: data.title, title: title,
deskripsi: data.deskripsi, deskripsi: deskripsi,
donasiId: id, donasiId: id,
imageId: data.imageId, imageId: imageId,
}, },
}); });
@@ -28,8 +42,8 @@ async function POST(
} else { } else {
const create = await prisma.donasi_Kabar.create({ const create = await prisma.donasi_Kabar.create({
data: { data: {
title: data.title, title: title,
deskripsi: data.deskripsi, deskripsi: deskripsi,
donasiId: id, donasiId: id,
}, },
}); });
@@ -38,6 +52,25 @@ async function POST(
return NextResponse.json({ status: 400, message: "Gagal disimpan" }); return NextResponse.json({ status: 400, message: "Gagal disimpan" });
} }
const recipientIds = await funFindDonaturList(id);
// SEND NOTIFICATION
if (recipientIds.length > 0) {
await sendNotificationMobileToManyUser({
recipientIds,
senderId: senderId?.authorId!,
payload: {
title: "Berita terbaru" as NotificationMobileTitleType,
body: `Ada berita terupdate pada ${title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "DONASI",
deepLink: routeUserMobile.donationDetailPublish({
id: id,
}),
},
});
}
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
success: true, success: true,
@@ -56,7 +89,7 @@ async function POST(
async function GET( async function GET(
request: NextRequest, request: NextRequest,
{ params }: { params: { id: string } } { params }: { params: { id: string } },
) { ) {
const { id } = params; const { id } = params;
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
@@ -178,7 +211,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
async function DELETE( async function DELETE(
request: Request, request: Request,
{ params }: { params: { id: string } } { params }: { params: { id: string } },
) { ) {
const { id } = params; const { id } = params;
try { try {
@@ -198,7 +231,7 @@ async function DELETE(
headers: { headers: {
Authorization: `Bearer ${process.env.WS_APIKEY}`, Authorization: `Bearer ${process.env.WS_APIKEY}`,
}, },
} },
); );
if (!deleteImage) { if (!deleteImage) {

View File

@@ -1,8 +1,11 @@
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import _ from "lodash"; import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { NotificationMobileBodyType } from "../../../../../types/type-mobile-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
export { POST }; export { POST, GET };
async function POST(request: Request) { async function POST(request: Request) {
const { data } = await request.json(); const { data } = await request.json();
@@ -49,6 +52,26 @@ async function POST(request: Request) {
console.log("[DATA DONASI]", dataDonasi); console.log("[DATA DONASI]", dataDonasi);
const adminUsers = await prisma.user.findMany({
where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Pengajuan Review Baru",
body: data.title as NotificationMobileBodyType,
type: "announcement",
deepLink: routeAdminMobile.donationByStatus({ status: "review" }),
kategoriApp: "DONASI",
},
});
if (!dataDonasi) if (!dataDonasi)
return NextResponse.json({ return NextResponse.json({
status: 400, status: 400,
@@ -98,7 +121,7 @@ async function POST(request: Request) {
} }
// GET ALL DATA DONASI // GET ALL DATA DONASI
export async function GET(request: Request) { async function GET(request: Request) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const category = searchParams.get("category"); const category = searchParams.get("category");
const authorId = searchParams.get("authorId"); const authorId = searchParams.get("authorId");

View File

@@ -1,5 +1,11 @@
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, POST }; export { GET, POST };
@@ -13,18 +19,28 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
eventId: id, eventId: id,
userId: userId, userId: userId,
}, },
// select: {
// Event: {
// select: {
// id: true,
// title: true,
// authorId: true,
// },
// },
// },
}); });
const findEvent = await prisma.event.findUnique({
where: { id: id },
select: { authorId: true, title: true },
});
// SEND NOTIFICATION
if (userId !== findEvent?.authorId) {
await sendNotificationMobileToOneUser({
recipientId: findEvent?.authorId as string,
senderId: userId,
payload: {
title: "Peserta Baru Join" as NotificationMobileTitleType,
body: `Ada peserta baru dalam event: ${findEvent?.title}` as NotificationMobileBodyType,
type: "announcement",
deepLink: routeUserMobile.eventDetailPublised({ id: id }),
kategoriApp: "EVENT",
},
});
}
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,

View File

@@ -1,7 +1,10 @@
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import _ from "lodash"; import _ from "lodash";
import moment from "moment"; import moment from "moment";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { NotificationMobileBodyType } from "../../../../../types/type-mobile-notification";
export { GET, POST }; export { GET, POST };
@@ -30,6 +33,24 @@ async function POST(request: Request) {
}, },
}); });
const adminUsers = await prisma.user.findMany({
where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Pengajuan Review Baru",
body: create.title as NotificationMobileBodyType,
type: "announcement",
deepLink: routeAdminMobile.eventByStatus({ status: "review" }),
kategoriApp: "EVENT",
},
});
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,

View File

@@ -1,11 +1,18 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET, DELETE }; export { POST, GET, DELETE };
async function POST(request: Request, { params }: { params: { id: string } }) { async function POST(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { comment, authorId } = data;
console.log("[ID COMMENT]", id); console.log("[ID COMMENT]", id);
console.log("[DATA COMMENT]", data); console.log("[DATA COMMENT]", data);
@@ -14,8 +21,8 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
const createComment = await prisma.forum_Komentar.create({ const createComment = await prisma.forum_Komentar.create({
data: { data: {
forum_PostingId: id, forum_PostingId: id,
komentar: data.comment, komentar: comment,
authorId: data.authorId, authorId: authorId,
}, },
select: { select: {
id: true, id: true,
@@ -38,6 +45,24 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
const findForum = await prisma.forum_Posting.findUnique({
where: { id: id },
select: { authorId: true, diskusi: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToOneUser({
recipientId: findForum?.authorId as string,
senderId: authorId,
payload: {
title: "Komentar Baru" as NotificationMobileTitleType,
body: `Ayo cek komentar pada postingan: ${findForum?.diskusi}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeUserMobile.forumDetail({ id: id }),
},
});
if (!createComment) { if (!createComment) {
return NextResponse.json({ return NextResponse.json({
status: 400, status: 400,
@@ -52,7 +77,6 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
message: "Berhasil update data", message: "Berhasil update data",
data: createComment, data: createComment,
}); });
} catch (error) { } catch (error) {
console.log("[ERROR COMMENT]", error); console.log("[ERROR COMMENT]", error);
return NextResponse.json({ return NextResponse.json({
@@ -66,9 +90,15 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
async function GET(request: Request, { params }: { params: { id: string } }) { async function GET(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { searchParams } = new URL(request.url);
const page = Number(searchParams.get("page"));
const takeData = 5
const skipData = page * takeData - takeData;
try { try {
const data = await prisma.forum_Komentar.findMany({ const data = await prisma.forum_Komentar.findMany({
take: page ? takeData : undefined,
skip: page ? skipData : undefined,
orderBy: { orderBy: {
createdAt: "desc", createdAt: "desc",
}, },
@@ -114,7 +144,10 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
} }
} }
async function DELETE(request: Request, { params }: { params: { id: string } }) { async function DELETE(
request: Request,
{ params }: { params: { id: string } }
) {
const { id } = params; const { id } = params;
try { try {
@@ -146,4 +179,4 @@ async function DELETE(request: Request, { params }: { params: { id: string } })
reason: (error as Error).message || error, reason: (error as Error).message || error,
}); });
} }
} }

View File

@@ -0,0 +1,42 @@
import { NextResponse } from "next/server";
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const { id } = params;
try {
const data = await prisma.forum_Komentar.findUnique({
where: {
id: id,
},
select: {
id: true,
komentar: true,
isActive: true,
createdAt: true,
Forum_ReportKomentar: {
select: {
deskripsi: true,
ForumMaster_KategoriReport: true,
},
},
},
});
return NextResponse.json({
status: 200,
success: true,
data: data,
});
} catch (error) {
console.log("[ERROR]", error);
return NextResponse.json({
status: 500,
success: false,
message: "Gagal mendapatkan data posting",
reason: (error as Error).message,
});
}
}

View File

@@ -0,0 +1,49 @@
import { NextResponse } from "next/server";
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const { id } = params;
try {
const data = await prisma.forum_Posting.findUnique({
where: {
id: id,
},
select: {
id: true,
diskusi: true,
isActive: true,
createdAt: true,
authorId: true,
Author: {
select: {
id: true,
username: true,
},
},
Forum_ReportPosting: {
select: {
deskripsi: true,
ForumMaster_KategoriReport: true,
},
},
},
});
return NextResponse.json({
status: 200,
success: true,
data: data,
});
} catch (error) {
console.log("[ERROR]", error);
return NextResponse.json({
status: 500,
success: false,
message: "Gagal mendapatkan data posting",
reason: (error as Error).message,
});
}
}

View File

@@ -1,5 +1,11 @@
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
export { POST }; export { POST };
@@ -7,44 +13,70 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
let fixData; let fixData;
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
console.log("[DATA]", data); const { authorId: reportedUserId, categoryId, description } = data;
console.log("[ID]", id);
try { try {
const content = await prisma.forum_Komentar.findUnique({ // Komentar yang di report
where: { const findComment = await prisma.forum_Komentar.findUnique({
id: id, where: { id: id },
}, select: { authorId: true, komentar: true },
}); });
const reportList = await prisma.forumMaster_KategoriReport.findUnique({ // List admin untuk dikirim notifikasi
const adminUsers = await prisma.user.findMany({
where: { where: {
id: data.categoryId, masterUserRoleId: "2",
NOT: { id: findComment?.authorId as any },
}, },
select: { id: true },
}); });
const msg = `Report Komentar: "${content?.komentar}" dengan kategori \n\n\n${reportList?.title} : \n\n${reportList?.deskripsi}`; if (categoryId) {
const res = await fetch( const createdReport = await prisma.forum_ReportKomentar.create({
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=6282340374412&text=${msg}`,
{ cache: "no-cache" }
);
if (data.categoryId) {
fixData = await prisma.forum_ReportKomentar.create({
data: { data: {
forum_KomentarId: id, forum_KomentarId: id,
userId: data.authorId, userId: reportedUserId,
forumMaster_KategoriReportId: data.categoryId as any, forumMaster_KategoriReportId: categoryId,
}, },
}); });
//SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: reportedUserId,
payload: {
title: "Laporan Dari User" as NotificationMobileTitleType,
body: `Report terhadap komentar, ${findComment?.komentar}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeAdminMobile.forumPreviewReportComment,
},
});
fixData = createdReport;
} else { } else {
fixData = await prisma.forum_ReportKomentar.create({ const createdReport = await prisma.forum_ReportKomentar.create({
data: { data: {
forum_KomentarId: id, forum_KomentarId: id,
userId: data.authorId, userId: reportedUserId,
deskripsi: data.description, deskripsi: description,
}, },
}); });
//SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: reportedUserId,
payload: {
title: "Laporan Dari User" as NotificationMobileTitleType,
body: `Report terhadap komentar, ${findComment?.komentar}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeAdminMobile.forumPreviewReportComment,
},
});
fixData = createdReport;
} }
if (!fixData) { if (!fixData) {

View File

@@ -1,5 +1,15 @@
import { NextResponse } from "next/server"; import {
sendNotificationMobileToManyUser
} from "@/lib/mobile/notification/send-notification";
import {
routeAdminMobile
} from "@/lib/mobile/route-page-mobile";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { NextResponse } from "next/server";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
export { POST }; export { POST };
@@ -7,38 +17,70 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
let fixData; let fixData;
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
console.log("[DATA]", data); const { authorId: reportedUserId, categoryId, description } = data;
console.log("[ID]", id);
try { try {
const content = await prisma.forum_Posting.findUnique({ // Postingan yang akan di report
where: { const findPosting = await prisma.forum_Posting.findUnique({
id: id, where: { id: id },
}, select: { authorId: true, diskusi: true },
}); });
const msg = `Report Postingan: "${content?.diskusi}"`; // List admin untuk dikirim notifikasi
const res = await fetch( const adminUsers = await prisma.user.findMany({
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=6282340374412&text=${msg}`, where: {
{ cache: "no-cache" } masterUserRoleId: "2",
); NOT: { id: findPosting?.authorId as any },
},
select: { id: true },
});
if (data.categoryId) { if (categoryId) {
fixData = await prisma.forum_ReportPosting.create({ const createReported = await prisma.forum_ReportPosting.create({
data: { data: {
forum_PostingId: id, forum_PostingId: id,
userId: data.authorId, userId: reportedUserId,
forumMaster_KategoriReportId: data.categoryId, forumMaster_KategoriReportId: categoryId,
}, },
}); });
//SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: reportedUserId,
payload: {
title: "Laporan Dari User" as NotificationMobileTitleType,
body: `Report terhadap postingan, ${findPosting?.diskusi}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeAdminMobile.forumPreviewReportPosting,
},
});
fixData = createReported;
} else { } else {
fixData = await prisma.forum_ReportPosting.create({ const createReported = await prisma.forum_ReportPosting.create({
data: { data: {
forum_PostingId: id, forum_PostingId: id,
userId: data.authorId, userId: reportedUserId,
deskripsi: data.description, deskripsi: description,
}, },
}); });
//SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: reportedUserId,
payload: {
title: "Laporan Dari User" as NotificationMobileTitleType,
body: `Report terhadap postingan, ${findPosting?.diskusi}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeAdminMobile.forumPreviewReportPosting,
},
});
fixData = createReported;
} }
if (!fixData) { if (!fixData) {
@@ -63,4 +105,4 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
reason: (error as Error).message, reason: (error as Error).message,
}); });
} }
} }

View File

@@ -1,22 +1,54 @@
import _ from "lodash"; import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { NotificationMobileBodyType, NotificationMobileTitleType } from "../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET }; export { POST, GET };
async function POST(request: Request) { async function POST(request: Request) {
const { data } = await request.json(); const { data } = await request.json();
console.log("[DATA]", data); console.log("[DATA]", data);
const { diskusi, authorId } = data;
try { try {
const create = await prisma.forum_Posting.create({ const create = await prisma.forum_Posting.create({
data: { data: {
diskusi: data.diskusi, diskusi: diskusi,
authorId: data.authorId, authorId: authorId,
forumMaster_StatusPostingId: 1, forumMaster_StatusPostingId: 1,
}, },
}); });
if (!create) {
return NextResponse.json({
success: false,
message: "Gagal memposting",
status: 400,
});
}
const allUsers = await prisma.user.findMany({
where: {
id: { not: authorId },
},
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: allUsers.map((user) => user.id),
senderId: authorId,
payload: {
title: "Ada Diskusi Baru" as NotificationMobileTitleType,
body: `${diskusi}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "FORUM",
deepLink: routeUserMobile.forumBeranda,
},
});
return NextResponse.json({ return NextResponse.json({
success: true, success: true,
message: "Berhasil membuat postingan", message: "Berhasil membuat postingan",
@@ -43,7 +75,6 @@ async function GET(request: Request) {
const takeData = 5; const takeData = 5;
const skipData = (Number(page) - 1) * takeData; const skipData = (Number(page) - 1) * takeData;
// console.log("authorId", authorId); // console.log("authorId", authorId);
// console.log("userLoginId", userLoginId); // console.log("userLoginId", userLoginId);
// console.log("search", search); // console.log("search", search);
@@ -83,7 +114,7 @@ async function GET(request: Request) {
notIn: blockUserId, notIn: blockUserId,
}, },
}, },
select: { select: {
id: true, id: true,
diskusi: true, diskusi: true,
@@ -128,13 +159,12 @@ async function GET(request: Request) {
fixData = newData; fixData = newData;
} else if (category === "forumku") { } else if (category === "forumku") {
const count = await prisma.forum_Posting.count({ const count = await prisma.forum_Posting.count({
where: { where: {
isActive: true, isActive: true,
authorId: authorId, authorId: authorId,
}, },
}) });
const data = await prisma.forum_Posting.findMany({ const data = await prisma.forum_Posting.findMany({
take: page ? takeData : undefined, take: page ? takeData : undefined,
@@ -191,7 +221,7 @@ async function GET(request: Request) {
const dataFix = { const dataFix = {
data: newData, data: newData,
count, count,
} };
fixData = dataFix; fixData = dataFix;
} else { } else {

View File

@@ -1,5 +1,11 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeAdminMobile, routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET, DELETE }; export { POST, GET, DELETE };
@@ -10,7 +16,7 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
console.log("[POST DOCUMENT DATA]", data); console.log("[POST DOCUMENT DATA]", data);
try { try {
const create = await prisma.dokumenInvestasi.upsert({ const createdDocs = await prisma.dokumenInvestasi.upsert({
where: { where: {
id: id, id: id,
}, },
@@ -23,9 +29,49 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
title: data.title, title: data.title,
fileId: data.fileId, fileId: data.fileId,
}, },
select: {
investasiId: true,
investasi: {
select: {
title: true,
authorId: true,
},
},
},
}); });
if (!create) console.log("[CREATED DOCS]", createdDocs);
const findInvestor = await prisma.investasi_Invoice.findMany({
where: {
investasiId: id,
StatusInvoice: {
name: "Berhasil",
},
},
select: {
authorId: true,
},
});
console.log("[FIND INVESTOR]", findInvestor);
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: findInvestor.map((e) => e.authorId!),
senderId: createdDocs.investasi?.authorId as string,
payload: {
title: "Cek Dokumen" as NotificationMobileTitleType,
body: `Ada dokumen terupdate pada ${createdDocs.investasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({
id: createdDocs.investasiId as string,
}),
},
});
if (!createdDocs)
return NextResponse.json({ return NextResponse.json({
status: 201, status: 201,
success: true, success: true,
@@ -93,7 +139,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function DELETE( async function DELETE(
request: Request, request: Request,
{ params }: { params: { id: string } } { params }: { params: { id: string } },
) { ) {
const { id } = params; const { id } = params;
@@ -111,9 +157,9 @@ async function DELETE(
headers: { headers: {
Authorization: `Bearer ${process.env.WS_APIKEY}`, Authorization: `Bearer ${process.env.WS_APIKEY}`,
}, },
} },
); );
return NextResponse.json({ return NextResponse.json({
status: 200, status: 200,
success: true, success: true,

View File

@@ -1,6 +1,12 @@
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
import _ from "lodash"; import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import {
NotificationMobileTitleType,
NotificationMobileBodyType,
} from "../../../../../../../types/type-mobile-notification";
export { POST, GET, PUT }; export { POST, GET, PUT };
@@ -49,7 +55,6 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
const authorId = searchParams.get("authorId"); const authorId = searchParams.get("authorId");
console.log("[ID INVOICE]", id); console.log("[ID INVOICE]", id);
let fixData; let fixData;
@@ -198,8 +203,49 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
statusInvoiceId: checkStatus.id, statusInvoiceId: checkStatus.id,
imageId: data.imageId, imageId: data.imageId,
}, },
select: {
investasiId: true,
},
}); });
if (fixStatus === "Proses") {
// kirim notif ke author investasi
const findInvestasi = await prisma.investasi.findUnique({
where: {
id: update.investasiId as any,
},
select: {
title: true,
authorId: true,
},
});
const findUsers = await prisma.user.findMany({
where: {
masterUserRoleId: "2",
active: true,
NOT: { id: findInvestasi?.authorId as any },
},
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: findUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Ada Investor Baru !" as NotificationMobileTitleType,
body: `Cek data investor pada ${findInvestasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeAdminMobile.investmentDetailPublish({
id: update.investasiId as string,
status: "publish",
}),
},
});
}
console.log("[UPDATE]", update); console.log("[UPDATE]", update);
return NextResponse.json({ return NextResponse.json({

View File

@@ -1,6 +1,7 @@
import _ from "lodash"; import _ from "lodash";
import { prisma } from "@/lib"; import { prisma } from "@/lib";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { sendNotificationInvestmentAddNews } from "@/lib/mobile/notification/notification-add-news-investment";
export { POST, GET, DELETE }; export { POST, GET, DELETE };
@@ -21,6 +22,21 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
deskripsi: data.deskripsi, deskripsi: data.deskripsi,
imageId: data.imageId, imageId: data.imageId,
}, },
select: {
investasiId: true,
investasi: {
select: {
title: true,
authorId: true,
},
},
},
});
await sendNotificationInvestmentAddNews({
invesmentId: createWithFile.investasiId,
senderId: createWithFile.investasi.authorId as string,
title: createWithFile.investasi.title,
}); });
fixData = createWithFile; fixData = createWithFile;
@@ -31,6 +47,21 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
title: _.startCase(data.title), title: _.startCase(data.title),
deskripsi: data.deskripsi, deskripsi: data.deskripsi,
}, },
select: {
investasiId: true,
investasi: {
select: {
title: true,
authorId: true,
},
},
},
});
await sendNotificationInvestmentAddNews({
invesmentId: createWitOutFile.investasiId,
senderId: createWitOutFile.investasi.authorId as string,
title: createWitOutFile.investasi.title,
}); });
fixData = createWitOutFile; fixData = createWitOutFile;
@@ -111,7 +142,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function DELETE( async function DELETE(
request: Request, request: Request,
{ params }: { params: { id: string } } { params }: { params: { id: string } },
) { ) {
const { id } = params; const { id } = params;
console.log("id", id); console.log("id", id);

View File

@@ -2,6 +2,9 @@ import _ from "lodash";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import moment from "moment"; import moment from "moment";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { NotificationMobileBodyType } from "../../../../../types/type-mobile-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET }; export { POST, GET };
@@ -9,12 +12,14 @@ async function POST(request: Request) {
const { data } = await request.json(); const { data } = await request.json();
console.log(["DATA INVESTASI"], data); console.log(["DATA INVESTASI"], data);
const fixTitle = _.startCase(data.title)
try { try {
const create = await prisma.investasi.create({ const create = await prisma.investasi.create({
data: { data: {
masterStatusInvestasiId: "2", masterStatusInvestasiId: "2",
authorId: data.authorId, authorId: data.authorId,
title: _.startCase(data.title), title: fixTitle,
targetDana: data.targetDana, targetDana: data.targetDana,
hargaLembar: data.hargaLembar, hargaLembar: data.hargaLembar,
totalLembar: data.totalLembar, totalLembar: data.totalLembar,
@@ -30,6 +35,24 @@ async function POST(request: Request) {
console.log("[CREATE INVESTASI]", create); console.log("[CREATE INVESTASI]", create);
const adminUsers = await prisma.user.findMany({
where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Pengajuan Review Baru",
body: fixTitle as NotificationMobileBodyType,
type: "announcement",
deepLink: routeAdminMobile.investmentByStatus({ status: "review" }),
kategoriApp: "INVESTASI",
},
});
return NextResponse.json({ return NextResponse.json({
status: 201, status: 201,
success: true, success: true,

View File

@@ -2,6 +2,7 @@ import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile"; import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { NotificationMobileBodyType } from "../../../../../types/type-mobile-notification";
export { POST, GET }; export { POST, GET };
@@ -30,8 +31,8 @@ async function POST(request: Request) {
recipientIds: adminUsers.map((user) => user.id), recipientIds: adminUsers.map((user) => user.id),
senderId: data.authorId, senderId: data.authorId,
payload: { payload: {
title: "Pengajuan Review", title: "Pengajuan Review Baru",
body: "Terdapat pengajuan baru yang perlu direview", body: `${create.title}` as NotificationMobileBodyType,
type: "announcement", type: "announcement",
deepLink: routeAdminMobile.jobByStatus({ status: "review" }), deepLink: routeAdminMobile.jobByStatus({ status: "review" }),
kategoriApp: "JOB", kategoriApp: "JOB",

View File

@@ -45,23 +45,38 @@ export async function PUT(
{ params }: { params: { id: string } } { params }: { params: { id: string } }
) { ) {
const { id } = params; const { id } = params;
const { searchParams } = new URL(request.url);
const category = searchParams.get("category");
try { try {
await prisma.notifikasi.update({ if (category === "one") {
where: { await prisma.notifikasi.update({
id: id, where: {
}, id: id,
data: { },
isRead: true, data: {
readAt: new Date(), isRead: true,
}, readAt: new Date(),
}); },
});
} else if (category === "all") {
await prisma.notifikasi.updateMany({
where: {
recipientId: id,
},
data: {
isRead: true,
readAt: new Date(),
},
});
}
return NextResponse.json({ return NextResponse.json({
success: true, success: true,
message: "Notifications marked as read", message: "Notifications marked as read",
}); });
} catch (error) { } catch (error) {
console.error("Error marking notifications as read:", error);
return NextResponse.json( return NextResponse.json(
{ error: (error as Error).message }, { error: (error as Error).message },
{ status: 500 } { status: 500 }
@@ -69,129 +84,129 @@ export async function PUT(
} }
} }
export async function POST( // export async function POST(
request: NextRequest, // request: NextRequest,
{ params }: { params: { id: string } } // { params }: { params: { id: string } }
) { // ) {
const { id } = params; // const { id } = params;
const { data } = await request.json(); // const { data } = await request.json();
const { // const {
title, // title,
body: notificationBody, // body: notificationBody,
userLoginId, // userLoginId,
type, // type,
kategoriApp, // kategoriApp,
appId, // appId,
status, // status,
deepLink, // deepLink,
} = data as NotificationProp; // } = data as NotificationProp;
console.log("Notification Send >>", data); // console.log("Notification Send >>", data);
try { // try {
// Cari user yang login // // Cari user yang login
const findUserLogin = await prisma.user.findUnique({ // const findUserLogin = await prisma.user.findUnique({
where: { // where: {
id: userLoginId, // id: userLoginId,
}, // },
}); // });
if (!findUserLogin) { // if (!findUserLogin) {
return NextResponse.json({ error: "User not found" }, { status: 404 }); // return NextResponse.json({ error: "User not found" }, { status: 404 });
} // }
// Cari token fcm user yang login // // Cari token fcm user yang login
const checkFcmToken = await prisma.tokenUserDevice.findFirst({ // const checkFcmToken = await prisma.tokenUserDevice.findFirst({
where: { // where: {
userId: findUserLogin.id, // userId: findUserLogin.id,
}, // },
}); // });
if (!checkFcmToken) { // if (!checkFcmToken) {
return NextResponse.json( // return NextResponse.json(
{ error: "FCM Token not found" }, // { error: "FCM Token not found" },
{ status: 404 } // { status: 404 }
); // );
} // }
const created = await prisma.notifikasi.create({ // const created = await prisma.notifikasi.create({
data: { // data: {
title, // title,
type, // type,
createdAt: new Date(), // createdAt: new Date(),
appId, // appId,
kategoriApp, // kategoriApp,
pesan: notificationBody || "", // pesan: notificationBody || "",
userRoleId: findUserLogin.masterUserRoleId, // userRoleId: findUserLogin.masterUserRoleId,
status, // status,
deepLink, // deepLink,
senderId: findUserLogin.id, // senderId: findUserLogin.id,
recipientId: id, // recipientId: id,
}, // },
}); // });
if (created) { // if (created) {
const deviceToken = await prisma.tokenUserDevice.findMany({ // const deviceToken = await prisma.tokenUserDevice.findMany({
where: { // where: {
userId: id, // userId: id,
isActive: true, // isActive: true,
}, // },
}); // });
for (let i of deviceToken) { // for (let i of deviceToken) {
const message = { // const message = {
token: i.token, // token: i.token,
notification: { // notification: {
title, // title,
body: notificationBody || "", // body: notificationBody || "",
}, // },
data: { // data: {
sentAt: new Date().toISOString(), // ✅ Simpan metadata di data // sentAt: new Date().toISOString(), // ✅ Simpan metadata di data
id: created.id, // id: created.id,
deepLink: deepLink || "", // deepLink: deepLink || "",
}, // },
// Konfigurasi Android untuk prioritas tinggi // // Konfigurasi Android untuk prioritas tinggi
android: { // android: {
priority: "high" as const, // Kirim secepatnya, bahkan di doze mode untuk notifikasi penting // priority: "high" as const, // Kirim secepatnya, bahkan di doze mode untuk notifikasi penting
notification: { // notification: {
channelId: "default", // Sesuaikan dengan channel yang kamu buat di Android // channelId: "default", // Sesuaikan dengan channel yang kamu buat di Android
}, // },
ttl: 0 as const, // Kirim secepatnya, jangan tunda // ttl: 0 as const, // Kirim secepatnya, jangan tunda
}, // },
// Opsional: tambahkan untuk iOS juga // // Opsional: tambahkan untuk iOS juga
apns: { // apns: {
payload: { // payload: {
aps: { // aps: {
sound: "default" as const, // sound: "default" as const,
// 'content-available': 1 as const, // jika butuh silent push // // 'content-available': 1 as const, // jika butuh silent push
}, // },
}, // },
}, // },
}; // };
try { // try {
const response = await adminMessaging.send(message); // const response = await adminMessaging.send(message);
console.log("✅ FCM sent successfully", "Response:", response); // console.log("✅ FCM sent successfully", "Response:", response);
} catch (error: any) { // } catch (error: any) {
console.error("❌ FCM send failed:", error); // console.error("❌ FCM send failed:", error);
// Lanjutkan ke token berikutnya meski satu gagal // // Lanjutkan ke token berikutnya meski satu gagal
} // }
} // }
} // }
return NextResponse.json({ // return NextResponse.json({
success: true, // success: true,
message: "Notification sent successfully", // message: "Notification sent successfully",
}); // });
} catch (error) { // } catch (error) {
console.error("❌ FCM error:", error); // console.error("❌ FCM error:", error);
return NextResponse.json( // return NextResponse.json(
{ error: (error as Error).message }, // { error: (error as Error).message },
{ status: 500 } // { status: 500 }
); // );
} // }
} // }

View File

@@ -5,8 +5,16 @@ export async function GET(request: Request) {
try { try {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const search = searchParams.get("search"); const search = searchParams.get("search");
const page = Number(searchParams.get("page"));
const takeData = 10;
const skipData = page * takeData - takeData;
console.log("SEARCH", search);
console.log("PAGE", page);
const data = await prisma.user.findMany({ const data = await prisma.user.findMany({
take: page ? takeData : undefined,
skip: page ? skipData : undefined,
orderBy: { orderBy: {
username: "asc", username: "asc",
}, },
@@ -43,16 +51,12 @@ export async function GET(request: Request) {
}, },
}); });
return NextResponse.json( return NextResponse.json({
{ status: 200,
success: true, success: true,
message: "Berhasil mendapatkan data", message: "Berhasil mendapatkan data",
data: data, data: data,
}, });
{
status: 200,
}
);
} catch (error) { } catch (error) {
return NextResponse.json( return NextResponse.json(
{ {
@@ -62,7 +66,7 @@ export async function GET(request: Request) {
}, },
{ {
status: 500, status: 500,
} },
); );
} }

View File

@@ -1,6 +1,12 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import _ from "lodash"; import _ from "lodash";
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, DELETE, PUT, POST }; export { GET, DELETE, PUT, POST };
@@ -39,7 +45,6 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
const listNamaVote = data?.Voting_DaftarNamaVote || []; const listNamaVote = data?.Voting_DaftarNamaVote || [];
for (let v of listNamaVote) { for (let v of listNamaVote) {
const kontributor = await prisma.voting_Kontributor.findMany({ const kontributor = await prisma.voting_Kontributor.findMany({
where: { where: {
voting_DaftarNamaVoteId: v.id, voting_DaftarNamaVoteId: v.id,
@@ -90,7 +95,6 @@ async function DELETE(
}, },
}); });
return NextResponse.json({ return NextResponse.json({
success: true, success: true,
message: "Berhasil menghapus data", message: "Berhasil menghapus data",
@@ -171,7 +175,6 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
if (!updateVoting) if (!updateVoting)
return NextResponse.json({ status: 400, message: "Gagal Update" }); return NextResponse.json({ status: 400, message: "Gagal Update" });
} }
@@ -193,11 +196,12 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
async function POST(request: Request, { params }: { params: { id: string } }) { async function POST(request: Request, { params }: { params: { id: string } }) {
const { id } = params; const { id } = params;
const { data } = await request.json(); const { data } = await request.json();
const { chooseId, userId } = data;
try { try {
const findData = await prisma.voting_DaftarNamaVote.findFirst({ const findDatapilihan = await prisma.voting_DaftarNamaVote.findFirst({
where: { where: {
id: data.chooseId, id: chooseId,
}, },
select: { select: {
jumlah: true, jumlah: true,
@@ -205,28 +209,32 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
}, },
}); });
if (!findData) if (!findDatapilihan)
return NextResponse.json({ return NextResponse.json({
success: false, success: false,
message: "Data tidak ditemukan", message: "Data tidak ditemukan",
}); });
const updateData = await prisma.voting_DaftarNamaVote.update({ const updateDataPilihan = await prisma.voting_DaftarNamaVote.update({
where: { where: {
id: data.chooseId, id: data.chooseId,
}, },
data: { data: {
jumlah: findData.jumlah + 1, jumlah: findDatapilihan.jumlah + 1,
}, },
}); });
if (!updateDataPilihan)
if (!updateData)
return NextResponse.json({ return NextResponse.json({
success: false, success: false,
message: "Gagal Update Data", message: "Gagal Update Data",
}); });
const findVotingData = await prisma.voting.findUnique({
where: { id: id },
select: { authorId: true, title: true },
});
const createKontributor = await prisma.voting_Kontributor.create({ const createKontributor = await prisma.voting_Kontributor.create({
data: { data: {
votingId: id, votingId: id,
@@ -250,6 +258,21 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
message: "Gagal Menjadi Kontributor", message: "Gagal Menjadi Kontributor",
}); });
// SEND NOTIFICATION
if (userId !== findVotingData?.authorId) {
await sendNotificationMobileToOneUser({
recipientId: findVotingData?.authorId as string,
senderId: userId,
payload: {
title: "User Melakukan Vote" as NotificationMobileTitleType,
body: `Salah satu user telah melakukan voting pada: ${findVotingData?.title}` as NotificationMobileBodyType,
type: "announcement",
deepLink: routeUserMobile.votingDetailPublised({ id: id }),
kategoriApp: "VOTING",
},
});
}
return NextResponse.json({ return NextResponse.json({
success: true, success: true,
message: "Berhasil Voting", message: "Berhasil Voting",

View File

@@ -1,6 +1,9 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import prisma from "@/lib/prisma"; import prisma from "@/lib/prisma";
import _ from "lodash"; import _ from "lodash";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { NotificationMobileBodyType } from "../../../../../types/type-mobile-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET }; export { POST, GET };
@@ -41,6 +44,24 @@ async function POST(request: Request) {
}); });
} }
const adminUsers = await prisma.user.findMany({
where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Pengajuan Review Baru",
body: create.title as NotificationMobileBodyType,
type: "announcement",
deepLink: routeAdminMobile.votingByStatus({ status: "review" }),
kategoriApp: "VOTING",
},
});
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,
@@ -125,8 +146,6 @@ async function GET(request: Request) {
}); });
fixData = data; fixData = data;
} else if (category === "contribution") { } else if (category === "contribution") {
const data = await prisma.voting_Kontributor.findMany({ const data = await prisma.voting_Kontributor.findMany({
orderBy: { orderBy: {

View File

@@ -1,13 +1,13 @@
[ [
{ {
"name": "default_user", "name": "demo_user",
"nomor": "6282340374412", "nomor": "6282340374412",
"masterUserRoleId": "1", "masterUserRoleId": "1",
"active": true, "active": true,
"termsOfServiceAccepted": false "termsOfServiceAccepted": false
}, },
{ {
"name": "admin_911", "name": "demo_admin",
"nomor": "6281339158911", "nomor": "6281339158911",
"masterUserRoleId": "3", "masterUserRoleId": "3",
"active": true, "active": true,

View File

@@ -0,0 +1,31 @@
const sendCodeOtp = async ({
nomor,
codeOtp,
newMessage,
}: {
nomor: string;
codeOtp?: string;
newMessage?: string;
}) => {
const msg = newMessage || `HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya.\n\n>> Kode OTP anda: ${codeOtp}.`;
const enCode = encodeURIComponent(msg);
const res = await fetch(
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${enCode}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
},
);
// const res = await fetch(
// `https://wa.wibudev.com/code?nom=${nomor}&text=HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya.
// \n
// >> Kode OTP anda: ${codeOtp}.
// `,
// );
return res;
};
export { sendCodeOtp as funSendToWhatsApp };

View File

@@ -0,0 +1,25 @@
import prisma from "@/lib/prisma";
export const funFindDonaturList = async (donasiId: string) => {
const finDonatur = await prisma.donasi_Invoice.findMany({
where: {
donasiId: donasiId,
DonasiMaster_StatusInvoice: {
name: "Berhasil",
},
},
select: {
authorId: true,
},
distinct: ["authorId"], // Ambil hanya authorId unik dari DB
});
// Filter null safety (jika diperlukan)
const recipientIds = finDonatur
.map((e) => e.authorId)
.filter((id): id is string => id !== null && id !== undefined);
console.log("[FIND DONATUR UNIK]", recipientIds);
return recipientIds;
};

View File

@@ -0,0 +1,46 @@
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../types/type-mobile-notification";
import { sendNotificationMobileToManyUser } from "./send-notification";
import { routeUserMobile } from "../route-page-mobile";
import prisma from "@/lib/prisma";
export const sendNotificationInvestmentAddNews = async ({
invesmentId,
senderId,
title,
}: {
invesmentId: string;
senderId: string;
title: string;
}) => {
const findInvestor = await prisma.investasi_Invoice.findMany({
where: {
investasiId: invesmentId,
StatusInvoice: {
name: "Berhasil",
},
},
select: {
authorId: true,
},
});
console.log("[FIND INVESTOR]", findInvestor);
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: findInvestor.map((e) => e.authorId!),
senderId: senderId,
payload: {
title: "Berita terbaru" as NotificationMobileTitleType,
body: `Ada berita yang terupdate pada ${title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({
id: invesmentId,
}),
},
});
};

View File

@@ -22,7 +22,10 @@ export async function sendNotificationMobileToOneUser({
}) { }) {
try { try {
const kategoriToNormalCase = _.lowerCase(payload.kategoriApp); const kategoriToNormalCase = _.lowerCase(payload.kategoriApp);
const titleFix = `${_.startCase(kategoriToNormalCase)}: ${payload.title}`; const titleFix =
kategoriToNormalCase === "other"
? payload.title
: `${_.startCase(kategoriToNormalCase)}: ${payload.title}`;
console.log("titleFix", titleFix); console.log("titleFix", titleFix);
// 1. Simpan notifikasi ke DB // 1. Simpan notifikasi ke DB
@@ -40,7 +43,7 @@ export async function sendNotificationMobileToOneUser({
// 2. Ambil semua token aktif milik penerima // 2. Ambil semua token aktif milik penerima
const tokens = await prisma.tokenUserDevice.findMany({ const tokens = await prisma.tokenUserDevice.findMany({
where: { userId: recipientId, isActive: true }, where: { userId: recipientId },
select: { token: true, id: true }, select: { token: true, id: true },
}); });
@@ -50,7 +53,6 @@ export async function sendNotificationMobileToOneUser({
} }
// 3. Kirim FCM ke semua token // 3. Kirim FCM ke semua token
await Promise.allSettled( await Promise.allSettled(
tokens.map(async ({ token, id }) => { tokens.map(async ({ token, id }) => {
try { try {
@@ -77,12 +79,11 @@ export async function sendNotificationMobileToOneUser({
}); });
} catch (fcmError: any) { } catch (fcmError: any) {
// Hapus token jika invalid // Hapus token jika invalid
console.log("fcmError", fcmError); if (fcmError.code === "messaging/registration-token-not-registered") {
if (fcmError.code === "messaging/invalid-registration-token") { // Hapus token dari DB
await prisma.tokenUserDevice.delete({ where: { id: id } }); await prisma.tokenUserDevice.delete({ where: { id } });
console.log(` Invalid token removed: ${token}`); console.log(`🗑️ Invalid token removed: ${id}`);
} }
console.error(`FCM failed for token ${token}:`, fcmError.message);
} }
}) })
); );

View File

@@ -5,16 +5,77 @@ type StatusApp = "review" | "draft" | "reject" | "publish";
const routeAdminMobile = { const routeAdminMobile = {
userAccess: ({ id }: { id: string }) => `/admin/user-access/${id}`, userAccess: ({ id }: { id: string }) => `/admin/user-access/${id}`,
// JOB // JOB
jobDetail: ({ id, status }: { id: string; status: StatusApp }) =>
`/admin/job/${id}/${status}`,
jobByStatus: ({ status }: { status: StatusApp }) => jobByStatus: ({ status }: { status: StatusApp }) =>
`/admin/job/${status}/status`, `/admin/job/${status}/status`,
// EVENT
eventByStatus: ({ status }: { status: StatusApp }) =>
`/admin/event/${status}/status`,
// VOTING
votingByStatus: ({ status }: { status: StatusApp }) =>
`/admin/voting/${status}/status`,
// FORUM
forumPreviewReportPosting: `/admin/forum/report-posting`,
forumPreviewReportComment: `/admin/forum/report-comment`,
// INVESTMENT
investmentByStatus: ({ status }: { status: StatusApp }) => `/admin/investment/${status}/status`,
investmentDetailPublish: ({
id,
status,
}: {
id: string;
status: StatusApp;
}) => `/admin/investment/${id}/${status}`,
// DONATION
donationByStatus: ({ status }: { status: StatusApp }) => `/admin/donation/${status}/status`,
donationDetailPublish: ({
id,
status,
}: {
id: string;
status: StatusApp;
}) => `/admin/donation/${id}/${status}`,
}; };
// ================ ROUTER USER =================
const routeUserMobile = { const routeUserMobile = {
home: `/(user)/home`, home: `/(user)/home`,
// JOB // JOB
jobDetailPublised: ({ id }: { id: string }) => `/job/${id}`,
jobByStatus: ({ status }: { status?: StatusApp }) => jobByStatus: ({ status }: { status?: StatusApp }) =>
`/job/(tabs)/status?status=${status}`, `/job/(tabs)/status?status=${status}`,
jobDetailPublised: ({ id }: { id: string }) => `/job/${id}`,
// EVENT
eventByStatus: ({ status }: { status?: StatusApp }) =>
`/event/(tabs)/status?status=${status}`,
eventDetailPublised: ({ id }: { id: string }) => `/event/${id}/publish`,
// VOTING
votingByStatus: ({ status }: { status?: StatusApp }) =>
`/voting/(tabs)/status?status=${status}`,
votingDetailPublised: ({ id }: { id: string }) => `/voting/${id}`,
// FORUM
forumBeranda: `/forum`,
forumDetail: ({ id }: { id: string }) => `/forum/${id}`,
forumPreviewReportPosting: ({ id }: { id: string }) =>
`/forum/${id}/preview-report-posting`,
forumPreviewReportComment: ({ id }: { id: string }) =>
`/forum/${id}/preview-report-comment`,
// INVESTMENT
investmentPortofolioByStatus: ({ status }: { status?: StatusApp }) =>
`/investment/(tabs)/portofolio?status=${status}`,
investmentDetailPublish: ({ id }: { id: string }) => `/investment/${id}`,
investmentTransaction: `/investment/(tabs)/transaction`,
// DONATION
donationByStatus: ({ status }: { status?: StatusApp }) =>
`/donation/(tabs)/status?status=${status}`,
donationDetailPublish: ({ id }: { id: string }) => `/donation/${id}`,
donationTransaction: `/donation/(tabs)/my-donation`,
}; };

View File

@@ -23,6 +23,6 @@
"@/*": ["./src/*"] "@/*": ["./src/*"]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app_modules/investasi/proses_transaksi/view.jsx", "src/app/api/investasi/midtrans/[id]/route.ts", "src/app_modules/job/create/TextEdit.tsx", "src/app/api/mobile/forum/[id]/report-comment/route.ts"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app_modules/investasi/proses_transaksi/view.jsx", "src/app/api/investasi/midtrans/[id]/route.ts", "src/app_modules/job/create/TextEdit.tsx", "src/app/api/mobile/forum/[id]/report-comment-del-soon/route.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }

View File

@@ -13,18 +13,20 @@ export type NotificationMobilePayload = {
export type NotificationMobileTitleType = export type NotificationMobileTitleType =
| (string & { __type: "NotificationMobileTitleType" }) | (string & { __type: "NotificationMobileTitleType" })
| "Pengajuan Review" // Admin
| "Pengajuan Review Baru"
// USER
| "Pengajuan Review Ditolak"
| "Review Selesai" | "Review Selesai"
// to ALL user // to ALL user
| "Ada lowongan kerja baru"
export type NotificationMobileBodyType = export type NotificationMobileBodyType =
// USER // USER
| (string & { __type: "NotificationMobileBodyType" }) | (string & { __type: "NotificationMobileBodyType" })
| "Terdapat pengajuan baru yang perlu direview" | "Ada pengajuan review" // tambah title
// ADMIN // ADMIN
| "Pengajuan data anda telah di tolak !" | "Mohon perbaiki data sesuai catatan penolakan !"
| "Selamat data anda telah terpublikasi" | "Selamat data anda telah terpublikasi"
export type TypeNotificationCategoryApp = export type TypeNotificationCategoryApp =