From d7a592c6354c508dba2d9161eec51133ad0be7c1 Mon Sep 17 00:00:00 2001 From: nico Date: Thu, 14 Aug 2025 20:47:07 +0800 Subject: [PATCH] Fix UI & API Admin Menu Kesehatan, Submenu Data Kesehatan Warga Bagian ChartBar --- prisma/schema.prisma | 45 +- .../persentaseKelahiran.ts | 596 +++++++++++++++++- .../[id]/page.tsx | 113 ---- .../create/page.tsx | 101 --- .../kelahiran/[id]/edit/page.tsx | 107 ++++ .../kelahiran/[id]/page.tsx | 121 ++++ .../kelahiran/create/page.tsx | 83 +++ .../kelahiran/page.tsx | 118 ++++ .../kematian/[id]/edit/page.tsx | 121 ++++ .../kematian/[id]/page.tsx | 126 ++++ .../kematian/create/page.tsx | 94 +++ .../kematian/page.tsx | 118 ++++ .../page.tsx | 342 +++++----- .../persentase_kelahiran_kematian/create.ts | 26 +- .../find-many.ts | 59 +- .../findUnique.ts | 4 + .../persentase_kelahiran_kematian/index.ts | 12 +- .../kelahiran/create.ts | 34 + .../kelahiran/del.ts | 36 ++ .../kelahiran/findMany.ts | 54 ++ .../kelahiran/findUnique.ts | 46 ++ .../kelahiran/index.ts | 39 ++ .../kelahiran/updt.ts | 34 + .../kematian/create.ts | 36 ++ .../kematian/del.ts | 36 ++ .../kematian/findMany.ts | 54 ++ .../kematian/findUnique.ts | 46 ++ .../kematian/index.ts | 41 ++ .../kematian/updt.ts | 36 ++ .../persentase_kelahiran_kematian/updt.ts | 14 +- .../api/[[...slugs]]/_lib/kesehatan/index.ts | 6 +- .../main-page/landing-page/ModuleView.tsx | 16 +- .../main-page/landing-page/ProfileView.tsx | 6 +- .../main-page/landing-page/SosmedView.tsx | 10 +- 34 files changed, 2285 insertions(+), 445 deletions(-) delete mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/[id]/page.tsx delete mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/create/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/[id]/edit/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/[id]/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/create/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/edit/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/create/page.tsx create mode 100644 src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/page.tsx create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/create.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/del.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/findMany.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/updt.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/create.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/del.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/findMany.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/updt.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 674c980a..7d2f89e2 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -911,15 +911,42 @@ model PendaftaranJadwalKegiatan { // ========================================= PERSENTASE KELAHIRAN & KEMATIAN ========================================= // model DataKematian_Kelahiran { - id String @id @default(cuid()) - tahun String - kematianKasar String - kematianBayi String - kelahiranKasar String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + kematian Kematian @relation(fields: [kematianId], references: [id]) + kematianId String + kelahiran Kelahiran @relation(fields: [kelahiranId], references: [id]) + kelahiranId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +model Kelahiran { + id String @id @default(cuid()) + nama String + tanggal DateTime + jenisKelamin String + alamat String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + DataKematian_Kelahiran DataKematian_Kelahiran[] +} + +model Kematian { + id String @id @default(cuid()) + nama String + tanggal DateTime + jenisKelamin String + alamat String + penyebab String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + DataKematian_Kelahiran DataKematian_Kelahiran[] } // ========================================= GRAFIK KEPUASAN ========================================= // 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 cf0febd9..4da79df8 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 @@ -1,10 +1,13 @@ +/* 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"; -const templatePersentase = z.object({ +//persentase kelahiran kematian + +const templatePersentaseKelahiran = z.object({ tahun: z.string().min(4, "Tahun harus diisi"), kematianKasar: z.string().min(1, "Kematian kasar harus diisi"), kelahiranKasar: z.string().min(1, "Kelahiran kasar harus diisi"), @@ -13,18 +16,14 @@ const templatePersentase = z.object({ type Persentase = Prisma.DataKematian_KelahiranGetPayload<{ select: { - tahun: true; - kematianKasar: true; - kelahiranKasar: true; - kematianBayi: true; + kematianId: true; + kelahiranId: true; }; }>; const defaultForm: Persentase = { - tahun: "", - kematianKasar: "", - kelahiranKasar: "", - kematianBayi: "", + kematianId: "", + kelahiranId: "", }; const persentasekelahiran = proxy({ @@ -32,7 +31,9 @@ const persentasekelahiran = proxy({ form: defaultForm, loading: false, async create() { - const cek = templatePersentase.safeParse(persentasekelahiran.create.form); + const cek = templatePersentaseKelahiran.safeParse( + persentasekelahiran.create.form + ); if (!cek.success) { const err = `[${cek.error.issues .map((v) => `${v.path.join(".")}`) @@ -47,7 +48,7 @@ const persentasekelahiran = proxy({ ].post(persentasekelahiran.create.form); if (res.status === 200) { - const id = res.data?.data?.id; + const id = res.data?.data; if (id) { toast.success("Success create"); persentasekelahiran.create.form = { ...defaultForm }; @@ -69,21 +70,51 @@ const persentasekelahiran = proxy({ findMany: { data: null as | Prisma.DataKematian_KelahiranGetPayload<{ - omit: { isActive: true }; + include: { + kematian: true; + kelahiran: true; + }; }>[] | null, - async load() { - const res = await ApiFetch.api.kesehatan.persentasekelahiran[ - "find-many" - ].get(); - if (res.status === 200) { - persentasekelahiran.findMany.data = res.data?.data ?? []; + page: 1, + totalPages: 1, + loading: false, + search: "", + load: async (page = 1, limit = 10, search = "") => { + persentasekelahiran.findMany.loading = true; // ✅ Akses langsung via nama path + persentasekelahiran.findMany.page = page; + persentasekelahiran.findMany.search = search; + + try { + const query: any = { page, limit }; + if (search) query.search = search; + + const res = await ApiFetch.api.kesehatan.persentasekelahiran[ + "find-many" + ].get({ query }); + + if (res.status === 200 && res.data?.success) { + persentasekelahiran.findMany.data = res.data.data ?? []; + persentasekelahiran.findMany.totalPages = res.data.totalPages ?? 1; + } else { + persentasekelahiran.findMany.data = []; + persentasekelahiran.findMany.totalPages = 1; + } + } catch (err) { + console.error("Gagal fetch berita paginated:", err); + persentasekelahiran.findMany.data = []; + persentasekelahiran.findMany.totalPages = 1; + } finally { + persentasekelahiran.findMany.loading = false; } }, }, findUnique: { data: null as Prisma.DataKematian_KelahiranGetPayload<{ - omit: { isActive: true }; + include: { + kematian: true; + kelahiran: true; + }; }> | null, async load(id: string) { try { @@ -114,13 +145,11 @@ const persentasekelahiran = proxy({ } const formData = { - tahun: this.form.tahun, - kematianKasar: this.form.kematianKasar, - kelahiranKasar: this.form.kelahiranKasar, - kematianBayi: this.form.kematianBayi, + kematianId: this.form.kematianId, + kelahiranId: this.form.kelahiranId, }; - const cek = templatePersentase.safeParse(formData); + const cek = templatePersentaseKelahiran.safeParse(formData); if (!cek.success) { const err = `[${cek.error.issues .map((v) => `${v.path.join(".")}`) @@ -197,4 +226,521 @@ const persentasekelahiran = proxy({ }, }); -export default persentasekelahiran; +// data kelahiran + +const templateKelahiran = z.object({ + nama: z.string().min(1, "Nama harus diisi"), + tanggal: z.string().min(4, "Tahun harus diisi"), + jenisKelamin: z.string().min(1, "Jenis kelamin harus diisi"), + alamat: z.string().min(1, "Alamat harus diisi"), +}); + +const defaultKelahiran = { + nama: "", + tanggal: "", + jenisKelamin: "", + alamat: "", +}; + +const kelahiran = proxy({ + create: { + form: { ...defaultKelahiran }, // ✅ ini kunci fix-nya + loading: false, + async create() { + const cek = templateKelahiran.safeParse(kelahiran.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + kelahiran.create.loading = true; + const res = await ApiFetch.api.kesehatan.kelahiran["create"].post( + kelahiran.create.form + ); + if (res.status === 200) { + kelahiran.findMany.load(); + return toast.success("Kelahiran berhasil disimpan!"); + } + + return toast.error("Gagal menyimpan kelahiran"); + } catch (error) { + console.log((error as Error).message); + } finally { + kelahiran.create.loading = false; + } + }, + resetForm() { + kelahiran.create.form = { ...defaultKelahiran }; + }, + }, + findMany: { + data: null as + | Prisma.KelahiranGetPayload<{ + omit: { + isActive: true; + }; + }>[] + | null, + page: 1, + totalPages: 1, + loading: false, + search: "", + load: async (page = 1, limit = 10, search = "") => { + kelahiran.findMany.loading = true; // ✅ Akses langsung via nama path + kelahiran.findMany.page = page; + kelahiran.findMany.search = search; + + try { + const query: any = { page, limit }; + if (search) query.search = search; + + const res = await ApiFetch.api.kesehatan.kelahiran["findMany"].get({ + query, + }); + + if (res.status === 200 && res.data?.success) { + kelahiran.findMany.data = res.data.data ?? []; + kelahiran.findMany.totalPages = res.data.totalPages ?? 1; + } else { + kelahiran.findMany.data = []; + kelahiran.findMany.totalPages = 1; + } + } catch (err) { + console.error("Gagal fetch kelahiran paginated:", err); + kelahiran.findMany.data = []; + kelahiran.findMany.totalPages = 1; + } finally { + kelahiran.findMany.loading = false; + } + }, + }, + findUnique: { + data: null as Prisma.KelahiranGetPayload<{ + omit: { + isActive: true; + }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/kesehatan/kelahiran/${id}`); + if (res.ok) { + const data = await res.json(); + kelahiran.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch kelahiran:", res.statusText); + kelahiran.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching kelahiran:", error); + kelahiran.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + kelahiran.delete.loading = true; + + const response = await fetch(`/api/kesehatan/kelahiran/del/${id}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Kelahiran berhasil dihapus"); + await kelahiran.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus kelahiran"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus kelahiran"); + } finally { + kelahiran.delete.loading = false; + } + }, + }, + edit: { + id: "", + form: { ...defaultKelahiran }, + loading: false, + + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch(`/api/kesehatan/kelahiran/${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 = { + nama: data.nama, + tanggal: data.tanggal, + jenisKelamin: data.jenisKelamin, + alamat: data.alamat, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error loading data kelahiran:", error); + toast.error( + error instanceof Error ? error.message : "Gagal memuat data" + ); + return null; + } + }, + + async update() { + const cek = templateKelahiran.safeParse(kelahiran.edit.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + toast.error(err); + return false; + } + + try { + kelahiran.edit.loading = true; + + const response = await fetch(`/api/kesehatan/kelahiran/${this.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + nama: this.form.nama, + tanggal: this.form.tanggal, + jenisKelamin: this.form.jenisKelamin, + alamat: this.form.alamat, + }), + }); + + 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("Berhasil update data kelahiran"); + await kelahiran.findMany.load(); // refresh list + return true; + } else { + throw new Error(result.message || "Gagal update data kelahiran"); + } + } catch (error) { + console.error("Error updating data kelahiran:", error); + toast.error( + error instanceof Error + ? error.message + : "Terjadi kesalahan saat update data kelahiran" + ); + return false; + } finally { + kelahiran.edit.loading = false; + } + }, + + reset() { + kelahiran.edit.id = ""; + kelahiran.edit.form = { ...defaultKelahiran }; + }, + }, +}); + + +// data kematian + +const templateKematian = z.object({ + nama: z.string().min(1, "Nama harus diisi"), + tanggal: z.string().min(4, "Tahun harus diisi"), + jenisKelamin: z.string().min(1, "Jenis kelamin harus diisi"), + alamat: z.string().min(1, "Alamat harus diisi"), + penyebab: z.string().min(1, "Penyebab harus diisi"), +}); + +const defaultKematian = { + nama: "", + tanggal: "", + jenisKelamin: "", + alamat: "", + penyebab: "", +}; + +const kematian = proxy({ + create: { + form: { ...defaultKematian }, // ✅ ini kunci fix-nya + loading: false, + async create() { + const cek = templateKematian.safeParse(kematian.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + kematian.create.loading = true; + const res = await ApiFetch.api.kesehatan.kematian["create"].post( + kematian.create.form + ); + if (res.status === 200) { + kematian.findMany.load(); + return toast.success("Kematian berhasil disimpan!"); + } + + return toast.error("Gagal menyimpan kematian"); + } catch (error) { + console.log((error as Error).message); + } finally { + kematian.create.loading = false; + } + }, + resetForm() { + kematian.create.form = { ...defaultKematian }; + }, + }, + findMany: { + data: null as + | Prisma.KematianGetPayload<{ + omit: { + isActive: true; + }; + }>[] + | null, + page: 1, + totalPages: 1, + loading: false, + search: "", + load: async (page = 1, limit = 10, search = "") => { + kematian.findMany.loading = true; // ✅ Akses langsung via nama path + kematian.findMany.page = page; + kematian.findMany.search = search; + + try { + const query: any = { page, limit }; + if (search) query.search = search; + + const res = await ApiFetch.api.kesehatan.kematian["findMany"].get({ + query, + }); + + if (res.status === 200 && res.data?.success) { + kematian.findMany.data = res.data.data ?? []; + kematian.findMany.totalPages = res.data.totalPages ?? 1; + } else { + kematian.findMany.data = []; + kematian.findMany.totalPages = 1; + } + } catch (err) { + console.error("Gagal fetch kematian paginated:", err); + kematian.findMany.data = []; + kematian.findMany.totalPages = 1; + } finally { + kematian.findMany.loading = false; + } + }, + }, + findUnique: { + data: null as Prisma.KematianGetPayload<{ + omit: { + isActive: true; + }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/kesehatan/kematian/${id}`); + if (res.ok) { + const data = await res.json(); + kematian.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch kematian:", res.statusText); + kematian.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching kematian:", error); + kematian.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + kematian.delete.loading = true; + + const response = await fetch(`/api/kesehatan/kematian/del/${id}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Kematian berhasil dihapus"); + await kematian.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus kematian"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus kematian"); + } finally { + kematian.delete.loading = false; + } + }, + }, + edit: { + id: "", + form: { ...defaultKematian }, + loading: false, + + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch(`/api/kesehatan/kematian/${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 = { + nama: data.nama, + tanggal: data.tanggal, + jenisKelamin: data.jenisKelamin, + alamat: data.alamat, + penyebab: data.penyebab, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error loading data kematian:", error); + toast.error( + error instanceof Error ? error.message : "Gagal memuat data" + ); + return null; + } + }, + + async update() { + const cek = templateKematian.safeParse(kematian.edit.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + toast.error(err); + return false; + } + + try { + kematian.edit.loading = true; + + const response = await fetch(`/api/kesehatan/kematian/${this.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + nama: this.form.nama, + tanggal: this.form.tanggal, + jenisKelamin: this.form.jenisKelamin, + alamat: this.form.alamat, + penyebab: this.form.penyebab, + }), + }); + + 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("Berhasil update data kematian"); + await kematian.findMany.load(); // refresh list + return true; + } else { + throw new Error(result.message || "Gagal update data kematian"); + } + } catch (error) { + console.error("Error updating data kematian:", error); + toast.error( + error instanceof Error + ? error.message + : "Terjadi kesalahan saat update data kematian" + ); + return false; + } finally { + kematian.edit.loading = false; + } + }, + + reset() { + kematian.edit.id = ""; + kematian.edit.form = { ...defaultKematian }; + }, + }, +}); + +const persentaseKelahiranKematian = proxy({ + persentasekelahiran, + kelahiran, + kematian +}); + +export default persentaseKelahiranKematian; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/[id]/page.tsx deleted file mode 100644 index 5b441229..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/[id]/page.tsx +++ /dev/null @@ -1,113 +0,0 @@ -/* 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 { id: string } - const statePresentase = useProxy(persentasekelahiran) - - const id = params.id - - // Load data saat komponen mount -// Di file page.tsx, ubah useEffect-nya menjadi: -useEffect(() => { - if (!id) return; - statePresentase.update.id = 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.id = 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 deleted file mode 100644 index 2df71d8b..00000000 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/create/page.tsx +++ /dev/null @@ -1,101 +0,0 @@ -/* 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/kelahiran/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/[id]/edit/page.tsx new file mode 100644 index 00000000..b23233e5 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/[id]/edit/page.tsx @@ -0,0 +1,107 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import persentaseKelahiranKematian from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +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'; + +function EditKelahiran() { + const editState = useProxy(persentaseKelahiranKematian.kelahiran) + const router = useRouter(); + const params = useParams(); + const [formData, setFormData] = useState({ + nama: editState.edit.form.nama || '', + tanggal: editState.edit.form.tanggal || '', + jenisKelamin: editState.edit.form.jenisKelamin || '', + alamat: editState.edit.form.alamat || '', + }); + + useEffect(() => { + const loadKelahiran = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await editState.edit.load(id); // akses langsung, bukan dari proxy + if (data) { + setFormData({ + nama: data.nama || '', + tanggal: data.tanggal || '', + jenisKelamin: data.jenisKelamin || '', + alamat: data.alamat || '', + }); + } + } catch (error) { + console.error("Error loading data kelahiran:", error); + toast.error("Gagal memuat data data kelahiran"); + } + }; + + loadKelahiran(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + editState.edit.form = { + ...editState.edit.form, + nama: formData.nama, + tanggal: formData.tanggal, + jenisKelamin: formData.jenisKelamin, + alamat: formData.alamat, + }; + await editState.edit.update(); + toast.success('data kelahiran berhasil diperbarui!'); + router.push('/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran'); + } catch (error) { + console.error('Error updating data kelahiran:', error); + toast.error('Terjadi kesalahan saat memperbarui data kelahiran'); + } + }; + + return ( + + + + + + + Edit data kelahiran + setFormData({ ...formData, nama: e.target.value })} + label={Nama} + placeholder="masukkan nama" + /> + setFormData({ ...formData, tanggal: e.target.value })} + label={Tanggal} + placeholder="masukkan tanggal" + /> + setFormData({ ...formData, jenisKelamin: e.target.value })} + label={Jenis Kelamin} + placeholder="masukkan jenis kelamin" + /> + setFormData({ ...formData, alamat: e.target.value })} + label={Alamat} + placeholder="masukkan alamat" + /> + + + + + ); +} + +export default EditKelahiran; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/[id]/page.tsx new file mode 100644 index 00000000..90ae22a2 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/[id]/page.tsx @@ -0,0 +1,121 @@ +'use client' +import { useProxy } from 'valtio/utils'; + +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 { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus'; +import persentaseKelahiranKematian from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; + + +function DetailKelahiran() { + const state = useProxy(persentaseKelahiranKematian.kelahiran) + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const params = useParams() + const router = useRouter() + + useShallowEffect(() => { + state.findUnique.load(params?.id as string) + }, []) + + + const handleHapus = () => { + if (selectedId) { + state.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran") + } + } + + if (!state.findUnique.data) { + return ( + + + + ) + } + + return ( + + + + + + + Detail Data Kelahiran + {state.findUnique.data ? ( + + + + Nama + {state.findUnique.data?.nama} + + + Tanggal + + {new Date(state.findUnique.data?.tanggal).toLocaleDateString('id-ID', { + day: '2-digit', + month: 'long', + year: 'numeric' + })} + + + + Jenis Kelamin + {state.findUnique.data?.jenisKelamin} + + + Alamat + {state.findUnique.data?.alamat} + + + + + + + + ) : null} + + + + {/* Modal Konfirmasi Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text='Apakah anda yakin ingin menghapus data ini?' + /> + + ); +} + +export default DetailKelahiran; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/create/page.tsx new file mode 100644 index 00000000..ffc936f8 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/create/page.tsx @@ -0,0 +1,83 @@ +'use client' +import persentaseKelahiranKematian from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; + + + +function CreateKelahiran() { + const createState = useProxy(persentaseKelahiranKematian.kelahiran) + const router = useRouter(); + + const resetForm = () => { + createState.create.form = { + nama: "", + tanggal: "", + jenisKelamin: "", + alamat: "", + }; + }; + + const handleSubmit = async () => { + await createState.create.create(); + resetForm(); + router.push("/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran") + }; + + return ( + + + + + + + + Create Kelahiran + Nama} + placeholder='Masukkan nama' + value={createState.create.form.nama} + onChange={(val) => { + createState.create.form.nama = val.target.value; + }} + /> + Tanggal} + placeholder='Masukkan tanggal' + value={createState.create.form.tanggal} + onChange={(val) => { + createState.create.form.tanggal = val.target.value; + }} + /> + Jenis Kelamin} + placeholder='Masukkan jenis kelamin' + value={createState.create.form.jenisKelamin} + onChange={(val) => { + createState.create.form.jenisKelamin = val.target.value; + }} + /> + Alamat} + placeholder='Masukkan alamat' + value={createState.create.form.alamat} + onChange={(val) => { + createState.create.form.alamat = val.target.value; + }} + /> + + + + + + + ); +} + +export default CreateKelahiran; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/page.tsx new file mode 100644 index 00000000..1b64d1f7 --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran/page.tsx @@ -0,0 +1,118 @@ +'use client' +import HeaderSearch from '@/app/admin/(dashboard)/_com/header'; +import JudulList from '@/app/admin/(dashboard)/_com/judulList'; +import persentasekelahiran from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; +import { Box, Button, Center, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack, IconEdit, IconSearch } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; + + +function Kelahiran() { + const router = useRouter(); + const [search, setSearch] = useState(""); + return ( + + + + + } + value={search} + onChange={(e) => setSearch(e.currentTarget.value)} + /> + + + ); +} +function ListKelahiran({ search }: { search: string }) { + const statePersentase = useProxy(persentasekelahiran.kelahiran); + const router = useRouter(); + + + const { + data, + page, + totalPages, + loading, + load + } = statePersentase.findMany; + + useShallowEffect(() => { + load(page, 10, search) + }, [search]) + + const filteredData = data || [] + + if (loading || !data) { + return ( + + + + ) + } + + return ( + + + {/* Form Input */} + + + + + + Nama + Tanggal + Jenis Kelamin + Alamat + Detail + + + + {filteredData.map((item) => ( + + {item.nama} + + {new Date(item.tanggal).toLocaleDateString('id-ID', { + day: '2-digit', + month: 'long', + year: 'numeric' + })} + + {item.jenisKelamin} + {item.alamat} + + + + + ))} + +
+
+
+
+ load(newPage)} // ini penting! + total={totalPages} + mt="md" + mb="md" + /> +
+
+ ); +} + +export default Kelahiran; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/edit/page.tsx new file mode 100644 index 00000000..eab57efe --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/edit/page.tsx @@ -0,0 +1,121 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import persentaseKelahiranKematian from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +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'; + +function EditKematian() { + const editState = useProxy(persentaseKelahiranKematian.kematian) + const router = useRouter(); + const params = useParams(); + const [formData, setFormData] = useState({ + nama: editState.edit.form.nama || '', + tanggal: editState.edit.form.tanggal || '', + jenisKelamin: editState.edit.form.jenisKelamin || '', + alamat: editState.edit.form.alamat || '', + penyebab: editState.edit.form.penyebab || '', + }); + + useEffect(() => { + const loadKelahiran = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await editState.edit.load(id); // akses langsung, bukan dari proxy + if (data) { + setFormData({ + nama: data.nama || '', + tanggal: data.tanggal || '', + jenisKelamin: data.jenisKelamin || '', + alamat: data.alamat || '', + penyebab: data.penyebab || '', + }); + } + } catch (error) { + console.error("Error loading data kelahiran:", error); + toast.error("Gagal memuat data data kelahiran"); + } + }; + + loadKelahiran(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + editState.edit.form = { + ...editState.edit.form, + nama: formData.nama, + tanggal: formData.tanggal, + jenisKelamin: formData.jenisKelamin, + alamat: formData.alamat, + penyebab: formData.penyebab, + }; + await editState.edit.update(); + toast.success('data kelahiran berhasil diperbarui!'); + router.push('/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran'); + } catch (error) { + console.error('Error updating data kelahiran:', error); + toast.error('Terjadi kesalahan saat memperbarui data kelahiran'); + } + }; + + return ( + + + + + + + Edit data kelahiran + setFormData({ ...formData, nama: e.target.value })} + label={Nama} + placeholder="masukkan nama" + /> + setFormData({ ...formData, tanggal: e.target.value })} + label={Tanggal} + placeholder="masukkan tanggal" + /> + setFormData({ ...formData, jenisKelamin: e.target.value })} + label={Jenis Kelamin} + placeholder="masukkan jenis kelamin" + /> + setFormData({ ...formData, alamat: e.target.value })} + label={Alamat} + placeholder="masukkan alamat" + /> + + Penyebab + { + setFormData((prev) => ({ ...prev, penyebab: htmlContent })); + editState.edit.form.penyebab = htmlContent; + }} + /> + + + + + + ); +} + +export default EditKematian; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/page.tsx new file mode 100644 index 00000000..b967f25a --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/[id]/page.tsx @@ -0,0 +1,126 @@ +'use client' +import { useProxy } from 'valtio/utils'; + +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 { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus'; +import persentaseKelahiranKematian from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; + + +function DetailKematian() { + const state = useProxy(persentaseKelahiranKematian.kematian) + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + const params = useParams() + const router = useRouter() + + useShallowEffect(() => { + state.findUnique.load(params?.id as string) + }, []) + + const handleHapus = () => { + if (selectedId) { + state.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + router.push("/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran") + } + } + + if (!state.findUnique.data) { + return ( + + + + ) + } + + return ( + + + + + + + Detail Data Kematian + {state.findUnique.data ? ( + + + + Nama + {state.findUnique.data?.nama} + + + Tanggal + + {state.findUnique.data?.tanggal instanceof Date + ? state.findUnique.data.tanggal.toLocaleDateString('id-ID', { + day: '2-digit', + month: 'long', + year: 'numeric' + }) + : state.findUnique.data?.tanggal} + + + + Jenis Kelamin + {state.findUnique.data?.jenisKelamin} + + + Alamat + {state.findUnique.data?.alamat} + + + Penyebab + + + + + + + + + ) : null} + + + + {/* Modal Konfirmasi Hapus */} + setModalHapus(false)} + onConfirm={handleHapus} + text='Apakah anda yakin ingin menghapus data ini?' + /> + + ); +} + +export default DetailKematian; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/create/page.tsx new file mode 100644 index 00000000..310a7a6b --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/create/page.tsx @@ -0,0 +1,94 @@ +'use client' +import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor'; +import persentaseKelahiranKematian from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; + + + +function CreateKematian() { + const createState = useProxy(persentaseKelahiranKematian.kematian) + const router = useRouter(); + + const resetForm = () => { + createState.create.form = { + nama: "", + tanggal: "", + jenisKelamin: "", + alamat: "", + penyebab: "", + }; + }; + + const handleSubmit = async () => { + await createState.create.create(); + resetForm(); + router.push("/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian") + }; + + return ( + + + + + + + + Create Kematian + Nama} + placeholder='Masukkan nama' + value={createState.create.form.nama} + onChange={(val) => { + createState.create.form.nama = val.target.value; + }} + /> + Tanggal} + placeholder='Masukkan tanggal' + value={createState.create.form.tanggal} + onChange={(val) => { + createState.create.form.tanggal = val.target.value; + }} + /> + Jenis Kelamin} + placeholder='Masukkan jenis kelamin' + value={createState.create.form.jenisKelamin} + onChange={(val) => { + createState.create.form.jenisKelamin = val.target.value; + }} + /> + Alamat} + placeholder='Masukkan alamat' + value={createState.create.form.alamat} + onChange={(val) => { + createState.create.form.alamat = val.target.value; + }} + /> + + Penyebab + { + createState.create.form.penyebab = htmlContent; + }} + /> + + + + + + + + ); +} + +export default CreateKematian; diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/page.tsx new file mode 100644 index 00000000..c7d4df3e --- /dev/null +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/page.tsx @@ -0,0 +1,118 @@ +'use client' +import HeaderSearch from '@/app/admin/(dashboard)/_com/header'; +import JudulList from '@/app/admin/(dashboard)/_com/judulList'; +import persentasekelahiran from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran'; +import colors from '@/con/colors'; +import { Box, Button, Center, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack, IconEdit, IconSearch } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; + + +function Kematian() { + const [search, setSearch] = useState(""); + const router = useRouter(); + return ( + + + + + } + value={search} + onChange={(e) => setSearch(e.currentTarget.value)} + /> + + + ); +} +function ListKematian({ search }: { search: string }) { + const statePersentase = useProxy(persentasekelahiran.kematian); + const router = useRouter(); + + + const { + data, + page, + totalPages, + loading, + load + } = statePersentase.findMany; + + useShallowEffect(() => { + load(page, 10, search) + }, [search]) + + const filteredData = data || [] + + if (loading || !data) { + return ( + + + + ) + } + + return ( + + + {/* Form Input */} + + + + + + Nama + Tanggal + Jenis Kelamin + Alamat + Detail + + + + {filteredData.map((item) => ( + + {item.nama} + + {new Date(item.tanggal).toLocaleDateString('id-ID', { + day: '2-digit', + month: 'long', + year: 'numeric' + })} + + {item.jenisKelamin} + {item.alamat} + + + + + ))} + +
+
+
+
+ load(newPage)} // ini penting! + total={totalPages} + mt="md" + mb="md" + /> +
+
+ ); +} + +export default Kematian; 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 index d2beb0d9..a5a07128 100644 --- 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 @@ -1,183 +1,229 @@ +/* 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, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core'; +import { ActionIcon, Box, Button, Center, Flex, Paper, Skeleton, Stack, Table, Text, Title } from '@mantine/core'; import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; -import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react'; +import { IconBabyCarriage, IconGrave2 } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; -import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts'; +import { Bar, BarChart, Legend, Tooltip, TooltipProps, XAxis, YAxis } from 'recharts'; import { useProxy } from 'valtio/utils'; -import JudulListTab from '../../../_com/judulListTab'; -import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; -import HeaderSearch from '../../../_com/header'; + +type TooltipPayload = { + name: string; + value: number; + payload: any; + color: string; + dataKey: string; +}; + +type CustomTooltipProps = TooltipProps & { + active?: boolean; + payload?: TooltipPayload[]; + label?: string; +}; function PersentaseDataKelahiranKematian() { - const [search, setSearch] = useState(""); return ( - - } - value={search} - onChange={(e) => setSearch(e.currentTarget.value)} - /> - - + + + ); } -function ListPersentaseDataKelahiranKematian({ search }: { search: string }) { - type PDKMGrafik = { - id: 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) +function GrafikPersentaseKelahiranKematian() { const router = useRouter(); + type DataTahunan = { + tahun: string; + totalKelahiran: number; + totalKematian: number; + data: Array<{ + id: string; + bulan: string; + kelahiran: number; + kematian: number; + }>; + }; - const handleDelete = () => { - if (selectedId) { - statePersentase.delete.byId(selectedId) - setModalHapus(false) - setSelectedId(null) + // Count occurrences per year + const countByYear = (data: any[], dateField: string) => { + const counts: Record = {}; + data?.forEach(item => { + const year = new Date(item[dateField]).getFullYear().toString(); + counts[year] = (counts[year] || 0) + 1; + }); + return counts; + }; - statePersentase.findMany.load() + const statePersentase = useProxy(persentasekelahiran); + const [chartData, setChartData] = useState([]); + const isTablet = useMediaQuery('(max-width: 1024px)'); + const isMobile = useMediaQuery('(max-width: 768px)'); + const [selectedYear, setSelectedYear] = useState(null); + + // Format number to Indonesian locale + const formatNumber = (num: number) => { + return new Intl.NumberFormat('id-ID').format(num); + }; + + // Format tooltip + const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => { + if (active && payload && payload.length) { + return ( + + Tahun {label} + Kelahiran: {formatNumber(payload[0].value)} + Kematian: {formatNumber(payload[1].value)} + + ); } - } + return null; + }; useShallowEffect(() => { - setMounted(true) - statePersentase.findMany.load() - }, []) + statePersentase.kelahiran.findMany.load(1, 1000); // Load all kelahiran data + statePersentase.kematian.findMany.load(1, 1000); // Load all kematian data + }, []); useEffect(() => { - setMounted(true); - if (statePersentase.findMany.data) { - setChartData(statePersentase.findMany.data.map((item) => ({ - id: item.id, - tahun: item.tahun, - kematianKasar: Number(item.kematianKasar), - kematianBayi: Number(item.kematianBayi), - kelahiranKasar: Number(item.kelahiranKasar), - }))); + if (statePersentase.kelahiran.findMany.data && statePersentase.kematian.findMany.data) { + // Count kelahiran and kematian by year + const kelahiranByYear = countByYear(statePersentase.kelahiran.findMany.data, 'tanggal'); + const kematianByYear = countByYear(statePersentase.kematian.findMany.data, 'tanggal'); + + // Get all unique years + const allYears = new Set([ + ...Object.keys(kelahiranByYear), + ...Object.keys(kematianByYear) + ]); + + // Create data structure for the chart + const dataByYear = Array.from(allYears).reduce>((acc, year) => { + acc[year] = { + tahun: year, + totalKelahiran: kelahiranByYear[year] || 0, + totalKematian: kematianByYear[year] || 0, + data: [] + }; + return acc; + }, {}); + + const sortedData = Object.values(dataByYear).sort((a, b) => + parseInt(a.tahun) - parseInt(b.tahun) + ); + + setChartData(sortedData); + setSelectedYear(sortedData[0]?.tahun || ''); } - }, [statePersentase.findMany.data]); + }, [ + statePersentase.kelahiran.findMany.data, + statePersentase.kematian.findMany.data, + ]); - const filteredData = (statePersentase.findMany.data || []).filter(item => { - const keyword = search.toLowerCase(); - return ( - item.tahun.toLowerCase().includes(keyword) || - item.kematianKasar.toString().toLowerCase().includes(keyword) || - item.kematianBayi.toString().toLowerCase().includes(keyword) || - item.kelahiranKasar.toString().toLowerCase().includes(keyword) - ); - }); - - if (!statePersentase.findMany.data) { + if (!statePersentase.kelahiran.findMany.data || !statePersentase.kematian.findMany.data) { return ( - ) + ); } + const selectedYearData = chartData.find(d => d.tahun === selectedYear); + return ( - + - {/* Form Input */} - - } - /> - - - - Tahun - Kematian Kasar - Kematian Bayi - kelahiran Kasar - Edit - Delete - - - - {filteredData.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 && ( - - - - - - - - - - )} - - - )} + Statistik Kelahiran & Kematian + + + + router.push('/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran')}> + + + + + router.push('/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian')} > + + + + +
- {/* Modal Konfirmasi Hapus */} - setModalHapus(false)} - onConfirm={handleDelete} - text='Apakah anda yakin ingin menghapus persentase data kelahiran & kematian ini?' - /> -
+ {chartData.length === 0 ? ( + + Belum ada data yang tersedia untuk ditampilkan + + ) : ( + <> + {/* Year Selector */} + + Pilih Tahun: +
+ {chartData.map(({ tahun }) => ( + + ))} +
+
+ + {/* Main Chart */} +
+ + + + + } /> + + + + + +
+ + {/* Yearly Breakdown */} + {selectedYearData && ( + + Rincian Tahun {selectedYear} + + + + Bulan + Kelahiran + Kematian + + + + {selectedYearData.data.map((item) => ( + + {item.bulan} + {formatNumber(item.kelahiran)} + {formatNumber(item.kematian)} + + ))} + + Total + {formatNumber(selectedYearData.totalKelahiran)} + {formatNumber(selectedYearData.totalKematian)} + + +
+
+ )} + + )} + ); } 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 f78a22f3..899415e2 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 @@ -1,32 +1,22 @@ import prisma from "@/lib/prisma"; -import { Prisma } from "@prisma/client"; import { Context } from "elysia"; -type FormCreate = Prisma.DataKematian_KelahiranGetPayload<{ - select: { - tahun: true; - kematianKasar: true; - kematianBayi: true; - kelahiranKasar: true; - }; -}>; +type FormCreate = { + kematianId: string; + kelahiranId: string; +}; export default async function persentaseKelahiranKematianCreate(context: Context) { const body = context.body as FormCreate const created = await prisma.dataKematian_Kelahiran.create({ data: { - tahun: body.tahun, - kematianKasar: body.kematianKasar, - kematianBayi: body.kematianBayi, - kelahiranKasar: body.kelahiranKasar, + kematianId: body.kematianId, + kelahiranId: body.kelahiranId, }, select: { - id: true, - tahun: true, - kematianKasar: true, - kematianBayi: true, - kelahiranKasar: true, + kematianId: true, + kelahiranId: true, } }) return{ diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/find-many.ts index c3ed94ee..efce1035 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/find-many.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/find-many.ts @@ -1,9 +1,58 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// /api/berita/findManyPaginated.ts import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +async function persentaseKelahiranKematianFindMany(context: Context) { + // Ambil parameter dari query + const page = Number(context.query.page) || 1; + const limit = Number(context.query.limit) || 10; + const search = (context.query.search as string) || ''; + const skip = (page - 1) * limit; + + // Buat where clause + const where: any = { isActive: true }; + + // Tambahkan pencarian (jika ada) + if (search) { + where.OR = [ + { kematian: { nama: { contains: search, mode: 'insensitive' } } }, + { kelahiran: { nama: { contains: search, mode: 'insensitive' } } }, + ]; + } + + try { + // Ambil data dan total count secara paralel + const [data, total] = await Promise.all([ + prisma.dataKematian_Kelahiran.findMany({ + where, + include: { + kematian: true, + kelahiran: true, + }, + skip, + take: limit, + orderBy: { createdAt: 'desc' }, + }), + prisma.dataKematian_Kelahiran.count({ where }), + ]); -export default async function persentaseKelahiranKematianFindMany() { - const res = await prisma.dataKematian_Kelahiran.findMany(); return { - data: res - } + success: true, + message: "Berhasil ambil data persentase kelahiran kematian dengan pagination", + data, + page, + limit, + total, + totalPages: Math.ceil(total / limit), + }; + } catch (e) { + console.error("Error di findMany paginated:", e); + return { + success: false, + message: "Gagal mengambil data persentase kelahiran kematian", + }; + } } - \ No newline at end of file + +export default persentaseKelahiranKematianFindMany; \ 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 index cdc1a08b..81838db9 100644 --- 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 @@ -22,6 +22,10 @@ export default async function persentaseKelahiranKematianFindUnique(request: Req const data = await prisma.dataKematian_Kelahiran.findUnique({ where: { id }, + include: { + kematian: true, + kelahiran: true, + }, }); if (!data) { 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 62419584..f52be0f8 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 @@ -16,10 +16,8 @@ const PersentaseKelahiranKematian = new Elysia({ .get("/find-many", persentaseKelahiranKematianFindMany) .post("/create", persentaseKelahiranKematianCreate, { body: t.Object({ - tahun: t.String(), - kematianKasar: t.String(), - kematianBayi: t.String(), - kelahiranKasar: t.String(), + kematianId: t.String(), + kelahiranId: t.String(), }), }) .put("/:id", persentaseKelahiranKematianUpdate, { @@ -27,10 +25,8 @@ const PersentaseKelahiranKematian = new Elysia({ id: t.String(), }), body: t.Object({ - tahun: t.String(), - kematianKasar: t.String(), - kematianBayi: t.String(), - kelahiranKasar: t.String(), + kematianId: t.String(), + kelahiranId: t.String(), }), }) .delete("/del/:id", persentaseKelahiranKematianDelete, { diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/create.ts new file mode 100644 index 00000000..93ad49b1 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/create.ts @@ -0,0 +1,34 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormCreate = { + nama: string; + tanggal: string; + jenisKelamin: string; + alamat: string; +} + +export default async function kelahiranCreate(context: Context) { + const body = context.body as FormCreate; + + const created = await prisma.kelahiran.create({ + data: { + nama: body.nama, + tanggal: new Date(body.tanggal), + jenisKelamin: body.jenisKelamin, + alamat: body.alamat, + }, + select: { + nama: true, + tanggal: true, + jenisKelamin: true, + alamat: true, + }, + }); + return { + success: true, + message: "Success create kelahiran", + data: created, + }; +} + \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/del.ts new file mode 100644 index 00000000..324ad18c --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/del.ts @@ -0,0 +1,36 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function kelahiranDelete(context: Context) { + const id = context.params?.id; + + if (!id) { + return { + success: false, + message: "ID tidak ditemukan", + } + } + + const existing = await prisma.kelahiran.findUnique({ + where: { + id: id, + }, + }) + + if (!existing) { + return { + success: false, + message: "Data tidak ditemukan", + } + } + + const deleted = await prisma.kelahiran.delete({ + where: { id }, + }) + + 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/kelahiran/findMany.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/findMany.ts new file mode 100644 index 00000000..f0738b20 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/findMany.ts @@ -0,0 +1,54 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// /api/berita/findManyPaginated.ts +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +async function kelahiranFindMany(context: Context) { + // Ambil parameter dari query + const page = Number(context.query.page) || 1; + const limit = Number(context.query.limit) || 10; + const search = (context.query.search as string) || ''; + const skip = (page - 1) * limit; + + // Buat where clause + const where: any = { isActive: true }; + + // Tambahkan pencarian (jika ada) + if (search) { + where.OR = [ + { nama: { contains: search, mode: 'insensitive' } }, + { alamat: { contains: search, mode: 'insensitive' } }, + ]; + } + + try { + // Ambil data dan total count secara paralel + const [data, total] = await Promise.all([ + prisma.kelahiran.findMany({ + where, + skip, + take: limit, + orderBy: { createdAt: 'desc' }, + }), + prisma.kelahiran.count({ where }), + ]); + + return { + success: true, + message: "Berhasil ambil data kelahiran dengan pagination", + data, + page, + limit, + total, + totalPages: Math.ceil(total / limit), + }; + } catch (e) { + console.error("Error di findMany paginated:", e); + return { + success: false, + message: "Gagal mengambil data kelahiran", + }; + } +} + +export default kelahiranFindMany; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/findUnique.ts new file mode 100644 index 00000000..88a1d5a7 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/findUnique.ts @@ -0,0 +1,46 @@ +import prisma from "@/lib/prisma"; + +export default async function kelahiranFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return { + success: false, + message: "ID is required", + } + } + + try { + if (typeof id !== 'string') { + return { + success: false, + message: "ID is required", + } + } + + const data = await prisma.kelahiran.findUnique({ + where: { id }, + }); + + if (!data) { + return { + success: false, + message: "Data not found", + } + } + + return { + success: true, + message: "Success get data kelahiran", + data, + } + } catch (error) { + console.error("Find by ID error:", error); + return { + success: false, + message: "Gagal mengambil data: " + (error instanceof Error ? error.message : 'Unknown error'), + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/index.ts new file mode 100644 index 00000000..991fa2c9 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/index.ts @@ -0,0 +1,39 @@ +import Elysia, { t } from "elysia"; +import kelahiranCreate from "./create"; +import kelahiranDelete from "./del"; +import kelahiranFindMany from "./findMany"; +import kelahiranFindUnique from "./findUnique"; +import kelahiranUpdate from "./updt"; + +const Kelahiran = new Elysia({ + prefix: "/kelahiran", + tags: ["Kesehatan / Data Kesehatan Warga / Persentase Kelahiran Kematian / Kelahiran"], +}) + + .post("/create", kelahiranCreate, { + body: t.Object({ + nama: t.String(), + tanggal: t.String(), + jenisKelamin: t.String(), + alamat: t.String(), + }), + }) + + .get("/findMany", kelahiranFindMany) + .get("/:id", async (context) => { + const response = await kelahiranFindUnique( + new Request(context.request) + ); + return response; + }) + .put("/:id", kelahiranUpdate, { + body: t.Object({ + nama: t.String(), + tanggal: t.String(), + jenisKelamin: t.String(), + alamat: t.String(), + }), + }) + .delete("/del/:id", kelahiranDelete); + +export default Kelahiran; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/updt.ts new file mode 100644 index 00000000..b1f7d6ed --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran/updt.ts @@ -0,0 +1,34 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormUpdate = { + nama: string; + tanggal: string; + jenisKelamin: string; + alamat: string; +} + +export default async function kelahiranUpdate(context: Context) { + const body = (await context.body) as FormUpdate; + const id = context.params.id as string; + + try { + const result = await prisma.kelahiran.update({ + where: { id }, + data: { + nama: body.nama, + tanggal: new Date(body.tanggal), + jenisKelamin: body.jenisKelamin, + alamat: body.alamat, + }, + }); + return { + success: true, + message: "Berhasil mengupdate data kelahiran", + data: result, + }; + } catch (error) { + console.error("Error updating data kelahiran:", error); + throw new Error("Gagal mengupdate data kelahiran: " + (error as Error).message); + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/create.ts new file mode 100644 index 00000000..4faeb5b9 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/create.ts @@ -0,0 +1,36 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormCreate = { + nama: string; + tanggal: string; + jenisKelamin: string; + alamat: string; + penyebab: string; +}; + +export default async function kematianCreate(context: Context) { + const body = context.body as FormCreate; + + const created = await prisma.kematian.create({ + data: { + nama: body.nama, + tanggal: new Date(body.tanggal), + jenisKelamin: body.jenisKelamin, + alamat: body.alamat, + penyebab: body.penyebab, + }, + select: { + nama: true, + tanggal: true, + jenisKelamin: true, + alamat: true, + penyebab: true, + }, + }); + return { + success: true, + message: "Success create kematian", + data: created, + }; +} diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/del.ts new file mode 100644 index 00000000..e4bf8c16 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/del.ts @@ -0,0 +1,36 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function kematianDelete(context: Context) { + const id = context.params?.id; + + if (!id) { + return { + success: false, + message: "ID tidak ditemukan", + } + } + + const existing = await prisma.kematian.findUnique({ + where: { + id: id, + }, + }) + + if (!existing) { + return { + success: false, + message: "Data tidak ditemukan", + } + } + + const deleted = await prisma.kematian.delete({ + where: { id }, + }) + + 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/kematian/findMany.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/findMany.ts new file mode 100644 index 00000000..bfc50c4d --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/findMany.ts @@ -0,0 +1,54 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// /api/berita/findManyPaginated.ts +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +async function kematianFindMany(context: Context) { + // Ambil parameter dari query + const page = Number(context.query.page) || 1; + const limit = Number(context.query.limit) || 10; + const search = (context.query.search as string) || ''; + const skip = (page - 1) * limit; + + // Buat where clause + const where: any = { isActive: true }; + + // Tambahkan pencarian (jika ada) + if (search) { + where.OR = [ + { nama: { contains: search, mode: 'insensitive' } }, + { alamat: { contains: search, mode: 'insensitive' } }, + ]; + } + + try { + // Ambil data dan total count secara paralel + const [data, total] = await Promise.all([ + prisma.kematian.findMany({ + where, + skip, + take: limit, + orderBy: { createdAt: 'desc' }, + }), + prisma.kematian.count({ where }), + ]); + + return { + success: true, + message: "Berhasil ambil data kematian dengan pagination", + data, + page, + limit, + total, + totalPages: Math.ceil(total / limit), + }; + } catch (e) { + console.error("Error di findMany paginated:", e); + return { + success: false, + message: "Gagal mengambil data kematian", + }; + } +} + +export default kematianFindMany; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/findUnique.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/findUnique.ts new file mode 100644 index 00000000..eeca3e0b --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/findUnique.ts @@ -0,0 +1,46 @@ +import prisma from "@/lib/prisma"; + +export default async function kematianFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return { + success: false, + message: "ID is required", + } + } + + try { + if (typeof id !== 'string') { + return { + success: false, + message: "ID is required", + } + } + + const data = await prisma.kematian.findUnique({ + where: { id }, + }); + + if (!data) { + return { + success: false, + message: "Data not found", + } + } + + return { + success: true, + message: "Success get data kematian", + data, + } + } catch (error) { + console.error("Find by ID error:", error); + return { + success: false, + message: "Gagal mengambil data: " + (error instanceof Error ? error.message : 'Unknown error'), + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/index.ts new file mode 100644 index 00000000..53eacda4 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/index.ts @@ -0,0 +1,41 @@ +import Elysia, { t } from "elysia"; +import kematianCreate from "./create"; +import kematianDelete from "./del"; +import kematianFindMany from "./findMany"; +import kematianFindUnique from "./findUnique"; +import kematianUpdate from "./updt"; + +const Kematian = new Elysia({ + prefix: "/kematian", + tags: ["Kesehatan / Data Kesehatan Warga / Persentase Kelahiran Kematian / Kematian"], +}) + + .post("/create", kematianCreate, { + body: t.Object({ + nama: t.String(), + tanggal: t.String(), + jenisKelamin: t.String(), + alamat: t.String(), + penyebab: t.String(), + }), + }) + + .get("/findMany", kematianFindMany) + .get("/:id", async (context) => { + const response = await kematianFindUnique( + new Request(context.request) + ); + return response; + }) + .put("/:id", kematianUpdate, { + body: t.Object({ + nama: t.String(), + tanggal: t.String(), + jenisKelamin: t.String(), + alamat: t.String(), + penyebab: t.String(), + }), + }) + .delete("/del/:id", kematianDelete); + +export default Kematian; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/updt.ts new file mode 100644 index 00000000..47217244 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/data_kesehatan_warga/persentase_kelahiran_kematian/kematian/updt.ts @@ -0,0 +1,36 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormUpdate = { + nama: string; + tanggal: string; + jenisKelamin: string; + alamat: string; + penyebab: string; +} + +export default async function kematianUpdate(context: Context) { + const body = (await context.body) as FormUpdate; + const id = context.params.id as string; + + try { + const result = await prisma.kematian.update({ + where: { id }, + data: { + nama: body.nama, + tanggal: new Date(body.tanggal), + jenisKelamin: body.jenisKelamin, + alamat: body.alamat, + penyebab: body.penyebab, + }, + }); + return { + success: true, + message: "Berhasil mengupdate data kematian", + data: result, + }; + } catch (error) { + console.error("Error updating data kematian:", error); + throw new Error("Gagal mengupdate data kematian: " + (error as Error).message); + } +} \ 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 index 2e2ea281..96a5936f 100644 --- 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 @@ -11,11 +11,9 @@ export default async function persentaseKelahiranKematianUpdate(context: Context } } - const {tahun, kematianKasar, kematianBayi, kelahiranKasar} = context.body as { - tahun: string; - kematianKasar: string; - kematianBayi: string; - kelahiranKasar: string; + const {kematianId, kelahiranId} = context.body as { + kematianId: string; + kelahiranId: string; } const existing = await prisma.dataKematian_Kelahiran.findUnique({ @@ -34,10 +32,8 @@ export default async function persentaseKelahiranKematianUpdate(context: Context const updated = await prisma.dataKematian_Kelahiran.update({ where: { id }, data: { - tahun, - kematianKasar, - kematianBayi, - kelahiranKasar, + kematianId, + kelahiranId, }, }) diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts index b9c0cbbc..83eb1f3b 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts @@ -16,6 +16,8 @@ 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"; +import Kelahiran from "./data_kesehatan_warga/persentase_kelahiran_kematian/kelahiran"; +import Kematian from "./data_kesehatan_warga/persentase_kelahiran_kematian/kematian"; const Kesehatan = new Elysia({ @@ -38,5 +40,7 @@ const Kesehatan = new Elysia({ .use(InfoWabahPenyakit) .use(FasilitasKesehatan) .use(JadwalKegiatan) -.use(ArtikelKesehatan); +.use(ArtikelKesehatan) +.use(Kelahiran) +.use(Kematian) export default Kesehatan; diff --git a/src/app/darmasaba/_com/main-page/landing-page/ModuleView.tsx b/src/app/darmasaba/_com/main-page/landing-page/ModuleView.tsx index e0c7ab8a..267d2aee 100644 --- a/src/app/darmasaba/_com/main-page/landing-page/ModuleView.tsx +++ b/src/app/darmasaba/_com/main-page/landing-page/ModuleView.tsx @@ -1,5 +1,5 @@ import profileLandingPageState from "@/app/admin/(dashboard)/_state/landing-page/profile"; -import { Center, Image, Paper, SimpleGrid } from "@mantine/core"; +import { Center, Image, Paper, SimpleGrid, Text } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import { motion } from 'framer-motion'; import { useTransitionRouter } from 'next-view-transitions'; @@ -25,15 +25,21 @@ function ModuleItem({ data }: { data: ProgramInovasiItem }) { - icon + ) : ( + + - + + )} diff --git a/src/app/darmasaba/_com/main-page/landing-page/ProfileView.tsx b/src/app/darmasaba/_com/main-page/landing-page/ProfileView.tsx index 1c3d6254..9a723e08 100644 --- a/src/app/darmasaba/_com/main-page/landing-page/ProfileView.tsx +++ b/src/app/darmasaba/_com/main-page/landing-page/ProfileView.tsx @@ -23,13 +23,17 @@ function ProfileView({ data }: ProfileViewProps) { }} px="xl" > - {data.image?.link && ( + {data.image?.link ? ( {data.name + ): ( + + - + )} - icon + {item.image?.link ? ( + icon + ) : ( + + none + + )} ); })}