diff --git a/src/components/DesaSetting.tsx b/src/components/DesaSetting.tsx
index fa9e3f3..d136937 100644
--- a/src/components/DesaSetting.tsx
+++ b/src/components/DesaSetting.tsx
@@ -1,16 +1,16 @@
import apiFetch from "@/lib/apiFetch";
import {
- ActionIcon,
- Button,
- Divider,
- Flex,
- Group,
- Input,
- Modal,
- Stack,
- Table,
- Title,
- Tooltip
+ ActionIcon,
+ Button,
+ Divider,
+ Flex,
+ Group,
+ Input,
+ Modal,
+ Stack,
+ Table,
+ Title,
+ Tooltip,
} from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconEdit } from "@tabler/icons-react";
@@ -19,139 +19,153 @@ import useSWR from "swr";
import notification from "./notificationGlobal";
export default function DesaSetting() {
- const [btnDisable, setBtnDisable] = useState(false);
- const [btnLoading, setBtnLoading] = useState(false);
- const [opened, { open, close }] = useDisclosure(false);
- const { data, mutate, isLoading } = useSWR("/", () =>
- apiFetch.api["configuration-desa"].list.get(),
- );
- const list = data?.data || [];
- const [dataEdit, setDataEdit] = useState({
- id: "",
- value: "",
- name: "",
- });
+ const [btnDisable, setBtnDisable] = useState(false);
+ const [btnLoading, setBtnLoading] = useState(false);
+ const [opened, { open, close }] = useDisclosure(false);
+ const { data, mutate, isLoading } = useSWR("/", () =>
+ apiFetch.api["configuration-desa"].list.get(),
+ );
+ const list = data?.data || [];
+ const [dataEdit, setDataEdit] = useState({
+ id: "",
+ value: "",
+ name: "",
+ });
- useShallowEffect(() => {
- mutate();
- }, []);
+ useShallowEffect(() => {
+ mutate();
+ }, []);
- async function handleEdit() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api["configuration-desa"].edit.post(dataEdit);
- if (res.status === 200) {
- mutate();
- close();
- notification({
- title: "Success",
- message: "Your settings have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to edit configuration",
- type: "error",
- })
- }
- } catch (error) {
- console.log(error);
- notification({
- title: "Error",
- message: "Failed to edit configuration",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
- }
- }
-
- function chooseEdit({ data }: { data: { id: string, value: string, name: string } }) {
- setDataEdit(data);
- open();
- }
-
- function onValidation({ kat, value }: { kat: 'value', value: string }) {
- if (value.length < 1) {
- setBtnDisable(true);
+ async function handleEdit() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api["configuration-desa"].edit.post(dataEdit);
+ if (res.status === 200) {
+ mutate();
+ close();
+ notification({
+ title: "Success",
+ message: "Your settings have been saved",
+ type: "success",
+ });
} else {
- setBtnDisable(false);
+ notification({
+ title: "Error",
+ message: "Failed to edit configuration",
+ type: "error",
+ });
}
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to edit configuration",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
- if (kat === 'value') {
- setDataEdit({ ...dataEdit, value: value });
- }
- }
+ function chooseEdit({
+ data,
+ }: {
+ data: { id: string; value: string; name: string };
+ }) {
+ setDataEdit(data);
+ open();
+ }
- useShallowEffect(() => {
- if (dataEdit.value.length > 0) {
- setBtnDisable(false);
- }
- }, [dataEdit.id]);
+ function onValidation({ kat, value }: { kat: "value"; value: string }) {
+ if (value.length < 1) {
+ setBtnDisable(true);
+ } else {
+ setBtnDisable(false);
+ }
- return (
- <>
-
-
-
- onValidation({ kat: 'value', value: e.target.value })} />
-
-
-
-
-
-
-
-
-
-
- Pengaturan Desa
-
-
-
-
-
-
-
- Nama
- Value
- Aksi
-
-
-
- {list?.map((v: any) => (
-
- {v.name}
- {v.value}
-
-
- chooseEdit({ data: v })}
- >
-
-
-
-
-
- ))}
-
-
-
-
- >
- );
+ if (kat === "value") {
+ setDataEdit({ ...dataEdit, value: value });
+ }
+ }
+
+ useShallowEffect(() => {
+ if (dataEdit.value.length > 0) {
+ setBtnDisable(false);
+ }
+ }, [dataEdit.id]);
+
+ return (
+ <>
+
+
+
+
+ onValidation({ kat: "value", value: e.target.value })
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+ Pengaturan Desa
+
+
+
+
+
+
+
+ Nama
+ Value
+ Aksi
+
+
+
+ {list?.map((v: any) => (
+
+ {v.name}
+ {v.value}
+
+
+ chooseEdit({ data: v })}
+ >
+
+
+
+
+
+ ))}
+
+
+
+
+ >
+ );
}
diff --git a/src/components/KategoriPelayananSurat.tsx b/src/components/KategoriPelayananSurat.tsx
index 94f90d7..1982bf8 100644
--- a/src/components/KategoriPelayananSurat.tsx
+++ b/src/components/KategoriPelayananSurat.tsx
@@ -1,20 +1,20 @@
import apiFetch from "@/lib/apiFetch";
import {
- ActionIcon,
- Button,
- Divider,
- Flex,
- Grid,
- Group,
- Input,
- List,
- Modal,
- Stack,
- Table,
- TagsInput,
- Text,
- Title,
- Tooltip
+ ActionIcon,
+ Button,
+ Divider,
+ Flex,
+ Grid,
+ Group,
+ Input,
+ List,
+ Modal,
+ Stack,
+ Table,
+ TagsInput,
+ Text,
+ Title,
+ Tooltip,
} from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconEdit, IconEye, IconPlus, IconTrash } from "@tabler/icons-react";
@@ -23,470 +23,590 @@ import useSWR from "swr";
import notification from "./notificationGlobal";
export default function KategoriPelayananSurat() {
- const [openedDelete, { open: openDelete, close: closeDelete }] = useDisclosure(false);
- const [openedDetail, { open: openDetail, close: closeDetail }] = useDisclosure(false);
- const [btnLoading, setBtnLoading] = useState(false);
- const [opened, { open, close }] = useDisclosure(false);
- const [openedTambah, { open: openTambah, close: closeTambah }] = useDisclosure(false);
- const [dataDelete, setDataDelete] = useState("")
- const { data, mutate, isLoading } = useSWR("/", () =>
- apiFetch.api.pelayanan.category.get(),
- );
- const list = data?.data || [];
- const [dataChoose, setDataChoose] = useState({
- id: "",
- name: "",
- syaratDokumen: [{ name: "", desc: "" }],
- dataText: [""],
- });
- const [dataTambah, setDataTambah] = useState({
- name: "",
- syaratDokumen: [{ name: "", desc: "" }],
- dataText: [""],
- })
+ const [openedDelete, { open: openDelete, close: closeDelete }] =
+ useDisclosure(false);
+ const [openedDetail, { open: openDetail, close: closeDetail }] =
+ useDisclosure(false);
+ const [btnLoading, setBtnLoading] = useState(false);
+ const [opened, { open, close }] = useDisclosure(false);
+ const [openedTambah, { open: openTambah, close: closeTambah }] =
+ useDisclosure(false);
+ const [dataDelete, setDataDelete] = useState("");
+ const { data, mutate, isLoading } = useSWR("/", () =>
+ apiFetch.api.pelayanan.category.get(),
+ );
+ const list = data?.data || [];
+ const [dataChoose, setDataChoose] = useState({
+ id: "",
+ name: "",
+ syaratDokumen: [{ name: "", desc: "" }],
+ dataText: [""],
+ });
+ const [dataTambah, setDataTambah] = useState({
+ name: "",
+ syaratDokumen: [{ name: "", desc: "" }],
+ dataText: [""],
+ });
- useShallowEffect(() => {
- mutate();
- }, []);
+ useShallowEffect(() => {
+ mutate();
+ }, []);
- async function handleCreate() {
- try {
- setBtnLoading(true);
- const cleanedDataText = dataTambah.dataText.map(v => v.trim()).filter(v => v !== "");
- const cleanedSyarat = dataTambah.syaratDokumen.map((item) => ({
- name: item.name.trim(),
- desc: item.desc.trim(),
- })).filter(item => item.name !== "" && item.desc !== "");
+ async function handleCreate() {
+ try {
+ setBtnLoading(true);
+ const cleanedDataText = dataTambah.dataText
+ .map((v) => v.trim())
+ .filter((v) => v !== "");
+ const cleanedSyarat = dataTambah.syaratDokumen
+ .map((item) => ({
+ name: item.name.trim(),
+ desc: item.desc.trim(),
+ }))
+ .filter((item) => item.name !== "" && item.desc !== "");
- const cleanedTambah = {
- name: dataTambah.name.trim(),
- syaratDokumen: cleanedSyarat,
- dataText: cleanedDataText,
- }
- const res = await apiFetch.api.pelayanan.category.create.post(cleanedTambah);
- if (res.status === 200) {
- mutate();
- closeTambah();
- setDataTambah({
- name: "",
- syaratDokumen: [{ name: "", desc: "" }],
- dataText: [""],
- });
- notification({
- title: "Success",
- message: "Your category have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to create category",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to create category",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
+ const cleanedTambah = {
+ name: dataTambah.name.trim(),
+ syaratDokumen: cleanedSyarat,
+ dataText: cleanedDataText,
+ };
+ const res =
+ await apiFetch.api.pelayanan.category.create.post(cleanedTambah);
+ if (res.status === 200) {
+ mutate();
+ closeTambah();
+ setDataTambah({
+ name: "",
+ syaratDokumen: [{ name: "", desc: "" }],
+ dataText: [""],
+ });
+ notification({
+ title: "Success",
+ message: "Your category have been saved",
+ type: "success",
+ });
+ } else {
+ notification({
+ title: "Error",
+ message: "Failed to create category",
+ type: "error",
+ });
}
- }
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to create category",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
- async function handleEdit() {
- try {
- setBtnLoading(true);
- const cleanedDataText = dataChoose.dataText.map(v => v.trim()).filter(v => v !== "");
- const cleanedSyarat = dataChoose.syaratDokumen.map((item) => ({
- name: item.name.trim(),
- desc: item.desc.trim(),
- })).filter(item => item.name !== "" && item.desc !== "");
+ async function handleEdit() {
+ try {
+ setBtnLoading(true);
+ const cleanedDataText = dataChoose.dataText
+ .map((v) => v.trim())
+ .filter((v) => v !== "");
+ const cleanedSyarat = dataChoose.syaratDokumen
+ .map((item) => ({
+ name: item.name.trim(),
+ desc: item.desc.trim(),
+ }))
+ .filter((item) => item.name !== "" && item.desc !== "");
- const res = await apiFetch.api.pelayanan.category.update.post({
- id: dataChoose.id,
- name: dataChoose.name,
- syaratDokumen: cleanedSyarat,
- dataText: cleanedDataText,
- });
- if (res.status === 200) {
- mutate();
- close();
- notification({
- title: "Success",
- message: "Your category have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to edit category",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to edit category",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
+ const res = await apiFetch.api.pelayanan.category.update.post({
+ id: dataChoose.id,
+ name: dataChoose.name,
+ syaratDokumen: cleanedSyarat,
+ dataText: cleanedDataText,
+ });
+ if (res.status === 200) {
+ mutate();
+ close();
+ notification({
+ title: "Success",
+ message: "Your category have been saved",
+ type: "success",
+ });
+ } else {
+ notification({
+ title: "Error",
+ message: "Failed to edit category",
+ type: "error",
+ });
}
- }
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to edit category",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
-
- async function handleDelete() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api.pelayanan.category.delete.post({ id: dataDelete });
- if (res.status === 200) {
- mutate();
- closeDelete();
- notification({
- title: "Success",
- message: "Your category have been deleted",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to delete category",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to delete category",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
+ async function handleDelete() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api.pelayanan.category.delete.post({
+ id: dataDelete,
+ });
+ if (res.status === 200) {
+ mutate();
+ closeDelete();
+ notification({
+ title: "Success",
+ message: "Your category have been deleted",
+ type: "success",
+ });
+ } else {
+ notification({
+ title: "Error",
+ message: "Failed to delete category",
+ type: "error",
+ });
}
- }
-
-
- function handleAddSyarat() {
- setDataChoose({
- ...dataChoose,
- syaratDokumen: [...dataChoose.syaratDokumen, { name: "", desc: "" }],
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to delete category",
+ type: "error",
});
- }
+ } finally {
+ setBtnLoading(false);
+ }
+ }
- function handleDeleteSyarat(index: number) {
- setDataChoose({
- ...dataChoose,
- syaratDokumen: dataChoose.syaratDokumen.filter((_, i) => i !== index),
- });
- }
+ function handleAddSyarat() {
+ setDataChoose({
+ ...dataChoose,
+ syaratDokumen: [...dataChoose.syaratDokumen, { name: "", desc: "" }],
+ });
+ }
- function handleEditSyarat(index: number, data: { name: string; desc: string }) {
- setDataChoose({
- ...dataChoose,
- syaratDokumen: dataChoose.syaratDokumen.map((v, i) => (i === index ? data : v)),
- });
- }
+ function handleDeleteSyarat(index: number) {
+ setDataChoose({
+ ...dataChoose,
+ syaratDokumen: dataChoose.syaratDokumen.filter((_, i) => i !== index),
+ });
+ }
+ function handleEditSyarat(
+ index: number,
+ data: { name: string; desc: string },
+ ) {
+ setDataChoose({
+ ...dataChoose,
+ syaratDokumen: dataChoose.syaratDokumen.map((v, i) =>
+ i === index ? data : v,
+ ),
+ });
+ }
- return (
- <>
- {/* Modal Edit */}
-
-
-
- setDataChoose({ ...dataChoose, name: e.target.value })} />
-
- setDataChoose({ ...dataChoose, dataText: value })}
- />
-
-
-
- Syarat dokumen
-
-
+ return (
+ <>
+ {/* Modal Edit */}
+
+
+
+
+ setDataChoose({ ...dataChoose, name: e.target.value })
+ }
+ />
+
+
+ setDataChoose({ ...dataChoose, dataText: value })
+ }
+ />
+
+
+
+ Syarat dokumen
+
+
+
+
+
+
+
+ {dataChoose?.syaratDokumen?.map((v: any, i: number) => (
+
+
+
+ {
+ handleDeleteSyarat(i);
+ }}
+ >
+
+
+
+
+
+
+
+ handleEditSyarat(i, {
+ name: e.target.value,
+ desc: v.desc,
+ })
+ }
+ />
+
+
+
+
+
+ handleEditSyarat(i, {
+ name: v.name,
+ desc: e.target.value,
+ })
+ }
+ />
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+ {/* Modal Tambah */}
+
+
+
+
+ setDataTambah({ ...dataTambah, name: e.target.value })
+ }
+ />
+
+
+ setDataTambah({ ...dataTambah, dataText: value })
+ }
+ />
+
+
+
+ Syarat dokumen
+
+
+ {
+ setDataTambah({
+ ...dataTambah,
+ syaratDokumen: [
+ ...dataTambah.syaratDokumen,
+ { name: "", desc: "" },
+ ],
+ });
+ }}
+ >
+
+
+
+
+ {dataTambah?.syaratDokumen?.map((v: any, index: number) => (
+
+
+
+ {
+ setDataTambah({
+ ...dataTambah,
+ syaratDokumen: dataTambah.syaratDokumen.filter(
+ (v: any, i: number) => i !== index,
+ ),
+ });
+ }}
+ disabled={dataTambah?.syaratDokumen?.length === 1}
+ >
+
+
+
+
+
+
+
+ setDataTambah({
+ ...dataTambah,
+ syaratDokumen: dataTambah.syaratDokumen.map(
+ (v: any, i: number) =>
+ i === index ? { ...v, name: e.target.value } : v,
+ ),
+ })
+ }
+ />
+
+
+
+
+
+ setDataTambah({
+ ...dataTambah,
+ syaratDokumen: dataTambah.syaratDokumen.map(
+ (v: any, i: number) =>
+ i === index ? { ...v, desc: e.target.value } : v,
+ ),
+ })
+ }
+ />
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+ {/* Modal Delete */}
+
+
+
+ Apakah anda yakin ingin menghapus kategori ini?
+
+
+
+
+
+
+
+
+ {/* Modal Detail */}
+
+
+
+
+ Kategori
+
+ {dataChoose?.name ?? ""}
+
+
+
+ Syarat Dokumen
+
+
+ {dataChoose?.syaratDokumen?.map((v: any) => (
+ {v.desc}
+ ))}
+
+
+
+
+ Data Pelengkap
+
+
+ {dataChoose?.dataText?.map((v: any) => (
+ {v}
+ ))}
+
+
+
+
+
+ {/* Table */}
+
+
+
+ Kategori Pelayanan Surat
+
+
+ }
+ onClick={openTambah}
+ >
+ Tambah
+
+
+
+
+
+
+
+
+ Kategori
+ Aksi
+
+
+
+ {list?.map((v: any) => (
+
+ {v.name}
+
+
+
{
+ setDataChoose(v);
+ openDetail();
+ }}
>
-
+
-
-
- {
- dataChoose?.syaratDokumen?.map((v: any, i: number) => (
-
-
-
- {
- handleDeleteSyarat(i)
- }}
- >
-
-
-
-
-
-
- handleEditSyarat(i, { name: e.target.value, desc: v.desc })} />
-
-
-
-
- handleEditSyarat(i, { name: v.name, desc: e.target.value })} />
-
-
-
- ))
- }
-
-
-
-
-
-
-
-
-
- {/* Modal Tambah */}
-
-
-
- setDataTambah({ ...dataTambah, name: e.target.value })} />
-
- setDataTambah({ ...dataTambah, dataText: value })}
- />
-
-
-
- Syarat dokumen
-
-
+
+
{
- setDataTambah({ ...dataTambah, syaratDokumen: [...dataTambah.syaratDokumen, { name: "", desc: "" }] })
- }}
+ variant="light"
+ size="sm"
+ style={{ boxShadow: "0 0 8px rgba(0,255,200,0.2)" }}
+ onClick={() => {
+ setDataChoose(v);
+ open();
+ }}
>
-
+
-
-
- {
-
- dataTambah?.syaratDokumen?.map((v: any, index: number) => (
-
-
-
- {
- setDataTambah({ ...dataTambah, syaratDokumen: dataTambah.syaratDokumen.filter((v: any, i: number) => i !== index) })
- }}
- disabled={dataTambah?.syaratDokumen?.length === 1}
- >
-
-
-
-
-
-
- setDataTambah({ ...dataTambah, syaratDokumen: dataTambah.syaratDokumen.map((v: any, i: number) => i === index ? { ...v, name: e.target.value } : v) })} />
-
-
-
-
- setDataTambah({ ...dataTambah, syaratDokumen: dataTambah.syaratDokumen.map((v: any, i: number) => i === index ? { ...v, desc: e.target.value } : v) })} />
-
-
-
- ))
- }
-
-
-
-
-
-
-
-
- {/* Modal Delete */}
-
-
-
- Apakah anda yakin ingin menghapus kategori ini?
-
-
-
-
-
-
-
-
- {/* Modal Detail */}
-
-
-
- Kategori
- {dataChoose?.name ?? ""}
-
-
- Syarat Dokumen
-
- {dataChoose?.syaratDokumen?.map((v: any) => (
- {v.desc}
- ))}
-
-
-
- Data Pelengkap
-
- {dataChoose?.dataText?.map((v: any) => (
- {v}
- ))}
-
-
-
-
-
-
- {/* Table */}
-
-
-
- Kategori Pelayanan Surat
-
-
- }
- onClick={openTambah}
- >
- Tambah
-
-
-
-
-
-
-
-
- Kategori
- Aksi
-
-
-
- {list?.map((v: any) => (
-
- {v.name}
-
-
-
- { setDataChoose(v); openDetail() }}
- >
-
-
-
-
- { setDataChoose(v); open(); }}
- >
-
-
-
-
- {
- setDataDelete(v.id)
- openDelete()
- }}
- >
-
-
-
-
-
-
- ))}
-
-
-
-
- >
- );
+
+
+ {
+ setDataDelete(v.id);
+ openDelete();
+ }}
+ >
+
+
+
+
+
+
+ ))}
+
+
+
+
+ >
+ );
}
diff --git a/src/components/KategoriPengaduan.tsx b/src/components/KategoriPengaduan.tsx
index 6fdbf00..fd2ea73 100644
--- a/src/components/KategoriPengaduan.tsx
+++ b/src/components/KategoriPengaduan.tsx
@@ -1,17 +1,17 @@
import apiFetch from "@/lib/apiFetch";
import {
- ActionIcon,
- Button,
- Divider,
- Flex,
- Group,
- Input,
- Modal,
- Stack,
- Table,
- Text,
- Title,
- Tooltip
+ ActionIcon,
+ Button,
+ Divider,
+ Flex,
+ Group,
+ Input,
+ Modal,
+ Stack,
+ Table,
+ Text,
+ Title,
+ Tooltip,
} from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react";
@@ -20,288 +20,336 @@ import useSWR from "swr";
import notification from "./notificationGlobal";
export default function KategoriPengaduan() {
- const [openedDelete, { open: openDelete, close: closeDelete }] = useDisclosure(false);
- const [btnDisable, setBtnDisable] = useState(true);
- const [btnLoading, setBtnLoading] = useState(false);
- const [opened, { open, close }] = useDisclosure(false);
- const [openedTambah, { open: openTambah, close: closeTambah }] = useDisclosure(false);
- const [dataDelete, setDataDelete] = useState("")
- const { data, mutate, isLoading } = useSWR("/", () =>
- apiFetch.api.pengaduan.category.get(),
- );
- const list = data?.data?.data || [];
- const [dataEdit, setDataEdit] = useState({
- id: "",
- name: "",
- });
- const [dataTambah, setDataTambah] = useState("")
+ const [openedDelete, { open: openDelete, close: closeDelete }] =
+ useDisclosure(false);
+ const [btnDisable, setBtnDisable] = useState(true);
+ const [btnLoading, setBtnLoading] = useState(false);
+ const [opened, { open, close }] = useDisclosure(false);
+ const [openedTambah, { open: openTambah, close: closeTambah }] =
+ useDisclosure(false);
+ const [dataDelete, setDataDelete] = useState("");
+ const { data, mutate, isLoading } = useSWR("/", () =>
+ apiFetch.api.pengaduan.category.get(),
+ );
+ const list = data?.data?.data || [];
+ const [dataEdit, setDataEdit] = useState({
+ id: "",
+ name: "",
+ });
+ const [dataTambah, setDataTambah] = useState("");
- useShallowEffect(() => {
- mutate();
- }, []);
+ useShallowEffect(() => {
+ mutate();
+ }, []);
- async function handleCreate() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api.pengaduan.category.create.post({ name: dataTambah });
- if (res.status === 200) {
- mutate();
- closeTambah();
- setDataTambah("");
- notification({
- title: "Success",
- message: "Your category have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to create category",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to create category",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
- }
- }
-
- async function handleEdit() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api.pengaduan.category.update.post(dataEdit);
- if (res.status === 200) {
- mutate();
- close();
- notification({
- title: "Success",
- message: "Your category have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to edit category",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to edit category",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
- }
- }
-
- function chooseEdit({ data }: { data: { id: string, value: string, name: string } }) {
- setDataEdit(data);
- open();
- }
-
- function onValidation({ kat, value, aksi }: { kat: 'name', value: string, aksi: 'edit' | 'tambah' }) {
- if (value.length < 1) {
- setBtnDisable(true);
+ async function handleCreate() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api.pengaduan.category.create.post({
+ name: dataTambah,
+ });
+ if (res.status === 200) {
+ mutate();
+ closeTambah();
+ setDataTambah("");
+ notification({
+ title: "Success",
+ message: "Your category have been saved",
+ type: "success",
+ });
} else {
- setBtnDisable(false);
+ notification({
+ title: "Error",
+ message: "Failed to create category",
+ type: "error",
+ });
}
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to create category",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
- if (kat === 'name') {
- if (aksi === 'edit') {
- setDataEdit({ ...dataEdit, name: value });
- } else {
- setDataTambah(value);
- }
+ async function handleEdit() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api.pengaduan.category.update.post(dataEdit);
+ if (res.status === 200) {
+ mutate();
+ close();
+ notification({
+ title: "Success",
+ message: "Your category have been saved",
+ type: "success",
+ });
+ } else {
+ notification({
+ title: "Error",
+ message: "Failed to edit category",
+ type: "error",
+ });
}
- }
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to edit category",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
- async function handleDelete() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api.pengaduan.category.delete.post({ id: dataDelete });
- if (res.status === 200) {
- mutate();
- closeDelete();
- notification({
- title: "Success",
- message: "Your category have been deleted",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to delete category",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to delete category",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
+ function chooseEdit({
+ data,
+ }: {
+ data: { id: string; value: string; name: string };
+ }) {
+ setDataEdit(data);
+ open();
+ }
+
+ function onValidation({
+ kat,
+ value,
+ aksi,
+ }: {
+ kat: "name";
+ value: string;
+ aksi: "edit" | "tambah";
+ }) {
+ if (value.length < 1) {
+ setBtnDisable(true);
+ } else {
+ setBtnDisable(false);
+ }
+
+ if (kat === "name") {
+ if (aksi === "edit") {
+ setDataEdit({ ...dataEdit, name: value });
+ } else {
+ setDataTambah(value);
}
- }
+ }
+ }
- useShallowEffect(() => {
- if (dataEdit.name.length > 0) {
- setBtnDisable(false);
+ async function handleDelete() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api.pengaduan.category.delete.post({
+ id: dataDelete,
+ });
+ if (res.status === 200) {
+ mutate();
+ closeDelete();
+ notification({
+ title: "Success",
+ message: "Your category have been deleted",
+ type: "success",
+ });
+ } else {
+ notification({
+ title: "Error",
+ message: "Failed to delete category",
+ type: "error",
+ });
}
- }, [dataEdit.id]);
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to delete category",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
- useShallowEffect(() => {
- if (dataTambah.length > 0) {
- setBtnDisable(false);
- }
- }, [dataTambah]);
+ useShallowEffect(() => {
+ if (dataEdit.name.length > 0) {
+ setBtnDisable(false);
+ }
+ }, [dataEdit.id]);
- return (
- <>
- {/* Modal Edit */}
-
-
-
- onValidation({ kat: 'name', value: e.target.value, aksi: 'edit' })} />
-
-
-
-
-
-
-
+ useShallowEffect(() => {
+ if (dataTambah.length > 0) {
+ setBtnDisable(false);
+ }
+ }, [dataTambah]);
- {/* Modal Tambah */}
-
-
-
- onValidation({ kat: 'name', value: e.target.value, aksi: 'tambah' })} />
-
-
-
-
-
-
-
+ return (
+ <>
+ {/* Modal Edit */}
+
+
+
+
+ onValidation({
+ kat: "name",
+ value: e.target.value,
+ aksi: "edit",
+ })
+ }
+ />
+
+
+
+
+
+
+
+ {/* Modal Tambah */}
+
+
+
+
+ onValidation({
+ kat: "name",
+ value: e.target.value,
+ aksi: "tambah",
+ })
+ }
+ />
+
+
+
+
+
+
+
- {/* Modal Delete */}
-
-
-
- Apakah anda yakin ingin menghapus kategori ini?
-
-
-
-
-
-
-
+ {/* Modal Delete */}
+
+
+
+ Apakah anda yakin ingin menghapus kategori ini?
+
+
+
+
+
+
+
-
-
-
-
-
- Kategori Pengaduan
-
-
- }
- onClick={openTambah}
- >
- Tambah
-
-
-
-
-
-
-
-
- Kategori
- Aksi
-
-
-
- {list?.map((v: any) => (
-
- {v.name}
-
-
-
- chooseEdit({ data: v })}
- >
-
-
-
-
- {
- setDataDelete(v.id)
- openDelete()
- }}
- >
-
-
-
-
-
-
- ))}
-
-
-
-
- >
- );
+
+
+
+ Kategori Pengaduan
+
+
+ }
+ onClick={openTambah}
+ >
+ Tambah
+
+
+
+
+
+
+
+
+ Kategori
+ Aksi
+
+
+
+ {list?.map((v: any) => (
+
+ {v.name}
+
+
+
+ chooseEdit({ data: v })}
+ >
+
+
+
+
+ {
+ setDataDelete(v.id);
+ openDelete();
+ }}
+ >
+
+
+
+
+
+
+ ))}
+
+
+
+
+ >
+ );
}
diff --git a/src/components/ProfileUser.tsx b/src/components/ProfileUser.tsx
index 31b8d45..d622062 100644
--- a/src/components/ProfileUser.tsx
+++ b/src/components/ProfileUser.tsx
@@ -1,190 +1,246 @@
import apiFetch from "@/lib/apiFetch";
-import { Button, Divider, Flex, Group, Input, Modal, Stack, Title } from "@mantine/core";
+import {
+ Button,
+ Divider,
+ Flex,
+ Group,
+ Input,
+ Modal,
+ Stack,
+ Title,
+} from "@mantine/core";
import { useEffect, useState } from "react";
import notification from "./notificationGlobal";
export default function ProfileUser() {
- const [opened, setOpened] = useState(false);
- const [openedPassword, setOpenedPassword] = useState(false);
- const [pwdBaru, setPwdBaru] = useState("");
- const [host, setHost] = useState({
- id: "",
- name: "",
- phone: "",
- roleId: "",
- email: "",
- });
+ const [opened, setOpened] = useState(false);
+ const [openedPassword, setOpenedPassword] = useState(false);
+ const [pwdBaru, setPwdBaru] = useState("");
+ const [host, setHost] = useState({
+ id: "",
+ name: "",
+ phone: "",
+ roleId: "",
+ email: "",
+ });
- const [error, setError] = useState({
- name: false,
- email: false,
- phone: false,
- });
+ const [error, setError] = useState({
+ name: false,
+ email: false,
+ phone: false,
+ });
- useEffect(() => {
- async function fetchHost() {
- const { data } = await apiFetch.api.user.find.get();
- setHost({
- id: data?.user?.id ?? "",
- name: data?.user?.name ?? "",
- phone: data?.user?.phone ?? "",
- roleId: data?.user?.roleId ?? "",
- email: data?.user?.email ?? "",
- });
- }
- fetchHost();
- }, []);
+ useEffect(() => {
+ async function fetchHost() {
+ const { data } = await apiFetch.api.user.find.get();
+ setHost({
+ id: data?.user?.id ?? "",
+ name: data?.user?.name ?? "",
+ phone: data?.user?.phone ?? "",
+ roleId: data?.user?.roleId ?? "",
+ email: data?.user?.email ?? "",
+ });
+ }
+ fetchHost();
+ }, []);
+ function onValidation({
+ kat,
+ value,
+ }: {
+ kat: "name" | "email" | "phone";
+ value: string;
+ }) {
+ if (value.length < 1) {
+ setError({ ...error, [kat]: true });
+ } else {
+ setError({ ...error, [kat]: false });
+ }
- function onValidation({ kat, value }: { kat: 'name' | 'email' | 'phone', value: string, }) {
- if (value.length < 1) {
- setError({ ...error, [kat]: true });
+ setHost({ ...host, [kat]: value });
+ }
+
+ async function handleUpdate() {
+ try {
+ const res = await apiFetch.api.user.update.post(host);
+ if (res.status === 200) {
+ setOpened(false);
+ notification({
+ title: "Success",
+ message: "Your profile have been saved",
+ type: "success",
+ });
} else {
- setError({ ...error, [kat]: false });
+ notification({
+ title: "Error",
+ message: "Failed to update profile",
+ type: "error",
+ });
}
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to update profile",
+ type: "error",
+ });
+ }
+ }
- setHost({ ...host, [kat]: value });
- }
-
- async function handleUpdate() {
- try {
- const res = await apiFetch.api.user.update.post(host);
- if (res.status === 200) {
- setOpened(false);
- notification({
- title: "Success",
- message: "Your profile have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to update profile",
- type: "error",
- })
- }
- } catch (error) {
- console.log(error);
- notification({
- title: "Error",
- message: "Failed to update profile",
- type: "error",
- })
+ async function handleUpdatePassword() {
+ try {
+ const res = await apiFetch.api.user["update-password"].post({
+ password: pwdBaru,
+ id: host.id,
+ });
+ if (res.status === 200) {
+ setPwdBaru("");
+ setOpenedPassword(false);
+ notification({
+ title: "Success",
+ message: "Your password have been saved",
+ type: "success",
+ });
+ } else {
+ notification({
+ title: "Error",
+ message: "Failed to update password",
+ type: "error",
+ });
}
- }
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to update password",
+ type: "error",
+ });
+ }
+ }
- async function handleUpdatePassword() {
- try {
- const res = await apiFetch.api.user["update-password"].post({ password: pwdBaru, id: host.id });
- if (res.status === 200) {
- setPwdBaru("");
- setOpenedPassword(false);
- notification({
- title: "Success",
- message: "Your password have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to update password",
- type: "error",
- })
- }
- } catch (error) {
- console.log(error);
- notification({
- title: "Error",
- message: "Failed to update password",
- type: "error",
- })
- }
- }
+ return (
+ <>
+
+
+
+ Profile Pengguna
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setOpened(false)}
+ title={"Edit Profile"}
+ size={"lg"}
+ overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
+ >
+
+
+
+ onValidation({ kat: "name", value: e.target.value })
+ }
+ />
+
+
+
+ onValidation({ kat: "phone", value: e.target.value })
+ }
+ />
+
+
+
+ onValidation({ kat: "email", value: e.target.value })
+ }
+ />
+
+
+
+
+
+
+
-
- return (
- <>
-
-
-
- Profile Pengguna
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setOpened(false)}
- title={"Edit Profile"}
-
- size={"lg"}
- overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
- >
-
-
- onValidation({ kat: 'name', value: e.target.value })} />
-
-
- onValidation({ kat: 'phone', value: e.target.value })} />
-
-
- onValidation({ kat: 'email', value: e.target.value })} />
-
-
-
-
-
-
-
-
- setOpenedPassword(false)}
- title={"Ubah Password"}
- overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
- >
-
-
- setPwdBaru(e.target.value)} />
-
-
-
-
-
-
-
- >
- )
-}
\ No newline at end of file
+ setOpenedPassword(false)}
+ title={"Ubah Password"}
+ overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
+ >
+
+
+ setPwdBaru(e.target.value)}
+ />
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/components/UserSetting.tsx b/src/components/UserSetting.tsx
index 0dd1fd9..1861a15 100644
--- a/src/components/UserSetting.tsx
+++ b/src/components/UserSetting.tsx
@@ -1,18 +1,18 @@
import apiFetch from "@/lib/apiFetch";
import {
- ActionIcon,
- Button,
- Divider,
- Flex,
- Group,
- Input,
- Modal,
- Select,
- Stack,
- Table,
- Text,
- Title,
- Tooltip
+ ActionIcon,
+ Button,
+ Divider,
+ Flex,
+ Group,
+ Input,
+ Modal,
+ Select,
+ Stack,
+ Table,
+ Text,
+ Title,
+ Tooltip,
} from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react";
@@ -21,345 +21,446 @@ import useSWR from "swr";
import notification from "./notificationGlobal";
export default function UserSetting() {
- const [btnDisable, setBtnDisable] = useState(true);
- const [btnLoading, setBtnLoading] = useState(false);
- const [opened, { open, close }] = useDisclosure(false);
- const [openedDelete, { open: openDelete, close: closeDelete }] = useDisclosure(false);
- const [dataDelete, setDataDelete] = useState("")
- const { data: dataRole, mutate: mutateRole, isLoading: isLoadingRole } = useSWR("user-role", () =>
- apiFetch.api.user.role.get(),
- );
- const [openedTambah, { open: openTambah, close: closeTambah }] = useDisclosure(false);
- const { data, mutate, isLoading } = useSWR("user-list", () =>
- apiFetch.api.user.list.get(),
- );
- const list = data?.data || [];
- const listRole = dataRole?.data || [];
- const [dataEdit, setDataEdit] = useState({
- id: "",
- name: "",
- phone: "",
- email: "",
- roleId: "",
- });
- const [dataTambah, setDataTambah] = useState({
- name: "",
- email: "",
- roleId: "",
- password: "",
- phone: "",
- })
- const [error, setError] = useState({
- name: false,
- email: false,
- roleId: false,
- password: false,
- phone: false,
- })
+ const [btnDisable, setBtnDisable] = useState(true);
+ const [btnLoading, setBtnLoading] = useState(false);
+ const [opened, { open, close }] = useDisclosure(false);
+ const [openedDelete, { open: openDelete, close: closeDelete }] =
+ useDisclosure(false);
+ const [dataDelete, setDataDelete] = useState("");
+ const {
+ data: dataRole,
+ mutate: mutateRole,
+ isLoading: isLoadingRole,
+ } = useSWR("user-role", () => apiFetch.api.user.role.get());
+ const [openedTambah, { open: openTambah, close: closeTambah }] =
+ useDisclosure(false);
+ const { data, mutate, isLoading } = useSWR("user-list", () =>
+ apiFetch.api.user.list.get(),
+ );
+ const list = data?.data || [];
+ const listRole = dataRole?.data || [];
+ const [dataEdit, setDataEdit] = useState({
+ id: "",
+ name: "",
+ phone: "",
+ email: "",
+ roleId: "",
+ });
+ const [dataTambah, setDataTambah] = useState({
+ name: "",
+ email: "",
+ roleId: "",
+ password: "",
+ phone: "",
+ });
+ const [error, setError] = useState({
+ name: false,
+ email: false,
+ roleId: false,
+ password: false,
+ phone: false,
+ });
- useShallowEffect(() => {
- mutate();
- }, []);
+ useShallowEffect(() => {
+ mutate();
+ }, []);
- async function handleCreate() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api.user.create.post(dataTambah);
- if (res.status === 200) {
- mutate();
- closeTambah();
- setDataTambah({
- name: "",
- email: "",
- roleId: "",
- password: "",
- phone: "",
- });
- notification({
- title: "Success",
- message: "Your user have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to create user ",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to create user",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
- }
- }
-
- async function handleEdit() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api.pengaduan.category.update.post(dataEdit);
- if (res.status === 200) {
- mutate();
- close();
- notification({
- title: "Success",
- message: "Your category have been saved",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to edit category",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to edit category",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
- }
- }
-
- async function handleDelete() {
- try {
- setBtnLoading(true);
- const res = await apiFetch.api.user.delete.post({ id: dataDelete });
- if (res.status === 200) {
- mutate();
- closeDelete();
- notification({
- title: "Success",
- message: "Your user have been deleted",
- type: "success",
- })
- } else {
- notification({
- title: "Error",
- message: "Failed to delete user",
- type: "error",
- })
- }
- } catch (error) {
- console.error(error);
- notification({
- title: "Error",
- message: "Failed to delete user",
- type: "error",
- })
- } finally {
- setBtnLoading(false);
- }
- }
-
- function chooseEdit({ data }: { data: { id: string, name: string, phone: string, email: string, roleId: string } }) {
- setDataEdit(data);
- open();
- }
-
- function onValidation({ kat, value, aksi }: { kat: 'name' | 'email' | 'roleId' | 'password' | 'phone', value: string | null, aksi: 'edit' | 'tambah' }) {
- if (value == null || value.length < 1) {
- setBtnDisable(true);
- setError({ ...error, [kat]: true });
+ async function handleCreate() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api.user.create.post(dataTambah);
+ if (res.status === 200) {
+ mutate();
+ closeTambah();
+ setDataTambah({
+ name: "",
+ email: "",
+ roleId: "",
+ password: "",
+ phone: "",
+ });
+ notification({
+ title: "Success",
+ message: "Your user have been saved",
+ type: "success",
+ });
} else {
- setBtnDisable(false);
- setError({ ...error, [kat]: false });
+ notification({
+ title: "Error",
+ message: "Failed to create user ",
+ type: "error",
+ });
}
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to create user",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
-
- if (aksi === 'edit') {
- setDataEdit({ ...dataEdit, [kat]: value });
+ async function handleEdit() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api.pengaduan.category.update.post(dataEdit);
+ if (res.status === 200) {
+ mutate();
+ close();
+ notification({
+ title: "Success",
+ message: "Your category have been saved",
+ type: "success",
+ });
} else {
- setDataTambah({ ...dataTambah, [kat]: value });
+ notification({
+ title: "Error",
+ message: "Failed to edit category",
+ type: "error",
+ });
}
- }
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to edit category",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
- useShallowEffect(() => {
- if (dataEdit.name.length > 0) {
- setBtnDisable(false);
+ async function handleDelete() {
+ try {
+ setBtnLoading(true);
+ const res = await apiFetch.api.user.delete.post({ id: dataDelete });
+ if (res.status === 200) {
+ mutate();
+ closeDelete();
+ notification({
+ title: "Success",
+ message: "Your user have been deleted",
+ type: "success",
+ });
+ } else {
+ notification({
+ title: "Error",
+ message: "Failed to delete user",
+ type: "error",
+ });
}
- }, [dataEdit.id]);
+ } catch (error) {
+ console.error(error);
+ notification({
+ title: "Error",
+ message: "Failed to delete user",
+ type: "error",
+ });
+ } finally {
+ setBtnLoading(false);
+ }
+ }
+ function chooseEdit({
+ data,
+ }: {
+ data: {
+ id: string;
+ name: string;
+ phone: string;
+ email: string;
+ roleId: string;
+ };
+ }) {
+ setDataEdit(data);
+ open();
+ }
- return (
- <>
- {/* Modal Edit */}
-
-
-
- onValidation({ kat: 'name', value: e.target.value, aksi: 'edit' })} />
-
-
-
-
-
-
-
+ function onValidation({
+ kat,
+ value,
+ aksi,
+ }: {
+ kat: "name" | "email" | "roleId" | "password" | "phone";
+ value: string | null;
+ aksi: "edit" | "tambah";
+ }) {
+ if (value == null || value.length < 1) {
+ setBtnDisable(true);
+ setError({ ...error, [kat]: true });
+ } else {
+ setBtnDisable(false);
+ setError({ ...error, [kat]: false });
+ }
- {/* Modal Tambah */}
-
-
-
- onValidation({ kat: 'name', value: e.target.value, aksi: 'tambah' })} />
-
-
-
+ useShallowEffect(() => {
+ if (dataEdit.name.length > 0) {
+ setBtnDisable(false);
+ }
+ }, [dataEdit.id]);
+ return (
+ <>
+ {/* Modal Edit */}
+
+
+
+
+ onValidation({
+ kat: "name",
+ value: e.target.value,
+ aksi: "edit",
+ })
+ }
+ />
+
+
+
+
+
+
+
- {/* Modal Delete */}
-
-
-
- Apakah anda yakin ingin menghapus user ini?
-
-
-
-
-
-
-
+ {/* Modal Tambah */}
+
+
+
+
+ onValidation({
+ kat: "name",
+ value: e.target.value,
+ aksi: "tambah",
+ })
+ }
+ />
+
+
+
-
-
-
- Daftar User
-
-
- }
- onClick={openTambah}
- >
- Tambah
-
-
-
-
-
-
-
-
- Nama
- Telepon
- Email
- Role
- Aksi
-
-
-
- {
- list.length > 0 ? (
- list?.map((v: any) => (
-
- {v.name}
- {v.phone}
- {v.email}
- {v.roleId}
-
-
-
- chooseEdit({ data: v })}
- >
-
-
-
-
- {
- setDataDelete(v.id)
- openDelete()
- }}
- >
-
-
-
-
-
-
- ))
- ) : (
-
-
- Data User Tidak Ditemukan
-
-
- )
- }
-
-
-
-
- >
- );
+ {/* Modal Delete */}
+
+
+
+ Apakah anda yakin ingin menghapus user ini?
+
+
+
+
+
+
+
+
+
+
+
+ Daftar User
+
+
+ }
+ onClick={openTambah}
+ >
+ Tambah
+
+
+
+
+
+
+
+
+ Nama
+ Telepon
+ Email
+ Role
+ Aksi
+
+
+
+ {list.length > 0 ? (
+ list?.map((v: any) => (
+
+ {v.name}
+ {v.phone}
+ {v.email}
+ {v.roleId}
+
+
+
+ chooseEdit({ data: v })}
+ >
+
+
+
+
+ {
+ setDataDelete(v.id);
+ openDelete();
+ }}
+ >
+
+
+
+
+
+
+ ))
+ ) : (
+
+
+ Data User Tidak Ditemukan
+
+
+ )}
+
+
+
+
+ >
+ );
}
diff --git a/src/index.tsx b/src/index.tsx
index 202417e..fc83f18 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -7,6 +7,7 @@ import { apiAuth } from "./server/middlewares/apiAuth";
import AduanRoute from "./server/routes/aduan_route";
import ApiKeyRoute from "./server/routes/apikey_route";
import Auth from "./server/routes/auth_route";
+import ConfigurationDesaRoute from "./server/routes/configuration_desa_route";
import CredentialRoute from "./server/routes/credential_route";
import DarmasabaRoute from "./server/routes/darmasaba_route";
import LayananRoute from "./server/routes/layanan_route";
@@ -15,7 +16,7 @@ import PelayananRoute from "./server/routes/pelayanan_surat_route";
import PengaduanRoute from "./server/routes/pengaduan_route";
import TestRoute from "./server/routes/test";
import UserRoute from "./server/routes/user_route";
-import ConfigurationDesaRoute from "./server/routes/configuration_desa_route";
+import WargaRoute from "./server/routes/warga_route";
const Docs = new Elysia({
tags: ["docs"],
@@ -32,6 +33,7 @@ const Api = new Elysia({
.use(PengaduanRoute)
.use(PelayananRoute)
.use(ConfigurationDesaRoute)
+ .use(WargaRoute)
.use(TestRoute)
.use(apiAuth)
.use(ApiKeyRoute)
diff --git a/src/pages/scr/dashboard/pelayanan-surat/list_pelayanan_page.tsx b/src/pages/scr/dashboard/pelayanan-surat/list_pelayanan_page.tsx
index 0a6d2bb..c23c3b1 100644
--- a/src/pages/scr/dashboard/pelayanan-surat/list_pelayanan_page.tsx
+++ b/src/pages/scr/dashboard/pelayanan-surat/list_pelayanan_page.tsx
@@ -172,7 +172,7 @@ function ListPelayananSurat({ status }: { status: StatusKey }) {
}
/>
- {list.length === 0 ? (
+ {list?.length === 0 ? (
@@ -182,7 +182,7 @@ function ListPelayananSurat({ status }: { status: StatusKey }) {
) : (
- list.map((v: any) => (
+ list?.map((v: any) => (
) : (
- list.map((v: any) => (
+ list?.map((v: any) => (
);
-}
\ No newline at end of file
+}
diff --git a/src/pages/scr/dashboard/warga/detail_warga_page.tsx b/src/pages/scr/dashboard/warga/detail_warga_page.tsx
index a4a3d04..57c6f67 100644
--- a/src/pages/scr/dashboard/warga/detail_warga_page.tsx
+++ b/src/pages/scr/dashboard/warga/detail_warga_page.tsx
@@ -2,62 +2,66 @@ import apiFetch from "@/lib/apiFetch";
import {
Avatar,
Box,
+ Button,
Card,
Container,
Divider,
Flex,
Grid,
Group,
+ LoadingOverlay,
Stack,
Table,
Text,
Title,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
-import { IconMail, IconMapPin, IconPhone } from "@tabler/icons-react";
-import { useState } from "react";
-import { useLocation } from "react-router-dom";
+import { IconPhone } from "@tabler/icons-react";
+import _ from "lodash";
+import { useLocation, useNavigate } from "react-router-dom";
import useSwr from "swr";
export default function DetailWargaPage() {
const { search } = useLocation();
const query = new URLSearchParams(search);
const id = query.get("id");
+ const { data, mutate, isLoading } = useSwr("/", () =>
+ apiFetch.api.warga.detail.get({
+ query: {
+ id: id!,
+ },
+ }),
+ );
+
+ useShallowEffect(() => {
+ mutate();
+ }, []);
+
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+
);
}
-function DetailDataHistori() {
- const elements = [
- { position: 6, mass: 12.011, symbol: "C", name: "Carbon" },
- { position: 7, mass: 14.007, symbol: "N", name: "Nitrogen" },
- { position: 39, mass: 88.906, symbol: "Y", name: "Yttrium" },
- { position: 56, mass: 137.33, symbol: "Ba", name: "Barium" },
- { position: 58, mass: 140.12, symbol: "Ce", name: "Cerium" },
- ];
+function DetailDataHistori({ data, kategori }: { data: any, kategori: 'pengaduan' | 'pelayanan' }) {
+ const navigate = useNavigate();
- const rows = elements.map((element) => (
-
- {element.position}
- {element.name}
- {element.symbol}
- {element.mass}
-
- ));
return (
- Histori Pengaduan
+ Histori {_.upperFirst(kategori)}
- Tanggal
- Deskripsi
+ No {_.upperFirst(kategori)}
+ {kategori == "pengaduan" ? "Judul" : "Kategori"}
Status
- User
+
- {rows}
+
+ {
+ data?.length > 0 ? (
+ data?.map((item: any, index: number) => (
+
+ {item.noPengaduan}
+ {kategori == "pengaduan" ? item.title : item.category}
+ {item.status}
+
+
+
+
+ ))
+ ) : (
+
+ Tidak ada data
+
+ )
+ }
+
);
}
-function DetailWarga() {
- const [page, setPage] = useState(1);
- const [value, setValue] = useState("");
- const { data, mutate, isLoading } = useSwr("/", () =>
- apiFetch.api.pengaduan.list.get({
- query: {
- status,
- search: value,
- take: "",
- page: "",
- },
- }),
- );
-
- useShallowEffect(() => {
- mutate();
- }, [status, value]);
-
- const list = data?.data || [];
-
+function DetailWarga({ data }: { data: any }) {
return (
- {/* Profile image */}
+ >
+ A
+
{/* Main content */}
- Lizbeth Moore
+ {data?.name}
- Social Media Strategies
+ Warga Desa
@@ -161,19 +180,9 @@ function DetailWarga() {
{/* Contact info */}
-
-
- lizbeth.moore@email.com
-
-
- +1 555-7788
-
-
-
-
- Greenway Ave, Los Angeles, CA, USA
+ {data?.phone}
diff --git a/src/pages/scr/dashboard/warga/list_warga_page.tsx b/src/pages/scr/dashboard/warga/list_warga_page.tsx
index cb34134..149d10a 100644
--- a/src/pages/scr/dashboard/warga/list_warga_page.tsx
+++ b/src/pages/scr/dashboard/warga/list_warga_page.tsx
@@ -1,3 +1,4 @@
+import apiFetch from "@/lib/apiFetch";
import {
Button,
Card,
@@ -10,41 +11,30 @@ import {
Table,
Title,
} from "@mantine/core";
+import { useShallowEffect } from "@mantine/hooks";
import { IconSearch } from "@tabler/icons-react";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
+import useSWR from "swr";
export default function ListWargaPage() {
const navigate = useNavigate();
- const [value, setValue] = useState("");
- const elements = [
- { position: 6, mass: 12.011, symbol: "C", name: "Carbon" },
- { position: 7, mass: 14.007, symbol: "N", name: "Nitrogen" },
- { position: 39, mass: 88.906, symbol: "Y", name: "Yttrium" },
- { position: 56, mass: 137.33, symbol: "Ba", name: "Barium" },
- { position: 58, mass: 140.12, symbol: "Ce", name: "Cerium" },
- ];
+ const { data, mutate, isLoading } = useSWR("/", () =>
+ apiFetch.api.warga.list.get({
+ query: {
+ search: value,
+ },
+ }),
+ );
+
+ const list = data?.data || [];
+
+ const [value, setValue] = useState("");
+
+ useShallowEffect(() => {
+ mutate();
+ }, [value]);
- const rows = elements.map((element) => (
-
- {element.position}
- {element.name}
- {element.symbol}
- {element.mass}
-
-
-
-
- ));
return (
@@ -81,14 +71,39 @@ export default function ListWargaPage() {
- Tanggal
- Deskripsi
- Status
- User
+ Nama
+ No Telepon
Aksi
- {rows}
+
+ {
+ list?.length === 0 ? (
+
+ Tidak ada data
+
+ ) : (
+ list?.map((item, i) => (
+
+ {item.name}
+ {item.phone}
+
+
+
+
+ ))
+ )
+ }
+
diff --git a/src/server/routes/warga_route.ts b/src/server/routes/warga_route.ts
new file mode 100644
index 0000000..d5324ed
--- /dev/null
+++ b/src/server/routes/warga_route.ts
@@ -0,0 +1,141 @@
+import Elysia, { t } from "elysia";
+import _ from "lodash";
+import { normalizePhoneNumber } from "../lib/normalizePhone";
+import { prisma } from "../lib/prisma";
+
+const WargaRoute = new Elysia({
+ prefix: "warga",
+ tags: ["warga"],
+})
+
+ .get("/list", async ({ query }) => {
+ const { search } = query
+
+ const data = await prisma.warga.findMany({
+ where: {
+ OR: [
+ {
+ name: {
+ contains: search,
+ mode: "insensitive"
+ }
+ },
+ {
+ phone: {
+ contains: search,
+ mode: "insensitive"
+ }
+ }
+ ]
+ },
+ orderBy: {
+ name: "asc"
+ }
+ })
+
+ return data
+ }, {
+ detail: {
+ summary: "List Warga",
+ description: `tool untuk mendapatkan list warga`,
+ }
+ })
+ .post("/edit", async ({ body }) => {
+ const { id, name, phone } = body
+
+ const nomorHP = normalizePhoneNumber({ phone })
+ await prisma.warga.update({
+ where: {
+ id,
+ },
+ data: {
+ name,
+ phone: nomorHP
+ }
+ })
+
+ return { success: true, message: 'data warga sudah diperbarui' }
+ }, {
+ body: t.Object({
+ id: t.String({ minLength: 1, error: "id harus diisi" }),
+ name: t.String({ minLength: 1, error: "value harus diisi" }),
+ phone: t.String({ minLength: 1 })
+ }),
+ detail: {
+ summary: "edit konfigurasi desa",
+ description: `tool untuk edit konfigurasi desa`
+ }
+ })
+ .get("/detail", async ({ query }) => {
+ const { id } = query
+ const dataWarga = await prisma.warga.findUnique({
+ where: {
+ id
+ }
+ })
+
+ const dataPengaduan = await prisma.pengaduan.findMany({
+ orderBy: {
+ createdAt: "desc"
+ },
+ where: {
+ isActive: true,
+ idWarga: id
+ },
+ select: {
+ id: true,
+ status: true,
+ noPengaduan: true,
+ title: true
+ }
+ })
+
+
+
+ const dataPelayanan = await prisma.pelayananAjuan.findMany({
+ orderBy: {
+ createdAt: "desc"
+ },
+ where: {
+ isActive: true,
+ idWarga: id
+ },
+ select: {
+ id: true,
+ noPengajuan: true,
+ status: true,
+ CategoryPelayanan: {
+ select: {
+ name: true
+ }
+ }
+ }
+ })
+
+ const dataPelayanFix = dataPelayanan.map((v: any) => ({
+ ..._.omit(v, ["CategoryPelayanan"]),
+ id: v.id,
+ noPengaduan: v.noPengajuan,
+ status: v.status,
+ category: v.CategoryPelayanan.name
+ }))
+
+ return {
+ warga: dataWarga,
+ pengaduan: dataPengaduan,
+ pelayanan: dataPelayanFix
+ }
+
+ }, {
+ query: t.Object({
+ id: t.String({ minLength: 1, error: "id harus diisi" })
+ }),
+ detail: {
+ summary: "Detail Warga",
+ description: `tool untuk mendapatkan detail warga`,
+ }
+
+ })
+ ;
+
+export default WargaRoute