diff --git a/CHANGELOG.md b/CHANGELOG.md index e7628590..7242b2ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ 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.17](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.16...v1.5.17) (2025-11-24) + + +### Bug Fixes + +* delete all data user ([fb9515d](https://wibugit.wibudev.com/wibu/hipmi/commit/fb9515dfe465ef07d43460ca4e9bb31705ec48b8)) + ## [1.5.16](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.15...v1.5.16) (2025-11-20) ## [1.5.15](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.5.14...v1.5.15) (2025-11-18) diff --git a/package.json b/package.json index 93abd286..42daea0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.5.16", + "version": "1.5.17", "private": true, "prisma": { "seed": "bun prisma/seed.ts" diff --git a/prisma/migrations/20251124061947_add_terms_of_service_accepted/migration.sql b/prisma/migrations/20251124061947_add_terms_of_service_accepted/migration.sql new file mode 100644 index 00000000..2fd9edc8 --- /dev/null +++ b/prisma/migrations/20251124061947_add_terms_of_service_accepted/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "Donasi_Invoice" ALTER COLUMN "masterBankId" SET DEFAULT 'null'; + +-- AlterTable +ALTER TABLE "User" ADD COLUMN "termsOfServiceAccepted" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/migrations/20251124081155_add_blocked_user_and_menu_feature/migration.sql b/prisma/migrations/20251124081155_add_blocked_user_and_menu_feature/migration.sql new file mode 100644 index 00000000..c3959d1f --- /dev/null +++ b/prisma/migrations/20251124081155_add_blocked_user_and_menu_feature/migration.sql @@ -0,0 +1,35 @@ +-- CreateTable +CREATE TABLE "BlockedUser" ( + "id" TEXT NOT NULL, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "blockerId" TEXT NOT NULL, + "blockedId" TEXT NOT NULL, + "menuFeatureId" TEXT NOT NULL, + + CONSTRAINT "BlockedUser_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MenuFeature" ( + "id" TEXT NOT NULL, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "name" TEXT NOT NULL, + + CONSTRAINT "MenuFeature_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "BlockedUser_blockerId_blockedId_key" ON "BlockedUser"("blockerId", "blockedId"); + +-- AddForeignKey +ALTER TABLE "BlockedUser" ADD CONSTRAINT "BlockedUser_menuFeatureId_fkey" FOREIGN KEY ("menuFeatureId") REFERENCES "MenuFeature"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "BlockedUser" ADD CONSTRAINT "BlockedUser_blockerId_fkey" FOREIGN KEY ("blockerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "BlockedUser" ADD CONSTRAINT "BlockedUser_blockedId_fkey" FOREIGN KEY ("blockedId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20251124083155_fix_master_kategori_app_and_delete_menu_feature/migration.sql b/prisma/migrations/20251124083155_fix_master_kategori_app_and_delete_menu_feature/migration.sql new file mode 100644 index 00000000..dae34b57 --- /dev/null +++ b/prisma/migrations/20251124083155_fix_master_kategori_app_and_delete_menu_feature/migration.sql @@ -0,0 +1,14 @@ +/* + Warnings: + + - You are about to drop the `MenuFeature` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "BlockedUser" DROP CONSTRAINT "BlockedUser_menuFeatureId_fkey"; + +-- DropTable +DROP TABLE "MenuFeature"; + +-- AddForeignKey +ALTER TABLE "BlockedUser" ADD CONSTRAINT "BlockedUser_menuFeatureId_fkey" FOREIGN KEY ("menuFeatureId") REFERENCES "MasterKategoriApp"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index c72df09a..8fb86280 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -49,8 +49,12 @@ model User { BusinessMaps BusinessMaps[] Investasi_Invoice Investasi_Invoice[] - EventSponsor EventSponsor[] - EventTransaksi EventTransaksi[] + EventSponsor EventSponsor[] + EventTransaksi EventTransaksi[] + termsOfServiceAccepted Boolean @default(false) + + blockedUsers BlockedUser[] @relation("Blocking") + blockedBy BlockedUser[] @relation("BlockedBy") } model MasterUserRole { @@ -1011,6 +1015,8 @@ model MasterKategoriApp { updatedAt DateTime @updatedAt name String value String? + + blockedUsers BlockedUser[] } // ======================= EVENT ======================= // @@ -1073,3 +1079,20 @@ model Sticker { MasterEmotions MasterEmotions[] @relation("StikerEmotions") } + +model BlockedUser { + id String @id @default(uuid()) + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + blockerId String // ID user yang memblokir + blockedId String // ID user yang diblokir + + menuFeatureId String + menuFeature MasterKategoriApp @relation(fields: [menuFeatureId], references: [id]) + + blocker User @relation("BlockedBy", fields: [blockerId], references: [id]) + blocked User @relation("Blocking", fields: [blockedId], references: [id]) + + @@unique([blockerId, blockedId]) +} diff --git a/public/terms-of-service.html b/public/terms-of-service.html new file mode 100644 index 00000000..e28fd62b --- /dev/null +++ b/public/terms-of-service.html @@ -0,0 +1,110 @@ + + + + + + Syarat & Ketentuan - HIPMI Badung Connect + + + +

