Compare commits
35 Commits
main
...
mobile-not
| Author | SHA1 | Date | |
|---|---|---|---|
| 70db97f5bb | |||
| 8ccf1f2b6e | |||
| 048b7b6094 | |||
| fc23e01275 | |||
| 20d05c1cc7 | |||
| 2c269db250 | |||
| fea94df7bb | |||
| 3c6dde6204 | |||
| cb0845e264 | |||
| d09e30c049 | |||
| c8bd928c33 | |||
| 3a558cec8e | |||
| b9354cb6bf | |||
| 7cdde6b5a9 | |||
| e77e5eb3ac | |||
| 8f3f27122a | |||
| d84a1d84ff | |||
| 40ba31edec | |||
| a54f8599b4 | |||
| 09825756f3 | |||
| 2086692897 | |||
| 87515ae19f | |||
| 44d6788f6e | |||
| ac634100b5 | |||
| 1b206102b0 | |||
| 94a545bd30 | |||
| 3552cf4f39 | |||
| d50fda90e0 | |||
| d3d4912a5f | |||
| b2e8bc3caf | |||
| d207b6feed | |||
| f05571caa4 | |||
| 6507bdcd35 | |||
| e2c8a1edbc | |||
| 02b25ffc84 |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -2,6 +2,24 @@
|
|||||||
|
|
||||||
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.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.33](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.32...v1.5.33) (2026-01-06)
|
||||||
|
|
||||||
|
## [1.5.32](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.31...v1.5.32) (2026-01-05)
|
||||||
|
|
||||||
|
## [1.5.31](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.30...v1.5.31) (2025-12-24)
|
||||||
|
|
||||||
|
## [1.5.30](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.29...v1.5.30) (2025-12-19)
|
||||||
|
|
||||||
|
## [1.5.29](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.28...v1.5.29) (2025-12-17)
|
||||||
|
|
||||||
## [1.5.28](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.27...v1.5.28) (2025-12-17)
|
## [1.5.28](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.27...v1.5.28) (2025-12-17)
|
||||||
|
|
||||||
## [1.5.27](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.26...v1.5.27) (2025-12-17)
|
## [1.5.27](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.26...v1.5.27) (2025-12-17)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hipmi",
|
"name": "hipmi",
|
||||||
"version": "1.5.28",
|
"version": "1.5.37",
|
||||||
"private": true,
|
"private": true,
|
||||||
"prisma": {
|
"prisma": {
|
||||||
"seed": "bun prisma/seed.ts"
|
"seed": "bun prisma/seed.ts"
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Notifikasi" ADD COLUMN "type" TEXT;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "Notifikasi" DROP CONSTRAINT "Notifikasi_userRoleId_fkey";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Notifikasi" ADD COLUMN "recipientId" TEXT,
|
||||||
|
ADD COLUMN "senderId" TEXT,
|
||||||
|
ALTER COLUMN "userRoleId" DROP NOT NULL;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Notifikasi" ADD CONSTRAINT "Notifikasi_userRoleId_fkey" FOREIGN KEY ("userRoleId") REFERENCES "MasterUserRole"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Notifikasi" ADD CONSTRAINT "Notifikasi_recipientId_fkey" FOREIGN KEY ("recipientId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Notifikasi" ADD CONSTRAINT "Notifikasi_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Notifikasi" ALTER COLUMN "appId" DROP NOT NULL,
|
||||||
|
ALTER COLUMN "kategoriApp" DROP NOT NULL,
|
||||||
|
ALTER COLUMN "pesan" DROP NOT NULL;
|
||||||
@@ -59,6 +59,10 @@ model User {
|
|||||||
acceptedTermsAt DateTime?
|
acceptedTermsAt DateTime?
|
||||||
acceptedForumTermsAt DateTime?
|
acceptedForumTermsAt DateTime?
|
||||||
tokenUserDevices TokenUserDevice[]
|
tokenUserDevices TokenUserDevice[]
|
||||||
|
|
||||||
|
// For Mobile App
|
||||||
|
NotificationRecipient Notifikasi[] @relation("NotificationRecipient")
|
||||||
|
NotificationSender Notifikasi[] @relation("NotificationSender")
|
||||||
}
|
}
|
||||||
|
|
||||||
model MasterUserRole {
|
model MasterUserRole {
|
||||||
@@ -974,27 +978,36 @@ model NomorAdmin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Notifikasi {
|
model Notifikasi {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
appId String
|
appId String?
|
||||||
kategoriApp String
|
kategoriApp String?
|
||||||
pesan String
|
pesan String?
|
||||||
title String?
|
title String?
|
||||||
status String?
|
status String?
|
||||||
|
|
||||||
isRead Boolean @default(false)
|
isRead Boolean @default(false)
|
||||||
readAt DateTime? // kapan user membaca notifikasi ini
|
readAt DateTime? // kapan user membaca notifikasi ini
|
||||||
deepLink String? // misal: "announcement/123", "user/profile/cmha6wb9w0001cfndwl9fcse6"
|
deepLink String? // misal: "announcement/123", "user/profile/cmha6wb9w0001cfndwl9fcse6"
|
||||||
|
type String?
|
||||||
|
|
||||||
Role MasterUserRole? @relation(fields: [userRoleId], references: [id])
|
Role MasterUserRole? @relation(fields: [userRoleId], references: [id])
|
||||||
userRoleId String
|
userRoleId String?
|
||||||
|
|
||||||
User User? @relation("UserNotifikasi", fields: [userId], references: [id], map: "NotifikasiUser")
|
User User? @relation("UserNotifikasi", fields: [userId], references: [id], map: "NotifikasiUser")
|
||||||
userId String?
|
userId String?
|
||||||
Admin User? @relation("AdminNotifikasi", fields: [adminId], references: [id], map: "NotifikasiAdmin")
|
Admin User? @relation("AdminNotifikasi", fields: [adminId], references: [id], map: "NotifikasiAdmin")
|
||||||
adminId String?
|
adminId String?
|
||||||
|
|
||||||
|
// Recipient (user who receives the notification)
|
||||||
|
recipient User? @relation("NotificationRecipient", fields: [recipientId], references: [id])
|
||||||
|
recipientId String?
|
||||||
|
|
||||||
|
// Sender (user who sent the notification)
|
||||||
|
sender User? @relation("NotificationSender", fields: [senderId], references: [id])
|
||||||
|
senderId String?
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAPS
|
// MAPS
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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 { sendCodeOtp } 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 sendCodeOtp({
|
||||||
// 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 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
src/app/api/auth/mobile-eula/route.tsx
Normal file
54
src/app/api/auth/mobile-eula/route.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { prisma } from "@/lib";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
try {
|
||||||
|
const { nomor } = await req.json();
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
nomor: nomor,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user)
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "User belum terdaftar",
|
||||||
|
status: 404,
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateTerms = await prisma.user.update({
|
||||||
|
where: { nomor: nomor },
|
||||||
|
data: {
|
||||||
|
termsOfServiceAccepted: true,
|
||||||
|
acceptedTermsAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!updateTerms) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "Gagal setujui syarat dan ketentuan",
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: true,
|
||||||
|
message: "Anda telah setujui syarat dan ketentuan",
|
||||||
|
},
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Terjadi masalah saat setujui syarat dan ketentuan",
|
||||||
|
reason: error as Error,
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
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 { sendCodeOtp } from "@/lib/code-otp-sender";
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
export async function POST(req: Request) {
|
||||||
try {
|
try {
|
||||||
const codeOtp = randomOTP();
|
const codeOtp = randomOTP();
|
||||||
const body = await req.json();
|
const body = await req.json();
|
||||||
console.log("[Masuk API]", body);
|
|
||||||
const { nomor } = body;
|
const { nomor } = body;
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
@@ -15,9 +15,6 @@ export async function POST(req: Request) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(["cek user", user]);
|
|
||||||
console.log(["cek nomor", nomor]);
|
|
||||||
|
|
||||||
if (!user)
|
if (!user)
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: false,
|
success: false,
|
||||||
@@ -35,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 sendCodeOtp({
|
||||||
// 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(
|
||||||
@@ -66,8 +54,9 @@ export async function POST(req: Request) {
|
|||||||
success: true,
|
success: true,
|
||||||
message: "Kode verifikasi terkirim",
|
message: "Kode verifikasi terkirim",
|
||||||
kodeId: createOtpId.id,
|
kodeId: createOtpId.id,
|
||||||
|
isAcceptTerms: user.termsOfServiceAccepted,
|
||||||
},
|
},
|
||||||
{ status: 200 }
|
{ status: 200 },
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
@@ -76,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 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +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 { 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 { sendCodeOtp } 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") {
|
||||||
@@ -51,12 +57,6 @@ export async function POST(req: Request) {
|
|||||||
{ status: 500 }
|
{ status: 500 }
|
||||||
);
|
);
|
||||||
|
|
||||||
// const token = await sessionCreate({
|
|
||||||
// sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
|
|
||||||
// encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
|
|
||||||
// user: createUser as any,
|
|
||||||
// });
|
|
||||||
|
|
||||||
const createOtpId = await prisma.kodeOtp.create({
|
const createOtpId = await prisma.kodeOtp.create({
|
||||||
data: {
|
data: {
|
||||||
nomor: data.nomor,
|
nomor: data.nomor,
|
||||||
@@ -70,28 +70,58 @@ 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 sendCodeOtp({
|
||||||
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 =========== //
|
||||||
|
|
||||||
|
const adminUsers = await prisma.user.findMany({
|
||||||
|
where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Users to notify:", adminUsers);
|
||||||
|
|
||||||
|
const dataNotification = {
|
||||||
|
title: "Pendaftaran Baru",
|
||||||
|
type: "announcement",
|
||||||
|
kategoriApp: "OTHER",
|
||||||
|
createdAt: new Date(),
|
||||||
|
pesan: "User baru telah melakukan registrasi. Ayo cek dan verifikasi!",
|
||||||
|
deepLink: `/admin/user-access/${createUser.id}`,
|
||||||
|
senderId: createUser.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
await sendNotificationMobileToManyUser({
|
||||||
|
recipientIds: adminUsers.map((user) => user.id),
|
||||||
|
senderId: data.authorId,
|
||||||
|
payload: {
|
||||||
|
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 }),
|
||||||
|
kategoriApp: "OTHER",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// =========== END SEND NOTIFICATION =========== //
|
||||||
|
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
success: true,
|
success: true,
|
||||||
message: "Registrasi Berhasil",
|
message: "Registrasi Berhasil",
|
||||||
// token: token,
|
|
||||||
kodeId: createOtpId.id,
|
kodeId: createOtpId.id,
|
||||||
},
|
},
|
||||||
{ status: 201 }
|
{ status: 201 }
|
||||||
|
|||||||
@@ -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 { sendCodeOtp } 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 sendCodeOtp({
|
||||||
|
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();
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
|
||||||
@@ -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 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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 }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
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 };
|
||||||
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
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 };
|
||||||
|
|
||||||
@@ -54,6 +60,9 @@ 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);
|
||||||
@@ -83,7 +92,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
masterStatusId: checkStatus.id,
|
masterStatusId: checkStatus.id,
|
||||||
catatan: data,
|
catatan: catatan,
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
@@ -97,6 +106,18 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await sendNotificationMobileToOneUser({
|
||||||
|
recipientId: updt.authorId as any,
|
||||||
|
senderId: senderId,
|
||||||
|
payload: {
|
||||||
|
title: "Pengajuan Review Ditolak",
|
||||||
|
body: "Mohon perbaiki data sesuai catatan penolakan !",
|
||||||
|
type: "announcement",
|
||||||
|
kategoriApp: "JOB",
|
||||||
|
deepLink: routeUserMobile.jobByStatus({ status: "reject" }),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
fixData = updt;
|
fixData = updt;
|
||||||
} else if (fixStatus === "Publish") {
|
} else if (fixStatus === "Publish") {
|
||||||
const updt = await prisma.job.update({
|
const updt = await prisma.job.update({
|
||||||
@@ -118,6 +139,35 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await sendNotificationMobileToOneUser({
|
||||||
|
recipientId: updt.authorId as any,
|
||||||
|
senderId: senderId,
|
||||||
|
payload: {
|
||||||
|
title: "Review Selesai",
|
||||||
|
body: "Selamat data anda telah terpublikasi",
|
||||||
|
type: "announcement",
|
||||||
|
kategoriApp: "JOB",
|
||||||
|
deepLink: routeUserMobile.jobByStatus({ status: "publish" }),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const adminUsers = await prisma.user.findMany({
|
||||||
|
where: { masterUserRoleId: "1", NOT: { id: updt.authorId as any } },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
await sendNotificationMobileToManyUser({
|
||||||
|
recipientIds: adminUsers.map((user) => user.id),
|
||||||
|
senderId: data.authorId,
|
||||||
|
payload: {
|
||||||
|
title: "Ada Lowongan Kerja Baru" as NotificationMobileTitleType,
|
||||||
|
body: `${updt.title}` as NotificationMobileBodyType,
|
||||||
|
type: "announcement",
|
||||||
|
deepLink: routeUserMobile.jobDetailPublised({ id: id }),
|
||||||
|
kategoriApp: "JOB",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
fixData = updt;
|
fixData = updt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,15 @@ 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 { searchParams } = new URL(request.url);
|
||||||
|
const category = searchParams.get("category");
|
||||||
|
|
||||||
|
console.log("Received data:", data);
|
||||||
|
console.log("User ID:", id);
|
||||||
|
console.log("Category:", category);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (data.active) {
|
if (category === "access") {
|
||||||
const updateData = await prisma.user.update({
|
const updateData = await prisma.user.update({
|
||||||
where: {
|
where: {
|
||||||
id: id,
|
id: id,
|
||||||
@@ -47,7 +53,7 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
console.log("[Update Active Berhasil]", updateData);
|
console.log("[Update Active Berhasil]", updateData);
|
||||||
} else if (data.role) {
|
} else if (category === "role") {
|
||||||
const fixName = _.startCase(data.role.replace(/_/g, " "));
|
const fixName = _.startCase(data.role.replace(/_/g, " "));
|
||||||
|
|
||||||
const checkRole = await prisma.masterUserRole.findFirst({
|
const checkRole = await prisma.masterUserRole.findFirst({
|
||||||
@@ -68,6 +74,12 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
console.log("[Update Role Berhasil]", updateData);
|
console.log("[Update Role Berhasil]", updateData);
|
||||||
|
} else {
|
||||||
|
return NextResponse.json({
|
||||||
|
status: 400,
|
||||||
|
success: false,
|
||||||
|
message: "Invalid category",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
51
src/app/api/mobile/auth/device-tokens/[id]/route.ts
Normal file
51
src/app/api/mobile/auth/device-tokens/[id]/route.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import { prisma } from "@/lib";
|
||||||
|
|
||||||
|
export { DELETE };
|
||||||
|
|
||||||
|
async function DELETE(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
const { id } = params;
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const deviceId = searchParams.get("deviceId");
|
||||||
|
|
||||||
|
console.log("ID", id);
|
||||||
|
console.log("DEVICE ID", deviceId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const findFirst = await prisma.tokenUserDevice.findFirst({
|
||||||
|
where: {
|
||||||
|
userId: id,
|
||||||
|
deviceId: deviceId as any,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!findFirst) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "User tidak ditemukan !",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleted = await prisma.tokenUserDevice.delete({
|
||||||
|
where: {
|
||||||
|
id: findFirst.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("DEL", deleted);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil menghapus device token user",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("ERROR", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: (error as Error).message, message: "Terjadi error pada API" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { prisma } from "@/lib";
|
import { prisma } from "@/lib";
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export { POST, GET };
|
||||||
|
|
||||||
|
async function POST(request: NextRequest) {
|
||||||
const { data } = await request.json();
|
const { data } = await request.json();
|
||||||
try {
|
try {
|
||||||
console.log("Data >>", JSON.stringify(data, null, 2));
|
|
||||||
|
|
||||||
const { userId, platform, deviceId, model, appVersion, fcmToken } =
|
const { userId, platform, deviceId, model, appVersion, fcmToken } = data;
|
||||||
data;
|
|
||||||
|
|
||||||
if (!fcmToken) {
|
if (!fcmToken) {
|
||||||
return NextResponse.json({ error: "Missing Token" }, { status: 400 });
|
return NextResponse.json({ error: "Missing Token" }, { status: 400 });
|
||||||
@@ -23,6 +23,9 @@ export async function POST(request: NextRequest) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
console.log("✅ EX", existing);
|
||||||
|
|
||||||
let deviceToken;
|
let deviceToken;
|
||||||
|
|
||||||
if (existing) {
|
if (existing) {
|
||||||
@@ -62,3 +65,22 @@ export async function POST(request: NextRequest) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const data = await prisma.tokenUserDevice.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, data });
|
||||||
|
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: (error as Error).message },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
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 };
|
||||||
|
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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({
|
||||||
@@ -114,7 +138,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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,7 +157,7 @@ async function DELETE(
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
Authorization: `Bearer ${process.env.WS_APIKEY}`,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
|
||||||
@@ -50,7 +56,6 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
|
|||||||
|
|
||||||
console.log("[ID INVOICE]", id);
|
console.log("[ID INVOICE]", id);
|
||||||
|
|
||||||
|
|
||||||
let fixData;
|
let fixData;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -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({
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
|
|||||||
include: {
|
include: {
|
||||||
Author: {
|
Author: {
|
||||||
select: {
|
select: {
|
||||||
|
id: true,
|
||||||
username: true,
|
username: true,
|
||||||
nomor: true,
|
nomor: true,
|
||||||
Profile: {
|
Profile: {
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
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 } from "../../../../../types/type-mobile-notification";
|
||||||
|
|
||||||
export { POST, GET };
|
export { POST, GET };
|
||||||
|
|
||||||
@@ -17,6 +20,25 @@ async function POST(request: Request) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// kirim notifikasi ke semua admin untuk mengetahui ada job baru yang harus di review
|
||||||
|
|
||||||
|
const adminUsers = await prisma.user.findMany({
|
||||||
|
where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
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.jobByStatus({ status: "review" }),
|
||||||
|
kategoriApp: "JOB",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
success: true,
|
success: true,
|
||||||
@@ -54,10 +76,10 @@ async function GET(request: Request) {
|
|||||||
MasterStatus: {
|
MasterStatus: {
|
||||||
name: "Publish",
|
name: "Publish",
|
||||||
},
|
},
|
||||||
// title: {
|
// title: {
|
||||||
// contains: search || "",
|
// contains: search || "",
|
||||||
// mode: "insensitive",
|
// mode: "insensitive",
|
||||||
// },
|
// },
|
||||||
},
|
},
|
||||||
orderBy: {
|
orderBy: {
|
||||||
createdAt: "desc",
|
createdAt: "desc",
|
||||||
@@ -90,46 +112,46 @@ async function GET(request: Request) {
|
|||||||
|
|
||||||
fixData = data;
|
fixData = data;
|
||||||
} else if (category === "beranda") {
|
} else if (category === "beranda") {
|
||||||
const data = await prisma.job.findMany({
|
const data = await prisma.job.findMany({
|
||||||
where: {
|
where: {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
isArsip: false,
|
isArsip: false,
|
||||||
MasterStatus: {
|
MasterStatus: {
|
||||||
name: "Publish",
|
name: "Publish",
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
contains: search || "",
|
contains: search || "",
|
||||||
mode: "insensitive",
|
mode: "insensitive",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
orderBy: {
|
orderBy: {
|
||||||
createdAt: "desc",
|
createdAt: "desc",
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
title: true,
|
title: true,
|
||||||
deskripsi: true,
|
deskripsi: true,
|
||||||
authorId: true,
|
authorId: true,
|
||||||
MasterStatus: {
|
MasterStatus: {
|
||||||
select: {
|
select: {
|
||||||
name: true,
|
name: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Author: {
|
Author: {
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
username: true,
|
username: true,
|
||||||
Profile: {
|
Profile: {
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
name: true,
|
name: true,
|
||||||
imageId: true,
|
imageId: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
fixData = data;
|
fixData = data;
|
||||||
}
|
}
|
||||||
|
|||||||
212
src/app/api/mobile/notification/[id]/route.ts
Normal file
212
src/app/api/mobile/notification/[id]/route.ts
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
import { prisma } from "@/lib";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import { NotificationProp } from "../route";
|
||||||
|
import { adminMessaging } from "@/lib/firebase-admin";
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
const { id } = params;
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const category = searchParams.get("category");
|
||||||
|
|
||||||
|
let fixData;
|
||||||
|
const fixCategory = _.upperCase(category || "");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await prisma.notifikasi.findMany({
|
||||||
|
orderBy: {
|
||||||
|
createdAt: "desc",
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
recipientId: id,
|
||||||
|
kategoriApp: fixCategory,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fixData = data;
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
data: fixData,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: (error as Error).message },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PUT(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
const { id } = params;
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const category = searchParams.get("category");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (category === "one") {
|
||||||
|
await prisma.notifikasi.update({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
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({
|
||||||
|
success: true,
|
||||||
|
message: "Notifications marked as read",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error marking notifications as read:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: (error as Error).message },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// export async function POST(
|
||||||
|
// request: NextRequest,
|
||||||
|
// { params }: { params: { id: string } }
|
||||||
|
// ) {
|
||||||
|
// const { id } = params;
|
||||||
|
|
||||||
|
// const { data } = await request.json();
|
||||||
|
|
||||||
|
// const {
|
||||||
|
// title,
|
||||||
|
// body: notificationBody,
|
||||||
|
// userLoginId,
|
||||||
|
// type,
|
||||||
|
// kategoriApp,
|
||||||
|
// appId,
|
||||||
|
// status,
|
||||||
|
// deepLink,
|
||||||
|
// } = data as NotificationProp;
|
||||||
|
|
||||||
|
// console.log("Notification Send >>", data);
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// // Cari user yang login
|
||||||
|
// const findUserLogin = await prisma.user.findUnique({
|
||||||
|
// where: {
|
||||||
|
// id: userLoginId,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (!findUserLogin) {
|
||||||
|
// return NextResponse.json({ error: "User not found" }, { status: 404 });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Cari token fcm user yang login
|
||||||
|
// const checkFcmToken = await prisma.tokenUserDevice.findFirst({
|
||||||
|
// where: {
|
||||||
|
// userId: findUserLogin.id,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (!checkFcmToken) {
|
||||||
|
// return NextResponse.json(
|
||||||
|
// { error: "FCM Token not found" },
|
||||||
|
// { status: 404 }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const created = await prisma.notifikasi.create({
|
||||||
|
// data: {
|
||||||
|
// title,
|
||||||
|
// type,
|
||||||
|
// createdAt: new Date(),
|
||||||
|
// appId,
|
||||||
|
// kategoriApp,
|
||||||
|
// pesan: notificationBody || "",
|
||||||
|
// userRoleId: findUserLogin.masterUserRoleId,
|
||||||
|
// status,
|
||||||
|
// deepLink,
|
||||||
|
// senderId: findUserLogin.id,
|
||||||
|
// recipientId: id,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (created) {
|
||||||
|
// const deviceToken = await prisma.tokenUserDevice.findMany({
|
||||||
|
// where: {
|
||||||
|
// userId: id,
|
||||||
|
// isActive: true,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// for (let i of deviceToken) {
|
||||||
|
// const message = {
|
||||||
|
// token: i.token,
|
||||||
|
// notification: {
|
||||||
|
// title,
|
||||||
|
// body: notificationBody || "",
|
||||||
|
// },
|
||||||
|
// data: {
|
||||||
|
// sentAt: new Date().toISOString(), // ✅ Simpan metadata di data
|
||||||
|
// id: created.id,
|
||||||
|
// deepLink: 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
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return NextResponse.json({
|
||||||
|
// success: true,
|
||||||
|
// message: "Notification sent successfully",
|
||||||
|
// });
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("❌ FCM error:", error);
|
||||||
|
|
||||||
|
// return NextResponse.json(
|
||||||
|
// { error: (error as Error).message },
|
||||||
|
// { status: 500 }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
31
src/app/api/mobile/notification/[id]/unread-count/route.ts
Normal file
31
src/app/api/mobile/notification/[id]/unread-count/route.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { prisma } from "@/lib";
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
const { id } = params;
|
||||||
|
console.log("User ID:", id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await prisma.notifikasi.count({
|
||||||
|
where: {
|
||||||
|
recipientId: id,
|
||||||
|
isRead: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("List Notification >>", data);
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to get unread count",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
210
src/app/api/mobile/notification/route.ts
Normal file
210
src/app/api/mobile/notification/route.ts
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
// app/api/test/notifications/route.ts
|
||||||
|
import { prisma } from "@/lib";
|
||||||
|
import { adminMessaging } from "@/lib/firebase-admin";
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export type NotificationProp = {
|
||||||
|
title: string;
|
||||||
|
body: string;
|
||||||
|
userLoginId: string;
|
||||||
|
appId?: string;
|
||||||
|
status?: string;
|
||||||
|
kategoriApp?: string;
|
||||||
|
type?: string;
|
||||||
|
deepLink?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { data } = await request.json();
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
body: notificationBody,
|
||||||
|
userLoginId,
|
||||||
|
type,
|
||||||
|
kategoriApp,
|
||||||
|
appId,
|
||||||
|
status,
|
||||||
|
deepLink,
|
||||||
|
} = data as NotificationProp;
|
||||||
|
|
||||||
|
console.log("Notification Send >>", data);
|
||||||
|
|
||||||
|
// Cari user yang login
|
||||||
|
const findUserLogin = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
id: userLoginId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!findUserLogin) {
|
||||||
|
return NextResponse.json({ error: "User not found" }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cari token fcm user yang login
|
||||||
|
const checkFcmToken = await prisma.tokenUserDevice.findFirst({
|
||||||
|
where: {
|
||||||
|
userId: findUserLogin.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!checkFcmToken) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "FCM Token not found" },
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika user yang masuk maka notifikasik akan dikirim ke semua admin , begitu sebaliknya !
|
||||||
|
const filterByCurrentLoginId =
|
||||||
|
findUserLogin.masterUserRoleId === "1" ? "2" : "1";
|
||||||
|
|
||||||
|
// Cari user yang akan menerima notifikasi
|
||||||
|
const findAllUserBySendTo = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
masterUserRoleId: filterByCurrentLoginId,
|
||||||
|
NOT: {
|
||||||
|
id: findUserLogin.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Find All User By Send To >>", findAllUserBySendTo);
|
||||||
|
|
||||||
|
for (let a of findAllUserBySendTo) {
|
||||||
|
const responseCreatedNotifications = await createNotification({
|
||||||
|
title,
|
||||||
|
type: type as string,
|
||||||
|
createdAt: new Date(),
|
||||||
|
pesan: notificationBody || "",
|
||||||
|
appId: appId as string,
|
||||||
|
kategoriApp: kategoriApp as string,
|
||||||
|
userRoleId: findUserLogin.masterUserRoleId,
|
||||||
|
status: status,
|
||||||
|
deepLink: deepLink,
|
||||||
|
senderId: findUserLogin.id,
|
||||||
|
recipientId: a.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (responseCreatedNotifications) {
|
||||||
|
const deviceToken = await prisma.tokenUserDevice.findMany({
|
||||||
|
where: {
|
||||||
|
userId: a.id,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i of deviceToken) {
|
||||||
|
const message = {
|
||||||
|
token: i.token,
|
||||||
|
notification: {
|
||||||
|
title,
|
||||||
|
body: notificationBody || "",
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
sentAt: new Date().toISOString(), // ✅ Simpan metadata di data
|
||||||
|
id: responseCreatedNotifications.id,
|
||||||
|
deepLink: deepLink || "",
|
||||||
|
// contoh: senderId, type, etc.
|
||||||
|
},
|
||||||
|
// 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
|
||||||
|
// Opsional: sesuaikan icon & warna
|
||||||
|
// icon: 'ic_notification',
|
||||||
|
// color: '#FFD700',
|
||||||
|
},
|
||||||
|
// FCM akan bangunkan app jika perlu
|
||||||
|
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 to token:",
|
||||||
|
"Response:",
|
||||||
|
response
|
||||||
|
);
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("❌ FCM send failed for token:", i.token, error);
|
||||||
|
// Lanjutkan ke token berikutnya meski satu gagal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return NextResponse.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to create notification",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: "Notification sent successfully",
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("❌ FCM error:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: error.message || "Failed to send FCM" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createNotification({
|
||||||
|
title,
|
||||||
|
type,
|
||||||
|
createdAt,
|
||||||
|
appId,
|
||||||
|
kategoriApp,
|
||||||
|
pesan,
|
||||||
|
userRoleId,
|
||||||
|
status,
|
||||||
|
deepLink,
|
||||||
|
senderId,
|
||||||
|
recipientId,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
type: string;
|
||||||
|
createdAt: Date;
|
||||||
|
appId: string;
|
||||||
|
kategoriApp: string;
|
||||||
|
userRoleId: string;
|
||||||
|
status?: string;
|
||||||
|
deepLink?: string;
|
||||||
|
pesan: string;
|
||||||
|
|
||||||
|
senderId: string;
|
||||||
|
recipientId: string;
|
||||||
|
}) {
|
||||||
|
const createNotification = await prisma.notifikasi.create({
|
||||||
|
data: {
|
||||||
|
title,
|
||||||
|
type,
|
||||||
|
createdAt,
|
||||||
|
appId,
|
||||||
|
kategoriApp,
|
||||||
|
pesan,
|
||||||
|
userRoleId,
|
||||||
|
status,
|
||||||
|
deepLink,
|
||||||
|
senderId,
|
||||||
|
recipientId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return createNotification;
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// app/api/test/notifications/route.ts
|
|
||||||
import { adminMessaging } from "@/lib/firebase-admin";
|
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
|
||||||
try {
|
|
||||||
const { data } = await request.json();
|
|
||||||
const { fcmToken, title, body: notificationBody } = data;
|
|
||||||
|
|
||||||
console.log("Data Notifikasi >>", data);
|
|
||||||
|
|
||||||
if (!fcmToken || !title) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "Missing fcmToken or title" },
|
|
||||||
{ status: 400 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const message = {
|
|
||||||
token: fcmToken,
|
|
||||||
notification: {
|
|
||||||
title,
|
|
||||||
body: notificationBody || "",
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
sentAt: new Date().toISOString(), // ✅ Simpan metadata di data
|
|
||||||
// contoh: senderId, type, etc.
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log("[MSG]", message);
|
|
||||||
|
|
||||||
const response = await adminMessaging.send(message);
|
|
||||||
console.log("✅ FCM sent:", response);
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, messageId: response });
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error("❌ FCM error:", error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: error.message || "Failed to send FCM" },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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",
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
28
src/lib/code-otp-sender.ts
Normal file
28
src/lib/code-otp-sender.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
const sendCodeOtp = async ({
|
||||||
|
nomor,
|
||||||
|
codeOtp,
|
||||||
|
}: {
|
||||||
|
nomor: string;
|
||||||
|
codeOtp: string;
|
||||||
|
}) => {
|
||||||
|
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}.`;
|
||||||
|
const res = await fetch(
|
||||||
|
`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}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
// 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 };
|
||||||
@@ -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,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
119
src/lib/mobile/notification/send-notification.ts
Normal file
119
src/lib/mobile/notification/send-notification.ts
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
// lib/notifications/send-notification.ts
|
||||||
|
import { adminMessaging } from "@/lib/firebase-admin";
|
||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { NotificationMobilePayload } from "../../../../types/type-mobile-notification";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kirim notifikasi ke satu user (semua device aktifnya)
|
||||||
|
* @param recipientId - ID penerima
|
||||||
|
* @param senderId - ID pengirim
|
||||||
|
* @param payload - Data notifikasi
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function sendNotificationMobileToOneUser({
|
||||||
|
recipientId,
|
||||||
|
senderId,
|
||||||
|
payload,
|
||||||
|
}: {
|
||||||
|
recipientId: string;
|
||||||
|
senderId: string;
|
||||||
|
payload: NotificationMobilePayload;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const kategoriToNormalCase = _.lowerCase(payload.kategoriApp);
|
||||||
|
const titleFix =
|
||||||
|
kategoriToNormalCase === "other"
|
||||||
|
? payload.title
|
||||||
|
: `${_.startCase(kategoriToNormalCase)}: ${payload.title}`;
|
||||||
|
console.log("titleFix", titleFix);
|
||||||
|
|
||||||
|
// 1. Simpan notifikasi ke DB
|
||||||
|
const notification = await prisma.notifikasi.create({
|
||||||
|
data: {
|
||||||
|
title: titleFix,
|
||||||
|
pesan: payload.body,
|
||||||
|
deepLink: payload.deepLink,
|
||||||
|
kategoriApp: payload.kategoriApp,
|
||||||
|
recipientId: recipientId,
|
||||||
|
senderId: senderId,
|
||||||
|
type: payload.type.trim(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Ambil semua token aktif milik penerima
|
||||||
|
const tokens = await prisma.tokenUserDevice.findMany({
|
||||||
|
where: { userId: recipientId },
|
||||||
|
select: { token: true, id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (tokens.length === 0) {
|
||||||
|
console.warn(`No active tokens found for user ${recipientId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Kirim FCM ke semua token
|
||||||
|
await Promise.allSettled(
|
||||||
|
tokens.map(async ({ token, id }) => {
|
||||||
|
try {
|
||||||
|
await adminMessaging.send({
|
||||||
|
token,
|
||||||
|
notification: {
|
||||||
|
title: titleFix,
|
||||||
|
body: payload.body,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
sentAt: new Date().toISOString(), // ✅ Simpan metadata di data
|
||||||
|
id: notification.id,
|
||||||
|
deepLink: payload.deepLink,
|
||||||
|
recipientId: recipientId,
|
||||||
|
},
|
||||||
|
android: {
|
||||||
|
priority: "high" as const,
|
||||||
|
notification: { channelId: "default" },
|
||||||
|
ttl: 0 as const,
|
||||||
|
},
|
||||||
|
apns: {
|
||||||
|
payload: { aps: { sound: "default" as const } },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (fcmError: any) {
|
||||||
|
// Hapus token jika invalid
|
||||||
|
if (fcmError.code === "messaging/registration-token-not-registered") {
|
||||||
|
// Hapus token dari DB
|
||||||
|
await prisma.tokenUserDevice.delete({ where: { id } });
|
||||||
|
console.log(`🗑️ Invalid token removed: ${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`✅ Notification sent to user ${recipientId}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to send notification:", error);
|
||||||
|
throw error; // biarkan caller handle error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kirim notifikasi ke banyak user
|
||||||
|
*/
|
||||||
|
export async function sendNotificationMobileToManyUser({
|
||||||
|
recipientIds,
|
||||||
|
senderId,
|
||||||
|
payload,
|
||||||
|
}: {
|
||||||
|
recipientIds: string[];
|
||||||
|
senderId: string;
|
||||||
|
payload: NotificationMobilePayload;
|
||||||
|
}) {
|
||||||
|
await Promise.allSettled(
|
||||||
|
recipientIds.map((id) =>
|
||||||
|
sendNotificationMobileToOneUser({
|
||||||
|
recipientId: id,
|
||||||
|
senderId: senderId,
|
||||||
|
payload: payload,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
81
src/lib/mobile/route-page-mobile.ts
Normal file
81
src/lib/mobile/route-page-mobile.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
export { routeAdminMobile, routeUserMobile };
|
||||||
|
|
||||||
|
type StatusApp = "review" | "draft" | "reject" | "publish";
|
||||||
|
|
||||||
|
const routeAdminMobile = {
|
||||||
|
userAccess: ({ id }: { id: string }) => `/admin/user-access/${id}`,
|
||||||
|
// JOB
|
||||||
|
jobByStatus: ({ status }: { status: StatusApp }) =>
|
||||||
|
`/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 = {
|
||||||
|
home: `/(user)/home`,
|
||||||
|
// JOB
|
||||||
|
jobByStatus: ({ status }: { status?: StatusApp }) =>
|
||||||
|
`/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`,
|
||||||
|
};
|
||||||
@@ -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"]
|
||||||
}
|
}
|
||||||
|
|||||||
40
types/type-mobile-notification.ts
Normal file
40
types/type-mobile-notification.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Jika semua custom type diawali "custom_"
|
||||||
|
|
||||||
|
export type NotificationMobilePayload = {
|
||||||
|
title: NotificationMobileTitleType;
|
||||||
|
body: NotificationMobileBodyType;
|
||||||
|
userLoginId?: string;
|
||||||
|
appId?: string;
|
||||||
|
status?: string;
|
||||||
|
type: "announcement" | "trigger";
|
||||||
|
deepLink: string;
|
||||||
|
kategoriApp: TypeNotificationCategoryApp;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NotificationMobileTitleType =
|
||||||
|
| (string & { __type: "NotificationMobileTitleType" })
|
||||||
|
// Admin
|
||||||
|
| "Pengajuan Review Baru"
|
||||||
|
// USER
|
||||||
|
| "Pengajuan Review Ditolak"
|
||||||
|
| "Review Selesai"
|
||||||
|
// to ALL user
|
||||||
|
|
||||||
|
export type NotificationMobileBodyType =
|
||||||
|
// USER
|
||||||
|
| (string & { __type: "NotificationMobileBodyType" })
|
||||||
|
| "Ada pengajuan review" // tambah title
|
||||||
|
|
||||||
|
// ADMIN
|
||||||
|
| "Mohon perbaiki data sesuai catatan penolakan !"
|
||||||
|
| "Selamat data anda telah terpublikasi"
|
||||||
|
|
||||||
|
export type TypeNotificationCategoryApp =
|
||||||
|
| "EVENT"
|
||||||
|
| "JOB"
|
||||||
|
| "VOTING"
|
||||||
|
| "DONASI"
|
||||||
|
| "INVESTASI"
|
||||||
|
| "COLLABORATION"
|
||||||
|
| "FORUM"
|
||||||
|
| "OTHER";
|
||||||
7
x.sh
7
x.sh
@@ -3,10 +3,13 @@ URL="http://localhost:3000"
|
|||||||
# curl -X GET -H "Authorization: Bearer $TOKEN" ${URL}/api/middleware
|
# curl -X GET -H "Authorization: Bearer $TOKEN" ${URL}/api/middleware
|
||||||
# curl -X GET -H "Cookie: hipmi-key=$TOKEN; user_id=789" ${URL}/dev/home | tee test.html
|
# curl -X GET -H "Cookie: hipmi-key=$TOKEN; user_id=789" ${URL}/dev/home | tee test.html
|
||||||
|
|
||||||
curl -X POST ${URL}/api/mobile/notifications \
|
curl -X POST ${URL}/api/mobile/notification \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"fcmToken": "cVmHm-3P4E-1vjt6AA9kSF:APA91bHTkHjGTLxrFsb6Le6bZmzboZhwMGYXU4p0FP9yEeXixLDXNKS4F5vLuZV3sRgSnjjQsPpLOgstVLHJB8VJTObctKLdN-CxAp4dnP7Jbc_mH53jWvs",
|
"fcmToken": "cVmHm-3P4E-1vjt6AA9kSF:APA91bHTkHjGTLxrFsb6Le6bZmzboZhwMGYXU4p0FP9yEeXixLDXNKS4F5vLuZV3sRgSnjjQsPpLOgstVLHJB8VJTObctKLdN-CxAp4dnP7Jbc_mH53jWvs",
|
||||||
"title": "Test dari Backend (App Router)!",
|
"title": "Test dari Backend (App Router)!",
|
||||||
"body": "Berhasil di App Router!"
|
"body": "Berhasil di App Router!",
|
||||||
|
"userLoginId": "cmha7p6yc0000cfoe5w2e7gdr",
|
||||||
|
"type": "NOTIFICATION",
|
||||||
|
"kategoriApp": "PERCOBAAN"
|
||||||
}'
|
}'
|
||||||
Reference in New Issue
Block a user