Merge pull request #63 from bipproduction/notifikasi/job

Notifikasi/job
This commit is contained in:
Bagasbanuna02
2024-06-12 14:27:04 +08:00
committed by GitHub
69 changed files with 3129 additions and 1029 deletions

View File

@@ -53,6 +53,7 @@
"mqtt": "^5.5.0",
"next": "^13.5.4-canary.8",
"next-dev": "^1.1.9",
"next-scroll-loader": "^1.0.5",
"postcss": "8.4.27",
"react": "18.2.0",
"react-countdown": "^2.3.5",

View File

@@ -0,0 +1,820 @@
/*
Warnings:
- You are about to drop the `Katalog` table. If the table is not empty, all the data it contains will be lost.
- A unique constraint covering the columns `[imagesBackgroundId]` on the table `Profile` will be added. If there are existing duplicate values, this will fail.
*/
-- DropForeignKey
ALTER TABLE "Katalog" DROP CONSTRAINT "Katalog_masterBidangBisnisId_fkey";
-- DropForeignKey
ALTER TABLE "Katalog" DROP CONSTRAINT "Katalog_profileId_fkey";
-- AlterTable
ALTER TABLE "Images" ADD COLUMN "label" TEXT NOT NULL DEFAULT 'null';
-- AlterTable
ALTER TABLE "Profile" ADD COLUMN "imagesBackgroundId" TEXT;
-- DropTable
DROP TABLE "Katalog";
-- CreateTable
CREATE TABLE "KodeOtp" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"nomor" TEXT NOT NULL,
"otp" INTEGER NOT NULL,
CONSTRAINT "KodeOtp_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ImagesBackground" (
"id" TEXT NOT NULL,
"url" TEXT NOT NULL,
"label" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "ImagesBackground_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Portofolio" (
"id" TEXT NOT NULL,
"id_Portofolio" TEXT NOT NULL,
"namaBisnis" TEXT NOT NULL,
"alamatKantor" TEXT NOT NULL,
"tlpn" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"profileId" TEXT,
"masterBidangBisnisId" TEXT NOT NULL,
"logoId" TEXT,
CONSTRAINT "Portofolio_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Portofolio_MediaSosial" (
"id" TEXT NOT NULL,
"facebook" TEXT,
"twitter" TEXT,
"instagram" TEXT,
"tiktok" TEXT,
"youtube" TEXT,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"portofolioId" TEXT,
CONSTRAINT "Portofolio_MediaSosial_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "MasterStatus" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "MasterStatus_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Donasi" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"target" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"publishTime" TIMESTAMP(3),
"catatan" TEXT,
"progres" TEXT DEFAULT '0',
"terkumpul" TEXT DEFAULT '0',
"namaBank" TEXT,
"rekening" TEXT,
"akumulasiPencairan" INTEGER DEFAULT 0,
"totalPencairan" INTEGER DEFAULT 0,
"authorId" TEXT,
"imagesId" TEXT,
"donasiMaster_KategoriId" TEXT,
"donasiMaster_DurasiId" TEXT,
"donasiMaster_StatusDonasiId" TEXT DEFAULT '2',
CONSTRAINT "Donasi_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Donasi_TemporaryCreate" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"target" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"imagesId" TEXT,
"donasiMaster_KategoriId" TEXT,
"donasiMaster_DurasiId" TEXT,
CONSTRAINT "Donasi_TemporaryCreate_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "DonasiMaster_Kategori" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "DonasiMaster_Kategori_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "DonasiMaster_Durasi" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "DonasiMaster_Durasi_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Donasi_Cerita" (
"id" TEXT NOT NULL,
"pembukaan" TEXT NOT NULL,
"cerita" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"imagesId" TEXT,
"donasiId" TEXT,
CONSTRAINT "Donasi_Cerita_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "DonasiMaster_StatusDonasi" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "DonasiMaster_StatusDonasi_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "DonasiMaster_Bank" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"norek" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "DonasiMaster_Bank_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "DonasiMaster_StatusInvoice" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "DonasiMaster_StatusInvoice_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Donasi_Invoice" (
"id" TEXT NOT NULL,
"nominal" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"donasiId" TEXT,
"donasiMaster_BankId" TEXT,
"donasiMaster_StatusInvoiceId" TEXT DEFAULT '3',
"authorId" TEXT,
"imagesId" TEXT,
CONSTRAINT "Donasi_Invoice_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Donasi_Kabar" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"donasiId" TEXT,
"imagesId" TEXT,
CONSTRAINT "Donasi_Kabar_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Donasi_Notif" (
"id" TEXT NOT NULL,
"isRead" BOOLEAN NOT NULL DEFAULT false,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"userId" TEXT,
"donasi_KabarId" TEXT,
CONSTRAINT "Donasi_Notif_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Donasi_PencairanDana" (
"id" TEXT NOT NULL,
"nominalCair" INTEGER NOT NULL,
"title" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"donasiId" TEXT,
"imagesId" TEXT,
CONSTRAINT "Donasi_PencairanDana_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Event" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"lokasi" TEXT NOT NULL,
"tanggal" TIMESTAMP(3) NOT NULL,
"deskripsi" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"catatan" TEXT,
"authorId" TEXT,
"eventMaster_StatusId" TEXT DEFAULT '2',
"eventMaster_TipeAcaraId" INTEGER,
CONSTRAINT "Event_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "EventMaster_TipeAcara" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "EventMaster_TipeAcara_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "EventMaster_Status" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "EventMaster_Status_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Event_Peserta" (
"id" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"eventId" TEXT,
"userId" TEXT,
CONSTRAINT "Event_Peserta_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Voting" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"title" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
"awalVote" TIMESTAMP(3) NOT NULL,
"akhirVote" TIMESTAMP(3) NOT NULL,
"catatan" TEXT,
"authorId" TEXT NOT NULL,
"voting_StatusId" TEXT DEFAULT '2',
CONSTRAINT "Voting_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Voting_Status" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Voting_Status_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Voting_DaftarNamaVote" (
"id" TEXT NOT NULL,
"value" TEXT NOT NULL,
"jumlah" INTEGER NOT NULL DEFAULT 0,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"votingId" TEXT,
CONSTRAINT "Voting_DaftarNamaVote_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Voting_Kontributor" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"votingId" TEXT,
"authorId" TEXT,
"voting_DaftarNamaVoteId" TEXT,
CONSTRAINT "Voting_Kontributor_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Job" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"isArsip" BOOLEAN NOT NULL DEFAULT false,
"catatan" TEXT,
"title" TEXT NOT NULL,
"content" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
"imagesId" TEXT,
"authorId" TEXT,
"masterStatusId" TEXT DEFAULT '2',
CONSTRAINT "Job_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ForumMaster_StatusPosting" (
"id" SERIAL NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"status" TEXT NOT NULL,
CONSTRAINT "ForumMaster_StatusPosting_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Forum_Posting" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"publishAt" TIMESTAMP(3),
"diskusi" TEXT NOT NULL,
"authorId" TEXT,
"forumMaster_StatusPostingId" INTEGER,
CONSTRAINT "Forum_Posting_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Forum_Komentar" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"komentar" TEXT NOT NULL,
"forum_PostingId" TEXT,
"authorId" TEXT,
CONSTRAINT "Forum_Komentar_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ForumMaster_KategoriReport" (
"id" SERIAL NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"title" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
CONSTRAINT "ForumMaster_KategoriReport_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Forum_ReportPosting" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deskripsi" TEXT,
"forumMaster_KategoriReportId" INTEGER,
"forum_PostingId" TEXT,
"userId" TEXT,
CONSTRAINT "Forum_ReportPosting_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Forum_ReportKomentar" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deskripsi" TEXT,
"forumMaster_KategoriReportId" INTEGER,
"forum_KomentarId" TEXT,
"userId" TEXT,
CONSTRAINT "Forum_ReportKomentar_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaboration" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"title" TEXT NOT NULL,
"lokasi" TEXT NOT NULL,
"purpose" TEXT NOT NULL,
"benefit" TEXT,
"isReject" BOOLEAN DEFAULT false,
"report" TEXT,
"projectCollaborationMaster_IndustriId" INTEGER,
"userId" TEXT,
"projectCollaborationMaster_StatusId" INTEGER DEFAULT 1,
CONSTRAINT "ProjectCollaboration_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaborationMaster_Industri" (
"id" SERIAL 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 "ProjectCollaborationMaster_Industri_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaborationMaster_Status" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "ProjectCollaborationMaster_Status_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaboration_Partisipasi" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"userId" TEXT,
"projectCollaborationId" TEXT,
"deskripsi_diri" TEXT NOT NULL,
CONSTRAINT "ProjectCollaboration_Partisipasi_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaboration_RoomChat" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"userId" TEXT,
"projectCollaborationId" TEXT,
CONSTRAINT "ProjectCollaboration_RoomChat_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaboration_AnggotaRoomChat" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"userId" TEXT NOT NULL,
"projectCollaboration_RoomChatId" TEXT,
CONSTRAINT "ProjectCollaboration_AnggotaRoomChat_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaboration_Message" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"message" TEXT NOT NULL,
"isFile" BOOLEAN DEFAULT false,
"userId" TEXT,
"projectCollaboration_RoomChatId" TEXT,
CONSTRAINT "ProjectCollaboration_Message_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProjectCollaboration_Notifikasi" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"isRead" BOOLEAN NOT NULL DEFAULT false,
"note" TEXT,
"projectCollaborationId" TEXT NOT NULL,
"adminId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
CONSTRAINT "ProjectCollaboration_Notifikasi_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "NomorAdmin" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"nomor" TEXT NOT NULL,
CONSTRAINT "NomorAdmin_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Notifikasi" (
"id" TEXT NOT NULL,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"isRead" BOOLEAN NOT NULL DEFAULT false,
"appId" TEXT NOT NULL,
"kategoriApp" TEXT NOT NULL,
"pesan" TEXT NOT NULL,
"title" TEXT,
"status" TEXT,
"userRoleId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"adminId" TEXT NOT NULL,
CONSTRAINT "Notifikasi_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "Portofolio_id_Portofolio_key" ON "Portofolio"("id_Portofolio");
-- CreateIndex
CREATE UNIQUE INDEX "Portofolio_MediaSosial_portofolioId_key" ON "Portofolio_MediaSosial"("portofolioId");
-- CreateIndex
CREATE UNIQUE INDEX "Donasi_imagesId_key" ON "Donasi"("imagesId");
-- CreateIndex
CREATE UNIQUE INDEX "Donasi_TemporaryCreate_imagesId_key" ON "Donasi_TemporaryCreate"("imagesId");
-- CreateIndex
CREATE UNIQUE INDEX "Donasi_Cerita_imagesId_key" ON "Donasi_Cerita"("imagesId");
-- CreateIndex
CREATE UNIQUE INDEX "Donasi_Cerita_donasiId_key" ON "Donasi_Cerita"("donasiId");
-- CreateIndex
CREATE UNIQUE INDEX "Profile_imagesBackgroundId_key" ON "Profile"("imagesBackgroundId");
-- AddForeignKey
ALTER TABLE "Profile" ADD CONSTRAINT "Profile_imagesBackgroundId_fkey" FOREIGN KEY ("imagesBackgroundId") REFERENCES "ImagesBackground"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Portofolio" ADD CONSTRAINT "Portofolio_profileId_fkey" FOREIGN KEY ("profileId") REFERENCES "Profile"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Portofolio" ADD CONSTRAINT "Portofolio_masterBidangBisnisId_fkey" FOREIGN KEY ("masterBidangBisnisId") REFERENCES "MasterBidangBisnis"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Portofolio" ADD CONSTRAINT "Portofolio_logoId_fkey" FOREIGN KEY ("logoId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Portofolio_MediaSosial" ADD CONSTRAINT "Portofolio_MediaSosial_portofolioId_fkey" FOREIGN KEY ("portofolioId") REFERENCES "Portofolio"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi" ADD CONSTRAINT "Donasi_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi" ADD CONSTRAINT "Donasi_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi" ADD CONSTRAINT "Donasi_donasiMaster_KategoriId_fkey" FOREIGN KEY ("donasiMaster_KategoriId") REFERENCES "DonasiMaster_Kategori"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi" ADD CONSTRAINT "Donasi_donasiMaster_DurasiId_fkey" FOREIGN KEY ("donasiMaster_DurasiId") REFERENCES "DonasiMaster_Durasi"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi" ADD CONSTRAINT "Donasi_donasiMaster_StatusDonasiId_fkey" FOREIGN KEY ("donasiMaster_StatusDonasiId") REFERENCES "DonasiMaster_StatusDonasi"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_TemporaryCreate" ADD CONSTRAINT "Donasi_TemporaryCreate_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_TemporaryCreate" ADD CONSTRAINT "Donasi_TemporaryCreate_donasiMaster_KategoriId_fkey" FOREIGN KEY ("donasiMaster_KategoriId") REFERENCES "DonasiMaster_Kategori"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_TemporaryCreate" ADD CONSTRAINT "Donasi_TemporaryCreate_donasiMaster_DurasiId_fkey" FOREIGN KEY ("donasiMaster_DurasiId") REFERENCES "DonasiMaster_Durasi"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Cerita" ADD CONSTRAINT "Donasi_Cerita_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Cerita" ADD CONSTRAINT "Donasi_Cerita_donasiId_fkey" FOREIGN KEY ("donasiId") REFERENCES "Donasi"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Invoice" ADD CONSTRAINT "Donasi_Invoice_donasiId_fkey" FOREIGN KEY ("donasiId") REFERENCES "Donasi"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Invoice" ADD CONSTRAINT "Donasi_Invoice_donasiMaster_BankId_fkey" FOREIGN KEY ("donasiMaster_BankId") REFERENCES "DonasiMaster_Bank"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Invoice" ADD CONSTRAINT "Donasi_Invoice_donasiMaster_StatusInvoiceId_fkey" FOREIGN KEY ("donasiMaster_StatusInvoiceId") REFERENCES "DonasiMaster_StatusInvoice"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Invoice" ADD CONSTRAINT "Donasi_Invoice_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Invoice" ADD CONSTRAINT "Donasi_Invoice_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Kabar" ADD CONSTRAINT "Donasi_Kabar_donasiId_fkey" FOREIGN KEY ("donasiId") REFERENCES "Donasi"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Kabar" ADD CONSTRAINT "Donasi_Kabar_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Notif" ADD CONSTRAINT "Donasi_Notif_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_Notif" ADD CONSTRAINT "Donasi_Notif_donasi_KabarId_fkey" FOREIGN KEY ("donasi_KabarId") REFERENCES "Donasi_Kabar"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_PencairanDana" ADD CONSTRAINT "Donasi_PencairanDana_donasiId_fkey" FOREIGN KEY ("donasiId") REFERENCES "Donasi"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Donasi_PencairanDana" ADD CONSTRAINT "Donasi_PencairanDana_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Event" ADD CONSTRAINT "Event_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Event" ADD CONSTRAINT "Event_eventMaster_StatusId_fkey" FOREIGN KEY ("eventMaster_StatusId") REFERENCES "EventMaster_Status"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Event" ADD CONSTRAINT "Event_eventMaster_TipeAcaraId_fkey" FOREIGN KEY ("eventMaster_TipeAcaraId") REFERENCES "EventMaster_TipeAcara"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Event_Peserta" ADD CONSTRAINT "Event_Peserta_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "Event"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Event_Peserta" ADD CONSTRAINT "Event_Peserta_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Voting" ADD CONSTRAINT "Voting_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Voting" ADD CONSTRAINT "Voting_voting_StatusId_fkey" FOREIGN KEY ("voting_StatusId") REFERENCES "Voting_Status"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Voting_DaftarNamaVote" ADD CONSTRAINT "Voting_DaftarNamaVote_votingId_fkey" FOREIGN KEY ("votingId") REFERENCES "Voting"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Voting_Kontributor" ADD CONSTRAINT "Voting_Kontributor_votingId_fkey" FOREIGN KEY ("votingId") REFERENCES "Voting"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Voting_Kontributor" ADD CONSTRAINT "Voting_Kontributor_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Voting_Kontributor" ADD CONSTRAINT "Voting_Kontributor_voting_DaftarNamaVoteId_fkey" FOREIGN KEY ("voting_DaftarNamaVoteId") REFERENCES "Voting_DaftarNamaVote"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Job" ADD CONSTRAINT "Job_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Job" ADD CONSTRAINT "Job_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Job" ADD CONSTRAINT "Job_masterStatusId_fkey" FOREIGN KEY ("masterStatusId") REFERENCES "MasterStatus"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_Posting" ADD CONSTRAINT "Forum_Posting_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_Posting" ADD CONSTRAINT "Forum_Posting_forumMaster_StatusPostingId_fkey" FOREIGN KEY ("forumMaster_StatusPostingId") REFERENCES "ForumMaster_StatusPosting"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_Komentar" ADD CONSTRAINT "Forum_Komentar_forum_PostingId_fkey" FOREIGN KEY ("forum_PostingId") REFERENCES "Forum_Posting"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_Komentar" ADD CONSTRAINT "Forum_Komentar_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_ReportPosting" ADD CONSTRAINT "Forum_ReportPosting_forumMaster_KategoriReportId_fkey" FOREIGN KEY ("forumMaster_KategoriReportId") REFERENCES "ForumMaster_KategoriReport"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_ReportPosting" ADD CONSTRAINT "Forum_ReportPosting_forum_PostingId_fkey" FOREIGN KEY ("forum_PostingId") REFERENCES "Forum_Posting"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_ReportPosting" ADD CONSTRAINT "Forum_ReportPosting_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_ReportKomentar" ADD CONSTRAINT "Forum_ReportKomentar_forumMaster_KategoriReportId_fkey" FOREIGN KEY ("forumMaster_KategoriReportId") REFERENCES "ForumMaster_KategoriReport"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_ReportKomentar" ADD CONSTRAINT "Forum_ReportKomentar_forum_KomentarId_fkey" FOREIGN KEY ("forum_KomentarId") REFERENCES "Forum_Komentar"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Forum_ReportKomentar" ADD CONSTRAINT "Forum_ReportKomentar_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration" ADD CONSTRAINT "ProjectCollaboration_projectCollaborationMaster_IndustriId_fkey" FOREIGN KEY ("projectCollaborationMaster_IndustriId") REFERENCES "ProjectCollaborationMaster_Industri"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration" ADD CONSTRAINT "ProjectCollaboration_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration" ADD CONSTRAINT "ProjectCollaboration_projectCollaborationMaster_StatusId_fkey" FOREIGN KEY ("projectCollaborationMaster_StatusId") REFERENCES "ProjectCollaborationMaster_Status"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_Partisipasi" ADD CONSTRAINT "ProjectCollaboration_Partisipasi_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_Partisipasi" ADD CONSTRAINT "ProjectCollaboration_Partisipasi_projectCollaborationId_fkey" FOREIGN KEY ("projectCollaborationId") REFERENCES "ProjectCollaboration"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_RoomChat" ADD CONSTRAINT "ProjectCollaboration_RoomChat_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_RoomChat" ADD CONSTRAINT "ProjectCollaboration_RoomChat_projectCollaborationId_fkey" FOREIGN KEY ("projectCollaborationId") REFERENCES "ProjectCollaboration"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_AnggotaRoomChat" ADD CONSTRAINT "ProjectCollaboration_AnggotaRoomChat_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_AnggotaRoomChat" ADD CONSTRAINT "ProjectCollaboration_AnggotaRoomChat_projectCollaboration__fkey" FOREIGN KEY ("projectCollaboration_RoomChatId") REFERENCES "ProjectCollaboration_RoomChat"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_Message" ADD CONSTRAINT "ProjectCollaboration_Message_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_Message" ADD CONSTRAINT "ProjectCollaboration_Message_projectCollaboration_RoomChat_fkey" FOREIGN KEY ("projectCollaboration_RoomChatId") REFERENCES "ProjectCollaboration_RoomChat"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_Notifikasi" ADD CONSTRAINT "ProjectCollaboration_Notifikasi_projectCollaborationId_fkey" FOREIGN KEY ("projectCollaborationId") REFERENCES "ProjectCollaboration"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_Notifikasi" ADD CONSTRAINT "AdminNotifProjectUser" FOREIGN KEY ("adminId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProjectCollaboration_Notifikasi" ADD CONSTRAINT "UserNotifProjectUser" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Notifikasi" ADD CONSTRAINT "Notifikasi_userRoleId_fkey" FOREIGN KEY ("userRoleId") REFERENCES "MasterUserRole"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Notifikasi" ADD CONSTRAINT "NotifikasiUser" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Notifikasi" ADD CONSTRAINT "NotifikasiAdmin" FOREIGN KEY ("adminId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@@ -43,15 +43,18 @@ model User {
ProjectCollaboration_Message ProjectCollaboration_Message[]
AdminProjectCollaboration_Notifikasi ProjectCollaboration_Notifikasi[] @relation("AdminNotifProjectToUser")
UserProjectCollaboration_Notifikasi ProjectCollaboration_Notifikasi[] @relation("UserNotifProjectToUser")
Admin_Notifikasi Notifikasi[] @relation("AdminNotifikasi")
User_Notifikasi Notifikasi[] @relation("UserNotifikasi")
}
model MasterUserRole {
id String @id
name String
active Boolean @default(true)
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt
User User[]
id String @id
name String
active Boolean @default(true)
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt
User User[]
Notifikasi Notifikasi[]
}
model UserSession {
@@ -847,3 +850,23 @@ model NomorAdmin {
nomor String
}
model Notifikasi {
id String @id @default(cuid())
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isRead Boolean @default(false)
appId String
kategoriApp String
pesan String
title String?
status String?
Role MasterUserRole? @relation(fields: [userRoleId], references: [id])
userRoleId String
User User @relation("UserNotifikasi", fields: [userId], references: [id], map: "NotifikasiUser")
userId String
Admin User @relation("AdminNotifikasi", fields: [adminId], references: [id], map: "NotifikasiAdmin")
adminId String
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@@ -0,0 +1,8 @@
import adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id";
import { NextRequest, NextResponse } from "next/server";
export async function GET(req: NextRequest) {
return NextResponse.json({ success: true });
}

View File

@@ -1,12 +1,13 @@
import { AdminJob_TablePublish } from "@/app_modules/admin/job";
import adminJob_getListPublish from "@/app_modules/admin/job/fun/get/get_list_publish";
import { AdminJob_getListTableByStatusId } from "@/app_modules/admin/job/fun/get/get_list_table_by_status_id";
export default async function Page() {
const listPublish = await AdminJob_getListTableByStatusId("1")
// console.log(listPublish)
const listPublish = await adminJob_getListPublish({page: 1})
return (
<>
<AdminJob_TablePublish dataVote={listPublish} />
<AdminJob_TablePublish dataPublish={listPublish as any} />
</>
);
}

View File

@@ -1,13 +1,13 @@
import { AdminJob_TableReject } from "@/app_modules/admin/job";
import adminJob_getListReject from "@/app_modules/admin/job/fun/get/get_list_reject";
import { AdminJob_getListTableByStatusId } from "@/app_modules/admin/job/fun/get/get_list_table_by_status_id";
export default async function Page() {
const listReject = await AdminJob_getListTableByStatusId("4");
const listReject = await adminJob_getListReject({ page: 1 });
return (
<>
<AdminJob_TableReject dataVote={listReject} />
<AdminJob_TableReject dataReject={listReject} />
</>
);
}

View File

@@ -1,11 +1,13 @@
import { AdminJob_TableReview } from "@/app_modules/admin/job";
import adminJob_getListReview from "@/app_modules/admin/job/fun/get/get_list_review";
import { AdminJob_getListTableByStatusId } from "@/app_modules/admin/job/fun/get/get_list_table_by_status_id";
export default async function Page() {
const listReview = await AdminJob_getListTableByStatusId("2");
const dataReview = await adminJob_getListReview({ page: 1 });
return (
<>
<AdminJob_TableReview dataVote={listReview} />
<AdminJob_TableReview dataReview={dataReview} />
</>
);
}

View File

@@ -0,0 +1,10 @@
import { AdminJob_DetailPoster } from "@/app_modules/admin/job";
export default async function Page({ params }: { params: { id: string } }) {
const imageId = params.id;
return (
<>
<AdminJob_DetailPoster imageId={imageId} />
</>
);
}

View File

@@ -1,4 +1,6 @@
import { AdminLayout } from "@/app_modules/admin/main_dashboard";
import adminNotifikasi_countNotifikasi from "@/app_modules/admin/notifikasi/fun/count/count_is_read";
import adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
import { user_getOneByUserId } from "@/app_modules/home/fun/get/get_one_user_by_id";
import React from "react";
@@ -8,13 +10,20 @@ export default async function Layout({
}: {
children: React.ReactNode;
}) {
const userId = await user_getOneUserId()
const dataUser = await user_getOneByUserId(userId)
const userRole = dataUser?.masterUserRoleId
const userId = await user_getOneUserId();
const dataUser = await user_getOneByUserId(userId);
const listNotif = await adminNotifikasi_getByUserId();
const countNotifikasi = await adminNotifikasi_countNotifikasi();
return (
<>
<AdminLayout userRole={userRole as any}>{children}</AdminLayout>
<AdminLayout
listNotif={listNotif as any}
dataUser={dataUser as any}
countNotifikasi={countNotifikasi}
>
{children}
</AdminLayout>
</>
);
}

View File

@@ -1,15 +1,20 @@
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
import { HomeLayout } from "@/app_modules/home";
import { user_getOneByUserId } from "@/app_modules/home/fun/get/get_one_user_by_id";
import notifikasi_countUserNotifikasi from "@/app_modules/notifikasi/fun/count/fun_count_by_id";
import { redirect } from "next/navigation";
export default async function Layout({ children }: { children: any }) {
const userId = await user_getOneUserId();
const dataUser = await user_getOneByUserId(userId);
const countNotifikasi = await notifikasi_countUserNotifikasi();
return (
<>
<HomeLayout dataUser={dataUser as any}>{children}</HomeLayout>
<HomeLayout dataUser={dataUser as any} countNotifikasi={countNotifikasi}>
{children}
</HomeLayout>
</>
);
}

View File

@@ -0,0 +1,13 @@
import { Notifikasi_MainView } from "@/app_modules/notifikasi";
import notifikasi_getByUserId from "@/app_modules/notifikasi/fun/get/get_notifiaksi_by_id";
export default async function Page() {
const listNotifikasi = await notifikasi_getByUserId()
return (
<>
<Notifikasi_MainView listNotifikasi={listNotifikasi as any} />
</>
);
}

View File

@@ -1,7 +1,8 @@
export const RouterAdminJob = {
main: "/dev/admin/job/main",
table_publish: "/dev/admin/job/child/table_publish",
table_review: "/dev/admin/job/child/table_review",
table_reject: "/dev/admin/job/child/table_reject",
publish: "/dev/admin/job/child/publish",
review: "/dev/admin/job/child/review",
reject: "/dev/admin/job/child/reject",
arsip: "/dev/admin/job/child/arsip",
detail_poster: "/dev/admin/job/detail/poster/",
};

View File

@@ -0,0 +1,3 @@
export const RouterNotifikasi = {
main: "/dev/notifikasi",
};

View File

@@ -5,6 +5,14 @@ import { atomWithStorage } from "jotai/utils";
* @type number
* @
*/
export const gs_admin_hotMenu = atomWithStorage("gs_admin_hotMenu", 1)
export const gs_admin_hotMenu = atomWithStorage("gs_admin_hotMenu", 1);
export const gs_admin_subMenu = atomWithStorage<number | null>("gs_admin_subMenu",null)
export const gs_admin_subMenu = atomWithStorage<number | null>(
"gs_admin_subMenu",
null
);
export const gs_layout_admin_isNavbarOpen = atomWithStorage(
"gs_layout_admin_isNavbarOpen",
false
);

View File

@@ -0,0 +1,224 @@
"use client";
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component_global/header_tamplate";
import { MODEL_JOB } from "@/app_modules/job/model/interface";
import {
Badge,
Button,
Center,
Group,
Pagination,
Paper,
ScrollArea,
Spoiler,
Stack,
Table,
Text,
TextInput,
Title
} from "@mantine/core";
import {
IconEyeCheck,
IconSearch
} from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import adminJob_getListPublish from "../../fun/get/get_list_publish";
import { IconPhotoCheck } from "@tabler/icons-react";
export default function AdminJob_TablePublish({
dataPublish,
}: {
dataPublish: any;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Job Vacancy" />
<TableStatus dataPublish={dataPublish} />
</Stack>
</>
);
}
function TableStatus({ dataPublish }: { dataPublish: any }) {
const router = useRouter();
const [data, setData] = useState<MODEL_JOB[]>(dataPublish.data);
const [nPage, setNPage] = useState(dataPublish.nPage);
const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState("");
async function onSearch(s: string) {
setSearch(s);
setActivePage(1);
const loadData = await adminJob_getListPublish({
page: 1,
search: s,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminJob_getListPublish({
search: isSearch,
page: p,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
const TableRows = data?.map((e, i) => (
<tr key={i}>
<td>
<Center w={150}>
<Text>{e?.Author?.username}</Text>
</Center>
</td>
<td>
<Center w={150}>
<Text>
{e?.isArsip ? (
<Badge variant="light">Arsip</Badge>
) : (
<Badge color="green">Publish</Badge>
)}
</Text>
</Center>
</td>
<td>
<Spoiler
w={300}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
{e.title}
</Spoiler>
</td>
<td>
<Center w={200}>
{e.imagesId ? (
<Button
color="green"
radius={"xl"}
leftIcon={<IconPhotoCheck />}
onClick={() => {
router.push(RouterAdminJob.detail_poster + e?.imagesId);
}}
>
Lihat
</Button>
) : (
<Center w={200}>
<Text fw={"bold"} fz={"xs"} fs={"italic"}>
Tidak ada poster
</Text>
</Center>
)}
</Center>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.content }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.deskripsi }} />
</Spoiler>
</td>
</tr>
));
return (
<>
<Stack spacing={"xs"} h={"100%"}>
{/* <pre>{JSON.stringify(listUser, null, 2)}</pre> */}
<Group
position="apart"
bg={"green.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4} c={"white"}>
Publish
</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Masukan judul"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group>
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"}>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={1500}
h={"100%"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Author</Center>
</th>
<th>
<Center>Status</Center>
</th>
<th>
<Text>Judul</Text>
</th>
<th>
<Center>Poster</Center>
</th>
<th>
<Text>Syarat Ketentuan</Text>
</th>
<th>
<Text>Deskripsi</Text>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={nPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
</Stack>
</>
);
}

View File

@@ -0,0 +1,338 @@
"use client";
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component_global/header_tamplate";
import ComponentGlobal_InputCountDown from "@/app_modules/component_global/input_countdown";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import { MODEL_JOB } from "@/app_modules/job/model/interface";
import {
Button,
Center,
Group,
Modal,
Pagination,
Paper,
ScrollArea,
Spoiler,
Stack,
Table,
Text,
TextInput,
Textarea,
Title,
} from "@mantine/core";
import { IconBan, IconPhotoCheck, IconSearch } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
import adminJob_getListReject from "../../fun/get/get_list_reject";
import { AdminJob_getListTableByStatusId } from "../../fun/get/get_list_table_by_status_id";
import mqtt_client from "@/util/mqtt_client";
import adminNotifikasi_funCreateToUser from "@/app_modules/admin/notifikasi/fun/create/fun_create_notif_user";
export default function AdminJob_TableReject({
dataReject,
}: {
dataReject: any;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Job Vacancy" />
<TableStatus listReject={dataReject} />
</Stack>
</>
);
}
function TableStatus({ listReject }: { listReject: any }) {
const router = useRouter();
const [data, setData] = useState<MODEL_JOB[]>(listReject.data);
const [nPage, setNPage] = useState(listReject.nPage);
const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState("");
const [reject, setReject] = useState(false);
const [jobId, setJobId] = useState("");
const [catatan, setCatatan] = useState("");
async function onSearch(s: string) {
setSearch(s);
const loadData = await adminJob_getListReject({
page: 1,
search: s,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
setActivePage(1);
}
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminJob_getListReject({
search: isSearch,
page: p,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
const rowTable = data?.map((e, i) => (
<tr key={i}>
<td>
<Center w={150}>
<Text>{e?.Author?.username}</Text>
</Center>
</td>
<td>
<Spoiler
w={200}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
{e.title}
</Spoiler>
</td>
<td>
<Center w={150}>
{e.imagesId ? (
<Button
color="green"
radius={"xl"}
leftIcon={<IconPhotoCheck />}
onClick={() => {
router.push(RouterAdminJob.detail_poster + e?.imagesId);
}}
>
Lihat
</Button>
) : (
<Center w={150}>
<Text fw={"bold"} fz={"xs"} fs={"italic"}>
Tidak ada poster
</Text>
</Center>
)}
</Center>
</td>
<td>
<Spoiler
w={400}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.content }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.deskripsi }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
{e.catatan}
</Spoiler>
</td>
<td>
<Button
color={"red"}
leftIcon={<IconBan />}
radius={"xl"}
onClick={() => {
setReject(true);
setJobId(e.id);
setCatatan(e.catatan);
}}
>
<Stack spacing={0}>
<Text fz={10}>Tambah</Text>
<Text fz={10}>Catatan</Text>
</Stack>
</Button>
</td>
</tr>
));
return (
<>
<Modal
opened={reject}
onClose={() => {
setReject(false);
}}
withCloseButton={false}
size={"sm"}
centered
>
<Stack>
<Stack spacing={5}>
<Textarea
minRows={2}
maxRows={5}
maxLength={300}
autosize
label={<Text fw={"bold"}>Alasan Penolakan</Text>}
placeholder="Masukkan alasan penolakan lowongan ini"
value={catatan}
onChange={(val) => setCatatan(val.currentTarget.value)}
/>
<ComponentGlobal_InputCountDown
lengthInput={catatan.length}
maxInput={300}
/>
</Stack>
<Group position="right">
<Button radius={"xl"} onClick={() => setReject(false)}>
Batal
</Button>
<Button
style={{
transition: "0.5s",
}}
disabled={catatan === "" ? true : false}
radius={"xl"}
onClick={() => {
onReject({
catatan: catatan,
jobId: jobId,
onSetData(val) {
setData(val.data);
setNPage(val.nPage);
},
});
setReject(false);
}}
>
Simpan
</Button>
</Group>
</Stack>
</Modal>
<Stack spacing={"xs"} h={"100%"}>
<Group
position="apart"
bg={"red.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4} c={"white"}>
Reject
</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Masukan judul"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group>
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"}>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={1500}
h={"100%"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Author</Center>
</th>
<th>
<Text>Judul</Text>
</th>
<th>
<Center>Poster</Center>
</th>
<th>
<Text>Syarat Ketentuan</Text>
</th>
<th>
<Text>Deskripsi</Text>
</th>
<th>
<Text>Report</Text>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{rowTable}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={nPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
</Stack>
</>
);
}
async function onReject({
jobId,
catatan,
onSetData,
}: {
jobId: string;
catatan: string;
onSetData: (val: any) => void;
}) {
const reject = await AdminJob_funEditCatatanById(jobId, catatan);
if (reject.status === 200) {
const loadData = await adminJob_getListReject({ page: 1 });
onSetData(loadData);
const dataNotif = {
appId: reject.data?.id as any,
status: reject.data?.MasterStatus?.name as any,
userId: reject.data?.authorId as any,
pesan: reject.data?.title as any,
kategoriApp: "JOB",
title: "Report tambahan",
};
const notif = await adminNotifikasi_funCreateToUser({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish(
"USER",
JSON.stringify({ userId: reject?.data?.authorId, count: 1 })
);
}
ComponentGlobal_NotifikasiBerhasil(reject.message);
} else {
ComponentGlobal_NotifikasiGagal(reject.message);
}
}

View File

@@ -0,0 +1,402 @@
"use client";
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component_global/header_tamplate";
import adminNotifikasi_funCreateToUser from "@/app_modules/admin/notifikasi/fun/create/fun_create_notif_user";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import { MODEL_JOB } from "@/app_modules/job/model/interface";
import mqtt_client from "@/util/mqtt_client";
import {
Button,
Center,
Group,
Modal,
Pagination,
Paper,
ScrollArea,
Spoiler,
Stack,
Table,
Text,
TextInput,
Textarea,
Title,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import {
IconBan,
IconEyeCheck,
IconEyeShare,
IconHandFinger,
IconSearch,
} from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
import { AdminJob_funEditStatusPublishById } from "../../fun/edit/fun_edit_status_publish_by_id";
import adminJob_getListReview from "../../fun/get/get_list_review";
import { IconPhotoCheck } from "@tabler/icons-react";
import ComponentGlobal_InputCountDown from "@/app_modules/component_global/input_countdown";
export default function AdminJob_TableReview({
dataReview,
}: {
dataReview: any;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Job Vacancy" />
<TableStatus listReview={dataReview} />
</Stack>
</>
);
}
function TableStatus({ listReview }: { listReview: any }) {
const router = useRouter();
const [data, setData] = useState<MODEL_JOB[]>(listReview.data);
const [nPage, setNPage] = useState(listReview.nPage);
const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState("");
const [reject, setReject] = useState(false);
const [jobId, setJobId] = useState("");
const [catatan, setCatatan] = useState("");
useShallowEffect(() => {
onLoadData({
onSuccessLoad(val) {
setData(val.data);
setNPage(val.nPage);
},
});
}, [setData, setNPage]);
async function onLoadData({
onSuccessLoad,
}: {
onSuccessLoad: (val: any) => any;
}) {
const loadData = await adminJob_getListReview({ page: 1 });
onSuccessLoad(loadData);
}
async function onSearch(s: string) {
setSearch(s);
setActivePage(1)
const loadData = await adminJob_getListReview({
page: 1,
search: s,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminJob_getListReview({
search: isSearch,
page: p,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
const rowTable = data?.map((e, i) => (
<tr key={i}>
<td>
<Center w={150}>
<Text>{e?.Author?.username}</Text>
</Center>
</td>
<td>
<Spoiler
w={200}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
{e.title}
</Spoiler>
</td>
<td>
<Center w={200}>
{e.imagesId ? (
<Button
color="green"
radius={"xl"}
leftIcon={<IconPhotoCheck />}
onClick={() => {
router.push(RouterAdminJob.detail_poster + e?.imagesId);
}}
>
Lihat
</Button>
) : (
<Center w={150}>
<Text fw={"bold"} fz={"xs"} fs={"italic"}>
Tidak ada poster
</Text>
</Center>
)}
</Center>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.content }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.deskripsi }} />
</Spoiler>
</td>
<td>
<Stack>
<Stack align="center">
<Button
color={"green"}
leftIcon={<IconEyeShare />}
radius={"xl"}
onClick={() =>
onPublish({
jobId: e?.id,
onLoadData(val: any) {
setData(val.data);
setNPage(val.nPage);
},
})
}
>
Publish
</Button>
<Button
color={"red"}
leftIcon={<IconBan />}
radius={"xl"}
onClick={() => {
setReject(true);
setJobId(e.id);
}}
>
Reject
</Button>
</Stack>
</Stack>
</td>
</tr>
));
return (
<>
<Modal
opened={reject}
onClose={() => {
setReject(false);
}}
withCloseButton={false}
size={"sm"}
centered
>
<Stack>
<Stack spacing={5}>
<Textarea
minRows={2}
maxRows={5}
maxLength={300}
autosize
label={<Text fw={"bold"}>Alasan Penolakan</Text>}
placeholder="Masukkan alasan penolakan lowongan ini"
onChange={(val) => setCatatan(val.currentTarget.value)}
/>
<ComponentGlobal_InputCountDown
maxInput={300}
lengthInput={catatan.length}
/>
</Stack>
<Group position="right">
<Button radius={"xl"} onClick={() => setReject(false)}>
Batal
</Button>
<Button
style={{ transition: "0.5s" }}
disabled={catatan === "" ? true : false}
radius={"xl"}
onClick={() => {
onReject({
jobId: jobId,
catatan: catatan,
onLoadData(val) {
setData(val.data);
setNPage(val.nPage);
},
});
setReject(false);
}}
>
Simpan
</Button>
</Group>
</Stack>
</Modal>
<Stack spacing={"xs"} h={"100%"}>
<Group
position="apart"
bg={"orange.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4} c={"white"}>
Review
</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Masukan judul"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group>
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"}>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={1500}
h={"100%"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Author</Center>
</th>
<th>
<Text>Judul</Text>
</th>
<th>
<Center>Poster</Center>
</th>
<th>
<Text>Syarat Ketentuan</Text>
</th>
<th>
<Text>Deskripsi</Text>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{rowTable}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={nPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
</Stack>
</>
);
}
async function onPublish({
jobId,
onLoadData,
}: {
jobId: string;
onLoadData: (val: any) => void;
}) {
const publish = await AdminJob_funEditStatusPublishById(jobId);
if (publish.status === 200) {
const loadData = await adminJob_getListReview({ page: 1 });
onLoadData(loadData);
const dataNotif = {
appId: publish.data?.id as any,
status: publish.data?.MasterStatus?.name as any,
userId: publish.data?.authorId as any,
pesan: publish.data?.title as any,
kategoriApp: "JOB",
title: "Job publish",
};
const notif = await adminNotifikasi_funCreateToUser({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish(
"USER",
JSON.stringify({ userId: publish?.data?.authorId, count: 1 })
);
}
ComponentGlobal_NotifikasiBerhasil(publish.message);
} else {
ComponentGlobal_NotifikasiGagal(publish.message);
}
}
async function onReject({
jobId,
catatan,
onLoadData,
}: {
jobId: string;
catatan: string;
onLoadData: (val: any) => void;
}) {
const reject = await AdminJob_funEditCatatanById(jobId, catatan);
if (reject.status === 200) {
const loadData = await adminJob_getListReview({ page: 1 });
onLoadData(loadData);
ComponentGlobal_NotifikasiBerhasil(reject.message);
const dataNotif = {
appId: reject.data?.id as any,
status: reject.data?.MasterStatus?.name as any,
userId: reject.data?.authorId as any,
pesan: reject.data?.title as any,
kategoriApp: "JOB",
title: "Job anda ditolak !",
};
const notif = await adminNotifikasi_funCreateToUser({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish(
"USER",
JSON.stringify({ userId: reject?.data?.authorId, count: 1 })
);
}
} else {
ComponentGlobal_NotifikasiGagal(reject.message);
}
}

View File

@@ -1,171 +0,0 @@
"use client";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component_global/header_tamplate";
import { MODEL_JOB } from "@/app_modules/job/model/interface";
import {
Avatar,
Badge,
Box,
Button,
Card,
Center,
Divider,
Grid,
Group,
Image,
Modal,
Paper,
ScrollArea,
Spoiler,
Stack,
Table,
Text,
Title,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconBan, IconEyeCheck, IconEyeShare } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
export default function AdminJob_TablePublish({
dataVote,
}: {
dataVote?: any;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Job Vacancy: Table Publish" />
<TableStatus listReview={dataVote} />
</Stack>
</>
);
}
function TableStatus({ listReview }: { listReview: MODEL_JOB[] }) {
const router = useRouter();
const [opened, { open, close }] = useDisclosure(false);
const [data, setData] = useState(listReview);
const [img, setImg] = useState("");
const TableRows = data?.map((e, i) => (
<tr key={i}>
<td>
<Spoiler
w={200}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
{e.title}
</Spoiler>
</td>
<td>
<Center w={150}>
{e.imagesId ? (
<Button
color="green"
radius={"xl"}
leftIcon={<IconEyeCheck />}
onClick={() => {
setImg(e.imagesId);
open();
}}
>
Lihat
</Button>
) : (
<Center w={150}>
<Text fw={"bold"} fz={"xs"} fs={"italic"}>
Tidak ada poster
</Text>
</Center>
)}
</Center>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.content }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.deskripsi }} />
</Spoiler>
</td>
</tr>
));
return (
<>
<Modal opened={opened} onClose={close} withCloseButton={false} centered>
<Center>
<Image
alt="Foto"
src={RouterJob.api_gambar + img}
mah={500}
maw={300}
/>
</Center>
</Modal>
<Box>
<Box bg={"green.1"} p={"xs"}>
<Title order={6} c={"green"}>
PUBLISH
</Title>
</Box>
<ScrollArea w={"100%"}>
<Table
withBorder
verticalSpacing={"md"}
horizontalSpacing={"xl"}
p={"md"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Judul</Center>
</th>
<th>
<Center>Poster</Center>
</th>
<th>
<Center>Syarat Ketentuan</Center>
</th>
<th>
<Center>Deskripsi</Center>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</ScrollArea>
<Center>
{_.isEmpty(TableRows) ? (
<Center h={"50vh"}>
<Title order={6}>Tidak Ada Data</Title>
</Center>
) : (
""
)}
</Center>
</Box>
{/* <pre>{JSON.stringify(data, null, 2)}</pre> */}
</>
);
}

View File

@@ -1,251 +0,0 @@
"use client";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component_global/header_tamplate";
import { MODEL_JOB } from "@/app_modules/job/model/interface";
import {
Avatar,
Badge,
Box,
Button,
Card,
Center,
Divider,
Grid,
Group,
Image,
Modal,
Paper,
ScrollArea,
Spoiler,
Stack,
Table,
Text,
Textarea,
Title,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconBan, IconEyeCheck, IconEyeShare } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
import { AdminJob_getListTableByStatusId } from "../../fun/get/get_list_table_by_status_id";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
export default function AdminJob_TableReject({ dataVote }: { dataVote?: any }) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Job Vacancy: Table Reject" />
<TableStatus listReject={dataVote} />
</Stack>
</>
);
}
function TableStatus({ listReject }: { listReject: MODEL_JOB[] }) {
const [opened, { open, close }] = useDisclosure(false);
const [data, setData] = useState(listReject);
const [reject, setReject] = useState(false);
const [img, setImg] = useState("");
const [jobId, setJobId] = useState("");
const [catatan, setCatatan] = useState("");
const TableRows = data?.map((e, i) => (
<tr key={i}>
<td>
<Spoiler
w={200}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
{e.title}
</Spoiler>
</td>
<td>
<Center w={150}>
{e.imagesId ? (
<Button
color="green"
radius={"xl"}
leftIcon={<IconEyeCheck />}
onClick={() => {
setImg(e.imagesId);
open();
}}
>
Lihat
</Button>
) : (
<Center w={150}>
<Text fw={"bold"} fz={"xs"} fs={"italic"}>
Tidak ada poster
</Text>
</Center>
)}
</Center>
</td>
<td>
<Spoiler
w={400}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.content }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.deskripsi }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
{e.catatan}
</Spoiler>
</td>
<td>
<Button
color={"red"}
leftIcon={<IconBan />}
radius={"xl"}
onClick={() => {
setReject(true);
setJobId(e.id);
setCatatan(e.catatan);
}}
>
Reject
</Button>
</td>
</tr>
));
return (
<>
<Modal opened={opened} onClose={close} withCloseButton={false} centered>
<Center>
<Image
alt="Foto"
src={RouterJob.api_gambar + img}
mah={500}
maw={300}
/>
</Center>
</Modal>
<Modal
opened={reject}
onClose={() => {
setReject(false);
}}
withCloseButton={false}
size={"lg"}
centered
>
<Stack>
<Textarea
minRows={2}
maxRows={5}
maxLength={300}
autosize
label="Alasan Penolakan"
placeholder="Masukkan alasan penolakan lowongan ini"
value={catatan}
onChange={(val) => setCatatan(val.currentTarget.value)}
/>
<Group position="right">
<Button
radius={"xl"}
onClick={() => {
onReject(jobId, catatan, setData);
setReject(false);
}}
>
Simpan
</Button>
</Group>
</Stack>
</Modal>
<Box>
<Box bg={"red.1"} p={"xs"}>
<Title order={6} c={"red"}>
REJECT
</Title>
</Box>
<ScrollArea w={"100%"}>
<Table
withBorder
verticalSpacing={"md"}
horizontalSpacing={"xl"}
p={"md"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Judul</Center>
</th>
<th>
<Center>Poster</Center>
</th>
<th>
<Center>Syarat Ketentuan</Center>
</th>
<th>
<Center>Deskripsi</Center>
</th>
<th>
<Center>Catatan</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</ScrollArea>
<Center>
{_.isEmpty(TableRows) ? (
<Center h={"50vh"}>
<Title order={6}>Tidak Ada Data</Title>
</Center>
) : (
""
)}
</Center>
</Box>
{/* <pre>{JSON.stringify(data, null, 2)}</pre> */}
</>
);
}
async function onReject(jobId: string, catatan: string, setData: any) {
await AdminJob_funEditCatatanById(jobId, catatan).then(async (res) => {
if (res.status === 200) {
await AdminJob_getListTableByStatusId("4").then((val) => {
setData(val);
ComponentGlobal_NotifikasiBerhasil(res.message);
});
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}

View File

@@ -1,263 +0,0 @@
"use client";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component_global/header_tamplate";
import { MODEL_JOB } from "@/app_modules/job/model/interface";
import {
Avatar,
Badge,
Box,
Button,
Card,
Center,
Divider,
Grid,
Group,
Image,
Modal,
Paper,
ScrollArea,
Spoiler,
Stack,
Table,
Text,
Textarea,
Title,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconBan, IconEyeCheck, IconEyeShare } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { AdminJob_funEditStatusPublishById } from "../../fun/edit/fun_edit_status_publish_by_id";
import { AdminJob_getListTableByStatusId } from "../../fun/get/get_list_table_by_status_id";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
export default function AdminJob_TableReview({ dataVote }: { dataVote?: any }) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Job Vacancy: Table Review" />
<TableStatus listReview={dataVote} />
</Stack>
</>
);
}
function TableStatus({ listReview }: { listReview: MODEL_JOB[] }) {
const router = useRouter();
const [opened, { open, close }] = useDisclosure(false);
const [data, setData] = useState(listReview);
const [reject, setReject] = useState(false);
const [img, setImg] = useState("");
const [jobId, setJobId] = useState("");
const [catatan, setCatatan] = useState("");
const TableRows = data?.map((e, i) => (
<tr key={i}>
<td>
<Spoiler
w={200}
maxHeight={50}
hideLabel="sembunyikan"
showLabel="tampilkan"
>
{e.title}
</Spoiler>
</td>
<td>
<Center w={150}>
{e.imagesId ? (
<Button
color="green"
radius={"xl"}
leftIcon={<IconEyeCheck />}
onClick={() => {
setImg(e.imagesId);
open();
}}
>
Lihat
</Button>
) : (
<Center w={150}>
<Text fw={"bold"} fz={"xs"} fs={"italic"}>
Tidak ada poster
</Text>
</Center>
)}
</Center>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.content }} />
</Spoiler>
</td>
<td>
<Spoiler
hideLabel="sembunyikan"
w={400}
maxHeight={50}
showLabel="tampilkan"
>
<div dangerouslySetInnerHTML={{ __html: e.deskripsi }} />
</Spoiler>
</td>
<td>
<Stack>
<Stack align="center">
<Button
color={"green"}
leftIcon={<IconEyeShare />}
radius={"xl"}
onClick={() => onPublish(e.id, setData)}
>
Publish
</Button>
<Button
color={"red"}
leftIcon={<IconBan />}
radius={"xl"}
onClick={() => {
setReject(true);
setJobId(e.id);
}}
>
Reject
</Button>
</Stack>
</Stack>
</td>
</tr>
));
return (
<>
<Modal opened={opened} onClose={close} withCloseButton={false} centered>
<Center>
<Image
alt="Foto"
src={RouterJob.api_gambar + img}
mah={500}
maw={300}
/>
</Center>
</Modal>
<Modal
opened={reject}
onClose={() => {
setReject(false);
}}
withCloseButton={false}
size={"lg"}
centered
>
<Stack>
<Textarea
minRows={2}
maxRows={5}
maxLength={300}
autosize
label="Alasan Penolakan"
placeholder="Masukkan alasan penolakan lowongan ini"
onChange={(val) => setCatatan(val.currentTarget.value)}
/>
<Group position="right">
<Button
radius={"xl"}
onClick={() => {
onReject(jobId, catatan, setData);
setReject(false);
}}
>
Simpan
</Button>
</Group>
</Stack>
</Modal>
<Box>
<Box bg={"orange.1"} p={"xs"}>
<Title order={6} c={"orange"}>
REVIEW
</Title>
</Box>
<ScrollArea w={"100%"}>
<Table
withBorder
verticalSpacing={"md"}
horizontalSpacing={"xl"}
p={"md"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Judul</Center>
</th>
<th>
<Center>Poster</Center>
</th>
<th>
<Center>Syarat Ketentuan</Center>
</th>
<th>
<Center>Deskripsi</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</ScrollArea>
<Center>
{_.isEmpty(TableRows) ? (
<Center h={"50vh"}>
<Title order={6}>Tidak Ada Data</Title>
</Center>
) : (
""
)}
</Center>
</Box>
{/* <pre>{JSON.stringify(data, null, 2)}</pre> */}
</>
);
}
async function onPublish(jobId: string, setData: any) {
await AdminJob_funEditStatusPublishById(jobId).then(async (res) => {
if (res.status === 200) {
await AdminJob_getListTableByStatusId("2").then((res) => {
setData(res);
ComponentGlobal_NotifikasiBerhasil("Berhasil Update");
});
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}
async function onReject(jobId: string, catatan: string, setData: any) {
await AdminJob_funEditCatatanById(jobId, catatan).then(async (res) => {
if (res.status === 200) {
await AdminJob_getListTableByStatusId("2").then((val) => {
setData(val);
ComponentGlobal_NotifikasiBerhasil(res.message);
});
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}

View File

@@ -0,0 +1,27 @@
"use client";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import { Center, Image, Stack } from "@mantine/core";
import ComponentGlobalAdmin_BackButton from "../../component_global/back_button";
export default function AdminJob_DetailPoster({
imageId,
}: {
imageId: string;
}) {
return (
<>
<Stack>
<ComponentGlobalAdmin_BackButton />
<Center>
<Image
alt="Foto"
src={RouterJob.api_gambar + imageId}
mah={500}
maw={300}
/>
</Center>
</Stack>
</>
);
}

View File

@@ -7,7 +7,7 @@ export async function AdminJob_funEditCatatanById(
jobId: string,
catatan: string
) {
const up = await prisma.job.update({
const udpt = await prisma.job.update({
where: {
id: jobId,
},
@@ -15,9 +15,21 @@ export async function AdminJob_funEditCatatanById(
masterStatusId: "4",
catatan: catatan,
},
select: {
id: true,
authorId: true,
MasterStatus: {
select: {
name: true,
},
},
title: true,
},
});
if (!up) return { status: 400, message: "Gagal reject" };
if (!udpt) return { status: 400, message: "Gagal menambah catatan" };
revalidatePath("/dev/admin/job/child/table_review");
return { status: 200, message: "Berhasil reject" };
return {data: udpt, status: 200, message: "Berhasil menambah catatan" };
}

View File

@@ -11,10 +11,20 @@ export async function AdminJob_funEditStatusPublishById(jobId: string) {
data: {
masterStatusId: "1",
},
select: {
id: true,
authorId: true,
MasterStatus: {
select: {
name: true,
},
},
title: true,
},
});
if(!updt) return {status: 400, message: "Update Gagal"}
revalidatePath("/dev/admin/job/child/table_review");
return {status: 200, message: "Berhasil Update"}
return {data: updt, status: 200, message: "Berhasil Update"}
}

View File

@@ -0,0 +1,63 @@
"use server";
import prisma from "@/app/lib/prisma";
import { ceil } from "lodash";
export default async function adminJob_getListPublish({
page,
search,
}: {
page: number;
search?: string;
}) {
let takeData = 5;
let skipData = page * takeData - takeData;
const getData = await prisma.job.findMany({
skip: skipData,
take: takeData,
orderBy: {
updatedAt: "desc",
},
where: {
masterStatusId: "1",
isActive: true,
title: {
contains: search,
mode: "insensitive",
},
},
select: {
id: true,
title: true,
isActive: true,
isArsip: true,
createdAt: true,
updatedAt: true,
content: true,
deskripsi: true,
catatan: true,
authorId: true,
Author: true,
imagesId: true,
},
});
const nCount = await prisma.job.count({
where: {
masterStatusId: "1",
isActive: true,
title: {
contains: search,
mode: "insensitive",
},
},
});
const allData = {
data: getData,
nPage: ceil(nCount / takeData),
};
return allData;
}

View File

@@ -0,0 +1,62 @@
"use server";
import prisma from "@/app/lib/prisma";
import { ceil } from "lodash";
export default async function adminJob_getListReject({
page,
search,
}: {
page: number;
search?: string;
}) {
let takeData = 5;
let skipData = page * takeData - takeData;
const getData = await prisma.job.findMany({
skip: skipData,
take: takeData,
orderBy: {
updatedAt: "desc",
},
where: {
masterStatusId: "4",
isActive: true,
title: {
contains: search,
mode: "insensitive",
},
},
select: {
id: true,
title: true,
isActive: true,
createdAt: true,
updatedAt: true,
content: true,
deskripsi: true,
catatan: true,
authorId: true,
Author: true,
imagesId: true,
},
});
const nCount = await prisma.job.count({
where: {
masterStatusId: "4",
isActive: true,
title: {
contains: search,
mode: "insensitive",
},
},
});
const allData = {
data: getData,
nPage: ceil(nCount / takeData),
};
return allData;
}

View File

@@ -0,0 +1,62 @@
"use server";
import prisma from "@/app/lib/prisma";
import { ceil } from "lodash";
export default async function adminJob_getListReview({
page,
search,
}: {
page: number;
search?: string;
}) {
let takeData = 5;
let skipData = page * takeData - takeData;
const getData = await prisma.job.findMany({
skip: skipData,
take: takeData,
orderBy: {
updatedAt: "desc",
},
where: {
masterStatusId: "2",
isActive: true,
title: {
contains: search,
mode: "insensitive",
},
},
select: {
id: true,
title: true,
isActive: true,
createdAt: true,
updatedAt: true,
content: true,
deskripsi: true,
catatan: true,
authorId: true,
Author: true,
imagesId: true,
},
});
const nCount = await prisma.job.count({
where: {
masterStatusId: "2",
isActive: true,
title: {
contains: search,
mode: "insensitive",
},
},
});
const allData = {
data: getData,
nPage: ceil(nCount / takeData),
};
return allData;
}

View File

@@ -1,6 +1,13 @@
import AdminJob_Main from "./main";
import AdminJob_TablePublish from "./child/table_publish";
import AdminJob_TableReview from "./child/table_review";
import AdminJob_TableReject from "./child/table_reject";
import AdminJob_TablePublish from "./child/publish";
import AdminJob_TableReview from "./child/review";
import AdminJob_TableReject from "./child/reject";
import AdminJob_DetailPoster from "./detail/detail_poster";
export { AdminJob_Main, AdminJob_TablePublish, AdminJob_TableReview, AdminJob_TableReject };
export {
AdminJob_Main,
AdminJob_TablePublish,
AdminJob_TableReview,
AdminJob_TableReject,
AdminJob_DetailPoster,
};

View File

@@ -23,24 +23,28 @@ export default function AdminJob_Main({
name: "Publish",
jumlah: countPublish,
color: "green",
text_color: "white",
},
{
id: 2,
name: "Review",
jumlah: countReview,
color: "orange",
text_color: "white",
},
{
id: 3,
name: "Reject",
jumlah: countReject,
color: "red",
text_color: "white",
},
{
id: 4,
name: "Arsip",
jumlah: countArsip,
color: "gray",
text_color: "white",
},
];
return (

View File

@@ -1,71 +1,83 @@
"use client";
import mqtt_client from "@/util/mqtt_client";
import {
ActionIcon,
AppShell,
Badge,
Box,
Burger,
Card,
Center,
Divider,
Drawer,
Group,
Header,
Indicator,
MediaQuery,
NavLink,
Navbar,
Paper,
ScrollArea,
Stack,
Text,
Title,
useMantineTheme
useMantineTheme,
} from "@mantine/core";
import {
IconBell,
IconCheck,
IconChecks,
IconCircleDot,
IconCircleDotFilled,
IconDashboard
IconUserSquareRounded,
} from "@tabler/icons-react";
import { useAtom } from "jotai";
import _ from "lodash";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { auth_Logout } from "../auth/fun/fun_logout";
import { gs_kodeId } from "../auth/state/state";
import { ComponentGlobal_NotifikasiBerhasil } from "../component_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiPeringatan } from "../component_global/notif_global/notifikasi_peringatan";
import React, { useEffect, useState } from "react";
import { MODEL_USER } from "../home/model/interface";
import { MODEL_NOTIFIKASI } from "../notifikasi/model/interface";
import Admin_Logout from "./component_global/logout";
import { gs_admin_hotMenu, gs_admin_subMenu } from "./global_state";
import {
gs_admin_hotMenu,
gs_admin_subMenu,
gs_layout_admin_isNavbarOpen,
} from "./global_state";
import { listAdminPage } from "./list_page";
import adminNotifikasi_countNotifikasi from "./notifikasi/fun/count/count_is_read";
import adminNotifikasi_getByUserId from "./notifikasi/fun/get/get_notifikasi_by_user_id";
import adminNotifikasi_funUpdateIsReadById from "./notifikasi/fun/update/fun_update_is_read_by_id";
export default function AdminLayout({
userRole,
children,
listNotif,
dataUser,
countNotifikasi,
}: {
userRole: string;
children: React.ReactNode;
listNotif: MODEL_NOTIFIKASI[];
dataUser: MODEL_USER;
countNotifikasi: number;
}) {
const theme = useMantineTheme();
const [opened, setOpened] = useState(false);
const router = useRouter();
const [active, setActive] = useAtom(gs_admin_hotMenu);
const [activeId, setActiveId] = useAtom(gs_admin_hotMenu);
const [activeChild, setActiveChild] = useAtom(gs_admin_subMenu);
const [loading, setLoading] = useState(false);
const [kodeId, setKodeId] = useAtom(gs_kodeId);
async function onClickLogout() {
// await auth_Logout(kodeId).then((res) => {
// ComponentGlobal_NotifikasiBerhasil("Berhasil Logout");
// });
await auth_Logout(kodeId).then((res) => {
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message);
setKodeId("");
} else {
ComponentGlobal_NotifikasiPeringatan(res.message);
}
});
}
const [user, setUser] = useState(dataUser);
const userRoleId = user.masterUserRoleId;
const navbarItems = listAdminPage.map((e, i) => (
const [isNotif, setIsNotif] = useState(false);
const [dataNotif, setDataNotif] = useState(listNotif);
const [countNotif, setCountNotif] = useState(countNotifikasi);
const [isNavbarOpen, setIsNavbarOpen] = useAtom(gs_layout_admin_isNavbarOpen);
const developerNavbar = listAdminPage.map((e, i) => (
<Box key={e.id}>
<NavLink
sx={{
@@ -73,7 +85,7 @@ export default function AdminLayout({
backgroundColor: "transparent",
},
}}
fw={active === e.id ? "bold" : "normal"}
fw={activeId === e.id ? "bold" : "normal"}
icon={
// active === e.id ? loading ? <Loader size={10} /> : e.icon : e.icon
e.icon
@@ -81,7 +93,7 @@ export default function AdminLayout({
label={<Text size={"sm"}>{e.name}</Text>}
onClick={() => {
setLoading(true);
setActive(e.id);
setActiveId(e.id);
setActiveChild(null);
e.path === "" ? router.push(e.child[0].path) : router.push(e.path);
e.path === "" ? setActiveChild(e.child[0].id) : "";
@@ -109,7 +121,7 @@ export default function AdminLayout({
)
}
onClick={() => {
setActive(e.id);
setActiveId(e.id);
setActiveChild(v.id);
router.push(v.path);
}}
@@ -123,26 +135,26 @@ export default function AdminLayout({
));
const bukanDeveloper = listAdminPage.slice(0, -1);
const notAdminDev = bukanDeveloper.map((e) => (
const adminNavbar = bukanDeveloper.map((e) => (
<Box key={e.id}>
<NavLink
opened={e?.id === activeId && isNavbarOpen ? true : false}
sx={{
":hover": {
backgroundColor: "transparent",
},
}}
fw={active === e.id ? "bold" : "normal"}
icon={
// active === e.id ? loading ? <Loader size={10} /> : e.icon : e.icon
e.icon
}
fw={activeId === e.id ? "bold" : "normal"}
icon={e.icon}
label={<Text size={"sm"}>{e.name}</Text>}
onClick={() => {
setLoading(true);
setActive(e.id);
setActiveId(e.id);
setActiveChild(null);
e.path === "" ? router.push(e.child[0].path) : router.push(e.path);
e.path === "" ? setActiveChild(e.child[0].id) : "";
setIsNavbarOpen(true);
}}
>
{_.isEmpty(e.child) ? (
@@ -167,7 +179,7 @@ export default function AdminLayout({
)
}
onClick={() => {
setActive(e.id);
setActiveId(e.id);
setActiveChild(v.id);
router.push(v.path);
}}
@@ -180,20 +192,20 @@ export default function AdminLayout({
</Box>
));
const navbarAdmin = (
<Box>
<NavLink
c="orange"
icon={<IconDashboard />}
label="Developer"
sx={{
":hover": {
backgroundColor: "transparent",
},
}}
/>
</Box>
);
async function onLoadNotifikasi() {
const loadNotif = await adminNotifikasi_getByUserId();
setDataNotif(loadNotif as any);
}
useEffect(() => {
mqtt_client.subscribe("ADMIN");
mqtt_client.on("message", (topic: any, message: any) => {
const data = JSON.parse(message.toString());
// console.log(data);
setCountNotif(countNotif + data.count);
});
}, [countNotif]);
return (
<>
@@ -201,59 +213,34 @@ export default function AdminLayout({
padding="md"
navbarOffsetBreakpoint="md"
asideOffsetBreakpoint="sm"
navbar={
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
<Navbar
h={"95%"}
width={{ lg: 250, md: 200, sm: 200, base: 250 }}
hiddenBreakpoint="md"
hidden={!opened}
p="xs"
bg={"gray.2"}
>
{/* <Navbar.Section>
<Center h={50}>
<Title order={4} ff={"sans-serif"}>
Dashboard Admin
</Title>
</Center>
<Divider />
</Navbar.Section> */}
<Navbar.Section grow component={ScrollArea}>
<Stack>{userRole === "3" ? navbarItems : notAdminDev}</Stack>
</Navbar.Section>
<Navbar.Section>
<Stack>
<Divider />
<Group position="apart">
<Text fs={"italic"} c={"gray"} fz={"xs"}>
V 1.0.0
</Text>
<Admin_Logout />
</Group>
</Stack>
</Navbar.Section>
</Navbar>
</MediaQuery>
}
header={
<Header height={"5vh"} bg={"gray.2"}>
<Header height={"6vh"} bg={"gray.2"}>
{/* Web View */}
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
<Group position="apart" align="center" h={"100%"} px={"md"}>
<Text fw={"lighter"}>Dashboard Admin</Text>
<Title order={4}> HIPMI</Title>
{/* <Group>
{listAdminPage.map((e) => (
<Text key={e.id} onClick={() => router.push(e.route)}>
{e.name}
</Text>
))}
</Group> */}
{/* <Admin_Logout /> */}
<ActionIcon radius={"xl"}>
<IconBell />
</ActionIcon>
<Title order={3}>Dashboard Admin</Title>
<Group>
<ActionIcon
radius={"xl"}
onClick={() => {
setIsNotif(true);
onLoadNotifikasi();
}}
>
<Indicator
processing
label={<Text fz={10}>{countNotif}</Text>}
>
<IconBell />
</Indicator>
</ActionIcon>
<Divider orientation="vertical" color="dark" />
<Group>
<Text>{user?.username}</Text>
<IconUserSquareRounded />
</Group>
</Group>
</Group>
</MediaQuery>
@@ -276,10 +263,39 @@ export default function AdminLayout({
</MediaQuery>
</Header>
}
navbar={
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
<Navbar
h={"94vh"}
width={{ lg: 250, md: 200, sm: 200, base: 250 }}
hiddenBreakpoint="md"
hidden={!opened}
p="xs"
bg={"gray.2"}
>
<Navbar.Section grow component={ScrollArea}>
<Stack>
{userRoleId === "3" ? developerNavbar : adminNavbar}
</Stack>
</Navbar.Section>
<Navbar.Section>
<Stack>
<Divider />
<Group position="apart">
<Text fs={"italic"} c={"gray"} fz={"xs"}>
V 1.0.0
</Text>
<Admin_Logout />
</Group>
</Stack>
</Navbar.Section>
</Navbar>
</MediaQuery>
}
>
{/* {JSON.stringify(active)} */}
{children}
</AppShell>
{/* Drawer Mobile View */}
<Drawer opened={opened} onClose={() => setOpened(false)} size={"50%"}>
<Stack spacing={"xl"}>
{listAdminPage.map((e) => (
@@ -289,6 +305,210 @@ export default function AdminLayout({
))}
</Stack>
</Drawer>
{/* Drawer Notifikasi */}
<Drawer
title={
<Group position="apart">
<Text fw={"bold"} fz={"lg"}>
Notifikasi
</Text>
</Group>
}
opened={isNotif}
onClose={() => setIsNotif(false)}
position="right"
size={"xs"}
>
<DrawerNotifikasi
data={dataNotif}
onLoadReadNotif={(val: any) => {
setDataNotif(val);
}}
onChangeNavbar={(val: any) => {
setActiveId(val.id);
setActiveChild(val.childId);
}}
onToggleNavbar={setIsNavbarOpen}
onLoadCountNotif={(val: any) => {
setCountNotif(val);
}}
/>
</Drawer>
</>
);
}
function DrawerNotifikasi({
data,
onLoadReadNotif,
onChangeNavbar,
onToggleNavbar,
onLoadCountNotif,
}: {
data: MODEL_NOTIFIKASI[];
onLoadReadNotif: (val: any) => void;
onChangeNavbar: (val: any) => void;
onToggleNavbar: (val: any) => void;
onLoadCountNotif: (val: any) => void;
}) {
const router = useRouter();
if (_.isEmpty(data)) {
return (
<>
<Center>
<Text c={"gray"} fz={"xs"}>
Tidak ada notifikasi
</Text>
</Center>
</>
);
}
return (
<>
<Paper h={"100%"}>
<Stack>
{data.map((e, i) => (
<Card
style={{
transition: "0.5s",
}}
key={e?.id}
// withBorder
bg={e?.isRead ? "gray.1" : "gray.4"}
sx={{
borderColor: "gray",
borderStyle: "solid",
borderWidth: "0.5px",
":hover": {
backgroundColor: "#C1C2C5",
},
}}
onClick={async () => {
e?.kategoriApp === "JOB" &&
findRouterJob({
data: e,
router: router,
onChangeNavbar2: (val: any) => {
onChangeNavbar(val);
},
onToggleNavbar2: onToggleNavbar,
});
const updateIsRead = await adminNotifikasi_funUpdateIsReadById({
notifId: e?.id,
});
if (updateIsRead) {
const loadCountNotif =
await adminNotifikasi_countNotifikasi();
onLoadCountNotif(loadCountNotif);
const loadDataNotif = await adminNotifikasi_getByUserId();
onLoadReadNotif(loadDataNotif);
} else {
return null;
}
// callBackIsNotifikasi(false);
}}
>
<Card.Section p={"sm"}>
<Stack spacing={"xs"}>
<Group position="apart">
<Text fw={"bold"} fz={10}>
# {e?.kategoriApp}
</Text>
{e?.status ? (
<Badge fz={10} size="sm">
{e?.status}
</Badge>
) : (
""
)}
</Group>
<Divider color="gray.3" />
</Stack>
</Card.Section>
<Card.Section px={"sm"} pb={"sm"}>
<Stack spacing={0}>
<Text lineClamp={2} fw={"bold"} fz={"xs"}>
{e?.title}
</Text>
<Text lineClamp={2} fz={"xs"}>
{e?.pesan}
</Text>
</Stack>
</Card.Section>
<Card.Section p={"sm"}>
<Group position="apart">
<Text fz={10} color="gray">
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "long",
}).format(e?.createdAt)}
<Text span inherit fz={10} color="gray">
{", "}
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.createdAt)}
</Text>
</Text>
{e?.isRead ? (
<Group spacing={5}>
<IconChecks color="gray" size={10} />
<Text fz={10} color="gray">
Sudah dilihat
</Text>
</Group>
) : (
<Group spacing={5}>
<IconCheck color="gray" size={10} />
<Text fz={10} color="gray">
Belum dilihat
</Text>
</Group>
)}
</Group>
</Card.Section>
</Card>
))}
</Stack>
</Paper>
</>
);
}
async function findRouterJob({
data,
router,
onChangeNavbar2,
onToggleNavbar2,
}: {
data: MODEL_NOTIFIKASI;
router: AppRouterInstance;
onChangeNavbar2: (val: any) => void;
onToggleNavbar2: (val: any) => void;
}) {
const routeName = "/dev/admin/job/child/";
if (data.status === "Review") {
router.push(routeName + _.lowerCase(data.status));
onChangeNavbar2({
id: 6,
childId: 63,
});
}
if (data.status === "Draft") {
router.push(routeName + "review");
onChangeNavbar2({
id: 6,
childId: 63,
});
}
onToggleNavbar2(true);
}

View File

@@ -194,23 +194,23 @@ export const listAdminPage = [
{
id: 62,
name: "Table Publish",
path: RouterAdminJob.table_publish,
path: RouterAdminJob.publish,
},
{
id: 63,
name: "Table Review",
path: RouterAdminJob.table_review,
path: RouterAdminJob.review,
},
{
id: 64,
name: "Table Reject",
path: RouterAdminJob.table_reject,
},
{
id: 65,
name: "Arsip",
path: RouterAdminJob.arsip,
path: RouterAdminJob.reject,
},
// {
// id: 65,
// name: "Arsip",
// path: RouterAdminJob.arsip,
// },
],
},

View File

@@ -0,0 +1,18 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export default async function adminNotifikasi_countNotifikasi() {
const adminId = await user_getOneUserId();
const data = await prisma.notifikasi.findMany({
where: {
adminId: adminId,
isRead: false,
userRoleId: "2",
},
});
return data.length;
}

View File

@@ -0,0 +1,28 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
import { MODEL_NOTIFIKASI } from "@/app_modules/notifikasi/model/interface";
export default async function adminNotifikasi_funCreateToUser({
data,
}: {
data: MODEL_NOTIFIKASI;
}) {
const adminId = await user_getOneUserId();
const create = await prisma.notifikasi.create({
data: {
adminId: adminId,
userId: data.userId,
appId: data.appId,
status: data.status,
title: data.title,
pesan: data.pesan,
kategoriApp: data.kategoriApp,
userRoleId: "1",
},
});
return { status: 201, message: "Berhasil mengirim notifikasi" };
}

View File

@@ -0,0 +1,21 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
import { NextRequest } from "next/server";
export default async function adminNotifikasi_getByUserId() {
const adminId = await user_getOneUserId();
const data = await prisma.notifikasi.findMany({
orderBy: {
createdAt: "desc",
},
where: {
adminId: adminId,
userRoleId: "2",
},
});
return data;
}

View File

@@ -0,0 +1,21 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function adminNotifikasi_funUpdateIsReadById({
notifId,
}: {
notifId: string;
}) {
const updt = await prisma.notifikasi.update({
where: {
id: notifId,
},
data: {
isRead: true,
},
});
if (!updt) return { status: 400 };
return { status: 200 };
}

View File

@@ -0,0 +1,2 @@
// test notif

View File

@@ -0,0 +1,13 @@
"use client";
import { Center } from "@mantine/core";
export default function ComponentGlobal_IsEmptyData({ text }: { text: string }) {
return (
<>
<Center h={"50vh"} fz={"sm"} fw={"bold"} c={"gray"}>
{text}
</Center>
</>
);
}

View File

@@ -12,7 +12,6 @@ export async function user_getOneUserId() {
const c = cookies().get("ssn");
if (!c?.value || c.value === "") return redirect(RouterAuth.login);
const token = JSON.parse(
await unsealData(c?.value as string, {
password: config.server.password,

View File

@@ -10,6 +10,7 @@ import {
Grid,
Group,
Header,
Indicator,
Loader,
SimpleGrid,
Stack,
@@ -23,6 +24,7 @@ import {
IconAward,
IconQrcode,
IconUserCircle,
IconBell,
} from "@tabler/icons-react";
import { Logout } from "../auth";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
@@ -32,116 +34,47 @@ import { useRouter } from "next/navigation";
import { ComponentGlobal_NotifikasiPeringatan } from "../component_global/notif_global/notifikasi_peringatan";
import { ComponentGlobal_NotifikasiBerhasil } from "../component_global/notif_global/notifikasi_berhasil";
import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search";
import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi";
import { useShallowEffect } from "@mantine/hooks";
import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id";
import mqtt_client from "@/util/mqtt_client";
export default function HomeLayout({
dataUser,
children,
countNotifikasi,
}: {
dataUser: MODEL_USER;
children: React.ReactNode;
countNotifikasi: number;
}) {
const router = useRouter();
// const [user, setUser] = useState(dataUser);
const [loadingProfil, setLoadingProfile] = useState(false);
const [loadingUS, setLoadingUS] = useState(false);
const listFooter = [
{
id: 1,
name: "Temukan user",
icon: <IconUserSearch />,
link: ``,
},
{
id: 2,
name: "Profile",
icon: <IconUserCircle />,
link: RouterProfile.katalog,
},
];
const [countNotif, setCountNotif] = useState(countNotifikasi);
const Compo_Footer = (
<Footer height={70} w={"100%"} bg={"black"}>
<Grid p={"xs"}>
<Grid.Col span={"auto"}>
{loadingUS ? (
<Center>
<Loader />
</Center>
) : (
<Center>
<Stack
align="center"
spacing={0}
onClick={() => {
if (dataUser?.Profile === null) {
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
} else {
setLoadingUS(true);
// router.push(RouterProfile.katalog + `${user.Profile.id}`);
router.push(RouterUserSearch.main);
}
}}
>
<ActionIcon variant={"transparent"}>
<IconUserSearch color="white" />
</ActionIcon>
<Text fz={"xs"} c={"white"}>
Temukan pengguna
</Text>
</Stack>
</Center>
)}
</Grid.Col>
<Grid.Col span={"auto"}>
{loadingProfil ? (
<Center>
<Loader />
</Center>
) : (
<Center>
<Stack
align="center"
spacing={2}
onClick={() => {
setLoadingProfile(true);
if (dataUser?.Profile === null) {
router.push(RouterProfile.create + `${dataUser.id}`);
} else {
router.push(
RouterProfile.katalog + `${dataUser.Profile.id}`
);
}
}}
>
<ActionIcon variant={"transparent"}>
{dataUser?.Profile === null ? (
<IconUserCircle color="white" />
) : (
<Avatar
radius={"xl"}
size={25}
sx={{
borderStyle: "solid",
borderWidth: "0.5px",
borderColor: "white",
}}
src={
RouterProfile.api_foto_profile +
`${dataUser?.Profile.imagesId}`
}
/>
)}
</ActionIcon>
<Text fz={"xs"} c={"white"}>
Profile
</Text>
</Stack>
</Center>
)}
</Grid.Col>
</Grid>
</Footer>
);
useShallowEffect(() => {
mqtt_client.subscribe("USER");
mqtt_client.on("message", (topic: any, message: any) => {
const data = JSON.parse(message.toString());
if (data.userId === dataUser.id) {
setCountNotif(countNotif + data.count);
}
});
onLoadNotifikasi({
onLoad(val) {
setCountNotif(val);
},
});
}, [countNotif]);
async function onLoadNotifikasi({ onLoad }: { onLoad: (val: any) => void }) {
const loadNotif = await notifikasi_countUserNotifikasi();
onLoad(loadNotif);
}
return (
<>
@@ -157,11 +90,24 @@ export default function HomeLayout({
top={0}
h={50}
>
<Center h={"100%"}>
<Title order={4} c={"white"}>
HIPMI
</Title>
</Center>
<Group position="apart" h={"100%"} px={"md"}>
<ActionIcon variant="transparent" disabled></ActionIcon>
<Center>
<Title order={4} c={"white"}>
HIPMI
</Title>
</Center>
<ActionIcon
variant="transparent"
onClick={() => {
router.push(RouterNotifikasi.main);
}}
>
<Indicator processing label={<Text fz={10}>{countNotif}</Text>}>
<IconBell />
</Indicator>
</ActionIcon>
</Group>
</Box>
{/* Children */}

View File

@@ -14,11 +14,11 @@ export let defaultDeskripsi = `
<p>Atau kunjungi website kami:</p>
<p>
<a
href="https://test-hipmi.wibudev.com/"
href="https://www.google.co.id/?hl=id"
rel="noopener noreferrer"
target="_blank"
>
https://test-hipmi.wibudev.com/
https://www.google.co.id/?hl=id
</a>
</p>
`;

View File

@@ -1,13 +1,9 @@
"use client";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import {
AspectRatio,
Box,
Button,
Center,
FileButton,
Flex,
Group,
Image,
Loader,
@@ -15,18 +11,15 @@ import {
Stack,
Text,
TextInput,
Textarea,
} from "@mantine/core";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import { useAtom } from "jotai";
import _ from "lodash";
import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { useState } from "react";
import { gs_job_hot_menu, gs_job_status } from "../global_state";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
import "react-quill/dist/quill.snow.css";
import dynamic from "next/dynamic";
import "react-quill/dist/quill.snow.css";
const ReactQuill = dynamic(
() => {
return import("react-quill");
@@ -34,16 +27,20 @@ const ReactQuill = dynamic(
{ ssr: false }
);
import { useShallowEffect, useToggle } from "@mantine/hooks";
import { Job_funCreate } from "../fun/create/fun_create";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import { MODEL_JOB } from "../model/interface";
import toast from "react-simple-toasts";
import ComponentJob_NotedBox from "../component/detail/noted_box";
import ComponentGlobal_V2_LoadingPage from "@/app_modules/component_global/loading_page_v2";
import { defaultDeskripsi, defaultSyarat } from "../component/default_value";
import ComponentGlobal_InputCountDown from "@/app_modules/component_global/input_countdown";
import ComponentGlobal_V2_LoadingPage from "@/app_modules/component_global/loading_page_v2";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
import mqtt_client from "@/util/mqtt_client";
import { useShallowEffect } from "@mantine/hooks";
import { defaultDeskripsi, defaultSyarat } from "../component/default_value";
import ComponentJob_NotedBox from "../component/detail/noted_box";
import { MODEL_JOB } from "../model/interface";
import { Job_funCreate } from "../fun/create/fun_create";
import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import { MODEL_NOTIFIKASI } from "@/app_modules/notifikasi/model/interface";
export default function Job_Create() {
const [value, setValue] = useState({
@@ -225,25 +222,41 @@ function ButtonAction({ value, file }: { value: MODEL_JOB; file: FormData }) {
const [hotMenu, setHotMenu] = useAtom(gs_job_hot_menu);
const [status, setStatus] = useAtom(gs_job_status);
const [preview, setPreview] = useToggle();
async function onAction() {
async function onCreate() {
const gambar = new FormData();
gambar.append("file", file as any);
// console.log(value);
const create = await Job_funCreate(value as any, gambar);
if (create.status === 201) {
const dataNotif : any = {
appId: create.data?.id as any,
kategoriApp: "JOB",
status: create.data?.MasterStatus?.name as any,
userId: create.data?.authorId as any,
pesan: create.data?.title as any,
title: "Job baru",
};
const notif = await notifikasiToAdmin_funCreate({ data: dataNotif as any });
console.log(notif)
if (notif.status === 201) {
mqtt_client.publish(
"ADMIN",
JSON.stringify({
count: 1,
})
);
await Job_funCreate(value as any, gambar).then((res) => {
if (res.status === 201) {
setHotMenu(2);
setStatus("Review");
router.replace(RouterJob.status);
setIsLoading(true);
ComponentGlobal_NotifikasiBerhasil("Tambah Lowongan Berhasil");
} else {
ComponentGlobal_NotifikasiGagal(res.message);
ComponentGlobal_NotifikasiBerhasil(create.message);
}
});
} else {
ComponentGlobal_NotifikasiGagal(create.message);
}
}
return (
@@ -251,11 +264,6 @@ function ButtonAction({ value, file }: { value: MODEL_JOB; file: FormData }) {
<Stack>
<Group grow mt={"lg"} mb={70}>
<Button
style={{
transition: "0.5s",
}}
loaderPosition="center"
loading={isLoading ? true : false}
disabled={
value.title === "" ||
value.content === "" ||
@@ -267,10 +275,15 @@ function ButtonAction({ value, file }: { value: MODEL_JOB; file: FormData }) {
? true
: false
}
style={{
transition: "0.5s",
}}
loaderPosition="center"
loading={isLoading ? true : false}
w={"100%"}
radius={"xl"}
onClick={() => {
onAction();
onCreate();
}}
>
Simpan

View File

@@ -14,6 +14,8 @@ import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/
import { Job_funDeleteById } from "../../fun/delete/fun_delete_by_id";
import ComponentJob_NotedBox from "../../component/detail/noted_box";
import { MODEL_JOB } from "../../model/interface";
import mqtt_client from "@/util/mqtt_client";
import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif";
export default function Job_DetailDraft({ dataJob }: { dataJob: MODEL_JOB }) {
return (
@@ -37,15 +39,31 @@ function ButtonAction({ jobId }: { jobId: string }) {
const [opened, { open, close }] = useDisclosure();
async function onAction() {
await Job_funEditStatusByStatusId(jobId, "2").then((res) => {
if (res.status === 200) {
setStatus("Review");
ComponentGlobal_NotifikasiBerhasil("Berhasil Diajukan");
router.push(RouterJob.status);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
const update = await Job_funEditStatusByStatusId(jobId, "2");
if (update.status === 200) {
const dataNotif = {
appId: update.data?.id as any,
status: update.data?.MasterStatus?.name as any,
userId: update.data?.authorId as any,
pesan: update.data?.title as any,
kategoriApp: "JOB",
title: "Mengajukan review",
};
const notif = await notifikasiToAdmin_funCreate({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish("ADMIN", JSON.stringify({ count: 1 }));
}
});
setStatus("Review");
ComponentGlobal_NotifikasiBerhasil("Berhasil Diajukan");
router.push(RouterJob.status);
} else {
ComponentGlobal_NotifikasiGagal(update.message);
}
}
async function onDelete() {

View File

@@ -16,6 +16,7 @@ import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/
import { Job_funDeleteById } from "../../fun/delete/fun_delete_by_id";
export default function Job_DetailReject({ dataJob }: { dataJob: MODEL_JOB }) {
return (
<>
<Stack>

View File

@@ -10,6 +10,8 @@ import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_glob
import { MODEL_JOB } from "../../model/interface";
import { Job_funEditStatusByStatusId } from "../../fun/edit/fun_edit_status_by_status_id";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif";
import mqtt_client from "@/util/mqtt_client";
export default function Job_DetailReview({ dataJob }: { dataJob: MODEL_JOB }) {
return (
@@ -27,15 +29,31 @@ function ButtonAction({ jobId }: { jobId: string }) {
const [status, setStatus] = useAtom(gs_job_status);
async function onAction() {
await Job_funEditStatusByStatusId(jobId, "3").then((res) => {
if (res.status === 200) {
setStatus("Draft");
ComponentGlobal_NotifikasiBerhasil("Berhasil Dibatalkan");
router.push(RouterJob.status);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
const update = await Job_funEditStatusByStatusId(jobId, "3");
if (update.status === 200) {
const dataNotif = {
appId: update.data?.id as any,
kategoriApp: "JOB",
status: update.data?.MasterStatus?.name as any,
userId: update.data?.authorId as any,
pesan: update.data?.title as any,
title: "Membatalkan review",
};
const notif = await notifikasiToAdmin_funCreate({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish("ADMIN", JSON.stringify({ count: 1 }));
}
});
setStatus("Draft");
ComponentGlobal_NotifikasiBerhasil("Berhasil Dibatalkan");
router.push(RouterJob.status);
} else {
ComponentGlobal_NotifikasiGagal(update.message);
}
}
return (
<>

View File

@@ -31,7 +31,7 @@ export async function Job_funCreate(req: MODEL_JOB, file: FormData) {
if (!upload) return { status: 400, message: "Gagal upload gambar" };
const uploadFolder = Buffer.from(await dataImage.arrayBuffer());
fs.writeFileSync(`./public/job/${upload.url}`, uploadFolder);
const create = await prisma.job.create({
const createDataWithImg = await prisma.job.create({
data: {
title: req.title,
content: req.content,
@@ -39,27 +39,50 @@ export async function Job_funCreate(req: MODEL_JOB, file: FormData) {
authorId: authorId,
imagesId: upload.id,
},
select: {
id: true,
authorId: true,
MasterStatus: {
select: {
name: true,
},
},
title: true,
},
});
if (!create) return { status: 400, message: "Gagal Disimpan" };
if (!createDataWithImg) return { status: 400, message: "Gagal Disimpan" };
revalidatePath("/dev/job/main/status");
return {
data: createDataWithImg,
status: 201,
message: "Berhasil Disimpan",
};
} else {
const create = await prisma.job.create({
const createDataWithoutImg = await prisma.job.create({
data: {
title: req.title,
content: req.content,
deskripsi: req.deskripsi,
authorId: authorId,
},
select: {
id: true,
authorId: true,
MasterStatus: {
select: {
name: true,
},
},
title: true,
},
});
if (!create) return { status: 400, message: "Gagal Disimpan" };
if (!createDataWithoutImg)
return { status: 400, message: "Gagal Disimpan" };
revalidatePath("/dev/job/main/status");
return {
data: createDataWithoutImg,
status: 201,
message: "Berhasil Disimpan",
};

View File

@@ -14,9 +14,19 @@ export async function Job_funEditStatusByStatusId(
data: {
masterStatusId: statusId,
},
select: {
id: true,
authorId: true,
MasterStatus: {
select: {
name: true,
},
},
title: true,
},
});
if (!updt) return { status: 400, message: "Gagal ganti status" };
revalidatePath("/dev/job/main/status");
return { status: 200, message: "Berhasil ganti status" };
return { data: updt, status: 200, message: "Berhasil ganti status" };
}

View File

@@ -0,0 +1,20 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export default async function job_getListReject({}: {}) {
const userId = await user_getOneUserId();
const data = await prisma.job.findMany({
orderBy: {
updatedAt: "desc",
},
where: {
masterStatusId: "2",
authorId: userId,
isActive: true,
},
});
return data;
}

View File

@@ -1,6 +1,6 @@
"use client";
import { Card, Center, Image, Stack, Text } from "@mantine/core";
import { Card, Center, Image, Overlay, Stack, Text, Title } from "@mantine/core";
import ComponentJob_DetailData from "../component/detail/detail_data";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import { data } from "autoprefixer";
@@ -46,6 +46,18 @@ export default function Job_NonUserView({ data }: { data: MODEL_JOB }) {
</Stack>
</Stack>
</Card.Section>
{data?.isArsip === true && (
<Overlay color="gray" opacity={0.5} blur={1}>
<Stack align="center" h={"100%"} justify="center">
<Title c={"red"} fw={"bold"} order={3}>
Mohon Maaf !
</Title>
<Title c={"red"} fw={"bold"} order={3}>
Lowongan Kerja Ini Sudah Ditutup{" "}
</Title>
</Stack>
</Overlay>
)}
</Card>
</Center>
</>

View File

@@ -0,0 +1,18 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export default async function notifikasi_countUserNotifikasi() {
const userId = await user_getOneUserId();
const count = await prisma.notifikasi.findMany({
where: {
userId: userId,
isRead: false,
userRoleId: "1"
},
});
return count.length;
}

View File

@@ -0,0 +1,35 @@
"use server";
import prisma from "@/app/lib/prisma";
import { MODEL_NOTIFIKASI } from "../../model/interface";
export default async function notifikasiToAdmin_funCreate({
data,
}: {
data: MODEL_NOTIFIKASI;
}) {
const getAdmin = await prisma.user.findMany({
where: {
active: true,
masterUserRoleId: "2",
},
});
for (let a of getAdmin) {
const create = await prisma.notifikasi.create({
data: {
adminId: a.id,
userId: data.userId,
appId: data.appId,
status: data.status,
title: data.title,
pesan: data.pesan,
kategoriApp: data.kategoriApp,
userRoleId: "2",
},
});
if (!create) return { status: 400, message: "Gagal mengirim notifikasi" };
}
return { status: 201, message: "Berhasil mengirim notifikasi" };
}

View File

@@ -0,0 +1,20 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export default async function notifikasi_getByUserId() {
const userId = await user_getOneUserId();
const data = await prisma.notifikasi.findMany({
orderBy: {
createdAt: "desc",
},
where: {
userId: userId,
userRoleId: "1",
},
});
return data;
}

View File

@@ -0,0 +1,21 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function notifikasi_funUpdateIsReadById({
notifId,
}: {
notifId: string;
}) {
const updt = await prisma.notifikasi.update({
where: {
id: notifId,
},
data: {
isRead: true,
},
});
if (!updt) return { status: 400 };
return { status: 200 };
}

View File

@@ -0,0 +1,3 @@
import Notifikasi_MainView from "./main";
export { Notifikasi_MainView };

View File

@@ -0,0 +1,181 @@
"use client";
import AppComponentGlobal_LayoutTamplate from "@/app_modules/component_global/component_layout_tamplate";
import ComponentGlobal_HeaderTamplate from "@/app_modules/component_global/header_tamplate";
import {
Badge,
Card,
Divider,
Group,
Paper,
SimpleGrid,
Stack,
Text,
} from "@mantine/core";
import { MODEL_NOTIFIKASI } from "../model/interface";
import { useState } from "react";
import adminNotifikasi_countNotifikasi from "@/app_modules/admin/notifikasi/fun/count/count_is_read";
import adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id";
import adminNotifikasi_funUpdateIsReadById from "@/app_modules/admin/notifikasi/fun/update/fun_update_is_read_by_id";
import { IconChecks, IconCheck } from "@tabler/icons-react";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { useRouter } from "next/navigation";
import { RouterJob } from "@/app/lib/router_hipmi/router_job";
import notifikasi_funUpdateIsReadById from "../fun/update/fun_update_is_read_by_user_id";
import { useAtom } from "jotai";
import { gs_job_hot_menu, gs_job_status } from "@/app_modules/job/global_state";
import _ from "lodash";
import ComponentGlobal_IsEmptyData from "@/app_modules/component_global/is_empty_data";
export default function Notifikasi_MainView({
listNotifikasi,
}: {
listNotifikasi: any[];
}) {
return (
<>
<AppComponentGlobal_LayoutTamplate
header={<ComponentGlobal_HeaderTamplate title="Notifikasi" />}
>
<MainView listNotifikasi={listNotifikasi} />
</AppComponentGlobal_LayoutTamplate>
</>
);
}
function MainView({ listNotifikasi }: { listNotifikasi: MODEL_NOTIFIKASI[] }) {
const router = useRouter();
const [data, setData] = useState(listNotifikasi);
// JOB
const [jobMenuId, setJobMenuId] = useAtom(gs_job_hot_menu);
const [jobStatus, setJobStatus] = useAtom(gs_job_status);
if (_.isEmpty(data)) {
return <ComponentGlobal_IsEmptyData text="Tidak ada pemberitahuan" />;
}
return (
<>
<SimpleGrid
cols={1}
spacing="lg"
breakpoints={[
{ maxWidth: "md", cols: 2, spacing: "md" },
{ maxWidth: "sm", cols: 2, spacing: "sm" },
{ maxWidth: "xs", cols: 1, spacing: "sm" },
]}
>
{data.map((e, i) => (
<Card
key={e?.id}
// withBorder
bg={e?.isRead ? "gray.1" : "gray.4"}
sx={{
borderColor: "gray",
borderStyle: "solid",
borderWidth: "0.5px",
}}
onClick={async () => {
e?.kategoriApp === "JOB" &&
redirectJobPage({
data: e,
router: router,
onSetPage(val) {
setJobMenuId(val.menuId);
setJobStatus(val.status);
},
});
const cek = await notifikasi_funUpdateIsReadById({
notifId: e?.id,
});
if (cek.status === 200) return null;
}}
>
<Card.Section p={"sm"}>
<Stack spacing={"xs"}>
<Group position="apart">
<Text fw={"bold"} fz={10}>
# {e?.kategoriApp}
</Text>
{e?.status ? <Badge fz={10}>{e?.status}</Badge> : ""}
</Group>
<Divider color="gray.3" />
</Stack>
</Card.Section>
<Card.Section px={"sm"} pb={"sm"}>
<Stack spacing={0}>
<Text lineClamp={2} fw={"bold"} fz={"xs"}>
{e?.title}
</Text>
<Text lineClamp={2} fz={"xs"}>
{e?.pesan}
</Text>
</Stack>
</Card.Section>
<Card.Section p={"sm"}>
<Group position="apart">
<Text fz={10} color="gray">
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "long",
}).format(e?.createdAt)}
<Text span inherit fz={10} color="gray">
{", "}
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.createdAt)}
</Text>
</Text>
{e?.isRead ? (
<Group spacing={5}>
<IconChecks color="gray" size={10} />
<Text fz={10} color="gray">
Sudah dilihat
</Text>
</Group>
) : (
<Group spacing={5}>
<IconCheck color="gray" size={10} />
<Text fz={10} color="gray">
Belum dilihat
</Text>
</Group>
)}
</Group>
</Card.Section>
</Card>
))}
</SimpleGrid>
</>
);
}
function redirectJobPage({
data,
router,
onSetPage,
}: {
data: MODEL_NOTIFIKASI;
router: AppRouterInstance;
onSetPage: (val: any) => void;
}) {
const path = RouterJob.status;
if (data.status === "Publish") {
onSetPage({
menuId: 2,
status: data.status,
});
}
if (data.status === "Reject") {
onSetPage({
menuId: 2,
status: data.status,
});
}
router.push(path);
}

View File

@@ -0,0 +1,20 @@
import { MODEL_USER } from "@/app_modules/home/model/interface";
import { MODEL_NEW_DEFAULT_MASTER } from "@/app_modules/model_global/interface";
export interface MODEL_NOTIFIKASI {
id: string;
isActive: boolean;
createdAt: Date;
updatedAt: Date;
appId: string;
kategoriApp: string;
isRead: boolean;
title: string,
pesan: string;
User: MODEL_USER;
userId: string;
Admin: MODEL_USER;
adminId: string;
status?: string;
Role: MODEL_NEW_DEFAULT_MASTER;
userRoleId: String;
}

View File

@@ -7,6 +7,21 @@
{
"name": "firman",
"nomor": "6281339158911",
"masterUserRoleId": "2"
},
{
"name": "amalia",
"nomor": "628980185458",
"masterUserRoleId": "1"
},
{
"name": "lukman",
"nomor": "6287701790942",
"masterUserRoleId": "1"
},
{
"name": "fahmi",
"nomor": "628123833845",
"masterUserRoleId": "3"
}
]

View File

@@ -5,6 +5,6 @@ declare global {
}
const mqtt_client =
globalThis.mqtt_client || mqtt.connect("wss://io.wibudev.com");
globalThis.mqtt_client || mqtt.connect("ws://wibudev.com:3003");
export default mqtt_client;

View File

@@ -10,51 +10,17 @@ import { Button, Stack } from "@mantine/core";
export default function MqttLoader() {
useEffect(() => {
mqtt_client.on("connect", () => {
try {
console.log("connected");
} catch (error) {
console.log(error)
};
mqtt_client.subscribe("pesan");
mqtt_client.subscribe("pesan2");
// fetch("").then((res) => {
// mqtt_client.subscribe("pesan");
// });
});
mqtt_client.on("message", (topic: any, message: any) => {
// console.log(itu)
// evnPesan.emit("pesan", itu);
const data = JSON.parse(message.toString());
if (data) {
if (data.id === "1") {
console.log("ini untuk id satu", data.data);
}
}
console.log("connected");
});
}, []);
const onClick = async () => {
mqtt_client.publish("pesan2", "apa pesannya 2");
};
return null;
const onClick2 = () => {
mqtt_client.publish(
"pesan",
JSON.stringify({
id: "2",
title: "donasi",
data: "databta",
})
);
};
return null
// (
// <Stack>
// <Button onClick={onClick}>Tekan</Button>
// <Button onClick={onClick2}>Tekan 2</Button>
// </Stack>
// <>
// <Stack>
// <Button onClick={onClick}>Tekan</Button>
// <Button onClick={onClick2}>Tekan 2</Button>
// </Stack>
// </>
// );
}

View File

@@ -3718,6 +3718,14 @@ next-dev@^1.1.9:
readdirp "^3.6.0"
yargs "^17.7.2"
next-scroll-loader@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/next-scroll-loader/-/next-scroll-loader-1.0.5.tgz#e25aaed2c3e5c60bf6d2fa89a387b62483b2ffd0"
integrity sha512-j2/yQkjtCZttnpZcKMyLbIylBsGsutFD4Net0cdk3lYOWN7FmPRUlpK0JrZP+KGnq6pyuXh6OxCxY9HJ8BWGZQ==
dependencies:
react "^18.3.1"
react-dom "^18.3.1"
next@^13.5.4-canary.8:
version "13.5.6"
resolved "https://registry.yarnpkg.com/next/-/next-13.5.6.tgz#e964b5853272236c37ce0dd2c68302973cf010b1"