Syarat & Ketentuan Penggunaan HIPMI Badung Connect

+ +

+ Dengan menggunakan aplikasi HIPMI Badung Connect (“Aplikasi”), Anda setuju untuk mematuhi dan terikat oleh syarat dan ketentuan berikut. Jika Anda tidak setuju dengan ketentuan ini, harap jangan gunakan Aplikasi. +

+ +

1. Definisi

+

+ HIPMI Badung Connect adalah platform digital resmi untuk anggota Himpunan Pengusaha Muda Indonesia (HIPMI) Kabupaten Badung, yang bertujuan memfasilitasi jaringan, kolaborasi, dan pertumbuhan bisnis para pengusaha muda. +

+ +

2. Larangan Konten Tidak Pantas

+

+ Anda dilarang keras memposting, mengirim, membagikan, atau mengunggah konten apa pun yang mengandung: +

+ + +

3. Tanggung Jawab Pengguna

+

+ Anda bertanggung jawab penuh atas setiap konten yang Anda unggah atau bagikan melalui fitur-fitur berikut: +

+ +

+ Konten yang melanggar ketentuan ini dapat dihapus kapan saja tanpa pemberitahuan. +

+ +

4. Tindakan terhadap Pelanggaran

+

+ Jika kami menerima laporan atau menemukan konten yang melanggar ketentuan ini, kami akan: +

+ +

+ Tim kami berkomitmen untuk menanggapi laporan konten tidak pantas dalam waktu 24 jam. +

+ +

5. Mekanisme Pelaporan

+

+ Anda dapat melaporkan konten atau pengguna yang mencurigakan melalui: +

+ +

+ Setiap laporan akan ditangani secara rahasia dan segera. +

+ +

6. Perubahan Ketentuan

+

+ Kami berhak memperbarui Syarat & Ketentuan ini sewaktu-waktu. Versi terbaru akan dipublikasikan di halaman ini dengan tanggal revisi yang diperbarui. +

+ +

7. Kontak

+

+ Jika Anda memiliki pertanyaan tentang ketentuan ini, silakan hubungi kami di: + bip.baliinteraktifperkasa@gmail.com +

