diff --git a/package.json b/package.json index a23894c8..59285404 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "desa-darmasaba", - "version": "0.1.2", + "version": "0.1.3", "private": true, "scripts": { "dev": "next dev --turbopack", diff --git a/prisma/migrations/20250624034125_24_jun2025/migration.sql b/prisma/migrations/20250624034125_24_jun2025/migration.sql new file mode 100644 index 00000000..f7dfc831 --- /dev/null +++ b/prisma/migrations/20250624034125_24_jun2025/migration.sql @@ -0,0 +1,139 @@ +/* + Warnings: + + - The primary key for the `DataKematian_Kelahiran` table will be changed. If it partially fails, the table could be left without primary key constraint. + +*/ +-- AlterTable +ALTER TABLE "DataKematian_Kelahiran" DROP CONSTRAINT "DataKematian_Kelahiran_pkey", +ALTER COLUMN "id" DROP DEFAULT, +ALTER COLUMN "id" SET DATA TYPE TEXT, +ADD CONSTRAINT "DataKematian_Kelahiran_pkey" PRIMARY KEY ("id"); +DROP SEQUENCE "DataKematian_Kelahiran_id_seq"; + +-- AlterTable +ALTER TABLE "ProfilePPID" ADD COLUMN "imageUrl" TEXT; + +-- CreateTable +CREATE TABLE "Puskesmas" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "alamat" TEXT NOT NULL, + "jamId" TEXT NOT NULL, + "imageId" TEXT NOT NULL, + "kontakId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "Puskesmas_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "JamOperasional" ( + "id" TEXT NOT NULL, + "workDays" TEXT NOT NULL, + "weekDays" TEXT NOT NULL, + "holiday" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "JamOperasional_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "KontakPuskesmas" ( + "id" TEXT NOT NULL, + "kontakPuskesmas" TEXT NOT NULL, + "email" TEXT NOT NULL, + "facebook" TEXT NOT NULL, + "kontakUGD" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "KontakPuskesmas_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProgramKesehatan" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "deskripsiSingkat" TEXT NOT NULL, + "deskripsi" TEXT NOT NULL, + "imageId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "ProgramKesehatan_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "PenangananDarurat" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "deskripsi" TEXT NOT NULL, + "imageId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "PenangananDarurat_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "KontakDarurat" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "deskripsi" TEXT NOT NULL, + "imageId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "KontakDarurat_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "InfoWabahPenyakit" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "deskripsiSingkat" TEXT NOT NULL, + "deskripsiLengkap" TEXT NOT NULL, + "imageId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "InfoWabahPenyakit_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "Puskesmas" ADD CONSTRAINT "Puskesmas_jamId_fkey" FOREIGN KEY ("jamId") REFERENCES "JamOperasional"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Puskesmas" ADD CONSTRAINT "Puskesmas_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Puskesmas" ADD CONSTRAINT "Puskesmas_kontakId_fkey" FOREIGN KEY ("kontakId") REFERENCES "KontakPuskesmas"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProgramKesehatan" ADD CONSTRAINT "ProgramKesehatan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PenangananDarurat" ADD CONSTRAINT "PenangananDarurat_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "KontakDarurat" ADD CONSTRAINT "KontakDarurat_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "InfoWabahPenyakit" ADD CONSTRAINT "InfoWabahPenyakit_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20250624061829_24jun2025_2/migration.sql b/prisma/migrations/20250624061829_24jun2025_2/migration.sql new file mode 100644 index 00000000..9fa565af --- /dev/null +++ b/prisma/migrations/20250624061829_24jun2025_2/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - The primary key for the `GrafikKepuasan` table will be changed. If it partially fails, the table could be left without primary key constraint. + +*/ +-- AlterTable +ALTER TABLE "GrafikKepuasan" DROP CONSTRAINT "GrafikKepuasan_pkey", +ALTER COLUMN "id" DROP DEFAULT, +ALTER COLUMN "id" SET DATA TYPE TEXT, +ADD CONSTRAINT "GrafikKepuasan_pkey" PRIMARY KEY ("id"); +DROP SEQUENCE "GrafikKepuasan_id_seq"; diff --git a/prisma/migrations/20250625035558_25jun2025_1/migration.sql b/prisma/migrations/20250625035558_25jun2025_1/migration.sql new file mode 100644 index 00000000..a97587d1 --- /dev/null +++ b/prisma/migrations/20250625035558_25jun2025_1/migration.sql @@ -0,0 +1,96 @@ +/* + Warnings: + + - You are about to drop the `_DokterdanTenagaMedisToFasilitasKesehatan` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `_FasilitasKesehatanToFasilitasPendukung` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `_FasilitasKesehatanToInformasiUmum` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `_FasilitasKesehatanToLayananUnggulan` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `_FasilitasKesehatanToProsedurPendaftaran` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `_FasilitasKesehatanToTarifDanLayanan` table. If the table is not empty, all the data it contains will be lost. + - Added the required column `dokterdanTenagaMedisId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty. + - Added the required column `fasilitasPendukungId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty. + - Added the required column `informasiUmumId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty. + - Added the required column `layananUnggulanId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty. + - Added the required column `prosedurPendaftaranId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty. + - Added the required column `tarifDanLayananId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "_DokterdanTenagaMedisToFasilitasKesehatan" DROP CONSTRAINT "_DokterdanTenagaMedisToFasilitasKesehatan_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_DokterdanTenagaMedisToFasilitasKesehatan" DROP CONSTRAINT "_DokterdanTenagaMedisToFasilitasKesehatan_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToFasilitasPendukung" DROP CONSTRAINT "_FasilitasKesehatanToFasilitasPendukung_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToFasilitasPendukung" DROP CONSTRAINT "_FasilitasKesehatanToFasilitasPendukung_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToInformasiUmum" DROP CONSTRAINT "_FasilitasKesehatanToInformasiUmum_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToInformasiUmum" DROP CONSTRAINT "_FasilitasKesehatanToInformasiUmum_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToLayananUnggulan" DROP CONSTRAINT "_FasilitasKesehatanToLayananUnggulan_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToLayananUnggulan" DROP CONSTRAINT "_FasilitasKesehatanToLayananUnggulan_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToProsedurPendaftaran" DROP CONSTRAINT "_FasilitasKesehatanToProsedurPendaftaran_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToProsedurPendaftaran" DROP CONSTRAINT "_FasilitasKesehatanToProsedurPendaftaran_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToTarifDanLayanan" DROP CONSTRAINT "_FasilitasKesehatanToTarifDanLayanan_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_FasilitasKesehatanToTarifDanLayanan" DROP CONSTRAINT "_FasilitasKesehatanToTarifDanLayanan_B_fkey"; + +-- AlterTable +ALTER TABLE "FasilitasKesehatan" ADD COLUMN "dokterdanTenagaMedisId" TEXT NOT NULL, +ADD COLUMN "fasilitasPendukungId" TEXT NOT NULL, +ADD COLUMN "informasiUmumId" TEXT NOT NULL, +ADD COLUMN "layananUnggulanId" TEXT NOT NULL, +ADD COLUMN "prosedurPendaftaranId" TEXT NOT NULL, +ADD COLUMN "tarifDanLayananId" TEXT NOT NULL; + +-- DropTable +DROP TABLE "_DokterdanTenagaMedisToFasilitasKesehatan"; + +-- DropTable +DROP TABLE "_FasilitasKesehatanToFasilitasPendukung"; + +-- DropTable +DROP TABLE "_FasilitasKesehatanToInformasiUmum"; + +-- DropTable +DROP TABLE "_FasilitasKesehatanToLayananUnggulan"; + +-- DropTable +DROP TABLE "_FasilitasKesehatanToProsedurPendaftaran"; + +-- DropTable +DROP TABLE "_FasilitasKesehatanToTarifDanLayanan"; + +-- AddForeignKey +ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_informasiUmumId_fkey" FOREIGN KEY ("informasiUmumId") REFERENCES "InformasiUmum"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_layananUnggulanId_fkey" FOREIGN KEY ("layananUnggulanId") REFERENCES "LayananUnggulan"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_dokterdanTenagaMedisId_fkey" FOREIGN KEY ("dokterdanTenagaMedisId") REFERENCES "DokterdanTenagaMedis"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_fasilitasPendukungId_fkey" FOREIGN KEY ("fasilitasPendukungId") REFERENCES "FasilitasPendukung"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_prosedurPendaftaranId_fkey" FOREIGN KEY ("prosedurPendaftaranId") REFERENCES "ProsedurPendaftaran"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_tarifDanLayananId_fkey" FOREIGN KEY ("tarifDanLayananId") REFERENCES "TarifDanLayanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20250625085706_25_jun_25_2/migration.sql b/prisma/migrations/20250625085706_25_jun_25_2/migration.sql new file mode 100644 index 00000000..28a29c1e --- /dev/null +++ b/prisma/migrations/20250625085706_25_jun_25_2/migration.sql @@ -0,0 +1,32 @@ +/* + Warnings: + + - The primary key for the `DataKematian_Kelahiran` table will be changed. If it partially fails, the table could be left without primary key constraint. + - The `id` column on the `DataKematian_Kelahiran` table would be dropped and recreated. This will lead to data loss if there is data in the column. + - The primary key for the `GrafikKepuasan` table will be changed. If it partially fails, the table could be left without primary key constraint. + - The `id` column on the `GrafikKepuasan` table would be dropped and recreated. This will lead to data loss if there is data in the column. + - A unique constraint covering the columns `[uuid]` on the table `DataKematian_Kelahiran` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[uuid]` on the table `GrafikKepuasan` will be added. If there are existing duplicate values, this will fail. + - The required column `uuid` was added to the `DataKematian_Kelahiran` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required. + - The required column `uuid` was added to the `GrafikKepuasan` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required. + +*/ +-- AlterTable +ALTER TABLE "DataKematian_Kelahiran" DROP CONSTRAINT "DataKematian_Kelahiran_pkey", +ADD COLUMN "uuid" TEXT NOT NULL, +DROP COLUMN "id", +ADD COLUMN "id" SERIAL NOT NULL, +ADD CONSTRAINT "DataKematian_Kelahiran_pkey" PRIMARY KEY ("id"); + +-- AlterTable +ALTER TABLE "GrafikKepuasan" DROP CONSTRAINT "GrafikKepuasan_pkey", +ADD COLUMN "uuid" TEXT NOT NULL, +DROP COLUMN "id", +ADD COLUMN "id" SERIAL NOT NULL, +ADD CONSTRAINT "GrafikKepuasan_pkey" PRIMARY KEY ("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "DataKematian_Kelahiran_uuid_key" ON "DataKematian_Kelahiran"("uuid"); + +-- CreateIndex +CREATE UNIQUE INDEX "GrafikKepuasan_uuid_key" ON "GrafikKepuasan"("uuid"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e7d3f683..716f13af 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -70,6 +70,12 @@ model FileStorage { ProfileDesaImage ProfileDesaImage[] ProfilePPID ProfilePPID[] ProfilPerbekel ProfilPerbekel[] + Puskesmas Puskesmas[] + ProgramKesehatan ProgramKesehatan[] + PenangananDarurat PenangananDarurat[] + KontakDarurat KontakDarurat[] + + InfoWabahPenyakit InfoWabahPenyakit[] } //========================================= MENU PPID ========================================= // @@ -471,12 +477,18 @@ model FasilitasKesehatan { updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) - InformasiUmum InformasiUmum[] - LayananUnggulan LayananUnggulan[] - DokterdanTenagaMedis DokterdanTenagaMedis[] - FasilitasPendukung FasilitasPendukung[] - ProsedurPendaftaran ProsedurPendaftaran[] - TarifDanLayanan TarifDanLayanan[] + informasiumum InformasiUmum @relation(fields: [informasiUmumId], references: [id]) + informasiUmumId String + layananunggulan LayananUnggulan @relation(fields: [layananUnggulanId], references: [id]) + layananUnggulanId String + dokterdantenagamedis DokterdanTenagaMedis @relation(fields: [dokterdanTenagaMedisId], references: [id]) + dokterdanTenagaMedisId String + fasilitaspendukung FasilitasPendukung @relation(fields: [fasilitasPendukungId], references: [id]) + fasilitasPendukungId String + prosedurpendaftaran ProsedurPendaftaran @relation(fields: [prosedurPendaftaranId], references: [id]) + prosedurPendaftaranId String + tarifdanlayanan TarifDanLayanan @relation(fields: [tarifDanLayananId], references: [id]) + tarifDanLayananId String } model InformasiUmum { @@ -484,10 +496,10 @@ model InformasiUmum { fasilitas String alamat String jamOperasional String - FasilitasKesehatan FasilitasKesehatan[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) + FasilitasKesehatan FasilitasKesehatan[] isActive Boolean @default(true) } @@ -618,7 +630,8 @@ model PendaftaranJadwalKegiatan { // ========================================= PERSENTASE KELAHIRAN & KEMATIAN ========================================= // model DataKematian_Kelahiran { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) + uuid String @default(cuid()) @unique tahun String kematianKasar String kematianBayi String @@ -632,6 +645,7 @@ model DataKematian_Kelahiran { // ========================================= GRAFIK KEPUASAN ========================================= // model GrafikKepuasan { id Int @id @default(autoincrement()) + uuid String @default(cuid()) @unique label String jumlah String createdAt DateTime @default(now()) @@ -723,3 +737,98 @@ model Posyandu { deletedAt DateTime @default(now()) isActive Boolean @default(true) } + +// ========================================= PUSKESMAS ========================================= // +model Puskesmas { + id String @id @default(cuid()) + name String + alamat String + jam JamOperasional @relation(fields: [jamId], references: [id]) + jamId String + image FileStorage @relation(fields: [imageId], references: [id]) + imageId String + kontak KontakPuskesmas @relation(fields: [kontakId], references: [id]) + kontakId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +model JamOperasional { + id String @id @default(cuid()) + workDays String + weekDays String + holiday String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + Puskesmas Puskesmas[] +} + +model KontakPuskesmas { + id String @id @default(cuid()) + kontakPuskesmas String + email String + facebook String + kontakUGD String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + Puskesmas Puskesmas[] +} + +// ========================================= PROGRAM KESSEHATAN ========================================= // +model ProgramKesehatan { + id String @id @default(cuid()) + name String + deskripsiSingkat String + deskripsi String + image FileStorage @relation(fields: [imageId], references: [id]) + imageId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +// ========================================= PENANGANAN DARURAT ========================================= // +model PenangananDarurat { + id String @id @default(cuid()) + name String + deskripsi String + image FileStorage @relation(fields: [imageId], references: [id]) + imageId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +// ========================================= KONTAK DARURAT ========================================= // +model KontakDarurat { + id String @id @default(cuid()) + name String + deskripsi String + image FileStorage @relation(fields: [imageId], references: [id]) + imageId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} +// ========================================= INFO WABAH PENYAKIT ========================================= // +model InfoWabahPenyakit { + id String @id @default(cuid()) + name String + deskripsiSingkat String + deskripsiLengkap String + image FileStorage @relation(fields: [imageId], references: [id]) + imageId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} diff --git a/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan.ts b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan.ts index 1a195d6d..41fed621 100644 --- a/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan.ts +++ b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan.ts @@ -1,333 +1,308 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import ApiFetch from "@/lib/api-fetch"; import { Prisma } from "@prisma/client"; import { toast } from "react-toastify"; import { proxy } from "valtio"; import { z } from "zod"; -/* Informasi Umum */ -const templateInformasiUmum = z.object({ - fasilitas: z.string().min(3, "Fasilitas minimal 3 karakter"), - alamat: z.string().min(3, "Alamat minimal 3 karakter"), - jamOperasional: z.string().min(3, "Jam Operasional minimal 3 karakter"), +// Validasi form +const templateForm = z.object({ + name: z.string().min(1, "Nama harus diisi"), + informasiUmum: z.object({ + fasilitas: z.string().min(1, "Fasilitas harus diisi"), + alamat: z.string().min(1, "Alamat harus diisi"), + jamOperasional: z.string().min(1, "Jam operasional harus diisi"), + }), + layananUnggulan: z.object({ + content: z.string().min(1, "Layanan unggulan harus diisi"), + }), + dokterdanTenagaMedis: z.object({ + name: z.string().min(1, "Nama dokter harus diisi"), + specialist: z.string().min(1, "Spesialis harus diisi"), + jadwal: z.string().min(1, "Jadwal harus diisi"), + }), + fasilitasPendukung: z.object({ + content: z.string().min(1, "Fasilitas pendukung harus diisi"), + }), + prosedurPendaftaran: z.object({ + content: z.string().min(1, "Prosedur pendaftaran harus diisi"), + }), + tarifDanLayanan: z.object({ + layanan: z.string().min(1, "Layanan harus diisi"), + tarif: z.string().min(1, "Tarif harus diisi"), + }), }); -type InfromasiUmum = Prisma.InformasiUmumGetPayload<{ - select: { - fasilitas: true; - alamat: true; - jamOperasional: true; - }; -}>; +// Default form kosong +const defaultForm = { + name: "", + informasiUmum: { + fasilitas: "", + alamat: "", + jamOperasional: "", + }, + layananUnggulan: { + content: "", + }, + dokterdanTenagaMedis: { + name: "", + specialist: "", + jadwal: "", + }, + fasilitasPendukung: { + content: "", + }, + prosedurPendaftaran: { + content: "", + }, + tarifDanLayanan: { + layanan: "", + tarif: "", + }, +}; -const informasiumum = proxy({ +const fasilitasKesehatanState = proxy({ create: { - form: {} as InfromasiUmum, + form: { ...defaultForm }, loading: false, - async create() { - const cek = templateInformasiUmum.safeParse(informasiumum.create.form); + async submit() { + const cek = templateForm.safeParse(this.form); if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); + const errMsg = cek.error.issues + .map((v) => `${v.path.join(".")}: ${v.message}`) + .join("\n"); + toast.error(errMsg); + return null; } + try { - informasiumum.create.loading = true; - const res = await ApiFetch.api.kesehatan.informasiumum["create"].post( - informasiumum.create.form + this.loading = true; + const payload = { ...this.form }; + + const res = await (ApiFetch.api.kesehatan as any)[ + "fasilitas-kesehatan" + ].create.post(payload); + + if (res.status === 200) { + toast.success("Berhasil menambahkan fasilitas kesehatan"); + this.resetForm(); + await fasilitasKesehatanState.findMany.load(); + return res.data; + } + } catch (err: any) { + const msg = err?.message || "Terjadi kesalahan saat mengirim data"; + toast.error(msg); + console.error("SUBMIT ERROR:", err); + return null; + } finally { + this.loading = false; + } + }, + resetForm() { + this.form = { ...defaultForm }; + }, + }, + + findMany: { + data: null as + | Prisma.FasilitasKesehatanGetPayload<{ + include: { + informasiumum: true; + layananunggulan: true; + dokterdantenagamedis: true; + fasilitaspendukung: true; + prosedurpendaftaran: true; + tarifdanlayanan: true; + }; + }>[] + | null, + loading: false, + async load() { + try { + this.loading = true; + const res = await (ApiFetch.api.kesehatan as any)[ + "fasilitas-kesehatan" + ]["find-many"].get(); + + if (res.status === 200) { + this.data = res.data?.data ?? []; + } else { + toast.error("Gagal memuat data fasilitas kesehatan"); + } + + return res; + } catch (err) { + toast.error("Terjadi error saat load data"); + console.error("LOAD ERROR:", err); + throw err; + } finally { + this.loading = false; + } + }, + }, + findUnique: { + data: null as Prisma.FasilitasKesehatanGetPayload<{ + include: { + informasiumum: true; + layananunggulan: true; + dokterdantenagamedis: true; + fasilitaspendukung: true; + prosedurpendaftaran: true; + tarifdanlayanan: true; + }; + }> | null, + loading: false, + async load(id: string) { + const res = await fetch(`/api/kesehatan/fasilitas-kesehatan/${id}`); + if (res.ok) { + const data = await res.json(); + fasilitasKesehatanState.findUnique.data = data.data ?? null; + } else { + toast.error("Gagal load data fasilitas kesehatan"); + } + }, + }, + edit: { + id: "", + form: { ...defaultForm }, + loading: false, + async load(id: string) { + const res = await fetch(`/api/kesehatan/fasilitas-kesehatan/${id}`); + if (!res.ok) { + toast.error("Gagal load data fasilitas kesehatan"); + return; + } + + const result = await res.json(); + const data = result.data; + + fasilitasKesehatanState.edit.id = data.id; + fasilitasKesehatanState.edit.form = { + name: data.name, + informasiUmum: { + fasilitas: data.informasiumum.fasilitas, + alamat: data.informasiumum.alamat, + jamOperasional: data.informasiumum.jamOperasional, + }, + layananUnggulan: { + content: data.layananunggulan.content, + }, + dokterdanTenagaMedis: { + name: data.dokterdantenagamedis.name, + specialist: data.dokterdantenagamedis.specialist, + jadwal: data.dokterdantenagamedis.jadwal, + }, + fasilitasPendukung: { + content: data.fasilitaspendukung.content, + }, + prosedurPendaftaran: { + content: data.prosedurpendaftaran.content, + }, + tarifDanLayanan: { + layanan: data.tarifdanlayanan.layanan, + tarif: data.tarifdanlayanan.tarif, + }, + }; + }, + async submit() { + const cek = templateForm.safeParse(fasilitasKesehatanState.edit.form); + if (!cek.success) { + const errMsg = cek.error.issues + .map((v) => `${v.path.join(".")}: ${v.message}`) + .join("\n"); + toast.error(errMsg); + return null; + } + + try { + fasilitasKesehatanState.edit.loading = true; + const payload = { + name: fasilitasKesehatanState.edit.form.name, + informasiUmum: { + fasilitas: + fasilitasKesehatanState.edit.form.informasiUmum.fasilitas, + alamat: fasilitasKesehatanState.edit.form.informasiUmum.alamat, + jamOperasional: + fasilitasKesehatanState.edit.form.informasiUmum.jamOperasional, + }, + layananUnggulan: { + content: fasilitasKesehatanState.edit.form.layananUnggulan.content, + }, + dokterdanTenagaMedis: { + name: fasilitasKesehatanState.edit.form.dokterdanTenagaMedis.name, + specialist: + fasilitasKesehatanState.edit.form.dokterdanTenagaMedis.specialist, + jadwal: + fasilitasKesehatanState.edit.form.dokterdanTenagaMedis.jadwal, + }, + fasilitasPendukung: { + content: + fasilitasKesehatanState.edit.form.fasilitasPendukung.content, + }, + prosedurPendaftaran: { + content: + fasilitasKesehatanState.edit.form.prosedurPendaftaran.content, + }, + tarifDanLayanan: { + layanan: fasilitasKesehatanState.edit.form.tarifDanLayanan.layanan, + tarif: fasilitasKesehatanState.edit.form.tarifDanLayanan.tarif, + }, + }; + + const res = await fetch( + `/api/kesehatan/fasilitas-kesehatan/${fasilitasKesehatanState.edit.id}`, + { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + } ); - if (res.status === 200) { - informasiumum.findMany.load(); - return toast.success("success create"); + + if (!res.ok) { + const error = await res.json(); + throw new Error(error.message || "Update gagal"); } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - informasiumum.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.InformasiUmumGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan. - informasiumum["find-many"].get(); - if (res.status === 200) { - informasiumum.findMany.data = res.data?.data ?? []; - } - }, - }, -}); -/* ======================================================================= */ -/* Layanan Unggulan */ -const templateLayananUnggulanForm = z.object({ - content: z.string().min(3, "Content minimal 3 karakter"), -}); - -type LayananUnggulan = Prisma.LayananUnggulanGetPayload<{ - select: { - content: true; - }; -}>; - -const layananunggulan = proxy({ - create: { - form: {} as LayananUnggulan, - loading: false, - async create() { - const cek = templateLayananUnggulanForm.safeParse(layananunggulan.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - layananunggulan.create.loading = true; - const res = await ApiFetch.api.kesehatan.layananunggulan["create"].post( - layananunggulan.create.form + toast.success("Berhasil update fasilitas kesehatan"); + await fasilitasKesehatanState.findMany.load(); + return true; + } catch (err) { + toast.error( + err instanceof Error ? err.message : "Terjadi kesalahan saat update" ); - if (res.status === 200) { - layananunggulan.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); + return false; } finally { - layananunggulan.create.loading = false; + fasilitasKesehatanState.edit.loading = false; } }, - }, - findMany: { - data: null as - | Prisma.LayananUnggulanGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan. - layananunggulan["find-many"].get(); - if (res.status === 200) { - layananunggulan.findMany.data = res.data?.data ?? []; - } + resetForm() { + fasilitasKesehatanState.edit.id = ""; + fasilitasKesehatanState.edit.form = { ...defaultForm }; }, }, -}) -/* ======================================================================= */ - -/* Dokter dan Tenaga Medis */ -const templateDokterdanTenagaMedis = z.object({ - name: z.string().min(3, "Name minimal 3 karakter"), - specialist: z.string().min(3, "Specialist minimal 3 karakter"), - jadwal: z.string().min(3, "Jadwal minimal 3 karakter"), -}) - -type DokterdanTenagaMedis = Prisma.DokterdanTenagaMedisGetPayload<{ - select: { - name: true; - specialist: true; - jadwal: true; - }; -}>; - -const dokterdantenagamedis = proxy({ - create: { - form: {} as DokterdanTenagaMedis, + delete: { loading: false, - async create() { - const cek = templateDokterdanTenagaMedis.safeParse(dokterdantenagamedis.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } + async byId(id: string){ try { - dokterdantenagamedis.create.loading = true; - const res = await ApiFetch.api.kesehatan.dokterdantenagamedis["create"].post(dokterdantenagamedis.create.form); - if (res.status === 200) { - dokterdantenagamedis.findMany.load(); - return toast.success("success create"); + fasilitasKesehatanState.delete.loading = true; + const res = await fetch(`/api/kesehatan/fasilitas-kesehatan/del/${id}`, { + method: "DELETE", + }); + + const result = await res.json(); + if (res.ok && result.success) { + toast.success("Fasilitas kesehatan berhasil dihapus"); + await fasilitasKesehatanState.findMany.load(); + } else { + toast.error(result.message || "Gagal menghapus"); } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); + } catch { + toast.error("Terjadi kesalahan saat menghapus"); } finally { - dokterdantenagamedis.create.loading = false; + fasilitasKesehatanState.delete.loading = false; } - }, + } }, - findMany: { - data: null as - | Prisma.DokterdanTenagaMedisGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan.dokterdantenagamedis["find-many"].get(); - if (res.status === 200) { - dokterdantenagamedis.findMany.data = res.data?.data ?? []; - } - }, - }, -}) -/* ======================================================================= */ +}); -/* Fasilitas Pendukung */ -const templateFasilitasPendukung = z.object({ - content: z.string().min(3, "Content minimal 3 karakter"), -}) - -type FasilitasPendukung = Prisma.FasilitasPendukungGetPayload<{ - select: { - content: true; - }; -}>; - -const fasilitaspendukung = proxy({ - create: { - form: {} as FasilitasPendukung, - loading: false, - async create() { - const cek = templateFasilitasPendukung.safeParse(fasilitaspendukung.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - fasilitaspendukung.create.loading = true; - const res = await ApiFetch.api.kesehatan.fasilitaspendukung["create"].post(fasilitaspendukung.create.form); - if (res.status === 200) { - fasilitaspendukung.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - fasilitaspendukung.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.FasilitasPendukungGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan. - fasilitaspendukung["find-many"].get(); - if (res.status === 200) { - fasilitaspendukung.findMany.data = res.data?.data ?? []; - } - }, - }, -}) -/* ======================================================================= */ - -/* Tarif dan Layanan */ -const templateTarifDanLayanan = z.object({ - layanan: z.string().min(3, "Layanan minimal 3 karakter"), - tarif: z.string().min(3, "Tarif minimal 3 karakter"), -}) - -const tarifdanlayanan = proxy({ - create: { - form: {} as Prisma.TarifDanLayananGetPayload<{ select: { layanan: true; tarif: true } }>, - loading: false, - async create() { - const cek = templateTarifDanLayanan.safeParse(tarifdanlayanan.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - tarifdanlayanan.create.loading = true; - const res = await ApiFetch.api.kesehatan.tarifdanlayanan["create"].post(tarifdanlayanan.create.form); - if (res.status === 200) { - tarifdanlayanan.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - tarifdanlayanan.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.TarifDanLayananGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan. - tarifdanlayanan["find-many"].get(); - if (res.status === 200) { - tarifdanlayanan.findMany.data = res.data?.data ?? []; - } - }, - }, -}) -/* ======================================================================= */ - -/* Prosedur Pendaftaran */ -const templateProsedurPendaftaran = z.object({ - content: z.string().min(3, "Content minimal 3 karakter"), -}) - -const prosedurpendaftaran = proxy({ - create: { - form: {} as Prisma.ProsedurPendaftaranGetPayload<{ select: { content: true } }>, - loading: false, - async create() { - const cek = templateProsedurPendaftaran.safeParse(prosedurpendaftaran.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - prosedurpendaftaran.create.loading = true; - const res = await ApiFetch.api.kesehatan.prosedurpendaftaran["create"].post(prosedurpendaftaran.create.form); - if (res.status === 200) { - prosedurpendaftaran.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - prosedurpendaftaran.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.ProsedurPendaftaranGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan. - prosedurpendaftaran["find-many"].get(); - if (res.status === 200) { - prosedurpendaftaran.findMany.data = res.data?.data ?? []; - } - }, - }, -}) - -const stateFasilitasKesehatan = proxy({ - informasiumum, - layananunggulan, - dokterdantenagamedis, - fasilitaspendukung, - tarifdanlayanan, - prosedurpendaftaran -}) - -export default stateFasilitasKesehatan +export default fasilitasKesehatanState; diff --git a/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan.ts b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan.ts index ac614ba9..985850d3 100644 --- a/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan.ts +++ b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan.ts @@ -6,7 +6,7 @@ import { z } from "zod"; const templateGrafikKepuasan = z.object({ label: z.string().min(2, "Label harus diisi"), - jumlah: z.string().min(2, "Jumlah harus diisi"), + jumlah: z.string().min(1, "Jumlah harus diisi"), }); type GrafikKepuasan = Prisma.GrafikKepuasanGetPayload<{ @@ -31,24 +31,30 @@ const grafikkepuasan = proxy({ const err = `[${cek.error.issues .map((v) => `${v.path.join(".")}`) .join("\n")}] required`; - return toast.error(err); + toast.error(err); + return null; } try { grafikkepuasan.create.loading = true; - const res = await ApiFetch.api.kesehatan.grafikkepuasan["create"].post( - grafikkepuasan.create.form - ); + const res = await ApiFetch.api.kesehatan.grafikkepuasan["create"].post(grafikkepuasan.create.form); + if (res.status === 200) { - grafikkepuasan.create.form = { - label: "", - jumlah: "" - }; - grafikkepuasan.findMany.load(); - return toast.success("success create"); + const uuid = res.data?.data?.uuid; + if (uuid) { + toast.success("Success create"); + grafikkepuasan.create.form = { + label: "", + jumlah: "", + }; + grafikkepuasan.findMany.load(); + return uuid; + } } - return toast.error("failed create"); + toast.error("failed create"); + return null; } catch (error) { console.log((error as Error).message); + return null; } finally { grafikkepuasan.create.loading = false; } @@ -67,10 +73,110 @@ const grafikkepuasan = proxy({ } }, }, + findUnique: { + data: null as Prisma.GrafikKepuasanGetPayload<{ + omit: { isActive: true } + }> | null, + async load(uuid: string) { + try { + const res = await fetch(`/api/kesehatan/grafikkepuasan/${uuid}`); + if (res.ok) { + const data = await res.json(); + grafikkepuasan.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch grafikkepuasan:", res.statusText); + grafikkepuasan.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching grafikkepuasan:", error); + grafikkepuasan.findUnique.data = null; + } + }, + }, + update: { + uuid: "", + form: {...defaultForm}, + loading: false, + async byId() { + }, + async submit() { + const uuid = this.uuid; + if (!uuid) { + toast.warn("ID tidak valid"); + return null; + } + const cek = templateGrafikKepuasan.safeParse(grafikkepuasan.update.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + try { + this.loading = true; + const response = await fetch(`/api/kesehatan/grafikkepuasan/${uuid}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.form), + }); + const result = await response.json(); + + if (!response.ok || !result?.success) { + throw new Error(result?.message || "Gagal update data"); + } + + toast.success("Berhasil update data!"); + + // ✅ Optional: refresh list kalau kamu langsung ke halaman list + await grafikkepuasan.findMany.load(); + + return result.data; + } catch (error) { + console.error("Error update data:", error); + toast.error("Gagal update data grafik kepuasan"); + } finally { + this.loading = false; + } + }, +}, +delete: { + loading: false, + async byId(uuid: string) { + if (!uuid) { + return toast.warn("ID tidak valid"); + } + try { + grafikkepuasan.delete.loading = true; + + const response = await fetch(`/api/kesehatan/grafikkepuasan/del/${uuid}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success( + result.message || "Grafik kepuasan berhasil dihapus" + ); + await grafikkepuasan.findMany.load(); // refresh list + } else { + toast.error( + result?.message || "Gagal menghapus grafik kepuasan" + ); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus grafik kepuasan"); + } finally { + grafikkepuasan.delete.loading = false; + } + } +} }); -const stategrafikKepuasan = proxy({ - grafikkepuasan, -}); - -export default stategrafikKepuasan; +export default grafikkepuasan; diff --git a/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran.ts b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran.ts index 3521775c..f1e9dd6d 100644 --- a/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran.ts +++ b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran.ts @@ -6,9 +6,9 @@ import { z } from "zod"; const templatePersentase = z.object({ tahun: z.string().min(4, "Tahun harus diisi"), - kematianKasar: z.string().min(2, "Kematian kasar harus diisi"), - kelahiranKasar: z.string().min(2, "Kelahiran kasar harus diisi"), - kematianBayi: z.string().min(2, "Kematian bayi harus diisi"), + kematianKasar: z.string().min(1, "Kematian kasar harus diisi"), + kelahiranKasar: z.string().min(1, "Kelahiran kasar harus diisi"), + kematianBayi: z.string().min(1, "Kematian bayi harus diisi"), }); type Persentase = Prisma.DataKematian_KelahiranGetPayload<{ @@ -34,51 +34,157 @@ const persentasekelahiran = proxy({ async create() { const cek = templatePersentase.safeParse(persentasekelahiran.create.form); if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); + const err = `[${cek.error.issues.map((v) => `${v.path.join(".")}`).join("\n")}] required`; + toast.error(err); + return null; } try { persentasekelahiran.create.loading = true; - const res = await ApiFetch.api.kesehatan.persentasekelahiran[ - "create" - ].post(persentasekelahiran.create.form); + const res = await ApiFetch.api.kesehatan.persentasekelahiran["create"].post( + persentasekelahiran.create.form + ); + if (res.status === 200) { - persentasekelahiran.create.form = { - tahun: "", - kematianKasar: "", - kelahiranKasar: "", - kematianBayi: "", - }; - persentasekelahiran.findMany.load(); - return toast.success("success create"); + const uuid = res.data?.data?.uuid; + if (uuid) { + toast.success("Success create"); + persentasekelahiran.create.form = { ...defaultForm }; + persentasekelahiran.findMany.load(); + return uuid; + } } - return toast.error("failed create"); + toast.error("failed create"); + return null; } catch (error) { console.log((error as Error).message); + return null; } finally { persentasekelahiran.create.loading = false; } }, }, + findMany: { - data: null as - | Prisma.DataKematian_KelahiranGetPayload<{ omit: { isActive: true } }>[] - | null, + data: null as Prisma.DataKematian_KelahiranGetPayload<{ + omit: { isActive: true }; + }>[] | null, async load() { - const res = await ApiFetch.api.kesehatan.persentasekelahiran[ - "find-many" - ].get(); + const res = await ApiFetch.api.kesehatan.persentasekelahiran["find-many"].get(); if (res.status === 200) { persentasekelahiran.findMany.data = res.data?.data ?? []; } }, }, + + findUnique: { + data: null as Prisma.DataKematian_KelahiranGetPayload<{ + omit: { isActive: true }; + }> | null, + async load(uuid: string) { + try { + const res = await fetch(`/api/kesehatan/persentasekelahiran/${uuid}`); + if (res.ok) { + const data = await res.json(); + persentasekelahiran.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch persentasekelahiran:", res.statusText); + persentasekelahiran.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching persentasekelahiran:", error); + persentasekelahiran.findUnique.data = null; + } + }, + }, + +update: { + uuid: "", + form: { ...defaultForm }, + loading: false, + async submit() { + const uuid = this.uuid; + if (!uuid) { + toast.warn("UUID tidak valid"); + return null; + } + + const formData = { + tahun: this.form.tahun, + kematianKasar: this.form.kematianKasar, + kelahiranKasar: this.form.kelahiranKasar, + kematianBayi: this.form.kematianBayi, + }; + + const cek = templatePersentase.safeParse(formData); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + toast.error(err); + return null; + } + + try { + this.loading = true; + const res = await fetch(`/api/kesehatan/persentasekelahiran/${uuid}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(formData), + }); + + const result = await res.json(); + + if (!res.ok || !result?.success) { + throw new Error(result?.message || "Gagal update data"); + } + + toast.success("Berhasil update data!"); + await persentasekelahiran.findMany.load(); + return result.data; + } catch (error) { + console.error("Update error:", error); + toast.error("Gagal update data persentase kelahiran"); + throw error; + } finally { + this.loading = false; + } + }, +}, + + + delete: { + loading: false, + async byId(uuid: string) { + if (!uuid) return toast.warn("UUID tidak valid"); + + try { + persentasekelahiran.delete.loading = true; + + const response = await fetch(`/api/kesehatan/persentasekelahiran/del/${uuid}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Persentase kelahiran berhasil dihapus"); + await persentasekelahiran.findMany.load(); + } else { + toast.error(result?.message || "Gagal menghapus persentase kelahiran"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus persentase kelahiran"); + } finally { + persentasekelahiran.delete.loading = false; + } + }, + }, }); -const statePersentase = proxy({ - persentasekelahiran, -}); - -export default statePersentase; +export default persentasekelahiran; diff --git a/src/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit.ts b/src/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit.ts new file mode 100644 index 00000000..e53417bd --- /dev/null +++ b/src/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit.ts @@ -0,0 +1,214 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +const templateForm = z.object({ + name: z.string().min(3, "Judul minimal 3 karakter"), + deskripsiSingkat: z.string().min(3, "Deskripsi singkat minimal 3 karakter"), + deskripsiLengkap: z.string().min(3, "Deskripsi lengkap minimal 3 karakter"), + imageId: z.string().nonempty(), +}); + +const defaultForm = { + name: "", + deskripsiSingkat: "", + deskripsiLengkap: "", + imageId: "", +}; + +const infoWabahPenyakit = proxy({ + findMany: { + data: [] as Prisma.InfoWabahPenyakitGetPayload<{ + include: { + image: true; + }; + }>[], + async load() { + const res = await ApiFetch.api.kesehatan.infowabahpenyakit[ + "find-many" + ].get(); + if (res.status === 200) { + infoWabahPenyakit.findMany.data = res.data?.data ?? []; + } + }, + }, + create: { + form: { ...defaultForm }, + loading: false, + async create() { + const cek = templateForm.safeParse(infoWabahPenyakit.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + infoWabahPenyakit.create.loading = true; + const res = await ApiFetch.api.kesehatan.infowabahpenyakit[ + "create" + ].post(infoWabahPenyakit.create.form); + if (res.status === 200) { + infoWabahPenyakit.findMany.load(); + return toast.success("Info wabah penyakit berhasil disimpan!"); + } + + return toast.error("Gagal menyimpan info wabah penyakit"); + } catch (error) { + console.log((error as Error).message); + } finally { + infoWabahPenyakit.create.loading = false; + } + }, + resetForm() { + infoWabahPenyakit.create.form = { ...defaultForm }; + }, + }, + findUnique: { + data: null as Prisma.InfoWabahPenyakitGetPayload<{ + include: { + image: true; + }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/kesehatan/infowabahpenyakit/${id}`); + if (res.ok) { + const data = await res.json(); + infoWabahPenyakit.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch info wabah penyakit:", res.statusText); + infoWabahPenyakit.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching info wabah penyakit:", error); + infoWabahPenyakit.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + infoWabahPenyakit.delete.loading = true; + + const response = await fetch(`/api/kesehatan/infowabahpenyakit/del/${id}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await response.json(); + if (response.ok && result?.success) { + toast.success(result.message || "Info wabah penyakit berhasil dihapus"); + await infoWabahPenyakit.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus info wabah penyakit"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus info wabah penyakit"); + } finally { + infoWabahPenyakit.delete.loading = false; + } + }, + }, + edit: { + id: "", + form: { ...defaultForm }, + loading: false, + + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch(`/api/kesehatan/infowabahpenyakit/${id}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result?.success) { + const data = result.data; + this.id = data.id; + this.form = { + name: data.name, + deskripsiSingkat: data.deskripsiSingkat, + deskripsiLengkap: data.deskripsiLengkap, + imageId: data.imageId, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error fetching info wabah penyakit:", error); + toast.error(error instanceof Error ? error.message : "Gagal memuat data"); + return null; + } + }, + + async update() { + const cek = templateForm.safeParse(infoWabahPenyakit.edit.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + infoWabahPenyakit.edit.loading = true; + const response = await fetch(`/api/kesehatan/infowabahpenyakit/${this.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: this.form.name, + deskripsiSingkat: this.form.deskripsiSingkat, + deskripsiLengkap: this.form.deskripsiLengkap, + imageId: this.form.imageId, + }), + }); + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || `HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result.success) { + toast.success(result.message || "Info wabah penyakit berhasil diupdate"); + await infoWabahPenyakit.findMany.load(); + return true; + } else { + throw new Error(result.message || "Gagal update info wabah penyakit"); + } + } catch (error) { + console.error("Gagal update:", error); + toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat mengupdate info wabah penyakit"); + return false; + } finally { + infoWabahPenyakit.edit.loading = false; + } + }, + reset() { + infoWabahPenyakit.edit.id = ""; + infoWabahPenyakit.edit.form = { ...defaultForm }; + }, + }, +}); + +export default infoWabahPenyakit; diff --git a/src/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat.ts b/src/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat.ts new file mode 100644 index 00000000..cfd2c18f --- /dev/null +++ b/src/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat.ts @@ -0,0 +1,208 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +const templateForm = z.object({ + name: z.string().min(3, "Judul minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), + imageId: z.string().nonempty(), +}) + +const defaultForm = { + name: "", + deskripsi: "", + imageId: "", +} + +const kontakDarurat = proxy({ + findMany: { + data: [] as Prisma.KontakDaruratGetPayload<{ + include: { + image: true; + }; + }>[], + async load() { + const res = await ApiFetch.api.kesehatan.kontakdarurat[ + "find-many" + ].get(); + if (res.status === 200) { + kontakDarurat.findMany.data = res.data?.data ?? []; + } + }, + }, + create:{ + form: {...defaultForm}, + loading: false, + async create() { + const cek = templateForm.safeParse(kontakDarurat.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + kontakDarurat.create.loading = true; + const res = await ApiFetch.api.kesehatan.kontakdarurat[ + "create" + ].post(kontakDarurat.create.form); + if (res.status === 200) { + kontakDarurat.findMany.load(); + return toast.success("Kontak Darurat berhasil disimpan!"); + } + + return toast.error("Gagal menyimpan kontak darurat"); + } catch (error) { + console.log((error as Error).message); + } finally { + kontakDarurat.create.loading = false; + } + }, + resetForm() { + kontakDarurat.create.form = {...defaultForm}; + } + }, + findUnique: { + data: null as Prisma.KontakDaruratGetPayload<{ + include: { + image: true; + }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/kesehatan/kontakdarurat/${id}`); + if (res.ok) { + const data = await res.json(); + kontakDarurat.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch data", res.status, res.statusText); + kontakDarurat.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching data:", error); + kontakDarurat.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + try { + kontakDarurat.delete.loading = true; + const response = await fetch(`/api/kesehatan/kontakdarurat/del/${id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Kontak darurat berhasil dihapus"); + await kontakDarurat.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus kontak darurat"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus kontak darurat"); + } finally { + kontakDarurat.delete.loading = false; + } + } + }, + edit: { + id: "", + form: { ...defaultForm }, + loading: false, + + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch(`/api/kesehatan/kontakdarurat/${id}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result?.success) { + const data = result.data; + this.id = data.id; + this.form = { + name: data.name, + deskripsi: data.deskripsi, + imageId: data.imageId, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error fetching kontak darurat:", error); + toast.error(error instanceof Error ? error.message : "Gagal memuat data"); + return null; + } + }, + + async update() { + const cek = templateForm.safeParse(kontakDarurat.edit.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + kontakDarurat.edit.loading = true; + const response = await fetch(`/api/kesehatan/kontakdarurat/${this.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: this.form.name, + deskripsi: this.form.deskripsi, + imageId: this.form.imageId, + }), + }); + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || `HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result.success) { + toast.success(result.message || "Kontak darurat berhasil diupdate"); + await kontakDarurat.findMany.load(); + return true; + } else { + throw new Error(result.message || "Gagal update kontak darurat"); + } + } catch (error) { + console.error("Gagal update:", error); + toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat mengupdate kontak darurat"); + return false; + } finally { + kontakDarurat.edit.loading = false; + } + }, + reset() { + kontakDarurat.edit.id = ""; + kontakDarurat.edit.form = { ...defaultForm }; + }, + }, +}); + +export default kontakDarurat diff --git a/src/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat.ts b/src/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat.ts new file mode 100644 index 00000000..b47e0b17 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat.ts @@ -0,0 +1,208 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +const templateForm = z.object({ + name: z.string().min(3, "Judul minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), + imageId: z.string().nonempty(), +}) + +const defaultForm = { + name: "", + deskripsi: "", + imageId: "", +} + +const penangananDarurat = proxy({ + findMany: { + data: [] as Prisma.PenangananDaruratGetPayload<{ + include: { + image: true; + }; + }>[], + async load() { + const res = await ApiFetch.api.kesehatan.penanganandarurat[ + "find-many" + ].get(); + if (res.status === 200) { + penangananDarurat.findMany.data = res.data?.data ?? []; + } + }, + }, + create:{ + form: {...defaultForm}, + loading: false, + async create() { + const cek = templateForm.safeParse(penangananDarurat.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + penangananDarurat.create.loading = true; + const res = await ApiFetch.api.kesehatan.penanganandarurat[ + "create" + ].post(penangananDarurat.create.form); + if (res.status === 200) { + penangananDarurat.findMany.load(); + return toast.success("Penanganan Darurat berhasil disimpan!"); + } + + return toast.error("Gagal menyimpan penanganan darurat"); + } catch (error) { + console.log((error as Error).message); + } finally { + penangananDarurat.create.loading = false; + } + }, + resetForm() { + penangananDarurat.create.form = {...defaultForm}; + } + }, + findUnique: { + data: null as Prisma.PenangananDaruratGetPayload<{ + include: { + image: true; + }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/kesehatan/penanganandarurat/${id}`); + if (res.ok) { + const data = await res.json(); + penangananDarurat.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch data", res.status, res.statusText); + penangananDarurat.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching data:", error); + penangananDarurat.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + try { + penangananDarurat.delete.loading = true; + const response = await fetch(`/api/kesehatan/penanganandarurat/del/${id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Penanganan darurat berhasil dihapus"); + await penangananDarurat.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus penanganan darurat"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus penanganan darurat"); + } finally { + penangananDarurat.delete.loading = false; + } + } + }, + edit: { + id: "", + form: { ...defaultForm }, + loading: false, + + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch(`/api/kesehatan/penanganandarurat/${id}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result?.success) { + const data = result.data; + this.id = data.id; + this.form = { + name: data.name, + deskripsi: data.deskripsi, + imageId: data.imageId, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error fetching penanganan darurat:", error); + toast.error(error instanceof Error ? error.message : "Gagal memuat data"); + return null; + } + }, + + async update() { + const cek = templateForm.safeParse(penangananDarurat.edit.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + penangananDarurat.edit.loading = true; + const response = await fetch(`/api/kesehatan/penanganandarurat/${this.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: this.form.name, + deskripsi: this.form.deskripsi, + imageId: this.form.imageId, + }), + }); + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || `HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result.success) { + toast.success(result.message || "Penanganan darurat berhasil diupdate"); + await penangananDarurat.findMany.load(); + return true; + } else { + throw new Error(result.message || "Gagal update penanganan darurat"); + } + } catch (error) { + console.error("Gagal update:", error); + toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat mengupdate penanganan darurat"); + return false; + } finally { + penangananDarurat.edit.loading = false; + } + }, + reset() { + penangananDarurat.edit.id = ""; + penangananDarurat.edit.form = { ...defaultForm }; + }, + }, +}); + +export default penangananDarurat diff --git a/src/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu.ts b/src/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu.ts new file mode 100644 index 00000000..83d9ded2 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu.ts @@ -0,0 +1,217 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +const templateForm = z.object({ + name: z.string().min(1, { message: "Name is required" }), + nomor: z.string().min(1, { message: "Nomor is required" }), + deskripsi: z.string().min(1, { message: "Deskripsi is required" }), + imageId: z.string().nonempty(), +}); + +const defaultForm = { + name: "", + nomor: "", + deskripsi: "", + imageId: "", +}; + +const posyandustate = proxy({ + create: { + form: { ...defaultForm }, + loading: false, + async create() { + const cek = templateForm.safeParse(posyandustate.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + posyandustate.create.loading = true; + const res = await ApiFetch.api.kesehatan.posyandu["create"].post(posyandustate.create.form); + if (res.status === 200) { + posyandustate.findMany.load(); + return toast.success("Posyandu berhasil disimpan!"); + } + return toast.error("Gagal menyimpan posyandu"); + } catch (error) { + console.log((error as Error).message); + } finally { + posyandustate.create.loading = false; + } + }, + resetForm(){ + posyandustate.create.form = { ...defaultForm }; + } + }, + findMany: { + data: null as + | Prisma.PosyanduGetPayload<{ + include: { + image: true; + } + }>[] + | null, + async load() { + const res = await ApiFetch.api.kesehatan.posyandu["find-many"].get(); + if (res.status === 200) { + posyandustate.findMany.data = res.data?.data ?? []; + } + } + }, + findUnique: { + data: null as + | Prisma.PosyanduGetPayload<{ + include: { + image: true; + } + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/kesehatan/posyandu/${id}`); + if (res.ok) { + const data = await res.json(); + posyandustate.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch posyandu:", res.statusText); + posyandustate.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching posyandu:", error); + posyandustate.findUnique.data = null; + } + } + }, + delete: { + loading: false, + async byId(id: string) { + try { + posyandustate.delete.loading = true; + const response = await fetch(`/api/kesehatan/posyandu/del/${id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Posyandu berhasil dihapus"); + await posyandustate.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus posyandu"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus posyandu"); + } finally { + posyandustate.delete.loading = false; + } + } + }, + edit: { + id: "", + form: {...defaultForm}, + loading: false, + + async load(id: string) { + if(!id){ + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch(`/api/kesehatan/posyandu/${id}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if(!response.ok){ + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + + if(result?.success){ + const data = result.data; + this.id = data.id; + this.form = { + name: data.name, + nomor: data.nomor, + deskripsi: data.deskripsi, + imageId: data.imageId || "", + }; + return data; + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error fetching posyandu:", error); + toast.error(error instanceof Error ? error.message : "Gagal memuat data"); + return null; + } + }, + async update() { + const cek = templateForm.safeParse(posyandustate.edit.form); + if(!cek.success){ + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + toast.error(err); + return false; + } + + try { + posyandustate.edit.loading = true; + const response = await fetch(`/api/kesehatan/posyandu/${this.id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: this.form.name, + nomor: this.form.nomor, + deskripsi: this.form.deskripsi, + imageId: this.form.imageId, + }), + }); + + if(!response.ok){ + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || `HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + + if(result.success){ + toast.success(result.message || "Posyandu berhasil diperbarui"); + await posyandustate.findMany.load(); // refresh list + return true; + } else { + throw new Error(result.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error fetching posyandu:", error); + toast.error(error instanceof Error ? error.message : "Gagal memuat data"); + return false; + } finally { + posyandustate.edit.loading = false; + } + }, + + reset() { + posyandustate.edit.id = ""; + posyandustate.edit.form = {...defaultForm}; + } + } +}) + +export default posyandustate; diff --git a/src/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan.ts b/src/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan.ts new file mode 100644 index 00000000..47676d85 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan.ts @@ -0,0 +1,214 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +const templateForm = z.object({ + name: z.string().min(3, "Judul minimal 3 karakter"), + deskripsiSingkat: z.string().min(3, "Deskripsi singkat minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), + imageId: z.string().nonempty(), +}); + +const defaultForm = { + name: "", + deskripsiSingkat: "", + deskripsi: "", + imageId: "", +}; + +const programKesehatan = proxy({ + findMany: { + data: [] as Prisma.ProgramKesehatanGetPayload<{ + include: { + image: true; + }; + }>[], + async load() { + const res = await ApiFetch.api.kesehatan.programkesehatan[ + "find-many" + ].get(); + if (res.status === 200) { + programKesehatan.findMany.data = res.data?.data ?? []; + } + }, + }, + create: { + form: { ...defaultForm }, + loading: false, + async create() { + const cek = templateForm.safeParse(programKesehatan.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + programKesehatan.create.loading = true; + const res = await ApiFetch.api.kesehatan.programkesehatan[ + "create" + ].post(programKesehatan.create.form); + if (res.status === 200) { + programKesehatan.findMany.load(); + return toast.success("Program Kesehatan berhasil disimpan!"); + } + + return toast.error("Gagal menyimpan program kesehatan"); + } catch (error) { + console.log((error as Error).message); + } finally { + programKesehatan.create.loading = false; + } + }, + resetForm() { + programKesehatan.create.form = { ...defaultForm }; + }, + }, + findUnique: { + data: null as Prisma.ProgramKesehatanGetPayload<{ + include: { + image: true; + }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/kesehatan/programkesehatan/${id}`); + if (res.ok) { + const data = await res.json(); + programKesehatan.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch program kesehatan:", res.statusText); + programKesehatan.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching program kesehatan:", error); + programKesehatan.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + programKesehatan.delete.loading = true; + + const response = await fetch(`/api/kesehatan/programkesehatan/del/${id}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await response.json(); + if (response.ok && result?.success) { + toast.success(result.message || "Program kesehatan berhasil dihapus"); + await programKesehatan.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus program kesehatan"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus program kesehatan"); + } finally { + programKesehatan.delete.loading = false; + } + }, + }, + edit: { + id: "", + form: { ...defaultForm }, + loading: false, + + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch(`/api/kesehatan/programkesehatan/${id}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result?.success) { + const data = result.data; + this.id = data.id; + this.form = { + name: data.name, + deskripsiSingkat: data.deskripsiSingkat, + deskripsi: data.deskripsi, + imageId: data.imageId, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error fetching program kesehatan:", error); + toast.error(error instanceof Error ? error.message : "Gagal memuat data"); + return null; + } + }, + + async update() { + const cek = templateForm.safeParse(programKesehatan.edit.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + programKesehatan.edit.loading = true; + const response = await fetch(`/api/kesehatan/programkesehatan/${this.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: this.form.name, + deskripsiSingkat: this.form.deskripsiSingkat, + deskripsi: this.form.deskripsi, + imageId: this.form.imageId, + }), + }); + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || `HTTP error! status: ${response.status}`); + } + const result = await response.json(); + if (result.success) { + toast.success(result.message || "Program kesehatan berhasil diupdate"); + await programKesehatan.findMany.load(); + return true; + } else { + throw new Error(result.message || "Gagal update program kesehatan"); + } + } catch (error) { + console.error("Gagal update:", error); + toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat mengupdate program kesehatan"); + return false; + } finally { + programKesehatan.edit.loading = false; + } + }, + reset() { + programKesehatan.edit.id = ""; + programKesehatan.edit.form = { ...defaultForm }; + }, + }, +}); + +export default programKesehatan; diff --git a/src/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas.ts b/src/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas.ts new file mode 100644 index 00000000..040d3f17 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas.ts @@ -0,0 +1,298 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +// Validasi form +const templateForm = z.object({ + name: z.string().min(1), + alamat: z.string().min(1), + imageId: z.string().min(1), + jam: z.object({ + workDays: z.string().min(1), + weekDays: z.string().min(1), + holiday: z.string().min(1), + }), + kontak: z.object({ + kontakPuskesmas: z.string().min(1), + email: z.string().min(1), + facebook: z.string().min(1), + kontakUGD: z.string().min(1), + }), +}); + +// Default form +const defaultForm = { + name: "", + alamat: "", + imageId: "", + jam: { + workDays: "", + weekDays: "", + holiday: "", + }, + kontak: { + kontakPuskesmas: "", + email: "", + facebook: "", + kontakUGD: "", + }, + image: undefined, +}; + +const puskesmasState = proxy({ + create: { + form: { ...defaultForm }, + loading: false, + async submit() { + const cek = templateForm.safeParse(puskesmasState.create.form); + if (!cek.success) { + const err = `[${cek.error.issues.map((v) => v.path.join(".")).join(", ")}] required`; + return toast.error(err); + } + + try { + puskesmasState.create.loading = true; + + console.log('Form data:', puskesmasState.create.form); + interface ErrorResponse { + message?: string; + error?: string; + errors?: Record; + } + + const payload = { + name: puskesmasState.create.form.name, + alamat: puskesmasState.create.form.alamat, + imageId: puskesmasState.create.form.imageId, + jam: { + workDays: puskesmasState.create.form.jam.workDays, + weekDays: puskesmasState.create.form.jam.weekDays, + holiday: puskesmasState.create.form.jam.holiday, + }, + kontak: { + kontakPuskesmas: puskesmasState.create.form.kontak.kontakPuskesmas, + email: puskesmasState.create.form.kontak.email, + facebook: puskesmasState.create.form.kontak.facebook, + kontakUGD: puskesmasState.create.form.kontak.kontakUGD, + }, + }; + + + + + console.log('Sending payload:', JSON.stringify(payload, null, 2)); + + try { + const res = await ApiFetch.api.kesehatan.puskesmas.create.post(payload); + console.log('API Response:', res); + + if (res.status === 200) { + await puskesmasState.findMany.load(); + toast.success("Berhasil menambahkan puskesmas"); + return res; + } else { + console.error('API Error Response:', { + status: res.status, + data: res.data + }); + + const errorData = res.data as ErrorResponse; + let errorMessage = 'Gagal menambahkan puskesmas'; + + if (errorData?.message) { + errorMessage = errorData.message; + } else if (errorData?.error) { + errorMessage = errorData.error; + } else if (errorData?.errors) { + errorMessage = Object.entries(errorData.errors) + .map(([field, messages]) => `${field}: ${Array.isArray(messages) ? messages.join(', ') : messages}`) + .join('; '); + } + + console.error('Extracted error message:', errorMessage); + toast.error(errorMessage); + throw new Error(errorMessage); + } + } catch (error) { + console.error('Error in API call:', { + error, + errorString: String(error), + jsonError: error instanceof Error ? { + name: error.name, + message: error.message, + stack: error.stack + } : 'Not an Error instance' + }); + throw error; + } + } catch (error) { + console.error("Error in puskesmas submit:", { + error, + errorString: String(error), + errorType: typeof error, + isErrorInstance: error instanceof Error, + errorDetails: error instanceof Error ? { + name: error.name, + message: error.message, + stack: error.stack, + cause: error.cause + } : null + }); + + let errorMessage = "Terjadi kesalahan saat menambahkan puskesmas"; + if (error instanceof Error) { + errorMessage = error.message || errorMessage; + } else if (error && typeof error === 'object' && 'message' in error) { + errorMessage = String((error as { message: unknown }).message); + } else if (typeof error === 'string') { + errorMessage = error; + } + + console.error('Displaying error to user:', errorMessage); + toast.error(errorMessage); + throw error; + } finally { + puskesmasState.create.loading = false; + } + }, + resetForm() { + puskesmasState.create.form = { ...defaultForm }; + } + }, + + findMany: { + data: null as Prisma.PuskesmasGetPayload<{ + include: { image: true; jam: true; kontak: true }; + }>[] | null, + async load() { + const res = await ApiFetch.api.kesehatan.puskesmas["find-many"].get(); + if (res.status === 200) { + puskesmasState.findMany.data = res.data?.data ?? []; + } + }, + }, + + findUnique: { + data: null as Prisma.PuskesmasGetPayload<{ + include: { image: true; jam: true; kontak: true }; + }> | null, + async load(id: string) { + const res = await fetch(`/api/kesehatan/puskesmas/${id}`); + if (res.ok) { + const data = await res.json(); + puskesmasState.findUnique.data = data.data ?? null; + } else { + toast.error("Gagal load data puskesmas"); + } + }, + }, + + edit: { + id: "", + form: { ...defaultForm }, + loading: false, + + async load(id: string) { + const res = await fetch(`/api/kesehatan/puskesmas/${id}`); + if (!res.ok) { + toast.error("Gagal memuat data"); + return; + } + + const result = await res.json(); + const data = result.data; + + puskesmasState.edit.id = data.id; + puskesmasState.edit.form = { + name: data.name, + alamat: data.alamat, + imageId: data.imageId, + jam: { + workDays: data.jam.workDays, + weekDays: data.jam.weekDays, + holiday: data.jam.holiday, + }, + kontak: { + kontakPuskesmas: data.kontak.kontakPuskesmas, + email: data.kontak.email, + facebook: data.kontak.facebook, + kontakUGD: data.kontak.kontakUGD, + }, + image: data.image, + }; + }, + + async submit() { + const cek = templateForm.safeParse(puskesmasState.edit.form); + if (!cek.success) { + const err = `[${cek.error.issues.map((v) => v.path.join(".")).join(", ")}] required`; + toast.error(err); + return false; + } + + try { + puskesmasState.edit.loading = true; + const payload = { + name: puskesmasState.edit.form.name, + alamat: puskesmasState.edit.form.alamat, + imageId: puskesmasState.edit.form.imageId, + jam: { ...puskesmasState.edit.form.jam }, + kontak: { ...puskesmasState.edit.form.kontak } + }; + + const res = await fetch(`/api/kesehatan/puskesmas/${puskesmasState.edit.id}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + + if (!res.ok) { + const error = await res.json(); + throw new Error(error.message || "Update gagal"); + } + + toast.success("Berhasil update puskesmas"); + await puskesmasState.findMany.load(); + return true; + } catch (err) { + toast.error(err instanceof Error ? err.message : "Terjadi kesalahan saat update"); + return false; + } finally { + puskesmasState.edit.loading = false; + } + }, + + reset() { + puskesmasState.edit.id = ""; + puskesmasState.edit.form = { ...defaultForm }; + } + }, + + delete: { + loading: false, + async byId(id: string) { + try { + puskesmasState.delete.loading = true; + const res = await fetch(`/api/kesehatan/puskesmas/del/${id}`, { + method: "DELETE", + }); + + const result = await res.json(); + if (res.ok && result.success) { + toast.success("Puskesmas berhasil dihapus"); + await puskesmasState.findMany.load(); + } else { + toast.error(result.message || "Gagal menghapus"); + } + } catch { + toast.error("Terjadi kesalahan saat menghapus"); + } finally { + puskesmasState.delete.loading = false; + } + } + } +}); + +export default puskesmasState; diff --git a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts index 164c6e81..b889d6a5 100644 --- a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts +++ b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts @@ -5,9 +5,9 @@ import { proxy } from "valtio"; import { z } from "zod"; const templateGrafikJenisKelamin = z.object({ - laki: z.string().min(2, "Data laki-laki harus diisi"), - perempuan: z.string().min(2, "Data perempuan harus diisi"), -}); + laki: z.string().min(1, "Data laki-laki harus diisi"), + perempuan: z.string().min(1, "Data perempuan harus diisi"), +}); type GrafikJenisKelamin = Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{ select: { diff --git a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts index 7b3f4693..eec88dc4 100644 --- a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts +++ b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts @@ -5,10 +5,10 @@ import { proxy } from "valtio"; import { z } from "zod"; const templateGrafikUmur = z.object({ - remaja: z.string().min(2, "Data remaja harus diisi"), - dewasa: z.string().min(2, "Data dewasa harus diisi"), - orangtua: z.string().min(2, "Data orangtua harus diisi"), - lansia: z.string().min(2, "Data lansia harus diisi"), + remaja: z.string().min(1, "Data remaja harus diisi"), + dewasa: z.string().min(1, "Data dewasa harus diisi"), + orangtua: z.string().min(1, "Data orangtua harus diisi"), + lansia: z.string().min(1, "Data lansia harus diisi"), }); type GrafikUmur = Prisma.GrafikBerdasarkanUmurGetPayload<{ diff --git a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts index 65287269..dc735972 100644 --- a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts +++ b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts @@ -6,7 +6,7 @@ import { z } from "zod"; const templateGrafikHasilKepuasanMasyarakat = z.object({ label: z.string().min(2, "Label harus diisi"), - kepuasan: z.string().min(2, "Kepuasan harus diisi"), + kepuasan: z.string().min(1, "Kepuasan harus diisi"), }); type GrafikHasilKepuasanMasyarakat = Prisma.IndeksKepuasanMasyarakatGetPayload<{ diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_lib/layoutTabs.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_lib/layoutTabs.tsx new file mode 100644 index 00000000..abacee4d --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_lib/layoutTabs.tsx @@ -0,0 +1,77 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import colors from '@/con/colors'; +import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core'; +import { usePathname, useRouter } from 'next/navigation'; +import React, { useEffect, useState } from 'react'; + +function LayoutTabs({ children }: { children: React.ReactNode }) { + const router = useRouter() + const pathname = usePathname() + const tabs = [ + { + label: "Presentase Kelahiran & Kematian", + value: "presentasekelahiran&kematian", + href: "/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian" + }, + { + label: "Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik", + value: "grafikhasilkepuasan", + href: "/admin/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan" + }, + { + label: "Fasilitas Kesehatan", + value: "fasilitaskesehatan", + href: "/admin/kesehatan/data-kesehatan-warga/fasilitas_kesehatan" + }, + { + label: "Jadwal Kegiatan", + value: "jadwalkegiatan", + href: "/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan" + }, + { + label: "Artikel Kesehatan", + value: "artikelkesehatan", + href: "/admin/kesehatan/data-kesehatan-warga/artikel_kesehatan" + }, + ]; + const curentTab = tabs.find(tab => tab.href === pathname) + const [activeTab, setActiveTab] = useState(curentTab?.value || tabs[0].value); + + const handleTabChange = (value: string | null) => { + const tab = tabs.find(t => t.value === value) + if (tab) { + router.push(tab.href) + } + setActiveTab(value) + } + + useEffect(() => { + const match = tabs.find(tab => tab.href === pathname) + if (match) { + setActiveTab(match.value) + } + }, [pathname]) + + return ( + + Data Kesehatan Warga + + + {tabs.map((e, i) => ( + {e.label} + ))} + + {tabs.map((e, i) => ( + + {/* Konten dummy, bisa diganti tergantung routing */} + <> + + ))} + + {children} + + ); +} + +export default LayoutTabs; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/dokterdantenagamedis/listData.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/dokterdantenagamedis/listData.tsx deleted file mode 100644 index ae79ddeb..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/dokterdantenagamedis/listData.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import colors from '@/con/colors'; -import { Center, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; -import { useShallowEffect } from '@mantine/hooks'; -import _ from 'lodash'; -import { useProxy } from 'valtio/utils'; - -function DokterdanTenagaMedisList() { - const kesehatanState = useProxy(stateFasilitasKesehatan.dokterdantenagamedis); - - useShallowEffect(() => { - kesehatanState.findMany.load(); - }, []); - - // Penanganan kasus ketika tidak ada data - if (_.isEmpty(kesehatanState.findMany.data)) { - return ( - - - - - -
Nama
-
- -
Specialist
-
- -
Jadwal
-
-
-
- - - -
- Tidak ada data -
-
-
-
-
-
- ); - } - - return ( - - - - - -
Nama
-
- -
Specialist
-
- -
Jadwal
-
-
-
- - {kesehatanState.findMany.data?.map((item) => ( - - {item.name} - Specialist {item.specialist} - {item.jadwal} - - ))} - -
-
- ); -} - -export default DokterdanTenagaMedisList; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/dokterdantenagamedis/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/dokterdantenagamedis/page.tsx deleted file mode 100644 index 4e888c40..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/dokterdantenagamedis/page.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import colors from '@/con/colors'; -import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; -import { useProxy } from 'valtio/utils'; - -function DokterDanTenagaMedis() { - const dokterdantenagamedisState = useProxy(stateFasilitasKesehatan.dokterdantenagamedis) - return ( - - - - Dokter & Tenaga Medis - { - dokterdantenagamedisState.create.form.name = val.target.value - }} - /> - { - dokterdantenagamedisState.create.form.specialist = val.target.value - }} - /> - { - dokterdantenagamedisState.create.form.jadwal = val.target.value - }} - /> - - - - ); -} - -export default DokterDanTenagaMedis; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/fasilitas_pendukung/listData.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/fasilitas_pendukung/listData.tsx deleted file mode 100644 index 8d315b88..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/fasilitas_pendukung/listData.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Box, Stack, Text } from '@mantine/core'; -import React from 'react'; -import { useProxy } from 'valtio/utils'; -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import { useShallowEffect } from '@mantine/hooks'; - -function FasilitasPendukungList() { - const fasilitaspendukungState = useProxy(stateFasilitasKesehatan.fasilitaspendukung) - useShallowEffect(() => { - fasilitaspendukungState.findMany.load() - }, []) - return - {fasilitaspendukungState.findMany.data?.map((item) => ( - - - - ))} - -} - -export default FasilitasPendukungList; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/fasilitas_pendukung/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/fasilitas_pendukung/page.tsx deleted file mode 100644 index 6195fcae..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/fasilitas_pendukung/page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import { Box, Paper, Text } from '@mantine/core'; -import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; - -function FasilitasPendukung() { - const fasilitaspendukungState = useProxy(stateFasilitasKesehatan.fasilitaspendukung) - return - - Fasilitas Pendukung - { - fasilitaspendukungState.create.form.content = val; - }} /> - - -} - -export default FasilitasPendukung; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/informasi_umum/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/informasi_umum/page.tsx deleted file mode 100644 index b220d62c..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/informasi_umum/page.tsx +++ /dev/null @@ -1,40 +0,0 @@ -'use client' -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import colors from '@/con/colors'; -import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; -import { useProxy } from 'valtio/utils'; - -function InformasiUmum() { - const infromasiState = useProxy(stateFasilitasKesehatan.informasiumum) - return - - Informasi Umum - - { - infromasiState.create.form.fasilitas = val.target.value - }} - /> - { - infromasiState.create.form.alamat = val.target.value - }} - /> - { - infromasiState.create.form.jamOperasional = val.target.value - }} - /> - - - -} - -export default InformasiUmum; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/layanan_unggulan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/layanan_unggulan/page.tsx deleted file mode 100644 index 63c53209..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/layanan_unggulan/page.tsx +++ /dev/null @@ -1,23 +0,0 @@ -'use client' -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import { Box, Paper, Text } from '@mantine/core'; -import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; - -function LayananUnggulan() { - const informasiumumState = useProxy(stateFasilitasKesehatan.layananunggulan) - return - - Layanan Unggulan - { - informasiumumState.create.form.content = val; - }} /> - - - ; -} - -export default LayananUnggulan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/page.tsx deleted file mode 100644 index bdb84c62..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/page.tsx +++ /dev/null @@ -1,254 +0,0 @@ -"use client" - -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import colors from '@/con/colors'; -import { Box, Button, Center, Paper, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core'; -import { useShallowEffect } from '@mantine/hooks'; -import { useProxy } from 'valtio/utils'; -import DokterDanTenagaMedis from './dokterdantenagamedis/page'; -import FasilitasPendukung from './fasilitas_pendukung/page'; -import InformasiUmum from './informasi_umum/page'; -import LayananUnggulan from './layanan_unggulan/page'; -import ProsedurPendaftaran from './prosedurpendaftaran/page'; -import TarifDanLayanan from './tarifdanlayanan/page'; - - -function FasilitasKesehatan() { - const allState = useProxy(stateFasilitasKesehatan) - const submitAllForms = () => { - if (allState.informasiumum.create.form.fasilitas && - allState.informasiumum.create.form.alamat && - allState.informasiumum.create.form.jamOperasional) { - allState.informasiumum.create.create() - } - - if (allState.layananunggulan.create.form.content) { - allState.layananunggulan.create.create(); - } - - if (allState.dokterdantenagamedis.create.form.name && - allState.dokterdantenagamedis.create.form.specialist && - allState.dokterdantenagamedis.create.form.jadwal) { - allState.dokterdantenagamedis.create.create() - } - - if (allState.fasilitaspendukung.create.form.content) { - allState.fasilitaspendukung.create.create(); - } - - if (allState.tarifdanlayanan.create.form.tarif && - allState.tarifdanlayanan.create.form.layanan) { - allState.tarifdanlayanan.create.create() - } - - if (allState.prosedurpendaftaran.create.form.content) { - allState.prosedurpendaftaran.create.create(); - } - - // refreshListData(); - // resetAllForms(); - } - - // const refreshListData = () => { - // allState.informasiumum.findMany.load(); - // allState.layananunggulan.findMany.load(); - // allState.dokterdantenagamedis.findMany.load(); - // allState.fasilitaspendukung.findMany.load(); - // allState.tarifdanlayanan.findMany.load(); - // allState.prosedurpendaftaran.findMany.load(); - // } - - // const resetAllForms = () => { - // allState.informasiumum.create.form = { - // fasilitas: '', - // alamat: '', - // jamOperasional: '' - // }; - // allState.layananunggulan.create.form = { - // content: '' - // }; - // allState.dokterdantenagamedis.create.form = { - // name: '', - // specialist: '', - // jadwal: '' - // }; - // allState.fasilitaspendukung.create.form = { - // content: '' - // }; - // allState.tarifdanlayanan.create.form = { - // tarif: '', - // layanan: '' - // }; - // allState.prosedurpendaftaran.create.form = { - // content: '' - // }; - // } - - return ( - - - - - Tambah Fasilitas Kesehatan - {/* Informasi Umum */} - - {/* Layanan Unggulan */} - - {/* Dokter & Tenaga Medis */} - - {/* Fasilitas Pendukung */} - - {/* Tarif & Layanan */} - - {/* Prosedur Pendaftaran */} - - - - - - - - Data Fasilitas Kesehatan - - - - - - - ); -} - -function AllList() { - const allListState = useProxy(stateFasilitasKesehatan) - useShallowEffect(() => { - allListState.informasiumum.findMany.load(); - allListState.layananunggulan.findMany.load(); - allListState.dokterdantenagamedis.findMany.load(); - allListState.fasilitaspendukung.findMany.load(); - allListState.tarifdanlayanan.findMany.load(); - allListState.prosedurpendaftaran.findMany.load(); - }, []) - - if (!allListState.informasiumum.findMany.data - || !allListState.layananunggulan.findMany.data - || !allListState.dokterdantenagamedis.findMany.data - || !allListState.fasilitaspendukung.findMany.data - || !allListState.tarifdanlayanan.findMany.data - || !allListState.prosedurpendaftaran.findMany.data - ) return - {Array.from({ length: 10 }).map((v, k) => )} - - return - - Informasi Umum - {allListState.informasiumum.findMany.data?.map((item) => ( - - - {item.fasilitas} - {item.alamat} - {item.jamOperasional} - - ))} - - - - Layanan Unggulan - {allListState.layananunggulan.findMany.data?.map((item) => ( - - - - ))} - - - - - Dokter & Tenaga Medis - - - - - -
Nama
-
- -
Specialist
-
- -
Jadwal
-
-
-
- - {allListState.dokterdantenagamedis.findMany.data?.map((item) => ( - - {item.name} - Specialist {item.specialist} - {item.jadwal} - - ))} - -
-
- - - - Fasilitas Pendukung - {allListState.fasilitaspendukung.findMany.data?.map((item) => ( - - - - ))} - - - - Tarif & Layanan - - - - - Layanan - - - Tarif - - - - - {allListState.tarifdanlayanan.findMany.data?.map((item) => ( - - {item.layanan} - Rp.{item.tarif} - - ))} - -
-
- - - - Prosedur Pendaftaran - {allListState.prosedurpendaftaran.findMany.data?.map((item) => ( - - - - ))} - -
-} - -export default FasilitasKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/prosedurpendaftaran/listData.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/prosedurpendaftaran/listData.tsx deleted file mode 100644 index 4692b479..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/prosedurpendaftaran/listData.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import { Box, Skeleton, Stack, Text } from '@mantine/core'; -import { useShallowEffect } from '@mantine/hooks'; -import { useProxy } from 'valtio/utils'; - -function ListProsedurPendaftaran() { - const prosedurpendaftaranState = useProxy(stateFasilitasKesehatan.prosedurpendaftaran) - useShallowEffect(() => { - prosedurpendaftaranState.findMany.load() - }, []) - - if (!prosedurpendaftaranState.findMany.data)return - {Array.from({ length: 10 }).map((v, k) => )} - - - return - {prosedurpendaftaranState.findMany.data?.map((item) => ( - - - - ))} - -} - -export default ListProsedurPendaftaran; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/prosedurpendaftaran/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/prosedurpendaftaran/page.tsx deleted file mode 100644 index b28cb52e..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/prosedurpendaftaran/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import { Box, Text, Paper } from '@mantine/core'; -import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; - -function ProsedurPendaftaran() { - const prosedurpendaftaranState = useProxy(stateFasilitasKesehatan.prosedurpendaftaran) - return - - Prosedur Pendaftaran - { - prosedurpendaftaranState.create.form.content = val; - }} /> - - - -} - -export default ProsedurPendaftaran; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/tarifdanlayanan/listData.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/tarifdanlayanan/listData.tsx deleted file mode 100644 index 1675952e..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/tarifdanlayanan/listData.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import colors from '@/con/colors'; -import { Center, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; -import { useShallowEffect } from '@mantine/hooks'; -import _ from 'lodash'; -import { useProxy } from 'valtio/utils'; - -function TarifDanLayananList() { - const tarifdanlayanan = useProxy(stateFasilitasKesehatan.tarifdanlayanan) - useShallowEffect(() => { - tarifdanlayanan.findMany.load() - }, []) - - if (_.isEmpty(tarifdanlayanan.findMany.data)) { - return ( - - - - - -
Nama
-
- -
Specialist
-
- -
Jadwal
-
-
-
- - - -
- Tidak ada data -
-
-
-
-
-
- ); - } - - return - - - - - Layanan - - - Tarif - - - - - {tarifdanlayanan.findMany.data?.map((item) => ( - - {item.layanan} - Rp.{item.tarif} - - ))} - -
-
-} - -export default TarifDanLayananList; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/tarifdanlayanan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/tarifdanlayanan/page.tsx deleted file mode 100644 index b9ae2bce..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/fasilitas_kesehatan/tarifdanlayanan/page.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; -import colors from '@/con/colors'; -import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; -import { useProxy } from 'valtio/utils'; - -function TarifDanLayanan() { - const tarifdanlayanan = useProxy(stateFasilitasKesehatan.tarifdanlayanan) - return - - Tarif & Layanan - - { - tarifdanlayanan.create.form.tarif = val.target.value - }} - /> - { - tarifdanlayanan.create.form.layanan = val.target.value - }} - /> - - - -} - -export default TarifDanLayanan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/grafik_hasil_kepuasan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/grafik_hasil_kepuasan/page.tsx deleted file mode 100644 index cd352a75..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/grafik_hasil_kepuasan/page.tsx +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -'use client' -import stategrafikKepuasan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan'; -import colors from '@/con/colors'; -import { Box, Button, Group, Paper, Skeleton, Stack, TextInput, Title } from '@mantine/core'; -import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; -import { useEffect, useState } from 'react'; -import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts'; -import { useProxy } from 'valtio/utils'; - -function GrafikHasilKepuasan() { - const grafikkepuasan = useProxy(stategrafikKepuasan.grafikkepuasan) - const [mounted, setMounted] = useState(false); - const isTablet = useMediaQuery('(max-width: 1024px)') - const isMobile = useMediaQuery('(max-width: 768px)') - const [chartData, setChartData] = useState([]) - - useShallowEffect(() => { - const fetchData = async () => { - await grafikkepuasan.findMany.load(); - if (grafikkepuasan.findMany.data && grafikkepuasan.findMany.data.length > 0) { - setChartData(grafikkepuasan.findMany.data); - } - }; - fetchData(); - }, []); - - useEffect(() => { - setMounted(true); // setelah komponen siap di client - }, []); - - if (!mounted) { - return null; // Jangan render apa-apa dulu sebelum mounted - } - - - return ( - - - Tambah Grafik Hasil Kepuasan - - { - grafikkepuasan.create.form.label = val.currentTarget.value - }} - /> - { - grafikkepuasan.create.form.jumlah = val.currentTarget.value - }} - /> - - - - - - {!chartData ? ( - - - Data Hasil Kepuasan - - - - ) : ( - - - Data Hasil Kepuasan - - - - - - - - - - )} - - ); -} - -export default GrafikHasilKepuasan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/persentase_data_kelahiran_kematian/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/persentase_data_kelahiran_kematian/page.tsx deleted file mode 100644 index 87714c66..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/persentase_data_kelahiran_kematian/page.tsx +++ /dev/null @@ -1,124 +0,0 @@ -'use client' -/* eslint-disable @typescript-eslint/no-explicit-any */ -import statePersentase from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; -import colors from '@/con/colors'; -import { Box, Button, Group, Paper, Skeleton, Stack, TextInput, Title } from '@mantine/core'; -import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; -import { useEffect, useState } from 'react'; -import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts'; -import { useProxy } from 'valtio/utils'; - -function PersentaseDataKelahiranKematian() { - const persentase = useProxy(statePersentase.persentasekelahiran); - const [chartData, setChartData] = useState([]); - const [mounted, setMounted] = useState(false); // untuk memastikan DOM sudah ready - const isTablet = useMediaQuery('(max-width: 1024px)') - const isMobile = useMediaQuery('(max-width: 768px)') - - useEffect(() => { - setMounted(true); - }, []); - - useShallowEffect(() => { - const fetchData = async () => { - await persentase.findMany.load(); - if (persentase.findMany.data && persentase.findMany.data.length > 0) { - setChartData(persentase.findMany.data); - } - }; - fetchData(); - }, []); - - return ( - - {/* Form Input */} - - - Tambah Persentase Data Kelahiran & Kematian - - { - persentase.create.form.tahun = val.currentTarget.value; - }} - /> - { - persentase.create.form.kematianKasar = val.currentTarget.value; - }} - /> - { - persentase.create.form.kematianBayi = val.currentTarget.value; - }} - /> - { - persentase.create.form.kelahiranKasar = val.currentTarget.value; - }} - /> - - - - - - - - {/* Chart */} - {!mounted && !chartData ? ( - - - Data Kelahiran & Kematian - - - - ) : ( - - - Data Kelahiran & Kematian - {mounted && chartData.length > 0 && ( - - - - - - - - - - )} - - - )} - - ); -} - -export default PersentaseDataKelahiranKematian; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/doctor_sign/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/doctor_sign/page.tsx similarity index 88% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/doctor_sign/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/doctor_sign/page.tsx index 7975625c..6f09affc 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/doctor_sign/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/doctor_sign/page.tsx @@ -1,10 +1,9 @@ 'use client' -import { Box, Paper, Text } from '@mantine/core'; -import React from 'react'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import { useProxy } from 'valtio/utils'; -import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; import colors from '@/con/colors'; +import { Box, Paper, Text } from '@mantine/core'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; +import { useProxy } from 'valtio/utils'; function DoctorSignUI() { const doctorSign = useProxy(stateArtikelKesehatan.doctorSign) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/first_aid/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/first_aid/page.tsx similarity index 91% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/first_aid/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/first_aid/page.tsx index 61021b8c..71a082a5 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/first_aid/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/first_aid/page.tsx @@ -1,10 +1,9 @@ 'use client' -import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; -import React from 'react'; -import { useProxy } from 'valtio/utils'; import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; import colors from '@/con/colors'; +import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; +import { useProxy } from 'valtio/utils'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; function FirstAidUI() { const firstAidState = useProxy(stateArtikelKesehatan.firstAid) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/introduction/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/introduction/page.tsx similarity index 92% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/introduction/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/introduction/page.tsx index 7dce6b06..95eefb74 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/introduction/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/introduction/page.tsx @@ -2,9 +2,9 @@ import { Box, Paper, Stack, Text } from '@mantine/core'; import React from 'react'; import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; import colors from '@/con/colors'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; function IntoductionUI() { const introduction = useProxy(stateArtikelKesehatan.introduction) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/mythVsfact/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/mythVsfact/page.tsx similarity index 100% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/mythVsfact/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/mythVsfact/page.tsx diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/page.tsx similarity index 99% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/page.tsx index 4f944e96..fb964e67 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/page.tsx @@ -169,4 +169,4 @@ function AllList() { } -export default ArtikelKesehatan; +export default ArtikelKesehatan; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/prevention/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/prevention/page.tsx similarity index 91% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/prevention/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/prevention/page.tsx index 4752cb9b..5dd3533d 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/prevention/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/prevention/page.tsx @@ -1,10 +1,9 @@ 'use client' import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; -import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; -import React from 'react'; -import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; import colors from '@/con/colors'; +import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; +import { useProxy } from 'valtio/utils'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; function PreventionUI() { const preventionState = useProxy(stateArtikelKesehatan.prevention) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/symptom/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/symptom/page.tsx similarity index 93% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/symptom/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/symptom/page.tsx index 195775f8..d5f3f302 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/artikel_kesehatan/symptom/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/symptom/page.tsx @@ -1,9 +1,9 @@ 'use client' import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; +import colors from '@/con/colors'; import { Box, Paper, Stack, Text, TextInput } from '@mantine/core'; import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; function SymptomUI() { const symptomState = useProxy(stateArtikelKesehatan.symptom) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/[id]/edit/page.tsx new file mode 100644 index 00000000..ff3e5321 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/[id]/edit/page.tsx @@ -0,0 +1,359 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' + +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + +interface FasilitasKesehatanFormBase { + name: string; + informasiUmum: { + fasilitas: string; + alamat: string; + jamOperasional: string; + }; + layananUnggulan: { + content: string; + }; + dokterdanTenagaMedis: { + name: string; + specialist: string; + jadwal: string; + }; + fasilitasPendukung: { + content: string; + }; + prosedurPendaftaran: { + content: string; + }; + tarifDanLayanan: { + layanan: string; + tarif: string; + }; +} + +function EditFasilitasKesehatan() { + const stateFasilitasKesehatan = useProxy(fasilitasKesehatanState); + const router = useRouter(); + const params = useParams(); + + const [formData, setFormData] = useState({ + name: stateFasilitasKesehatan.edit.form.name || '', + informasiUmum: { + fasilitas: stateFasilitasKesehatan.edit.form.informasiUmum?.fasilitas || '', + alamat: stateFasilitasKesehatan.edit.form.informasiUmum?.alamat || '', + jamOperasional: stateFasilitasKesehatan.edit.form.informasiUmum?.jamOperasional || '', + }, + layananUnggulan: { + content: stateFasilitasKesehatan.edit.form.layananUnggulan?.content || '', + }, + dokterdanTenagaMedis: { + name: stateFasilitasKesehatan.edit.form.dokterdanTenagaMedis?.name || '', + specialist: stateFasilitasKesehatan.edit.form.dokterdanTenagaMedis?.specialist || '', + jadwal: stateFasilitasKesehatan.edit.form.dokterdanTenagaMedis?.jadwal || '', + }, + fasilitasPendukung: { + content: stateFasilitasKesehatan.edit.form.fasilitasPendukung?.content || '', + }, + prosedurPendaftaran: { + content: stateFasilitasKesehatan.edit.form.prosedurPendaftaran?.content || '', + }, + tarifDanLayanan: { + layanan: stateFasilitasKesehatan.edit.form.tarifDanLayanan?.layanan || '', + tarif: stateFasilitasKesehatan.edit.form.tarifDanLayanan?.tarif || '', + }, + }); + + useEffect(() => { + const loadFasilitasKesehatan = async () => { + const id = params?.id as string; + if (!id) return; + + try { + await stateFasilitasKesehatan.edit.load(id); + const { form } = stateFasilitasKesehatan.edit; + if (form) { + setFormData({ + name: form.name, + informasiUmum: { + fasilitas: form.informasiUmum?.fasilitas || '', + alamat: form.informasiUmum?.alamat || '', + jamOperasional: form.informasiUmum?.jamOperasional || '', + }, + layananUnggulan: { + content: form.layananUnggulan?.content || '', + }, + dokterdanTenagaMedis: { + name: form.dokterdanTenagaMedis?.name || '', + specialist: form.dokterdanTenagaMedis?.specialist || '', + jadwal: form.dokterdanTenagaMedis?.jadwal || '', + }, + fasilitasPendukung: { + content: form.fasilitasPendukung?.content || '', + }, + prosedurPendaftaran: { + content: form.prosedurPendaftaran?.content || '', + }, + tarifDanLayanan: { + layanan: form.tarifDanLayanan?.layanan || '', + tarif: form.tarifDanLayanan?.tarif || '', + }, + }); + } + } catch (error) { + console.error("Error loading fasilitas kesehatan:", error); + toast.error("Gagal memuat data fasilitas kesehatan"); + } + }; + loadFasilitasKesehatan(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + stateFasilitasKesehatan.edit.form = { + ...stateFasilitasKesehatan.edit.form, + name: formData.name, + informasiUmum: { + fasilitas: formData.informasiUmum.fasilitas, + alamat: formData.informasiUmum.alamat, + jamOperasional: formData.informasiUmum.jamOperasional, + }, + layananUnggulan: { + content: formData.layananUnggulan.content, + }, + dokterdanTenagaMedis: { + name: formData.dokterdanTenagaMedis.name, + specialist: formData.dokterdanTenagaMedis.specialist, + jadwal: formData.dokterdanTenagaMedis.jadwal, + }, + fasilitasPendukung: { + content: formData.fasilitasPendukung.content, + }, + prosedurPendaftaran: { + content: formData.prosedurPendaftaran.content, + }, + tarifDanLayanan: { + layanan: formData.tarifDanLayanan.layanan, + tarif: formData.tarifDanLayanan.tarif, + }, + }; + const success = await stateFasilitasKesehatan.edit.submit(); + if (success) { + toast.success("Fasilitas kesehatan berhasil diperbarui!"); + router.push("/admin/kesehatan/data-kesehatan-warga/fasilitas_kesehatan"); + } + } catch (error) { + console.error("Error updating fasilitas kesehatan:", error); + toast.error(error instanceof Error ? error.message : "Gagal memperbarui data fasilitas kesehatan"); + } + }; + return ( + + + + + + + + Edit Fasilitas Kesehatan + Nama Fasilitas Kesehatan} + placeholder="masukkan nama fasilitas kesehatan" + value={formData.name} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + name: e.target.value + })); + }} + /> + + Informasi Umum + Fasilitas} + placeholder="masukkan fasilitas" + value={formData.informasiUmum.fasilitas} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + informasiUmum: { + ...prev.informasiUmum, + fasilitas: e.target.value + } + })); + }} + /> + Alamat} + placeholder="masukkan alamat" + value={formData.informasiUmum.alamat} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + informasiUmum: { + ...prev.informasiUmum, + alamat: e.target.value + } + })); + }} + /> + Jam Operasional} + placeholder="masukkan jam operasional" + value={formData.informasiUmum.jamOperasional} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + informasiUmum: { + ...prev.informasiUmum, + jamOperasional: e.target.value + } + })); + }} + /> + + + Layanan Unggulan + { + setFormData(prev => ({ + ...prev, + layananUnggulan: { + ...prev.layananUnggulan, + content: e + } + })); + }} + /> + + + Dokter dan Tenaga Medis + Nama Dokter} + placeholder="masukkan nama dokter" + value={formData.dokterdanTenagaMedis.name} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + dokterdanTenagaMedis: { + ...prev.dokterdanTenagaMedis, + name: e.target.value + } + })); + }} + /> + Specialist} + placeholder="masukkan specialist" + value={formData.dokterdanTenagaMedis.specialist} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + dokterdanTenagaMedis: { + ...prev.dokterdanTenagaMedis, + specialist: e.target.value + } + })); + }} + /> + Jadwal} + placeholder="masukkan jadwal" + value={formData.dokterdanTenagaMedis.jadwal} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + dokterdanTenagaMedis: { + ...prev.dokterdanTenagaMedis, + jadwal: e.target.value + } + })); + }} + /> + + + Fasilitas Pendukung + { + setFormData(prev => ({ + ...prev, + fasilitasPendukung: { + ...prev.fasilitasPendukung, + content: e + } + })); + }} + /> + + + Prosedur Pendaftaran + { + setFormData(prev => ({ + ...prev, + prosedurPendaftaran: { + ...prev.prosedurPendaftaran, + content: e + } + })); + }} + /> + + + Tarif dan Layanan + Tarif} + placeholder="masukkan tarif" + value={formData.tarifDanLayanan.tarif} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + tarifDanLayanan: { + ...prev.tarifDanLayanan, + tarif: e.target.value + } + })); + }} + /> + Layanan} + placeholder="masukkan layanan" + value={formData.tarifDanLayanan.layanan} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + tarifDanLayanan: { + ...prev.tarifDanLayanan, + layanan: e.target.value + } + })); + }} + /> + + + + + + + + ); +} + +export default EditFasilitasKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/[id]/page.tsx new file mode 100644 index 00000000..8b115483 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/[id]/page.tsx @@ -0,0 +1,127 @@ +'use client' +import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus'; +import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; +import colors from '@/con/colors'; +import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +function DetailFasilitasKesehatan() { + const params = useParams() + const router = useRouter(); + const stateFasilitasKesehatan = useProxy(fasilitasKesehatanState) + const [modalHapus, setModalHapus] = useState(false); + const [selectedId, setSelectedId] = useState(null) + + useShallowEffect(() => { + stateFasilitasKesehatan.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + stateFasilitasKesehatan.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/data-kesehatan-warga/fasilitas_kesehatan") + } + } + + if (!stateFasilitasKesehatan.findUnique.data) { + return ( + + + + ) + } + + + return ( + + + + + + + Detail Fasilitas Kesehatan + {stateFasilitasKesehatan.findUnique.data ? ( + + + + Nama Fasilitas Kesehatan + {stateFasilitasKesehatan.findUnique.data.name} + + + Informasi Umum + Fasilitas + {stateFasilitasKesehatan.findUnique.data.informasiumum.fasilitas} + Alamat + {stateFasilitasKesehatan.findUnique.data.informasiumum.alamat} + Jam Operasional + {stateFasilitasKesehatan.findUnique.data.informasiumum.jamOperasional} + + + Layanan Unggulan + + + + Dokter dan Tenaga Medis + Nama Dokter + {stateFasilitasKesehatan.findUnique.data.dokterdantenagamedis.name} + Specialist + {stateFasilitasKesehatan.findUnique.data.dokterdantenagamedis.specialist} + Jadwal + {stateFasilitasKesehatan.findUnique.data.dokterdantenagamedis.jadwal} + + + Fasilitas Pendukung + + + + Prosedur Pendaftaran + + + + Tarif dan Layanan + Layanan + {stateFasilitasKesehatan.findUnique.data.tarifdanlayanan.layanan} + Tarif + {stateFasilitasKesehatan.findUnique.data.tarifdanlayanan.tarif} + + + + + + + + + + ) : null} + + + + {/* Modal Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus fasilitas kesehatan ini?" + /> + + ); +} + +export default DetailFasilitasKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/create/page.tsx new file mode 100644 index 00000000..2b5122b2 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/create/page.tsx @@ -0,0 +1,187 @@ +'use client' +import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor'; +import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + + +function CreateFasilitasKesehatan() { + const stateFasilitasKesehatan = useProxy(fasilitasKesehatanState) + const router = useRouter(); + + + const resetForm = () => { + stateFasilitasKesehatan.create.form = { + name: "", + informasiUmum: { + fasilitas: "", + alamat: "", + jamOperasional: "", + }, + layananUnggulan: { + content: "", + }, + dokterdanTenagaMedis: { + name: "", + specialist: "", + jadwal: "", + }, + fasilitasPendukung: { + content: "", + }, + prosedurPendaftaran: { + content: "", + }, + tarifDanLayanan: { + layanan: "", + tarif: "", + }, + }; + }; + + + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + await stateFasilitasKesehatan.create.submit(); + + toast.success("Data berhasil disimpan"); + resetForm(); + // After successful submission, redirect to the list page + router.push('/admin/kesehatan/data-kesehatan-warga/fasilitas_kesehatan'); + } + + return ( + + + + + + + + Create Fasilitas Kesehatan + Nama Fasilitas Kesehatan} + placeholder="masukkan nama fasilitas kesehatan" + value={stateFasilitasKesehatan.create.form.name} + onChange={(e) => { + stateFasilitasKesehatan.create.form.name = e.target.value; + }} + /> + + Informasi Umum + Fasilitas} + placeholder="masukkan fasilitas" + value={stateFasilitasKesehatan.create.form.informasiUmum.fasilitas} + onChange={(e) => { + stateFasilitasKesehatan.create.form.informasiUmum.fasilitas = e.target.value; + }} + /> + Alamat} + placeholder="masukkan alamat" + value={stateFasilitasKesehatan.create.form.informasiUmum.alamat} + onChange={(e) => { + stateFasilitasKesehatan.create.form.informasiUmum.alamat = e.target.value; + }} + /> + Jam Operasional} + placeholder="masukkan jam operasional" + value={stateFasilitasKesehatan.create.form.informasiUmum.jamOperasional} + onChange={(e) => { + stateFasilitasKesehatan.create.form.informasiUmum.jamOperasional = e.target.value; + }} + /> + + + Layanan Unggulan + { + stateFasilitasKesehatan.create.form.layananUnggulan.content = e; + }} + /> + + + Dokter dan Tenaga Medis + Nama Dokter} + placeholder="masukkan nama dokter" + value={stateFasilitasKesehatan.create.form.dokterdanTenagaMedis.name} + onChange={(e) => { + stateFasilitasKesehatan.create.form.dokterdanTenagaMedis.name = e.target.value; + }} + /> + Specialist} + placeholder="masukkan specialist" + value={stateFasilitasKesehatan.create.form.dokterdanTenagaMedis.specialist} + onChange={(e) => { + stateFasilitasKesehatan.create.form.dokterdanTenagaMedis.specialist = e.target.value; + }} + /> + Jadwal} + placeholder="masukkan jadwal" + value={stateFasilitasKesehatan.create.form.dokterdanTenagaMedis.jadwal} + onChange={(e) => { + stateFasilitasKesehatan.create.form.dokterdanTenagaMedis.jadwal = e.target.value; + }} + /> + + + Fasilitas Pendukung + { + stateFasilitasKesehatan.create.form.fasilitasPendukung.content = e; + }} + /> + + + Prosedur Pendaftaran + { + stateFasilitasKesehatan.create.form.prosedurPendaftaran.content = e; + }} + /> + + + Tarif dan Layanan + Tarif} + placeholder="masukkan tarif" + value={stateFasilitasKesehatan.create.form.tarifDanLayanan.tarif} + onChange={(e) => { + stateFasilitasKesehatan.create.form.tarifDanLayanan.tarif = e.target.value; + }} + /> + Layanan} + placeholder="masukkan layanan" + value={stateFasilitasKesehatan.create.form.tarifDanLayanan.layanan} + onChange={(e) => { + stateFasilitasKesehatan.create.form.tarifDanLayanan.layanan = e.target.value; + }} + /> + + + + + + + ); +} + +export default CreateFasilitasKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/page.tsx new file mode 100644 index 00000000..fecd5925 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/page.tsx @@ -0,0 +1,81 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import fasilitasKesehatanState from '../../../_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan'; +import HeaderSearch from '../../../_com/header'; +import JudulList from '../../../_com/judulList'; + + +function FasilitasKesehatan() { + return ( + + } + /> + + + ); +} + +function ListFasilitasKesehatan() { + const stateFasilitasKesehatan = useProxy(fasilitasKesehatanState) + const router = useRouter(); + + useShallowEffect(() => { + stateFasilitasKesehatan.findMany.load() + }, []) + + if (!stateFasilitasKesehatan.findMany.data) { + return ( + + + + ) + } + return ( + + + + + + + + + Fasilitas Kesehatan + Alamat + Jam Operasional + Detail + + + + {stateFasilitasKesehatan.findMany.data?.map((item) => ( + + {item.name} + {item.informasiumum.alamat} + {item.informasiumum.jamOperasional} + + + + + ))} + +
+
+
+
+
+ ) +} + +export default FasilitasKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/[uuid]/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/[uuid]/page.tsx new file mode 100644 index 00000000..39133915 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/[uuid]/page.tsx @@ -0,0 +1,80 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' + +import grafikkepuasan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan'; +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect } from 'react'; +import { useProxy } from 'valtio/utils'; + +function EditGrafikHasilKepuasan() { + const router = useRouter() + const params = useParams() as { uuid: string } + const stateGrafikKepuasan = useProxy(grafikkepuasan) + + const uuid = params.uuid + + // Load data saat komponen mount + useEffect(() => { + if (uuid) { + stateGrafikKepuasan.findUnique.load(uuid).then(() => { + const data = stateGrafikKepuasan.findUnique.data + if (data) { + stateGrafikKepuasan.update.form = { + label: data.label || '', + jumlah: data.jumlah || '', + } + } + }) + } + }, [uuid]) + + const handleSubmit = async () => { + // Set the ID before submitting + stateGrafikKepuasan.update.uuid = uuid; + await stateGrafikKepuasan.update.submit(); + router.push('/admin/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan') + } +return ( + + + + + + + Edit Grafik Hasil Kepuasan + { + stateGrafikKepuasan.update.form.label = val.currentTarget.value; + }} + /> + { + stateGrafikKepuasan.update.form.jumlah = val.currentTarget.value; + }} + /> + + + + + ) +} + +export default EditGrafikHasilKepuasan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/create/page.tsx new file mode 100644 index 00000000..497f62ba --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/create/page.tsx @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +'use client' +import grafikkepuasan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +function CreateGrafikHasilKepuasanMasyarakat() { + const stateGrafikKepuasan = useProxy(grafikkepuasan); + const [chartData, setChartData] = useState([]); + const router = useRouter() + + const resetForm = () => { + stateGrafikKepuasan.create.form = { + label: "", + jumlah: "", + } + } + + const handleSubmit = async () => { + const id = await stateGrafikKepuasan.create.create(); + if (id) { + const idStr = String(id); + await stateGrafikKepuasan.findUnique.load(idStr); + if (stateGrafikKepuasan.findUnique.data) { + setChartData([stateGrafikKepuasan.findUnique.data]); + } + } + resetForm(); + router.push("/admin/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan"); + } + return ( + + + + + + + Tambah Grafik Hasil Kepuasan Masyarakat + + { + stateGrafikKepuasan.create.form.label = val.currentTarget.value; + }} + /> + { + stateGrafikKepuasan.create.form.jumlah = val.currentTarget.value; + }} + /> + + + + + + + + ); +} + +export default CreateGrafikHasilKepuasanMasyarakat; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/page.tsx new file mode 100644 index 00000000..7ef36104 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan/page.tsx @@ -0,0 +1,148 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core'; +import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; +import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts'; +import { useProxy } from 'valtio/utils'; +import JudulListTab from '../../../_com/jusulListTab'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; +import grafikkepuasan from '../../../_state/kesehatan/data_kesehatan_warga/grafikKepuasan'; + +function GrafikHasilKepuasanMasyarakat() { + type PDKMGrafik = { + id: string; + label: string; + jumlah: number; + } + const stateGrafikKepuasan = useProxy(grafikkepuasan); + const [chartData, setChartData] = useState([]); + const [mounted, setMounted] = useState(false); // untuk memastikan DOM sudah ready + const isTablet = useMediaQuery('(max-width: 1024px)') + const isMobile = useMediaQuery('(max-width: 768px)') + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const router = useRouter(); + + const handleDelete = () => { + if (selectedId) { + stateGrafikKepuasan.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + + stateGrafikKepuasan.findMany.load() + } + } + + useShallowEffect(() => { + setMounted(true) + stateGrafikKepuasan.findMany.load() + }, []) + + useEffect(() => { + setMounted(true); + if (stateGrafikKepuasan.findMany.data) { + setChartData(stateGrafikKepuasan.findMany.data.map((item) => ({ + id: item.uuid, + label: item.label, + jumlah: Number(item.jumlah), + }))); + } + }, [stateGrafikKepuasan.findMany.data]); + + if (!stateGrafikKepuasan.findMany.data) { + return ( + + + + ) + } + + return ( + + + {/* Form Input */} + + } + /> + + + + Label + Jumlah + Edit + Delete + + + + {stateGrafikKepuasan.findMany.data?.map((item) => ( + + {item.label} + {item.jumlah} + + + + + + + + ))} + +
+
+ + + {/* Chart */} + {!mounted && !chartData ? ( + + + Grafik Hasil Kepuasan Masyarakat + Belum ada data untuk ditampilkan dalam grafik + + + ) : ( + + + Grafik Hasil Kepuasan Masyarakat + {mounted && chartData.length > 0 && ( + + + + + + + + )} + + + )} +
+ + {/* Modal Konfirmasi Hapus */} + setModalHapus(false)} + onConfirm={handleDelete} + text='Apakah anda yakin ingin menghapus grafik hasil kepuasan masyarakat ini?' + /> +
+ ); +} + +export default GrafikHasilKepuasanMasyarakat; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/deskripsi_kegiatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/deskripsi_kegiatan/page.tsx similarity index 91% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/deskripsi_kegiatan/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/deskripsi_kegiatan/page.tsx index f9800287..01016aa5 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/deskripsi_kegiatan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/deskripsi_kegiatan/page.tsx @@ -1,8 +1,9 @@ +'use client' import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan'; +import colors from '@/con/colors'; import { Box, Paper, Stack, Text } from '@mantine/core'; import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; function DeskripsiKegiatan() { const deskripsiKegiatanState = useProxy(stateJadwalKegiatan.deskripsiKegiatan) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/dokumen_yang_diperlukan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/dokumen_yang_diperlukan/page.tsx similarity index 91% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/dokumen_yang_diperlukan/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/dokumen_yang_diperlukan/page.tsx index 4593215e..0576e07b 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/dokumen_yang_diperlukan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/dokumen_yang_diperlukan/page.tsx @@ -1,8 +1,9 @@ +'use client' import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan'; +import colors from '@/con/colors'; import { Box, Paper, Stack, Text } from '@mantine/core'; import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; function DokumenYangDiperlukan() { const dokumenDiperlukan = useProxy(stateJadwalKegiatan.dokumenjadwalkegiatan) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/informasi_kegiatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/informasi_kegiatan/page.tsx similarity index 99% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/informasi_kegiatan/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/informasi_kegiatan/page.tsx index ea6429c5..88cab315 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/informasi_kegiatan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/informasi_kegiatan/page.tsx @@ -1,3 +1,4 @@ +'use client' import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan'; import colors from '@/con/colors'; import { Box, Paper, Stack, TextInput, Title } from '@mantine/core'; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/layanan_yang_tersedia/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/layanan_yang_tersedia/page.tsx similarity index 91% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/layanan_yang_tersedia/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/layanan_yang_tersedia/page.tsx index c324079a..bcca180f 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/layanan_yang_tersedia/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/layanan_yang_tersedia/page.tsx @@ -1,8 +1,9 @@ +'use client' import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan'; +import colors from '@/con/colors'; import { Box, Paper, Stack, Text } from '@mantine/core'; import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; function LayananTersedia() { const layananTersediaState = useProxy(stateJadwalKegiatan.layanantersedia) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/page.tsx similarity index 100% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/page.tsx diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/pendaftaran/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/pendaftaran/page.tsx similarity index 100% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/pendaftaran/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/pendaftaran/page.tsx diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/syarat_dan_ketentuan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/syarat_dan_ketentuan/page.tsx similarity index 91% rename from src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/syarat_dan_ketentuan/page.tsx rename to src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/syarat_dan_ketentuan/page.tsx index dc2757fe..efda060a 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/_ui/jadwal_kegiatan/syarat_dan_ketentuan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/jadwal_kegiatan/syarat_dan_ketentuan/page.tsx @@ -1,8 +1,9 @@ -import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan'; +'use client' +import colors from '@/con/colors'; import { Box, Paper, Stack, Text } from '@mantine/core'; import { useProxy } from 'valtio/utils'; -import { KesehatanEditor } from '../../../_com/kesehatanEditor'; -import colors from '@/con/colors'; +import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan'; function SyaratDanKetentuan() { const syaratKetentuan = useProxy(stateJadwalKegiatan.syaratketentuan) diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/layout.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/layout.tsx new file mode 100644 index 00000000..9ebad0e4 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/layout.tsx @@ -0,0 +1,12 @@ +'use client' + +import LayoutTabs from "./_lib/layoutTabs" + + +export default function Layout({children} : {children: React.ReactNode}) { + return ( + + {children} + + ) +} \ No newline at end of file diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/page.tsx deleted file mode 100644 index 0f5a0f45..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/page.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import colors from '@/con/colors'; -import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core'; -import ArtikelKesehatan from './_ui/artikel_kesehatan/page'; -import FasilitasKesehatan from './_ui/fasilitas_kesehatan/page'; -import GrafikHasilKepuasan from './_ui/grafik_hasil_kepuasan/page'; -import JadwalKegiatan from './_ui/jadwal_kegiatan/page'; -import PersentaseDataKelahiranKematian from './_ui/persentase_data_kelahiran_kematian/page'; - - -function Page() { - return ( - - Data Kesehatan Warga - - - - Persentase Kelahiran & Kematian - - - Grafik Hasil Kepuasan - - - Fasilitas Kesehatan - - - Jadwal Kegiatan - - - Artikel Kesehatan - - - - - - - - - - - - - - - - - - - - - - ); -} - -export default Page; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/[uuid]/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/[uuid]/page.tsx new file mode 100644 index 00000000..725af4e6 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/[uuid]/page.tsx @@ -0,0 +1,114 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' + +import persentasekelahiran from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + +function EditPersentaseDataKelahiranKematian() { + const router = useRouter() + const params = useParams() as { uuid: string } + const statePresentase = useProxy(persentasekelahiran) + + const id = params.uuid + + // Load data saat komponen mount +// Di file page.tsx, ubah useEffect-nya menjadi: +useEffect(() => { + if (!id) return; + statePresentase.update.uuid = id; + statePresentase.findUnique.load(id) + .then(() => { + const data = statePresentase.findUnique.data; + if (data) { + statePresentase.update.form = { + tahun: String(data.tahun || ''), + kematianKasar: String(data.kematianKasar || ''), + kelahiranKasar: String(data.kelahiranKasar || ''), + kematianBayi: String(data.kematianBayi || '') + }; + } + }) + .catch(error => { + console.error('Error loading data:', error); + toast.error('Gagal memuat data'); + }); +}, [id]); + +// Di handleSubmit, ubah menjadi: +const handleSubmit = async () => { + try { + statePresentase.update.uuid = id; + await statePresentase.update.submit(); + toast.success('Data berhasil diperbarui'); + router.push('/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian'); + } catch (error) { + console.error('Error updating data:', error); + toast.error('Gagal memperbarui data'); + } +}; + + return ( + + + + + + + Edit Persentase Data Kelahiran & Kematian + { + statePresentase.update.form.tahun = val.currentTarget.value; + }} + /> + { + statePresentase.update.form.kematianKasar = val.currentTarget.value; + }} + /> + { + statePresentase.update.form.kematianBayi = val.currentTarget.value; + }} + /> + { + statePresentase.update.form.kelahiranKasar = val.currentTarget.value; + }} + /> + + + + + ) +} + +export default EditPersentaseDataKelahiranKematian; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/create/page.tsx new file mode 100644 index 00000000..2df71d8b --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/create/page.tsx @@ -0,0 +1,101 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +'use client' +import persentasekelahiran from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +function CreatePersentaseDataKelahiranKematian() { + const statePersentase = useProxy(persentasekelahiran); + const [chartData, setChartData] = useState([]); + const router = useRouter() + + const resetForm = () => { + statePersentase.create.form = { + tahun: "", + kematianBayi: "", + kematianKasar: "", + kelahiranKasar: "", + } + } + + const handleSubmit = async () => { + const id = await statePersentase.create.create(); + if (id) { + const idStr = String(id); + await statePersentase.findUnique.load(idStr); + if (statePersentase.findUnique.data) { + setChartData([statePersentase.findUnique.data]); + } + } + resetForm(); + router.push("/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian"); + } + return ( + + + + + + + Tambah Persentase Data Kelahiran & Kematian + + { + statePersentase.create.form.tahun = val.currentTarget.value; + }} + /> + { + statePersentase.create.form.kematianKasar = val.currentTarget.value; + }} + /> + { + statePersentase.create.form.kematianBayi = val.currentTarget.value; + }} + /> + { + statePersentase.create.form.kelahiranKasar = val.currentTarget.value; + }} + /> + + + + + + + + ); +} + +export default CreatePersentaseDataKelahiranKematian; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/page.tsx new file mode 100644 index 00000000..137296d1 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/page.tsx @@ -0,0 +1,158 @@ +'use client' +import persentasekelahiran from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; +import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core'; +import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; +import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts'; +import { useProxy } from 'valtio/utils'; +import JudulListTab from '../../../_com/jusulListTab'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; + +function PersentaseDataKelahiranKematian() { + type PDKMGrafik = { + uuid: string; + tahun: string; + kematianKasar: number; + kematianBayi: number; + kelahiranKasar: number; + } + const statePersentase = useProxy(persentasekelahiran); + const [chartData, setChartData] = useState([]); + const [mounted, setMounted] = useState(false); // untuk memastikan DOM sudah ready + const isTablet = useMediaQuery('(max-width: 1024px)') + const isMobile = useMediaQuery('(max-width: 768px)') + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const router = useRouter(); + + const handleDelete = () => { + if (selectedId) { + statePersentase.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + + statePersentase.findMany.load() + } + } + + useShallowEffect(() => { + setMounted(true) + statePersentase.findMany.load() + }, []) + + useEffect(() => { + setMounted(true); + if (statePersentase.findMany.data) { + setChartData(statePersentase.findMany.data.map((item) => ({ + uuid: item.uuid, + tahun: item.tahun, + kematianKasar: Number(item.kematianKasar), + kematianBayi: Number(item.kematianBayi), + kelahiranKasar: Number(item.kelahiranKasar), + }))); + } + }, [statePersentase.findMany.data]); + + if (!statePersentase.findMany.data) { + return ( + + + + ) + } + + return ( + + + {/* Form Input */} + + } + /> + + + + Tahun + Kematian Kasar + Kematian Bayi + kelahiran Kasar + Edit + Delete + + + + {statePersentase.findMany.data?.map((item) => ( + + {item.tahun} + {item.kematianKasar} + {item.kematianBayi} + {item.kelahiranKasar} + + + + + + + + ))} + +
+
+ + + {/* Chart */} + {!mounted && !chartData ? ( + + + Data Kelahiran & Kematian + Belum ada data untuk ditampilkan dalam grafik + + + ) : ( + + + Data Kelahiran & Kematian + {mounted && chartData.length > 0 && ( + + + + + + + + + + )} + + + )} +
+ + {/* Modal Konfirmasi Hapus */} + setModalHapus(false)} + onConfirm={handleDelete} + text='Apakah anda yakin ingin menghapus persentase data kelahiran & kematian ini?' + /> +
+ ); +} + +export default PersentaseDataKelahiranKematian; diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/edit/page.tsx new file mode 100644 index 00000000..a69c05fc --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/edit/page.tsx @@ -0,0 +1,150 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import infoWabahPenyakit from '@/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit'; +import colors from '@/con/colors'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + + +function EditInfoWabahPenyakit() { + const infoWabahPenyakitState = useProxy(infoWabahPenyakit) + const router = useRouter(); + const params = useParams() + + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [formData, setFormData] = useState({ + name: infoWabahPenyakitState.edit.form.name || '', + deskripsiSingkat: infoWabahPenyakitState.edit.form.deskripsiSingkat || '', + deskripsi: infoWabahPenyakitState.edit.form.deskripsiLengkap || '', + imageId: infoWabahPenyakitState.edit.form.imageId || '', + }) + + useEffect(() => { + const loadInfoWabahPenyakit = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await infoWabahPenyakitState.edit.load(id); + if (data) { + setFormData({ + name: data.name || '', + deskripsiSingkat: data.deskripsiSingkat || '', + deskripsi: data.deskripsiLengkap || '', + imageId: data.imageId || '', + }); + + if (data?.image?.link) { + setPreviewImage(data.image.link); + } + } + } catch (error) { + console.error("Error loading program kesehatan:", error); + toast.error("Gagal memuat data program kesehatan"); + } + }; + + loadInfoWabahPenyakit(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + infoWabahPenyakitState.edit.form = { + ...infoWabahPenyakitState.edit.form, + name: formData.name, + deskripsiSingkat: formData.deskripsiSingkat, + deskripsiLengkap: formData.deskripsi, + imageId: formData.imageId, + }; + + if (file) { + const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = res.data?.data; + + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + infoWabahPenyakitState.edit.form.imageId = uploaded.id; + } + + await infoWabahPenyakitState.edit.update(); + toast.success("Info wabah penyakit berhasil diperbarui!"); + router.push("/admin/kesehatan/info-wabah-penyakit"); + } catch (error) { + console.error("Error updating info wabah penyakit:", error); + toast.error("Gagal memuat data info wabah penyakit"); + } + } + return ( + + + + + + + + Edit Info Wabah Penyakit + setFormData({ ...formData, name: e.target.value })} + label={Judul} + placeholder="masukkan judul" + /> + + setFormData({ ...formData, deskripsiSingkat: e.target.value })} + label={Deskripsi Singkat} + placeholder="masukkan deskripsi" + /> + + + Deskripsi + setFormData({ ...formData, deskripsi: val })} + /> + + + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + 'data:image/png;base64,' + Buffer.from(buf).toString('base64') + ); + setPreviewImage(base64); + }} + /> + + {previewImage ? ( + + ) : ( +
+ +
+ )} + + +
+
+
+
+ ); +} + +export default EditInfoWabahPenyakit; diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/page.tsx new file mode 100644 index 00000000..fc86ef6b --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/page.tsx @@ -0,0 +1,103 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Flex, Text, Image, Skeleton } from '@mantine/core'; +import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +import infoWabahPenyakit from '../../../_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit'; +import { useProxy } from 'valtio/utils'; +import { useShallowEffect } from '@mantine/hooks'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; + +function DetailInfoWabahPenyakit() { + const infoWabahPenyakitState = useProxy(infoWabahPenyakit) + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const router = useRouter(); + const params = useParams() + + useShallowEffect(() => { + infoWabahPenyakitState.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + infoWabahPenyakitState.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/info-wabah-penyakit") + } + } + + if (!infoWabahPenyakitState.findUnique.data) { + return ( + + + + ) + } + + return ( + + + + + + + Detail Info Wabah Penyakit + {infoWabahPenyakitState.findUnique.data ? ( + + + + Judul + {infoWabahPenyakitState.findUnique.data.name} + + + Deskripsi Singkat + {infoWabahPenyakitState.findUnique.data.deskripsiSingkat} + + + Deskripsi + + + + Gambar + gambar + + + + + + + + + + ) : null} + + + + {/* Modal Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus info wabah penyakit ini?" + /> + + ); +} + +export default DetailInfoWabahPenyakit; diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx index 56b212be..4fb3f039 100644 --- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx @@ -1,43 +1,101 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; -import { IconArrowBack } from '@tabler/icons-react'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import { useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; +import CreateEditor from '../../../_com/createEditor'; +import infoWabahPenyakit from '../../../_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit'; function CreateInfoWabahPenyakit() { const router = useRouter(); + const infoWabahPenyakitState = useProxy(infoWabahPenyakit) + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + + const resetForm = () => { + // Reset state di valtio + infoWabahPenyakitState.create.form = { + name: "", + deskripsiSingkat: "", + deskripsiLengkap: "", + imageId: "", + }; + + // Reset state lokal + setPreviewImage(null); + setFile(null); + }; + + const handleSubmit = async () => { + if (!file) { + return toast.warn("Pilih file gambar terlebih dahulu"); + } + + // Upload gambar dulu + const res = await ApiFetch.api.fileStorage.create.post({ + file, + name: file.name, + }); + + const uploaded = res.data?.data; + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + // Simpan ID gambar ke form + infoWabahPenyakitState.create.form.imageId = uploaded.id; + + // Submit data berita + await infoWabahPenyakitState.create.create(); + + // Reset form setelah submit + resetForm(); + router.push("/admin/kesehatan/info-wabah-penyakit") + }; + return ( - + - Create Info Wabah Penyakit - { + infoWabahPenyakitState.create.form.name = val.target.value; + }} label={Judul} placeholder="masukkan judul" /> Deskripsi} + value={infoWabahPenyakitState.create.form.deskripsiSingkat} + onChange={(val) => { + infoWabahPenyakitState.create.form.deskripsiSingkat = val.target.value; + }} + label={Deskripsi Singkat} placeholder="masukkan deskripsi" /> - Kategori} - placeholder="masukkan kategori" - /> + + Deskripsi + { + infoWabahPenyakitState.create.form.deskripsiLengkap = val; + }} + /> + - {/* Upload Gambar} value={file} onChange={async (e) => { @@ -48,25 +106,18 @@ function CreateInfoWabahPenyakit() { ); setPreviewImage(base64); }} - /> */} + /> - {/* {previewImage ? ( + {previewImage ? ( ) : (
- )} */} + )} - - Konten - - - -
diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/detail/page.tsx deleted file mode 100644 index 2b9163d5..00000000 --- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/detail/page.tsx +++ /dev/null @@ -1,70 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core'; -import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import React from 'react'; -// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; - -function DetailInfoWabahPenyakit() { - const router = useRouter(); - return ( - - - - - - - Detail Info Wabah/Penyakit - - - - - Nama Info Wabah/Penyakit - Test Judul - - - Deskripsi Info Wabah/Penyakit - Test Kategori - - - Deskripsi - Test Deskripsi - - - Gambar - gambar - - - Konten - Test Konten - - - - - - - - - - - - - {/* Modal Hapus - setModalHapus(false)} - onConfirm={handleHapus} - text="Apakah anda yakin ingin menghapus penanganan darurat ini?" - /> */} - - ); -} - -export default DetailInfoWabahPenyakit; diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/edit/page.tsx deleted file mode 100644 index 885ce912..00000000 --- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/edit/page.tsx +++ /dev/null @@ -1,62 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button, Image } from '@mantine/core'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; -import { IconArrowBack } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; - - -function EditInfoWabahPenyakit() { - const router = useRouter(); - return ( - - - - - - - - - - Edit Info Wabah/Penyakit - Nama Info Wabah/Penyakit} - placeholder='Masukkan nama Info Wabah/Penyakit' - /> - Deskripsi Info Wabah/Penyakit} - placeholder='Masukkan deskripsi Info Wabah/Penyakit' - /> - - Deskripsi - - - - Gambar - gambar - - - - - - - - Preview Data Info Wabah/Penyakit - Nama Info Wabah/Penyakit - Deskripsi Info Wabah/Penyakit - Deskripsi - Gambar - - - - - - - ); -} - -export default EditInfoWabahPenyakit; diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx index 9ce24e0f..92bc2ac6 100644 --- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx @@ -1,10 +1,13 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; +import { Box, Button, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; import JudulList from '../../_com/judulList'; import HeaderSearch from '../../_com/header'; import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import infoWabahPenyakit from '../../_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit'; +import { useShallowEffect } from '@mantine/hooks'; function InfoWabahPenyakit() { return ( @@ -20,7 +23,20 @@ function InfoWabahPenyakit() { } function ListInfoWabahPenyakit() { + const infoWabahPenyakitState = useProxy(infoWabahPenyakit) const router = useRouter() + + useShallowEffect(() => { + infoWabahPenyakitState.findMany.load() + }, []) + + if (!infoWabahPenyakitState.findMany.data) { + return ( + + + + ) + } return ( @@ -34,27 +50,32 @@ function ListInfoWabahPenyakit() { Judul - Kategori + Deskripsi Singkat Image Detail - - - - Test - - Test - - image - - - - - + {infoWabahPenyakitState.findMany.data?.map((item) => ( + + + + {item.name} + + + + {item.deskripsiSingkat} + + + image + + + + + + ))} diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/edit/page.tsx new file mode 100644 index 00000000..dea08402 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/edit/page.tsx @@ -0,0 +1,140 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import kontakDarurat from '@/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat'; +import colors from '@/con/colors'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + + + +function EditKontakDarurat() { + const kontakDaruratState = useProxy(kontakDarurat) + const router = useRouter(); + const params = useParams() + + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [formData, setFormData] = useState({ + name: kontakDaruratState.edit.form.name || '', + deskripsi: kontakDaruratState.edit.form.deskripsi || '', + imageId: kontakDaruratState.edit.form.imageId || '', + }) + + useEffect(() => { + const loadProgramKesehatan = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await kontakDaruratState.edit.load(id); + if (data) { + setFormData({ + name: data.name || '', + deskripsi: data.deskripsi || '', + imageId: data.imageId || '', + }); + + if (data?.image?.link) { + setPreviewImage(data.image.link); + } + } + } catch (error) { + console.error("Error loading program kesehatan:", error); + toast.error("Gagal memuat data program kesehatan"); + } + }; + + loadProgramKesehatan(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + kontakDaruratState.edit.form = { + ...kontakDaruratState.edit.form, + name: formData.name, + deskripsi: formData.deskripsi, + imageId: formData.imageId, + }; + + if (file) { + const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = res.data?.data; + + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + kontakDaruratState.edit.form.imageId = uploaded.id; + } + + await kontakDaruratState.edit.update(); + toast.success("Kontak darurat berhasil diperbarui!"); + router.push("/admin/kesehatan/kontak-darurat"); + } catch (error) { + console.error("Error updating kontak darurat:", error); + toast.error("Gagal memuat data kontak darurat"); + } + } + return ( + + + + + + + + Edit Kontak Darurat + setFormData({ ...formData, name: e.target.value })} + label={Judul} + placeholder="masukkan judul" + /> + + Deskripsi + setFormData({ ...formData, deskripsi: val })} + /> + + + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + 'data:image/png;base64,' + Buffer.from(buf).toString('base64') + ); + setPreviewImage(base64); + }} + /> + + {previewImage ? ( + + ) : ( +
+ +
+ )} + + +
+
+
+
+ ); +} + +export default EditKontakDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/page.tsx new file mode 100644 index 00000000..cec338fa --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/page.tsx @@ -0,0 +1,99 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Flex, Image, Paper, Skeleton, Stack, Text } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; +import kontakDarurat from '../../../_state/kesehatan/kontak-darurat/kontakDarurat'; + +function DetailKontakDarurat() { + const kontakDaruratState = useProxy(kontakDarurat) + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const router = useRouter(); + const params = useParams() + + useShallowEffect(() => { + kontakDaruratState.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + kontakDaruratState.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/kontak-darurat") + } + } + + if (!kontakDaruratState.findUnique.data) { + return ( + + + + ) + } + + return ( + + + + + + + Detail Kontak Darurat + {kontakDaruratState.findUnique.data ? ( + + + + Judul + {kontakDaruratState.findUnique.data.name} + + + Deskripsi + + + + Gambar + gambar + + + + + + + + + + ) : null} + + + + {/* Modal Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus kontak darurat ini?" + /> + + ); +} + +export default DetailKontakDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx index c9a9f0f3..ac55207c 100644 --- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx @@ -1,77 +1,113 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; -import { IconArrowBack } from '@tabler/icons-react'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import { useProxy } from 'valtio/utils'; +import kontakDarurat from '../../../_state/kesehatan/kontak-darurat/kontakDarurat'; +import { useState } from 'react'; +import { toast } from 'react-toastify'; +import ApiFetch from '@/lib/api-fetch'; +import CreateEditor from '../../../_com/createEditor'; + function CreateKontakDarurat() { - const router = useRouter(); - return ( - - - - - - - - Create Kontak Darurat - - Judul} - placeholder="masukkan judul" - /> - - Deskripsi} - placeholder="masukkan deskripsi" - /> - - Kategori} - placeholder="masukkan kategori" - /> - - {/* Upload Gambar} - value={file} - onChange={async (e) => { - if (!e) return; - setFile(e); - const base64 = await e.arrayBuffer().then((buf) => - 'data:image/png;base64,' + Buffer.from(buf).toString('base64') - ); - setPreviewImage(base64); - }} - /> */} - - {/* {previewImage ? ( - - ) : ( -
- -
- )} */} - - - Konten - - - - -
-
-
- ); +
+ + + + Create Kontak Darurat + + { + kontakDaruratState.create.form.name = val.target.value; + }} + label={Judul} + placeholder="masukkan judul" + /> + + + Deskripsi + { + kontakDaruratState.create.form.deskripsi = val; + }} + /> + + + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + 'data:image/png;base64,' + Buffer.from(buf).toString('base64') + ); + setPreviewImage(base64); + }} + /> + + {previewImage ? ( + + ) : ( +
+ +
+ )} + + +
+
+
+ ); } export default CreateKontakDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/detail/page.tsx deleted file mode 100644 index 7ed97108..00000000 --- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/detail/page.tsx +++ /dev/null @@ -1,70 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core'; -import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import React from 'react'; -// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; - -function DetailKontakDarurat() { - const router = useRouter(); - return ( - - - - - - - Detail Kontak Darurat - - - - - Nama Kontak Darurat - Test Judul - - - Deskripsi Kontak Darurat - Test Kategori - - - Deskripsi - Test Deskripsi - - - Gambar - gambar - - - Konten - Test Konten - - - - - - - - - - - - - {/* Modal Hapus - setModalHapus(false)} - onConfirm={handleHapus} - text="Apakah anda yakin ingin menghapus penanganan darurat ini?" - /> */} - - ); -} - -export default DetailKontakDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/edit/page.tsx deleted file mode 100644 index e7338470..00000000 --- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/edit/page.tsx +++ /dev/null @@ -1,62 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button, Image } from '@mantine/core'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; -import { IconArrowBack } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; - - -function EditKontakDarurat() { - const router = useRouter(); - return ( - - - - - - - - - - Edit Kontak Darurat - Nama Kontak Darurat} - placeholder='Masukkan nama Kontak Darurat' - /> - Deskripsi Kontak Darurat} - placeholder='Masukkan deskripsi Kontak Darurat' - /> - - Deskripsi - - - - Gambar - gambar - - - - - - - - Preview Data Kontak Darurat - Nama Kontak Darurat - Deskripsi Kontak Darurat - Deskripsi - Gambar - - - - - - - ); -} - -export default EditKontakDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx index 52168304..dae268f9 100644 --- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx @@ -1,66 +1,88 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; +import { Box, Button, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; import JudulList from '../../_com/judulList'; import HeaderSearch from '../../_com/header'; import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import kontakDarurat from '../../_state/kesehatan/kontak-darurat/kontakDarurat'; +import { useShallowEffect } from '@mantine/hooks'; function KontakDarurat() { return ( } /> - + ); } function ListKontakDarurat() { + const kontakDaruratState = useProxy(kontakDarurat) const router = useRouter(); + + useShallowEffect(() => { + kontakDaruratState.findMany.load() + }, []) + + if (!kontakDaruratState.findMany.data) { + return ( + + + + ) + } + return ( - - - - - - - - Judul - Kategori - Image - Detail - - - - - - - Test - - Test - - - - - - - - -
-
-
-
-
+ + + + + + + + Judul + Deskripsi + Image + Detail + + + + {kontakDaruratState.findMany.data?.map((item) => ( + + + + {item.name} + + + + + + + + + + + + + ))} + +
+
+
+
+ ) } diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/[id]/edit/page.tsx new file mode 100644 index 00000000..3f1c5019 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/[id]/edit/page.tsx @@ -0,0 +1,140 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat'; +import colors from '@/con/colors'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + +function EditPenangananDarurat() { + const penangananDaruratState = useProxy(penangananDarurat) + const router = useRouter(); + const params = useParams() + + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [formData, setFormData] = useState({ + name: penangananDaruratState.edit.form.name || '', + deskripsi: penangananDaruratState.edit.form.deskripsi || '', + imageId: penangananDaruratState.edit.form.imageId || '', + }) + + useEffect(() => { + const loadPenangananDarurat = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await penangananDaruratState.edit.load(id); + if (data) { + setFormData({ + name: data.name || '', + deskripsi: data.deskripsi || '', + imageId: data.imageId || '', + }) + + if (data?.image?.link) { + setPreviewImage(data.image.link); + } + } + } catch (error) { + console.error('Error loading penanganan darurat:', error); + toast.error('Gagal memuat data penanganan darurat'); + } + } + + loadPenangananDarurat(); + }, [params?.id]) + + const handleSubmit = async () => { + try { + penangananDaruratState.edit.form = { + ...penangananDaruratState.edit.form, + name: formData.name, + deskripsi: formData.deskripsi, + imageId: formData.imageId, + } + + if (file) { + const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = res.data?.data; + + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + penangananDaruratState.edit.form.imageId = uploaded.id; + } + + await penangananDaruratState.edit.update(); + toast.success("Penanganan darurat berhasil diperbarui!"); + router.push("/admin/kesehatan/penanganan-darurat"); + } catch (error) { + console.error("Error updating penanganan darurat:", error); + toast.error("Gagal memuat data penanganan darurat"); + } + } + return ( + + + + + + + + Edit Penanganan Darurat + + setFormData({ ...formData, name: e.target.value })} + label={Judul} + placeholder="masukkan judul" + /> + + + Deskripsi + setFormData({ ...formData, deskripsi: val })} + /> + + + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + 'data:image/png;base64,' + Buffer.from(buf).toString('base64') + ); + setPreviewImage(base64); + }} + /> + + {previewImage ? ( + + ) : ( +
+ +
+ )} + + +
+
+
+
+ ); +} + +export default EditPenangananDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/[id]/page.tsx new file mode 100644 index 00000000..46615005 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/[id]/page.tsx @@ -0,0 +1,101 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core'; +import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; +import penangananDarurat from '../../../_state/kesehatan/penanganan-darurat/penangananDarurat'; +import { useProxy } from 'valtio/utils'; +import { useShallowEffect } from '@mantine/hooks'; +import { useParams } from 'next/navigation'; +import { Skeleton } from '@mantine/core'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; + +function DetailPenangananDarurat() { + const penangananDaruratState = useProxy(penangananDarurat) + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const router = useRouter(); + const params = useParams() + + useShallowEffect(() => { + penangananDaruratState.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + penangananDaruratState.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/penanganan-darurat") + } + } + + if (!penangananDaruratState.findUnique.data) { + return ( + + + + ) + } + + return ( + + + + + + + Detail Penanganan Darurat + {penangananDaruratState.findUnique.data ? ( + + + + Nama Penanganan Darurat + {penangananDaruratState.findUnique.data.name} + + + Deskripsi + + + + Gambar + gambar + + + + + + + + + + ) : null} + + + + {/* Modal Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus penanganan darurat ini?" + /> + + ); +} + +export default DetailPenangananDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/create/page.tsx index 8397049b..2c972d9b 100644 --- a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/create/page.tsx @@ -1,14 +1,56 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; -import { IconArrowBack } from '@tabler/icons-react'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import { useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; +import CreateEditor from '../../../_com/createEditor'; +import penangananDarurat from '../../../_state/kesehatan/penanganan-darurat/penangananDarurat'; + function CreatePenangananDarurat() { const router = useRouter(); + const penangananDaruratState = useProxy(penangananDarurat) + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + + const resetForm = () => { + penangananDaruratState.create.form = { + name: "", + deskripsi: "", + imageId: "", + }; + setPreviewImage(null); + setFile(null); + }; + + const handleSubmit = async () => { + if (!file) { + return toast.warn("Pilih file gambar terlebih dahulu"); + } + + const res = await ApiFetch.api.fileStorage.create.post({ + file, + name: file.name, + }); + + const uploaded = res.data?.data; + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + penangananDaruratState.create.form.imageId = uploaded.id; + + await penangananDaruratState.create.create(); + + resetForm(); + router.push("/admin/kesehatan/penanganan-darurat") + } return ( - + + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + 'data:image/png;base64,' + Buffer.from(buf).toString('base64') + ); + setPreviewImage(base64); + }} + /> + + {previewImage ? ( + + ) : ( +
+ +
+ )} + +
diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/detail/page.tsx deleted file mode 100644 index 847728db..00000000 --- a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/detail/page.tsx +++ /dev/null @@ -1,70 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core'; -import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import React from 'react'; -// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; - -function DetailPenangananDarurat() { - const router = useRouter(); - return ( - - - - - - - Detail Penanganan Darurat - - - - - Nama Penanganan Darurat - Test Judul - - - Deskripsi Penanganan Darurat - Test Kategori - - - Deskripsi - Test Deskripsi - - - Gambar - gambar - - - Konten - Test Konten - - - - - - - - - - - - - {/* Modal Hapus - setModalHapus(false)} - onConfirm={handleHapus} - text="Apakah anda yakin ingin menghapus penanganan darurat ini?" - /> */} - - ); -} - -export default DetailPenangananDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/edit/page.tsx deleted file mode 100644 index 68539b65..00000000 --- a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/edit/page.tsx +++ /dev/null @@ -1,62 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button, Image } from '@mantine/core'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; -import { IconArrowBack } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; - - -function EditPenangananDarurat() { - const router = useRouter(); - return ( - - - - - - - - - - Edit Penanganan Darurat - Nama Penanganan Darurat} - placeholder='Masukkan nama Penanganan Darurat' - /> - Deskripsi Penanganan Darurat} - placeholder='Masukkan deskripsi Penanganan Darurat' - /> - - Deskripsi - - - - Gambar - gambar - - - - - - - - Preview Data Penanganan Darurat - Nama Penanganan Darurat - No Telp Penanganan Darurat - Deskripsi - Pelayanan Posyandu - - - - - - - ); -} - -export default EditPenangananDarurat; diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx index 714ac745..4468840c 100644 --- a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx @@ -1,10 +1,14 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; +import { Box, Button, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; import JudulList from '../../_com/judulList'; import HeaderSearch from '../../_com/header'; import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import { useShallowEffect } from '@mantine/hooks'; +import penangananDarurat from '../../_state/kesehatan/penanganan-darurat/penangananDarurat'; + function PenangananDarurat() { return ( @@ -20,7 +24,21 @@ function PenangananDarurat() { } function ListPenangananDarurat() { + const penangananDaruratState = useProxy(penangananDarurat) const router = useRouter(); + + useShallowEffect(() => { + penangananDaruratState.findMany.load() + }, []) + + if (!penangananDaruratState.findMany.data) { + return ( + + + + ) + } + return ( @@ -34,27 +52,31 @@ function ListPenangananDarurat() { Judul - Kategori + Deskripsi Image Detail - + {penangananDaruratState.findMany.data?.map((item) => ( + - Test + {item.name} - Test - image + - + ))} diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/[id]/edit/page.tsx new file mode 100644 index 00000000..192f363a --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/posyandu/[id]/edit/page.tsx @@ -0,0 +1,147 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import posyandustate from '@/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu'; +import colors from '@/con/colors'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + + +function EditPosyandu() { + const statePosyandu = useProxy(posyandustate) + const router = useRouter(); + const params = useParams() + + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [formData, setFormData] = useState({ + name: statePosyandu.edit.form.name || '', + nomor: statePosyandu.edit.form.nomor || '', + deskripsi: statePosyandu.edit.form.deskripsi || '', + imageId: statePosyandu.edit.form.imageId || '', + }); + + useEffect(() => { + const loadPosyandu = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await statePosyandu.edit.load(id); + if (data) { + setFormData({ + name: data.name || '', + nomor: data.nomor || '', + deskripsi: data.deskripsi || '', + imageId: data.imageId || '', + }); + + if (data?.image?.link) { + setPreviewImage(data.image.link); + } + } + } catch (error) { + console.error("Error loading posyandu:", error); + toast.error("Gagal memuat data posyandu"); + } + } + loadPosyandu(); + }, [params?.id]) + + const handleSubmit = async () => { + try { + statePosyandu.edit.form = { + ...statePosyandu.edit.form, + name: formData.name, + nomor: formData.nomor, + deskripsi: formData.deskripsi, + imageId: formData.imageId, + } + + if (file) { + const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = res.data?.data; + + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + statePosyandu.edit.form.imageId = uploaded.id; + } + + await statePosyandu.edit.update(); + toast.success("Posyandu berhasil diperbarui!"); + router.push("/admin/kesehatan/posyandu"); + } catch (error) { + console.error("Error updating posyandu:", error); + toast.error("Gagal memuat data posyandu"); + } + } + + return ( + + + + + + + + Edit Posyandu + {previewImage ? ( + + ) : ( +
+ +
+ )} + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + "data:image/png;base64," + Buffer.from(buf).toString("base64") + ); + setPreviewImage(base64); + }} + /> + setFormData({ ...formData, name: e.target.value })} + label={Nama Posyandu} + placeholder='Masukkan nama posyandu' + /> + setFormData({ ...formData, nomor: e.target.value })} + label={Nomor Posyandu} + placeholder='Masukkan nomor posyandu' + /> + + Deskripsi Posyandu + { + setFormData({ ...formData, deskripsi: htmlContent }); + statePosyandu.edit.form.deskripsi = htmlContent; + }} + /> + + + + +
+
+
+ ); +} + +export default EditPosyandu; diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/[id]/page.tsx new file mode 100644 index 00000000..415a17c4 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/posyandu/[id]/page.tsx @@ -0,0 +1,101 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Flex, Text, Image, Skeleton } from '@mantine/core'; +import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +import { useProxy } from 'valtio/utils'; +import posyandustate from '../../../_state/kesehatan/posyandu/posyandu'; +import { useShallowEffect } from '@mantine/hooks'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; +// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; + +function DetailPosyandu() { + const statePosyandu = useProxy(posyandustate) + const params = useParams() + const router = useRouter(); + const [modalHapus, setModalHapus] = useState(false); + const [selectedId, setSelectedId] = useState(null) + + useShallowEffect(() => { + statePosyandu.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + statePosyandu.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/posyandu") + } + } + + if (!statePosyandu.findUnique.data) { + return ( + + + + ) + } + + return ( + + + + + + + Detail Posyandu + {statePosyandu.findUnique.data ? ( + + + + Nama Posyandu + {statePosyandu.findUnique.data.name} + + + Nomor Posyandu + {statePosyandu.findUnique.data.nomor} + + + Deskripsi Posyandu + + + + Gambar + gambar + + + + + + + + + + ) : null} + + + + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus posyandu ini?" + /> + + ); +} + +export default DetailPosyandu; diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx index 6060f701..f0c09ea7 100644 --- a/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx @@ -1,13 +1,59 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; -import React from 'react'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import { useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; +import CreateEditor from '../../../_com/createEditor'; +import posyandustate from '../../../_state/kesehatan/posyandu/posyandu'; function CreatePosyandu() { + const statePosyandu = useProxy(posyandustate) const router = useRouter(); + const [file, setFile] = useState(null); + const [previewImage, setPreviewImage] = useState(null); + + const resetForm = () => { + statePosyandu.create.form = { + name: "", + nomor: "", + deskripsi: "", + imageId: "", + }; + + setFile(null); + setPreviewImage(null); + } + + const handleSubmit = async () => { + if (!file) { + return toast.warn("Pilih file gambar terlebih dahulu"); + } + + // Upload gambar dulu + const res = await ApiFetch.api.fileStorage.create.post({ + file, + name: file.name, + }); + + const uploaded = res.data?.data; + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + statePosyandu.create.form.imageId = uploaded.id; + + await statePosyandu.create.create(); + + resetForm(); + router.push("/admin/kesehatan/posyandu") + } + + + return ( @@ -19,26 +65,52 @@ function CreatePosyandu() { Create Posyandu - - Masukkan Image - - + {previewImage ? ( + + ) : ( +
+ +
+ )} + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + "data:image/png;base64," + Buffer.from(buf).toString("base64") + ); + setPreviewImage(base64); + }} + /> Nama Posyandu} placeholder='Masukkan nama posyandu' + value={statePosyandu.create.form.name} + onChange={(e) => { + statePosyandu.create.form.name = e.target.value; + }} /> Nomor Posyandu} placeholder='Masukkan nomor posyandu' + value={statePosyandu.create.form.nomor} + onChange={(e) => { + statePosyandu.create.form.nomor = e.target.value; + }} /> Deskripsi Posyandu - { + statePosyandu.create.form.deskripsi = htmlContent; + }} /> - +
diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/detail/page.tsx deleted file mode 100644 index ec649457..00000000 --- a/src/app/admin/(dashboard)/kesehatan/posyandu/detail/page.tsx +++ /dev/null @@ -1,66 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core'; -import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import React from 'react'; -// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; - -function DetailPosyandu() { - const router = useRouter(); - return ( - - - - - - - Detail Posyandu - - - - - Nama Posyandu - Test Judul - - - Nomor Posyandu - 089647038426 - - - Deskripsi Posyandu - Test Kategori - - - Gambar - gambar - - - - - - - - - - - - - {/* Modal Hapus - setModalHapus(false)} - onConfirm={handleHapus} - text="Apakah anda yakin ingin menghapus penanganan darurat ini?" - /> */} - - ); -} - -export default DetailPosyandu; diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/edit/page.tsx deleted file mode 100644 index 5ecb68d2..00000000 --- a/src/app/admin/(dashboard)/kesehatan/posyandu/edit/page.tsx +++ /dev/null @@ -1,49 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; -import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import React from 'react'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; - -function EditPosyandu() { - const router = useRouter(); - return ( - - - - - - - - Edit Posyandu - - Masukkan Image - - - Nama Posyandu} - placeholder='Masukkan nama posyandu' - /> - Nomor Posyandu} - placeholder='Masukkan nomor posyandu' - /> - - Deskripsi Posyandu - - - - - - - - - ); -} - -export default EditPosyandu; diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx index b6c17360..f25f694f 100644 --- a/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx @@ -1,10 +1,13 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core'; +import { Box, Button, Paper, Skeleton, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; import { IconDeviceImac, IconSearch } from '@tabler/icons-react'; import HeaderSearch from '../../_com/header'; import JudulList from '../../_com/judulList'; import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import posyandustate from '../../_state/kesehatan/posyandu/posyandu'; +import { useShallowEffect } from '@mantine/hooks'; function Posyandu() { return ( @@ -14,13 +17,27 @@ function Posyandu() { placeholder='pencarian' searchIcon={} /> - +
); } function ListPosyandu() { + const statePosyandu = useProxy(posyandustate) const router = useRouter(); + + useShallowEffect(() => { + statePosyandu.findMany.load() + }, []) + + if (!statePosyandu.findMany.data) { + return ( + + + + ) + } + return ( @@ -28,28 +45,34 @@ function ListPosyandu() { title='List Posyandu' href='/admin/kesehatan/posyandu/create' /> - - - - Nama Posyandu - Nomor Posyandu - Deskripsi - Detail + +
+ + + Nama Posyandu + Nomor Posyandu + Deskripsi + Detail - - - - Posyandu 1 - 0896232831883 - Posyandu 1 - - - - - -
+ + + {statePosyandu.findMany.data?.map((item) => ( + + {item.name} + {item.nomor} + + + + + + + + ))} + + +
); diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/edit/page.tsx new file mode 100644 index 00000000..4f4e527e --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/edit/page.tsx @@ -0,0 +1,150 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import programKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan'; +import colors from '@/con/colors'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + + +function EditProgramKesehatan() { + const programKesehatanState = useProxy(programKesehatan) + const router = useRouter(); + const params = useParams() + + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [formData, setFormData] = useState({ + name: programKesehatanState.edit.form.name || '', + deskripsiSingkat: programKesehatanState.edit.form.deskripsiSingkat || '', + deskripsi: programKesehatanState.edit.form.deskripsi || '', + imageId: programKesehatanState.edit.form.imageId || '', + }) + + useEffect(() => { + const loadProgramKesehatan = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await programKesehatanState.edit.load(id); + if (data) { + setFormData({ + name: data.name || '', + deskripsiSingkat: data.deskripsiSingkat || '', + deskripsi: data.deskripsi || '', + imageId: data.imageId || '', + }); + + if (data?.image?.link) { + setPreviewImage(data.image.link); + } + } + } catch (error) { + console.error("Error loading program kesehatan:", error); + toast.error("Gagal memuat data program kesehatan"); + } + }; + + loadProgramKesehatan(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + programKesehatanState.edit.form = { + ...programKesehatanState.edit.form, + name: formData.name, + deskripsiSingkat: formData.deskripsiSingkat, + deskripsi: formData.deskripsi, + imageId: formData.imageId, + }; + + if (file) { + const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = res.data?.data; + + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + programKesehatanState.edit.form.imageId = uploaded.id; + } + + await programKesehatanState.edit.update(); + toast.success("Program kesehatan berhasil diperbarui!"); + router.push("/admin/kesehatan/program-kesehatan"); + } catch (error) { + console.error("Error updating program kesehatan:", error); + toast.error("Gagal memuat data program kesehatan"); + } + } + return ( + + + + + + + + Edit Program Kesehatan + setFormData({ ...formData, name: e.target.value })} + label={Judul} + placeholder="masukkan judul" + /> + + setFormData({ ...formData, deskripsiSingkat: e.target.value })} + label={Deskripsi Singkat} + placeholder="masukkan deskripsi" + /> + + + Deskripsi + setFormData({ ...formData, deskripsi: val })} + /> + + + Upload Gambar} + value={file} + onChange={async (e) => { + if (!e) return; + setFile(e); + const base64 = await e.arrayBuffer().then((buf) => + 'data:image/png;base64,' + Buffer.from(buf).toString('base64') + ); + setPreviewImage(base64); + }} + /> + + {previewImage ? ( + + ) : ( +
+ +
+ )} + + +
+
+
+
+ ); +} + +export default EditProgramKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/page.tsx new file mode 100644 index 00000000..51452e18 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/page.tsx @@ -0,0 +1,103 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Flex, Text, Image, Skeleton } from '@mantine/core'; +import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +import programKesehatan from '../../../_state/kesehatan/program-kesehatan/programKesehatan'; +import { useProxy } from 'valtio/utils'; +import { useShallowEffect } from '@mantine/hooks'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; + +function DetailProgramKesehatan() { + const programKesehatanState = useProxy(programKesehatan) + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const router = useRouter(); + const params = useParams() + + useShallowEffect(() => { + programKesehatanState.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + programKesehatanState.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/program-kesehatan") + } + } + + if (!programKesehatanState.findUnique.data) { + return ( + + + + ) + } + + return ( + + + + + + + Detail Program Kesehatan + {programKesehatanState.findUnique.data ? ( + + + + Judul + {programKesehatanState.findUnique.data.name} + + + Deskripsi Singkat + {programKesehatanState.findUnique.data.deskripsiSingkat} + + + Deskripsi + + + + Gambar + gambar + + + + + + + + + + ) : null} + + + + {/* Modal Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus program kesehatan ini?" + /> + + ); +} + +export default DetailProgramKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx index fb9d57ba..1bd5f486 100644 --- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx @@ -1,43 +1,101 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; -import { IconArrowBack } from '@tabler/icons-react'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import { useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; +import CreateEditor from '../../../_com/createEditor'; +import programKesehatan from '../../../_state/kesehatan/program-kesehatan/programKesehatan'; function CreateProgramKesehatan() { const router = useRouter(); + const programKesehatanState = useProxy(programKesehatan) + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + + const resetForm = () => { + // Reset state di valtio + programKesehatanState.create.form = { + name: "", + deskripsiSingkat: "", + deskripsi: "", + imageId: "", + }; + + // Reset state lokal + setPreviewImage(null); + setFile(null); + }; + + const handleSubmit = async () => { + if (!file) { + return toast.warn("Pilih file gambar terlebih dahulu"); + } + + // Upload gambar dulu + const res = await ApiFetch.api.fileStorage.create.post({ + file, + name: file.name, + }); + + const uploaded = res.data?.data; + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + // Simpan ID gambar ke form + programKesehatanState.create.form.imageId = uploaded.id; + + // Submit data berita + await programKesehatanState.create.create(); + + // Reset form setelah submit + resetForm(); + router.push("/admin/kesehatan/program-kesehatan") + }; + return ( - + - Create Program Kesehatan - { + programKesehatanState.create.form.name = val.target.value; + }} label={Judul} placeholder="masukkan judul" /> Deskripsi} + value={programKesehatanState.create.form.deskripsiSingkat} + onChange={(val) => { + programKesehatanState.create.form.deskripsiSingkat = val.target.value; + }} + label={Deskripsi Singkat} placeholder="masukkan deskripsi" /> - Kategori} - placeholder="masukkan kategori" - /> + + Deskripsi + { + programKesehatanState.create.form.deskripsi = val; + }} + /> + - {/* Upload Gambar} value={file} onChange={async (e) => { @@ -48,25 +106,18 @@ function CreateProgramKesehatan() { ); setPreviewImage(base64); }} - /> */} + /> - {/* {previewImage ? ( + {previewImage ? ( ) : (
- )} */} + )} - - Konten - - - -
diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/detail/page.tsx deleted file mode 100644 index 193f9366..00000000 --- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/detail/page.tsx +++ /dev/null @@ -1,70 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core'; -import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import React from 'react'; -// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; - -function DetailProgramKesehatan() { - const router = useRouter(); - return ( - - - - - - - Detail Potensi - - - - - Judul - Test Judul - - - Kategori - Test Kategori - - - Deskripsi - Test Deskripsi - - - Gambar - gambar - - - Konten - Test Konten - - - - - - - - - - - - - {/* Modal Hapus - setModalHapus(false)} - onConfirm={handleHapus} - text="Apakah anda yakin ingin menghapus potensi ini?" - /> */} - - ); -} - -export default DetailProgramKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/edit/page.tsx deleted file mode 100644 index d6e72783..00000000 --- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/edit/page.tsx +++ /dev/null @@ -1,64 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button } from '@mantine/core'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; -import { IconArrowBack } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; - - -function EditProgramKesehatan() { - const router = useRouter(); - return ( - - - - - - - - - - Edit Program Kesehatan - Nama Program Kesehatan} - placeholder='Masukkan nama Program Kesehatan' - /> - No Telp Program Kesehatan} - placeholder='Masukkan no telp Program Kesehatan' - /> - - Deskripsi - - - - Pelayanan Posyandu - - - - - - - - - Preview Data Program Kesehatan - Nama Program Kesehatan - No Telp Program Kesehatan - Deskripsi - Pelayanan Posyandu - - - - - - - ); -} - -export default EditProgramKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx index 8461d09c..c7c6206e 100644 --- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx @@ -1,66 +1,86 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; +import { Box, Button, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; import JudulList from '../../_com/judulList'; import HeaderSearch from '../../_com/header'; import { useRouter } from 'next/navigation'; +import programKesehatan from '../../_state/kesehatan/program-kesehatan/programKesehatan'; +import { useProxy } from 'valtio/utils'; +import { useShallowEffect } from '@mantine/hooks'; function ProgramKesehatan() { return ( } /> - + ); } function ListProgramKesehatan() { + const programKesehatanState = useProxy(programKesehatan) const router = useRouter() + + useShallowEffect(() => { + programKesehatanState.findMany.load() + }, []) + + if (!programKesehatanState.findMany.data) { + return ( + + + + ) + } + return ( - - - - - - - - Judul - Kategori - Image - Detail - - - - - - - Test - - Test - - - - - - - - -
-
-
-
-
+ + + + + + + + Judul + Deskripsi Singkat + Image + Detail + + + + {programKesehatanState.findMany.data?.map((item) => ( + + + + {item.name} + + + {item.deskripsiSingkat} + + + + + + + + ))} + +
+
+
+
+
) } diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/[id]/edit/page.tsx new file mode 100644 index 00000000..2d84f27a --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/puskesmas/[id]/edit/page.tsx @@ -0,0 +1,286 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' + +import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas'; +import colors from '@/con/colors'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { ChangeEvent, useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + +interface PuskesmasFormBase { + name: string; + alamat: string; + jam: { + workDays: string; + weekDays: string; + holiday: string; + }; + kontak: { + kontakPuskesmas: string; + email: string; + facebook: string; + kontakUGD: string; + }; + imageId: string; +} + +interface PuskesmasFormData extends PuskesmasFormBase { + image?: { + link: string; + }; +} + +function EditPuskesmas() { + const statePuskesmas = useProxy(puskesmasState); + const router = useRouter(); + const params = useParams(); + + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [formData, setFormData] = useState({ + name: statePuskesmas.edit.form.name || '', + alamat: statePuskesmas.edit.form.alamat || '', + jam: { + workDays: statePuskesmas.edit.form.jam?.workDays || '', + weekDays: statePuskesmas.edit.form.jam?.weekDays || '', + holiday: statePuskesmas.edit.form.jam?.holiday || '', + }, + kontak: { + kontakPuskesmas: statePuskesmas.edit.form.kontak?.kontakPuskesmas || '', + email: statePuskesmas.edit.form.kontak?.email || '', + facebook: statePuskesmas.edit.form.kontak?.facebook || '', + kontakUGD: statePuskesmas.edit.form.kontak?.kontakUGD || '', + }, + imageId: statePuskesmas.edit.form.imageId || '', + }); + + useEffect(() => { + const loadPuskesmas = async () => { + const id = params?.id as string; + if (!id) return; + + try { + await statePuskesmas.edit.load(id); + const { form } = statePuskesmas.edit; + if (form) { + setFormData({ + name: form.name, + alamat: form.alamat, + jam: { + workDays: form.jam.workDays, + weekDays: form.jam.weekDays, + holiday: form.jam.holiday, + }, + kontak: { + kontakPuskesmas: form.kontak.kontakPuskesmas, + email: form.kontak.email, + facebook: form.kontak.facebook, + kontakUGD: form.kontak.kontakUGD, + }, + imageId: form.imageId, + }); + + // Check if there's an existing image URL in the form data + const formWithImage = form as PuskesmasFormData; + if (formWithImage.image?.link) { + setPreviewImage(formWithImage.image.link); + } + } + } catch (error) { + console.error("Error loading puskesmas:", error); + toast.error("Gagal memuat data puskesmas"); + } + }; + loadPuskesmas(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + statePuskesmas.edit.form = { + ...statePuskesmas.edit.form, + name: formData.name, + alamat: formData.alamat, + jam: { + workDays: formData.jam.workDays, + weekDays: formData.jam.weekDays, + holiday: formData.jam.holiday, + }, + kontak: { + kontakPuskesmas: formData.kontak.kontakPuskesmas, + email: formData.kontak.email, + facebook: formData.kontak.facebook, + kontakUGD: formData.kontak.kontakUGD, + }, + imageId: formData.imageId, + }; + + if (file) { + const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = res.data?.data; + + if (!uploaded?.id) { + toast.error("Gagal upload gambar"); + return; + } + + statePuskesmas.edit.form.imageId = uploaded.id; + } + + const success = await statePuskesmas.edit.submit(); + if (success) { + toast.success("Puskesmas berhasil diperbarui!"); + router.push("/admin/kesehatan/puskesmas"); + } + } catch (error) { + console.error("Error updating puskesmas:", error); + toast.error(error instanceof Error ? error.message : "Gagal memperbarui data puskesmas"); + } + }; + + const handleFileChange = (selectedFile: File | null) => { + if (selectedFile) { + setFile(selectedFile); + const reader = new FileReader(); + reader.onload = (e) => { + if (e.target?.result) { + setPreviewImage(e.target.result as string); + } + }; + reader.readAsDataURL(selectedFile); + } else { + setFile(null); + setPreviewImage(null); + } + }; + + const handleInputChange = (e: ChangeEvent) => { + const { name, value } = e.target; + setFormData(prev => ({ + ...prev, + [name]: value + })); + }; + + const handleNestedChange = (section: 'jam' | 'kontak', field: string, value: string) => { + setFormData(prev => ({ + ...prev, + [section]: { + ...prev[section], + [field]: value + } + })); + }; + + return ( + + + + + + + + Edit Puskesmas + + Nama Puskesmas} + placeholder="masukkan nama puskesmas" + name="name" + value={formData.name} + onChange={handleInputChange} + /> + + Alamat} + placeholder="masukkan alamat" + name="alamat" + value={formData.alamat} + onChange={handleInputChange} + /> + + Jam Buka} + placeholder="masukkan jam buka" + value={formData.jam.workDays} + onChange={(e) => handleNestedChange('jam', 'workDays', e.target.value)} + /> + + Jam Tutup} + placeholder="masukkan jam tutup" + value={formData.jam.weekDays} + onChange={(e) => handleNestedChange('jam', 'weekDays', e.target.value)} + /> + + Jam Libur} + placeholder="masukkan jam libur" + value={formData.jam.holiday} + onChange={(e) => handleNestedChange('jam', 'holiday', e.target.value)} + /> + + Kontak Puskesmas} + placeholder="masukkan kontak puskesmas" + value={formData.kontak.kontakPuskesmas} + onChange={(e) => handleNestedChange('kontak', 'kontakPuskesmas', e.target.value)} + /> + + Email} + placeholder="masukkan email" + value={formData.kontak.email} + onChange={(e) => handleNestedChange('kontak', 'email', e.target.value)} + /> + + Facebook} + placeholder="masukkan facebook" + value={formData.kontak.facebook} + onChange={(e) => handleNestedChange('kontak', 'facebook', e.target.value)} + /> + + Kontak UGD} + placeholder="masukkan kontak UGD" + value={formData.kontak.kontakUGD} + onChange={(e) => handleNestedChange('kontak', 'kontakUGD', e.target.value)} + /> + + } + value={file} + onChange={handleFileChange} + /> + + {previewImage ? ( + Preview + ) : ( +
+ +
+ )} + + +
+
+
+
+ ); +} + +export default EditPuskesmas; diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/[id]/page.tsx new file mode 100644 index 00000000..c3edf01c --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/puskesmas/[id]/page.tsx @@ -0,0 +1,111 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Flex, Text, Image, Skeleton } from '@mantine/core'; +import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +import puskesmasState from '../../../_state/kesehatan/puskesmas/puskesmas'; +import { useProxy } from 'valtio/utils'; +import { useShallowEffect } from '@mantine/hooks'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; + +function DetailPuskesmas() { + const params = useParams() + const router = useRouter(); + const statePuskesmas = useProxy(puskesmasState) + const [modalHapus, setModalHapus] = useState(false); + const [selectedId, setSelectedId] = useState(null) + + useShallowEffect(() => { + statePuskesmas.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + statePuskesmas.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/puskesmas") + } + } + + if (!statePuskesmas.findUnique.data) { + return ( + + + + ) + } + + + return ( + + + + + + + Detail Puskesmas + {statePuskesmas.findUnique.data ? ( + + + + Nama Puskesmas + {statePuskesmas.findUnique.data.name} + + + Alamat + {statePuskesmas.findUnique.data.alamat} + + + Jam Operasional + {statePuskesmas.findUnique.data.jam.workDays} + {statePuskesmas.findUnique.data.jam.weekDays} + {statePuskesmas.findUnique.data.jam.holiday} + + + Gambar + gambar + + + Kontak + {statePuskesmas.findUnique.data.kontak.kontakPuskesmas} + {statePuskesmas.findUnique.data.kontak.email} + {statePuskesmas.findUnique.data.kontak.facebook} + {statePuskesmas.findUnique.data.kontak.kontakUGD} + + + + + + + + + + ) : null} + + + + {/* Modal Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus potensi ini?" + /> + + ); +} + +export default DetailPuskesmas; diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/create/page.tsx index 0df37b2a..1bedaad5 100644 --- a/src/app/admin/(dashboard)/kesehatan/puskesmas/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/puskesmas/create/page.tsx @@ -1,14 +1,76 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; -import { IconArrowBack } from '@tabler/icons-react'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; +import { useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; +import puskesmasState from '../../../_state/kesehatan/puskesmas/puskesmas'; function CreatePuskesmas() { + const statePuskesmas = useProxy(puskesmasState) const router = useRouter(); + const [file, setFile] = useState(null); + const [previewImage, setPreviewImage] = useState(null); + + + const resetForm = () => { + statePuskesmas.create.form = { + name: "", + alamat: "", + jam: { + workDays: "", + weekDays: "", + holiday: "", + }, + kontak: { + kontakPuskesmas: "", + email: "", + facebook: "", + kontakUGD: "", + }, + imageId: "", + image: undefined, + }; + + setFile(null); + setPreviewImage(null); + }; + + + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!file) { + return toast.warn("Pilih file gambar terlebih dahulu"); + } + + // Upload gambar dulu + const res = await ApiFetch.api.fileStorage.create.post({ + file, + name: file.name, + }); + + const uploaded = res.data?.data; + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + statePuskesmas.create.form.imageId = uploaded.id; + // State is already being updated directly in the form inputs + + await statePuskesmas.create.submit(); + + toast.success("Data berhasil disimpan"); + resetForm(); + // After successful submission, redirect to the list page + router.push('/admin/kesehatan/puskesmas'); + } + return ( - + diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/detail/page.tsx deleted file mode 100644 index e43adab4..00000000 --- a/src/app/admin/(dashboard)/kesehatan/puskesmas/detail/page.tsx +++ /dev/null @@ -1,70 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core'; -import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import React from 'react'; -// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; - -function DetailPuskesmas() { - const router = useRouter(); - return ( - - - - - - - Detail Potensi - - - - - Judul - Test Judul - - - Kategori - Test Kategori - - - Deskripsi - Test Deskripsi - - - Gambar - gambar - - - Konten - Test Konten - - - - - - - - - - - - - {/* Modal Hapus - setModalHapus(false)} - onConfirm={handleHapus} - text="Apakah anda yakin ingin menghapus potensi ini?" - /> */} - - ); -} - -export default DetailPuskesmas; diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/edit/page.tsx deleted file mode 100644 index fa27e730..00000000 --- a/src/app/admin/(dashboard)/kesehatan/puskesmas/edit/page.tsx +++ /dev/null @@ -1,64 +0,0 @@ -'use client' -import colors from '@/con/colors'; -import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button } from '@mantine/core'; -import { KesehatanEditor } from '../../_com/kesehatanEditor'; -import { useRouter } from 'next/navigation'; -import { IconArrowBack } from '@tabler/icons-react'; - - -function EditPuskesmas() { - const router = useRouter(); - return ( - - - - - - - - - - Edit Puskesmas - Nama Puskesmas} - placeholder='Masukkan nama puskesmas' - /> - No Telp Puskesmas} - placeholder='Masukkan no telp puskesmas' - /> - - Deskripsi - - - - Pelayanan Posyandu - - - - - - - - - Preview Data Puskesmas - Nama Puskesmas - No Telp Puskesmas - Deskripsi - Pelayanan Posyandu - - - - - - - ); -} - -export default EditPuskesmas; diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx index a11048ae..403e4d8b 100644 --- a/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx @@ -1,10 +1,13 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; +import { Box, Button, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; -import JudulList from '../../_com/judulList'; -import HeaderSearch from '../../_com/header'; import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import HeaderSearch from '../../_com/header'; +import JudulList from '../../_com/judulList'; +import puskesmasState from '../../_state/kesehatan/puskesmas/puskesmas'; function Puskesmas() { return ( @@ -20,7 +23,20 @@ function Puskesmas() { } function ListPuskesmas() { + const statePuskesmas = useProxy(puskesmasState) const router = useRouter(); + + useShallowEffect(() => { + statePuskesmas.findMany.load() + }, []) + + if (!statePuskesmas.findMany.data) { + return ( + + + + ) + } return ( @@ -33,28 +49,27 @@ function ListPuskesmas() { - Judul - Kategori + Nama Puskesmas + Alamat Image Detail - - - - Test - - Test - - - - - - - + {statePuskesmas.findMany.data?.map((item) => ( + + {item.name} + {item.alamat} + + + + + + + + ))}
diff --git a/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/page.tsx b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/page.tsx index f88bb835..df696fe3 100644 --- a/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/page.tsx +++ b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/page.tsx @@ -42,6 +42,7 @@ function VisiMisiPPIDEdit() { visiMisi.findById.data.misi = draftMisi; visiMisi.update.save(visiMisi.findById.data); } + router.push('/admin/ppid/visi-misi-ppid') }; return ( diff --git a/src/app/admin/_com/list_PageAdmin.tsx b/src/app/admin/_com/list_PageAdmin.tsx index d5d9606c..ef9d99ae 100644 --- a/src/app/admin/_com/list_PageAdmin.tsx +++ b/src/app/admin/_com/list_PageAdmin.tsx @@ -11,41 +11,26 @@ export const navBar = [ }, { id: "Landing_Page_2", - name: "Penghargaan", - path: "/admin/landing-page/penghargaan" - }, - { - id: "Landing_Page_3", - name: "Layanan", - path: "/admin/landing-page/layanan" - }, - { - id: "Landing_Page_4", - name: "Potensi", - path: "/admin/landing-page/potensi" - }, - { - id: "Landing_Page_5", name: "Desa Anti Korupsi", path: "/admin/landing-page/desa-anti-korupsi" }, { - id: "Landing_Page_6", + id: "Landing_Page_3", name: "Indeks Kepuasan Masyarakat", path: "/admin/landing-page/indeks-kepuasan-masyarakat" }, { - id: "Landing_Page_7", + id: "Landing_Page_4", name: "SDGs Desa", path: "/admin/landing-page/sdgs-desa" }, { - id: "Landing_Page_8", + id: "Landing_Page_5", name: "APBDes", path: "/admin/landing-page/apbdes" }, { - id: "Landing_Page_9", + id: "Landing_Page_6", name: "Prestasi Desa", path: "/admin/landing-page/prestasi-desa" } @@ -156,7 +141,7 @@ export const navBar = [ { id: "Kesehatan_2", name: "Data Kesehatan Warga", - path: "/admin/kesehatan/data-kesehatan-warga" + path: "/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian" }, { id: "Kesehatan_3", diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/create.ts new file mode 100644 index 00000000..479a61cf --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/create.ts @@ -0,0 +1,64 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FasilitasKesehatanInput = { + name: string; + informasiUmum: { fasilitas: string; alamat: string; jamOperasional: string }; + layananUnggulan: { content: string }; + dokterdanTenagaMedis: { name: string; specialist: string; jadwal: string }; + fasilitasPendukung: { content: string }; + prosedurPendaftaran: { content: string }; + tarifDanLayanan: { layanan: string; tarif: string }; +}; + +const fasilitasKesehatanCreate = async (context: Context) => { + const body = await context.body as FasilitasKesehatanInput; + + const { + name, + informasiUmum, + layananUnggulan, + dokterdanTenagaMedis, + fasilitasPendukung, + prosedurPendaftaran, + tarifDanLayanan, + } = body; + + // Buat masing-masing relasi terlebih dahulu + const [createdInformasiUmum, createdLayananUnggulan, createdDokter, createdPendukung, createdProsedur, createdTarif] = await Promise.all([ + prisma.informasiUmum.create({ data: informasiUmum }), + prisma.layananUnggulan.create({ data: layananUnggulan }), + prisma.dokterdanTenagaMedis.create({ data: dokterdanTenagaMedis }), + prisma.fasilitasPendukung.create({ data: fasilitasPendukung }), + prisma.prosedurPendaftaran.create({ data: prosedurPendaftaran }), + prisma.tarifDanLayanan.create({ data: tarifDanLayanan }), + ]); + + const fasilitas = await prisma.fasilitasKesehatan.create({ + data: { + name, + informasiUmumId: createdInformasiUmum.id, + layananUnggulanId: createdLayananUnggulan.id, + dokterdanTenagaMedisId: createdDokter.id, + fasilitasPendukungId: createdPendukung.id, + prosedurPendaftaranId: createdProsedur.id, + tarifDanLayananId: createdTarif.id, + }, + include: { + informasiumum: true, + layananunggulan: true, + dokterdantenagamedis: true, + fasilitaspendukung: true, + prosedurpendaftaran: true, + tarifdanlayanan: true, + }, + }); + + return { + success: true, + message: "Fasilitas berhasil dibuat", + data: fasilitas, + }; +}; + +export default fasilitasKesehatanCreate; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/del.ts new file mode 100644 index 00000000..349c46ce --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/del.ts @@ -0,0 +1,43 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +const fasilitasKesehatanDelete = async (context: Context) => { + const id = context.params?.id as string; + + if (!id) { + return { + status: 400, + message: "ID tidak ditemukan", + } + } + + const fasilitasKesehatan = await prisma.fasilitasKesehatan.findUnique({ + where: { id }, + include: { + informasiumum: true, + layananunggulan: true, + dokterdantenagamedis: true, + fasilitaspendukung: true, + prosedurpendaftaran: true, + tarifdanlayanan: true, + } + }) + + if (!fasilitasKesehatan) { + return { + status: 404, + message: "Fasilitas kesehatan tidak ditemukan", + } + } + + await prisma.fasilitasKesehatan.delete({ + where: { id }, + }) + + return { + status: 200, + success: true, + message: "Fasilitas kesehatan berhasil dihapus", + } +} +export default fasilitasKesehatanDelete \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/create.ts deleted file mode 100644 index 44da0e41..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/create.ts +++ /dev/null @@ -1,31 +0,0 @@ -import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; -import { Context } from "elysia"; - -type FormCreate = Prisma.DokterdanTenagaMedisGetPayload<{ - select: { - name: true - specialist: true - jadwal: true - } -}> - -async function dokterDantenagamedisCreate(context: Context) { - const body = context.body as FormCreate - - await prisma.dokterdanTenagaMedis.create({ - data: { - name: body.name, - specialist: body.specialist, - jadwal: body.jadwal, - } - }) - return { - success: true, - message: "Success create dokter dan tenaga medis", - data: { - ...body - } - } -} -export default dokterDantenagamedisCreate \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/find-many.ts deleted file mode 100644 index 3792ad71..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/find-many.ts +++ /dev/null @@ -1,8 +0,0 @@ -import prisma from "@/lib/prisma"; - -export default async function dokterDantenagamedisFindMany() { - const res = await prisma.dokterdanTenagaMedis.findMany(); - return { - data: res - } -} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/index.ts deleted file mode 100644 index a360ee2c..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import Elysia, { t } from "elysia"; -import dokterDantenagamedisFindMany from "./find-many"; -import dokterDantenagamedisCreate from "./create"; - -const DokterDantenagamedis = new Elysia({ - prefix: "/dokterdantenagamedis", - tags: ["Data Kesehatan/Fasilitas Kesehatan/Dokter dan Tenaga Medis"], -}) -.get("/find-many", dokterDantenagamedisFindMany) -.post("/create", dokterDantenagamedisCreate, { - body: t.Object({ - name: t.String(), - specialist: t.String(), - jadwal: t.String(), - }) -}) - -export default DokterDantenagamedis \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/create.ts deleted file mode 100644 index 8cb74eff..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/create.ts +++ /dev/null @@ -1,29 +0,0 @@ -import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; -import { Context } from "elysia"; - -type FormCreate = Prisma.FasilitasPendukungGetPayload<{ - select: { - content: true - } -}> - -async function FasilitasPendukungCreate(context: Context){ - const body = context.body as FormCreate - - await prisma.fasilitasPendukung.create({ - data: { - - content: body.content - } - }) - return { - success: true, - message: "Success create fasilitas pendukung", - data: { - ...body - } - } -} - -export default FasilitasPendukungCreate \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/find-many.ts deleted file mode 100644 index 941f70e7..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/find-many.ts +++ /dev/null @@ -1,8 +0,0 @@ -import prisma from "@/lib/prisma"; - -export default async function fasilitasPendukungFindMany() { - const res = await prisma.fasilitasPendukung.findMany(); - return { - data: res - } -} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/index.ts deleted file mode 100644 index a985e712..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Elysia, { t } from "elysia"; -import fasilitasPendukungFindMany from "./find-many"; -import FasilitasPendukungCreate from "./create"; - -const FasilitasPendukung = new Elysia({ - prefix: "/fasilitaspendukung", - tags: ["Data Kesehatan/Fasilitas Kesehatan/Fasilitas Pendukung"], -}) - .get("/find-many", fasilitasPendukungFindMany) - .post("/create", FasilitasPendukungCreate, { - body: t.Object({ - content: t.String(), - }), - }); - -export default FasilitasPendukung; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/findMany.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/findMany.ts new file mode 100644 index 00000000..f9004f44 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/findMany.ts @@ -0,0 +1,30 @@ +import prisma from "@/lib/prisma"; + +export default async function findManyFasilitasKesehatan() { + try { + const data = await prisma.fasilitasKesehatan.findMany({ + where: { + isActive: true, + }, + include: { + informasiumum: true, + layananunggulan: true, + dokterdantenagamedis: true, + fasilitaspendukung: true, + prosedurpendaftaran: true, + tarifdanlayanan: true, + } + }) + return { + success: true, + message: "Success fetch fasilitas kesehatan", + data, + } + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: "Failed fetch fasilitas kesehatan", + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/findUnique.ts new file mode 100644 index 00000000..8cdd5014 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/findUnique.ts @@ -0,0 +1,53 @@ +import prisma from "@/lib/prisma"; + +export default async function findUniqueFasilitasKesehatan(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return Response.json({ + success: false, + message: "ID tidak boleh kosong", + }, { status: 400 }) + } + + try { + if (typeof id !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }) + } + + const data = await prisma.fasilitasKesehatan.findUnique({ + where: {id}, + include: { + informasiumum: true, + layananunggulan: true, + dokterdantenagamedis: true, + fasilitaspendukung: true, + prosedurpendaftaran: true, + tarifdanlayanan: true, + } + }) + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }) + } + + return Response.json({ + success: true, + data, + }, { status: 200 }) + } catch (error) { + console.error("Gagal mengambil data fasilitas kesehatan:", error); + return Response.json({ + success: false, + message: "Gagal mengambil data fasilitas kesehatan", + }, { status: 500 }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/index.ts new file mode 100644 index 00000000..1eb5badd --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/index.ts @@ -0,0 +1,84 @@ +import { Elysia, t } from "elysia"; +import fasilitasKesehatanCreate from "./create"; +import findManyFasilitasKesehatan from "./findMany"; +import findUniqueFasilitasKesehatan from "./findUnique"; +import fasilitasKesehatanUpdate from "./updt"; +import fasilitasKesehatanDelete from "./del"; + +const FasilitasKesehatan = new Elysia({ + prefix: "fasilitas-kesehatan", + tags: ["Kesehatan/Fasilitas Kesehatan"], +}) + .post("/create", fasilitasKesehatanCreate, { + body: t.Object({ + name: t.String(), + informasiUmum: t.Object({ + fasilitas: t.String(), + alamat: t.String(), + jamOperasional: t.String(), + }), + layananUnggulan: t.Object({ + content: t.String(), + }), + dokterdanTenagaMedis: t.Object({ + name: t.String(), + specialist: t.String(), + jadwal: t.String(), + }), + fasilitasPendukung: t.Object({ + content: t.String(), + }), + prosedurPendaftaran: t.Object({ + content: t.String(), + }), + tarifDanLayanan: t.Object({ + layanan: t.String(), + tarif: t.String(), + }), + }), + }) + .get("/find-many", findManyFasilitasKesehatan) + .delete("/del/:id", fasilitasKesehatanDelete) + .get("/:id", async (context) => { + const response = await findUniqueFasilitasKesehatan( + new Request(context.request) + ); + return response; + }) + .put( + "/:id", + async (context) => { + const response = await fasilitasKesehatanUpdate(context); + return response; + }, + { + body: t.Object({ + name: t.String(), + informasiUmum: t.Object({ + fasilitas: t.String(), + alamat: t.String(), + jamOperasional: t.String(), + }), + layananUnggulan: t.Object({ + content: t.String(), + }), + dokterdanTenagaMedis: t.Object({ + name: t.String(), + specialist: t.String(), + jadwal: t.String(), + }), + fasilitasPendukung: t.Object({ + content: t.String(), + }), + prosedurPendaftaran: t.Object({ + content: t.String(), + }), + tarifDanLayanan: t.Object({ + layanan: t.String(), + tarif: t.String(), + }), + }), + } + ); + +export default FasilitasKesehatan; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/create.ts deleted file mode 100644 index 7b2655fc..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/create.ts +++ /dev/null @@ -1,31 +0,0 @@ -import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; -import { Context } from "elysia"; - -type FormCreate = Prisma.InformasiUmumGetPayload<{ - select: { - fasilitas: true - alamat: true - jamOperasional: true - } -}> -async function informasiUmumCreate(context: Context) { - const body = context.body as FormCreate - - await prisma.informasiUmum.create({ - data: { - fasilitas: body.fasilitas, - alamat: body.alamat, - jamOperasional: body.jamOperasional, - } - }) - return{ - success: true, - message: "Success create informasi umum", - data: { - ...body - } - } -} - -export default informasiUmumCreate diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/find-many.ts deleted file mode 100644 index cc3b51da..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/find-many.ts +++ /dev/null @@ -1,8 +0,0 @@ -import prisma from "@/lib/prisma"; - -export default async function informasiUmumFindMany() { - const res = await prisma.informasiUmum.findMany(); - return { - data: res - } -} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/index.ts deleted file mode 100644 index 5d474739..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/informasi_umum/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import Elysia, { t } from "elysia"; -import informasiUmumFindMany from "./find-many"; -import informasiUmumCreate from "./create"; - -const InformasiUmum = new Elysia({ - prefix: "/informasiumum", - tags: ["Data Kesehatan/Fasilitas Kesehatan/Informasi Umum"], -}) - .get("/find-many", informasiUmumFindMany) - .post("/create", informasiUmumCreate, { - body: t.Object({ - fasilitas: t.String(), - alamat: t.String(), - jamOperasional: t.String(), - }), - }); - -export default InformasiUmum; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/create.ts deleted file mode 100644 index 2e9b1289..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/create.ts +++ /dev/null @@ -1,28 +0,0 @@ -import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; -import { Context } from "elysia"; - -type FormCreate = Prisma.LayananUnggulanGetPayload<{ - select: { - content: true - } -}> - -async function layananUnggulanCreate(context: Context) { - const body = context.body as FormCreate - - await prisma.layananUnggulan.create({ - data: { - content: body.content - } - }) - return { - success: true, - message: "Success create layanan unggulan", - data: { - ...body - } - } -} - -export default layananUnggulanCreate diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/find-many.ts deleted file mode 100644 index 716a7e54..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/find-many.ts +++ /dev/null @@ -1,8 +0,0 @@ -import prisma from "@/lib/prisma"; - -export default async function layananUnggulanFindMany() { - const res = await prisma.layananUnggulan.findMany(); - return { - data: res - } -} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/index.ts deleted file mode 100644 index 72777c4d..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Elysia, { t } from "elysia"; -import layananUnggulanCreate from "./create"; -import layananUnggulanFindMany from "./find-many"; - -const LayananUnggulan = new Elysia({ - prefix: "/layananunggulan", - tags: ["Data Kesehatan/Fasilitas Kesehatan/Layanan Unggulan"] -}) - -.get("/find-many", layananUnggulanFindMany) -.post("/create", layananUnggulanCreate, { - body: t.Object({ - content: t.String() - }) -}) - -export default LayananUnggulan \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/create.ts deleted file mode 100644 index 1bc93b08..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/create.ts +++ /dev/null @@ -1,28 +0,0 @@ -import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; -import { Context } from "elysia"; - -type FormCreate = Prisma.ProsedurPendaftaranGetPayload<{ - select: { - content: true - } -}> - -async function prosedurPendaftaranCreate(context: Context) { - const body = context.body as FormCreate - - await prisma.prosedurPendaftaran.create({ - data: { - content: body.content - } - }) - return{ - success: true, - message: "Success create prosedur pendaftaran", - data: { - ...body - } - } -} - -export default prosedurPendaftaranCreate diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/find-many.ts deleted file mode 100644 index 2da795a6..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/find-many.ts +++ /dev/null @@ -1,8 +0,0 @@ -import prisma from "@/lib/prisma"; - -export default async function prosedurPendaftaranFindMany() { - const res = await prisma.prosedurPendaftaran.findMany(); - return { - data: res - } -} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/index.ts deleted file mode 100644 index f1a798ad..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import Elysia, { t } from "elysia"; -import prosedurPendaftaranFindMany from "./find-many"; -import prosedurPendaftaranCreate from "./create"; - -const ProsedurPendaftaran = new Elysia({ - prefix: "/prosedurpendaftaran", - tags: ["Data Kesehatan/Fasilitas Kesehatan/Prosedur Pendaftaran"], -}) - .get("/find-many", prosedurPendaftaranFindMany) - .post("/create", prosedurPendaftaranCreate, { - body: t.Object({ - content: t.String(), - }), - }); -export default ProsedurPendaftaran; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/create.ts deleted file mode 100644 index 8f89cd45..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/create.ts +++ /dev/null @@ -1,30 +0,0 @@ -import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; -import { Context } from "elysia"; - -type FormCreate = Prisma.TarifDanLayananGetPayload<{ - select: { - layanan: true - tarif: true - } -}> - -async function tarifdanlayananCreate(context: Context) { - const body = context.body as FormCreate - - await prisma.tarifDanLayanan.create({ - data: { - layanan: body.layanan, - tarif: body.tarif, - } - }) - return { - success: true, - message: "Success create tarif dan layanan", - data: { - ...body - } - } -} - -export default tarifdanlayananCreate diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/find-many.ts deleted file mode 100644 index 7dcbfeae..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/find-many.ts +++ /dev/null @@ -1,8 +0,0 @@ -import prisma from "@/lib/prisma"; - -export default async function tarifdanlayananFindMany() { - const res = await prisma.tarifDanLayanan.findMany(); - return { - data: res - } -} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/index.ts deleted file mode 100644 index 37e1f224..00000000 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import Elysia, { t } from "elysia"; -import tarifdanlayananFindMany from "./find-many"; -import tarifdanlayananCreate from "./create"; - - -const TarifDanLayanan = new Elysia({ - prefix: "/tarifdanlayanan", - tags: ["Data Kesehatan/Fasilitas Kesehatan/Tarif dan Layanan"] -}) -.get("/find-many", tarifdanlayananFindMany) -.post("/create", tarifdanlayananCreate, { - body: t.Object({ - layanan: t.String(), - tarif: t.String(), - }) -}) - -export default TarifDanLayanan; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/updt.ts new file mode 100644 index 00000000..d0061150 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/fasilitas_kesehatan/updt.ts @@ -0,0 +1,95 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FasilitasKesehatanInput = { + name: string; + informasiUmum: { fasilitas: string; alamat: string; jamOperasional: string }; + layananUnggulan: { content: string }; + dokterdanTenagaMedis: { name: string; specialist: string; jadwal: string }; + fasilitasPendukung: { content: string }; + prosedurPendaftaran: { content: string }; + tarifDanLayanan: { layanan: string; tarif: string }; +}; + +const fasilitasKesehatanUpdate = async (context: Context) => { + const id = context.params?.id as string; + const body = await context.body as FasilitasKesehatanInput; + + if (!id) { + return new Response( + JSON.stringify({ success: false, message: "ID is required" }), + { status: 400, headers: { "Content-Type": "application/json" } } + ); + } + + const existing = await prisma.fasilitasKesehatan.findUnique({ + where: { id }, + }); + + if (!existing) { + return new Response( + JSON.stringify({ success: false, message: "Data not found" }), + { status: 404, headers: { "Content-Type": "application/json" } } + ); + } + + const { + name, + informasiUmum, + layananUnggulan, + dokterdanTenagaMedis, + fasilitasPendukung, + prosedurPendaftaran, + tarifDanLayanan, + } = body; + + // Update data masing-masing relasi + await Promise.all([ + prisma.informasiUmum.update({ + where: { id: existing.informasiUmumId }, + data: informasiUmum, + }), + prisma.layananUnggulan.update({ + where: { id: existing.layananUnggulanId }, + data: layananUnggulan, + }), + prisma.dokterdanTenagaMedis.update({ + where: { id: existing.dokterdanTenagaMedisId }, + data: dokterdanTenagaMedis, + }), + prisma.fasilitasPendukung.update({ + where: { id: existing.fasilitasPendukungId }, + data: fasilitasPendukung, + }), + prisma.prosedurPendaftaran.update({ + where: { id: existing.prosedurPendaftaranId }, + data: prosedurPendaftaran, + }), + prisma.tarifDanLayanan.update({ + where: { id: existing.tarifDanLayananId }, + data: tarifDanLayanan, + }), + ]); + + // Update main record + const updated = await prisma.fasilitasKesehatan.update({ + where: { id }, + data: { name }, + include: { + informasiumum: true, + layananunggulan: true, + dokterdantenagamedis: true, + fasilitaspendukung: true, + prosedurpendaftaran: true, + tarifdanlayanan: true, + }, + }); + + return { + success: true, + message: "Fasilitas berhasil diupdate", + data: updated, + }; +}; + +export default fasilitasKesehatanUpdate; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/create.ts index cb7e6f8b..961c194f 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/create.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/create.ts @@ -11,17 +11,20 @@ type FormCreate = Prisma.GrafikKepuasanGetPayload<{ export default async function grafikKepuasanCreate(context: Context) { const body = context.body as FormCreate; - await prisma.grafikKepuasan.create({ + const created = await prisma.grafikKepuasan.create({ data: { label: body.label, jumlah: body.jumlah, }, + select: { + uuid: true, + label: true, + jumlah: true, + } }); return { success: true, message: "Success create grafik kepuasan", - data: { - ...body, - }, + data: created, }; } diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/del.ts new file mode 100644 index 00000000..841a7154 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/del.ts @@ -0,0 +1,36 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function grafikKepuasanDelete(context: Context) { + const uuid = context.params?.uuid; + + if (!uuid) { + return { + success: false, + message: "ID tidak ditemukan" + } + } + + const existing = await prisma.grafikKepuasan.findUnique({ + where: { + uuid: uuid, + }, + }) + + if (!existing) { + return { + success: false, + message: "Data tidak ditemukan", + } + } + + const deleted = await prisma.grafikKepuasan.delete({ + where: { uuid }, + }) + + return { + success: true, + message: "Data berhasil dihapus", + data: deleted, + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/findUnique.ts new file mode 100644 index 00000000..352915ad --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/findUnique.ts @@ -0,0 +1,46 @@ +import prisma from "@/lib/prisma"; + +export default async function grafikKepuasanFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const uuid = pathSegments[pathSegments.length - 1]; + + if (!uuid) { + return Response.json({ + success: false, + message: 'ID tidak boleh kosong', + }, {status: 400}) + } + + try { + if (typeof uuid !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }); + } + + const data = await prisma.grafikKepuasan.findUnique({ + where: { uuid }, + }); + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }); + } + + return Response.json({ + success: true, + message: "Berhasil mengambil data berdasarkan ID", + data, + }, { status: 200 }); + } catch (error) { + console.error("Error fetching data:", error); + return Response.json({ + success: false, + message: "Terjadi kesalahan saat mengambil data", + }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/index.ts index e533a509..31a0df63 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/index.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/index.ts @@ -1,11 +1,18 @@ import Elysia, { t } from "elysia"; import grafikKepuasanCreate from "./create"; import grafikKepuasanFindMany from "./find-many"; +import grafikKepuasanFindUnique from "./findUnique"; +import grafikKepuasanUpdate from "./updt"; +import grafikKepuasanDelete from "./del"; const GrafikKepuasan = new Elysia({ prefix: "/grafikkepuasan", tags: ["Data Kesehatan/Grafik Kepuasan"] }) + .get("/:uuid", async (context) => { + const response = await grafikKepuasanFindUnique(new Request(context.request)); + return response; + }) .get("/find-many", grafikKepuasanFindMany) .post("/create", grafikKepuasanCreate, { body: t.Object({ @@ -13,4 +20,18 @@ const GrafikKepuasan = new Elysia({ jumlah: t.String(), }), }) + .put("/:uuid", grafikKepuasanUpdate, { + params: t.Object({ + uuid: t.String(), + }), + body: t.Object({ + label: t.String(), + jumlah: t.String(), + }), + }) + .delete("/del/:uuid", grafikKepuasanDelete, { + params: t.Object({ + uuid: t.String(), + }), + }) export default GrafikKepuasan \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/updt.ts new file mode 100644 index 00000000..7e72a2db --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/grafik_kepuasan/updt.ts @@ -0,0 +1,45 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function grafikKepuasanUpdate(context: Context) { + const uuid = context.params?.uuid; + + if (!uuid) { + return { + success: false, + message: "ID tidak ditemukan" + } + } + + const {label, jumlah} = context.body as { + label: string; + jumlah: string; + } + + const existing = await prisma.grafikKepuasan.findUnique({ + where: { + uuid: uuid, + }, + }) + + if (!existing) { + return { + success: false, + message: "Data tidak ditemukan", + } + } + + const updated = await prisma.grafikKepuasan.update({ + where: { uuid }, + data: { + label, + jumlah, + }, + }) + + return { + success: true, + message: "Data berhasil diupdate", + data: updated, + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/create.ts index 70942825..fc623df3 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/create.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/create.ts @@ -14,19 +14,24 @@ type FormCreate = Prisma.DataKematian_KelahiranGetPayload<{ export default async function persentaseKelahiranKematianCreate(context: Context) { const body = context.body as FormCreate - await prisma.dataKematian_Kelahiran.create({ + const created = await prisma.dataKematian_Kelahiran.create({ data: { tahun: body.tahun, kematianKasar: body.kematianKasar, kematianBayi: body.kematianBayi, kelahiranKasar: body.kelahiranKasar, + }, + select: { + uuid: true, + tahun: true, + kematianKasar: true, + kematianBayi: true, + kelahiranKasar: true, } }) return{ success: true, message: "Success create persentase kelahiran kematian", - data: { - ...body - } + data: created } } \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/del.ts new file mode 100644 index 00000000..7b2fd868 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/del.ts @@ -0,0 +1,36 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function persentaseKelahiranKematianDelete(context: Context) { + const uuid = context.params?.uuid; + + if (!uuid) { + return { + success: false, + message: "ID tidak ditemukan", + } + } + + const existing = await prisma.dataKematian_Kelahiran.findUnique({ + where: { + uuid: uuid, + }, + }) + + if (!existing) { + return { + success: false, + message: "Data tidak ditemukan", + } + } + + const deleted = await prisma.dataKematian_Kelahiran.delete({ + where: { uuid }, + }) + + return { + success: true, + message: "Data berhasil dihapus", + data: deleted, + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/findUnique.ts new file mode 100644 index 00000000..15283fe2 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/findUnique.ts @@ -0,0 +1,46 @@ +import prisma from "@/lib/prisma"; + +export default async function persentaseKelahiranKematianFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const uuid = pathSegments[pathSegments.length - 1]; + + if (!uuid) { + return Response.json({ + success: false, + message: "ID tidak boleh kosong", + }, { status: 400 }); + } + + try { + if (typeof uuid !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }); + } + + const data = await prisma.dataKematian_Kelahiran.findUnique({ + where: { uuid }, + }); + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }); + } + + return Response.json({ + success: true, + message: "Berhasil mengambil data berdasarkan ID", + data, + }, { status: 200 }); + } catch (error) { + console.error("Error fetching data:", error); + return Response.json({ + success: false, + message: "Terjadi kesalahan saat mengambil data", + }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/index.ts index 7ecb2381..aa116c56 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/index.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/index.ts @@ -1,11 +1,18 @@ import Elysia, { t } from "elysia"; import persentaseKelahiranKematianCreate from "./create"; import persentaseKelahiranKematianFindMany from "./find-many"; +import persentaseKelahiranKematianFindUnique from "./findUnique"; +import persentaseKelahiranKematianUpdate from "./updt"; +import persentaseKelahiranKematianDelete from "./del"; const PersentaseKelahiranKematian = new Elysia({ prefix: "/persentasekelahiran", tags: ["Data Kesehatan/Persentase Kelahiran Kematian"], }) + .get("/:uuid", async (context) => { + const response = await persentaseKelahiranKematianFindUnique(new Request(context.request)) + return response + }) .get("/find-many", persentaseKelahiranKematianFindMany) .post("/create", persentaseKelahiranKematianCreate, { body: t.Object({ @@ -15,5 +22,20 @@ const PersentaseKelahiranKematian = new Elysia({ kelahiranKasar: t.String(), }), }) - + .put("/:uuid", persentaseKelahiranKematianUpdate, { + params: t.Object({ + uuid: t.String(), + }), + body: t.Object({ + tahun: t.String(), + kematianKasar: t.String(), + kematianBayi: t.String(), + kelahiranKasar: t.String(), + }), + }) + .delete("/del/:uuid", persentaseKelahiranKematianDelete, { + params: t.Object({ + uuid: t.String(), + }), + }) export default PersentaseKelahiranKematian; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/updt.ts new file mode 100644 index 00000000..261c6480 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/updt.ts @@ -0,0 +1,49 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function persentaseKelahiranKematianUpdate(context: Context) { + const uuid = context.params?.uuid; + + if (!uuid) { + return { + success: false, + message: "ID tidak ditemukan", + } + } + + const {tahun, kematianKasar, kematianBayi, kelahiranKasar} = context.body as { + tahun: string; + kematianKasar: string; + kematianBayi: string; + kelahiranKasar: string; + } + + const existing = await prisma.dataKematian_Kelahiran.findUnique({ + where: { + uuid: uuid, + }, + }) + + if (!existing) { + return { + success: false, + message: "Data tidak ditemukan", + } + } + + const updated = await prisma.dataKematian_Kelahiran.update({ + where: { uuid }, + data: { + tahun, + kematianKasar, + kematianBayi, + kelahiranKasar, + }, + }) + + return { + success: true, + message: "Data berhasil diupdate", + data: updated, + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts index bc5a99df..7eb104bd 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts @@ -1,37 +1,31 @@ import Elysia from "elysia"; -import InformasiUmum from "./data_kesehatan_warga/fasilitas_kesehatan/informasi_umum"; -import LayananUnggulan from "./data_kesehatan_warga/fasilitas_kesehatan/layanan_unggulan"; -import DokterDantenagamedis from "./data_kesehatan_warga/fasilitas_kesehatan/dokterDantenagamedis"; -import FasilitasPendukung from "./data_kesehatan_warga/fasilitas_kesehatan/fasilitas_pendukung"; -import TarifDanLayanan from "./data_kesehatan_warga/fasilitas_kesehatan/tarifDanlayanan"; -import ProsedurPendaftaran from "./data_kesehatan_warga/fasilitas_kesehatan/prosedur_pendaftaran"; -import InformasiJadwalKegiatan from "./data_kesehatan_warga/jadwal_kegiatan/informasi_kegiatan"; -import DeskripsiJadwalKegiatan from "./data_kesehatan_warga/jadwal_kegiatan/deskripsi_kegiatan"; -import LayananTersedia from "./data_kesehatan_warga/jadwal_kegiatan/layanan_yang_tersedia"; -import SyaratKetentuan from "./data_kesehatan_warga/jadwal_kegiatan/syarat_dan_ketentuan"; -import DokumenDiperlukan from "./data_kesehatan_warga/jadwal_kegiatan/dokumen_yang_diperlukan"; -import PendaftaranJadwal from "./data_kesehatan_warga/jadwal_kegiatan/pendaftaran"; -import PersentaseKelahiranKematian from "./data_kesehatan_warga/persentase_kelahiran_kematian"; -import GrafikKepuasan from "./data_kesehatan_warga/grafik_kepuasan"; -import Introduction from "./data_kesehatan_warga/artikel_kesehatan/introduction"; -import Syptom from "./data_kesehatan_warga/artikel_kesehatan/syptom"; -import Prevention from "./data_kesehatan_warga/artikel_kesehatan/prevention"; -import FirstAid from "./data_kesehatan_warga/artikel_kesehatan/first_aid"; -import MythVsFact from "./data_kesehatan_warga/artikel_kesehatan/myth_vs_fact"; import DoctorSign from "./data_kesehatan_warga/artikel_kesehatan/doctor_sign"; +import FirstAid from "./data_kesehatan_warga/artikel_kesehatan/first_aid"; +import Introduction from "./data_kesehatan_warga/artikel_kesehatan/introduction"; +import MythVsFact from "./data_kesehatan_warga/artikel_kesehatan/myth_vs_fact"; +import Prevention from "./data_kesehatan_warga/artikel_kesehatan/prevention"; +import Syptom from "./data_kesehatan_warga/artikel_kesehatan/syptom"; +import GrafikKepuasan from "./data_kesehatan_warga/grafik_kepuasan"; +import DeskripsiJadwalKegiatan from "./data_kesehatan_warga/jadwal_kegiatan/deskripsi_kegiatan"; +import DokumenDiperlukan from "./data_kesehatan_warga/jadwal_kegiatan/dokumen_yang_diperlukan"; +import InformasiJadwalKegiatan from "./data_kesehatan_warga/jadwal_kegiatan/informasi_kegiatan"; +import LayananTersedia from "./data_kesehatan_warga/jadwal_kegiatan/layanan_yang_tersedia"; +import PendaftaranJadwal from "./data_kesehatan_warga/jadwal_kegiatan/pendaftaran"; +import SyaratKetentuan from "./data_kesehatan_warga/jadwal_kegiatan/syarat_dan_ketentuan"; +import PersentaseKelahiranKematian from "./data_kesehatan_warga/persentase_kelahiran_kematian"; +import InfoWabahPenyakit from "./info-wabah-penyakit"; +import KontakDarurat from "./kontak-darurat"; +import PenangananDarurat from "./penanganan-darurat"; import Posyandu from "./posyandu"; +import ProgramKesehatan from "./program-kesehatan"; +import Puskesmas from "./puskesmas"; +import FasilitasKesehatan from "./data_kesehatan_warga/fasilitas_kesehatan"; const Kesehatan = new Elysia({ prefix: "/api/kesehatan", tags: ["Kesehatan"], }) -.use(InformasiUmum) -.use(LayananUnggulan) -.use(DokterDantenagamedis) -.use(FasilitasPendukung) -.use(TarifDanLayanan) -.use(ProsedurPendaftaran) .use(InformasiJadwalKegiatan) .use(DeskripsiJadwalKegiatan) .use(LayananTersedia) @@ -47,4 +41,10 @@ const Kesehatan = new Elysia({ .use(MythVsFact) .use(DoctorSign) .use(Posyandu) +.use(Puskesmas) +.use(ProgramKesehatan) +.use(PenangananDarurat) +.use(KontakDarurat) +.use(InfoWabahPenyakit) +.use(FasilitasKesehatan) export default Kesehatan; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/create.ts new file mode 100644 index 00000000..eb8a5422 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/create.ts @@ -0,0 +1,32 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.InfoWabahPenyakitGetPayload<{ + select: { + name: true; + deskripsiSingkat: true; + deskripsiLengkap: true; + imageId: true; + }; +}> +export default async function infoWabahPenyakitCreate(context: Context) { + const body = context.body as FormCreate; + + await prisma.infoWabahPenyakit.create({ + data: { + name: body.name, + deskripsiSingkat: body.deskripsiSingkat, + deskripsiLengkap: body.deskripsiLengkap, + imageId: body.imageId, + } + }) + return { + success: true, + message: "Success create info wabah penyakit", + data: { + ...body, + }, + }; +} + \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/del.ts new file mode 100644 index 00000000..79f87a1c --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/del.ts @@ -0,0 +1,51 @@ +import prisma from "@/lib/prisma"; +import fs from "fs/promises"; +import { Context } from "elysia"; +import path from "path"; + +const infoWabahPenyakitDelete = async (context: Context) => { + const id = context.params?.id as string; + + if (!id) { + return { + status: 400, + body: "ID tidak diberikan", + }; + } + + const infoWabahPenyakit = await prisma.infoWabahPenyakit.findUnique({ + where: { id }, + include: { image: true }, + }); + + if (!infoWabahPenyakit) { + return { + status: 404, + body: "Info wabah penyakit tidak ditemukan", + }; + } + + // Hapus file gambar dari filesystem jika ada + if (infoWabahPenyakit.image) { + try { + const filePath = path.join(infoWabahPenyakit.image.path, infoWabahPenyakit.image.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: infoWabahPenyakit.image.id }, + }); + } catch (err) { + console.error("Gagal hapus gambar:", err); + } + } + + await prisma.infoWabahPenyakit.delete({ + where: { id }, + }); + + return { + status: 200, + success: true, + message: "Penanganan darurat dan file terkait berhasil dihapus", + }; +}; +export default infoWabahPenyakitDelete; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/find-many.ts new file mode 100644 index 00000000..faeb312d --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/find-many.ts @@ -0,0 +1,25 @@ +import prisma from "@/lib/prisma"; + +export default async function infoWabahPenyakitFindMany() { + try { + const data = await prisma.infoWabahPenyakit.findMany({ + where: { + isActive: true, + }, + include: { + image: true, + } + }) + return { + success: true, + message: "Success fetch info wabah penyakit", + data, + } + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: "Failed fetch info wabah penyakit", + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/findUnique.ts new file mode 100644 index 00000000..74c2b601 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/findUnique.ts @@ -0,0 +1,49 @@ +import prisma from "@/lib/prisma"; + +export default async function infoWabahPenyakitFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return Response.json({ + success: false, + message: "ID tidak boleh kosong", + }, { status: 400 }) + } + + try { + if (typeof id !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }) + } + + const data = await prisma.infoWabahPenyakit.findUnique({ + where: {id}, + include: { + image: true + } + }) + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }) + } + + return Response.json({ + success: true, + message: "Success fetch info wabah penyakit by ID", + data, + }, { status: 200 }) + } catch (error) { + console.error("Find by ID error:", error); + return Response.json({ + success: false, + message: "Gagal mengambil info wabah penyakit: " + (error instanceof Error ? error.message : 'Unknown error'), + }, { status: 500 }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/index.ts new file mode 100644 index 00000000..17069a2d --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/index.ts @@ -0,0 +1,40 @@ +import Elysia, { t } from "elysia"; +import infoWabahPenyakitCreate from "./create"; +import infoWabahPenyakitFindMany from "./find-many"; +import infoWabahPenyakitDelete from "./del"; +import infoWabahPenyakitFindUnique from "./findUnique"; +import infoWabahPenyakitUpdate from "./updt"; + +const InfoWabahPenyakit = new Elysia({ + prefix: "/infowabahpenyakit", + tags: ["Kesehatan/Info Wabah Penyakit"] +}) +.post("/create", infoWabahPenyakitCreate, { + body: t.Object({ + name: t.String(), + deskripsiSingkat: t.String(), + deskripsiLengkap: t.String(), + imageId: t.String(), + }) +}) +.get("/find-many", infoWabahPenyakitFindMany) +.delete("/del/:id", infoWabahPenyakitDelete) +.get("/:id", async (context) => { + const response = await infoWabahPenyakitFindUnique(new Request(context.request)); + return response; +}) +.put("/:id", async (context) => { + const response = await infoWabahPenyakitUpdate(context); + return response; +}, +{ + body: t.Object({ + name: t.String(), + deskripsiSingkat: t.String(), + deskripsiLengkap: t.String(), + imageId: t.String(), + }) +} +) +export default InfoWabahPenyakit; + diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/updt.ts new file mode 100644 index 00000000..3cfdaab7 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/info-wabah-penyakit/updt.ts @@ -0,0 +1,105 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; +import path from "path"; +import fs from "fs/promises"; + +type FormUpdate = Prisma.InfoWabahPenyakitGetPayload<{ + select: { + id: true; + name: true; + deskripsiSingkat: true; + deskripsiLengkap: true; + imageId: true; + } +}> + +export default async function infoWabahPenyakitUpdate(context: Context) { + try { + const id = context.params?.id as string; + const body = (await context.body) as Omit; + + const { + name, + deskripsiSingkat, + deskripsiLengkap, + imageId, + } = body; + + if(!id) { + return new Response(JSON.stringify({ + success: false, + message: "ID tidak boleh kosong", + }), { + status: 400, + headers: { + 'Content-Type': 'application/json' + } + }) + } + + const existing = await prisma.infoWabahPenyakit.findUnique({ + where: { id }, + include: { + image: true, + } + }) + + if (!existing) { + return new Response(JSON.stringify({ + success: false, + message: "Info wabah penyakit tidak ditemukan", + }), { + status: 404, + headers: { + 'Content-Type': 'application/json' + } + }) + } + + if (existing.imageId && existing.imageId !== imageId) { + const oldImage = existing.image; + if (oldImage) { + try { + const filePath = path.join(oldImage.path, oldImage.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: oldImage.id }, + }); + } catch (err) { + console.error("Gagal hapus gambar lama:", err); + } + } + } + + const updated = await prisma.infoWabahPenyakit.update({ + where: { id }, + data: { + name, + deskripsiSingkat, + deskripsiLengkap, + imageId, + } + }) + + return new Response(JSON.stringify({ + success: true, + message: "Info wabah penyakit berhasil diupdate", + data: updated, + }), { + status: 200, + headers: { + 'Content-Type': 'application/json' + } + }) + } catch (error) { + console.error("Error updating info wabah penyakit:", error); + return new Response( + JSON.stringify({ + success: false, + message: "Terjadi kesalahan saat mengupdate info wabah penyakit", + }), + { status: 500, headers: { 'Content-Type': 'application/json' } } + ); + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/create.ts new file mode 100644 index 00000000..8c5be87d --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/create.ts @@ -0,0 +1,29 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.KontakDaruratGetPayload<{ + select: { + name: true; + deskripsi: true; + imageId: true; + }; +}>; +export default async function kontakDaruratCreate(context: Context) { + const body = context.body as FormCreate; + + await prisma.kontakDarurat.create({ + data: { + name: body.name, + deskripsi: body.deskripsi, + imageId: body.imageId, + } + }) + return { + success: true, + message: "Success create kontak darurat", + data: { + ...body, + }, + }; +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/del.ts new file mode 100644 index 00000000..c878ffa5 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/del.ts @@ -0,0 +1,51 @@ +import prisma from "@/lib/prisma"; +import fs from "fs/promises"; +import { Context } from "elysia"; +import path from "path"; + +const kontakDaruratDelete = async (context: Context) => { + const id = context.params?.id as string; + + if (!id) { + return { + status: 400, + body: "ID tidak diberikan", + }; + } + + const kontakDarurat = await prisma.kontakDarurat.findUnique({ + where: { id }, + include: { image: true }, + }); + + if (!kontakDarurat) { + return { + status: 404, + body: "Kontak darurat tidak ditemukan", + }; + } + + // Hapus file gambar dari filesystem jika ada + if (kontakDarurat.image) { + try { + const filePath = path.join(kontakDarurat.image.path, kontakDarurat.image.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: kontakDarurat.image.id }, + }); + } catch (error) { + console.error("Error deleting image file:", error); + } + } + + await prisma.kontakDarurat.delete({ + where: { id }, + }); + + return { + status: 200, + success: true, + message: "Kontak darurat dan file terkait berhasil dihapus", + }; +}; +export default kontakDaruratDelete; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/find-many.ts new file mode 100644 index 00000000..8b675f79 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/find-many.ts @@ -0,0 +1,25 @@ +import prisma from "@/lib/prisma"; + +export default async function kontakDaruratFindMany() { + try { + const data = await prisma.kontakDarurat.findMany({ + where: { + isActive: true, + }, + include: { + image: true, + } + }) + return { + success: true, + message: "Success fetch kontak darurat", + data, + } + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: "Failed fetch kontak darurat", + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/findUnique.ts new file mode 100644 index 00000000..9bb074b1 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/findUnique.ts @@ -0,0 +1,49 @@ +import prisma from "@/lib/prisma"; + +export default async function kontakDaruratFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return Response.json({ + success: false, + message: "ID tidak boleh kosong", + }, { status: 400 }) + } + + try { + if (typeof id !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }) + } + + const data = await prisma.kontakDarurat.findUnique({ + where: {id}, + include: { + image: true + } + }) + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }) + } + + return Response.json({ + success: true, + message: "Success fetch kontak darurat", + data, + }, { status: 200 }) + } catch (error) { + console.error("Find unique error:", error); + return Response.json({ + success: false, + message: "Failed fetch kontak darurat", + }, { status: 500 }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/index.ts new file mode 100644 index 00000000..a5162b83 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/index.ts @@ -0,0 +1,40 @@ +import Elysia, { t } from "elysia"; +import kontakDaruratCreate from "./create"; +import kontakDaruratFindMany from "./find-many"; +import kontakDaruratDelete from "./del"; +import kontakDaruratUpdate from "./updt"; +import kontakDaruratFindUnique from "./findUnique"; + +const KontakDarurat = new Elysia({ + prefix: "/kontakdarurat", + tags: ["Kesehatan/Kontak Darurat"] +}) +.post("/create", kontakDaruratCreate, { + body: t.Object({ + name: t.String(), + deskripsi: t.String(), + imageId: t.String(), + }) +}) +.get("/find-many", kontakDaruratFindMany) +.delete("/del/:id", kontakDaruratDelete) +.get("/:id", async (context) => { + const response = await kontakDaruratFindUnique(new Request(context.request)); + return response; +}) +.put( + "/:id", + async (context) => { + const response = await kontakDaruratUpdate(context); + return response; + }, + { + body: t.Object({ + name: t.String(), + deskripsi: t.String(), + imageId: t.String(), + }) + } +) + +export default KontakDarurat; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/updt.ts new file mode 100644 index 00000000..bc9d7922 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/updt.ts @@ -0,0 +1,102 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; +import path from "path"; +import fs from "fs/promises"; + +type FormUpdate = Prisma.KontakDaruratGetPayload<{ + select: { + id: true; + name: true; + deskripsi: true; + imageId: true; + } +}> +export default async function kontakDaruratUpdate(context: Context) { + try { + const id = context.params?.id as string; + const body = (await context.body) as Omit; + + const { + name, + deskripsi, + imageId, + } = body; + + if(!id) { + return new Response(JSON.stringify({ + success: false, + message: "ID tidak boleh kosong", + }), { + status: 400, + headers: { + 'Content-Type': 'application/json' + } + }) + } + + const existing = await prisma.kontakDarurat.findUnique({ + where: { id }, + include: { + image: true, + } + }) + + if (!existing) { + return new Response(JSON.stringify({ + success: false, + message: "Kontak Darurat tidak ditemukan", + }), { + status: 404, + headers: { + 'Content-Type': 'application/json' + } + }) + } + + if (existing.imageId && existing.imageId !== imageId) { + const oldImage = existing.image; + if (oldImage) { + try { + const filePath = path.join(oldImage.path, oldImage.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: oldImage.id }, + }); + } catch (err) { + console.error("Gagal hapus gambar lama:", err); + } + } + } + + const updated = await prisma.kontakDarurat.update({ + where: { id }, + data: { + name, + deskripsi, + imageId, + } + }) + + return new Response(JSON.stringify({ + success: true, + message: "Kontak Darurat berhasil diupdate", + data: updated, + }), { + status: 200, + headers: { + 'Content-Type': 'application/json' + } + }) + } catch (error) { + console.error("Error updating kontak darurat:", error); + return new Response( + JSON.stringify({ + success: false, + message: "Terjadi kesalahan saat mengupdate kontak darurat", + }), + { status: 500, headers: { 'Content-Type': 'application/json' } } + ); + } +} + \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/create.ts new file mode 100644 index 00000000..cbd05516 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/create.ts @@ -0,0 +1,29 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.PenangananDaruratGetPayload<{ + select: { + name: true; + deskripsi: true; + imageId: true; + }; +}>; +export default async function penangananDaruratCreate(context: Context) { + const body = context.body as FormCreate; + + await prisma.penangananDarurat.create({ + data: { + name: body.name, + deskripsi: body.deskripsi, + imageId: body.imageId, + } + }) + return { + success: true, + message: "Success create penanganan darurat", + data: { + ...body, + }, + }; +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/del.ts new file mode 100644 index 00000000..50089f9a --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/del.ts @@ -0,0 +1,54 @@ +import prisma from "@/lib/prisma"; +import fs from "fs/promises"; +import { Context } from "elysia"; +import path from "path"; + +const penangananDaruratDelete = async (context: Context) => { + const id = context.params?.id as string; + + if (!id) { + return { + status: 400, + body: "ID tidak diberikan", + }; + } + + const penangananDarurat = await prisma.penangananDarurat.findUnique({ + where: { id }, + include: { image: true }, + }); + if (!penangananDarurat) { + return { + status: 404, + body: "Penanganan darurat tidak ditemukan", + }; + } + + // Hapus file gambar dari filesystem jika ada + if (penangananDarurat.image) { + try { + const filePath = path.join( + penangananDarurat.image.path, + penangananDarurat.image.name + ); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: penangananDarurat.image.id }, + }); + } catch (error) { + console.error("Error deleting image file:", error); + } + } + + // Hapus data dari database + await prisma.penangananDarurat.delete({ + where: { id }, + }); + + return { + status: 200, + success: true, + message: "Penanganan darurat dan file terkait berhasil dihapus", + }; +}; +export default penangananDaruratDelete; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/find-many.ts new file mode 100644 index 00000000..849b9b51 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/find-many.ts @@ -0,0 +1,25 @@ +import prisma from "@/lib/prisma"; + +export default async function penangananDaruratFindMany() { + try { + const data = await prisma.penangananDarurat.findMany({ + where: { + isActive: true, + }, + include: { + image: true, + } + }) + return { + success: true, + message: "Success fetch penanganan darurat", + data, + } + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: "Failed fetch penanganan darurat", + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/findUnique.ts new file mode 100644 index 00000000..9171fcdf --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/findUnique.ts @@ -0,0 +1,49 @@ +import prisma from "@/lib/prisma"; + +export default async function penangananDaruratFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return Response.json({ + success: false, + message: "ID tidak boleh kosong", + }, { status: 400 }) + } + + try { + if (typeof id !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }) + } + + const data = await prisma.penangananDarurat.findUnique({ + where: {id}, + include: { + image: true + } + }) + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }) + } + + return Response.json({ + success: true, + message: "Success fetch penanganan darurat by ID", + data, + }, { status: 200 }) + } catch (error) { + console.error("Find by ID error:", error); + return Response.json({ + success: false, + message: "Gagal mengambil penanganan darurat: " + (error instanceof Error ? error.message : 'Unknown error'), + }, { status: 500 }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/index.ts new file mode 100644 index 00000000..6f8eaebe --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/index.ts @@ -0,0 +1,39 @@ +import Elysia, { t } from "elysia"; +import penangananDaruratCreate from "./create"; +import penangananDaruratDelete from "./del"; +import penangananDaruratFindMany from "./find-many"; +import penangananDaruratFindUnique from "./findUnique"; +import penangananDaruratUpdate from "./updt"; + +const PenangananDarurat = new Elysia({ + prefix: "/penanganandarurat", + tags: ["Kesehatan/Penanganan Darurat"] +}) +.post("/create", penangananDaruratCreate, { + body: t.Object({ + name: t.String(), + deskripsi: t.String(), + imageId: t.String(), + }) +}) +.get("/find-many", penangananDaruratFindMany) +.delete("/del/:id", penangananDaruratDelete) +.get(":id", async (context) => { + const response = await penangananDaruratFindUnique(new Request(context.request)); + return response; +}) +.put( + ":id", + async (context) => { + const response = await penangananDaruratUpdate(context); + return response; + }, + { + body: t.Object({ + name: t.String(), + deskripsi: t.String(), + imageId: t.String(), + }) + } +) +export default PenangananDarurat; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/updt.ts new file mode 100644 index 00000000..53acac3c --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/penanganan-darurat/updt.ts @@ -0,0 +1,103 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; +import path from "path"; +import fs from "fs/promises"; + +type FormUpdate = Prisma.PenangananDaruratGetPayload<{ + select: { + id: true; + name: true; + deskripsi: true; + imageId: true; + } +}> +export default async function penangananDaruratUpdate(context: Context) { + try { + const id = context.params?.id as string; + const body = (await context.body) as Omit; + + const { + name, + deskripsi, + imageId, + } = body; + + if (!id) { + return new Response(JSON.stringify({ + success: false, + message: "ID tidak boleh kosong", + }), { + status: 400, + headers: { + 'Content-Type': 'application/json' + } + }) + } + + const existing = await prisma.penangananDarurat.findUnique({ + where: { id }, + include: { + image: true, + } + }) + + if (!existing) { + return new Response(JSON.stringify({ + success: false, + message: "Penanganan darurat tidak ditemukan", + }), { + status: 404, + headers: { + 'Content-Type': 'application/json' + } + }) + } + + if (existing.imageId && existing.imageId !== imageId) { + const oldImage = existing.image; + if (oldImage) { + try { + const filePath = path.join(oldImage.path, oldImage.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: oldImage.id }, + }); + } catch (err) { + console.error("Gagal hapus gambar lama:", err); + } + } + } + + const updated = await prisma.penangananDarurat.update({ + where: { id }, + data: { + name, + deskripsi, + imageId, + } + }) + + return new Response(JSON.stringify({ + success: true, + message: "Penanganan darurat berhasil diupdate", + data: updated, + }), { + status: 200, + headers: { + 'Content-Type': 'application/json' + } + }) + } catch (error) { + console.error("Error updating penanganan darurat:", error); + return new Response(JSON.stringify({ + success: false, + message: "Gagal mengupdate penanganan darurat: " + (error instanceof Error ? error.message : 'Unknown error'), + }), { + status: 500, + headers: { + 'Content-Type': 'application/json' + } + }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/create.ts new file mode 100644 index 00000000..da9f4a28 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/create.ts @@ -0,0 +1,31 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.ProgramKesehatanGetPayload<{ + select: { + name: true; + deskripsiSingkat: true; + deskripsi: true; + imageId: true; + } +}> +export default async function programKesehatanCreate(context: Context) { + const body = context.body as FormCreate; + + await prisma.programKesehatan.create({ + data: { + name: body.name, + deskripsiSingkat: body.deskripsiSingkat, + deskripsi: body.deskripsi, + imageId: body.imageId, + } + }) + return { + success: true, + message: "Success create program kesehatan", + data: { + ...body, + }, + }; +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/del.ts new file mode 100644 index 00000000..7eccaa36 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/del.ts @@ -0,0 +1,52 @@ +import prisma from "@/lib/prisma"; +import fs from "fs/promises"; +import { Context } from "elysia"; +import path from "path"; + +const programKesehatanDelete = async (context: Context) => { + const id = context.params?.id as string; + + if (!id) { + return { + status: 400, + body: "ID tidak diberikan", + }; + } + + const programKesehatan = await prisma.programKesehatan.findUnique({ + where: { id }, + include: { image: true }, + }); + + if (!programKesehatan) { + return { + status: 404, + body: "Program kesehatan tidak ditemukan", + }; + } + + // Hapus file gambar dari filesystem jika ada + if (programKesehatan.image) { + try { + const filePath = path.join(programKesehatan.image.path, programKesehatan.image.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: programKesehatan.image.id }, + }); + } catch (error) { + console.error("Gagal hapus file image:", error); + } + } + + // Hapus berita dari DB + await prisma.programKesehatan.delete({ + where: { id }, + }); + + return { + success: true, + message: "Program kesehatan dan file terkait berhasil dihapus", + }; +}; + +export default programKesehatanDelete; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/find-many.ts new file mode 100644 index 00000000..d3f8c003 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/find-many.ts @@ -0,0 +1,25 @@ +import prisma from "@/lib/prisma"; + +export default async function programKesehatanFindMany() { + try { + const data = await prisma.programKesehatan.findMany({ + where: { + isActive: true, + }, + include: { + image: true, + } + }) + return { + success: true, + message: "Success fetch program kesehatan", + data, + } + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: "Failed fetch program kesehatan", + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/findUnique.ts new file mode 100644 index 00000000..2edcf0db --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/findUnique.ts @@ -0,0 +1,49 @@ +import prisma from "@/lib/prisma"; + +export default async function programKesehatanFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return Response.json({ + success: false, + message: "ID tidak boleh kosong", + }, { status: 400 }) + } + + try { + if (typeof id !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }) + } + + const data = await prisma.programKesehatan.findUnique({ + where: {id}, + include: { + image: true + } + }) + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }) + } + + return Response.json({ + success: true, + message: "Success fetch program kesehatan by ID", + data, + }, { status: 200 }) + } catch (error) { + console.error("Find by ID error:", error); + return Response.json({ + success: false, + message: "Gagal mengambil program kesehatan: " + (error instanceof Error ? error.message : 'Unknown error'), + }, { status: 500 }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/index.ts new file mode 100644 index 00000000..01c8268a --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/index.ts @@ -0,0 +1,41 @@ +import Elysia, { t } from "elysia"; +import programKesehatanCreate from "./create"; +import programKesehatanFindMany from "./find-many"; +import programKesehatanDelete from "./del"; +import programKesehatanFindUnique from "./findUnique"; +import programKesehatanUpdate from "./updt"; + +const ProgramKesehatan = new Elysia({ + prefix: "/programkesehatan", + tags: ["Kesehatan/Program Kesehatan"], +}) +.post("/create", programKesehatanCreate, { + body: t.Object({ + name: t.String(), + deskripsiSingkat: t.String(), + deskripsi: t.String(), + imageId: t.String(), + }) +}) +.get("/find-many", programKesehatanFindMany) +.delete("/del/:id", programKesehatanDelete) +.get("/:id", async (context) => { + const response = await programKesehatanFindUnique(new Request(context.request)); + return response; +}) +.put( + "/:id", + async (context) => { + const response = await programKesehatanUpdate(context); + return response; + }, + { + body: t.Object({ + name: t.String(), + deskripsiSingkat: t.String(), + deskripsi: t.String(), + imageId: t.String(), + }) + } +) +export default ProgramKesehatan; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/updt.ts new file mode 100644 index 00000000..0033b87c --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/program-kesehatan/updt.ts @@ -0,0 +1,115 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; +import path from "path"; +import fs from "fs/promises"; + +type FormUpdate = Prisma.ProgramKesehatanGetPayload<{ + select: { + id: true; + name: true; + deskripsiSingkat: true; + deskripsi: true; + imageId: true; + }; +}>; +export default async function programKesehatanUpdate(context: Context) { + try { + const id = context.params?.id as string; + const body = (await context.body) as Omit; + + const { name, deskripsiSingkat, deskripsi, imageId } = body; + + if (!id) { + return new Response( + JSON.stringify({ + success: false, + message: "ID tidak boleh kosong", + }), + { + status: 400, + headers: { + "Content-Type": "application/json", + }, + } + ); + } + + const existing = await prisma.programKesehatan.findUnique({ + where: { id }, + include: { + image: true, + }, + }); + + if (!existing) { + return new Response( + JSON.stringify({ + success: false, + message: "Program kesehatan tidak ditemukan", + }), + { + status: 404, + headers: { + "Content-Type": "application/json", + }, + } + ); + } + + if (existing.imageId && existing.imageId !== imageId) { + const oldImage = existing.image; + if (oldImage) { + try { + const filePath = path.join(oldImage.path, oldImage.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: oldImage.id }, + }); + } catch (err) { + console.error("Gagal hapus gambar lama:", err); + } + } + } + + const updated = await prisma.programKesehatan.update({ + where: { id }, + data: { + name, + deskripsiSingkat, + deskripsi, + imageId, + }, + }); + + return new Response( + JSON.stringify({ + success: true, + message: "Success update program kesehatan", + data: updated, + }), + { + status: 200, + headers: { + "Content-Type": "application/json", + }, + } + ); + } catch (error) { + console.error("Update error:", error); + return new Response( + JSON.stringify({ + success: false, + message: + "Gagal mengupdate program kesehatan: " + + (error instanceof Error ? error.message : "Unknown error"), + }), + { + status: 500, + headers: { + "Content-Type": "application/json", + }, + } + ); + } +} diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/create.ts new file mode 100644 index 00000000..44296f21 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/create.ts @@ -0,0 +1,69 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type JamOperasionalInput = { + workDays: string; + weekDays: string; + holiday: string; +}; + +type KontakPuskesmasInput = { + kontakPuskesmas: string; + email: string; + facebook: string; + kontakUGD: string; +}; + +type CreatePuskesmasInput = { + name: string; + alamat: string; + imageId: string; + jam: JamOperasionalInput; + kontak: KontakPuskesmasInput; +}; + +const puskesmasCreate = async (context: Context) => { + const { name, alamat, imageId, jam, kontak } = await context.body as CreatePuskesmasInput; + + // 1. Buat jam operasional + const createdJam = await prisma.jamOperasional.create({ + data: { + workDays: jam.workDays, + weekDays: jam.weekDays, + holiday: jam.holiday + } + }); + + // 2. Buat kontak puskesmas + const createdKontak = await prisma.kontakPuskesmas.create({ + data: { + kontakPuskesmas: kontak.kontakPuskesmas, + email: kontak.email, + facebook: kontak.facebook, + kontakUGD: kontak.kontakUGD + } + }); + + // 3. Buat puskesmas + const createdPuskesmas = await prisma.puskesmas.create({ + data: { + name, + alamat, + imageId, + jamId: createdJam.id, + kontakId: createdKontak.id + }, + include: { + image: true, + jam: true, + kontak: true + } + }); + + return { + success: true, + data: createdPuskesmas + }; +}; + +export default puskesmasCreate; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/del.ts new file mode 100644 index 00000000..7809dffe --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/del.ts @@ -0,0 +1,49 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; +import path from "path"; +import fs from "fs/promises"; + +const puskesmasDelete = async (context: Context) => { + const id = context.params?.id as string; + + if (!id) { + return { + status: 400, + body: "ID tidak diberikan", + }; + } + + const puskesmas = await prisma.puskesmas.findUnique({ + where: { id }, + include: { image: true, kontak: true, jam: true }, + }); + + if (!puskesmas) { + return { + status: 404, + body: "Puskesmas tidak ditemukan", + }; + } + + if (puskesmas.image) { + try { + const filePath = path.join(puskesmas.image.path, puskesmas.image.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: puskesmas.image.id }, + }); + } catch (error) { + console.error("Gagal hapus file image:", error); + } + } + + await prisma.puskesmas.delete({ + where: { id }, + }) + + return { + success: true, + message: "Puskesmas dan file terkait berhasil dihapus", + } +}; +export default puskesmasDelete; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/find-many.ts new file mode 100644 index 00000000..d485d94d --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/find-many.ts @@ -0,0 +1,27 @@ +import prisma from "@/lib/prisma"; + +export default async function puskesmasFindMany() { + try { + const data = await prisma.puskesmas.findMany({ + where: { + isActive: true, + }, + include: { + image: true, + jam: true, + kontak: true, + } + }) + return { + success: true, + message: "Success fetch puskesmas", + data, + } + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: "Failed fetch puskesmas", + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/findUnique.ts new file mode 100644 index 00000000..6613df7f --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/findUnique.ts @@ -0,0 +1,51 @@ +import prisma from "@/lib/prisma"; + +export default async function findUniquePuskesmas(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return Response.json({ + success: false, + message: "ID tidak boleh kosong", + }, { status: 400 }) + } + + try { + if (typeof id !== 'string') { + return Response.json({ + success: false, + message: "ID tidak valid", + }, { status: 400 }) + } + + const data = await prisma.puskesmas.findUnique({ + where: {id}, + include: { + image: true, + jam: true, + kontak: true, + } + }) + + if (!data) { + return Response.json({ + success: false, + message: "Data tidak ditemukan", + }, { status: 404 }) + } + + return Response.json({ + success: true, + message: "Success fetch puskesmas by ID", + data, + }, { status: 200 }) + } catch (error) { + console.error("Find by ID error:", error); + return Response.json({ + success: false, + message: "Gagal mengambil puskesmas: " + (error instanceof Error ? error.message : 'Unknown error'), + }, { status: 500 }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/index.ts new file mode 100644 index 00000000..c7387622 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/index.ts @@ -0,0 +1,62 @@ +import Elysia, { t } from "elysia"; +import puskesmasCreate from "./create"; +import puskesmasDelete from "./del"; +import puskesmasFindMany from "./find-many"; +import findUniquePuskesmas from "./findUnique"; +import puskesmasUpdate from "./updt"; + +const Puskesmas = new Elysia({ + prefix: "puskesmas", + tags: ["Kesehatan/Puskesmas"], +}) +.post("/create", puskesmasCreate, { + body: t.Object({ + name: t.String(), + alamat: t.String(), + imageId: t.String(), + jam: t.Object({ + workDays: t.String(), + weekDays: t.String(), + holiday: t.String(), + }), + kontak: t.Object({ + kontakPuskesmas: t.String(), + email: t.String(), + facebook: t.String(), + kontakUGD: t.String(), + }), + }), +}) +.get("/find-many", puskesmasFindMany) +.delete("/del/:id", puskesmasDelete) +.get("/:id", async (context) => { + const response = await findUniquePuskesmas(new Request(context.request)); + return response; + }) + .put( + "/:id", + async (context) => { + const response = await puskesmasUpdate(context); + return response; + }, + { + body: t.Object({ + name: t.String(), + alamat: t.String(), + imageId: t.String(), + jam: t.Object({ + workDays: t.String(), + weekDays: t.String(), + holiday: t.String(), + }), + kontak: t.Object({ + kontakPuskesmas: t.String(), + email: t.String(), + facebook: t.String(), + kontakUGD: t.String(), + }), + }), + } + ); + +export default Puskesmas; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/updt.ts new file mode 100644 index 00000000..e8ba06f0 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/puskesmas/updt.ts @@ -0,0 +1,139 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; +import path from "path"; +import fs from "fs/promises"; + +type FormUpdate = Prisma.PuskesmasGetPayload<{ + select: { + id: true; + name: true; + alamat: true; + jam: true; + imageId: true; + kontak: true; + }; +}>; + +export default async function puskesmasUpdate(context: Context) { + try { + const id = context.params?.id as string; + const body = (await context.body) as Omit; + + const { name, alamat, jam, imageId, kontak } = body; + + if (!id) { + return new Response( + JSON.stringify({ + success: false, + message: "ID tidak boleh kosong", + }), + { + status: 400, + headers: { + "Content-Type": "application/json", + }, + } + ); + } + + const existing = await prisma.puskesmas.findUnique({ + where: { id }, + include: { + image: true, + kontak: true, + jam: true, + }, + }); + + if (!existing) { + return new Response( + JSON.stringify({ + success: false, + message: "Puskesmas tidak ditemukan", + }), + { + status: 404, + headers: { + "Content-Type": "application/json", + }, + } + ); + } + + if (existing.imageId && existing.imageId !== imageId) { + const oldImage = existing.image; + if (oldImage) { + try { + const filePath = path.join(oldImage.path, oldImage.name); + await fs.unlink(filePath); + await prisma.fileStorage.delete({ + where: { id: oldImage.id }, + }); + } catch (err) { + console.error("Gagal hapus gambar lama:", err); + } + } + } + + await prisma.jamOperasional.update({ + where: { id: existing.jamId }, + data: { + workDays: jam.workDays, + weekDays: jam.weekDays, + holiday: jam.holiday, + }, + }); + + await prisma.kontakPuskesmas.update({ + where: { id: existing.kontakId }, + data: { + kontakPuskesmas: kontak.kontakPuskesmas, + email: kontak.email, + facebook: kontak.facebook, + kontakUGD: kontak.kontakUGD, + }, + }); + + const updated = await prisma.puskesmas.update({ + where: { id }, + data: { + name, + alamat, + jamId: jam.id, + imageId, + kontakId: kontak.id, + }, + }); + + return new Response( + JSON.stringify({ + success: true, + message: "Success update puskesmas", + data: updated, + }), + { + status: 200, + headers: { + "Content-Type": "application/json", + }, + } + ); + } catch (error) { + console.error("Update error:", error); + return new Response( + JSON.stringify({ + success: false, + message: + "Gagal update puskesmas: " + + (error instanceof Error ? error.message : "Unknown error"), + }), + { + status: 500, + headers: { + "Content-Type": "application/json", + }, + } + ); + } +}