Tampilan UI Admin PPID IKM & API
This commit is contained in:
@@ -196,7 +196,7 @@ model FormulirPermohonanKeberatan {
|
|||||||
|
|
||||||
// ========================================= IKM ========================================= //
|
// ========================================= IKM ========================================= //
|
||||||
model IndeksKepuasanMasyarakat {
|
model IndeksKepuasanMasyarakat {
|
||||||
id Int @id @default(autoincrement())
|
id String @id @default(cuid())
|
||||||
label String
|
label String
|
||||||
kepuasan String
|
kepuasan String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function ModalKonfirmasiHapus({
|
|||||||
<Modal
|
<Modal
|
||||||
opened={opened}
|
opened={opened}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
title="Konfirmasi Hapus"
|
title={<Text fw={"bold"} fz={"xl"}>Konfirmasi Hapus</Text>}
|
||||||
centered
|
centered
|
||||||
>
|
>
|
||||||
<Text mb="md">{text}</Text>
|
<Text mb="md">{text}</Text>
|
||||||
|
|||||||
@@ -11,12 +11,13 @@ const templateGrafikJenisKelamin = z.object({
|
|||||||
|
|
||||||
type GrafikJenisKelamin = Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
|
type GrafikJenisKelamin = Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
|
||||||
select: {
|
select: {
|
||||||
|
id: true;
|
||||||
laki: true;
|
laki: true;
|
||||||
perempuan: true;
|
perempuan: true;
|
||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const defaultForm: GrafikJenisKelamin = {
|
const defaultForm: Omit<GrafikJenisKelamin, 'id'> & { id?: string } = {
|
||||||
laki: "",
|
laki: "",
|
||||||
perempuan: "",
|
perempuan: "",
|
||||||
};
|
};
|
||||||
@@ -41,9 +42,16 @@ const grafikBerdasarkanJenisKelamin = proxy({
|
|||||||
"create"
|
"create"
|
||||||
].post(grafikBerdasarkanJenisKelamin.create.form);
|
].post(grafikBerdasarkanJenisKelamin.create.form);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
grafikBerdasarkanJenisKelamin.create.form = defaultForm;
|
const id = res.data?.data?.id;
|
||||||
grafikBerdasarkanJenisKelamin.findMany.load();
|
if (id) {
|
||||||
return toast.success("success create");
|
toast.success("Success create");
|
||||||
|
grafikBerdasarkanJenisKelamin.create.form = {
|
||||||
|
laki: "",
|
||||||
|
perempuan: "",
|
||||||
|
};
|
||||||
|
grafikBerdasarkanJenisKelamin.findMany.load();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -69,9 +77,103 @@ const grafikBerdasarkanJenisKelamin = proxy({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
findUnique: {
|
||||||
|
data: null as Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
|
||||||
|
omit: { isActive: true };
|
||||||
|
}> | null,
|
||||||
|
async load(id: string) {
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`/api/ppid/grafikberdasarkanjeniskelamin/${id}`
|
||||||
|
);
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json();
|
||||||
|
grafikBerdasarkanJenisKelamin.findUnique.data = data.data ?? null;
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch data", res.status, res.statusText);
|
||||||
|
grafikBerdasarkanJenisKelamin.findUnique.data = null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading grafik berdasarkan jenis kelamin:", error);
|
||||||
|
grafikBerdasarkanJenisKelamin.findUnique.data = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
id: "",
|
||||||
|
form: {...defaultForm},
|
||||||
|
loading: false,
|
||||||
|
async byId() {
|
||||||
|
// Method implementation if needed
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
const id = this.id;
|
||||||
|
if (!id) {
|
||||||
|
toast.warn("ID tidak valid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const cek = templateGrafikJenisKelamin.safeParse(this.form);
|
||||||
|
if (!cek.success) {
|
||||||
|
const err = `[${cek.error.issues.map((v) => `${v.path.join(".")}`).join("\n")}] required`;
|
||||||
|
toast.error(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.loading = true;
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/ppid/grafikberdasarkanjeniskelamin/${id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(this.form),
|
||||||
|
});
|
||||||
|
const result = await response.json();
|
||||||
|
if (!response.ok || !result?.success) {
|
||||||
|
throw new Error(result?.message || "Gagal update data");
|
||||||
|
}
|
||||||
|
toast.success("Berhasil update data!");
|
||||||
|
await grafikBerdasarkanJenisKelamin.findMany.load();
|
||||||
|
return result.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error update data:", error);
|
||||||
|
toast.error("Gagal update data grafik berdasarkan jenis kelamin");
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
loading: false,
|
||||||
|
async byId(id: string) {
|
||||||
|
if (!id) return toast.warn("ID tidak valid");
|
||||||
|
|
||||||
|
try {
|
||||||
|
grafikBerdasarkanJenisKelamin.delete.loading = true;
|
||||||
|
|
||||||
|
const response = await fetch(`/api/ppid/grafikberdasarkanjeniskelamin/del/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (response.ok && result?.success) {
|
||||||
|
toast.success(result.message || "Grafik berdasarkan jenis kelamin berhasil dihapus");
|
||||||
|
await grafikBerdasarkanJenisKelamin.findMany.load(); // refresh list
|
||||||
|
} else {
|
||||||
|
toast.error(result?.message || "Gagal menghapus grafik berdasarkan jenis kelamin");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal delete:", error);
|
||||||
|
toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan jenis kelamin");
|
||||||
|
} finally {
|
||||||
|
grafikBerdasarkanJenisKelamin.delete.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const stateGrafikBerdasarkanJenisKelamin = proxy({
|
export default grafikBerdasarkanJenisKelamin;
|
||||||
grafikBerdasarkanJenisKelamin,
|
|
||||||
});
|
|
||||||
export default stateGrafikBerdasarkanJenisKelamin;
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const templateGrafikResponden = z.object({
|
|||||||
|
|
||||||
type GrafikResponden = Prisma.GrafikBerdasarkanRespondenGetPayload<{
|
type GrafikResponden = Prisma.GrafikBerdasarkanRespondenGetPayload<{
|
||||||
select: {
|
select: {
|
||||||
|
id: true;
|
||||||
sangatbaik: true;
|
sangatbaik: true;
|
||||||
baik: true;
|
baik: true;
|
||||||
kurangbaik: true;
|
kurangbaik: true;
|
||||||
@@ -20,7 +21,7 @@ type GrafikResponden = Prisma.GrafikBerdasarkanRespondenGetPayload<{
|
|||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const defaultForm: GrafikResponden = {
|
const defaultForm: Omit<GrafikResponden, 'id'> & { id?: string } = {
|
||||||
sangatbaik: "",
|
sangatbaik: "",
|
||||||
baik: "",
|
baik: "",
|
||||||
kurangbaik: "",
|
kurangbaik: "",
|
||||||
@@ -47,9 +48,15 @@ const grafikBerdasarkanResponden = proxy({
|
|||||||
"create"
|
"create"
|
||||||
].post(grafikBerdasarkanResponden.create.form);
|
].post(grafikBerdasarkanResponden.create.form);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
grafikBerdasarkanResponden.create.form = defaultForm;
|
const id = res.data?.data?.id;
|
||||||
grafikBerdasarkanResponden.findMany.load();
|
if (id) {
|
||||||
return toast.success("success create");
|
toast.success("Success create");
|
||||||
|
grafikBerdasarkanResponden.create.form = {
|
||||||
|
...defaultForm
|
||||||
|
};
|
||||||
|
grafikBerdasarkanResponden.findMany.load();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -75,10 +82,112 @@ const grafikBerdasarkanResponden = proxy({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
findUnique: {
|
||||||
|
data: null as Prisma.GrafikBerdasarkanRespondenGetPayload<{
|
||||||
|
omit: { isActive: true };
|
||||||
|
}> | null,
|
||||||
|
async load(id: string) {
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`/api/ppid/grafikberdasarkanresponden/${id}`
|
||||||
|
);
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json();
|
||||||
|
grafikBerdasarkanResponden.findUnique.data = data.data ?? null;
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch data", res.status, res.statusText);
|
||||||
|
grafikBerdasarkanResponden.findUnique.data = null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading grafik berdasarkan responden:", error);
|
||||||
|
grafikBerdasarkanResponden.findUnique.data = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
id: "",
|
||||||
|
form: {...defaultForm},
|
||||||
|
loading: false,
|
||||||
|
async byId() {
|
||||||
|
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
const id = this.id;
|
||||||
|
if (!id) {
|
||||||
|
toast.warn("ID tidak valid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cek = templateGrafikResponden.safeParse(this.form);
|
||||||
|
if (!cek.success) {
|
||||||
|
const err = `[${cek.error.issues
|
||||||
|
.map((v) => `${v.path.join(".")}`)
|
||||||
|
.join("\n")}] required`;
|
||||||
|
toast.error(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/ppid/grafikberdasarkanresponden/${id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(this.form),
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok || !result?.success) {
|
||||||
|
throw new Error(result?.message || "Gagal update data");
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success("Berhasil update data!");
|
||||||
|
|
||||||
|
await grafikBerdasarkanResponden.findMany.load();
|
||||||
|
|
||||||
|
return result.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error update data:", error);
|
||||||
|
toast.error("Gagal update data grafik berdasarkan responden");
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
loading: false,
|
||||||
|
async byId(id: string) {
|
||||||
|
if (!id) return toast.warn("ID tidak valid");
|
||||||
|
|
||||||
|
try {
|
||||||
|
grafikBerdasarkanResponden.delete.loading = true;
|
||||||
|
|
||||||
|
const response = await fetch(`/api/ppid/grafikberdasarkanresponden/del/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (response.ok && result?.success) {
|
||||||
|
toast.success(result.message || "Grafik berdasarkan responden berhasil dihapus");
|
||||||
|
await grafikBerdasarkanResponden.findMany.load(); // refresh list
|
||||||
|
} else {
|
||||||
|
toast.error(result?.message || "Gagal menghapus grafik berdasarkan responden");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal delete:", error);
|
||||||
|
toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan responden");
|
||||||
|
} finally {
|
||||||
|
grafikBerdasarkanResponden.delete.loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const stateGrafikResponden = proxy({
|
export default grafikBerdasarkanResponden;
|
||||||
grafikBerdasarkanResponden,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default stateGrafikResponden;
|
|
||||||
@@ -5,80 +5,182 @@ import { proxy } from "valtio";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const templateGrafikUmur = z.object({
|
const templateGrafikUmur = z.object({
|
||||||
remaja: z.string().min(2, "Data remaja harus diisi"),
|
remaja: z.string().min(2, "Data remaja harus diisi"),
|
||||||
dewasa: z.string().min(2, "Data dewasa harus diisi"),
|
dewasa: z.string().min(2, "Data dewasa harus diisi"),
|
||||||
orangtua: z.string().min(2, "Data orangtua harus diisi"),
|
orangtua: z.string().min(2, "Data orangtua harus diisi"),
|
||||||
lansia: z.string().min(2, "Data lansia harus diisi"),
|
lansia: z.string().min(2, "Data lansia harus diisi"),
|
||||||
});
|
});
|
||||||
|
|
||||||
type GrafikUmur = Prisma.GrafikBerdasarkanUmurGetPayload<{
|
type GrafikUmur = Prisma.GrafikBerdasarkanUmurGetPayload<{
|
||||||
select: {
|
select: {
|
||||||
remaja: true;
|
id: true;
|
||||||
dewasa: true;
|
remaja: true;
|
||||||
orangtua: true;
|
dewasa: true;
|
||||||
lansia: true;
|
orangtua: true;
|
||||||
};
|
lansia: true;
|
||||||
|
};
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const defaultForm: GrafikUmur = {
|
const defaultForm: Omit<GrafikUmur, "id"> & { id?: string } = {
|
||||||
remaja: "",
|
remaja: "",
|
||||||
dewasa: "",
|
dewasa: "",
|
||||||
orangtua: "",
|
orangtua: "",
|
||||||
lansia: "",
|
lansia: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const grafikBerdasarkanUmur = proxy({
|
const grafikBerdasarkanUmur = proxy({
|
||||||
create: {
|
create: {
|
||||||
form: defaultForm,
|
form: defaultForm,
|
||||||
loading: false,
|
loading: false,
|
||||||
async create() {
|
async create() {
|
||||||
const cek = templateGrafikUmur.safeParse(
|
const cek = templateGrafikUmur.safeParse(
|
||||||
grafikBerdasarkanUmur.create.form
|
grafikBerdasarkanUmur.create.form
|
||||||
);
|
);
|
||||||
if (!cek.success) {
|
if (!cek.success) {
|
||||||
const err = `[${cek.error.issues
|
const err = `[${cek.error.issues
|
||||||
.map((v) => `${v.path.join(".")}`)
|
.map((v) => `${v.path.join(".")}`)
|
||||||
.join("\n")}] required`;
|
.join("\n")}] required`;
|
||||||
return toast.error(err);
|
return toast.error(err);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
grafikBerdasarkanUmur.create.loading = true;
|
grafikBerdasarkanUmur.create.loading = true;
|
||||||
const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
|
const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
|
||||||
"create"
|
"create"
|
||||||
].post(grafikBerdasarkanUmur.create.form);
|
].post(grafikBerdasarkanUmur.create.form);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
grafikBerdasarkanUmur.create.form = defaultForm;
|
const id = res.data?.data?.id;
|
||||||
grafikBerdasarkanUmur.findMany.load();
|
if (id) {
|
||||||
return toast.success("success create");
|
toast.success("Success create");
|
||||||
}
|
grafikBerdasarkanUmur.create.form = {
|
||||||
return toast.error("failed create");
|
remaja: "",
|
||||||
} catch (error) {
|
dewasa: "",
|
||||||
console.log((error as Error).message);
|
orangtua: "",
|
||||||
} finally {
|
lansia: "",
|
||||||
grafikBerdasarkanUmur.create.loading = false;
|
};
|
||||||
}
|
grafikBerdasarkanUmur.findMany.load();
|
||||||
},
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toast.error("failed create");
|
||||||
|
} catch (error) {
|
||||||
|
console.log((error as Error).message);
|
||||||
|
} finally {
|
||||||
|
grafikBerdasarkanUmur.create.loading = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
findMany: {
|
},
|
||||||
data: null as
|
findMany: {
|
||||||
| Prisma.GrafikBerdasarkanUmurGetPayload<{
|
data: null as
|
||||||
omit: { isActive: true };
|
| Prisma.GrafikBerdasarkanUmurGetPayload<{
|
||||||
|
omit: { isActive: true };
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
loading: false,
|
loading: false,
|
||||||
async load() {
|
async load() {
|
||||||
const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
|
const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
|
||||||
"find-many"
|
"find-many"
|
||||||
].get();
|
].get();
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
grafikBerdasarkanUmur.findMany.data = res.data?.data ?? [];
|
grafikBerdasarkanUmur.findMany.data = res.data?.data ?? [];
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
findUnique: {
|
||||||
|
data: null as Prisma.GrafikBerdasarkanUmurGetPayload<{
|
||||||
|
omit: { isActive: true };
|
||||||
|
}> | null,
|
||||||
|
async load(id: string) {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/ppid/grafikberdasarkanumur/${id}`);
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json();
|
||||||
|
grafikBerdasarkanUmur.findUnique.data = data.data ?? null;
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch data", res.status, res.statusText);
|
||||||
|
grafikBerdasarkanUmur.findUnique.data = null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading grafik berdasarkan umur:", error);
|
||||||
|
grafikBerdasarkanUmur.findUnique.data = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
id: "",
|
||||||
|
form: { ...defaultForm },
|
||||||
|
loading: false,
|
||||||
|
async byId() {
|
||||||
|
// Method implementation if needed
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
const id = this.id;
|
||||||
|
if (!id) {
|
||||||
|
toast.warn("ID tidak valid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const cek = templateGrafikUmur.safeParse(this.form);
|
||||||
|
if (!cek.success) {
|
||||||
|
const err = `[${cek.error.issues
|
||||||
|
.map((v) => `${v.path.join(".")}`)
|
||||||
|
.join("\n")}] required`;
|
||||||
|
toast.error(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.loading = true;
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/ppid/grafikberdasarkanumur/${id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(this.form),
|
||||||
|
});
|
||||||
|
const result = await response.json();
|
||||||
|
if (!response.ok || !result?.success) {
|
||||||
|
throw new Error(result?.message || "Gagal update data");
|
||||||
|
}
|
||||||
|
toast.success("Berhasil update data!");
|
||||||
|
await grafikBerdasarkanUmur.findMany.load();
|
||||||
|
return result.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error update data:", error);
|
||||||
|
toast.error("Gagal update data grafik berdasarkan umur");
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
loading: false,
|
||||||
|
async byId(id: string) {
|
||||||
|
if (!id) return toast.warn("ID tidak valid");
|
||||||
|
|
||||||
const stateGrafikBerdasarkanUmur = proxy({
|
try {
|
||||||
grafikBerdasarkanUmur,
|
grafikBerdasarkanUmur.delete.loading = true;
|
||||||
})
|
|
||||||
|
|
||||||
export default stateGrafikBerdasarkanUmur;
|
const response = await fetch(`/api/ppid/grafikberdasarkanumur/del/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (response.ok && result?.success) {
|
||||||
|
toast.success(result.message || "Grafik berdasarkan umur berhasil dihapus");
|
||||||
|
await grafikBerdasarkanUmur.findMany.load(); // refresh list
|
||||||
|
} else {
|
||||||
|
toast.error(result?.message || "Gagal menghapus grafik berdasarkan umur");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal delete:", error);
|
||||||
|
toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan umur");
|
||||||
|
} finally {
|
||||||
|
grafikBerdasarkanUmur.delete.loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default grafikBerdasarkanUmur;
|
||||||
@@ -11,12 +11,13 @@ const templateGrafikHasilKepuasanMasyarakat = z.object({
|
|||||||
|
|
||||||
type GrafikHasilKepuasanMasyarakat = Prisma.IndeksKepuasanMasyarakatGetPayload<{
|
type GrafikHasilKepuasanMasyarakat = Prisma.IndeksKepuasanMasyarakatGetPayload<{
|
||||||
select: {
|
select: {
|
||||||
|
id: true;
|
||||||
label: true;
|
label: true;
|
||||||
kepuasan: true;
|
kepuasan: true;
|
||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const defaultForm: GrafikHasilKepuasanMasyarakat = {
|
const defaultForm: Omit<GrafikHasilKepuasanMasyarakat, 'id'> & { id?: string } = {
|
||||||
label: "",
|
label: "",
|
||||||
kepuasan: "",
|
kepuasan: "",
|
||||||
};
|
};
|
||||||
@@ -41,13 +42,18 @@ const grafikHasilKepuasanMasyarakat = proxy({
|
|||||||
grafikHasilKepuasanMasyarakat.create.form
|
grafikHasilKepuasanMasyarakat.create.form
|
||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
grafikHasilKepuasanMasyarakat.create.form = {
|
const id = res.data?.data?.id;
|
||||||
label: "",
|
if (id) {
|
||||||
kepuasan: ""
|
toast.success("Success create");
|
||||||
};
|
grafikHasilKepuasanMasyarakat.create.form = {
|
||||||
grafikHasilKepuasanMasyarakat.findMany.load();
|
label: "",
|
||||||
return toast.success("success create");
|
kepuasan: "",
|
||||||
|
};
|
||||||
|
grafikHasilKepuasanMasyarakat.findMany.load();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log((error as Error).message);
|
console.log((error as Error).message);
|
||||||
@@ -58,19 +64,127 @@ const grafikHasilKepuasanMasyarakat = proxy({
|
|||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as
|
data: null as
|
||||||
| Prisma.IndeksKepuasanMasyarakatGetPayload<{ omit: { isActive: true } }>[]
|
| Prisma.IndeksKepuasanMasyarakatGetPayload<{
|
||||||
| null,
|
omit: { isActive: true };
|
||||||
|
}>[]
|
||||||
|
| null,
|
||||||
async load() {
|
async load() {
|
||||||
const res = await ApiFetch.api.ppid.grafikhasilkepuasamanmasyarakat["find-many"].get();
|
const res = await ApiFetch.api.ppid.grafikhasilkepuasamanmasyarakat[
|
||||||
if (res.status === 200) {
|
"find-many"
|
||||||
grafikHasilKepuasanMasyarakat.findMany.data = res.data?.data ?? [];
|
].get();
|
||||||
|
if (res.status === 200) {
|
||||||
|
grafikHasilKepuasanMasyarakat.findMany.data = res.data?.data ?? [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
findUnique: {
|
||||||
|
data: null as Prisma.IndeksKepuasanMasyarakatGetPayload<{
|
||||||
|
omit: { isActive: true };
|
||||||
|
}> | null,
|
||||||
|
|
||||||
|
async load(id: string) {
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`/api/ppid/grafikhasilkepuasamanmasyarakat/${id}`
|
||||||
|
);
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json();
|
||||||
|
grafikHasilKepuasanMasyarakat.findUnique.data = data.data ?? null;
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch data", res.status, res.statusText);
|
||||||
|
grafikHasilKepuasanMasyarakat.findUnique.data = null;
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading grafik hasil kepuasan masyarakat:", error);
|
||||||
|
grafikHasilKepuasanMasyarakat.findUnique.data = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
id: "",
|
||||||
|
form: { ...defaultForm },
|
||||||
|
loading: false,
|
||||||
|
async byId() {
|
||||||
|
// Method implementation if needed
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
const id = this.id;
|
||||||
|
if (!id) {
|
||||||
|
toast.warn("ID tidak valid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Validasi pakai Zod
|
||||||
|
const cek = templateGrafikHasilKepuasanMasyarakat.safeParse(this.form);
|
||||||
|
if (!cek.success) {
|
||||||
|
const err = `[${cek.error.issues.map((v) => `${v.path.join(".")}`).join("\n")}] required`;
|
||||||
|
toast.error(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/ppid/grafikhasilkepuasamanmasyarakat/${id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(this.form),
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok || !result?.success) {
|
||||||
|
throw new Error(result?.message || "Gagal update data");
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success("Berhasil update data!");
|
||||||
|
|
||||||
|
// ✅ Optional: refresh list kalau kamu langsung ke halaman list
|
||||||
|
await grafikHasilKepuasanMasyarakat.findMany.load();
|
||||||
|
|
||||||
|
return result.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error update data:", error);
|
||||||
|
toast.error("Gagal update data grafik hasil kepuasan masyarakat");
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
loading: false,
|
||||||
|
async byId(id: string) {
|
||||||
|
if (!id) return toast.warn("ID tidak valid");
|
||||||
|
|
||||||
|
try {
|
||||||
|
grafikHasilKepuasanMasyarakat.delete.loading = true;
|
||||||
|
|
||||||
|
const response = await fetch(`/api/ppid/grafikhasilkepuasamanmasyarakat/del/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (response.ok && result?.success) {
|
||||||
|
toast.success(result.message || "Grafik hasil kepuasan masyarakat berhasil dihapus");
|
||||||
|
await grafikHasilKepuasanMasyarakat.findMany.load(); // refresh list
|
||||||
|
} else {
|
||||||
|
toast.error(result?.message || "Gagal menghapus grafik hasil kepuasan masyarakat");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal delete:", error);
|
||||||
|
toast.error("Terjadi kesalahan saat menghapus grafik hasil kepuasan masyarakat");
|
||||||
|
} finally {
|
||||||
|
grafikHasilKepuasanMasyarakat.delete.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const stateGrafikHasilKepuasanMasyarakat = proxy({
|
export default grafikHasilKepuasanMasyarakat;
|
||||||
grafikHasilKepuasanMasyarakat,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default stateGrafikHasilKepuasanMasyarakat;
|
|
||||||
|
|||||||
72
src/app/admin/(dashboard)/ppid/_com/layoutTabs.tsx
Normal file
72
src/app/admin/(dashboard)/ppid/_com/layoutTabs.tsx
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
'use client'
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
function LayoutTabs({ children }: { children: React.ReactNode }) {
|
||||||
|
const router = useRouter()
|
||||||
|
const pathname = usePathname()
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
label: "Grafik Hasil Kepuasan Masyarakat",
|
||||||
|
value: "grafikhasilkepuasamanmasyarakat",
|
||||||
|
href: "/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Grafik Berdasarkan Jenis Kelamin Responden",
|
||||||
|
value: "grafikberdasarkanjeniskelaminresponden",
|
||||||
|
href: "/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Grafik Berdasarkan Pilihan Responden",
|
||||||
|
value: "grafikberdasarkanpilihanresponden",
|
||||||
|
href: "/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Grafik Berdasarkan Umur Responden",
|
||||||
|
value: "grafikberdasarkanumurresponden",
|
||||||
|
href: "/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const curentTab = tabs.find(tab => tab.href === pathname)
|
||||||
|
const [activeTab, setActiveTab] = useState<string | null>(curentTab?.value || tabs[0].value);
|
||||||
|
|
||||||
|
const handleTabChange = (value: string | null) => {
|
||||||
|
const tab = tabs.find(t => t.value === value)
|
||||||
|
if (tab) {
|
||||||
|
router.push(tab.href)
|
||||||
|
}
|
||||||
|
setActiveTab(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const match = tabs.find(tab => tab.href === pathname)
|
||||||
|
if (match) {
|
||||||
|
setActiveTab(match.value)
|
||||||
|
}
|
||||||
|
}, [pathname])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Indeks Kepuasan Masyarakat (IKM) Desa Darmasaba</Title>
|
||||||
|
<Tabs color={colors['blue-button']} variant='pills' value={activeTab} onChange={handleTabChange}>
|
||||||
|
<TabsList p={"xs"} bg={"#BBC8E7FF"}>
|
||||||
|
{tabs.map((e, i) => (
|
||||||
|
<TabsTab key={i} value={e.value}>{e.label}</TabsTab>
|
||||||
|
))}
|
||||||
|
</TabsList>
|
||||||
|
{tabs.map((e, i) => (
|
||||||
|
<TabsPanel key={i} value={e.value}>
|
||||||
|
{/* Konten dummy, bisa diganti tergantung routing */}
|
||||||
|
<></>
|
||||||
|
</TabsPanel>
|
||||||
|
))}
|
||||||
|
</Tabs>
|
||||||
|
{children}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LayoutTabs;
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
'use client'
|
|
||||||
import stateGrafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
|
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { Box, Button, Center, Flex, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { Cell, Pie, PieChart } from 'recharts';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
|
|
||||||
function GrafikBerdasarkanJenisKelamin() {
|
|
||||||
const grafikBerdasarkanJenisKelamin = useProxy(stateGrafikBerdasarkanJenisKelamin.grafikBerdasarkanJenisKelamin)
|
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const updateChartData = (data: any) => {
|
|
||||||
if (data && data.length > 0) {
|
|
||||||
const totalLaki = data.reduce((acc: number, cur: any) => acc + Number(cur.laki || 0), 0);
|
|
||||||
const totalPerempuan = data.reduce((acc: number, cur: any) => acc + Number(cur.perempuan || 0), 0);
|
|
||||||
|
|
||||||
setDonutData([
|
|
||||||
{ name: 'Laki-laki', value: totalLaki, color: colors['blue-button'], key: 'laki-laki' },
|
|
||||||
{ name: 'Perempuan', value: totalPerempuan, color: '#FF6384', key: 'perempuan' }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
|
||||||
await grafikBerdasarkanJenisKelamin.findMany.load();
|
|
||||||
if (grafikBerdasarkanJenisKelamin.findMany.data) {
|
|
||||||
updateChartData(grafikBerdasarkanJenisKelamin.findMany.data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
try {
|
|
||||||
// Simpan data baru
|
|
||||||
await grafikBerdasarkanJenisKelamin.create.create();
|
|
||||||
|
|
||||||
// Muat ulang data
|
|
||||||
await grafikBerdasarkanJenisKelamin.findMany.load();
|
|
||||||
|
|
||||||
// Update chart dengan data baru
|
|
||||||
if (grafikBerdasarkanJenisKelamin.findMany.data) {
|
|
||||||
updateChartData(grafikBerdasarkanJenisKelamin.findMany.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset form setelah submit
|
|
||||||
grafikBerdasarkanJenisKelamin.create.form.laki = '';
|
|
||||||
grafikBerdasarkanJenisKelamin.create.form.perempuan = '';
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error submitting data:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Box py={15}>
|
|
||||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
|
||||||
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Laki-laki"
|
|
||||||
placeholder="masukkan jumlah laki-laki"
|
|
||||||
value={grafikBerdasarkanJenisKelamin.create.form.laki}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanJenisKelamin.create.form.laki = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Perempuan"
|
|
||||||
type="number"
|
|
||||||
placeholder="masukkan jumlah perempuan"
|
|
||||||
value={grafikBerdasarkanJenisKelamin.create.form.perempuan}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanJenisKelamin.create.form.perempuan = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
mt={10}
|
|
||||||
bg={colors['blue-button']}
|
|
||||||
onClick={handleSubmit}
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Chart */}
|
|
||||||
<Box>
|
|
||||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
|
||||||
<Stack>
|
|
||||||
<Title pb={10} order={3}>Grafik Berdasarkan Jenis Kelamin Responden</Title>
|
|
||||||
{mounted && donutData.length > 0 && (
|
|
||||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
|
||||||
<Center>
|
|
||||||
<PieChart
|
|
||||||
width={1000} height={400}
|
|
||||||
data={donutData}
|
|
||||||
>
|
|
||||||
|
|
||||||
<Pie
|
|
||||||
dataKey="value"
|
|
||||||
nameKey="name"
|
|
||||||
data={donutData}
|
|
||||||
innerRadius={120}
|
|
||||||
outerRadius={230}
|
|
||||||
label={true}
|
|
||||||
>
|
|
||||||
{donutData.map((entry, index) => (
|
|
||||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
||||||
))}
|
|
||||||
</Pie>
|
|
||||||
</PieChart>
|
|
||||||
</Center>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={'#FF6384'} w={20} h={20} />
|
|
||||||
<Text>Perempuan: {donutData.find((entry) => entry.name === 'Perempuan')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
|
||||||
<Text>Laki-laki: {donutData.find((entry) => entry.name === 'Laki-laki')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GrafikBerdasarkanJenisKelamin;
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
'use client'
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import stateGrafikResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
|
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { Box, Button, Center, Flex, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { PieChart, Pie, Cell } from 'recharts';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
|
|
||||||
function GrafikBerdasarkanResponden() {
|
|
||||||
const grafikBerdasarkanResponden = useProxy(stateGrafikResponden.grafikBerdasarkanResponden)
|
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const updateChartData = (data: any) => {
|
|
||||||
if (data && data.length > 0) {
|
|
||||||
const totalSangatBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.sangatbaik || 0), 0);
|
|
||||||
const totalBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.baik || 0), 0);
|
|
||||||
const totalKurangBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.kurangbaik || 0), 0);
|
|
||||||
const totalTidakBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.tidakbaik || 0), 0);
|
|
||||||
setDonutData([
|
|
||||||
{ name: 'sangatbaik', value: totalSangatBaik, color: colors['blue-button'], key: 'sangatbaik' },
|
|
||||||
{ name: 'baik', value: totalBaik, color: '#10A85AFF', key: 'baik' },
|
|
||||||
{ name: 'kurangbaik', value: totalKurangBaik, color: '#B3AA12FF', key: 'kurangbaik' },
|
|
||||||
{ name: 'tidakbaik', value: totalTidakBaik, color: '#B21313FF', key: 'tidakbaik' }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
|
||||||
await grafikBerdasarkanResponden.findMany.load();
|
|
||||||
if (grafikBerdasarkanResponden.findMany.data) {
|
|
||||||
updateChartData(grafikBerdasarkanResponden.findMany.data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
try {
|
|
||||||
// Simpan data baru
|
|
||||||
await grafikBerdasarkanResponden.create.create();
|
|
||||||
|
|
||||||
// Muat ulang data
|
|
||||||
await grafikBerdasarkanResponden.findMany.load();
|
|
||||||
|
|
||||||
// Update chart dengan data baru
|
|
||||||
if (grafikBerdasarkanResponden.findMany.data) {
|
|
||||||
updateChartData(grafikBerdasarkanResponden.findMany.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset form setelah submit
|
|
||||||
grafikBerdasarkanResponden.create.form.sangatbaik = '';
|
|
||||||
grafikBerdasarkanResponden.create.form.baik = '';
|
|
||||||
grafikBerdasarkanResponden.create.form.kurangbaik = '';
|
|
||||||
grafikBerdasarkanResponden.create.form.tidakbaik = '';
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error submitting data:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Box py={15}>
|
|
||||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
|
||||||
<Stack gap={"xs"}>
|
|
||||||
<Title order={3}>Grafik Berdasarkan Responden</Title>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Sangat Baik"
|
|
||||||
value={grafikBerdasarkanResponden.create.form.sangatbaik}
|
|
||||||
placeholder="masukkan jumlah respon sangat baik"
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanResponden.create.form.sangatbaik = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Baik"
|
|
||||||
value={grafikBerdasarkanResponden.create.form.baik}
|
|
||||||
placeholder="masukkan jumlah respon baik"
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanResponden.create.form.baik = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Kurang Baik"
|
|
||||||
value={grafikBerdasarkanResponden.create.form.kurangbaik}
|
|
||||||
placeholder="masukkan jumlah respon kurang baik"
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanResponden.create.form.kurangbaik = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Tidak Baik"
|
|
||||||
value={grafikBerdasarkanResponden.create.form.tidakbaik}
|
|
||||||
placeholder="masukkan jumlah respon tidak baik"
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanResponden.create.form.tidakbaik = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Group>
|
|
||||||
<Button
|
|
||||||
bg={colors['blue-button']}
|
|
||||||
onClick={handleSubmit}
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Chart */}
|
|
||||||
<Box>
|
|
||||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
|
||||||
<Stack>
|
|
||||||
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
|
||||||
{mounted && donutData.length > 0 && (
|
|
||||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
|
||||||
<Center>
|
|
||||||
<PieChart
|
|
||||||
width={1000} height={400}
|
|
||||||
data={donutData}
|
|
||||||
>
|
|
||||||
<Pie
|
|
||||||
dataKey="value"
|
|
||||||
nameKey="name"
|
|
||||||
data={donutData}
|
|
||||||
innerRadius={120}
|
|
||||||
outerRadius={230}
|
|
||||||
label={true}
|
|
||||||
>
|
|
||||||
{donutData.map((entry, index) => (
|
|
||||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
||||||
))}
|
|
||||||
</Pie>
|
|
||||||
</PieChart>
|
|
||||||
</Center>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
|
||||||
<Text>Sangat Baik: {donutData.find((entry) => entry.name === 'sangatbaik')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={'#10A85AFF'} w={20} h={20} />
|
|
||||||
<Text>Baik: {donutData.find((entry) => entry.name === 'baik')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={'#B3AA12FF'} w={20} h={20} />
|
|
||||||
<Text>Kurang Baik: {donutData.find((entry) => entry.name === 'kurangbaik')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={'#B21313FF'} w={20} h={20} />
|
|
||||||
<Text>Tidak Baik: {donutData.find((entry) => entry.name === 'tidakbaik')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GrafikBerdasarkanResponden;
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
'use client'
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { Box, Button, Center, Flex, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
import stateGrafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
|
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
|
||||||
import { PieChart, Pie, Cell } from 'recharts';
|
|
||||||
|
|
||||||
function GrafikBerdasarakanUmur() {
|
|
||||||
const grafikBerdasarkanUmur = useProxy(stateGrafikBerdasarkanUmur.grafikBerdasarkanUmur)
|
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const updateChartData = (data: any) => {
|
|
||||||
if (data && data.length > 0) {
|
|
||||||
const totalRemaja = data.reduce((acc: number, cur: any) => acc + Number(cur.remaja || 0), 0);
|
|
||||||
const totalDewasa = data.reduce((acc: number, cur: any) => acc + Number(cur.dewasa || 0), 0);
|
|
||||||
const totalOrangtua = data.reduce((acc: number, cur: any) => acc + Number(cur.orangtua || 0), 0);
|
|
||||||
const totalLansia = data.reduce((acc: number, cur: any) => acc + Number(cur.lansia || 0), 0);
|
|
||||||
|
|
||||||
setDonutData([
|
|
||||||
{ name: 'Remaja', value: totalRemaja, color: colors['blue-button'], key: 'remaja' },
|
|
||||||
{ name: 'Dewasa', value: totalDewasa, color: '#D32711FF', key: 'dewasa' },
|
|
||||||
{ name: 'Orangtua', value: totalOrangtua, color: '#B46B04FF', key: 'orangtua' },
|
|
||||||
{ name: 'Lansia', value: totalLansia, color: '#038617FF', key: 'lansia' }
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
|
||||||
await grafikBerdasarkanUmur.findMany.load();
|
|
||||||
if (grafikBerdasarkanUmur.findMany.data) {
|
|
||||||
updateChartData(grafikBerdasarkanUmur.findMany.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
try {
|
|
||||||
await grafikBerdasarkanUmur.create.create();
|
|
||||||
await grafikBerdasarkanUmur.findMany.load();
|
|
||||||
if (grafikBerdasarkanUmur.findMany.data) {
|
|
||||||
updateChartData(grafikBerdasarkanUmur.findMany.data);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error submitting data:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Box py={15}>
|
|
||||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
|
||||||
<Stack gap={"xs"}>
|
|
||||||
<Title order={3}>Grafik Berdasarkan Umur Responden</Title>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Remaja"
|
|
||||||
placeholder="masukkan jumlah responden remaja"
|
|
||||||
value={grafikBerdasarkanUmur.create.form.remaja}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanUmur.create.form.remaja = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Dewasa"
|
|
||||||
placeholder="masukkan jumlah responden dewasa"
|
|
||||||
value={grafikBerdasarkanUmur.create.form.dewasa}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanUmur.create.form.dewasa = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Orangtua"
|
|
||||||
placeholder="masukkan jumlah responden orangtua"
|
|
||||||
value={grafikBerdasarkanUmur.create.form.orangtua}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanUmur.create.form.orangtua = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
w={{ base: '100%', md: '50%' }}
|
|
||||||
label="Lansia"
|
|
||||||
placeholder="masukkan jumlah responden lansia"
|
|
||||||
value={grafikBerdasarkanUmur.create.form.lansia}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikBerdasarkanUmur.create.form.lansia = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Group>
|
|
||||||
<Button
|
|
||||||
mt={10}
|
|
||||||
bg={colors['blue-button']}
|
|
||||||
onClick={handleSubmit}
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Chart */}
|
|
||||||
<Box>
|
|
||||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
|
||||||
<Stack>
|
|
||||||
<Title pb={10} order={3}>Grafik Berdasarkan Umur Responden</Title>
|
|
||||||
{mounted && donutData.length > 0 && (
|
|
||||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
|
||||||
<Center>
|
|
||||||
<PieChart
|
|
||||||
width={1000} height={400}
|
|
||||||
data={donutData}
|
|
||||||
>
|
|
||||||
<Pie
|
|
||||||
dataKey="value"
|
|
||||||
nameKey="name"
|
|
||||||
data={donutData}
|
|
||||||
innerRadius={120}
|
|
||||||
outerRadius={230}
|
|
||||||
label={true}
|
|
||||||
>
|
|
||||||
{donutData.map((entry, index) => (
|
|
||||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
||||||
))}
|
|
||||||
</Pie>
|
|
||||||
</PieChart>
|
|
||||||
</Center>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
|
||||||
<Text>17 - 25 tahun: {donutData.find((entry) => entry.name === 'remaja')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={'#D32711FF'} w={20} h={20} />
|
|
||||||
<Text>26 - 45 tahun: {donutData.find((entry) => entry.name === 'dewasa')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={'#B46B04FF'} w={20} h={20} />
|
|
||||||
<Text>46 - 60 tahun: {donutData.find((entry) => entry.name === 'orangtua')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={"md"} align={"center"}>
|
|
||||||
<Box bg={'#038617FF'} w={20} h={20} />
|
|
||||||
<Text>di atas 60 tahun: {donutData.find((entry) => entry.name === 'lansia')?.value}</Text>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GrafikBerdasarakanUmur;
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
'use client'
|
|
||||||
import stateGrafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
|
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core';
|
|
||||||
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
|
|
||||||
function GrafikHasilKepuasan() {
|
|
||||||
const grafikHasilKepuasan = useProxy(stateGrafikHasilKepuasanMasyarakat.grafikHasilKepuasanMasyarakat)
|
|
||||||
const [chartData, setChartData] = useState<any[]>([]);
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
const isTablet = useMediaQuery('(max-width: 1024px)')
|
|
||||||
const isMobile = useMediaQuery('(max-width: 768px)')
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
|
||||||
const fetchData = async () => {
|
|
||||||
await grafikHasilKepuasan.findMany.load();
|
|
||||||
if (grafikHasilKepuasan.findMany.data && grafikHasilKepuasan.findMany.data.length > 0) {
|
|
||||||
setChartData(grafikHasilKepuasan.findMany.data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Box py={15}>
|
|
||||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
|
||||||
<Stack>
|
|
||||||
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
|
||||||
<TextInput
|
|
||||||
label="Label"
|
|
||||||
placeholder="masukkan label"
|
|
||||||
value={grafikHasilKepuasan.create.form.label}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikHasilKepuasan.create.form.label = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
label="Jumlah Kepuasan"
|
|
||||||
type="number"
|
|
||||||
placeholder="masukkan jumlah kepuasan"
|
|
||||||
value={grafikHasilKepuasan.create.form.kepuasan}
|
|
||||||
onChange={(val) => {
|
|
||||||
grafikHasilKepuasan.create.form.kepuasan = val.currentTarget.value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
mt={10}
|
|
||||||
bg={colors['blue-button']}
|
|
||||||
onClick={async () => {
|
|
||||||
await grafikHasilKepuasan.create.create();
|
|
||||||
await grafikHasilKepuasan.findMany.load();
|
|
||||||
if (grafikHasilKepuasan.findMany.data) {
|
|
||||||
setChartData(grafikHasilKepuasan.findMany.data);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Chart */}
|
|
||||||
<Box style={{ width: '100%', minWidth: 300, height: 400, minHeight: 300 }}>
|
|
||||||
<Paper style={{ width: '100%', minWidth: 300, height: 400, minHeight: 300 }} bg={colors['white-1']} p={'md'}>
|
|
||||||
<Stack gap={"xs"}>
|
|
||||||
<Title pb={10} order={3}>Data Kepuasan Masyarakat</Title>
|
|
||||||
{mounted && chartData.length > 0 && (
|
|
||||||
<BarChart width={isMobile ? 300 : isTablet ? 600 : 900} height={380} data={chartData} >
|
|
||||||
<XAxis dataKey="label" />
|
|
||||||
<YAxis />
|
|
||||||
<Tooltip />
|
|
||||||
<Legend />
|
|
||||||
<Bar dataKey="kepuasan" fill={colors['blue-button']} name="Kepuasan" />
|
|
||||||
</BarChart>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GrafikHasilKepuasan;
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
'use client'
|
||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useRouter, useParams } from 'next/navigation';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
|
||||||
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
|
||||||
|
function EditGrafikBerdasarkanJenisKelaminResponden() {
|
||||||
|
const router = useRouter()
|
||||||
|
const params = useParams() as { id: string }
|
||||||
|
const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
|
||||||
|
const id = params.id
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(id){
|
||||||
|
stategrafikBerdasarkanJenisKelamin.findUnique.load(id).then(() => {
|
||||||
|
const data = stategrafikBerdasarkanJenisKelamin.findUnique.data
|
||||||
|
if(data){
|
||||||
|
stategrafikBerdasarkanJenisKelamin.update.form = {
|
||||||
|
laki: data.laki || '',
|
||||||
|
perempuan: data.perempuan || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
stategrafikBerdasarkanJenisKelamin.update.id = id;
|
||||||
|
await stategrafikBerdasarkanJenisKelamin.update.submit();
|
||||||
|
router.push('/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden')
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Laki-laki"
|
||||||
|
type='number'
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanJenisKelamin.update.form.laki}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanJenisKelamin.update.form.laki = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Perempuan"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanJenisKelamin.update.form.perempuan}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanJenisKelamin.update.form.perempuan = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditGrafikBerdasarkanJenisKelaminResponden;
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
'use client'
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import React from 'react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
|
||||||
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
|
||||||
|
function GrafikBerdasarkanJenisKelaminRespondenCreate() {
|
||||||
|
const router = useRouter();
|
||||||
|
const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
|
||||||
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
stategrafikBerdasarkanJenisKelamin.create.form = {
|
||||||
|
...stategrafikBerdasarkanJenisKelamin.create.form,
|
||||||
|
laki: "",
|
||||||
|
perempuan: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
const id = await stategrafikBerdasarkanJenisKelamin.create.create();
|
||||||
|
if (id) {
|
||||||
|
const idStr = String(id);
|
||||||
|
await stategrafikBerdasarkanJenisKelamin.findUnique.load(idStr);
|
||||||
|
if (stategrafikBerdasarkanJenisKelamin.findUnique.data) {
|
||||||
|
setDonutData([stategrafikBerdasarkanJenisKelamin.findUnique.data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resetForm();
|
||||||
|
router.push("/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden")
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Laki-laki"
|
||||||
|
type='number'
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanJenisKelamin.create.form.laki}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanJenisKelamin.create.form.laki = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Baik"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanJenisKelamin.create.form.perempuan}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanJenisKelamin.create.form.perempuan = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GrafikBerdasarkanJenisKelaminRespondenCreate;
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
'use client'
|
||||||
|
import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Flex, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import JudulListTab from '../../../_com/jusulListTab';
|
||||||
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
|
|
||||||
|
function GrafikBerdasarkanJenisKelamin() {
|
||||||
|
const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
|
||||||
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
const [modalHapus, setModalHapus] = useState(false)
|
||||||
|
const [selectedId, setSelectedId] = useState<string | null>(null)
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
if (selectedId) {
|
||||||
|
await grafikBerdasarkanJenisKelamin.delete.byId(selectedId)
|
||||||
|
setModalHapus(false)
|
||||||
|
setSelectedId(null)
|
||||||
|
|
||||||
|
stategrafikBerdasarkanJenisKelamin.findMany.load()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
stategrafikBerdasarkanJenisKelamin.findMany.load()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (stategrafikBerdasarkanJenisKelamin.findMany.data) {
|
||||||
|
const totalLaki = stategrafikBerdasarkanJenisKelamin.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.laki || 0), 0);
|
||||||
|
const totalPerempuan = stategrafikBerdasarkanJenisKelamin.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.perempuan || 0), 0);
|
||||||
|
setDonutData([
|
||||||
|
{ name: 'laki', value: totalLaki, color: colors['blue-button'], key: 'laki' },
|
||||||
|
{ name: 'perempuan', value: totalPerempuan, color: '#10A85AFF', key: 'perempuan' }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}, [stategrafikBerdasarkanJenisKelamin.findMany.data])
|
||||||
|
|
||||||
|
if (!stategrafikBerdasarkanJenisKelamin.findMany.data) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Skeleton h={500} />
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Stack gap={"xs"}>
|
||||||
|
<Paper bg={colors['white-1']} p={"md"}>
|
||||||
|
<JudulListTab
|
||||||
|
title='List Grafik Berdasarkan Jenis Kelamin Responden'
|
||||||
|
href='/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/create'
|
||||||
|
placeholder='pencarian'
|
||||||
|
searchIcon={<IconSearch size={16} />}
|
||||||
|
/>
|
||||||
|
<Table striped withTableBorder withRowBorders>
|
||||||
|
<TableThead>
|
||||||
|
<TableTr>
|
||||||
|
<TableTh>Laki-laki</TableTh>
|
||||||
|
<TableTh>Perempuan</TableTh>
|
||||||
|
<TableTh>Edit</TableTh>
|
||||||
|
<TableTh>Delete</TableTh>
|
||||||
|
</TableTr>
|
||||||
|
</TableThead>
|
||||||
|
<TableTbody>
|
||||||
|
{stategrafikBerdasarkanJenisKelamin.findMany.data.length === 0 ? (
|
||||||
|
<TableTr>
|
||||||
|
<TableTd colSpan={6}>
|
||||||
|
<Text ta='center' c='dimmed'>Belum ada data grafik responden</Text>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
) : (
|
||||||
|
stategrafikBerdasarkanJenisKelamin.findMany.data.map((item) => (
|
||||||
|
<TableTr key={item.id}>
|
||||||
|
<TableTd>{item.laki}</TableTd>
|
||||||
|
<TableTd>{item.perempuan}</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button color='green' onClick={() => router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/${item.id}`)}>
|
||||||
|
<IconEdit size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button
|
||||||
|
color='red'
|
||||||
|
disabled={stategrafikBerdasarkanJenisKelamin.delete.loading}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedId(item.id)
|
||||||
|
setModalHapus(true)
|
||||||
|
}}>
|
||||||
|
<IconTrash size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableTbody>
|
||||||
|
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* Chart */}
|
||||||
|
<Box>
|
||||||
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
||||||
|
{mounted && donutData.length > 0 ? (<Box style={{ width: '100%', height: 'auto', minHeight: 200 }}>
|
||||||
|
<PieChart
|
||||||
|
width={800} height={300}
|
||||||
|
data={donutData}
|
||||||
|
>
|
||||||
|
<Pie
|
||||||
|
dataKey="value"
|
||||||
|
nameKey="name"
|
||||||
|
data={donutData}
|
||||||
|
cx={500}
|
||||||
|
cy={150}
|
||||||
|
innerRadius={60}
|
||||||
|
outerRadius={115}
|
||||||
|
label={true}
|
||||||
|
>
|
||||||
|
{donutData.map((entry, index) => (
|
||||||
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||||
|
))}
|
||||||
|
</Pie>
|
||||||
|
</PieChart>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||||
|
<Text>Laki-laki: {donutData.find((entry) => entry.name === 'laki')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={'#10A85AFF'} w={20} h={20} />
|
||||||
|
<Text>Perempuan: {donutData.find((entry) => entry.name === 'perempuan')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Text c='dimmed'>Belum ada data untuk ditampilkan dalam grafik</Text>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{/* Modal Konfirmasi Hapus */}
|
||||||
|
<ModalKonfirmasiHapus
|
||||||
|
opened={modalHapus}
|
||||||
|
onClose={() => setModalHapus(false)}
|
||||||
|
onConfirm={handleDelete}
|
||||||
|
text='Apakah anda yakin ingin menghapus grafik berdasarkan hasil responden ini?'
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GrafikBerdasarkanJenisKelamin;
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
'use client'
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useRouter, useParams } from 'next/navigation';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import grafikBerdasarkanResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
|
||||||
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
|
||||||
|
function EditGrafikBerdasarkanResponden() {
|
||||||
|
const router = useRouter()
|
||||||
|
const params = useParams() as { id: string }
|
||||||
|
const stateGrafikResponden = useProxy(grafikBerdasarkanResponden)
|
||||||
|
const id = params.id
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(id){
|
||||||
|
stateGrafikResponden.findUnique.load(id).then(() => {
|
||||||
|
const data = stateGrafikResponden.findUnique.data
|
||||||
|
if(data){
|
||||||
|
stateGrafikResponden.update.form = {
|
||||||
|
sangatbaik: data.sangatbaik || '',
|
||||||
|
baik: data.baik || '',
|
||||||
|
kurangbaik: data.kurangbaik || '',
|
||||||
|
tidakbaik: data.tidakbaik || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
stateGrafikResponden.update.id = id;
|
||||||
|
await stateGrafikResponden.update.submit();
|
||||||
|
router.push('/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden')
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Sangat Baik"
|
||||||
|
type='number'
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stateGrafikResponden.update.form.sangatbaik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stateGrafikResponden.update.form.sangatbaik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Baik"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stateGrafikResponden.update.form.baik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stateGrafikResponden.update.form.baik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Kurang Baik"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stateGrafikResponden.update.form.kurangbaik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stateGrafikResponden.update.form.kurangbaik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Tidak Baik"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stateGrafikResponden.update.form.tidakbaik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stateGrafikResponden.update.form.tidakbaik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditGrafikBerdasarkanResponden;
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
'use client'
|
||||||
|
import grafikBerdasarkanResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, 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 GrafikBerdasarkanRespondenCreate() {
|
||||||
|
const router = useRouter()
|
||||||
|
const stategrafikBerdasarkanResponden = useProxy(grafikBerdasarkanResponden)
|
||||||
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
stategrafikBerdasarkanResponden.create.form = {
|
||||||
|
...stategrafikBerdasarkanResponden.create.form,
|
||||||
|
sangatbaik: "",
|
||||||
|
baik: "",
|
||||||
|
kurangbaik: "",
|
||||||
|
tidakbaik: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
const id = await stategrafikBerdasarkanResponden.create.create();
|
||||||
|
if (id) {
|
||||||
|
const idStr = String(id);
|
||||||
|
await stategrafikBerdasarkanResponden.findUnique.load(idStr);
|
||||||
|
if (stategrafikBerdasarkanResponden.findUnique.data) {
|
||||||
|
setDonutData([stategrafikBerdasarkanResponden.findUnique.data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resetForm();
|
||||||
|
router.push("/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden")
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Sangat Baik"
|
||||||
|
type='number'
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanResponden.create.form.sangatbaik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanResponden.create.form.sangatbaik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Baik"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanResponden.create.form.baik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanResponden.create.form.baik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Kurang Baik"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanResponden.create.form.kurangbaik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanResponden.create.form.kurangbaik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Tidak Baik"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanResponden.create.form.tidakbaik}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanResponden.create.form.tidakbaik = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GrafikBerdasarkanRespondenCreate;
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
'use client'
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Flex, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import JudulListTab from '../../../_com/jusulListTab';
|
||||||
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
|
import grafikBerdasarkanResponden from '../../../_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
|
||||||
|
|
||||||
|
function GrafikBerdasarkanResponden() {
|
||||||
|
|
||||||
|
const stategrafikBerdasarkanResponden = useProxy(grafikBerdasarkanResponden)
|
||||||
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
const [modalHapus, setModalHapus] = useState(false)
|
||||||
|
const [selectedId, setSelectedId] = useState<string | null>(null)
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
if (selectedId) {
|
||||||
|
await stategrafikBerdasarkanResponden.delete.byId(selectedId);
|
||||||
|
setModalHapus(false);
|
||||||
|
setSelectedId(null);
|
||||||
|
|
||||||
|
// Refresh data agar chart & tabel ikut update
|
||||||
|
stategrafikBerdasarkanResponden.findMany.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
setMounted(true)
|
||||||
|
stategrafikBerdasarkanResponden.findMany.load()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (stategrafikBerdasarkanResponden.findMany.data && stategrafikBerdasarkanResponden.findMany.data.length > 0) {
|
||||||
|
const totalSangatBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.sangatbaik || 0), 0);
|
||||||
|
const totalBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.baik || 0), 0);
|
||||||
|
const totalKurangBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.kurangbaik || 0), 0);
|
||||||
|
const totalTidakBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.tidakbaik || 0), 0);
|
||||||
|
setDonutData([
|
||||||
|
{ name: 'sangatbaik', value: totalSangatBaik, color: colors['blue-button'], key: 'sangatbaik' },
|
||||||
|
{ name: 'baik', value: totalBaik, color: '#10A85AFF', key: 'baik' },
|
||||||
|
{ name: 'kurangbaik', value: totalKurangBaik, color: '#B3AA12FF', key: 'kurangbaik' },
|
||||||
|
{ name: 'tidakbaik', value: totalTidakBaik, color: '#B21313FF', key: 'tidakbaik' }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [stategrafikBerdasarkanResponden.findMany.data])
|
||||||
|
|
||||||
|
if (!stategrafikBerdasarkanResponden.findMany.data) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Skeleton h={500} />
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Stack gap={"xs"}>
|
||||||
|
<Paper bg={colors['white-1']} p={"md"}>
|
||||||
|
<JudulListTab
|
||||||
|
title='List Grafik Berdasarkan Pilihan Responden'
|
||||||
|
href='/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/create'
|
||||||
|
placeholder='pencarian'
|
||||||
|
searchIcon={<IconSearch size={16} />}
|
||||||
|
/>
|
||||||
|
<Table striped withTableBorder withRowBorders>
|
||||||
|
<TableThead>
|
||||||
|
<TableTr>
|
||||||
|
<TableTh>Sangat Baik</TableTh>
|
||||||
|
<TableTh>Baik</TableTh>
|
||||||
|
<TableTh>Kurang Baik</TableTh>
|
||||||
|
<TableTh>Tidak Baik</TableTh>
|
||||||
|
<TableTh>Edit</TableTh>
|
||||||
|
<TableTh>Delete</TableTh>
|
||||||
|
</TableTr>
|
||||||
|
</TableThead>
|
||||||
|
<TableTbody>
|
||||||
|
{stategrafikBerdasarkanResponden.findMany.data.length === 0 ? (
|
||||||
|
<TableTr>
|
||||||
|
<TableTd colSpan={6}>
|
||||||
|
<Text ta='center' c='dimmed'>Belum ada data grafik responden</Text>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
) : (
|
||||||
|
stategrafikBerdasarkanResponden.findMany.data.map((item) => (
|
||||||
|
<TableTr key={item.id}>
|
||||||
|
<TableTd>{item.sangatbaik}</TableTd>
|
||||||
|
<TableTd>{item.baik}</TableTd>
|
||||||
|
<TableTd>{item.kurangbaik}</TableTd>
|
||||||
|
<TableTd>{item.tidakbaik}</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button color='green' onClick={() => router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/${item.id}`)}>
|
||||||
|
<IconEdit size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button
|
||||||
|
color='red'
|
||||||
|
disabled={stategrafikBerdasarkanResponden.delete.loading}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedId(item.id)
|
||||||
|
setModalHapus(true)
|
||||||
|
}}>
|
||||||
|
<IconTrash size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableTbody>
|
||||||
|
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* Chart */}
|
||||||
|
<Box>
|
||||||
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
||||||
|
{mounted && donutData.length > 0 ? (<Box style={{ width: '100%', height: 'auto', minHeight: 200 }}>
|
||||||
|
<PieChart
|
||||||
|
width={800} height={300}
|
||||||
|
data={donutData}
|
||||||
|
>
|
||||||
|
<Pie
|
||||||
|
dataKey="value"
|
||||||
|
nameKey="name"
|
||||||
|
data={donutData}
|
||||||
|
cx={500}
|
||||||
|
cy={150}
|
||||||
|
innerRadius={60}
|
||||||
|
outerRadius={115}
|
||||||
|
label={true}
|
||||||
|
>
|
||||||
|
{donutData.map((entry, index) => (
|
||||||
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||||
|
))}
|
||||||
|
</Pie>
|
||||||
|
</PieChart>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||||
|
<Text>Sangat Baik: {donutData.find((entry) => entry.name === 'sangatbaik')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={'#10A85AFF'} w={20} h={20} />
|
||||||
|
<Text>Baik: {donutData.find((entry) => entry.name === 'baik')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={'#B3AA12FF'} w={20} h={20} />
|
||||||
|
<Text>Kurang Baik: {donutData.find((entry) => entry.name === 'kurangbaik')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={'#B21313FF'} w={20} h={20} />
|
||||||
|
<Text>Tidak Baik: {donutData.find((entry) => entry.name === 'tidakbaik')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Text c='dimmed'>Belum ada data untuk ditampilkan dalam grafik</Text>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{/* Modal Konfirmasi Hapus */}
|
||||||
|
<ModalKonfirmasiHapus
|
||||||
|
opened={modalHapus}
|
||||||
|
onClose={() => setModalHapus(false)}
|
||||||
|
onConfirm={handleDelete}
|
||||||
|
text='Apakah anda yakin ingin menghapus grafik berdasarkan hasil responden ini?'
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GrafikBerdasarkanResponden;
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
'use client'
|
||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
|
||||||
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
|
function EditGrafikBerdasarakanUmur() {
|
||||||
|
const router = useRouter()
|
||||||
|
const params = useParams() as { id: string }
|
||||||
|
const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
|
||||||
|
const id = params.id
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(id){
|
||||||
|
stategrafikBerdasarkanUmur.findUnique.load(id).then(() => {
|
||||||
|
const data = stategrafikBerdasarkanUmur.findUnique.data
|
||||||
|
if(data){
|
||||||
|
stategrafikBerdasarkanUmur.update.form = {
|
||||||
|
remaja: data.remaja || '',
|
||||||
|
dewasa: data.dewasa || '',
|
||||||
|
orangtua: data.orangtua || '',
|
||||||
|
lansia: data.lansia || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
stategrafikBerdasarkanUmur.update.id = id;
|
||||||
|
await stategrafikBerdasarkanUmur.update.submit();
|
||||||
|
router.push('/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur')
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Remaja"
|
||||||
|
type='number'
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.update.form.remaja}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.update.form.remaja = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Dewasa"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.update.form.dewasa}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.update.form.dewasa = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Orangtua"
|
||||||
|
type='number'
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.update.form.orangtua}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.update.form.orangtua = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Lansia"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.update.form.lansia}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.update.form.lansia = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditGrafikBerdasarakanUmur;
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
'use client'
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
|
||||||
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
|
function GrafikBerdasarakanUmurCreate() {
|
||||||
|
const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
|
||||||
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
stategrafikBerdasarkanUmur.create.form = {
|
||||||
|
...stategrafikBerdasarkanUmur.create.form,
|
||||||
|
remaja: "",
|
||||||
|
dewasa: "",
|
||||||
|
orangtua: "",
|
||||||
|
lansia: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
const id = await stategrafikBerdasarkanUmur.create.create();
|
||||||
|
if (id) {
|
||||||
|
const idStr = String(id);
|
||||||
|
await stategrafikBerdasarkanUmur.findUnique.load(idStr);
|
||||||
|
if (stategrafikBerdasarkanUmur.findUnique.data) {
|
||||||
|
setDonutData([stategrafikBerdasarkanUmur.findUnique.data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resetForm();
|
||||||
|
router.push("/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur")
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Remaja"
|
||||||
|
type='number'
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.create.form.remaja}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.create.form.remaja = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Dewasa"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.create.form.dewasa}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.create.form.dewasa = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Orangtua"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.create.form.orangtua}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.create.form.orangtua = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Lansia"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah"
|
||||||
|
value={stategrafikBerdasarkanUmur.create.form.lansia}
|
||||||
|
onChange={(val) => {
|
||||||
|
stategrafikBerdasarkanUmur.create.form.lansia = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GrafikBerdasarakanUmurCreate;
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
'use client'
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Flex, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import JudulListTab from '../../../_com/jusulListTab';
|
||||||
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
|
|
||||||
|
function GrafikBerdasarakanUmur() {
|
||||||
|
const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
|
||||||
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
const [modalHapus, setModalHapus] = useState(false)
|
||||||
|
const [selectedId, setSelectedId] = useState<string | null>(null)
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
if (selectedId) {
|
||||||
|
await grafikBerdasarkanUmur.delete.byId(selectedId)
|
||||||
|
setModalHapus(false)
|
||||||
|
setSelectedId(null)
|
||||||
|
|
||||||
|
stategrafikBerdasarkanUmur.findMany.load()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
stategrafikBerdasarkanUmur.findMany.load()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (stategrafikBerdasarkanUmur.findMany.data) {
|
||||||
|
const totalRemaja = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.remaja || 0), 0);
|
||||||
|
const totalDewasa = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.dewasa || 0), 0);
|
||||||
|
const totalOrangtua = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.orangtua || 0), 0);
|
||||||
|
const totalLansia = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.lansia || 0), 0);
|
||||||
|
setDonutData([
|
||||||
|
{ name: 'remaja', value: totalRemaja, color: colors['blue-button'], key: 'remaja' },
|
||||||
|
{ name: 'dewasa', value: totalDewasa, color: '#D32711FF', key: 'dewasa' },
|
||||||
|
{ name: 'orangtua', value: totalOrangtua, color: '#B46B04FF', key: 'orangtua' },
|
||||||
|
{ name: 'lansia', value: totalLansia, color: '#038617FF', key: 'lansia' }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}, [stategrafikBerdasarkanUmur.findMany.data])
|
||||||
|
|
||||||
|
if (!stategrafikBerdasarkanUmur.findMany.data) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Skeleton h={500} />
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Stack gap={"xs"}>
|
||||||
|
<Paper bg={colors['white-1']} p={"md"}>
|
||||||
|
<JudulListTab
|
||||||
|
title='List Grafik Berdasarkan Umur Responden'
|
||||||
|
href='/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/create'
|
||||||
|
placeholder='pencarian'
|
||||||
|
searchIcon={<IconSearch size={16} />}
|
||||||
|
/>
|
||||||
|
<Table striped withTableBorder withRowBorders>
|
||||||
|
<TableThead>
|
||||||
|
<TableTr>
|
||||||
|
<TableTh>Remaja</TableTh>
|
||||||
|
<TableTh>Dewasa</TableTh>
|
||||||
|
<TableTh>Orangtua</TableTh>
|
||||||
|
<TableTh>Lansia</TableTh>
|
||||||
|
<TableTh>Edit</TableTh>
|
||||||
|
<TableTh>Delete</TableTh>
|
||||||
|
</TableTr>
|
||||||
|
</TableThead>
|
||||||
|
<TableTbody>
|
||||||
|
{stategrafikBerdasarkanUmur.findMany.data.length === 0 ? (
|
||||||
|
<TableTr>
|
||||||
|
<TableTd colSpan={6}>
|
||||||
|
<Text ta='center' c='dimmed'>Belum ada data grafik responden</Text>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
) : (
|
||||||
|
stategrafikBerdasarkanUmur.findMany.data.map((item) => (
|
||||||
|
<TableTr key={item.id}>
|
||||||
|
<TableTd>{item.remaja}</TableTd>
|
||||||
|
<TableTd>{item.dewasa}</TableTd>
|
||||||
|
<TableTd>{item.orangtua}</TableTd>
|
||||||
|
<TableTd>{item.lansia}</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button color='green' onClick={() => router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/${item.id}`)}>
|
||||||
|
<IconEdit size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button
|
||||||
|
color='red'
|
||||||
|
disabled={stategrafikBerdasarkanUmur.delete.loading}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedId(item.id)
|
||||||
|
setModalHapus(true)
|
||||||
|
}}>
|
||||||
|
<IconTrash size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableTbody>
|
||||||
|
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* Chart */}
|
||||||
|
<Box>
|
||||||
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
||||||
|
{mounted && donutData.length > 0 ? (<Box style={{ width: '100%', height: 'auto', minHeight: 200 }}>
|
||||||
|
<PieChart
|
||||||
|
width={800} height={300}
|
||||||
|
data={donutData}
|
||||||
|
>
|
||||||
|
<Pie
|
||||||
|
dataKey="value"
|
||||||
|
nameKey="name"
|
||||||
|
data={donutData}
|
||||||
|
cx={500}
|
||||||
|
cy={150}
|
||||||
|
innerRadius={60}
|
||||||
|
outerRadius={115}
|
||||||
|
label={true}
|
||||||
|
>
|
||||||
|
{donutData.map((entry, index) => (
|
||||||
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||||
|
))}
|
||||||
|
</Pie>
|
||||||
|
</PieChart>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||||
|
<Text>Remaja: {donutData.find((entry) => entry.name === 'remaja')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={'#D32711FF'} w={20} h={20} />
|
||||||
|
<Text>Dewasa: {donutData.find((entry) => entry.name === 'dewasa')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={'#B46B04FF'} w={20} h={20} />
|
||||||
|
<Text>Orangtua: {donutData.find((entry) => entry.name === 'orangtua')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Box bg={'#038617FF'} w={20} h={20} />
|
||||||
|
<Text>Lansia: {donutData.find((entry) => entry.name === 'lansia')?.value}</Text>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Text c='dimmed'>Belum ada data untuk ditampilkan dalam grafik</Text>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{/* Modal Konfirmasi Hapus */}
|
||||||
|
<ModalKonfirmasiHapus
|
||||||
|
opened={modalHapus}
|
||||||
|
onClose={() => setModalHapus(false)}
|
||||||
|
onConfirm={handleDelete}
|
||||||
|
text='Apakah anda yakin ingin menghapus grafik berdasarkan hasil responden ini?'
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GrafikBerdasarakanUmur;
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import grafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core';
|
||||||
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
import { useRouter, useParams } from 'next/navigation';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
|
function EditGrafikHasilKepuasan() {
|
||||||
|
const router = useRouter()
|
||||||
|
const params = useParams() as { id: string }
|
||||||
|
const grafikHasilKepuasan = useProxy(grafikHasilKepuasanMasyarakat)
|
||||||
|
|
||||||
|
const id = params.id
|
||||||
|
|
||||||
|
// Load data saat komponen mount
|
||||||
|
useEffect(() => {
|
||||||
|
if (id) {
|
||||||
|
grafikHasilKepuasan.findUnique.load(id).then(() => {
|
||||||
|
const data = grafikHasilKepuasan.findUnique.data
|
||||||
|
if (data) {
|
||||||
|
grafikHasilKepuasan.update.form = {
|
||||||
|
label: data.label || '',
|
||||||
|
kepuasan: data.kepuasan || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
// Set the ID before submitting
|
||||||
|
grafikHasilKepuasan.update.id = id;
|
||||||
|
await grafikHasilKepuasan.update.submit();
|
||||||
|
router.push('/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat')
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Edit Grafik Hasil Kepuasan Masyarakat</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Label"
|
||||||
|
placeholder="masukkan label"
|
||||||
|
value={grafikHasilKepuasan.update.form.label}
|
||||||
|
onChange={(val) => {
|
||||||
|
grafikHasilKepuasan.update.form.label = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Jumlah Kepuasan"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah kepuasan"
|
||||||
|
value={grafikHasilKepuasan.update.form.kepuasan}
|
||||||
|
onChange={(val) => {
|
||||||
|
grafikHasilKepuasan.update.form.kepuasan = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Simpan Perubahan
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditGrafikHasilKepuasan;
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import grafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, 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 GrafikHasilKepuasan() {
|
||||||
|
const router = useRouter()
|
||||||
|
const grafikHasilKepuasan = useProxy(grafikHasilKepuasanMasyarakat)
|
||||||
|
const [chartData, setChartData] = useState<any[]>([]);
|
||||||
|
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
grafikHasilKepuasan.create.form = {
|
||||||
|
...grafikHasilKepuasan.create.form,
|
||||||
|
label: "",
|
||||||
|
kepuasan: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
const id = await grafikHasilKepuasan.create.create();
|
||||||
|
if (id) {
|
||||||
|
// Ensure id is a string
|
||||||
|
const idStr = String(id);
|
||||||
|
await grafikHasilKepuasan.findUnique.load(idStr);
|
||||||
|
if (grafikHasilKepuasan.findUnique.data) {
|
||||||
|
setChartData([grafikHasilKepuasan.findUnique.data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resetForm();
|
||||||
|
router.push("/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat")
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
|
||||||
|
<Box mb={10}>
|
||||||
|
<Button variant="subtle" onClick={() => router.back()}>
|
||||||
|
<IconArrowBack size={20} />
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||||
|
<Stack>
|
||||||
|
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||||
|
<TextInput
|
||||||
|
label="Label"
|
||||||
|
placeholder="masukkan label"
|
||||||
|
value={grafikHasilKepuasan.create.form.label}
|
||||||
|
onChange={(val) => {
|
||||||
|
grafikHasilKepuasan.create.form.label = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Jumlah Kepuasan"
|
||||||
|
type="number"
|
||||||
|
placeholder="masukkan jumlah kepuasan"
|
||||||
|
value={grafikHasilKepuasan.create.form.kepuasan}
|
||||||
|
onChange={(val) => {
|
||||||
|
grafikHasilKepuasan.create.form.kepuasan = val.currentTarget.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mt={10}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default GrafikHasilKepuasan;
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
'use client'
|
||||||
|
import JudulListTab from '@/app/admin/(dashboard)/_com/jusulListTab';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Title } from '@mantine/core';
|
||||||
|
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
|
||||||
|
import { useSnapshot } from 'valtio';
|
||||||
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
|
import grafikHasilKepuasanMasyarakat from '../../../_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
|
||||||
|
|
||||||
|
|
||||||
|
function GrafikHasilKepuasanMasyarakat() {
|
||||||
|
type IKMGrafik = {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
kepuasan: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const stateGrafikHasilKepuasan = useSnapshot(grafikHasilKepuasanMasyarakat)
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
const [chartData, setChartData] = useState<IKMGrafik[]>([]);
|
||||||
|
const isTablet = useMediaQuery('(max-width: 1024px)')
|
||||||
|
const isMobile = useMediaQuery('(max-width: 768px)')
|
||||||
|
const [modalHapus, setModalHapus] = useState(false)
|
||||||
|
const [selectedId, setSelectedId] = useState<string | null>(null)
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
if (selectedId) {
|
||||||
|
stateGrafikHasilKepuasan.delete.byId(selectedId)
|
||||||
|
setModalHapus(false)
|
||||||
|
setSelectedId(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
setMounted(true)
|
||||||
|
stateGrafikHasilKepuasan.findMany.load()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (stateGrafikHasilKepuasan.findMany.data && stateGrafikHasilKepuasan.findMany.data.length > 0) {
|
||||||
|
setChartData([...stateGrafikHasilKepuasan.findMany.data.map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
label: item.label,
|
||||||
|
kepuasan: Number(item.kepuasan),
|
||||||
|
}))]);
|
||||||
|
}
|
||||||
|
}, [stateGrafikHasilKepuasan.findMany.data])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!stateGrafikHasilKepuasan.findMany.data) {
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
<Skeleton h={500} />
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Stack gap={"xs"}>
|
||||||
|
<Paper bg={colors['white-1']} p={'md'}>
|
||||||
|
<JudulListTab
|
||||||
|
title='List Grafik Hasil Kepuasan Masyarakat'
|
||||||
|
href='/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/create'
|
||||||
|
placeholder='pencarian'
|
||||||
|
searchIcon={<IconSearch size={16} />}
|
||||||
|
/>
|
||||||
|
<Table striped withTableBorder withRowBorders>
|
||||||
|
<TableThead>
|
||||||
|
<TableTr>
|
||||||
|
<TableTh>Label</TableTh>
|
||||||
|
<TableTh>Jumlah Kepuasan</TableTh>
|
||||||
|
<TableTh>Edit</TableTh>
|
||||||
|
<TableTh>Delete</TableTh>
|
||||||
|
</TableTr>
|
||||||
|
</TableThead>
|
||||||
|
<TableTbody>
|
||||||
|
{stateGrafikHasilKepuasan.findMany.data?.map((item) => (
|
||||||
|
<TableTr key={item.id}>
|
||||||
|
<TableTd>{item.label}</TableTd>
|
||||||
|
<TableTd>{item.kepuasan}</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button color='green' onClick={() => router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/${item.id}`)}>
|
||||||
|
<IconEdit size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button
|
||||||
|
color='red'
|
||||||
|
disabled={stateGrafikHasilKepuasan.delete.loading}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedId(item.id)
|
||||||
|
setModalHapus(true)
|
||||||
|
}}>
|
||||||
|
<IconTrash size={20} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))}
|
||||||
|
</TableTbody>
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* Chart */}
|
||||||
|
<Box style={{ width: '100%', minWidth: 300, height: 500, minHeight: 300 }}>
|
||||||
|
<Paper style={{ width: '100%', minWidth: 300, height: 500, minHeight: 300 }} bg={colors['white-1']} p={'md'}>
|
||||||
|
<Stack gap={"xs"}>
|
||||||
|
<Title pb={10} order={3}>Data Kepuasan Masyarakat</Title>
|
||||||
|
{mounted && chartData.length > 0 && (
|
||||||
|
<BarChart width={isMobile ? 300 : isTablet ? 300 : 300} height={380} data={chartData} >
|
||||||
|
<XAxis dataKey="label" />
|
||||||
|
<YAxis />
|
||||||
|
<Tooltip />
|
||||||
|
<Legend />
|
||||||
|
<Bar dataKey="kepuasan" fill={colors['blue-button']} name="Kepuasan" />
|
||||||
|
</BarChart>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{/* Modal Konfirmasi Hapus */}
|
||||||
|
<ModalKonfirmasiHapus
|
||||||
|
opened={modalHapus}
|
||||||
|
onClose={() => setModalHapus(false)}
|
||||||
|
onConfirm={handleDelete}
|
||||||
|
text='Apakah anda yakin ingin menghapus grafik hasil kepuasan masyarakat ini?'
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GrafikHasilKepuasanMasyarakat;
|
||||||
10
src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/layout.tsx
Normal file
10
src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/layout.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
'use client'
|
||||||
|
import LayoutTabs from "../_com/layoutTabs";
|
||||||
|
|
||||||
|
export default function Layout({children} : {children: React.ReactNode}) {
|
||||||
|
return (
|
||||||
|
<LayoutTabs>
|
||||||
|
{children}
|
||||||
|
</LayoutTabs>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
|
||||||
import React from 'react';
|
|
||||||
import colors from '@/con/colors';
|
|
||||||
import GrafikHasilKepuasan from './_ui/grafik_hasil_kepuasan_masyarakat/page';
|
|
||||||
import GrafikBerdasarkanJenisKelamin from './_ui/grafik_berdasarkan_jenis_kelamin_responden/page';
|
|
||||||
import GrafikBerdasarkanResponden from './_ui/grafik_berdasarkan_responden/page';
|
|
||||||
import GrafikBerdasarakanUmur from './_ui/grafik_berdasarkan_umur/page';
|
|
||||||
|
|
||||||
function Page() {
|
|
||||||
return (
|
|
||||||
<Stack >
|
|
||||||
<Title order={3}>Indeks Kepuasan Masyarakat (IKM) Desa Darmasaba</Title>
|
|
||||||
<Tabs color={colors['blue-button']} variant='pills' defaultValue={"Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik"}>
|
|
||||||
<TabsList p={"xs"} bg={"#BBC8E7FF"}>
|
|
||||||
<TabsTab value="Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik">
|
|
||||||
Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
|
|
||||||
</TabsTab>
|
|
||||||
<TabsTab value="Grafik Berdasarkan Jenis Kelamin Responden">
|
|
||||||
Grafik Berdasarkan Jenis Kelamin Responden
|
|
||||||
</TabsTab>
|
|
||||||
<TabsTab value="Grafik Berdasarkan Pilihan Responden">
|
|
||||||
Grafik Berdasarkan Pilihan Responden
|
|
||||||
</TabsTab>
|
|
||||||
<TabsTab value="Grafik Berdasarkan Umur Responden">
|
|
||||||
Grafik Berdasarkan Umur Responden
|
|
||||||
</TabsTab>
|
|
||||||
</TabsList>
|
|
||||||
|
|
||||||
<TabsPanel value="Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik">
|
|
||||||
<GrafikHasilKepuasan/>
|
|
||||||
</TabsPanel>
|
|
||||||
<TabsPanel value="Grafik Berdasarkan Jenis Kelamin Responden">
|
|
||||||
<GrafikBerdasarkanJenisKelamin/>
|
|
||||||
</TabsPanel>
|
|
||||||
<TabsPanel value="Grafik Berdasarkan Pilihan Responden">
|
|
||||||
<GrafikBerdasarkanResponden/>
|
|
||||||
</TabsPanel>
|
|
||||||
<TabsPanel value="Grafik Berdasarkan Umur Responden">
|
|
||||||
<GrafikBerdasarakanUmur/>
|
|
||||||
</TabsPanel>
|
|
||||||
</Tabs>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Page;
|
|
||||||
@@ -94,7 +94,7 @@ export const navBar = [
|
|||||||
{
|
{
|
||||||
id: "PPID_8",
|
id: "PPID_8",
|
||||||
name: "IKM Desa Darmasaba",
|
name: "IKM Desa Darmasaba",
|
||||||
path: "/admin/ppid/ikm-desa-darmasaba"
|
path: "/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat"
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import prisma from "@/lib/prisma";
|
import prisma from "@/lib/prisma";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { Context } from "vm";
|
import { Context } from "elysia";
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
|
|
||||||
const potensiDesaDelete = async (context: Context) => {
|
const potensiDesaDelete = async (context: Context) => {
|
||||||
|
|||||||
@@ -11,17 +11,20 @@ type FormCreate = Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
|
|||||||
export default async function grafikBerdasarkanJenisKelaminCreate(context: Context) {
|
export default async function grafikBerdasarkanJenisKelaminCreate(context: Context) {
|
||||||
const body = context.body as FormCreate;
|
const body = context.body as FormCreate;
|
||||||
|
|
||||||
await prisma.grafikBerdasarkanJenisKelamin.create({
|
const created = await prisma.grafikBerdasarkanJenisKelamin.create({
|
||||||
data: {
|
data: {
|
||||||
perempuan: body.perempuan,
|
perempuan: body.perempuan,
|
||||||
laki: body.laki,
|
laki: body.laki,
|
||||||
},
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
perempuan: true,
|
||||||
|
laki: true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: "Success create grafik berdasarkan jenis kelamin",
|
message: "Success create grafik berdasarkan jenis kelamin",
|
||||||
data: {
|
data: created,
|
||||||
...body,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { Context } from "elysia";
|
||||||
|
|
||||||
|
export default async function grafikBerdasarkanJenisKelaminDelete(context: Context) {
|
||||||
|
const {id} = context.params as {id: string}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const existingData = await prisma.grafikBerdasarkanJenisKelamin.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existingData) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.grafikBerdasarkanJenisKelamin.delete({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil dihapus",
|
||||||
|
data: {
|
||||||
|
id: id,
|
||||||
|
deleted: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: error instanceof Error ? error.message : "Unknown error",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
|
||||||
|
export default async function grafikBerdasarakanJenisKelaminFindById(
|
||||||
|
request: Request,
|
||||||
|
) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const pathSegments = url.pathname.split('/');
|
||||||
|
const id = pathSegments[pathSegments.length - 1];
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak boleh kosong",
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (typeof id !== 'string') {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak valid",
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await prisma.grafikBerdasarkanJenisKelamin.findUnique({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
}, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.json({
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil mengambil data berdasarkan ID",
|
||||||
|
data,
|
||||||
|
}, { status: 200 });
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Find by ID error:", e);
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
|
||||||
|
}, {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import Elysia, { t } from "elysia";
|
import Elysia, { t } from "elysia";
|
||||||
import grafikBerdasarkanJenisKelaminCreate from "./create";
|
import grafikBerdasarkanJenisKelaminCreate from "./create";
|
||||||
import grafikBerdasarkanJenisKelaminFindMany from "./find-many";
|
import grafikBerdasarkanJenisKelaminFindMany from "./find-many";
|
||||||
|
import grafikBerdasarakanJenisKelaminFindById from "./find-by-id";
|
||||||
|
import grafikBerdasarakanJenisKelaminUpdate from "./update";
|
||||||
|
import grafikBerdasarkanJenisKelaminDelete from "./del";
|
||||||
|
|
||||||
|
|
||||||
const GrafikBerdasarkanJenisKelamin = new Elysia({
|
const GrafikBerdasarkanJenisKelamin = new Elysia({
|
||||||
@@ -8,10 +11,28 @@ const GrafikBerdasarkanJenisKelamin = new Elysia({
|
|||||||
tags: ["PPID/IKM/grafikberdasarkanjeniskelamin"],
|
tags: ["PPID/IKM/grafikberdasarkanjeniskelamin"],
|
||||||
})
|
})
|
||||||
.get("/find-many", grafikBerdasarkanJenisKelaminFindMany)
|
.get("/find-many", grafikBerdasarkanJenisKelaminFindMany)
|
||||||
|
.get("/:id", async (context) => {
|
||||||
|
const response = await grafikBerdasarakanJenisKelaminFindById(new Request(context.request))
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.put("/:id", grafikBerdasarakanJenisKelaminUpdate, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
|
body: t.Object({
|
||||||
|
perempuan: t.String(),
|
||||||
|
laki: t.String(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
.post("/create", grafikBerdasarkanJenisKelaminCreate, {
|
.post("/create", grafikBerdasarkanJenisKelaminCreate, {
|
||||||
body: t.Object({
|
body: t.Object({
|
||||||
perempuan: t.String(),
|
perempuan: t.String(),
|
||||||
laki: t.String(),
|
laki: t.String(),
|
||||||
}),
|
}),
|
||||||
|
})
|
||||||
|
.delete("/del/:id", grafikBerdasarkanJenisKelaminDelete, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
export default GrafikBerdasarkanJenisKelamin;
|
export default GrafikBerdasarkanJenisKelamin;
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { Context } from "elysia";
|
||||||
|
|
||||||
|
export default async function grafikBerdasarakanJenisKelaminUpdate(
|
||||||
|
context: Context
|
||||||
|
) {
|
||||||
|
const id = context.params?.id;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Id tidak ditemukan",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {perempuan, laki} = context.body as {
|
||||||
|
perempuan: string;
|
||||||
|
laki: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = await prisma.grafikBerdasarkanJenisKelamin.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existing) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updated = await prisma.grafikBerdasarkanJenisKelamin.update({
|
||||||
|
where: {
|
||||||
|
id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
perempuan: perempuan,
|
||||||
|
laki: laki,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil diupdate",
|
||||||
|
data: updated,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,19 +13,24 @@ type FormCreate = Prisma.GrafikBerdasarkanUmurGetPayload<{
|
|||||||
export async function grafikBerdasarkanUmurCreate(context: Context) {
|
export async function grafikBerdasarkanUmurCreate(context: Context) {
|
||||||
const body = context.body as FormCreate;
|
const body = context.body as FormCreate;
|
||||||
|
|
||||||
await prisma.grafikBerdasarkanUmur.create({
|
const created = await prisma.grafikBerdasarkanUmur.create({
|
||||||
data: {
|
data: {
|
||||||
remaja: body.remaja,
|
remaja: body.remaja,
|
||||||
dewasa: body.dewasa,
|
dewasa: body.dewasa,
|
||||||
orangtua: body.orangtua,
|
orangtua: body.orangtua,
|
||||||
lansia: body.lansia,
|
lansia: body.lansia,
|
||||||
},
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
remaja: true,
|
||||||
|
dewasa: true,
|
||||||
|
orangtua: true,
|
||||||
|
lansia: true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: "Success create grafik berdasarkan umur",
|
message: "Success create grafik berdasarkan umur",
|
||||||
data: {
|
data: created,
|
||||||
...body,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import prisma from "@/lib/prisma"
|
||||||
|
import { Context } from "elysia"
|
||||||
|
|
||||||
|
export default async function grafikBerdasarkanUmurDelete(context: Context) {
|
||||||
|
const {id} = context.params as {id: string}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const existingData = await prisma.grafikBerdasarkanUmur.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existingData) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.grafikBerdasarkanUmur.delete({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil dihapus",
|
||||||
|
data: {
|
||||||
|
id: id,
|
||||||
|
deleted: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: error instanceof Error ? error.message : "Unknown error",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
|
||||||
|
export default async function grafikBerdasarakanUmurFindById(request: Request) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const pathSegments = url.pathname.split("/");
|
||||||
|
const id = pathSegments[pathSegments.length - 1];
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak boleh kosong",
|
||||||
|
},
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (typeof id !== "string") {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak valid",
|
||||||
|
},
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await prisma.grafikBerdasarkanUmur.findUnique({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
data: null,
|
||||||
|
}, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.json({
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil mengambil data berdasarkan ID",
|
||||||
|
data: data,
|
||||||
|
}, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching grafik berdasarkan umur:", error);
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: error instanceof Error ? error.message : "Unknown error",
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,42 @@
|
|||||||
import Elysia, { t } from "elysia";
|
import Elysia, { t } from "elysia";
|
||||||
import { grafikBerdasarkanUmurFindMany } from "./find-many";
|
import { grafikBerdasarkanUmurFindMany } from "./find-many";
|
||||||
import { grafikBerdasarkanUmurCreate } from "./create";
|
import { grafikBerdasarkanUmurCreate } from "./create";
|
||||||
|
import grafikBerdasarakanUmurUpdate from "./update";
|
||||||
|
import grafikBerdasarakanUmurFindById from "./find-by-id";
|
||||||
|
import grafikBerdasarkanUmurDelete from "./del";
|
||||||
|
|
||||||
const GrafikBerdasarkanUmur = new Elysia({
|
const GrafikBerdasarkanUmur = new Elysia({
|
||||||
prefix: "/grafikberdasarkanumur",
|
prefix: "/grafikberdasarkanumur",
|
||||||
tags: ["PPID/IKM/grafikberdasarkanumur"]
|
tags: ["PPID/IKM/grafikberdasarkanumur"],
|
||||||
})
|
})
|
||||||
.get("/find-many", grafikBerdasarkanUmurFindMany)
|
.get("/find-many", grafikBerdasarkanUmurFindMany)
|
||||||
.post("/create", grafikBerdasarkanUmurCreate, {
|
.post("/create", grafikBerdasarkanUmurCreate, {
|
||||||
body: t.Object({
|
body: t.Object({
|
||||||
remaja: t.String(),
|
remaja: t.String(),
|
||||||
dewasa: t.String(),
|
dewasa: t.String(),
|
||||||
orangtua: t.String(),
|
orangtua: t.String(),
|
||||||
lansia: t.String(),
|
lansia: t.String(),
|
||||||
}),
|
}),
|
||||||
});
|
})
|
||||||
|
.get("/:id", async (context) => {
|
||||||
|
const response = await grafikBerdasarakanUmurFindById(new Request(context.request))
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.put("/:id", grafikBerdasarakanUmurUpdate, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
|
body: t.Object({
|
||||||
|
remaja: t.String(),
|
||||||
|
dewasa: t.String(),
|
||||||
|
orangtua: t.String(),
|
||||||
|
lansia: t.String(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.delete("/del/:id", grafikBerdasarkanUmurDelete, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
export default GrafikBerdasarkanUmur;
|
export default GrafikBerdasarkanUmur;
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { Context } from "elysia";
|
||||||
|
|
||||||
|
export default async function grafikBerdasarakanUmurUpdate(context: Context) {
|
||||||
|
const id = context.params?.id;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Id tidak ditemukan",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {remaja, dewasa, orangtua, lansia} = context.body as {
|
||||||
|
remaja: string;
|
||||||
|
dewasa: string;
|
||||||
|
orangtua: string;
|
||||||
|
lansia: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = await prisma.grafikBerdasarkanUmur.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existing) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Grafik tidak ditemukan"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updated = await prisma.grafikBerdasarkanUmur.update({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
remaja: remaja,
|
||||||
|
dewasa: dewasa,
|
||||||
|
orangtua: orangtua,
|
||||||
|
lansia: lansia,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil diupdate",
|
||||||
|
data: updated,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,17 +11,20 @@ type FormCreate = Prisma.IndeksKepuasanMasyarakatGetPayload<{
|
|||||||
export default async function grafikHasilKepuasanMasyarakatCreate(context: Context) {
|
export default async function grafikHasilKepuasanMasyarakatCreate(context: Context) {
|
||||||
const body = context.body as FormCreate;
|
const body = context.body as FormCreate;
|
||||||
|
|
||||||
await prisma.indeksKepuasanMasyarakat.create({
|
const created = await prisma.indeksKepuasanMasyarakat.create({
|
||||||
data: {
|
data: {
|
||||||
label: body.label,
|
label: body.label,
|
||||||
kepuasan: body.kepuasan,
|
kepuasan: body.kepuasan,
|
||||||
},
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
label: true,
|
||||||
|
kepuasan: true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: "Success create grafik hasil kepuasan masyarakat",
|
message: "Success create grafik hasil kepuasan masyarakat",
|
||||||
data: {
|
data: created,
|
||||||
...body,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import prisma from "@/lib/prisma"
|
||||||
|
import { Context } from "elysia"
|
||||||
|
|
||||||
|
export default async function grafikHasilKepuasanMasyarakatDelete(context: Context) {
|
||||||
|
const {id} = context.params as {id: string}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const existingData = await prisma.indeksKepuasanMasyarakat.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existingData) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.indeksKepuasanMasyarakat.delete({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil dihapus",
|
||||||
|
data: {
|
||||||
|
id: id,
|
||||||
|
deleted: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: error instanceof Error ? error.message : "Unknown error",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
|
||||||
|
export default async function handler(request: Request) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const pathSegments = url.pathname.split('/');
|
||||||
|
const id = pathSegments[pathSegments.length - 1];
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak boleh kosong",
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (typeof id !== 'string') {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak valid",
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await prisma.indeksKepuasanMasyarakat.findUnique({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
}, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.json({
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil mengambil data berdasarkan ID",
|
||||||
|
data,
|
||||||
|
}, { status: 200 });
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Find by ID error:", e);
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
|
||||||
|
}, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,38 @@
|
|||||||
import Elysia, { t } from "elysia";
|
import Elysia, { t } from "elysia";
|
||||||
import grafikHasilKepuasanMasyarakatCreate from "./create";
|
import grafikHasilKepuasanMasyarakatCreate from "./create";
|
||||||
import grafikHasilKepuasanMasyarakatFindMany from "./find-many";
|
import grafikHasilKepuasanMasyarakatFindMany from "./find-many";
|
||||||
|
import grafikHasilKepuasanMasyarakatFindById from "./find-by-id";
|
||||||
|
import grafikHasilKepuasanMasyarakatUpdate from "./update";
|
||||||
|
import grafikHasilKepuasanMasyarakatDelete from "./del";
|
||||||
|
|
||||||
const GrafikHasilKepuasanMasyarakat = new Elysia({
|
const GrafikHasilKepuasanMasyarakat = new Elysia({
|
||||||
prefix: "/grafikhasilkepuasamanmasyarakat",
|
prefix: "/grafikhasilkepuasamanmasyarakat",
|
||||||
tags: ["PPID/IKM/grafikhasilkepuasanmasyarakat"],
|
tags: ["PPID/IKM/grafikhasilkepuasanmasyarakat"],
|
||||||
})
|
})
|
||||||
.get("/find-many", grafikHasilKepuasanMasyarakatFindMany)
|
.get("/find-many", grafikHasilKepuasanMasyarakatFindMany)
|
||||||
|
.get("/:id", async (context) => {
|
||||||
|
const response = await grafikHasilKepuasanMasyarakatFindById(new Request(context.request))
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.put("/:id", grafikHasilKepuasanMasyarakatUpdate, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
|
body: t.Object({
|
||||||
|
label: t.String(),
|
||||||
|
kepuasan: t.String(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
.post("/create", grafikHasilKepuasanMasyarakatCreate, {
|
.post("/create", grafikHasilKepuasanMasyarakatCreate, {
|
||||||
body: t.Object({
|
body: t.Object({
|
||||||
label: t.String(),
|
label: t.String(),
|
||||||
kepuasan: t.String(),
|
kepuasan: t.String(),
|
||||||
}),
|
}),
|
||||||
|
})
|
||||||
|
.delete("/del/:id", grafikHasilKepuasanMasyarakatDelete, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default GrafikHasilKepuasanMasyarakat;
|
export default GrafikHasilKepuasanMasyarakat;
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { Context } from "elysia";
|
||||||
|
|
||||||
|
export default async function grafikHasilKepuasanMasyarakatUpdate(context: Context) {
|
||||||
|
const id = context.params?.id;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Id tidak ditemukan",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {label, kepuasan} = context.body as {
|
||||||
|
label: string;
|
||||||
|
kepuasan: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = await prisma.indeksKepuasanMasyarakat.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existing) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updated = await prisma.indeksKepuasanMasyarakat.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
label,
|
||||||
|
kepuasan,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil diupdate",
|
||||||
|
data: updated,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,30 +2,16 @@ import prisma from "@/lib/prisma";
|
|||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { Context } from "elysia";
|
import { Context } from "elysia";
|
||||||
|
|
||||||
type FormCreate = Prisma.GrafikBerdasarkanRespondenGetPayload<{
|
|
||||||
select: {
|
|
||||||
sangatbaik: true;
|
|
||||||
baik: true;
|
|
||||||
kurangbaik: true;
|
|
||||||
tidakbaik: true
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
export default async function grafikRespondenCreate(context: Context) {
|
export default async function grafikRespondenCreate(context: Context) {
|
||||||
const body = context.body as FormCreate;
|
const body = context.body as Prisma.GrafikBerdasarkanRespondenCreateInput;
|
||||||
|
|
||||||
await prisma.grafikBerdasarkanResponden.create({
|
const created = await prisma.grafikBerdasarkanResponden.create({
|
||||||
data: {
|
data: body,
|
||||||
sangatbaik: body.sangatbaik,
|
|
||||||
baik: body.baik,
|
|
||||||
kurangbaik: body.kurangbaik,
|
|
||||||
tidakbaik: body.tidakbaik,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: "Success create grafik berdasarkan responden",
|
message: "Success create grafik berdasarkan responden",
|
||||||
data: {
|
data: created, // ini termasuk id
|
||||||
...body,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import prisma from "@/lib/prisma"
|
||||||
|
import { Context } from "elysia"
|
||||||
|
|
||||||
|
export default async function grafikRespondenDelete(context: Context) {
|
||||||
|
const { id } = context.params as { id: string }
|
||||||
|
|
||||||
|
try {
|
||||||
|
const existingData = await prisma.grafikBerdasarkanResponden.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existingData) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.grafikBerdasarkanResponden.delete({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil dihapus",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: error instanceof Error ? error.message : "Unknown error",
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
|
||||||
|
export default async function grafikRespondenFindById(request: Request) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const pathSegments = url.pathname.split('/');
|
||||||
|
const id = pathSegments[pathSegments.length - 1];
|
||||||
|
|
||||||
|
if (!id ) {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak boleh kosong",
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (typeof id !== 'string') {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak valid",
|
||||||
|
}, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await prisma.grafikBerdasarkanResponden.findUnique({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
}, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.json({
|
||||||
|
success: true,
|
||||||
|
message: "Berhasil mengambil data berdasarkan ID",
|
||||||
|
data,
|
||||||
|
}, { status: 200 });
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Find by ID error:", e);
|
||||||
|
return Response.json({
|
||||||
|
success: false,
|
||||||
|
message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
|
||||||
|
}, {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,29 @@
|
|||||||
import Elysia, { t } from "elysia";
|
import Elysia, { t } from "elysia";
|
||||||
import grafikRespondenCreate from "./create";
|
import grafikRespondenCreate from "./create";
|
||||||
import grafikRespondenFindMany from "./find-many";
|
import grafikRespondenFindMany from "./find-many";
|
||||||
|
import grafikRespondenFindById from "./find-by-id";
|
||||||
|
import grafikRespondenUpdate from "./update";
|
||||||
|
import grafikRespondenDelete from "./del";
|
||||||
|
|
||||||
const GrafikBerdasarkanResponden = new Elysia({
|
const GrafikBerdasarkanResponden = new Elysia({
|
||||||
prefix: "/grafikberdasarkanresponden",
|
prefix: "/grafikberdasarkanresponden",
|
||||||
tags: ["PPID/IKM/grafikberdasarkanresponden"]
|
tags: ["PPID/IKM/grafikberdasarkanresponden"]
|
||||||
})
|
})
|
||||||
|
.get("/:id", async (context) => {
|
||||||
|
const response = await grafikRespondenFindById(new Request(context.request))
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.put("/:id", grafikRespondenUpdate, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
|
body: t.Object({
|
||||||
|
sangatbaik: t.String(),
|
||||||
|
baik: t.String(),
|
||||||
|
kurangbaik: t.String(),
|
||||||
|
tidakbaik: t.String(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
.get("/find-many", grafikRespondenFindMany)
|
.get("/find-many", grafikRespondenFindMany)
|
||||||
.post("/create", grafikRespondenCreate, {
|
.post("/create", grafikRespondenCreate, {
|
||||||
body: t.Object({
|
body: t.Object({
|
||||||
@@ -15,6 +33,11 @@ const GrafikBerdasarkanResponden = new Elysia({
|
|||||||
tidakbaik: t.String(),
|
tidakbaik: t.String(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
.delete("/del/:id", grafikRespondenDelete, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
export default GrafikBerdasarkanResponden
|
export default GrafikBerdasarkanResponden
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import prisma from "@/lib/prisma";
|
||||||
|
import { Context } from "elysia";
|
||||||
|
|
||||||
|
export default async function grafikRespondenUpdate(context: Context) {
|
||||||
|
const id = context.params?.id;
|
||||||
|
|
||||||
|
if(!id) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "ID tidak ditemukan"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {sangatbaik, baik, kurangbaik, tidakbaik} = context.body as {
|
||||||
|
sangatbaik: string;
|
||||||
|
baik: string;
|
||||||
|
kurangbaik: string;
|
||||||
|
tidakbaik: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = await prisma.grafikBerdasarkanResponden.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!existing) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updated = await prisma.grafikBerdasarkanResponden.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
sangatbaik,
|
||||||
|
baik,
|
||||||
|
kurangbaik,
|
||||||
|
tidakbaik,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data berhasil diupdate",
|
||||||
|
data: updated,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import React, { useEffect, useState } from 'react';
|
import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
|
||||||
import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
|
|
||||||
import { Cell, Pie, PieChart } from 'recharts';
|
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import stateGrafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
|
|
||||||
|
|
||||||
function GrafikBerdasarkanJenisKelamin() {
|
function GrafikBerdasarkanJenisKelamin() {
|
||||||
const grafikBerdasarkanJenisKelamin = useProxy(stateGrafikBerdasarkanJenisKelamin.grafikBerdasarkanJenisKelamin)
|
const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
|
|
||||||
@@ -34,13 +34,13 @@ function GrafikBerdasarkanJenisKelamin() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
await grafikBerdasarkanJenisKelamin.findMany.load();
|
await stategrafikBerdasarkanJenisKelamin.findMany.load();
|
||||||
if (grafikBerdasarkanJenisKelamin.findMany.data) {
|
if (stategrafikBerdasarkanJenisKelamin.findMany.data) {
|
||||||
updateChartData(grafikBerdasarkanJenisKelamin.findMany.data);
|
updateChartData(stategrafikBerdasarkanJenisKelamin.findMany.data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(!grafikBerdasarkanJenisKelamin.findMany.data) return <Stack>
|
if(!stategrafikBerdasarkanJenisKelamin.findMany.data) return <Stack>
|
||||||
<Title pb={10} order={3}>Grafik Berdasarkan Jenis Kelamin Responden</Title>
|
<Title pb={10} order={3}>Grafik Berdasarkan Jenis Kelamin Responden</Title>
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} />
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import stateGrafikResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
|
import grafikBerdasarkanResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Stack, Title, Box, Center, Flex, Text, Skeleton } from '@mantine/core';
|
import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import React, { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { PieChart, Pie, Cell } from 'recharts';
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function GrafikBerdasarkanResponden() {
|
function GrafikBerdasarkanResponden() {
|
||||||
const grafikBerdasarkanResponden = useProxy(stateGrafikResponden.grafikBerdasarkanResponden)
|
const stategrafikBerdasarkanResponden = useProxy(grafikBerdasarkanResponden)
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
|
|
||||||
@@ -37,13 +37,13 @@ function GrafikBerdasarkanResponden() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
await grafikBerdasarkanResponden.findMany.load();
|
await stategrafikBerdasarkanResponden.findMany.load();
|
||||||
if (grafikBerdasarkanResponden.findMany.data) {
|
if (stategrafikBerdasarkanResponden.findMany.data) {
|
||||||
updateChartData(grafikBerdasarkanResponden.findMany.data);
|
updateChartData(stategrafikBerdasarkanResponden.findMany.data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!grafikBerdasarkanResponden.findMany.data) return <Stack>
|
if (!stategrafikBerdasarkanResponden.findMany.data) return <Stack>
|
||||||
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} />
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import stateGrafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
|
import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Stack, Title, Box, Center, Flex, Text, Skeleton } from '@mantine/core';
|
import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import React, { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { PieChart, Pie, Cell } from 'recharts';
|
import { Cell, Pie, PieChart } from 'recharts';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function GrafikBerdasarakanUmur() {
|
function GrafikBerdasarakanUmur() {
|
||||||
const grafikBerdasarkanUmur = useProxy(stateGrafikBerdasarkanUmur.grafikBerdasarkanUmur)
|
const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
|
||||||
const [donutData, setDonutData] = useState<any[]>([]);
|
const [donutData, setDonutData] = useState<any[]>([]);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
|
|
||||||
@@ -38,13 +38,13 @@ function GrafikBerdasarakanUmur() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
await grafikBerdasarkanUmur.findMany.load();
|
await stategrafikBerdasarkanUmur.findMany.load();
|
||||||
if (grafikBerdasarkanUmur.findMany.data) {
|
if (stategrafikBerdasarkanUmur.findMany.data) {
|
||||||
updateChartData(grafikBerdasarkanUmur.findMany.data);
|
updateChartData(stategrafikBerdasarkanUmur.findMany.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!grafikBerdasarkanUmur.findMany.data) return <Stack>
|
if(!stategrafikBerdasarkanUmur.findMany.data) return <Stack>
|
||||||
<Title pb={10} order={3}>Grafik Berdasarkan Umur Responden</Title>
|
<Title pb={10} order={3}>Grafik Berdasarkan Umur Responden</Title>
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} />
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import stateGrafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
|
import grafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Skeleton, Stack, Text, Title } from '@mantine/core';
|
import { Box, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
|
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
|
||||||
import React, { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { BarChart, Tooltip, XAxis, YAxis, Legend, Bar } from 'recharts';
|
import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function GrafikHasilKepuasan() {
|
function GrafikHasilKepuasan() {
|
||||||
const grafikHasilKepuasan = useProxy(stateGrafikHasilKepuasanMasyarakat.grafikHasilKepuasanMasyarakat)
|
const grafikHasilKepuasan = useProxy(grafikHasilKepuasanMasyarakat)
|
||||||
const [chartData, setChartData] = useState<any[]>([]);
|
const [chartData, setChartData] = useState<any[]>([]);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const isTablet = useMediaQuery('(max-width: 1024px)')
|
const isTablet = useMediaQuery('(max-width: 1024px)')
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const getCurrentTime = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isWorkingHours = (currentTime: string): boolean => {
|
const isWorkingHours = (currentTime: string): boolean => {
|
||||||
const [openTime, closeTime] = ['08:00', '11:00'];
|
const [openTime, closeTime] = ['08:00', '16:00'];
|
||||||
|
|
||||||
const compareTimes = (time1: string, time2: string) => {
|
const compareTimes = (time1: string, time2: string) => {
|
||||||
const [hour1, minute1] = time1.split(':').map(Number);
|
const [hour1, minute1] = time1.split(':').map(Number);
|
||||||
|
|||||||
Reference in New Issue
Block a user