+ + + + \ No newline at end of file diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 59049c88..4a93a84b 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -14,6 +14,8 @@ export async function POST(req: Request) { try { const { data } = await req.json(); + console.log("data >>", data); + const cekUsername = await prisma.user.findUnique({ where: { username: data.username, @@ -26,11 +28,20 @@ export async function POST(req: Request) { message: "Username sudah digunakan", }); + // ✅ Validasi wajib setuju Terms + if (data.termsOfServiceAccepted !== true) { + return NextResponse.json({ + success: false, + message: "You must agree to the Terms of Service", + }); + } + const createUser = await prisma.user.create({ data: { username: data.username, nomor: data.nomor, active: false, + termsOfServiceAccepted: data.termsOfServiceAccepted, }, }); @@ -51,7 +62,7 @@ export async function POST(req: Request) { success: true, message: "Registrasi Berhasil, Anda Sedang Login", token: token, - // data: createUser, + // data: createUser,x }, { status: 201 } ); @@ -65,7 +76,5 @@ export async function POST(req: Request) { }, { status: 500 } ); - } finally { - await prisma.$disconnect(); } } diff --git a/src/app/api/auth/term-service/route.ts b/src/app/api/auth/term-service/route.ts new file mode 100644 index 00000000..fc07faaf --- /dev/null +++ b/src/app/api/auth/term-service/route.ts @@ -0,0 +1,29 @@ +import { NextResponse } from "next/server"; +import prisma from "@/lib/prisma"; + +export async function POST(req: Request) { + try { + const { data } = await req.json(); + console.log("data >>", data); + + const updateTermService = await prisma.user.update({ + where: { + id: data.id, + }, + data: { + termsOfServiceAccepted: data.termsOfServiceAccepted, + }, + }); + + return NextResponse.json({ + success: true, + message: "Berhasil", + }); + } catch (error) { + console.log("error >>", error); + return NextResponse.json({ + success: false, + message: "Gagal", + }); + } +} diff --git a/src/app/api/auth/validasi/route.ts b/src/app/api/auth/validasi/route.ts index 3959ad1c..f0d94e08 100644 --- a/src/app/api/auth/validasi/route.ts +++ b/src/app/api/auth/validasi/route.ts @@ -24,6 +24,7 @@ export async function POST(req: Request) { username: true, active: true, masterUserRoleId: true, + termsOfServiceAccepted: true, }, }); @@ -52,6 +53,7 @@ export async function POST(req: Request) { message: "Berhasil Login", roleId: dataUser.masterUserRoleId, active: dataUser.active, + termsOfServiceAccepted: dataUser.termsOfServiceAccepted, token: token, }, { status: 200 } @@ -76,7 +78,5 @@ export async function POST(req: Request) { }, { status: 500 } ); - } finally { - await prisma.$disconnect(); } } diff --git a/src/app/api/mobile/block-user/route.ts b/src/app/api/mobile/block-user/route.ts new file mode 100644 index 00000000..76ca0a9b --- /dev/null +++ b/src/app/api/mobile/block-user/route.ts @@ -0,0 +1,47 @@ +import _ from "lodash"; +import { NextResponse } from "next/server"; +import prisma from "@/lib/prisma"; + +export { POST }; + +async function POST(request: Request) { + const { data } = await request.json(); + + console.log("data >>", data); + console.log("menuFeature masuk>>", data.menuFeature); + + try { + const nameApp = _.lowerCase(data.menuFeature); + const menuFeature = await prisma.masterKategoriApp.findFirst({ + where: { value: nameApp }, + select: { + id: true, + }, + }); + + console.log(" fix menuFeature >>", menuFeature); + + const blockUser = await prisma.blockedUser.create({ + data: { + blockerId: data.blockerId, + blockedId: data.blockedId, + menuFeatureId: menuFeature?.id as any, + }, + }); + + return NextResponse.json({ + status: 200, + success: true, + message: "success", + // data: blockUser, + }); + } catch (error) { + console.log("[ERROR BLOCK USER] >>", error); + return NextResponse.json({ + status: 500, + success: false, + message: "error", + reason: (error as Error).message || error, + }); + } +} diff --git a/src/app/api/mobile/forum/route.ts b/src/app/api/mobile/forum/route.ts index e27fef7a..bd236cf4 100644 --- a/src/app/api/mobile/forum/route.ts +++ b/src/app/api/mobile/forum/route.ts @@ -36,11 +36,109 @@ async function GET(request: Request) { let fixData; const { searchParams } = new URL(request.url); const authorId = searchParams.get("authorId"); + const userLoginId = searchParams.get("userLoginId"); const search = searchParams.get("search"); + const category = searchParams.get("category"); + const page = searchParams.get("page"); + const takeData = 5; + const skipData = (Number(page) - 1) * takeData; + + + // console.log("authorId", authorId); + // console.log("userLoginId", userLoginId); + // console.log("search", search); + // console.log("category", category); + console.log("page", page); try { - if (authorId) { + if (category === "beranda") { + const blockUserId = await prisma.blockedUser + .findMany({ + where: { + blockerId: userLoginId as string, + }, + select: { + blockedId: true, + }, + }) + .then((res) => { + return res.map((item) => item.blockedId); + }); + + console.log("blockUserId", blockUserId); + const data = await prisma.forum_Posting.findMany({ + take: page ? takeData : undefined, + skip: page ? skipData : undefined, + orderBy: { + createdAt: "desc", + }, + where: { + isActive: true, + diskusi: { + mode: "insensitive", + contains: search || "", + }, + authorId: { + notIn: blockUserId, + }, + }, + + select: { + id: true, + diskusi: true, + createdAt: true, + isActive: true, + authorId: true, + Author: { + select: { + id: true, + username: true, + Profile: { + select: { + id: true, + name: true, + imageId: true, + }, + }, + }, + }, + Forum_Komentar: { + where: { + isActive: true, + }, + }, + ForumMaster_StatusPosting: { + select: { + id: true, + status: true, + }, + }, + forumMaster_StatusPostingId: true, + }, + }); + + const newData = data.map((item) => { + const count = item.Forum_Komentar?.length ?? 0; + return { + ..._.omit(item, ["Forum_Komentar"]), + count, + }; + }); + + fixData = newData; + } else if (category === "forumku") { + + const count = await prisma.forum_Posting.count({ + where: { + isActive: true, + authorId: authorId, + }, + }) + + const data = await prisma.forum_Posting.findMany({ + take: page ? takeData : undefined, + skip: page ? skipData : undefined, orderBy: { createdAt: "desc", }, @@ -90,62 +188,18 @@ async function GET(request: Request) { }; }); - fixData = newData; + const dataFix = { + data: newData, + count, + } + + fixData = dataFix; } else { - const data = await prisma.forum_Posting.findMany({ - orderBy: { - createdAt: "desc", - }, - where: { - isActive: true, - diskusi: { - mode: "insensitive", - contains: search || "", - }, - }, - select: { - id: true, - diskusi: true, - createdAt: true, - isActive: true, - authorId: true, - Author: { - select: { - id: true, - username: true, - Profile: { - select: { - id: true, - name: true, - imageId: true, - }, - }, - }, - }, - Forum_Komentar: { - where: { - isActive: true, - }, - }, - ForumMaster_StatusPosting: { - select: { - id: true, - status: true, - }, - }, - forumMaster_StatusPostingId: true, - }, + return NextResponse.json({ + success: false, + message: "Gagal mendapatkan data", + reason: "Kategori tidak ditemukan", }); - - const newData = data.map((item) => { - const count = item.Forum_Komentar?.length ?? 0; - return { - ..._.omit(item, ["Forum_Komentar"]), - count, - }; - }); - - fixData = newData; } return NextResponse.json({ @@ -153,7 +207,6 @@ async function GET(request: Request) { message: "Berhasil mendapatkan data", data: fixData, }); - } catch (error) { console.log("[ERROR]", error); return NextResponse.json({ diff --git a/src/app/api/mobile/master/app-category/route.ts b/src/app/api/mobile/master/app-category/route.ts new file mode 100644 index 00000000..fa4c870b --- /dev/null +++ b/src/app/api/mobile/master/app-category/route.ts @@ -0,0 +1,28 @@ +import { NextResponse } from "next/server"; +import prisma from "@/lib/prisma"; + +export { GET }; + +async function GET(request: Request) { + try { + const data = await prisma.masterKategoriApp.findMany({ + where: { + isActive: true, + }, + }); + return NextResponse.json({ + status: 200, + success: true, + message: "success", + data: data, + }); + } catch (error) { + console.log("[ERROR GET APP CATEGORY] >>", error); + return NextResponse.json({ + status: 500, + success: false, + message: "error", + reason: (error as Error).message || error, + }); + } +} diff --git a/src/app_modules/_global/fun/generate_seeder.ts b/src/app_modules/_global/fun/generate_seeder.ts index 2595028d..95805602 100644 --- a/src/app_modules/_global/fun/generate_seeder.ts +++ b/src/app_modules/_global/fun/generate_seeder.ts @@ -60,12 +60,14 @@ async function seederUser() { username: i.name, masterUserRoleId: i.masterUserRoleId, active: i.active, + termsOfServiceAccepted: i.termsOfServiceAccepted, }, update: { nomor: i.nomor, username: i.name, masterUserRoleId: i.masterUserRoleId, active: i.active, + termsOfServiceAccepted: i.termsOfServiceAccepted, }, }); } @@ -564,10 +566,12 @@ async function masterKategoriApp() { create: { id: a.id, name: a.name, + value: a.value, }, update: { id: a.id, name: a.name, + value: a.value, }, }); } diff --git a/src/bin/seeder/master/master_kategori_app.json b/src/bin/seeder/master/master_kategori_app.json index 1ffdba06..3d8fc6f1 100644 --- a/src/bin/seeder/master/master_kategori_app.json +++ b/src/bin/seeder/master/master_kategori_app.json @@ -1,30 +1,37 @@ [ { "id": "1", - "name": "Event" + "name": "Event", + "value": "event" }, { "id": "2", - "name": "Job" + "name": "Job", + "value": "job" }, { "id": "3", - "name": "Voting" + "name": "Voting", + "value": "voting" }, { "id": "4", - "name": "Donasi" + "name": "Donasi", + "value": "donasi" }, { "id": "5", - "name": "Investasi" + "name": "Investasi", + "value": "investasi" }, { "id": "6", - "name": "Forum" + "name": "Forum", + "value": "forum" }, { "id": "7", - "name": "Collaboration" + "name": "Collaboration", + "value": "collaboration" } ] diff --git a/src/bin/seeder/user_seeder.json b/src/bin/seeder/user_seeder.json index 356be9bf..a8a2f0fd 100644 --- a/src/bin/seeder/user_seeder.json +++ b/src/bin/seeder/user_seeder.json @@ -3,12 +3,14 @@ "name": "bagas_admin", "nomor": "6282340374412", "masterUserRoleId": "3", - "active": true + "active": true, + "termsOfServiceAccepted": true }, { "name": "fahmi_admin", "nomor": "628123833845", "masterUserRoleId": "2", - "active": true + "active": true, + "termsOfServiceAccepted": true } ] diff --git a/src/middleware.tsx b/src/middleware.tsx index 03f518fb..5c421996 100644 --- a/src/middleware.tsx +++ b/src/middleware.tsx @@ -19,6 +19,7 @@ const CONFIG: MiddlewareConfig = { publicRoutes: [ "/", "/.well-known/*", + "/terms-of-service.html", "/privacy-policy.html", "/api/helper/*", "/api/not-user/*",