Compare commits
2 Commits
nico/28-ap
...
nico/push-
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f3ee2f831 | |||
| ea7de13d28 |
@@ -62,7 +62,7 @@
|
||||
"react-simple-toasts": "^6.1.0",
|
||||
"react-toastify": "^11.0.5",
|
||||
"readdirp": "^4.1.1",
|
||||
"recharts": "2",
|
||||
"recharts": "^2.15.3",
|
||||
"swr": "^2.3.2",
|
||||
"valtio": "^2.1.3",
|
||||
"zod": "^3.24.3"
|
||||
|
||||
@@ -46,6 +46,7 @@ model AppMenuChild {
|
||||
AppMenu AppMenu? @relation(fields: [appMenuId], references: [id])
|
||||
appMenuId String?
|
||||
}
|
||||
|
||||
// ========================================= MENU DESA ========================================= //
|
||||
// ========================================= BERITA ========================================= //
|
||||
model Berita {
|
||||
@@ -106,6 +107,7 @@ model Images {
|
||||
updatedAt DateTime @updatedAt
|
||||
GalleryFoto GalleryFoto[]
|
||||
}
|
||||
|
||||
// ========================================= VIDEOS ========================================= //
|
||||
model Videos {
|
||||
id String @id @default(cuid())
|
||||
@@ -117,7 +119,6 @@ model Videos {
|
||||
GalleryVideo GalleryVideo[]
|
||||
}
|
||||
|
||||
|
||||
// ========================================= GALLERY ========================================= //
|
||||
model GalleryFoto {
|
||||
id String @id @default(cuid())
|
||||
@@ -132,14 +133,14 @@ model GalleryFoto {
|
||||
}
|
||||
|
||||
model GalleryVideo {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
video String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
videosId String? @unique
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
video String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
videosId String? @unique
|
||||
videosGalleryVideo Videos? @relation(fields: [videosId], references: [id])
|
||||
}
|
||||
|
||||
@@ -147,6 +148,159 @@ model GalleryVideo {
|
||||
// ========================================= DATA KESEHATAN WARGA ========================================= //
|
||||
|
||||
// ========================================= 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[]
|
||||
LayananUnggulan LayananUnggulan[]
|
||||
DokterdanTenagaMedis DokterdanTenagaMedis[]
|
||||
FasilitasPendukung FasilitasPendukung[]
|
||||
ProsedurPendaftaran ProsedurPendaftaran[]
|
||||
TarifDanLayanan TarifDanLayanan[]
|
||||
}
|
||||
|
||||
model InformasiUmum {
|
||||
id String @id @default(cuid())
|
||||
fasilitas String
|
||||
alamat String
|
||||
jamOperasional String
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model LayananUnggulan {
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model DokterdanTenagaMedis {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
specialist String
|
||||
jadwal String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model FasilitasPendukung {
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model ProsedurPendaftaran {
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model TarifDanLayanan {
|
||||
id String @id @default(cuid())
|
||||
layanan String
|
||||
tarif String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
// ========================================= JADWAL KEGIATAN ========================================= //
|
||||
model JadwalKegiatan {
|
||||
id String @id @default(cuid())
|
||||
content 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)
|
||||
}
|
||||
|
||||
model DeskripsiJadwalKegiatan {
|
||||
id String @id @default(cuid())
|
||||
deskripsi String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model LayananJadwalKegiatan {
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model SyaratKetentuanJadwalKegiatan {
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model DokumenJadwalKegiatan {
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// ========================================= PERSENTASE KELAHIRAN & KEMATIAN ========================================= //
|
||||
model DataKematian_Kelahiran {
|
||||
id Int @id @default(autoincrement())
|
||||
tahun String
|
||||
@@ -155,156 +309,17 @@ model DataKematian_Kelahiran {
|
||||
kelahiranKasar String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model FasilitasKesehatan {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
// ========================================= GRAFIK KEPUASAN ========================================= //
|
||||
model GrafikKepuasan {
|
||||
id Int @id @default(autoincrement())
|
||||
label String
|
||||
jumlah String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
InformasiUmum InformasiUmum[]
|
||||
LayananUnggulan LayananUnggulan[]
|
||||
DokterdanTenagaMedis DokterdanTenagaMedis[]
|
||||
FasilitasPendukung FasilitasPendukung[]
|
||||
ProsedurPendaftaran ProsedurPendaftaran[]
|
||||
TarifDanLayanan TarifDanLayanan[]
|
||||
}
|
||||
|
||||
model InformasiUmum{
|
||||
id String @id @default(cuid())
|
||||
fasilitas String
|
||||
alamat String
|
||||
jamOperasional String
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model LayananUnggulan{
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model DokterdanTenagaMedis{
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
specialist String
|
||||
jadwal String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model FasilitasPendukung{
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model ProsedurPendaftaran{
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
model TarifDanLayanan{
|
||||
id String @id @default(cuid())
|
||||
layanan String
|
||||
tarif String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
FasilitasKesehatan FasilitasKesehatan[]
|
||||
}
|
||||
|
||||
// ========================================= JADWAL KEGIATAN ========================================= //
|
||||
model JadwalKegiatan{
|
||||
id String @id @default(cuid())
|
||||
content 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)
|
||||
}
|
||||
|
||||
model DeskripsiJadwalKegiatan{
|
||||
id String @id @default(cuid())
|
||||
deskripsi String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model LayananJadwalKegiatan{
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model SyaratKetentuanJadwalKegiatan{
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model DokumenJadwalKegiatan{
|
||||
id String @id @default(cuid())
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model PendaftaranJadwalKegiatan{
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
tanggal DateTime
|
||||
namaOrangtua String
|
||||
nomor String
|
||||
alamat String
|
||||
catatan String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
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 templateGrafikKepuasan = z.object({
|
||||
label: z.string().min(2, "Label harus diisi"),
|
||||
jumlah: z.string().min(2, "Jumlah harus diisi"),
|
||||
});
|
||||
|
||||
type GrafikKepuasan = Prisma.GrafikKepuasanGetPayload<{
|
||||
select: {
|
||||
label: true;
|
||||
jumlah: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultForm: GrafikKepuasan = {
|
||||
label: "",
|
||||
jumlah: ""
|
||||
};
|
||||
|
||||
const grafikkepuasan = proxy({
|
||||
create: {
|
||||
form: defaultForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateGrafikKepuasan.safeParse(grafikkepuasan.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
grafikkepuasan.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.grafikkepuasan["create"].post(
|
||||
grafikkepuasan.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
grafikkepuasan.create.form = {
|
||||
label: "",
|
||||
jumlah: ""
|
||||
};
|
||||
grafikkepuasan.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
grafikkepuasan.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.GrafikKepuasanGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.grafikkepuasan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
grafikkepuasan.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const stategrafikKepuasan = proxy({
|
||||
grafikkepuasan,
|
||||
});
|
||||
|
||||
export default stategrafikKepuasan;
|
||||
@@ -0,0 +1,84 @@
|
||||
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({
|
||||
tahun: z.string().min(4, "Tahun harus diisi"),
|
||||
kematianKasar: z.string().min(2, "Kematian kasar harus diisi"),
|
||||
kelahiranKasar: z.string().min(2, "Kelahiran kasar harus diisi"),
|
||||
kematianBayi: z.string().min(2, "Kematian bayi harus diisi"),
|
||||
});
|
||||
|
||||
type Persentase = Prisma.DataKematian_KelahiranGetPayload<{
|
||||
select: {
|
||||
tahun: true;
|
||||
kematianKasar: true;
|
||||
kelahiranKasar: true;
|
||||
kematianBayi: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultForm: Persentase = {
|
||||
tahun: "",
|
||||
kematianKasar: "",
|
||||
kelahiranKasar: "",
|
||||
kematianBayi: "",
|
||||
};
|
||||
|
||||
const persentasekelahiran = proxy({
|
||||
create: {
|
||||
form: defaultForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templatePersentase.safeParse(persentasekelahiran.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
persentasekelahiran.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.persentasekelahiran[
|
||||
"create"
|
||||
].post(persentasekelahiran.create.form);
|
||||
if (res.status === 200) {
|
||||
persentasekelahiran.create.form = {
|
||||
tahun: "",
|
||||
kematianKasar: "",
|
||||
kelahiranKasar: "",
|
||||
kematianBayi: "",
|
||||
};
|
||||
persentasekelahiran.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
persentasekelahiran.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DataKematian_KelahiranGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.persentasekelahiran[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
persentasekelahiran.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const statePersentase = proxy({
|
||||
persentasekelahiran,
|
||||
});
|
||||
|
||||
export default statePersentase;
|
||||
@@ -1,10 +1,72 @@
|
||||
import { Stack, Title } from '@mantine/core';
|
||||
import React from 'react';
|
||||
'use client'
|
||||
import stategrafikKepuasan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Stack, TextInput, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useState } from 'react';
|
||||
import { Bar, Legend, RadialBarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
function GrafikHasilKepuasan() {
|
||||
const grafikkepuasan = useProxy(stategrafikKepuasan.grafikkepuasan)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [chartData, setChartData] = useState<any[]>([])
|
||||
useShallowEffect(() => {
|
||||
const fetchData = async () => {
|
||||
await grafikkepuasan.findMany.load();
|
||||
if (grafikkepuasan.findMany.data && grafikkepuasan.findMany.data.length > 0) {
|
||||
setChartData(grafikkepuasan.findMany.data);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
return (
|
||||
<Stack py={10}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Grafik Hasil Kepuasan</Title>
|
||||
<Box>
|
||||
<TextInput
|
||||
label="Label"
|
||||
placeholder='Masukkan label yang diinginkan'
|
||||
value={grafikkepuasan.create.form.label}
|
||||
onChange={(val) => {
|
||||
grafikkepuasan.create.form.label = val.currentTarget.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Jumlah Penderita Farangitis Akut"
|
||||
type='number'
|
||||
placeholder='Masukkan jumlah penderita farangitis akut'
|
||||
value={grafikkepuasan.create.form.jumlah}
|
||||
onChange={(val) => {
|
||||
grafikkepuasan.create.form.jumlah = val.currentTarget.value
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Group>
|
||||
<Button mt={10}
|
||||
onClick={async () => {
|
||||
await grafikkepuasan.create.create();
|
||||
await grafikkepuasan.findMany.load();
|
||||
if (grafikkepuasan.findMany.data) {
|
||||
setChartData(grafikkepuasan.findMany.data);
|
||||
}
|
||||
}}
|
||||
>Submit</Button>
|
||||
</Group>
|
||||
<Box h={400} w={{ base: "100%", md: "80%" }}>
|
||||
<Title order={3}>Data Kelahiran & Kematian</Title>
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<RadialBarChart
|
||||
data={chartData}
|
||||
>
|
||||
<XAxis dataKey="label" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Bar dataKey="jumlah" fill={colors['blue-button']} name="Jumlah" />
|
||||
</RadialBarChart>
|
||||
</ResponsiveContainer>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ function JadwalKegiatan() {
|
||||
<SyaratDanKetentuan />
|
||||
<DokumenYangDiperlukan />
|
||||
<Pendaftaran />
|
||||
<Button onClick={submitAllForms}>
|
||||
<Button mt={10} onClick={submitAllForms}>
|
||||
Submit
|
||||
</Button>
|
||||
</Box>
|
||||
@@ -84,13 +84,15 @@ function AllList() {
|
||||
allList.layanantersedia.findMany.load()
|
||||
allList.syaratketentuan.findMany.load()
|
||||
allList.dokumenjadwalkegiatan.findMany.load()
|
||||
})
|
||||
allList.pendaftaranjadwal.findMany.load()
|
||||
}, [])
|
||||
|
||||
const isLoading = !allList.informasiKegiatan.findMany.data ||
|
||||
!allList.deskripsiKegiatan.findMany.data ||
|
||||
!allList.layanantersedia.findMany.data ||
|
||||
!allList.syaratketentuan.findMany.data ||
|
||||
!allList.dokumenjadwalkegiatan.findMany.data
|
||||
!allList.dokumenjadwalkegiatan.findMany.data ||
|
||||
!allList.pendaftaranjadwal.findMany.data
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
'use client'
|
||||
import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
||||
import { ActionIcon, Box, Text, Textarea, TextInput } from '@mantine/core';
|
||||
import { DateInput } from '@mantine/dates';
|
||||
import { IconCalendar } from '@tabler/icons-react';
|
||||
import { useState } from 'react';
|
||||
import { Box, Text, Textarea, TextInput } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
function Pendaftaran() {
|
||||
const pendaftaran = useProxy(stateJadwalKegiatan.pendaftaranjadwal)
|
||||
const [dateInputOpened, setDateInputOpened] = useState(false);
|
||||
const pickerControl = (
|
||||
<ActionIcon onClick={() => setDateInputOpened(true)} variant="subtle" color="gray">
|
||||
<IconCalendar size={18} />
|
||||
</ActionIcon>
|
||||
);
|
||||
|
||||
const formatDate = (date: Date | null): string => { if (!date) return ""; return date.toISOString().split('T')[0]; }
|
||||
|
||||
return (
|
||||
<Box>
|
||||
@@ -27,16 +16,11 @@ function Pendaftaran() {
|
||||
pendaftaran.create.form.name = val.target.value
|
||||
}}
|
||||
/>
|
||||
<DateInput
|
||||
clearable defaultValue={new Date()}
|
||||
styles={{label: {fontSize: '14px'}}}
|
||||
label='Tanggal Lahir'
|
||||
placeholder='dd/mm/yyyy'
|
||||
value={pendaftaran.create.form.tanggal ? new Date(pendaftaran.create.form.tanggal) : null}
|
||||
popoverProps={{opened: dateInputOpened, onChange: setDateInputOpened}}
|
||||
rightSection={pickerControl}
|
||||
<TextInput
|
||||
label='Tanggal'
|
||||
placeholder='Masukkan tanggal'
|
||||
onChange={(val) => {
|
||||
pendaftaran.create.form.tanggal = formatDate(val);
|
||||
pendaftaran.create.form.tanggal = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
|
||||
@@ -1,10 +1,107 @@
|
||||
import { Stack, Title } from '@mantine/core';
|
||||
import React from 'react';
|
||||
'use client'
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import statePersentase from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran';
|
||||
import { Box, Button, Stack, TextInput, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Bar, BarChart, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
function PersentaseDataKelahiranKematian() {
|
||||
const persentase = useProxy(statePersentase.persentasekelahiran);
|
||||
const [chartData, setChartData] = useState<any[]>([]);
|
||||
const [mounted, setMounted] = useState(false); // untuk memastikan DOM sudah ready
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
useShallowEffect(() => {
|
||||
const fetchData = async () => {
|
||||
await persentase.findMany.load();
|
||||
if (persentase.findMany.data && persentase.findMany.data.length > 0) {
|
||||
setChartData(persentase.findMany.data);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Stack py={10}>
|
||||
<Title order={3}>Persentase Data Kelahiran & Kematian</Title>
|
||||
{/* Form Input */}
|
||||
<Box>
|
||||
<Title order={3}>Persentase Data Kelahiran & Kematian</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Tahun"
|
||||
type="number"
|
||||
value={persentase.create.form.tahun}
|
||||
placeholder="Masukkan tahun"
|
||||
onChange={(val) => {
|
||||
persentase.create.form.tahun = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Kematian Kasar"
|
||||
type="number"
|
||||
value={persentase.create.form.kematianKasar}
|
||||
placeholder="Masukkan kematian kasar"
|
||||
onChange={(val) => {
|
||||
persentase.create.form.kematianKasar = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Kematian Bayi"
|
||||
type="number"
|
||||
value={persentase.create.form.kematianBayi}
|
||||
placeholder="Masukkan kematian bayi"
|
||||
onChange={(val) => {
|
||||
persentase.create.form.kematianBayi = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Kelahiran Kasar"
|
||||
type="number"
|
||||
value={persentase.create.form.kelahiranKasar}
|
||||
placeholder="Masukkan kelahiran kasar"
|
||||
onChange={(val) => {
|
||||
persentase.create.form.kelahiranKasar = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
mt={10}
|
||||
onClick={async () => {
|
||||
await persentase.create.create();
|
||||
await persentase.findMany.load();
|
||||
if (persentase.findMany.data) {
|
||||
setChartData(persentase.findMany.data);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
{/* Chart */}
|
||||
<Box style={{ width: '100%', minWidth: 300, height: 400, minHeight: 300 }}>
|
||||
<Title order={3}>Data Kelahiran & Kematian</Title>
|
||||
{mounted && chartData.length > 0 && (
|
||||
<ResponsiveContainer width="100%" aspect={2}>
|
||||
<BarChart width={300} data={chartData}>
|
||||
<XAxis dataKey="tahun" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Bar dataKey="kematianKasar" fill="#f03e3e" name="Kematian Kasar" />
|
||||
<Bar dataKey="kematianBayi" fill="#ff922b" name="Kematian Bayi" />
|
||||
<Bar dataKey="kelahiranKasar" fill="#4dabf7" name="Kelahiran Kasar" />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Tabs, TabsList, TabsPanel, TabsTab } from '@mantine/core';
|
||||
import ArtikelKesehatan from './_ui/artikel_kesehatan/page';
|
||||
import FasilitasKesehatan from './_ui/fasilitas_kesehatan/page';
|
||||
import GrafikHasilKepuasan from './_ui/grafik_hasil_kepuasan/page';
|
||||
import JadwalKegiatan from './_ui/jadwal_kegiatan/page';
|
||||
import PersentaseDataKelahiranKematian from './_ui/persentase_data_kelahiran_kematian/page';
|
||||
import GrafikHasilKepuasan from './_ui/grafik_hasil_kepuasan/page';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
|
||||
function Page() {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.GrafikKepuasanGetPayload<{
|
||||
select: {
|
||||
label: true;
|
||||
jumlah: true
|
||||
};
|
||||
}>;
|
||||
export default async function grafikKepuasanCreate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.grafikKepuasan.create({
|
||||
data: {
|
||||
label: body.label,
|
||||
jumlah: body.jumlah,
|
||||
},
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
message: "Success create grafik kepuasan",
|
||||
data: {
|
||||
...body,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import prisma from "@/lib/prisma"
|
||||
|
||||
export default async function grafikKepuasanFindMany() {
|
||||
const res = await prisma.grafikKepuasan.findMany()
|
||||
return {
|
||||
data: res
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import grafikKepuasanCreate from "./create";
|
||||
import grafikKepuasanFindMany from "./find-many";
|
||||
|
||||
const GrafikKepuasan = new Elysia({
|
||||
prefix: "/grafikkepuasan",
|
||||
tags: ["Data Kesehatan/Grafik Kepuasan"]
|
||||
})
|
||||
.get("/find-many", grafikKepuasanFindMany)
|
||||
.post("/create", grafikKepuasanCreate, {
|
||||
body: t.Object({
|
||||
label: t.String(),
|
||||
jumlah: t.String(),
|
||||
}),
|
||||
})
|
||||
export default GrafikKepuasan
|
||||
@@ -0,0 +1,32 @@
|
||||
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;
|
||||
};
|
||||
}>;
|
||||
|
||||
export default async function persentaseKelahiranKematianCreate(context: Context) {
|
||||
const body = context.body as FormCreate
|
||||
|
||||
await prisma.dataKematian_Kelahiran.create({
|
||||
data: {
|
||||
tahun: body.tahun,
|
||||
kematianKasar: body.kematianKasar,
|
||||
kematianBayi: body.kematianBayi,
|
||||
kelahiranKasar: body.kelahiranKasar,
|
||||
}
|
||||
})
|
||||
return{
|
||||
success: true,
|
||||
message: "Success create persentase kelahiran kematian",
|
||||
data: {
|
||||
...body
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function persentaseKelahiranKematianFindMany() {
|
||||
const res = await prisma.dataKematian_Kelahiran.findMany();
|
||||
return {
|
||||
data: res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import persentaseKelahiranKematianCreate from "./create";
|
||||
import persentaseKelahiranKematianFindMany from "./find-many";
|
||||
|
||||
const PersentaseKelahiranKematian = new Elysia({
|
||||
prefix: "/persentasekelahiran",
|
||||
tags: ["Data Kesehatan/Persentase Kelahiran Kematian"],
|
||||
})
|
||||
.get("/find-many", persentaseKelahiranKematianFindMany)
|
||||
.post("/create", persentaseKelahiranKematianCreate, {
|
||||
body: t.Object({
|
||||
tahun: t.String(),
|
||||
kematianKasar: t.String(),
|
||||
kematianBayi: t.String(),
|
||||
kelahiranKasar: t.String(),
|
||||
}),
|
||||
})
|
||||
|
||||
export default PersentaseKelahiranKematian;
|
||||
@@ -11,6 +11,9 @@ import LayananTersedia from "./data_kesehatan_warga/jadwal_kegiatan/layanan_yang
|
||||
import SyaratKetentuan from "./data_kesehatan_warga/jadwal_kegiatan/syarat_dan_ketentuan";
|
||||
import DokumenDiperlukan from "./data_kesehatan_warga/jadwal_kegiatan/dokumen_yang_diperlukan";
|
||||
import PendaftaranJadwal from "./data_kesehatan_warga/jadwal_kegiatan/pendaftaran";
|
||||
import PersentaseKelahiranKematian from "./data_kesehatan_warga/persentase_kelahiran_kematian";
|
||||
import GrafikKepuasan from "./data_kesehatan_warga/grafik_kepuasan";
|
||||
|
||||
|
||||
const Kesehatan = new Elysia({
|
||||
prefix: "/api/kesehatan",
|
||||
@@ -28,4 +31,6 @@ const Kesehatan = new Elysia({
|
||||
.use(SyaratKetentuan)
|
||||
.use(DokumenDiperlukan)
|
||||
.use(PendaftaranJadwal)
|
||||
.use(PersentaseKelahiranKematian)
|
||||
.use(GrafikKepuasan)
|
||||
export default Kesehatan;
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
'use client'
|
||||
import { Box, Container, Flex, Grid, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import React from 'react';
|
||||
|
||||
const tx = `
|
||||
Untuk menambahkan fitur berbagi nomor WhatsApp di kode yang Anda miliki, saya akan menjelaskan beberapa pendekatan yang bisa digunakan. Biasanya ini dilakukan dengan membuat link yang ketika diklik akan membuka aplikasi WhatsApp dengan nomor tujuan yang sudah diatur.
|
||||
Berikut adalah cara mengimplementasikannya pada kode React Anda:
|
||||
`
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<Stack>
|
||||
<Grid>
|
||||
<Grid.Col span={{
|
||||
base: 12,
|
||||
sm: 6,
|
||||
md: 4,
|
||||
xl: 10
|
||||
}}>
|
||||
<Box h={"200"} bg={"blue"}>1</Box>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{
|
||||
base: 12,
|
||||
sm: 6,
|
||||
md: 8,
|
||||
xl: 2
|
||||
}}>
|
||||
<Box h={"200"} bg={"red"}>1</Box>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<SimpleGrid cols={{
|
||||
base: 1,
|
||||
sm: 2,
|
||||
md: 4,
|
||||
xl: 20
|
||||
}}>
|
||||
{Array.from({ length: 10 }).map((_, i) => (
|
||||
<Box key={i} h={"60"} bg={"blue"}>1</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
<Flex >
|
||||
<Box w={400} h={"200"} bg={"blue"}>1</Box>
|
||||
<Box w={400} bg={"red"}>
|
||||
<Text fz={"42"} lineClamp={1} >{tx}</Text>
|
||||
<Text bg={"blue"} style={{
|
||||
fontSize: "2rem"
|
||||
}} lineClamp={1} >{tx}</Text>
|
||||
<Title order={1}>apa kabar</Title>
|
||||
</Box>
|
||||
|
||||
</Flex>
|
||||
|
||||
<Page2/>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
const Halaman = [Halaman1, Halaman2, Halaman3]
|
||||
|
||||
function Page2() {
|
||||
const page = useSearchParams().get("p");
|
||||
if (!page) return <Container >
|
||||
<Stack>
|
||||
<Text>halo 1</Text>
|
||||
{Array.from({ length: 4 }).map((v, k) => <Skeleton h={100} key={k} />)}
|
||||
</Stack>
|
||||
</Container>
|
||||
|
||||
|
||||
return (
|
||||
<Container w={"100%"}>
|
||||
<Stack>
|
||||
<Text>halo 2</Text>
|
||||
{Halaman[Number(page)-1]()}
|
||||
</Stack>
|
||||
</Container>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Halaman1() {
|
||||
return <Stack bg={"blue"}>
|
||||
ini halaman 1
|
||||
</Stack>
|
||||
}
|
||||
|
||||
|
||||
function Halaman2() {
|
||||
return <Stack bg={"red"}>
|
||||
ini halaman 2
|
||||
</Stack>
|
||||
}
|
||||
|
||||
|
||||
function Halaman3() {
|
||||
return <Stack bg={"grape"}>
|
||||
ini halaman 3
|
||||
</Stack>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user