diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f591974f..66c69e30 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -73,7 +73,7 @@ model FileStorage { Puskesmas Puskesmas[] ProgramKesehatan ProgramKesehatan[] PenangananDarurat PenangananDarurat[] - KontakDarurat KontakDarurat[] + KontakDarurat KontakDarurat[] InfoWabahPenyakit InfoWabahPenyakit[] } @@ -471,24 +471,24 @@ model Penghargaan { // ========================================= FASILITAS KESEHATAN ========================================= // model FasilitasKesehatan { - id String @id @default(cuid()) - name String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) - 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]) + id String @id @default(cuid()) + name String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + 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 + 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 { @@ -558,46 +558,46 @@ model TarifDanLayanan { // ========================================= JADWAL KEGIATAN ========================================= // model JadwalKegiatan { - id String @id @default(cuid()) - content String - informasijadwalkegiatan InformasiJadwalKegiatan @relation(fields: [informasiJadwalKegiatanId], references: [id]) - informasiJadwalKegiatanId String - deskripsijadwalkegiatan DeskripsiJadwalKegiatan @relation(fields: [deskripsiJadwalKegiatanId], references: [id]) - deskripsiJadwalKegiatanId String - layananjadwalkegiatan LayananJadwalKegiatan @relation(fields: [layananJadwalKegiatanId], references: [id]) - layananJadwalKegiatanId String - syaratketentuanjadwalkegiatan SyaratKetentuanJadwalKegiatan @relation(fields: [syaratKetentuanJadwalKegiatanId], references: [id]) + id String @id @default(cuid()) + content String + informasijadwalkegiatan InformasiJadwalKegiatan @relation(fields: [informasiJadwalKegiatanId], references: [id]) + informasiJadwalKegiatanId String + deskripsijadwalkegiatan DeskripsiJadwalKegiatan @relation(fields: [deskripsiJadwalKegiatanId], references: [id]) + deskripsiJadwalKegiatanId String + layananjadwalkegiatan LayananJadwalKegiatan @relation(fields: [layananJadwalKegiatanId], references: [id]) + layananJadwalKegiatanId String + syaratketentuanjadwalkegiatan SyaratKetentuanJadwalKegiatan @relation(fields: [syaratKetentuanJadwalKegiatanId], references: [id]) syaratKetentuanJadwalKegiatanId String - dokumenjadwalkegiatan DokumenJadwalKegiatan @relation(fields: [dokumenJadwalKegiatanId], references: [id]) - dokumenJadwalKegiatanId String - pendaftaranjadwalkegiatan PendaftaranJadwalKegiatan @relation(fields: [pendaftaranJadwalKegiatanId], references: [id]) - pendaftaranJadwalKegiatanId String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + dokumenjadwalkegiatan DokumenJadwalKegiatan @relation(fields: [dokumenJadwalKegiatanId], references: [id]) + dokumenJadwalKegiatanId String + pendaftaranjadwalkegiatan PendaftaranJadwalKegiatan @relation(fields: [pendaftaranJadwalKegiatanId], references: [id]) + pendaftaranJadwalKegiatanId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) } model InformasiJadwalKegiatan { - id String @id @default(cuid()) - name String - tanggal String - waktu String - lokasi String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + name String + tanggal String + waktu String + lokasi String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) JadwalKegiatan JadwalKegiatan[] } model DeskripsiJadwalKegiatan { - id String @id @default(cuid()) - deskripsi String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + deskripsi String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) JadwalKegiatan JadwalKegiatan[] } @@ -624,34 +624,34 @@ model SyaratKetentuanJadwalKegiatan { } model DokumenJadwalKegiatan { - id String @id @default(cuid()) - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) JadwalKegiatan JadwalKegiatan[] } model PendaftaranJadwalKegiatan { - id String @id @default(cuid()) - name String - tanggal String - namaOrangtua String - nomor String - alamat String - catatan String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + name String + tanggal String + namaOrangtua String + nomor String + alamat String + catatan String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) JadwalKegiatan JadwalKegiatan[] } // ========================================= PERSENTASE KELAHIRAN & KEMATIAN ========================================= // model DataKematian_Kelahiran { - id Int @id @default(autoincrement()) - uuid String @default(cuid()) @unique + id Int @id @default(autoincrement()) + uuid String @unique @default(cuid()) tahun String kematianKasar String kematianBayi String @@ -665,7 +665,7 @@ model DataKematian_Kelahiran { // ========================================= GRAFIK KEPUASAN ========================================= // model GrafikKepuasan { id Int @id @default(autoincrement()) - uuid String @default(cuid()) @unique + uuid String @unique @default(cuid()) label String jumlah String createdAt DateTime @default(now()) @@ -676,56 +676,74 @@ model GrafikKepuasan { // ========================================= ARTIKEL KESEHATAN ========================================= // model ArtikelKesehatan { - id String @id @default(cuid()) - title String - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + title String + content String + introduction Introduction @relation(fields: [introductionId], references: [id]) + introductionId String + symptom Symptom @relation(fields: [symptomId], references: [id]) + symptomId String + prevention Prevention @relation(fields: [preventionId], references: [id]) + preventionId String + firstaid FirstAid @relation(fields: [firstAidId], references: [id]) + firstAidId String + mythvsfact MythVsFact @relation(fields: [mythVsFactId], references: [id]) + mythVsFactId String + doctorsign DoctorSign @relation(fields: [doctorSignId], references: [id]) + doctorSignId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) } model Introduction { - id String @id @default(cuid()) - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + ArtikelKesehatan ArtikelKesehatan[] } model Symptom { - id String @id @default(cuid()) + id String @id @default(cuid()) title String content String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) + ArtikelKesehatan ArtikelKesehatan[] } model Prevention { - id String @id @default(cuid()) + id String @id @default(cuid()) title String content String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) + + ArtikelKesehatan ArtikelKesehatan[] } model FirstAid { - id String @id @default(cuid()) + id String @id @default(cuid()) title String content String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) + + ArtikelKesehatan ArtikelKesehatan[] } model MythVsFact { - id String @id @default(cuid()) + id String @id @default(cuid()) title String mitos String fakta String @@ -733,15 +751,19 @@ model MythVsFact { updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) + + ArtikelKesehatan ArtikelKesehatan[] } model DoctorSign { - id String @id @default(cuid()) + id String @id @default(cuid()) content String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) + + ArtikelKesehatan ArtikelKesehatan[] } // ========================================= POSYANDU ========================================= // @@ -839,16 +861,17 @@ model KontakDarurat { deletedAt DateTime @default(now()) isActive Boolean @default(true) } + // ========================================= INFO WABAH PENYAKIT ========================================= // model InfoWabahPenyakit { - id String @id @default(cuid()) - name String + 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) + 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/artikelKesehatan.ts b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan.ts index e750a7c9..50d1efd6 100644 --- a/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan.ts +++ b/src/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan.ts @@ -1,339 +1,306 @@ +/* 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"; -/* Introduction */ -const templateIntroduction = z.object({ - content: z.string().min(3, "Content minimal 3 karakter"), -}) +const templateForm = z.object({ + title: z.string().min(1, "Judul harus diisi"), + content: z.string().min(1, "Content harus diisi"), + introduction: z.object({ + content: z.string().min(1, "Content harus diisi"), + }), + symptom: z.object({ + title: z.string().min(1, "Judul harus diisi"), + content: z.string().min(1, "Content harus diisi"), + }), + prevention: z.object({ + title: z.string().min(1, "Judul harus diisi"), + content: z.string().min(1, "Content harus diisi"), + }), + firstAid: z.object({ + title: z.string().min(1, "Judul harus diisi"), + content: z.string().min(1, "Content harus diisi"), + }), + mythVsFact: z.object({ + title: z.string().min(1, "Judul harus diisi"), + mitos: z.string().min(1, "Mitos harus diisi"), + fakta: z.string().min(1, "Fakta harus diisi"), + }), + doctorSign: z.object({ + content: z.string().min(1, "Content harus diisi"), + }), +}); -type Introduction = Prisma.IntroductionGetPayload<{ - select: { - content: true; - }; -}>; +const defaultForm = { + title: "", + content: "", + introduction: { + content: "", + }, + symptom: { + title: "", + content: "", + }, + prevention: { + title: "", + content: "", + }, + firstAid: { + title: "", + content: "", + }, + mythVsFact: { + title: "", + mitos: "", + fakta: "", + }, + doctorSign: { + content: "", + }, +}; -const introduction = proxy({ +const artikelKesehatanState = proxy({ create: { - form: {} as Introduction, + form: { ...defaultForm }, loading: false, - async create() { - const cek = templateIntroduction.safeParse(introduction.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 { - introduction.create.loading = true; - const res = await ApiFetch.api.kesehatan.introduction["create"].post(introduction.create.form); + this.loading = true; + const payload = { ...this.form }; + + const res = await (ApiFetch.api.kesehatan as any)[ + "artikel-kesehatan" + ].create.post(payload); + if (res.status === 200) { - introduction.findMany.load(); - return toast.success("success create"); + toast.success("Berhasil menambahkan artikel kesehatan"); + this.resetForm(); + await artikelKesehatanState.findMany.load(); + return res.data; } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); + } catch (err: any) { + const msg = err?.message || "Terjadi kesalahan saat mengirim data"; + toast.error(msg); + console.error("SUBMIT ERROR:", err); + return null; } finally { - introduction.create.loading = false; + this.loading = false; } }, - }, - findMany: { - data: null as - | Prisma.IntroductionGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan.introduction["find-many"].get(); - if (res.status === 200) { - introduction.findMany.data = res.data?.data ?? []; - } - } - } -}); -/* ======================================================================= */ - -/* symptom */ -const templateSymptom = z.object({ - title: z.string().min(3, "Title minimal 3 karakter"), - content: z.string().min(3, "Content minimal 3 karakter"), -}) - -type Symptom = Prisma.SymptomGetPayload<{ - select: { - title: true; - content: true; - }; -}>; - -const symptom = proxy({ - create: { - form: {} as Symptom, - loading: false, - async create() { - const cek = templateSymptom.safeParse(symptom.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - symptom.create.loading = true; - const res = await ApiFetch.api.kesehatan.symptom["create"].post(symptom.create.form); - if (res.status === 200) { - symptom.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - symptom.create.loading = false; - } + resetForm() { + this.form = { ...defaultForm }; }, }, findMany: { data: null as - | Prisma.SymptomGetPayload<{ omit: { isActive: true } }>[] + | Prisma.ArtikelKesehatanGetPayload<{ + include: { + introduction: true; + symptom: true; + prevention: true; + firstaid: true; + mythvsfact: true; + doctorsign: true; + }; + }>[] | null, + loading: false, async load() { - const res = await ApiFetch.api.kesehatan.symptom["find-many"].get(); - if (res.status === 200) { - symptom.findMany.data = res.data?.data ?? []; + try { + this.loading = true; + const res = await (ApiFetch.api.kesehatan as any)["artikel-kesehatan"][ + "find-many" + ].get(); + + if (res.status === 200) { + this.data = res.data?.data ?? []; + } else { + toast.error("Gagal memuat data artikel 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.ArtikelKesehatanGetPayload<{ + include: { + introduction: true; + symptom: true; + prevention: true; + firstaid: true; + mythvsfact: true; + doctorsign: true; + }; + }> | null, + loading: false, + async load(id: string) { + const res = await fetch(`/api/kesehatan/artikel-kesehatan/${id}`); + if (res.ok) { + const data = await res.json(); + artikelKesehatanState.findUnique.data = data.data ?? null; + } else { + toast.error("Gagal load data artikel kesehatan"); + } + }, + }, + edit: { + id: "", + form: { ...defaultForm }, + loading: false, + async load(id: string) { + const res = await fetch(`/api/kesehatan/artikel-kesehatan/${id}`); + if (!res.ok) { + toast.error("Gagal load data artikel kesehatan"); + return; + } + + const result = await res.json(); + const data = result.data; + + artikelKesehatanState.edit.id = data.id; + artikelKesehatanState.edit.form = { + title: data.title, + content: data.content, + introduction: { + content: data.introduction.content, + }, + symptom: { + title: data.symptom.title, + content: data.symptom.content, + }, + prevention: { + title: data.prevention.title, + content: data.prevention.content, + }, + firstAid: { + title: data.firstaid.title, + content: data.firstaid.content, + }, + mythVsFact: { + title: data.mythvsfact.title, + mitos: data.mythvsfact.mitos, + fakta: data.mythvsfact.fakta, + }, + doctorSign: { + content: data.doctorsign.content, + }, + }; + }, + async submit() { + const cek = templateForm.safeParse(artikelKesehatanState.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 { + artikelKesehatanState.edit.loading = true; + const payload = { + title: artikelKesehatanState.edit.form.title, + content: artikelKesehatanState.edit.form.content, + introduction: { + content: artikelKesehatanState.edit.form.introduction.content, + }, + symptom: { + title: artikelKesehatanState.edit.form.symptom.title, + content: artikelKesehatanState.edit.form.symptom.content, + }, + prevention: { + title: artikelKesehatanState.edit.form.prevention.title, + content: artikelKesehatanState.edit.form.prevention.content, + }, + firstAid: { + title: artikelKesehatanState.edit.form.firstAid.title, + content: artikelKesehatanState.edit.form.firstAid.content, + }, + mythVsFact: { + title: artikelKesehatanState.edit.form.mythVsFact.title, + mitos: artikelKesehatanState.edit.form.mythVsFact.mitos, + fakta: artikelKesehatanState.edit.form.mythVsFact.fakta, + }, + doctorSign: { + content: artikelKesehatanState.edit.form.doctorSign.content, + }, + }; + + const res = await fetch( + `/api/kesehatan/artikel-kesehatan/${artikelKesehatanState.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 artikel kesehatan"); + await artikelKesehatanState.findMany.load(); + return true; + } catch (err) { + toast.error( + err instanceof Error ? err.message : "Terjadi kesalahan saat update" + ); + return false; + } finally { + artikelKesehatanState.edit.loading = false; + } + }, + resetForm() { + artikelKesehatanState.edit.id = ""; + artikelKesehatanState.edit.form = { ...defaultForm }; + }, + }, + delete: { + loading: false, + async byId(id: string) { + try { + artikelKesehatanState.delete.loading = true; + const res = await fetch( + `/api/kesehatan/artikel-kesehatan/del/${id}`, + { + method: "DELETE", + } + ); + + const result = await res.json(); + if (res.ok && result.success) { + toast.success("Artikel kesehatan berhasil dihapus"); + await artikelKesehatanState.findMany.load(); + } else { + toast.error(result.message || "Gagal menghapus"); + } + } catch { + toast.error("Terjadi kesalahan saat menghapus"); + } finally { + artikelKesehatanState.delete.loading = false; } }, }, }); -/* ======================================================================= */ -/* Prevention */ -const templatePrevention = z.object({ - title: z.string().min(3, "Title minimal 3 karakter"), - content: z.string().min(3, "Content minimal 3 karakter"), -}) - -type Prevention = Prisma.PreventionGetPayload<{ - select: { - title: true; - content: true; - }; -}>; - -const prevention = proxy({ - create: { - form: {} as Prevention, - loading: false, - async create() { - const cek = templatePrevention.safeParse(prevention.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - prevention.create.loading = true; - const res = await ApiFetch.api.kesehatan.prevention["create"].post(prevention.create.form); - if (res.status === 200) { - prevention.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - prevention.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.PreventionGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan.prevention["find-many"].get(); - if (res.status === 200) { - prevention.findMany.data = res.data?.data ?? []; - } - }, - }, -}); -/* ======================================================================= */ - -/* First Aid */ -const templateFirstAid = z.object({ - title: z.string().min(3, "Title minimal 3 karakter"), - content: z.string().min(3, "Content minimal 3 karakter"), -}) - -type FirstAid = Prisma.FirstAidGetPayload<{ - select: { - title: true; - content: true; - }; -}>; - -const firstAid = proxy({ - create: { - form: {} as FirstAid, - loading: false, - async create() { - const cek = templateFirstAid.safeParse(firstAid.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - firstAid.create.loading = true; - const res = await ApiFetch.api.kesehatan.firstaid["create"].post(firstAid.create.form); - if (res.status === 200) { - firstAid.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - firstAid.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.FirstAidGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan.firstaid["find-many"].get(); - if (res.status === 200) { - firstAid.findMany.data = res.data?.data ?? []; - } - }, - }, -}) -/* ======================================================================= */ - -/* Myth vs Fact */ -const templateMythFact = z.object({ - title: z.string().min(3, "Title minimal 3 karakter"), - mitos: z.string().min(3, "Mitos minimal 3 karakter"), - fakta: z.string().min(3, "Fakta minimal 3 karakter"), -}) - -type MythFact = Prisma.MythVsFactGetPayload<{ - select: { - title: true; - mitos: true; - fakta: true; - }; -}>; - -const mythFact = proxy({ - create: { - form: {} as MythFact, - loading: false, - async create() { - const cek = templateMythFact.safeParse(mythFact.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - mythFact.create.loading = true; - const res = await ApiFetch.api.kesehatan.mythvsfact["create"].post(mythFact.create.form); - if (res.status === 200) { - mythFact.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - mythFact.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.MythVsFactGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan.mythvsfact["find-many"].get(); - if (res.status === 200) { - mythFact.findMany.data = res.data?.data ?? []; - } - }, - }, -}) -/* ======================================================================= */ - -/* Doctor Sign */ -const templateDoctorSign = z.object({ - content: z.string().min(3, "Content minimal 3 karakter"), -}) - -type DoctorSign = Prisma.DoctorSignGetPayload<{ - select: { - content: true - } -}> - -const doctorSign = proxy({ - create: { - form: {} as DoctorSign, - loading: false, - async create() { - const cek = templateDoctorSign.safeParse(doctorSign.create.form); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - doctorSign.create.loading = true; - const res = await ApiFetch.api.kesehatan.doctor_sign["create"].post(doctorSign.create.form); - if (res.status === 200) { - doctorSign.findMany.load(); - return toast.success("success create"); - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - doctorSign.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.DoctorSignGetPayload<{ omit: { isActive: true } }>[] - | null, - async load() { - const res = await ApiFetch.api.kesehatan.doctor_sign["find-many"].get(); - if (res.status === 200) { - doctorSign.findMany.data = res.data?.data ?? []; - } - }, - }, -}) - -/* ======================================================================= */ - -const stateArtikelKesehatan = proxy({ - introduction, - symptom, - prevention, - firstAid, - mythFact, - doctorSign -}) - -export default stateArtikelKesehatan \ No newline at end of file +export default artikelKesehatanState; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/[id]/edit/page.tsx new file mode 100644 index 00000000..a3be391c --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/[id]/edit/page.tsx @@ -0,0 +1,374 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' + +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; +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 ArtikelKesehatanFormBase { + title: string; + content: string; + introduction: { + content: string; + }; + symptom: { + title: string; + content: string; + }; + prevention: { + title: string; + content: string; + }; + firstAid: { + title: string; + content: string; + }; + mythVsFact: { + title: string; + mitos: string; + fakta: string; + }; + doctorSign: { + content: string; + }; +} + +function EditArtikelKesehatan() { + const stateArtikelKesehatan = useProxy(artikelKesehatanState); + const router = useRouter(); + const params = useParams(); + + const [formData, setFormData] = useState({ + title: stateArtikelKesehatan.edit.form.title || '', + content: stateArtikelKesehatan.edit.form.content || '', + introduction: { + content: stateArtikelKesehatan.edit.form.introduction?.content || '', + }, + symptom: { + title: stateArtikelKesehatan.edit.form.symptom?.title || '', + content: stateArtikelKesehatan.edit.form.symptom?.content || '', + }, + prevention: { + title: stateArtikelKesehatan.edit.form.prevention?.title || '', + content: stateArtikelKesehatan.edit.form.prevention?.content || '', + }, + firstAid: { + title: stateArtikelKesehatan.edit.form.firstAid?.title || '', + content: stateArtikelKesehatan.edit.form.firstAid?.content || '', + }, + mythVsFact: { + title: stateArtikelKesehatan.edit.form.mythVsFact?.title || '', + mitos: stateArtikelKesehatan.edit.form.mythVsFact?.mitos || '', + fakta: stateArtikelKesehatan.edit.form.mythVsFact?.fakta || '', + }, + doctorSign: { + content: stateArtikelKesehatan.edit.form.doctorSign?.content || '', + }, + }); + + useEffect(() => { + const loadArtikelKesehatan = async () => { + const id = params?.id as string; + if (!id) return; + + try { + await stateArtikelKesehatan.edit.load(id); + const { form } = stateArtikelKesehatan.edit; + if (form) { + setFormData({ + title: form.title, + content: form.content, + introduction: { + content: form.introduction?.content || '', + }, + symptom: { + title: form.symptom?.title || '', + content: form.symptom?.content || '', + }, + prevention: { + title: form.prevention?.title || '', + content: form.prevention?.content || '', + }, + firstAid: { + title: form.firstAid?.title || '', + content: form.firstAid?.content || '', + }, + mythVsFact: { + title: form.mythVsFact?.title || '', + mitos: form.mythVsFact?.mitos || '', + fakta: form.mythVsFact?.fakta || '', + }, + doctorSign: { + content: form.doctorSign?.content || '', + }, + }); + } + } catch (error) { + console.error("Error loading artikel kesehatan:", error); + toast.error("Gagal memuat data artikel kesehatan"); + } + }; + loadArtikelKesehatan(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + stateArtikelKesehatan.edit.form = { + ...stateArtikelKesehatan.edit.form, + title: formData.title, + content: formData.content, + introduction: { + content: formData.introduction.content, + }, + symptom: { + title: formData.symptom.title, + content: formData.symptom.content, + }, + prevention: { + title: formData.prevention.title, + content: formData.prevention.content, + }, + firstAid: { + title: formData.firstAid.title, + content: formData.firstAid.content, + }, + mythVsFact: { + title: formData.mythVsFact.title, + mitos: formData.mythVsFact.mitos, + fakta: formData.mythVsFact.fakta, + }, + doctorSign: { + content: formData.doctorSign.content, + }, + }; + const success = await stateArtikelKesehatan.edit.submit(); + if (success) { + toast.success("Artikel kesehatan berhasil diperbarui!"); + router.push("/admin/kesehatan/data-kesehatan-warga/artikel_kesehatan"); + } + } catch (error) { + console.error("Error updating artikel kesehatan:", error); + toast.error(error instanceof Error ? error.message : "Gagal memperbarui data artikel kesehatan"); + } + }; + return ( + + + + + + + Edit Artikel Kesehatan + Judul} + placeholder="masukkan judul" + value={formData.title} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + title: e.target.value + })); + }} + /> + Deskripsi} + placeholder="masukkan deskripsi" + value={formData.content} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + content: e.target.value + })); + }} + /> + Pendahuluan} + placeholder="masukkan pendahuluan" + value={formData.introduction.content} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + introduction: { + ...prev.introduction, + content: e.target.value + } + })); + }} + /> + + Gejala + + Judul} + placeholder="masukkan judul gejala penyakit" + value={formData.symptom.title} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + symptom: { + ...prev.symptom, + title: e.target.value + } + })); + }} + /> + + Deskripsi Gejala + { + setFormData(prev => ({ + ...prev, + symptom: { + ...prev.symptom, + content: e + } + })); + }} + /> + + + + + + Pencegahan + Judul} + placeholder="masukkan judul" + value={formData.prevention.title} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + prevention: { + ...prev.prevention, + title: e.target.value + } + })); + }} + /> + { + setFormData(prev => ({ + ...prev, + prevention: { + ...prev.prevention, + content: e + } + })); + }} + /> + + + Pertolongan Pertama + Judul} + placeholder="masukkan judul" + value={formData.firstAid.title} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + firstAid: { + ...prev.firstAid, + title: e.target.value + } + })); + }} + /> + { + setFormData(prev => ({ + ...prev, + firstAid: { + ...prev.firstAid, + content: e + } + })); + }} + /> + + + Mitos dan Fakta + Judul} + placeholder="masukkan judul" + value={formData.mythVsFact.title} + onChange={(e) => { + setFormData(prev => ({ + ...prev, + mythVsFact: { + ...prev.mythVsFact, + title: e.target.value + } + })); + }} + /> + + + Mitos + + { + setFormData(prev => ({ + ...prev, + mythVsFact: { + ...prev.mythVsFact, + mitos: e + } + })); + }} + /> + + + + Fakta + + { + setFormData(prev => ({ + ...prev, + mythVsFact: { + ...prev.mythVsFact, + fakta: e + } + })); + }} + /> + + + + Kapan Harus Ke Dokter + { + setFormData(prev => ({ + ...prev, + doctorSign: { + ...prev.doctorSign, + content: e + } + })); + }} + /> + + + + + + ); +} + +export default EditArtikelKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/[id]/page.tsx new file mode 100644 index 00000000..d5202321 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/[id]/page.tsx @@ -0,0 +1,143 @@ +'use client' +import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus'; +import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; +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 DetailArtikelKesehatan() { + const params = useParams() + const router = useRouter(); + const stateArtikelKesehatan = useProxy(artikelKesehatanState) + const [modalHapus, setModalHapus] = useState(false); + const [selectedId, setSelectedId] = useState(null) + + useShallowEffect(() => { + stateArtikelKesehatan.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + stateArtikelKesehatan.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/data-kesehatan-warga/artikel_kesehatan") + } + } + + if (!stateArtikelKesehatan.findUnique.data) { + return ( + + + + ) + } + + + return ( + + + + + + + Detail Artikel Kesehatan + {stateArtikelKesehatan.findUnique.data ? ( + + + + Judul + {stateArtikelKesehatan.findUnique.data.title} + + + Deskripsi + + + + Pendahuluan + + + + + Gejala + Judul Gejala + {stateArtikelKesehatan.findUnique.data.symptom.title} + Deskripsi Gejala + + + + + + Pencegahan + Judul Pencegahan + {stateArtikelKesehatan.findUnique.data.prevention.title} + Deskripsi Pencegahan + + + + + + Pertolongan Pertama + Judul Pertolongan Pertama + {stateArtikelKesehatan.findUnique.data.firstaid.title} + Deskripsi Pertolongan Pertama + + + + + + Mitos dan Fakta + Judul Mitos dan Fakta + {stateArtikelKesehatan.findUnique.data.mythvsfact.title} + Deskripsi Mitos + + Deskripsi Fakta + + + + + + Kapan Harus ke Dokter + Deskripsi Kapan Harus ke Dokter + + + + + + + + + + + + ) : null} + + + + {/* Modal Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text="Apakah anda yakin ingin menghapus artikel kesehatan ini?" + /> + + ); +} + +export default DetailArtikelKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/create/page.tsx new file mode 100644 index 00000000..3aeab04f --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/create/page.tsx @@ -0,0 +1,203 @@ +'use client' +import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor'; +import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; +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 CreateArtikelKesehatan() { + const stateArtikelKesehatan = useProxy(artikelKesehatanState) + const router = useRouter(); + + + const resetForm = () => { + stateArtikelKesehatan.create.form = { + title: "", + content: "", + introduction: { + content: "", + }, + symptom: { + title: "", + content: "", + }, + prevention: { + title: "", + content: "", + }, + firstAid: { + title: "", + content: "", + }, + mythVsFact: { + title: "", + mitos: "", + fakta: "", + }, + doctorSign: { + content: "" + } + }; + }; + + + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + await stateArtikelKesehatan.create.submit(); + + toast.success("Data berhasil disimpan"); + resetForm(); + // After successful submission, redirect to the list page + router.push('/admin/kesehatan/data-kesehatan-warga/artikel_kesehatan'); + } + + return ( + + + + + + + + Create Artikel Kesehatan + Judul} + placeholder="masukkan judul" + value={stateArtikelKesehatan.create.form.title} + onChange={(e) => { + stateArtikelKesehatan.create.form.title = e.target.value; + }} + /> + Deskripsi} + placeholder="masukkan deskripsi" + value={stateArtikelKesehatan.create.form.content} + onChange={(e) => { + stateArtikelKesehatan.create.form.content = e.target.value; + }} + /> + Pendahuluan} + placeholder="masukkan pendahuluan" + value={stateArtikelKesehatan.create.form.introduction.content} + onChange={(e) => { + stateArtikelKesehatan.create.form.introduction.content = e.target.value; + }} + /> + + Gejala + + Judul} + placeholder="masukkan judul gejala penyakit" + value={stateArtikelKesehatan.create.form.symptom.title} + onChange={(e) => { + stateArtikelKesehatan.create.form.symptom.title = e.target.value; + }} + /> + + Deskripsi Gejala + { + stateArtikelKesehatan.create.form.symptom.content = e; + }} + /> + + + + + + Pencegahan + Judul} + placeholder="masukkan judul" + value={stateArtikelKesehatan.create.form.prevention.title} + onChange={(e) => { + stateArtikelKesehatan.create.form.prevention.title = e.target.value; + }} + /> + { + stateArtikelKesehatan.create.form.prevention.content = e; + }} + /> + + + Pertolongan Pertama + Judul} + placeholder="masukkan judul" + value={stateArtikelKesehatan.create.form.firstAid.title} + onChange={(e) => { + stateArtikelKesehatan.create.form.firstAid.title = e.target.value; + }} + /> + { + stateArtikelKesehatan.create.form.firstAid.content = e; + }} + /> + + + Mitos dan Fakta + Judul} + placeholder="masukkan judul" + value={stateArtikelKesehatan.create.form.mythVsFact.title} + onChange={(e) => { + stateArtikelKesehatan.create.form.mythVsFact.title = e.target.value; + }} + /> + + + Mitos + + { + stateArtikelKesehatan.create.form.mythVsFact.mitos = e; + }} + /> + + + + Fakta + + { + stateArtikelKesehatan.create.form.mythVsFact.fakta = e; + }} + /> + + + + Kapan Harus Ke Dokter + { + stateArtikelKesehatan.create.form.doctorSign.content = e; + }} + /> + + + + + + + ); +} + +export default CreateArtikelKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/doctor_sign/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/doctor_sign/page.tsx deleted file mode 100644 index 6f09affc..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/doctor_sign/page.tsx +++ /dev/null @@ -1,25 +0,0 @@ -'use client' -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) - return ( - - - Kapan Harus ke Dokter - { - doctorSign.create.form.content = val - }} - /> - - - ); -} - -export default DoctorSignUI; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/first_aid/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/first_aid/page.tsx deleted file mode 100644 index 71a082a5..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/first_aid/page.tsx +++ /dev/null @@ -1,33 +0,0 @@ -'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'; - -function FirstAidUI() { - const firstAidState = useProxy(stateArtikelKesehatan.firstAid) - return ( - - - - Judul Pertolongan Pertama} - placeholder="Masukkan judul" - onChange={(val) => { - firstAidState.create.form.title = val.target.value - }} - /> - { - firstAidState.create.form.content = val - }} - /> - - - - ); -} - -export default FirstAidUI; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/introduction/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/introduction/page.tsx deleted file mode 100644 index 95eefb74..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/introduction/page.tsx +++ /dev/null @@ -1,28 +0,0 @@ -'use client' -import { Box, Paper, Stack, Text } from '@mantine/core'; -import React from 'react'; -import { useProxy } from 'valtio/utils'; -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) - return ( - - - - Pendahuluan - { - introduction.create.form.content = val; - }} - /> - - - - ); -} - -export default IntoductionUI; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/mythVsfact/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/mythVsfact/page.tsx deleted file mode 100644 index 6a22d179..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/mythVsfact/page.tsx +++ /dev/null @@ -1,40 +0,0 @@ -'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'; - -function MythFactUI() { - const mythFact = useProxy(stateArtikelKesehatan.mythFact) - return ( - - - - Judul Pertolongan Pertama Penyakit} - placeholder="Masukkan judul" - onChange={(val) => { - mythFact.create.form.title = val.target.value - }} - /> - Mitos} - placeholder="Masukkan mitos" - onChange={(val) => { - mythFact.create.form.mitos = val.target.value - }} - /> - Fakta} - placeholder="Masukkan fakta" - onChange={(val) => { - mythFact.create.form.fakta = val.target.value - }} - /> - - - - ); -} - -export default MythFactUI; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/page.tsx index fb964e67..5946a042 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/page.tsx @@ -1,172 +1,79 @@ 'use client' -import { Box, Button, Center, Group, Paper, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core'; -import IntoductionUI from './introduction/page'; -import SymptomUI from './symptom/page'; -import PreventionUI from './prevention/page'; -import MythFactUI from './mythVsfact/page'; -import DoctorSignUI from './doctor_sign/page'; -import { useProxy } from 'valtio/utils'; -import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; -import FirstAidUI from './first_aid/page'; -import { useShallowEffect } from '@mantine/hooks'; 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 HeaderSearch from '../../../_com/header'; +import JudulList from '../../../_com/judulList'; +import artikelKesehatanState from '../../../_state/kesehatan/data_kesehatan_warga/artikelKesehatan'; + function ArtikelKesehatan() { - const state = useProxy(stateArtikelKesehatan) - const submitAllForms = () => { - if (state.introduction.create.form.content) { - state.introduction.create.create() - } - if (state.symptom.create.form.title && state.symptom.create.form.content) { - state.symptom.create.create() - } - if (state.prevention.create.form.title && state.prevention.create.form.content) { - state.prevention.create.create() - } - if (state.firstAid.create.form.title && state.firstAid.create.form.content) { - state.firstAid.create.create() - } - if (state.mythFact.create.form.title && state.mythFact.create.form.mitos && state.mythFact.create.form.fakta) { - state.mythFact.create.create() - } - if (state.doctorSign.create.form.content) { - state.doctorSign.create.create() - } - } return ( - - - - - Artikel Kesehatan - - - - - - - - - - - - - - - Data Artikel Kesehatan - - - - - + + } + /> + + ); } -function AllList() { - const listState = useProxy(stateArtikelKesehatan) +function ListArtikelKesehatan() { + const stateArtikelKesehatan = useProxy(artikelKesehatanState) + const router = useRouter(); + useShallowEffect(() => { - listState.introduction.findMany.load(); - listState.symptom.findMany.load(); - listState.prevention.findMany.load(); - listState.firstAid.findMany.load(); - listState.mythFact.findMany.load(); - listState.doctorSign.findMany.load(); + stateArtikelKesehatan.findMany.load() }, []) - if (!listState.introduction.findMany.data - || !listState.symptom.findMany.data - || !listState.prevention.findMany.data - || !listState.firstAid.findMany.data - || !listState.mythFact.findMany.data - || !listState.doctorSign.findMany.data - ) return - {Array.from({ length: 10 }).map((v, k) => )} - - return - {/* Introduction */} + if (!stateArtikelKesehatan.findMany.data) { + return ( + + + + ) + } + return ( + - Pendahuluan - {listState.introduction.findMany.data?.map((item) => ( - - - - ))} - - {/* Symptom */} - - Gejala Penyakit - {listState.symptom.findMany.data?.map((item) => ( - - {item.title} - - - ))} - - {/* Prevention */} - - Pencegahan Penyakit - {listState.prevention.findMany.data?.map((item) => ( - - {item.title} - - - ))} - - {/* First Aid */} - - Pertolongan Pertama - {listState.firstAid.findMany.data?.map((item) => ( - - {item.title} - - - ))} - - {/* Myth Fact */} - - Mitos vs Fakta - {listState.mythFact.findMany.data?.map((item) => ( - - {item.title} - - - - -
Mitos
-
- -
Fakta
-
+ + + +
+ + + Judul + Content + Detail - - - {item.mitos} - {item.fakta} - + + {stateArtikelKesehatan.findMany.data?.map((item) => ( + + {item.title} + {item.content} + + + + + ))}
- ))} +
- {/* Doctor Sign */} - - Kapan Harus Ke Dokter? - {listState.doctorSign.findMany.data?.map((item) => ( - - - - ))} - - + + ) } -export default ArtikelKesehatan; \ No newline at end of file +export default ArtikelKesehatan; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/prevention/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/prevention/page.tsx deleted file mode 100644 index 5dd3533d..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/prevention/page.tsx +++ /dev/null @@ -1,34 +0,0 @@ -'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'; - -function PreventionUI() { - const preventionState = useProxy(stateArtikelKesehatan.prevention) - return ( - - - - Judul Pencegahan Penyakit} - placeholder="Masukkan judul" - onChange={(val) => { - preventionState.create.form.title = val.target.value - }} - /> - { - preventionState.create.form.content = val - }} - /> - - - - ); -} - -export default PreventionUI; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/symptom/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/symptom/page.tsx deleted file mode 100644 index d5f3f302..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/artikel_kesehatan/symptom/page.tsx +++ /dev/null @@ -1,34 +0,0 @@ -'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'; - -function SymptomUI() { - const symptomState = useProxy(stateArtikelKesehatan.symptom) - return ( - - - - Judul Gejala Penyakit} - placeholder='masukkan judul' - onChange={(val) => { - symptomState.create.form.title = val.target.value - }} - /> - { - symptomState.create.form.content = val - }} - /> - - - - ); -} - -export default SymptomUI; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/create.ts new file mode 100644 index 00000000..4bef83d7 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/create.ts @@ -0,0 +1,55 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type ArtikelKesehatanInput = { + title: string; + content: string; + introduction: {content: string}; + symptom: {title: string; content: string}; + prevention: {title: string; content: string}; + firstAid: {title: string; content: string}; + mythVsFact: {title: string; mitos: string; fakta: string}; + doctorSign: {content: string}; +} + +const artikelKesehatanCreate = async (context: Context) => { + const body = await context.body as ArtikelKesehatanInput; + const { title, content, introduction, symptom, prevention, firstAid, mythVsFact, doctorSign } = body; + + const [createdIntroduction, createdSymptom, createdPrevention, createdFirstAid, createdMythVsFact, createdDoctorSign] = await Promise.all([ + prisma.introduction.create({ data: introduction }), + prisma.symptom.create({ data: symptom }), + prisma.prevention.create({ data: prevention }), + prisma.firstAid.create({ data: firstAid }), + prisma.mythVsFact.create({ data: mythVsFact }), + prisma.doctorSign.create({ data: doctorSign }), + ]) + + const artikelKesehatan = await prisma.artikelKesehatan.create({ + data: { + title, + content, + introductionId: createdIntroduction.id, + symptomId: createdSymptom.id, + preventionId: createdPrevention.id, + firstAidId: createdFirstAid.id, + mythVsFactId: createdMythVsFact.id, + doctorSignId: createdDoctorSign.id, + }, + include: { + introduction: true, + symptom: true, + prevention: true, + firstaid: true, + mythvsfact: true, + doctorsign: true, + } + }) + + return { + success: true, + message: "Success create artikel kesehatan", + data: artikelKesehatan, + } +} +export default artikelKesehatanCreate; // export the function \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/del.ts new file mode 100644 index 00000000..16d72781 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/del.ts @@ -0,0 +1,41 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +const artikelKesehatanDelete = async (context: Context) => { + const id = context.params?.id as string; + + if (!id) { + return { + status: 400, + message: "ID tidak ditemukan", + } + } + + const artikelKesehatan = await prisma.artikelKesehatan.findUnique({ + where: { id }, + include: { + introduction: true, + symptom: true, + prevention: true, + firstaid: true, + mythvsfact: true, + doctorsign: true, + } + }) + + if (!artikelKesehatan) { + return { + status: 404, + message: "Artikel kesehatan tidak ditemukan", + } + } + + await prisma.artikelKesehatan.delete({ where: { id } }) + + return { + status: 200, + success: true, + message: "Artikel kesehatan berhasil dihapus", + } +} +export default artikelKesehatanDelete; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/findMany.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/findMany.ts new file mode 100644 index 00000000..e48379df --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/findMany.ts @@ -0,0 +1,30 @@ +import prisma from "@/lib/prisma"; + +export default async function artikelKesehatanFindMany() { + try { + const data = await prisma.artikelKesehatan.findMany({ + where: { + isActive: true, + }, + include: { + introduction: true, + symptom: true, + prevention: true, + firstaid: true, + mythvsfact: true, + doctorsign: true, + } + }) + return { + success: true, + message: "Success fetch artikel kesehatan", + data, + } + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: "Failed fetch artikel kesehatan", + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/findUnique.ts new file mode 100644 index 00000000..8568ccaa --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/findUnique.ts @@ -0,0 +1,52 @@ +import prisma from "@/lib/prisma"; + +export async function artikelKesehatanFindUnique(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.artikelKesehatan.findUnique({ + where: {id}, + include: { + introduction: true, + symptom: true, + prevention: true, + firstaid: true, + mythvsfact: true, + doctorsign: 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("Find unique error:", error); + return Response.json({ + success: false, + message: "Failed fetch artikel kesehatan", + }, { status: 500 }) + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/index.ts new file mode 100644 index 00000000..0f1c5f70 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/index.ts @@ -0,0 +1,85 @@ +import Elysia, { t } from "elysia"; +import artikelKesehatanCreate from "./create"; +import artikelKesehatanFindMany from "./findMany"; +import artikelKesehatanDelete from "./del"; +import { artikelKesehatanFindUnique } from "./findUnique"; +import artikelKesehatanUpdate from "./updt"; + +const ArtikelKesehatan = new Elysia({ + prefix: "artikel-kesehatan", + tags: ["Kesehatan/Artikel Kesehatan"], +}) + .post("/create", artikelKesehatanCreate, { + body: t.Object({ + title: t.String(), + content: t.String(), + introduction: t.Object({ + content: t.String(), + }), + symptom: t.Object({ + title: t.String(), + content: t.String(), + }), + prevention: t.Object({ + title: t.String(), + content: t.String(), + }), + firstAid: t.Object({ + title: t.String(), + content: t.String(), + }), + mythVsFact: t.Object({ + title: t.String(), + mitos: t.String(), + fakta: t.String(), + }), + doctorSign: t.Object({ + content: t.String(), + }), + }), + }) + .get("/find-many", artikelKesehatanFindMany) + .delete("/del/:id", artikelKesehatanDelete) + .get("/:id", async (context) => { + const response = await artikelKesehatanFindUnique( + new Request(context.request) + ); + return response; + }) + .put( + "/:id", + async (context) => { + const response = await artikelKesehatanUpdate(context); + return response; + }, + { + body: t.Object({ + title: t.String(), + content: t.String(), + introduction: t.Object({ + content: t.String(), + }), + symptom: t.Object({ + title: t.String(), + content: t.String(), + }), + prevention: t.Object({ + title: t.String(), + content: t.String(), + }), + firstAid: t.Object({ + title: t.String(), + content: t.String(), + }), + mythVsFact: t.Object({ + title: t.String(), + mitos: t.String(), + fakta: t.String(), + }), + doctorSign: t.Object({ + content: t.String(), + }), + }), + } + ); +export default ArtikelKesehatan; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/updt.ts new file mode 100644 index 00000000..7bc4c9c6 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/artikel_kesehatan/updt.ts @@ -0,0 +1,106 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type ArtikelKesehatanInput = { + title: string; + content: string; + introduction: { content: string }; + symptom: { title: string; content: string }; + prevention: { title: string; content: string }; + firstAid: { title: string; content: string }; + mythVsFact: { title: string; mitos: string; fakta: string }; + doctorSign: { content: string }; +}; + +const artikelKesehatanUpdate = async (context: Context) => { + const id = context.params?.id as string; + const body = (await context.body) as ArtikelKesehatanInput; + + if (!id) { + return new Response( + JSON.stringify({ + success: false, + message: "ID is required", + }), + { + status: 400, + headers: { + "Content-Type": "application/json", + }, + } + ); + } + + const existing = await prisma.artikelKesehatan.findUnique({ + where: { id }, + }); + + if (!existing) { + return new Response( + JSON.stringify({ success: false, message: "Data not found" }), + { status: 404, headers: { "Content-Type": "application/json" } } + ); + } + + const { + title, + content, + introduction, + symptom, + prevention, + firstAid, + mythVsFact, + doctorSign, + } = body; + + await Promise.all([ + prisma.introduction.update({ + where: { id: existing.introductionId }, + data: introduction, + }), + prisma.symptom.update({ + where: { id: existing.symptomId }, + data: symptom, + }), + prisma.prevention.update({ + where: { id: existing.preventionId }, + data: prevention, + }), + prisma.firstAid.update({ + where: { id: existing.firstAidId }, + data: firstAid, + }), + prisma.mythVsFact.update({ + where: { id: existing.mythVsFactId }, + data: mythVsFact, + }), + prisma.doctorSign.update({ + where: { id: existing.doctorSignId }, + data: doctorSign, + }), + ]); + + const updated = await prisma.artikelKesehatan.update({ + where: { id }, + data: { + title, + content + }, + include: { + introduction: true, + symptom: true, + prevention: true, + firstaid: true, + mythvsfact: true, + doctorsign: true, + }, + }); + + return { + status: 200, + success: true, + message: "Artikel kesehatan berhasil dihapus", + data: updated, + }; +}; +export default artikelKesehatanUpdate; diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts index 50222cd4..b9c0cbbc 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts @@ -15,6 +15,7 @@ import ProgramKesehatan from "./program-kesehatan"; import Puskesmas from "./puskesmas"; import FasilitasKesehatan from "./data_kesehatan_warga/fasilitas_kesehatan"; import JadwalKegiatan from "./data_kesehatan_warga/jadwal_kegiatan"; +import ArtikelKesehatan from "./data_kesehatan_warga/artikel_kesehatan"; const Kesehatan = new Elysia({ @@ -37,4 +38,5 @@ const Kesehatan = new Elysia({ .use(InfoWabahPenyakit) .use(FasilitasKesehatan) .use(JadwalKegiatan) +.use(ArtikelKesehatan); export default Kesehatan;