diff --git a/PROMPT-AI.md b/PROMPT-AI.md index f40844d7..2dbed296 100644 --- a/PROMPT-AI.md +++ b/PROMPT-AI.md @@ -1,5 +1,5 @@ -File utama: src/app/api/mobile/donation/[id]/[status]/route.ts +File utama: src/app/api/mobile/donation/[id]/donatur/route.ts Terapkan pagination pada file "File utama" pada method GET Analisa juga file "File utama", jika belum memiliki page dari seachParams maka terapkan. Juga pastikan take dan skip sudah sesuai dengan pagination. Buat default nya menjadi 10 untuk take data @@ -33,4 +33,13 @@ Buatkan auto input untuk method POST dengan data yang dibutuhkan sesuai dengan s - rekening: string - imageId: number ( cm60j9q3m000xc9dc584v8rh8 ) -Untuk sisa nya anda bisa bebas mengisi data tersebut. \ No newline at end of file +Untuk sisa nya anda bisa bebas mengisi data tersebut. + + +Branch: mobile-api/10-feb-26 +Jalankan perintah ini: git checkout -b "Branch" +Setelah itu jalankan perintah ini: git add . +Setelah itu jalankan perintah ini: git commit -m " + +" +Setelah itu jalankan perintah ini: git push origin "Branch" \ No newline at end of file diff --git a/QWEN.md b/QWEN.md index 57dfe1b8..dff347ef 100644 --- a/QWEN.md +++ b/QWEN.md @@ -2,7 +2,7 @@ ## Project Overview -HIPMI (Himpunan Pengusaha Muda Indonesia) is a comprehensive Next.js-based web application built for the Indonesian Young Entrepreneurs Association. The project is a sophisticated platform that provides multiple business functionalities including investment management, donations, events, job listings, forums, voting systems, and collaborative projects. +HIPMI (Himpunan Pengusaha Muya Indonesia) is a comprehensive Next.js-based web application built for the Indonesian Young Entrepreneurs Association. The project is a sophisticated platform that provides multiple business functionalities including investment management, donations, events, job listings, forums, voting systems, and collaborative projects. ### Key Technologies - **Framework**: Next.js 13+ (with App Router) diff --git a/src/app/api/mobile/auth/device-tokens/route.ts b/src/app/api/mobile/auth/device-tokens/route.ts index 2b307500..bf281ee7 100644 --- a/src/app/api/mobile/auth/device-tokens/route.ts +++ b/src/app/api/mobile/auth/device-tokens/route.ts @@ -4,13 +4,42 @@ import { prisma } from "@/lib"; export { POST, GET }; async function POST(request: NextRequest) { - const { data } = await request.json(); try { + // Parse the request body - can accept either nested under 'data' or directly + const requestBody = await request.json(); + + // Check if the data is nested under 'data' property (as described in the issue) + // or if it's directly in the request body (more common pattern) + const payload = requestBody.data ? requestBody.data : requestBody; + + const { userId, platform, deviceId, model, appVersion, fcmToken } = payload; - const { userId, platform, deviceId, model, appVersion, fcmToken } = data; - + // Validate required fields if (!fcmToken) { - return NextResponse.json({ error: "Missing Token" }, { status: 400 }); + return NextResponse.json( + { error: "Missing FCM token", field: "fcmToken" }, + { status: 400 } + ); + } + + if (!userId) { + return NextResponse.json( + { error: "Missing user ID", field: "userId" }, + { status: 400 } + ); + } + + // Verify that the user exists before creating/updating the device token + const userExists = await prisma.user.findUnique({ + where: { id: userId }, + select: { id: true } + }); + + if (!userExists) { + return NextResponse.json( + { error: "User not found", field: "userId" }, + { status: 404 } + ); } const existing = await prisma.tokenUserDevice.findFirst({ @@ -23,7 +52,6 @@ async function POST(request: NextRequest) { }, }); - console.log("✅ EX", existing); let deviceToken; @@ -31,7 +59,7 @@ async function POST(request: NextRequest) { if (existing) { deviceToken = await prisma.tokenUserDevice.update({ where: { - id: existing?.id, + id: existing.id, }, data: { platform, @@ -43,7 +71,7 @@ async function POST(request: NextRequest) { }, }); } else { - // Buat baru jika belum ada + // Create new device token record deviceToken = await prisma.tokenUserDevice.create({ data: { token: fcmToken, @@ -58,9 +86,16 @@ async function POST(request: NextRequest) { } return NextResponse.json({ success: true, data: deviceToken }); - } catch (error) { + } catch (error: any) { + console.error("Error registering device token:", error); + + // Return more informative error response return NextResponse.json( - { error: (error as Error).message }, + { + error: "Internal server error", + message: error.message || "An unexpected error occurred", + field: "server" + }, { status: 500 } ); } diff --git a/src/app/api/mobile/donation/[id]/[status]/route.ts b/src/app/api/mobile/donation/[id]/[status]/route.ts index b2fb3c26..5ddc0a21 100644 --- a/src/app/api/mobile/donation/[id]/[status]/route.ts +++ b/src/app/api/mobile/donation/[id]/[status]/route.ts @@ -1,6 +1,7 @@ import _ from "lodash"; import { NextResponse } from "next/server"; import prisma from "@/lib/prisma"; +import { PAGINATION_DEFAULT_TAKE } from "@/lib/constans-value/constansValue"; export { GET, PUT }; @@ -12,7 +13,7 @@ async function GET( const fixStatus = _.startCase(status); const { searchParams } = new URL(request.url); const page = Number(searchParams.get("page")) || 1; - const takeData = 5 + const takeData = PAGINATION_DEFAULT_TAKE const skipData = page * takeData - takeData; let fixData; diff --git a/src/app/api/mobile/donation/[id]/disbursement/route.ts b/src/app/api/mobile/donation/[id]/disbursement/route.ts index a6786376..1245b70b 100644 --- a/src/app/api/mobile/donation/[id]/disbursement/route.ts +++ b/src/app/api/mobile/donation/[id]/disbursement/route.ts @@ -1,5 +1,6 @@ import { NextResponse } from "next/server"; import { prisma } from "@/lib"; +import { PAGINATION_DEFAULT_TAKE } from "@/lib/constans-value/constansValue"; export { GET }; @@ -7,7 +8,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) { const { id } = params; const { searchParams } = new URL(request.url); const page = Number(searchParams.get("page")); - const takeData = 5; + const takeData = PAGINATION_DEFAULT_TAKE; const skipData = page * takeData - takeData; try { diff --git a/src/app/api/mobile/donation/[id]/donatur/route.ts b/src/app/api/mobile/donation/[id]/donatur/route.ts index d33b97f9..c503cee5 100644 --- a/src/app/api/mobile/donation/[id]/donatur/route.ts +++ b/src/app/api/mobile/donation/[id]/donatur/route.ts @@ -1,3 +1,4 @@ +import { PAGINATION_DEFAULT_TAKE } from "@/lib/constans-value/constansValue"; import prisma from "@/lib/prisma"; import { NextResponse } from "next/server"; @@ -9,11 +10,12 @@ export async function GET( let fixData; const { id } = params; const { searchParams } = new URL(request.url); - const page = Number(searchParams.get("page")); - const takeData = 10; + const page = Number(searchParams.get("page")) || 1; // Default page 1 jika tidak ada atau invalid + const takeData = PAGINATION_DEFAULT_TAKE; const skipData = page * takeData - takeData; - fixData = await prisma.donasi_Invoice.findMany({ + // Query data dengan pagination + const data = await prisma.donasi_Invoice.findMany({ take: page ? takeData : undefined, skip: page ? skipData : undefined, orderBy: { @@ -59,10 +61,31 @@ export async function GET( }, }); + // Hitung total data untuk pagination + const totalCount = await prisma.donasi_Invoice.count({ + where: { + donasiId: id, + DonasiMaster_StatusInvoice: { + name: "Berhasil", + }, + }, + }); + + // Hitung total halaman + const totalPages = Math.ceil(totalCount / takeData); + + fixData = data; + return NextResponse.json({ success: true, message: "Data berhasil diambil", data: fixData, + pagination: { + currentPage: page, + totalPages: totalPages, + totalData: totalCount, + dataPerPage: takeData, + }, }); } catch (error) { return NextResponse.json({ diff --git a/src/app/api/mobile/donation/[id]/news/route.ts b/src/app/api/mobile/donation/[id]/news/route.ts index 72ad3121..b4262c55 100644 --- a/src/app/api/mobile/donation/[id]/news/route.ts +++ b/src/app/api/mobile/donation/[id]/news/route.ts @@ -8,6 +8,7 @@ import { } from "../../../../../../../types/type-mobile-notification"; import { routeUserMobile } from "@/lib/mobile/route-page-mobile"; import { funFindDonaturList } from "@/lib/mobile/donation/find-donatur-list"; +import { PAGINATION_DEFAULT_TAKE } from "@/lib/constans-value/constansValue"; export { POST, GET, PUT, DELETE }; @@ -94,11 +95,16 @@ async function GET( const { id } = params; const { searchParams } = new URL(request.url); const category = searchParams.get("category"); + const page = Number(searchParams.get("page")) || 1; // Default page 1 jika tidak ada + const takeData = PAGINATION_DEFAULT_TAKE; // Default 10 data per halaman + const skipData = page * takeData - takeData; + let fixData; + let totalCount = 0; // Untuk menghitung total data try { if (category === "get-all") { - fixData = await prisma.donasi_Kabar.findMany({ + const data = await prisma.donasi_Kabar.findMany({ orderBy: { updatedAt: "desc", }, @@ -106,6 +112,8 @@ async function GET( donasiId: id, active: true, }, + take: page ? takeData : undefined, + skip: page ? skipData : undefined, select: { id: true, title: true, @@ -113,6 +121,17 @@ async function GET( createdAt: true, }, }); + + // Hitung total data untuk pagination + totalCount = await prisma.donasi_Kabar.count({ + where: { + donasiId: id, + active: true, + }, + }); + + fixData = data; + } else if (category === "get-one") { const data = await prisma.donasi_Kabar.findUnique({ where: { @@ -135,11 +154,24 @@ async function GET( }; } + // Hitung total halaman jika kategori adalah get-all + let pagination = undefined; + if (category === "get-all") { + const totalPages = Math.ceil(totalCount / takeData); + pagination = { + currentPage: page, + totalPages: totalPages, + totalData: totalCount, + dataPerPage: takeData, + }; + } + return NextResponse.json({ status: 200, success: true, message: "Berhasil mengambil kabar", data: fixData, + pagination: pagination, }); } catch (error) { console.error("[ERROR GET NEWS]", error); diff --git a/src/app/api/mobile/donation/route.ts b/src/app/api/mobile/donation/route.ts index da4d9566..61e205e9 100644 --- a/src/app/api/mobile/donation/route.ts +++ b/src/app/api/mobile/donation/route.ts @@ -4,6 +4,7 @@ import _ from "lodash"; import { NextResponse } from "next/server"; import { NotificationMobileBodyType } from "../../../../../types/type-mobile-notification"; import { routeAdminMobile } from "@/lib/mobile/route-page-mobile"; +import { PAGINATION_DEFAULT_TAKE } from "@/lib/constans-value/constansValue"; export { POST, GET }; @@ -125,7 +126,12 @@ async function GET(request: Request) { const { searchParams } = new URL(request.url); const category = searchParams.get("category"); const authorId = searchParams.get("authorId"); + const page = Number(searchParams.get("page")) || 1; // Default page 1 jika tidak ada + const takeData = PAGINATION_DEFAULT_TAKE; // Default 10 data per halaman + const skipData = page * takeData - takeData; + let fixData; + let totalCount = 0; // Untuk menghitung total data try { if (category === "beranda") { @@ -137,6 +143,8 @@ async function GET(request: Request) { donasiMaster_StatusDonasiId: "1", active: true, }, + take: page ? takeData : undefined, + skip: page ? skipData : undefined, select: { id: true, imageId: true, @@ -152,6 +160,14 @@ async function GET(request: Request) { }, }); + // Hitung total data untuk pagination + totalCount = await prisma.donasi.count({ + where: { + donasiMaster_StatusDonasiId: "1", + active: true, + }, + }); + fixData = data.map((v: any) => ({ ..._.omit(v, ["DonasiMaster_Durasi"]), durasiDonasi: v.DonasiMaster_Durasi.name, @@ -164,6 +180,8 @@ async function GET(request: Request) { where: { authorId: authorId, }, + take: page ? takeData : undefined, + skip: page ? skipData : undefined, select: { id: true, nominal: true, @@ -190,6 +208,13 @@ async function GET(request: Request) { }, }); + // Hitung total data untuk pagination + totalCount = await prisma.donasi_Invoice.count({ + where: { + authorId: authorId, + }, + }); + fixData = data.map((v: any) => ({ ..._.omit(v, ["DonasiMaster_StatusInvoice", "Donasi"]), statusInvoice: v.DonasiMaster_StatusInvoice.name, @@ -202,8 +227,21 @@ async function GET(request: Request) { })); } + // Hitung total halaman + const totalPages = Math.ceil(totalCount / takeData); + return NextResponse.json( - { success: true, message: "Data berhasil diambil", data: fixData }, + { + success: true, + message: "Data berhasil diambil", + data: fixData, + pagination: { + currentPage: page, + totalPages: totalPages, + totalData: totalCount, + dataPerPage: takeData, + } + }, { status: 200 } ); } catch (error) {