Compare commits
9 Commits
amalia/18-
...
amalia/23-
| Author | SHA1 | Date | |
|---|---|---|---|
| 8bafb88086 | |||
| 777f2c04f1 | |||
| a81f6c4255 | |||
| 0f1b0196e7 | |||
| da86f5f10a | |||
| 91a3dfdb5d | |||
| 3904527c2a | |||
| ff0413be5a | |||
| fda2b0977a |
310
bak/listPermission.json.txt
Normal file
310
bak/listPermission.json.txt
Normal file
@@ -0,0 +1,310 @@
|
||||
{
|
||||
"menus": [
|
||||
{
|
||||
"key": "dashboard",
|
||||
"label": "Dashboard",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "dashboard.view",
|
||||
"label": "Melihat Dashboard",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "pengaduan",
|
||||
"label": "Pengaduan",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "pengaduan.view",
|
||||
"label": "Melihat List & Detail",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "pengaduan.antrian",
|
||||
"label": "Detail pengaduan dengan status antrian",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "pengaduan.antrian.tolak",
|
||||
"label": "Menolak pengaduan",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "pengaduan.antrian.terima",
|
||||
"label": "Menerima pengaduan",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "pengaduan.diterima",
|
||||
"label": "Detail pengaduan dengan status diterima",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "pengaduan.diterima.dikerjakan",
|
||||
"label": "Menegerjakan pengaduan",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "pengaduan.dikerjakan",
|
||||
"label": "Detail pengaduan dengan status dikerjakan",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "pengaduan.dikerjakan.selesai",
|
||||
"label": "Menyelesaikan pengaduan",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "pelayanan",
|
||||
"label": "Pelayanan",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "pelayanan.view",
|
||||
"label": "Melihat List & Detail",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "pelayanan.antrian",
|
||||
"label": "Detail pelayanan dengan status antrian",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "pelayanan.antrian.tolak",
|
||||
"label": "Menolak pelayanan",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "pelayanan.antrian.terima",
|
||||
"label": "Menerima pelayanan",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "pelayanan.diterima",
|
||||
"label": "Detail pelayanan dengan status diterima",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "pelayanan.diterima.tolak",
|
||||
"label": "Menolak pelayanan",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "pelayanan.diterima.setujui",
|
||||
"label": "Menyetujui pelayanan",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "warga",
|
||||
"label": "Warga",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "warga.view",
|
||||
"label": "Melihat List & Detail",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "setting",
|
||||
"label": "Setting",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "setting.profile",
|
||||
"label": "Profile",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "setting.profile.view",
|
||||
"label": "View",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.profile.edit",
|
||||
"label": "Edit",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.profile.password",
|
||||
"label": "Ubah Password",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "setting.user",
|
||||
"label": "User",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "setting.user.view",
|
||||
"label": "View List",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.user.tambah",
|
||||
"label": "Tambah",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.user.edit",
|
||||
"label": "Edit",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.user.delete",
|
||||
"label": "Delete",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "setting.user_role",
|
||||
"label": "User Role",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "setting.user_role.view",
|
||||
"label": "View List",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.user_role.tambah",
|
||||
"label": "Tambah",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.user_role.edit",
|
||||
"label": "Edit",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.user_role.delete",
|
||||
"label": "Delete",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pengaduan",
|
||||
"label": "Kategori Pengaduan",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "setting.kategori_pengaduan.view",
|
||||
"label": "View List",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pengaduan.tambah",
|
||||
"label": "Tambah",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pengaduan.edit",
|
||||
"label": "Edit",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pengaduan.delete",
|
||||
"label": "Delete",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan",
|
||||
"label": "Kategori Pelayanan Surat",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.view",
|
||||
"label": "View List",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.detail",
|
||||
"label": "View Detail",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.tambah",
|
||||
"label": "Tambah",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.edit",
|
||||
"label": "Edit",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.delete",
|
||||
"label": "Delete",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "setting.desa",
|
||||
"label": "Desa",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "setting.desa.view",
|
||||
"label": "View List",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.desa.edit",
|
||||
"label": "Edit",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "api_key",
|
||||
"label": "API Key",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "api_key.view",
|
||||
"label": "View List",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "credential",
|
||||
"label": "Credential",
|
||||
"default": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "credential.view",
|
||||
"label": "View List",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import FormKartuKeluarga from "./pages/darmasaba/form_kartu_keluarga";
|
||||
import FormLaporanSampah from "./pages/darmasaba/form_laporan_sampah";
|
||||
import FormSuratKeteranganPenghasilan from "./pages/darmasaba/form_surat_keterangan_penghasilan";
|
||||
import FormSuratKeteranganDomisiliOrganisasi from "./pages/darmasaba/form_surat_keterangan_domisili_organisasi";
|
||||
import UpdateDataSurat from "./pages/darmasaba/update_data_surat";
|
||||
import FormSuratKeteranganBelumKawin from "./pages/darmasaba/form_surat_keterangan_belum_kawin";
|
||||
import FormKeteranganKelahiran from "./pages/darmasaba/form_keterangan_kelahiran";
|
||||
import FormSuratKeteranganTempatUsaha from "./pages/darmasaba/form_surat_keterangan_tempat_usaha";
|
||||
@@ -69,6 +70,10 @@ export default function AppRoutes() {
|
||||
path="/darmasaba/surat-keterangan-domisili-organisasi"
|
||||
element={<FormSuratKeteranganDomisiliOrganisasi />}
|
||||
/>
|
||||
<Route
|
||||
path="/darmasaba/update-data-surat"
|
||||
element={<UpdateDataSurat />}
|
||||
/>
|
||||
<Route
|
||||
path="/darmasaba/surat-keterangan-belum-kawin"
|
||||
element={<FormSuratKeteranganBelumKawin />}
|
||||
|
||||
@@ -10,6 +10,7 @@ const clientRoutes = {
|
||||
"/darmasaba/laporan-sampah": "/darmasaba/laporan-sampah",
|
||||
"/darmasaba/surat-keterangan-penghasilan": "/darmasaba/surat-keterangan-penghasilan",
|
||||
"/darmasaba/surat-keterangan-domisili-organisasi": "/darmasaba/surat-keterangan-domisili-organisasi",
|
||||
"/darmasaba/update-data-surat": "/darmasaba/update-data-surat",
|
||||
"/darmasaba/surat-keterangan-belum-kawin": "/darmasaba/surat-keterangan-belum-kawin",
|
||||
"/darmasaba/keterangan-kelahiran": "/darmasaba/keterangan-kelahiran",
|
||||
"/darmasaba/surat-keterangan-tempat-usaha": "/darmasaba/surat-keterangan-tempat-usaha",
|
||||
|
||||
@@ -1,43 +1,38 @@
|
||||
import { Center, Loader, Overlay, Stack, Text } from "@mantine/core"
|
||||
import { Center, Loader, Overlay, Stack, Text } from "@mantine/core";
|
||||
|
||||
type FullScreenLoadingProps = {
|
||||
visible: boolean
|
||||
text?: string
|
||||
}
|
||||
visible: boolean;
|
||||
text?: string;
|
||||
};
|
||||
|
||||
export default function FullScreenLoading({
|
||||
visible,
|
||||
text = "Memproses data..."
|
||||
visible,
|
||||
text = "Memproses data...",
|
||||
}: FullScreenLoadingProps) {
|
||||
if (!visible) return null
|
||||
if (!visible) return null;
|
||||
|
||||
return (
|
||||
<Overlay
|
||||
fixed
|
||||
blur={6}
|
||||
backgroundOpacity={0.3}
|
||||
zIndex={10000}
|
||||
>
|
||||
<Center h="100%">
|
||||
<Stack align="center" justify="center">
|
||||
<Loader size="lg" />
|
||||
<Text size="sm" c="dimmed">
|
||||
{text}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
</Overlay>
|
||||
)
|
||||
return (
|
||||
<Overlay fixed blur={6} backgroundOpacity={0.3} zIndex={10000}>
|
||||
<Center h="100%">
|
||||
<Stack align="center" justify="center">
|
||||
<Loader size="lg" />
|
||||
<Text size="sm" c="dimmed">
|
||||
{text}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
</Overlay>
|
||||
);
|
||||
}
|
||||
|
||||
const overlayStyle: React.CSSProperties = {
|
||||
position: "fixed",
|
||||
inset: 0,
|
||||
zIndex: 9999,
|
||||
backdropFilter: "blur(6px)",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.6)"
|
||||
}
|
||||
position: "fixed",
|
||||
inset: 0,
|
||||
zIndex: 9999,
|
||||
backdropFilter: "blur(6px)",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.6)",
|
||||
};
|
||||
|
||||
const contentStyle: React.CSSProperties = {
|
||||
flexDirection: "column"
|
||||
}
|
||||
flexDirection: "column",
|
||||
};
|
||||
|
||||
@@ -11,10 +11,9 @@ import {
|
||||
Modal,
|
||||
Stack,
|
||||
Table,
|
||||
TagsInput,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
Tooltip
|
||||
} from "@mantine/core";
|
||||
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
|
||||
import { IconEdit, IconEye, IconPlus, IconTrash } from "@tabler/icons-react";
|
||||
@@ -44,13 +43,13 @@ export default function KategoriPelayananSurat({
|
||||
const [dataChoose, setDataChoose] = useState({
|
||||
id: "",
|
||||
name: "",
|
||||
syaratDokumen: [{ name: "", desc: "" }],
|
||||
dataText: [""],
|
||||
syaratDokumen: [{ key: "", name: "", desc: "" }],
|
||||
dataPelengkap: [{ key: "", name: "", desc: "" }],
|
||||
});
|
||||
const [dataTambah, setDataTambah] = useState({
|
||||
name: "",
|
||||
syaratDokumen: [{ name: "", desc: "" }],
|
||||
dataText: [""],
|
||||
syaratDokumen: [{ key: "", name: "", desc: "" }],
|
||||
dataPelengkap: [{ key: "", name: "", desc: "" }],
|
||||
});
|
||||
|
||||
useShallowEffect(() => {
|
||||
@@ -60,8 +59,8 @@ export default function KategoriPelayananSurat({
|
||||
async function handleCreate() {
|
||||
try {
|
||||
setBtnLoading(true);
|
||||
const cleanedDataText = dataTambah.dataText
|
||||
.map((v) => v.trim())
|
||||
const cleanedDataText = dataTambah.dataPelengkap
|
||||
.map((v) => v.name.trim())
|
||||
.filter((v) => v !== "");
|
||||
const cleanedSyarat = dataTambah.syaratDokumen
|
||||
.map((item) => ({
|
||||
@@ -82,8 +81,8 @@ export default function KategoriPelayananSurat({
|
||||
closeTambah();
|
||||
setDataTambah({
|
||||
name: "",
|
||||
syaratDokumen: [{ name: "", desc: "" }],
|
||||
dataText: [""],
|
||||
syaratDokumen: [{ key: "", name: "", desc: "" }],
|
||||
dataPelengkap: [{ key: "", name: "", desc: "" }],
|
||||
});
|
||||
notification({
|
||||
title: "Success",
|
||||
@@ -112,8 +111,8 @@ export default function KategoriPelayananSurat({
|
||||
async function handleEdit() {
|
||||
try {
|
||||
setBtnLoading(true);
|
||||
const cleanedDataText = dataChoose.dataText
|
||||
.map((v) => v.trim())
|
||||
const cleanedDataText = dataChoose.dataPelengkap
|
||||
.map((v) => v.name.trim())
|
||||
.filter((v) => v !== "");
|
||||
const cleanedSyarat = dataChoose.syaratDokumen
|
||||
.map((item) => ({
|
||||
@@ -191,7 +190,7 @@ export default function KategoriPelayananSurat({
|
||||
function handleAddSyarat() {
|
||||
setDataChoose({
|
||||
...dataChoose,
|
||||
syaratDokumen: [...dataChoose.syaratDokumen, { name: "", desc: "" }],
|
||||
syaratDokumen: [...dataChoose.syaratDokumen, { key: "", name: "", desc: "" }],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -204,7 +203,7 @@ export default function KategoriPelayananSurat({
|
||||
|
||||
function handleEditSyarat(
|
||||
index: number,
|
||||
data: { name: string; desc: string },
|
||||
data: { key: string; name: string; desc: string },
|
||||
) {
|
||||
setDataChoose({
|
||||
...dataChoose,
|
||||
@@ -217,7 +216,7 @@ export default function KategoriPelayananSurat({
|
||||
return (
|
||||
<>
|
||||
{/* Modal Edit */}
|
||||
<Modal
|
||||
{/* <Modal
|
||||
opened={opened}
|
||||
onClose={close}
|
||||
title={"Edit"}
|
||||
@@ -233,15 +232,85 @@ export default function KategoriPelayananSurat({
|
||||
}
|
||||
/>
|
||||
</Input.Wrapper>
|
||||
<TagsInput
|
||||
label="Data Pelengkap"
|
||||
placeholder="Tambah data pelengkap"
|
||||
splitChars={[","]}
|
||||
value={dataChoose.dataText}
|
||||
onChange={(value) =>
|
||||
setDataChoose({ ...dataChoose, dataText: value })
|
||||
}
|
||||
/>
|
||||
<Flex direction={"column"} gap={"md"}>
|
||||
<Group>
|
||||
<Text size="sm" c={"white"}>
|
||||
Data Pelengkap
|
||||
</Text>
|
||||
<Tooltip label="Tambah Data Pelengkap">
|
||||
<ActionIcon
|
||||
variant="light"
|
||||
size="sm"
|
||||
color="blue"
|
||||
style={{ boxShadow: "0 0 8px rgba(0,255,200,0.2)" }}
|
||||
onClick={handleAddSyarat}
|
||||
>
|
||||
<IconPlus size={20} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
{dataChoose?.dataPelengkap?.map((v: any, i: number) => (
|
||||
<Grid
|
||||
key={i}
|
||||
style={{
|
||||
borderBottom: "1px solid gray",
|
||||
paddingBottom: "10px",
|
||||
}}
|
||||
>
|
||||
<Grid.Col
|
||||
span={1}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Tooltip label="Delete Syarat Dokumen">
|
||||
<ActionIcon
|
||||
variant="light"
|
||||
size="sm"
|
||||
color="red"
|
||||
style={{ boxShadow: "0 0 8px rgba(0,255,200,0.2)" }}
|
||||
onClick={() => {
|
||||
handleDeleteSyarat(i);
|
||||
}}
|
||||
>
|
||||
<IconTrash size={20} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={5}>
|
||||
<Input.Wrapper label="Label">
|
||||
<Input
|
||||
value={v.name}
|
||||
onChange={(e) =>
|
||||
handleEditSyarat(i, {
|
||||
key: v.key,
|
||||
name: e.target.value,
|
||||
desc: v.desc,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Input.Wrapper>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={6}>
|
||||
<Input.Wrapper label="Deskripsi">
|
||||
<Input
|
||||
value={v.desc}
|
||||
onChange={(e) =>
|
||||
handleEditSyarat(i, {
|
||||
key: v.key,
|
||||
name: v.name,
|
||||
desc: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Input.Wrapper>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
))}
|
||||
</Flex>
|
||||
|
||||
<Flex direction={"column"} gap={"md"}>
|
||||
<Group>
|
||||
<Text size="sm" c={"white"}>
|
||||
@@ -290,11 +359,12 @@ export default function KategoriPelayananSurat({
|
||||
</Tooltip>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={5}>
|
||||
<Input.Wrapper label="Nama">
|
||||
<Input.Wrapper label="Label">
|
||||
<Input
|
||||
value={v.name}
|
||||
onChange={(e) =>
|
||||
handleEditSyarat(i, {
|
||||
key: v.key,
|
||||
name: e.target.value,
|
||||
desc: v.desc,
|
||||
})
|
||||
@@ -308,6 +378,7 @@ export default function KategoriPelayananSurat({
|
||||
value={v.desc}
|
||||
onChange={(e) =>
|
||||
handleEditSyarat(i, {
|
||||
key: v.key,
|
||||
name: v.name,
|
||||
desc: e.target.value,
|
||||
})
|
||||
@@ -328,10 +399,10 @@ export default function KategoriPelayananSurat({
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
</Modal> */}
|
||||
|
||||
{/* Modal Tambah */}
|
||||
<Modal
|
||||
{/* <Modal
|
||||
opened={openedTambah}
|
||||
onClose={closeTambah}
|
||||
title={"Tambah"}
|
||||
@@ -347,15 +418,6 @@ export default function KategoriPelayananSurat({
|
||||
}
|
||||
/>
|
||||
</Input.Wrapper>
|
||||
<TagsInput
|
||||
label="Data Pelengkap"
|
||||
placeholder="Tambah data pelengkap"
|
||||
splitChars={[","]}
|
||||
value={dataTambah.dataText}
|
||||
onChange={(value) =>
|
||||
setDataTambah({ ...dataTambah, dataText: value })
|
||||
}
|
||||
/>
|
||||
<Flex direction={"column"} gap={"md"}>
|
||||
<Group>
|
||||
<Text size="sm" c={"white"}>
|
||||
@@ -372,7 +434,7 @@ export default function KategoriPelayananSurat({
|
||||
...dataTambah,
|
||||
syaratDokumen: [
|
||||
...dataTambah.syaratDokumen,
|
||||
{ name: "", desc: "" },
|
||||
{ key: "", name: "", desc: "" },
|
||||
],
|
||||
});
|
||||
}}
|
||||
@@ -465,7 +527,7 @@ export default function KategoriPelayananSurat({
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
</Modal> */}
|
||||
|
||||
{/* Modal Delete */}
|
||||
<Modal
|
||||
@@ -524,8 +586,8 @@ export default function KategoriPelayananSurat({
|
||||
Data Pelengkap
|
||||
</Text>
|
||||
<List>
|
||||
{dataChoose?.dataText?.map((v: any) => (
|
||||
<List.Item key={v.id}>{v}</List.Item>
|
||||
{dataChoose?.dataPelengkap?.map((v: any) => (
|
||||
<List.Item key={v.id}>{v.name}</List.Item>
|
||||
))}
|
||||
</List>
|
||||
</Flex>
|
||||
@@ -538,7 +600,7 @@ export default function KategoriPelayananSurat({
|
||||
<Title order={4} c="gray.2">
|
||||
Kategori Pelayanan Surat
|
||||
</Title>
|
||||
{permissions.includes("setting.kategori_pelayanan.tambah") && (
|
||||
{/* {permissions.includes("setting.kategori_pelayanan.tambah") && (
|
||||
<Tooltip label="Tambah Kategori Pelayanan Surat">
|
||||
<Button
|
||||
variant="light"
|
||||
@@ -548,7 +610,7 @@ export default function KategoriPelayananSurat({
|
||||
Tambah
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
)} */}
|
||||
</Flex>
|
||||
<Divider my={0} />
|
||||
<Stack gap={"md"}>
|
||||
@@ -579,7 +641,7 @@ export default function KategoriPelayananSurat({
|
||||
<IconEye size={20} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
{/* <Tooltip
|
||||
label={
|
||||
permissions.includes(
|
||||
"setting.kategori_pelayanan.edit",
|
||||
@@ -604,7 +666,7 @@ export default function KategoriPelayananSurat({
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Tooltip> */}
|
||||
<Tooltip
|
||||
label={
|
||||
permissions.includes(
|
||||
|
||||
@@ -1,50 +1,45 @@
|
||||
import { Badge, Button, Card, Center, Stack, Text, Title } from "@mantine/core"
|
||||
import { IconCheck } from "@tabler/icons-react"
|
||||
import { Badge, Button, Card, Center, Stack, Text, Title } from "@mantine/core";
|
||||
import { IconCheck } from "@tabler/icons-react";
|
||||
|
||||
type SuccessPengajuanProps = {
|
||||
noPengajuan: string
|
||||
onClose?: () => void
|
||||
}
|
||||
noPengajuan: string;
|
||||
onClose?: () => void;
|
||||
category?: 'create' | 'update';
|
||||
};
|
||||
|
||||
export default function SuccessPengajuan({
|
||||
noPengajuan,
|
||||
onClose
|
||||
noPengajuan,
|
||||
onClose,
|
||||
category
|
||||
}: SuccessPengajuanProps) {
|
||||
return (
|
||||
<Center h="100vh">
|
||||
<Card
|
||||
shadow="md"
|
||||
radius="md"
|
||||
p="xl"
|
||||
withBorder
|
||||
maw={520}
|
||||
w="100%"
|
||||
>
|
||||
<Stack align="center" gap="md">
|
||||
<IconCheck size={56} color="green" />
|
||||
return (
|
||||
<Center h="100vh">
|
||||
<Card shadow="md" radius="md" p="xl" withBorder maw={520} w="100%">
|
||||
<Stack align="center" gap="md">
|
||||
<IconCheck size={56} color="green" />
|
||||
|
||||
<Title order={3} ta="center">
|
||||
Pengajuan Berhasil Dibuat
|
||||
</Title>
|
||||
<Title order={3} ta="center">
|
||||
{category == 'create' ? 'Pengajuan Berhasil Dibuat' : 'Pengajuan Berhasil Diupdate'}
|
||||
</Title>
|
||||
|
||||
<Text ta="center" size="sm" c="dimmed">
|
||||
Pengajuan layanan surat sudah dibuat dengan nomor:
|
||||
</Text>
|
||||
<Text ta="center" size="sm" c="dimmed">
|
||||
{category == 'create' ? 'Pengajuan layanan surat sudah dibuat dengan nomor:' : 'Pengajuan layanan surat sudah diupdate dengan nomor:'}
|
||||
</Text>
|
||||
|
||||
<Badge size="xl" variant="light" color="green">
|
||||
{noPengajuan}
|
||||
</Badge>
|
||||
<Badge size="xl" variant="light" color="green">
|
||||
{noPengajuan}
|
||||
</Badge>
|
||||
|
||||
<Text ta="center" size="sm">
|
||||
Nomor ini akan digunakan untuk mengakses dan memantau status
|
||||
pengajuan surat Anda.
|
||||
</Text>
|
||||
<Text ta="center" size="sm">
|
||||
Nomor ini akan digunakan untuk mengakses dan memantau status
|
||||
pengajuan surat Anda.
|
||||
</Text>
|
||||
|
||||
<Button fullWidth mt="md" onClick={onClose}>
|
||||
Selesai
|
||||
</Button>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Center>
|
||||
)
|
||||
<Button fullWidth mt="md" onClick={onClose}>
|
||||
Selesai
|
||||
</Button>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Center>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export default function SKBedaBiodataDiri({ data }: { data: any }) {
|
||||
const getValue = (jenis: string) =>
|
||||
_.upperFirst(
|
||||
data.surat.dataText.find((item: any) => item.jenis === jenis)?.value ||
|
||||
"",
|
||||
"",
|
||||
);
|
||||
|
||||
const loadImage = async () => {
|
||||
@@ -108,12 +108,12 @@ export default function SKBedaBiodataDiri({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td>Tempat/Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin")}</td>
|
||||
<td>{getValue("jenis_kelamin")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
@@ -144,36 +144,38 @@ export default function SKBedaBiodataDiri({ data }: { data: any }) {
|
||||
<table style={{ width: "100%", marginTop: "5px" }}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ width: "160px" }}>1. Nama</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>{getValue("nama")}</td>
|
||||
<td style={{ width: "160px" }}>1. {getValue("data_dokumen")}</td>
|
||||
<td style={{ width: "10px" }}></td>
|
||||
<td>
|
||||
{/* {getValue("nama")} */}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tertulis pada dokumen A</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tertulis pada dokumen a")}</td>
|
||||
<td>{getValue("dokumen_a")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tertulis pada dokumen B</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tertulis pada dokumen b")}</td>
|
||||
<td>{getValue("dokumen_b")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: "15px" }}>
|
||||
{/* <div style={{ marginTop: "15px" }}>
|
||||
<table style={{ width: "100%", marginTop: "5px" }}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ width: "160px" }}>2. Tempat/Tanggal Lahir</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{getValue("tempat_lahir")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tertulis pada dokumen A</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tertulis pada dokumen a")}</td>
|
||||
<td>{getValue("dokumen_a")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tertulis pada dokumen B</td>
|
||||
@@ -204,7 +206,7 @@ export default function SKBedaBiodataDiri({ data }: { data: any }) {
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<div style={{ marginTop: "15px" }}>
|
||||
Perbedaan tersebut terjadi karena{" "}
|
||||
|
||||
@@ -7,7 +7,7 @@ export default function SKBelumKawin({ data }: { data: any }) {
|
||||
const getValue = (jenis: string) =>
|
||||
_.upperFirst(
|
||||
data.surat.dataText.find((item: any) => item.jenis === jenis)?.value ||
|
||||
"",
|
||||
"",
|
||||
);
|
||||
|
||||
const loadImage = async () => {
|
||||
@@ -87,12 +87,12 @@ export default function SKBelumKawin({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td>Tempat/Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin")}</td>
|
||||
<td>{getValue("jenis_kelamin")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Agama</td>
|
||||
|
||||
@@ -95,27 +95,27 @@ export default function SKDomisiliOrganisasi({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "160px" }}>Nama Organisasi</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>{getValue("nama")}</td>
|
||||
<td>{getValue("nama_organisasi")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jenis Organisasi</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin")}</td>
|
||||
<td>{getValue("jenis_organisasi")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{getValue("alamat_organisasi")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nomor Telepon</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("negara")}</td>
|
||||
<td>{getValue("no_telepon")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nama Pimpinan</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("agama")}</td>
|
||||
<td>{getValue("nama_pimpinan")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -78,32 +78,32 @@ export default function SKKelahiran({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "200px" }}>Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tanggal lahir anak")}</td>
|
||||
<td>{getValue("tanggal_lahir_anak")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pukul</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("pukul lahir anak")}</td>
|
||||
<td>{getValue("pukul_lahir")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat Kelahiran</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat lahir anak")}</td>
|
||||
<td>{getValue("tempat_lahir")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin anak")}</td>
|
||||
<td>{getValue("jenis_kelamin")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Anak ke</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("anak ke")}</td>
|
||||
<td>{getValue("anak_ke")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nama Anak</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nama anak")}</td>
|
||||
<td>{getValue("nama_anak")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -117,27 +117,27 @@ export default function SKKelahiran({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "200px" }}>Nama Lengkap Ibu</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nama ibu")}</td>
|
||||
<td>{getValue("nama_ibu")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>NIK</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nik ibu")}</td>
|
||||
<td>{getValue("nik_ibu")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat & Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir ibu")}</td>
|
||||
<td>{`${getValue("tempat_lahir_ibu")}, ${getValue("tanggal_lahir_ibu")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pekerjaan</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("pekerjaan ibu")}</td>
|
||||
<td>{getValue("pekerjaan_ibu")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("alamat ibu")}</td>
|
||||
<td>{getValue("alamat_ibu")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -151,27 +151,27 @@ export default function SKKelahiran({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "200px" }}>Nama Lengkap Ayah</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nama ayah")}</td>
|
||||
<td>{getValue("nama_ayah")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>NIK</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nik ayah")}</td>
|
||||
<td>{getValue("nik_ayah")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat & Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir ayah")}</td>
|
||||
<td>{`${getValue("tempat_lahir_ayah")}, ${"tanggal_lahir_ayah"}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pekerjaan</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("pekerjaan ayah")}</td>
|
||||
<td>{getValue("pekerjaan_ayah")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("alamat ayah")}</td>
|
||||
<td>{getValue("alamat_ayah")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -185,17 +185,17 @@ export default function SKKelahiran({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "200px" }}>Nama Pelapor</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nama pelapor")}</td>
|
||||
<td>{getValue("nama_pelapor")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hubungan dengan Anak</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("hubungan pelapor")}</td>
|
||||
<td>{getValue("hubungan_pelapor")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("alamat pelapor")}</td>
|
||||
<td>{getValue("alamat_pelapor")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -71,12 +71,12 @@ export default function SKKelakuanBaik({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td>Tempat/Tgl Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin")}</td>
|
||||
<td>{getValue("jenis_kelamin")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Agama</td>
|
||||
|
||||
@@ -7,7 +7,7 @@ export default function SKKematian({ data }: { data: any }) {
|
||||
const getValue = (jenis: string) =>
|
||||
_.upperFirst(
|
||||
data.surat.dataText.find((item: any) => item.jenis === jenis)?.value ||
|
||||
"",
|
||||
"",
|
||||
);
|
||||
|
||||
const loadImage = async () => {
|
||||
@@ -71,27 +71,27 @@ export default function SKKematian({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "160px" }}>Nama</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>{getValue("nama")}</td>
|
||||
<td>{getValue("nama_pelapor")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>NIK</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nik")}</td>
|
||||
<td>{getValue("nik_pelapor")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pekerjaan</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("pekerjaan")}</td>
|
||||
<td>{getValue("pekerjaan_pelapor")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("alamat")}</td>
|
||||
<td>{getValue("alamat_pelapor")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hubungan dengan almarhum/almarhumah</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("hubungan dengan almarhum")}</td>
|
||||
<td>{getValue("hubungan_pelapor")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -104,32 +104,32 @@ export default function SKKematian({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "160px" }}>Nama</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>{getValue("nama")}</td>
|
||||
<td>{getValue("nama_almarhum")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>NIK</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("nik")}</td>
|
||||
<td>{getValue("nik_almarhum")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin")}</td>
|
||||
<td>{getValue("jenis_kelamin_almarhum")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat/Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{`${getValue("tempat_lahir_almarhum")}, ${getValue("tanggal_lahir_almarhum")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Agama</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("agama")}</td>
|
||||
<td>{getValue("agama_almarhum")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("alamat")}</td>
|
||||
<td>{getValue("alamat_almarhum")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -142,22 +142,22 @@ export default function SKKematian({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "160px" }}>Tanggal Kematian</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>{getValue("tanggal kematian")}</td>
|
||||
<td>{getValue("tanggal_kematian")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Waktu Kematian</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("waktu kematian")}</td>
|
||||
<td>{getValue("waktu_kematian")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat Kematian</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat kematian")}</td>
|
||||
<td>{getValue("tempat_kematian")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Penyebab Kematian</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("penyebab kematian")}</td>
|
||||
<td>{getValue("penyebab_kematian")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -185,7 +185,7 @@ export default function SKKematian({ data }: { data: any }) {
|
||||
<br />
|
||||
<br />
|
||||
<br /> <br />
|
||||
<u>{getValue("nama")}</u> <br />
|
||||
<u>{getValue("nama_pelapor")}</u> <br />
|
||||
</div>
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<br />
|
||||
|
||||
@@ -105,12 +105,12 @@ export default function SKPenghasilan({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin")}</td>
|
||||
<td>{getValue("jenis_kelamin")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat / Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pekerjaan</td>
|
||||
@@ -136,8 +136,7 @@ export default function SKPenghasilan({ data }: { data: any }) {
|
||||
<td style={{ width: "160px" }}>Penghasilan</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>
|
||||
Rp {getValue("penghasilan")} (
|
||||
{getValue("penghasilan terbilang")}) per bulan
|
||||
Rp. {getValue("penghasilan")} per bulan
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -147,7 +146,7 @@ export default function SKPenghasilan({ data }: { data: any }) {
|
||||
{/* KEPERLUAN */}
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
Surat keterangan ini dibuat untuk keperluan:{" "}
|
||||
<b>{getValue("alasan permohonan")}</b>.
|
||||
<b>{getValue("alasan")}</b>.
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
|
||||
@@ -66,12 +66,12 @@ export default function SKTempatUsaha({ data }: { data: any }) {
|
||||
|
||||
{/* DATA WARGA */}
|
||||
<div>
|
||||
<Row label="Nama Pemilik Usaha" value={getValue("nama")} />
|
||||
<Row label="Nama Pemilik Usaha" value={getValue("nama_pemilik")} />
|
||||
<Row
|
||||
label="Tempat/Tanggal Lahir"
|
||||
value={getValue("tempat tanggal lahir")}
|
||||
value={`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}
|
||||
/>
|
||||
<Row label="Alamat Pemilik Usaha" value={getValue("alamat")} />
|
||||
<Row label="Alamat Pemilik Usaha" value={getValue("alamat_pemilik")} />
|
||||
<Row label="Nomor KTP" value={getValue("nik")} />
|
||||
</div>
|
||||
|
||||
@@ -83,23 +83,23 @@ export default function SKTempatUsaha({ data }: { data: any }) {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Row label="Nama Usaha" value={getValue("nama usaha")} />
|
||||
<Row label="Bidang Usaha" value={getValue("bidang usaha")} />
|
||||
<Row label="Alamat Usaha" value={getValue("alamat usaha")} />
|
||||
<Row label="Nama Usaha" value={getValue("nama_usaha")} />
|
||||
<Row label="Bidang Usaha" value={getValue("bidang_usaha")} />
|
||||
<Row label="Alamat Usaha" value={getValue("alamat_usaha")} />
|
||||
<Row
|
||||
label="Status Tempat Usaha"
|
||||
value={getValue("status tempat usaha")}
|
||||
value={getValue("status_tempat")}
|
||||
/>
|
||||
<Row
|
||||
label="Luas Tempat Usaha"
|
||||
value={getValue("luas tempat usaha")}
|
||||
value={getValue("luas_usaha")}
|
||||
/>
|
||||
<Row label="Jumlah Karyawan" value={getValue("jumlah karyawan")} />
|
||||
<Row label="Jumlah Karyawan" value={getValue("jumlah_karyawan")} />
|
||||
</div>
|
||||
|
||||
<p style={{ textAlign: "justify" }}>
|
||||
Surat keterangan ini dibuat untuk keperluan{" "}
|
||||
<b>{getValue("alasan permohonan")}.</b>
|
||||
<b>{getValue("tujuan")}.</b>
|
||||
</p>
|
||||
|
||||
<p style={{ textAlign: "justify" }}>
|
||||
|
||||
@@ -66,13 +66,13 @@ export default function SKTidakMampu({ data }: { data: any }) {
|
||||
|
||||
{/* DATA WARGA */}
|
||||
<div>
|
||||
<Row label="NIK" value={getValue("nik")} />
|
||||
<Row label="Nama" value={getValue("nama")} />
|
||||
<Row
|
||||
label="Tempat Tgl Lahir"
|
||||
value={getValue("tempat tanggal lahir")}
|
||||
value={`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}
|
||||
/>
|
||||
<Row label="Alamat" value={getValue("alamat")} />
|
||||
<Row label="NIK" value={getValue("nik")} />
|
||||
</div>
|
||||
|
||||
<br />
|
||||
@@ -80,7 +80,7 @@ export default function SKTidakMampu({ data }: { data: any }) {
|
||||
<p style={{ textAlign: "justify" }}>
|
||||
Orang tersebut benar-benar penduduk desa {data.setting.desaNama} dan
|
||||
termasuk keluarga tidak mampu. Surat keterangan ini dipergunakan untuk
|
||||
<b>{getValue("alasan permohonan")}.</b>
|
||||
<b>{getValue("alasan")}.</b>
|
||||
</p>
|
||||
|
||||
<p style={{ textAlign: "justify" }}>
|
||||
|
||||
@@ -7,7 +7,7 @@ export default function SKUsaha({ data }: { data: any }) {
|
||||
const getValue = (jenis: string) =>
|
||||
_.upperFirst(
|
||||
data.surat.dataText.find((item: any) => item.jenis === jenis)?.value ||
|
||||
"",
|
||||
"",
|
||||
);
|
||||
|
||||
const loadImage = async () => {
|
||||
@@ -105,12 +105,12 @@ export default function SKUsaha({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("jenis kelamin")}</td>
|
||||
<td>{getValue("jenis_kelamin")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat / Tanggal Lahir</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("tempat tanggal lahir")}</td>
|
||||
<td>{`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Warga Negara</td>
|
||||
@@ -125,7 +125,7 @@ export default function SKUsaha({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("status perkawinan")}</td>
|
||||
<td>{getValue("status_perkawinan")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pekerjaan</td>
|
||||
@@ -173,12 +173,12 @@ export default function SKUsaha({ data }: { data: any }) {
|
||||
<tr>
|
||||
<td style={{ width: "160px" }}>Jenis Usaha</td>
|
||||
<td style={{ width: "10px" }}>:</td>
|
||||
<td>{getValue("jenis usaha")}</td>
|
||||
<td>{getValue("jenis_usaha")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat Usaha</td>
|
||||
<td>:</td>
|
||||
<td>{getValue("alamat usaha")}</td>
|
||||
<td>{getValue("alamat_usaha")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -88,26 +88,26 @@ export default function SKYatim({ data }: { data: any }) {
|
||||
|
||||
<table style={{ width: "100%", marginTop: "5px" }}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>NIK</td>
|
||||
<td>: {getValue("nik")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ width: "180px" }}>Nama</td>
|
||||
<td>: {getValue("nama")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tempat/Tanggal Lahir</td>
|
||||
<td>: {getValue("tempat tanggal lahir")}</td>
|
||||
<td>: {`${getValue("tempat_lahir")}, ${getValue("tanggal_lahir")}`}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jenis Kelamin</td>
|
||||
<td>: {getValue("jenis kelamin")}</td>
|
||||
<td>: {getValue("jenis_kelamin")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alamat</td>
|
||||
<td>: {getValue("alamat")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>NIK</td>
|
||||
<td>: {getValue("nik")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pekerjaan</td>
|
||||
<td>: {getValue("pekerjaan")}</td>
|
||||
@@ -133,11 +133,11 @@ export default function SKYatim({ data }: { data: any }) {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ width: "180px" }}>Nama Ayah</td>
|
||||
<td>: {getValue("nama ayah")}</td>
|
||||
<td>: {getValue("nama_ayah")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>: {getValue("status ayah")}</td>
|
||||
<td>: {getValue("status_ayah")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -151,11 +151,11 @@ export default function SKYatim({ data }: { data: any }) {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ width: "180px" }}>Nama Ibu</td>
|
||||
<td>: {getValue("nama ibu")}</td>
|
||||
<td>: {getValue("nama_ibu")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>: {getValue("status ibu")}</td>
|
||||
<td>: {getValue("status_ibu")}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -23,11 +23,13 @@ export const categoryPelayananSurat = [
|
||||
dataPelengkap: [
|
||||
{ key: "nik", name: "NIK", desc: "Nomor Induk Kependudukan" },
|
||||
{ key: "nama", name: "Nama Lengkap", desc: "Nama sesuai KTP" },
|
||||
{ key: "ttl", name: "Tempat & Tanggal Lahir", desc: "Tempat dan tanggal lahir pemohon" },
|
||||
{ key: "tempat_lahir", name: "Tempat Lahir", desc: "Tempat lahir pemohon" },
|
||||
{ key: "tanggal_lahir", name: "Tanggal Lahir", desc: "Tanggal lahir pemohon" },
|
||||
{ key: "jenis_kelamin", name: "Jenis Kelamin", desc: "Jenis kelamin pemohon" },
|
||||
{ key: "alamat", name: "Alamat", desc: "Alamat lengkap tempat tinggal" },
|
||||
{ key: "pekerjaan", name: "Pekerjaan", desc: "Pekerjaan pemohon" },
|
||||
{ key: "dokumen", name: "Nama Dokumen", desc: "Jenis dokumen yang mengalami perbedaan biodata" },
|
||||
{ key: "dokumen", name: "Nama Dokumen", desc: "Jenis dokumen yang mengalami perbedaan biodata (cth : ijazah, sertifikat, dll)" },
|
||||
{ key: "data_dokumen", name: "Data Dokumen", desc: "Data dokumen yg berbeda (cth : nama, tempat lahir, tanggal lahir, jenis kelamin, alamat, pekerjaan)" },
|
||||
{ key: "dokumen_a", name: "Data pada Dokumen A", desc: "Data biodata yang tertulis pada dokumen pertama" },
|
||||
{ key: "dokumen_b", name: "Data pada Dokumen B", desc: "Data biodata yang tertulis pada dokumen kedua" }
|
||||
]
|
||||
@@ -56,7 +58,8 @@ export const categoryPelayananSurat = [
|
||||
dataPelengkap: [
|
||||
{ key: "nik", name: "NIK", desc: "Nomor Induk Kependudukan" },
|
||||
{ key: "nama", name: "Nama Lengkap", desc: "Nama sesuai KTP" },
|
||||
{ key: "ttl", name: "Tempat & Tanggal Lahir", desc: "Tempat dan tanggal lahir" },
|
||||
{ key: "tempat_lahir", name: "Tempat Lahir", desc: "Tempat lahir pemohon" },
|
||||
{ key: "tanggal_lahir", name: "Tanggal Lahir", desc: "Tanggal lahir pemohon" },
|
||||
{ key: "jenis_kelamin", name: "Jenis Kelamin", desc: "Jenis kelamin pemohon" },
|
||||
{ key: "alamat", name: "Alamat", desc: "Alamat tempat tinggal" },
|
||||
{ key: "agama", name: "Agama", desc: "Agama pemohon" },
|
||||
@@ -110,8 +113,6 @@ export const categoryPelayananSurat = [
|
||||
],
|
||||
dataText: [],
|
||||
dataPelengkap: [
|
||||
{ key: "nama_ayah", name: "Nama Ayah", desc: "Nama lengkap ayah" },
|
||||
{ key: "nama_ibu", name: "Nama Ibu", desc: "Nama lengkap ibu" },
|
||||
{ key: "nama_anak", name: "Nama Anak", desc: "Nama bayi/anak" },
|
||||
{ key: "tanggal_lahir_anak", name: "Tanggal Lahir Anak", desc: "Tanggal lahir anak" },
|
||||
{ key: "pukul_lahir", name: "Pukul Lahir", desc: "Waktu kelahiran anak" },
|
||||
@@ -119,7 +120,17 @@ export const categoryPelayananSurat = [
|
||||
{ key: "jenis_kelamin", name: "Jenis Kelamin Anak", desc: "Jenis kelamin anak" },
|
||||
{ key: "anak_ke", name: "Anak Ke-", desc: "Urutan kelahiran anak" },
|
||||
{ key: "nik_ibu", name: "NIK Ibu", desc: "NIK ibu kandung" },
|
||||
{ key: "nama_ibu", name: "Nama Ibu", desc: "Nama lengkap ibu" },
|
||||
{ key: "tempat_lahir_ibu", name: "Tempat Lahir Ibu", desc: "Tempat lahir ibu kandung" },
|
||||
{ key: "tanggal_lahir_ibu", name: "Tanggal Lahir Ibu", desc: "Tanggal lahir ibu kandung" },
|
||||
{ key: "pekerjaan_ibu", name: "Pekerjaan Ibu", desc: "Pekerjaan ibu kandung" },
|
||||
{ key: "alamat_ibu", name: "Alamat Ibu", desc: "Alamat ibu kandung" },
|
||||
{ key: "nama_ayah", name: "Nama Ayah", desc: "Nama lengkap ayah" },
|
||||
{ key: "nik_ayah", name: "NIK Ayah", desc: "NIK ayah kandung" },
|
||||
{ key: "tempat_lahir_ayah", name: "Tempat Lahir Ayah", desc: "Tempat lahir ayah kandung" },
|
||||
{ key: "tanggal_lahir_ayah", name: "Tanggal Lahir Ayah", desc: "Tanggal lahir ayah kandung" },
|
||||
{ key: "pekerjaan_ayah", name: "Pekerjaan Ayah", desc: "Pekerjaan ayah kandung" },
|
||||
{ key: "alamat_ayah", name: "Alamat Ayah", desc: "Alamat ayah kandung" },
|
||||
{ key: "nama_pelapor", name: "Nama Pelapor", desc: "Nama pihak yang melaporkan" },
|
||||
{ key: "hubungan_pelapor", name: "Hubungan Pelapor", desc: "Hubungan pelapor dengan anak" },
|
||||
{ key: "alamat_pelapor", name: "Alamat Pelapor", desc: "Alamat pelapor" }
|
||||
@@ -144,7 +155,8 @@ export const categoryPelayananSurat = [
|
||||
dataPelengkap: [
|
||||
{ key: "nik", name: "NIK", desc: "Nomor Induk Kependudukan" },
|
||||
{ key: "nama", name: "Nama Lengkap", desc: "Nama sesuai KTP" },
|
||||
{ key: "ttl", name: "Tempat & Tanggal Lahir", desc: "Tempat dan tanggal lahir" },
|
||||
{ key: "tempat_lahir", name: "Tempat Lahir", desc: "Tempat lahir" },
|
||||
{ key: "tanggal_lahir", name: "Tanggal Lahir", desc: "Tanggal lahir" },
|
||||
{ key: "jenis_kelamin", name: "Jenis Kelamin", desc: "Jenis kelamin pemohon" },
|
||||
{ key: "agama", name: "Agama", desc: "Agama pemohon" },
|
||||
{ key: "alamat", name: "Alamat", desc: "Alamat tempat tinggal" },
|
||||
@@ -181,7 +193,8 @@ export const categoryPelayananSurat = [
|
||||
{ key: "hubungan_pelapor", name: "Hubungan dengan Almarhum", desc: "Hubungan pelapor dengan almarhum" },
|
||||
{ key: "nama_almarhum", name: "Nama Almarhum", desc: "Nama lengkap almarhum" },
|
||||
{ key: "nik_almarhum", name: "NIK Almarhum", desc: "Nomor Induk Kependudukan almarhum" },
|
||||
{ key: "ttl_almarhum", name: "Tempat & Tanggal Lahir Almarhum", desc: "Tempat dan tanggal lahir almarhum" },
|
||||
{ key: "tempat_lahir_almarhum", name: "Tempat Lahir Almarhum", desc: "Tempat lahir almarhum" },
|
||||
{ key: "tanggal_lahir_almarhum", name: "Tanggal Lahir Almarhum", desc: "Tanggal lahir almarhum" },
|
||||
{ key: "alamat_almarhum", name: "Alamat Almarhum", desc: "Alamat terakhir almarhum" },
|
||||
{ key: "agama_almarhum", name: "Agama Almarhum", desc: "Agama almarhum" },
|
||||
{ key: "tanggal_kematian", name: "Tanggal Kematian", desc: "Tanggal meninggal dunia" },
|
||||
@@ -213,7 +226,8 @@ export const categoryPelayananSurat = [
|
||||
dataText: [],
|
||||
dataPelengkap: [
|
||||
{ key: "nama", name: "Nama Lengkap", desc: "Nama pemohon" },
|
||||
{ key: "ttl", name: "Tempat & Tanggal Lahir", desc: "Tempat dan tanggal lahir" },
|
||||
{ key: "tempat_lahir", name: "Tempat Lahir", desc: "Tempat lahir" },
|
||||
{ key: "tanggal_lahir", name: "Tanggal Lahir", desc: "Tanggal lahir" },
|
||||
{ key: "jenis_kelamin", name: "Jenis Kelamin", desc: "Jenis kelamin pemohon" },
|
||||
{ key: "alamat", name: "Alamat", desc: "Alamat tempat tinggal" },
|
||||
{ key: "pekerjaan", name: "Pekerjaan", desc: "Pekerjaan pemohon/orang tua" },
|
||||
@@ -250,7 +264,8 @@ export const categoryPelayananSurat = [
|
||||
dataPelengkap: [
|
||||
{ key: "nik", name: "NIK", desc: "Nomor Induk Kependudukan" },
|
||||
{ key: "nama_pemilik", name: "Nama Pemilik", desc: "Nama pemilik usaha" },
|
||||
{ key: "ttl", name: "Tempat & Tanggal Lahir", desc: "Tempat dan tanggal lahir" },
|
||||
{ key: "tempat_lahir", name: "Tempat Lahir", desc: "Tempat lahir" },
|
||||
{ key: "tanggal_lahir", name: "Tanggal Lahir", desc: "Tanggal lahir" },
|
||||
{ key: "alamat_pemilik", name: "Alamat Pemilik", desc: "Alamat pemilik usaha" },
|
||||
{ key: "nama_usaha", name: "Nama Usaha", desc: "Nama usaha" },
|
||||
{ key: "bidang_usaha", name: "Bidang Usaha", desc: "Bidang atau jenis usaha" },
|
||||
@@ -289,9 +304,14 @@ export const categoryPelayananSurat = [
|
||||
desc: "Nama lengkap pemohon"
|
||||
},
|
||||
{
|
||||
key: "ttl",
|
||||
name: "Tempat & Tanggal Lahir",
|
||||
desc: "Tempat dan tanggal lahir pemohon"
|
||||
key: "tempat_lahir",
|
||||
name: "Tempat Lahir",
|
||||
desc: "Tempat lahir pemohon"
|
||||
},
|
||||
{
|
||||
key: "tanggal_lahir",
|
||||
name: "Tanggal Lahir",
|
||||
desc: "Tanggal lahir pemohon"
|
||||
},
|
||||
{
|
||||
key: "alamat",
|
||||
@@ -329,7 +349,8 @@ export const categoryPelayananSurat = [
|
||||
dataPelengkap: [
|
||||
{ key: "nama", name: "Nama Lengkap", desc: "Nama pemilik usaha" },
|
||||
{ key: "jenis_kelamin", name: "Jenis Kelamin", desc: "Jenis kelamin pemilik usaha" },
|
||||
{ key: "ttl", name: "Tempat & Tanggal Lahir", desc: "Tempat dan tanggal lahir" },
|
||||
{ key: "tempat_lahir", name: "Tempat Lahir", desc: "Tempat lahir" },
|
||||
{ key: "tanggal_lahir", name: "Tanggal Lahir", desc: "Tanggal lahir" },
|
||||
{ key: "negara", name: "Kewarganegaraan", desc: "Kewarganegaraan pemilik usaha" },
|
||||
{ key: "agama", name: "Agama", desc: "Agama pemilik usaha" },
|
||||
{ key: "status_perkawinan", name: "Status Perkawinan", desc: "Status perkawinan" },
|
||||
@@ -358,7 +379,8 @@ export const categoryPelayananSurat = [
|
||||
dataPelengkap: [
|
||||
{ key: "nik", name: "NIK", desc: "Nomor Induk Kependudukan" },
|
||||
{ key: "nama", name: "Nama Lengkap", desc: "Nama anak" },
|
||||
{ key: "ttl", name: "Tempat & Tanggal Lahir", desc: "Tempat dan tanggal lahir anak" },
|
||||
{ key: "tempat_lahir", name: "Tempat Lahir Anak", desc: "Tempat lahir anak" },
|
||||
{ key: "tanggal_lahir", name: "Tanggal Lahir Anak", desc: "Tanggal lahir anak" },
|
||||
{ key: "jenis_kelamin", name: "Jenis Kelamin", desc: "Jenis kelamin anak" },
|
||||
{ key: "alamat", name: "Alamat", desc: "Alamat tempat tinggal" },
|
||||
{ key: "pekerjaan", name: "Pekerjaan", desc: "Pekerjaan (jika ada)" },
|
||||
|
||||
@@ -246,16 +246,6 @@
|
||||
"label": "View Detail",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.tambah",
|
||||
"label": "Tambah",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.edit",
|
||||
"label": "Edit",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "setting.kategori_pelayanan.delete",
|
||||
"label": "Delete",
|
||||
|
||||
@@ -4,493 +4,543 @@ import SuccessPengajuan from "@/components/SuccessPengajuanSurat";
|
||||
import apiFetch from "@/lib/apiFetch";
|
||||
import { fromSlug, toSlug } from "@/server/lib/slug_converter";
|
||||
import {
|
||||
ActionIcon,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Container,
|
||||
Divider,
|
||||
FileInput,
|
||||
Flex,
|
||||
Grid,
|
||||
Group,
|
||||
Select,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip
|
||||
ActionIcon,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Container,
|
||||
Divider,
|
||||
FileInput,
|
||||
Flex,
|
||||
Grid,
|
||||
Group,
|
||||
Modal,
|
||||
Select,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
|
||||
import {
|
||||
IconBuildingCommunity,
|
||||
IconInfoCircle,
|
||||
IconUpload,
|
||||
IconUser
|
||||
IconBuildingCommunity,
|
||||
IconInfoCircle,
|
||||
IconUpload,
|
||||
IconUser,
|
||||
} from "@tabler/icons-react";
|
||||
import React, { useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import useSWR from "swr";
|
||||
|
||||
type DataItem = {
|
||||
key: string;
|
||||
value: string;
|
||||
key: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
type FormSurat = {
|
||||
kategoriId: string;
|
||||
nama: string;
|
||||
phone: string;
|
||||
dataPelengkap: DataItem[];
|
||||
syaratDokumen: DataItem[];
|
||||
kategoriId: string;
|
||||
nama: string;
|
||||
phone: string;
|
||||
dataPelengkap: DataItem[];
|
||||
syaratDokumen: DataItem[];
|
||||
};
|
||||
|
||||
|
||||
export default function FormSurat() {
|
||||
const [noPengajuan, setNoPengajuan] = useState("")
|
||||
const [submitLoading, setSubmitLoading] = useState(false)
|
||||
const navigate = useNavigate();
|
||||
const { search } = useLocation();
|
||||
const query = new URLSearchParams(search);
|
||||
const jenisSurat = query.get("jenis");
|
||||
const { data, mutate, isLoading } = useSWR("category-pelayanan-list", () =>
|
||||
apiFetch.api.pelayanan.category.get(),
|
||||
);
|
||||
const [jenisSuratFix, setJenisSuratFix] = useState({ name: "", id: "" });
|
||||
const [dataSurat, setDataSurat] = useState<any>({})
|
||||
const [formSurat, setFormSurat] = useState<FormSurat>({
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const [noPengajuan, setNoPengajuan] = useState("");
|
||||
const [submitLoading, setSubmitLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const { search } = useLocation();
|
||||
const query = new URLSearchParams(search);
|
||||
const jenisSurat = query.get("jenis");
|
||||
const { data, mutate, isLoading } = useSWR("category-pelayanan-list", () =>
|
||||
apiFetch.api.pelayanan.category.get(),
|
||||
);
|
||||
const [jenisSuratFix, setJenisSuratFix] = useState({ name: "", id: "" });
|
||||
const [dataSurat, setDataSurat] = useState<any>({});
|
||||
const [formSurat, setFormSurat] = useState<FormSurat>({
|
||||
nama: "",
|
||||
phone: "",
|
||||
kategoriId: "",
|
||||
dataPelengkap: [],
|
||||
syaratDokumen: [],
|
||||
});
|
||||
|
||||
const listCategory = data?.data || [];
|
||||
|
||||
function onResetAll() {
|
||||
setNoPengajuan("");
|
||||
setSubmitLoading(false);
|
||||
setFormSurat({
|
||||
nama: "",
|
||||
phone: "",
|
||||
kategoriId: "",
|
||||
dataPelengkap: [],
|
||||
syaratDokumen: [],
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const listCategory = data?.data || [];
|
||||
|
||||
function onResetAll() {
|
||||
setNoPengajuan("")
|
||||
setSubmitLoading(false)
|
||||
setFormSurat({
|
||||
nama: "",
|
||||
phone: "",
|
||||
kategoriId: "",
|
||||
dataPelengkap: [],
|
||||
syaratDokumen: [],
|
||||
})
|
||||
}
|
||||
|
||||
function onGetJenisSurat() {
|
||||
try {
|
||||
if (!jenisSurat || jenisSurat == "null") {
|
||||
setJenisSuratFix({ name: "", id: "" });
|
||||
} else {
|
||||
const namaJenis = fromSlug(jenisSurat);
|
||||
const data = listCategory.find((item: any) => item.name == namaJenis);
|
||||
if (!data) return;
|
||||
setJenisSuratFix(data);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function getDetailJenisSurat() {
|
||||
try {
|
||||
const get: any = await apiFetch.api.pelayanan.category.detail.get({
|
||||
query: {
|
||||
id: jenisSuratFix.id,
|
||||
},
|
||||
})
|
||||
|
||||
setDataSurat(get.data)
|
||||
setFormSurat({
|
||||
kategoriId: jenisSuratFix.id,
|
||||
nama: "",
|
||||
phone: "",
|
||||
dataPelengkap: (get.data?.dataPelengkap || []).map((item: { key: string }) => ({
|
||||
key: item.key,
|
||||
value: "",
|
||||
})),
|
||||
syaratDokumen: (get.data?.syaratDokumen || []).map(
|
||||
(item: { key: string }) => ({
|
||||
key: item.key,
|
||||
value: "",
|
||||
})
|
||||
),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useShallowEffect(() => {
|
||||
mutate();
|
||||
}, []);
|
||||
|
||||
|
||||
useShallowEffect(() => {
|
||||
if (listCategory.length > 0) {
|
||||
onGetJenisSurat();
|
||||
}
|
||||
}, [jenisSurat, listCategory]);
|
||||
|
||||
|
||||
useShallowEffect(() => {
|
||||
if (jenisSuratFix.id != "") {
|
||||
getDetailJenisSurat();
|
||||
}
|
||||
}, [jenisSuratFix.id]);
|
||||
|
||||
async function onSubmit() {
|
||||
const isFormKosong = Object.values(formSurat).some((value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return (
|
||||
value.length === 0 ||
|
||||
value.some(
|
||||
(item) => typeof item.value === "string" && item.value.trim() === ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
return value.trim() === ""
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
if (isFormKosong) {
|
||||
return notification({
|
||||
title: "Gagal",
|
||||
message: "Silahkan lengkapi form surat",
|
||||
type: "error",
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
setSubmitLoading(true)
|
||||
// 🔥 CLONE state SEKALI
|
||||
let finalFormSurat = structuredClone(formSurat)
|
||||
|
||||
// 2️⃣ Upload satu per satu
|
||||
for (const itemUpload of finalFormSurat.syaratDokumen) {
|
||||
const updImg = await apiFetch.api.pengaduan.upload.post({
|
||||
file: itemUpload.value,
|
||||
folder: "syarat-dokumen",
|
||||
})
|
||||
|
||||
if (updImg.status === 200) {
|
||||
// 🔥 UPDATE OBJECT LOKAL (BUKAN STATE)
|
||||
finalFormSurat.syaratDokumen = updateArrayByKey(
|
||||
finalFormSurat.syaratDokumen,
|
||||
itemUpload.key,
|
||||
updImg.data?.filename || ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ SET STATE SEKALI (optional, untuk UI)
|
||||
setFormSurat(finalFormSurat)
|
||||
|
||||
// 4️⃣ SUBMIT KE API
|
||||
const res = await apiFetch.api.pelayanan.create.post(finalFormSurat)
|
||||
|
||||
if (res.status === 200) {
|
||||
notification({
|
||||
title: "Berhasil",
|
||||
message: res.data?.message || "Pengajuan surat berhasil dibuat",
|
||||
type: "success",
|
||||
})
|
||||
} else {
|
||||
notification({
|
||||
title: "Gagal",
|
||||
message: "Pengajuan surat gagal dibuat, silahkan coba beberapa saat lagi",
|
||||
type: "error",
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
notification({
|
||||
title: "Gagal",
|
||||
message: "Server Error",
|
||||
type: "error"
|
||||
})
|
||||
} finally {
|
||||
setSubmitLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateArrayByKey(list: DataItem[], targetKey: string, value: string): DataItem[] {
|
||||
return list.map(item =>
|
||||
item.key === targetKey
|
||||
? { ...item, value }
|
||||
: item
|
||||
)
|
||||
}
|
||||
|
||||
function validationForm({ key, value }: { key: 'nama' | 'phone' | 'dataPelengkap' | 'syaratDokumen', value: any }) {
|
||||
if (key == "dataPelengkap" || key == "syaratDokumen") {
|
||||
setFormSurat(prev => ({
|
||||
...prev,
|
||||
[key]: updateArrayByKey(
|
||||
prev[key],
|
||||
value.key,
|
||||
value.value
|
||||
)
|
||||
}))
|
||||
function onGetJenisSurat() {
|
||||
try {
|
||||
if (!jenisSurat || jenisSurat == "null") {
|
||||
setJenisSuratFix({ name: "", id: "" });
|
||||
} else {
|
||||
setFormSurat({
|
||||
...formSurat,
|
||||
[key]: value,
|
||||
})
|
||||
const namaJenis = fromSlug(jenisSurat);
|
||||
const data = listCategory.find((item: any) => item.name == namaJenis);
|
||||
if (!data) return;
|
||||
setJenisSuratFix(data);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Container size="md" w={"100%"}>
|
||||
<FullScreenLoading visible={submitLoading} />
|
||||
{
|
||||
noPengajuan != "" &&
|
||||
<SuccessPengajuan noPengajuan={noPengajuan} onClose={() => { onResetAll(); navigate("/darmasaba/surat") }} />
|
||||
}
|
||||
<Box>
|
||||
async function getDetailJenisSurat() {
|
||||
try {
|
||||
const get: any = await apiFetch.api.pelayanan.category.detail.get({
|
||||
query: {
|
||||
id: jenisSuratFix.id,
|
||||
},
|
||||
});
|
||||
|
||||
setDataSurat(get.data);
|
||||
setFormSurat({
|
||||
kategoriId: jenisSuratFix.id,
|
||||
nama: "",
|
||||
phone: "",
|
||||
dataPelengkap: (get.data?.dataPelengkap || []).map(
|
||||
(item: { key: string }) => ({
|
||||
key: item.key,
|
||||
value: "",
|
||||
}),
|
||||
),
|
||||
syaratDokumen: (get.data?.syaratDokumen || []).map(
|
||||
(item: { key: string }) => ({
|
||||
key: item.key,
|
||||
value: "",
|
||||
}),
|
||||
),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
mutate();
|
||||
}, []);
|
||||
|
||||
useShallowEffect(() => {
|
||||
if (listCategory.length > 0) {
|
||||
onGetJenisSurat();
|
||||
}
|
||||
}, [jenisSurat, listCategory]);
|
||||
|
||||
useShallowEffect(() => {
|
||||
if (jenisSuratFix.id != "") {
|
||||
getDetailJenisSurat();
|
||||
}
|
||||
}, [jenisSuratFix.id]);
|
||||
|
||||
function onChecking() {
|
||||
const isFormKosong = Object.values(formSurat).some((value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return (
|
||||
value.length === 0 ||
|
||||
value.some(
|
||||
(item) =>
|
||||
typeof item.value === "string" && item.value.trim() === "",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
return value.trim() === "";
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (isFormKosong) {
|
||||
return notification({
|
||||
title: "Gagal",
|
||||
message: "Silahkan lengkapi form surat",
|
||||
type: "error",
|
||||
});
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
setSubmitLoading(true);
|
||||
// 🔥 CLONE state SEKALI
|
||||
let finalFormSurat = structuredClone(formSurat);
|
||||
|
||||
// 2️⃣ Upload satu per satu
|
||||
for (const itemUpload of finalFormSurat.syaratDokumen) {
|
||||
const updImg = await apiFetch.api.pengaduan.upload.post({
|
||||
file: itemUpload.value,
|
||||
folder: "syarat-dokumen",
|
||||
});
|
||||
|
||||
if (updImg.status === 200) {
|
||||
// 🔥 UPDATE OBJECT LOKAL (BUKAN STATE)
|
||||
finalFormSurat.syaratDokumen = updateArrayByKey(
|
||||
finalFormSurat.syaratDokumen,
|
||||
itemUpload.key,
|
||||
updImg.data?.filename || "",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ SET STATE SEKALI (optional, untuk UI)
|
||||
setFormSurat(finalFormSurat);
|
||||
|
||||
// 4️⃣ SUBMIT KE API
|
||||
const res = await apiFetch.api.pelayanan.create.post(finalFormSurat);
|
||||
|
||||
if (res.status === 200) {
|
||||
setNoPengajuan(res.data?.noPengajuan || "");
|
||||
} else {
|
||||
notification({
|
||||
title: "Gagal",
|
||||
message:
|
||||
"Pengajuan surat gagal dibuat, silahkan coba beberapa saat lagi",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
notification({
|
||||
title: "Gagal",
|
||||
message: "Server Error",
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setSubmitLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
function updateArrayByKey(
|
||||
list: DataItem[],
|
||||
targetKey: string,
|
||||
value: string,
|
||||
): DataItem[] {
|
||||
return list.map((item) =>
|
||||
item.key === targetKey ? { ...item, value } : item,
|
||||
);
|
||||
}
|
||||
|
||||
function validationForm({
|
||||
key,
|
||||
value,
|
||||
}: {
|
||||
key: "nama" | "phone" | "dataPelengkap" | "syaratDokumen";
|
||||
value: any;
|
||||
}) {
|
||||
if (key == "dataPelengkap" || key == "syaratDokumen") {
|
||||
setFormSurat((prev) => ({
|
||||
...prev,
|
||||
[key]: updateArrayByKey(prev[key], value.key, value.value),
|
||||
}));
|
||||
} else {
|
||||
setFormSurat({
|
||||
...formSurat,
|
||||
[key]: value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Container size="md" w={"100%"} pb={"lg"}>
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={close}
|
||||
title={"Konfirmasi"}
|
||||
overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Text>
|
||||
Apakah anda yakin ingin mengirim pengajuan surat ini?
|
||||
</Text>
|
||||
<Group justify="center" grow>
|
||||
<Button variant="light" onClick={close}>
|
||||
Tidak
|
||||
</Button>
|
||||
<Button
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
onSubmit();
|
||||
close();
|
||||
}}
|
||||
>
|
||||
Ya
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
<FullScreenLoading visible={submitLoading} />
|
||||
{noPengajuan != "" ? (
|
||||
<SuccessPengajuan
|
||||
noPengajuan={noPengajuan}
|
||||
onClose={() => {
|
||||
onResetAll();
|
||||
navigate("/darmasaba/surat");
|
||||
}}
|
||||
category="create"
|
||||
/>
|
||||
)
|
||||
:
|
||||
<Box>
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between" align="center">
|
||||
<Group align="center">
|
||||
<IconBuildingCommunity size={28} />
|
||||
<div>
|
||||
<Text fw={800} size="xl">
|
||||
Layanan Pengajuan Surat Administrasi
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
Formulir resmi untuk mengajukan berbagai jenis surat
|
||||
administrasi desa/kelurahan secara online.
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
<Group>
|
||||
<Badge radius="sm">Form Length: 3 Sections</Badge>
|
||||
</Group>
|
||||
</Group>
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between" align="center">
|
||||
<Group align="center">
|
||||
<IconBuildingCommunity size={28} />
|
||||
<div>
|
||||
<Text fw={800} size="xl">
|
||||
Layanan Pengajuan Surat Administrasi
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
Formulir resmi untuk mengajukan berbagai jenis surat administrasi desa/kelurahan secara online.
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
<Group>
|
||||
<Badge radius="sm">Form Length: 3 Sections</Badge>
|
||||
</Group>
|
||||
</Group>
|
||||
<Stack gap="lg">
|
||||
{/* Header Section */}
|
||||
{/* Header Section */}
|
||||
<FormSection
|
||||
title="Pemohon"
|
||||
icon={<IconUser size={16} />}
|
||||
description="Informasi identitas pemohon"
|
||||
>
|
||||
<Grid>
|
||||
<Grid.Col span={6}>
|
||||
<TextInput
|
||||
label={<FieldLabel label="Nama" hint="Nama pemohon" />}
|
||||
placeholder="Budi Setiawan"
|
||||
value={formSurat.nama}
|
||||
onChange={(e) =>
|
||||
validationForm({ key: "nama", value: e.target.value })
|
||||
}
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={6}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel
|
||||
label="Nomor Telephone"
|
||||
hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
|
||||
/>
|
||||
}
|
||||
placeholder="08123456789"
|
||||
value={formSurat.phone}
|
||||
onChange={(e) =>
|
||||
validationForm({ key: "phone", value: e.target.value })
|
||||
}
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={12}>
|
||||
<Select
|
||||
label={
|
||||
<FieldLabel
|
||||
label="Jenis Surat"
|
||||
hint="Jenis surat yang ingin diajukan"
|
||||
/>
|
||||
}
|
||||
placeholder="Pilih jenis surat"
|
||||
data={listCategory.map((item: any) => ({
|
||||
value: item.name,
|
||||
label: item.name,
|
||||
}))}
|
||||
value={jenisSuratFix.name}
|
||||
onChange={(value) => {
|
||||
const slug = toSlug(String(value));
|
||||
navigate("/darmasaba/surat?jenis=" + slug);
|
||||
}}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</FormSection>
|
||||
|
||||
{jenisSuratFix.id != "" && dataSurat && dataSurat.dataPelengkap && (
|
||||
<>
|
||||
<FormSection
|
||||
title="Pemohon"
|
||||
icon={<IconUser size={16} />}
|
||||
description="Informasi identitas pemohon"
|
||||
title="Data Pelengkap"
|
||||
description="Data pelengkap yang diperlukan"
|
||||
>
|
||||
<Grid>
|
||||
<Grid.Col span={6}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel
|
||||
label="Nama"
|
||||
hint="Nama pemohon"
|
||||
/>
|
||||
}
|
||||
placeholder="Budi Setiawan"
|
||||
value={formSurat.nama}
|
||||
onChange={(e) => validationForm({ key: "nama", value: e.target.value })}
|
||||
/>
|
||||
<Grid>
|
||||
{dataSurat.dataPelengkap.map((item: any, index: number) => (
|
||||
<Grid.Col span={6} key={index}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel label={item.name} hint={item.desc} />
|
||||
}
|
||||
placeholder={item.name}
|
||||
onChange={(e) =>
|
||||
validationForm({
|
||||
key: "dataPelengkap",
|
||||
value: { key: item.key, value: e.target.value },
|
||||
})
|
||||
}
|
||||
value={
|
||||
formSurat.dataPelengkap.find(
|
||||
(n: any) => n.key == item.key,
|
||||
)?.value
|
||||
}
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={6}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel
|
||||
label="Nomor Telephone"
|
||||
hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
|
||||
/>
|
||||
}
|
||||
placeholder="08123456789"
|
||||
value={formSurat.phone}
|
||||
onChange={(e) => validationForm({ key: "phone", value: e.target.value })}
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={12}>
|
||||
<Select
|
||||
label={<FieldLabel label="Jenis Surat" hint="Jenis surat yang ingin diajukan" />}
|
||||
placeholder="Pilih jenis surat"
|
||||
data={listCategory.map((item: any) => ({
|
||||
value: item.name,
|
||||
label: item.name,
|
||||
}))}
|
||||
value={jenisSuratFix.name}
|
||||
onChange={(value) => {
|
||||
const slug = toSlug(String(value))
|
||||
navigate("/darmasaba/surat?jenis=" + slug)
|
||||
}}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
|
||||
{
|
||||
jenisSuratFix.id != "" && dataSurat && dataSurat.dataPelengkap &&
|
||||
<>
|
||||
<FormSection
|
||||
title="Data Pelengkap"
|
||||
description="Data pelengkap yang diperlukan"
|
||||
>
|
||||
<Grid>
|
||||
{
|
||||
dataSurat.dataPelengkap.map((item: any, index: number) => (
|
||||
<Grid.Col span={6} key={index}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel
|
||||
label={item.name}
|
||||
hint={item.desc}
|
||||
/>
|
||||
}
|
||||
placeholder={item.name}
|
||||
onChange={(e) => validationForm({ key: "dataPelengkap", value: { key: item.key, value: e.target.value } })}
|
||||
value={formSurat.dataPelengkap.find((n: any) => n.key == item.key)?.value}
|
||||
/>
|
||||
</Grid.Col>
|
||||
))
|
||||
}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
<FormSection
|
||||
title="Syarat Dokumen"
|
||||
description="Syarat dokumen yang diperlukan"
|
||||
>
|
||||
<Grid>
|
||||
{dataSurat.syaratDokumen.map((item: any, index: number) => (
|
||||
<Grid.Col span={6} key={index}>
|
||||
<FileInputWrapper
|
||||
label={item.desc}
|
||||
placeholder={"Upload file "}
|
||||
accept="image/*,application/pdf"
|
||||
onChange={(file) =>
|
||||
validationForm({
|
||||
key: "syaratDokumen",
|
||||
value: { key: item.key, value: file },
|
||||
})
|
||||
}
|
||||
name={item.name}
|
||||
/>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
|
||||
<FormSection
|
||||
title="Syarat Dokumen"
|
||||
description="Syarat dokumen yang diperlukan"
|
||||
>
|
||||
<Grid>
|
||||
{
|
||||
dataSurat.syaratDokumen.map((item: any, index: number) => (
|
||||
<Grid.Col span={6} key={index}>
|
||||
<FileInputWrapper
|
||||
label={item.desc}
|
||||
placeholder={"Upload file "}
|
||||
accept="image/*,application/pdf"
|
||||
onChange={(file) => validationForm({ key: "syaratDokumen", value: { key: item.key, value: file } })}
|
||||
name={item.name}
|
||||
/>
|
||||
</Grid.Col>
|
||||
))
|
||||
}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
|
||||
{/* Actions */}
|
||||
<Group justify="right" mt="md">
|
||||
<Button variant="default" onClick={() => { }}>
|
||||
Reset
|
||||
</Button>
|
||||
<Button onClick={onSubmit}>Kirim</Button>
|
||||
</Group>
|
||||
</>
|
||||
|
||||
}
|
||||
</Stack>
|
||||
{/* Actions */}
|
||||
<Group justify="right" mt="md">
|
||||
{/* <Button variant="default" onClick={() => { }}>
|
||||
Reset
|
||||
</Button> */}
|
||||
<Button onClick={onChecking}>Kirim</Button>
|
||||
</Group>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
</Container>
|
||||
);
|
||||
</Stack>
|
||||
</Box>
|
||||
}
|
||||
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
|
||||
return (
|
||||
<Group justify="apart" gap="xs" align="center">
|
||||
<Text fw={600}>{label}</Text>
|
||||
{hint && (
|
||||
<Tooltip label={hint} withArrow>
|
||||
<ActionIcon size={24} variant="subtle">
|
||||
<IconInfoCircle size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Group>
|
||||
);
|
||||
return (
|
||||
<Group justify="apart" gap="xs" align="center">
|
||||
<Text fw={600}>{label}</Text>
|
||||
{hint && (
|
||||
<Tooltip label={hint} withArrow>
|
||||
<ActionIcon size={24} variant="subtle">
|
||||
<IconInfoCircle size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
function FormSection({
|
||||
title,
|
||||
icon,
|
||||
children,
|
||||
description,
|
||||
title,
|
||||
icon,
|
||||
children,
|
||||
description,
|
||||
}: {
|
||||
title: string;
|
||||
icon?: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
description?: string;
|
||||
title: string;
|
||||
icon?: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
description?: string;
|
||||
}) {
|
||||
return (
|
||||
<Card radius="md" shadow="sm" withBorder>
|
||||
<Group justify="apart" align="center" mb="xs">
|
||||
<Group align="center" gap="xs">
|
||||
{icon}
|
||||
<Text fw={700}>{title}</Text>
|
||||
</Group>
|
||||
{description && <Badge variant="light">{description}</Badge>}
|
||||
</Group>
|
||||
return (
|
||||
<Card radius="md" shadow="sm" withBorder>
|
||||
<Group justify="apart" align="center" mb="xs">
|
||||
<Group align="center" gap="xs">
|
||||
{icon}
|
||||
<Text fw={700}>{title}</Text>
|
||||
</Group>
|
||||
{description && <Badge variant="light">{description}</Badge>}
|
||||
</Group>
|
||||
|
||||
<Divider mb="sm" />
|
||||
<Stack gap="sm">{children}</Stack>
|
||||
</Card>
|
||||
);
|
||||
<Divider mb="sm" />
|
||||
<Stack gap="sm">{children}</Stack>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function FileInputWrapper({
|
||||
label,
|
||||
placeholder,
|
||||
accept,
|
||||
onChange,
|
||||
preview,
|
||||
name,
|
||||
description,
|
||||
label,
|
||||
placeholder,
|
||||
accept,
|
||||
onChange,
|
||||
preview,
|
||||
name,
|
||||
description,
|
||||
}: {
|
||||
label: string;
|
||||
placeholder?: string;
|
||||
accept?: string;
|
||||
onChange: (file: File | null) => void;
|
||||
preview?: string | null;
|
||||
name: string;
|
||||
description?: string;
|
||||
label: string;
|
||||
placeholder?: string;
|
||||
accept?: string;
|
||||
onChange: (file: File | null) => void;
|
||||
preview?: string | null;
|
||||
name: string;
|
||||
description?: string;
|
||||
}) {
|
||||
return (
|
||||
<Stack gap="xs">
|
||||
<Flex direction={"column"}>
|
||||
<Group justify="apart" align="center">
|
||||
<Text fw={500}>{label}</Text>
|
||||
</Group>
|
||||
{description && (
|
||||
<Text size="sm" c="dimmed" mt={4} style={{ lineHeight: 1.2 }}>
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
return (
|
||||
<Stack gap="xs">
|
||||
<Flex direction={"column"}>
|
||||
<Group justify="apart" align="center">
|
||||
<Text fw={500}>{label}</Text>
|
||||
</Group>
|
||||
{description && (
|
||||
<Text size="sm" c="dimmed" mt={4} style={{ lineHeight: 1.2 }}>
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
<FileInput
|
||||
accept={accept}
|
||||
placeholder={placeholder}
|
||||
onChange={(f) => onChange(f)}
|
||||
leftSection={<IconUpload />}
|
||||
aria-label={label}
|
||||
name={name}
|
||||
/>
|
||||
<FileInput
|
||||
accept={accept}
|
||||
placeholder={placeholder}
|
||||
onChange={(f) => onChange(f)}
|
||||
leftSection={<IconUpload />}
|
||||
aria-label={label}
|
||||
name={name}
|
||||
/>
|
||||
|
||||
{preview ? (
|
||||
<div>
|
||||
<Text size="xs" color="dimmed">
|
||||
Preview:
|
||||
</Text>
|
||||
{/* If preview is an image it will show; pdf preview might not render as image */}
|
||||
{/* Use <object> or <img> depending on file type — keep simple here */}
|
||||
<div style={{ marginTop: 6 }}>
|
||||
<img
|
||||
src={preview}
|
||||
alt={`${label} preview`}
|
||||
style={{ maxWidth: "200px", borderRadius: 4 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</Stack>
|
||||
);
|
||||
{preview ? (
|
||||
<div>
|
||||
<Text size="xs" color="dimmed">
|
||||
Preview:
|
||||
</Text>
|
||||
{/* If preview is an image it will show; pdf preview might not render as image */}
|
||||
{/* Use <object> or <img> depending on file type — keep simple here */}
|
||||
<div style={{ marginTop: 6 }}>
|
||||
<img
|
||||
src={preview}
|
||||
alt={`${label} preview`}
|
||||
style={{ maxWidth: "200px", borderRadius: 4 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
620
src/pages/darmasaba/update_data_surat.tsx
Normal file
620
src/pages/darmasaba/update_data_surat.tsx
Normal file
@@ -0,0 +1,620 @@
|
||||
import FullScreenLoading from "@/components/FullScreenLoading";
|
||||
import ModalFile from "@/components/ModalFile";
|
||||
import notification from "@/components/notificationGlobal";
|
||||
import SuccessPengajuan from "@/components/SuccessPengajuanSurat";
|
||||
import apiFetch from "@/lib/apiFetch";
|
||||
import {
|
||||
ActionIcon,
|
||||
Alert,
|
||||
Anchor,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Container,
|
||||
Divider,
|
||||
FileInput,
|
||||
Flex,
|
||||
Grid,
|
||||
Group,
|
||||
Modal,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip
|
||||
} from "@mantine/core";
|
||||
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
|
||||
import {
|
||||
IconBuildingCommunity,
|
||||
IconInfoCircle,
|
||||
IconUpload
|
||||
} from "@tabler/icons-react";
|
||||
import _ from "lodash";
|
||||
import React, { useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
type DataItem = {
|
||||
key: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
type UpdateDataItem = {
|
||||
id: string;
|
||||
key: string;
|
||||
value: any;
|
||||
};
|
||||
|
||||
type FormSurat = {
|
||||
kategoriId: string;
|
||||
nama: string;
|
||||
phone: string;
|
||||
dataPelengkap: DataItem[];
|
||||
syaratDokumen: DataItem[];
|
||||
};
|
||||
|
||||
type FormUpdateSurat = {
|
||||
dataPelengkap: UpdateDataItem[];
|
||||
syaratDokumen: UpdateDataItem[];
|
||||
};
|
||||
|
||||
type DataPengajuan = {
|
||||
id: string;
|
||||
noPengajuan: string;
|
||||
category: string;
|
||||
status: "antrian" | "diproses" | "selesai" | "ditolak";
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
idSurat: string | undefined;
|
||||
}
|
||||
|
||||
export default function UpdateDataSurat() {
|
||||
const navigate = useNavigate();
|
||||
const { search } = useLocation();
|
||||
const query = new URLSearchParams(search);
|
||||
const noPengajuan = query.get("pengajuan");
|
||||
|
||||
|
||||
return (
|
||||
<Container size="md" w={"100%"}>
|
||||
<Box>
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between" align="center" mt={"lg"}>
|
||||
<Group align="center">
|
||||
<IconBuildingCommunity size={28} />
|
||||
<div>
|
||||
<Text fw={800} size="xl">
|
||||
Update Data Pengajuan Surat Administrasi
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
Formulir ini digunakan untuk memperbarui data pengajuan surat administrasi yang telah diajukan sebelumnya.
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Group>
|
||||
<Stack gap="lg" mb="lg">
|
||||
{
|
||||
!noPengajuan ? (
|
||||
<SearchData />
|
||||
)
|
||||
:
|
||||
<DataUpdate noPengajuan={noPengajuan} />
|
||||
}
|
||||
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
|
||||
return (
|
||||
<Group justify="apart" gap="xs" align="center">
|
||||
<Text fw={600}>{label}</Text>
|
||||
{hint && (
|
||||
<Tooltip label={hint} withArrow>
|
||||
<ActionIcon size={24} variant="subtle">
|
||||
<IconInfoCircle size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
function FormSection({
|
||||
title,
|
||||
icon,
|
||||
children,
|
||||
description,
|
||||
info,
|
||||
}: {
|
||||
title?: string;
|
||||
icon?: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
description?: string;
|
||||
info?: string;
|
||||
}) {
|
||||
return (
|
||||
<Card radius="md" shadow="sm" withBorder>
|
||||
<Box mb="xs">
|
||||
<Group justify="apart" align="center">
|
||||
<Group align="center" gap="xs">
|
||||
{icon}
|
||||
{title && <Text fw={700}>{title}</Text>}
|
||||
</Group>
|
||||
{description && <Badge variant="light">{description}</Badge>}
|
||||
</Group>
|
||||
{info && <Text size="sm" c="dimmed">{info}</Text>}
|
||||
</Box>
|
||||
{
|
||||
title && <Divider mb="sm" />
|
||||
}
|
||||
<Stack gap="sm">{children}</Stack>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function FileInputWrapper({
|
||||
label,
|
||||
placeholder,
|
||||
accept,
|
||||
onChange,
|
||||
preview,
|
||||
name,
|
||||
description,
|
||||
linkView,
|
||||
disabled
|
||||
}: {
|
||||
label: string;
|
||||
placeholder?: string;
|
||||
accept?: string;
|
||||
linkView?: string;
|
||||
onChange: (file: File | null) => void;
|
||||
preview?: string | null;
|
||||
name: string;
|
||||
description?: string;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const [viewImg, setViewImg] = useState("");
|
||||
const [openedPreviewFile, setOpenedPreviewFile] = useState(false);
|
||||
|
||||
|
||||
useShallowEffect(() => {
|
||||
if (viewImg) {
|
||||
setOpenedPreviewFile(true);
|
||||
}
|
||||
}, [viewImg]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalFile
|
||||
open={openedPreviewFile && !_.isEmpty(viewImg)}
|
||||
onClose={() => {
|
||||
setOpenedPreviewFile(false);
|
||||
}}
|
||||
folder="syarat-dokumen"
|
||||
fileName={viewImg}
|
||||
/>
|
||||
|
||||
<Stack gap="xs">
|
||||
<Flex direction={"column"}>
|
||||
<Group justify="apart" align="center">
|
||||
<Text fw={500}>{label}</Text>
|
||||
</Group>
|
||||
{description && (
|
||||
<Text size="sm" c="dimmed" mt={4} style={{ lineHeight: 1.2 }}>
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
{
|
||||
linkView && (
|
||||
<Anchor onClick={() => setViewImg(linkView)} size="sm">
|
||||
Lihat dokumen sebelumnya
|
||||
</Anchor>
|
||||
)
|
||||
}
|
||||
</Flex>
|
||||
|
||||
<FileInput
|
||||
accept={accept}
|
||||
placeholder={placeholder}
|
||||
onChange={(f) => onChange(f)}
|
||||
leftSection={<IconUpload />}
|
||||
aria-label={label}
|
||||
name={name}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
{preview ? (
|
||||
<div>
|
||||
<Text size="xs" color="dimmed">
|
||||
Preview:
|
||||
</Text>
|
||||
<div style={{ marginTop: 6 }}>
|
||||
<img
|
||||
src={preview}
|
||||
alt={`${label} preview`}
|
||||
style={{ maxWidth: "200px", borderRadius: 4 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</Stack>
|
||||
</>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
function SearchData() {
|
||||
const [submitLoading, setSubmitLoading] = useState(false);
|
||||
const [searchPengajuan, setSearchPengajuan] = useState("");
|
||||
const [searchPengajuanPhone, setSearchPengajuanPhone] = useState("");
|
||||
const navigate = useNavigate();
|
||||
|
||||
async function handleSearch() {
|
||||
try {
|
||||
setSubmitLoading(true);
|
||||
if (searchPengajuan == "" || searchPengajuanPhone == "") {
|
||||
notification({
|
||||
title: "Peringatan",
|
||||
message: "Silakan isi nomor pengajuan atau nomor telephone",
|
||||
type: "warning"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await apiFetch.api.pelayanan["get-no-pengajuan"].post({
|
||||
phone: searchPengajuanPhone,
|
||||
noPengajuan: searchPengajuan
|
||||
});
|
||||
|
||||
if (response.status === 200) {
|
||||
if (response.data?.success) {
|
||||
navigate(`/darmasaba/update-data-surat?pengajuan=${response.data.nomer}`);
|
||||
} else {
|
||||
notification({
|
||||
title: "Peringatan",
|
||||
message: response.data?.message || "Data pengajuan tidak valid",
|
||||
type: "warning"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
notification({
|
||||
title: "Error",
|
||||
message: "Pengajuan tidak ditemukan atau gagal memuat data",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error searching:", error);
|
||||
notification({
|
||||
title: "Error",
|
||||
message: "Gagal mencari data pengajuan",
|
||||
type: "error"
|
||||
});
|
||||
} finally {
|
||||
setSubmitLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<FormSection
|
||||
title="Cari Pengajuan Surat"
|
||||
info="Masukkan nomor pengajuan dan nomor telepon yang digunakan saat pengajuan surat."
|
||||
>
|
||||
<Grid>
|
||||
<Grid.Col span={6}>
|
||||
<TextInput
|
||||
label={<FieldLabel label="Nomor Pengajuan" hint="Nomor pengajuan surat" />}
|
||||
placeholder="PS-2025-000123"
|
||||
onChange={(e) => { setSearchPengajuan(e.target.value) }}
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={6}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel
|
||||
label="Nomor Telephone"
|
||||
hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
|
||||
/>
|
||||
}
|
||||
placeholder="08123456789"
|
||||
type="number"
|
||||
onChange={(e) => { setSearchPengajuanPhone(e.target.value) }}
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={12}>
|
||||
<Button fullWidth variant="light" color="blue" onClick={() => { handleSearch() }} loading={submitLoading}>
|
||||
Cari Pengajuan
|
||||
</Button>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</FormSection>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
function DataUpdate({ noPengajuan }: { noPengajuan: string }) {
|
||||
const [opened, { open, close }] = useDisclosure(false)
|
||||
const navigate = useNavigate()
|
||||
const [sukses, setSukses] = useState(false)
|
||||
const [submitLoading, setSubmitLoading] = useState(false)
|
||||
const [dataPelengkap, setDataPelengkap] = useState<DataItem[]>([])
|
||||
const [dataSyaratDokumen, setDataSyaratDokumen] = useState<DataItem[]>([])
|
||||
const [dataPengajuan, setDataPengajuan] = useState<DataPengajuan | {}>({})
|
||||
const [status, setStatus] = useState("")
|
||||
const [formSurat, setFormSurat] = useState<FormUpdateSurat>({
|
||||
dataPelengkap: [],
|
||||
syaratDokumen: [],
|
||||
});
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
const res = await apiFetch.api.pelayanan["detail-data"].post({ nomerPengajuan: noPengajuan });
|
||||
if (res.data && res.data.success === true) {
|
||||
setDataPelengkap(res.data.dataPelengkap || []);
|
||||
setDataSyaratDokumen(res.data.syaratDokumen || []);
|
||||
setDataPengajuan(res.data.pengajuan || {});
|
||||
|
||||
setStatus(res.data.pengajuan && 'status' in res.data.pengajuan ? res.data.pengajuan.status : "");
|
||||
} else {
|
||||
notification({
|
||||
title: "Error",
|
||||
message: res.data?.message || "Gagal memuat data",
|
||||
type: "error",
|
||||
});
|
||||
setDataPelengkap([]);
|
||||
setDataSyaratDokumen([]);
|
||||
setDataPengajuan({});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
function upsertById<T extends { id: string }>(
|
||||
array: T[],
|
||||
item: T
|
||||
): T[] {
|
||||
const index = array.findIndex((v) => v.id === item.id)
|
||||
|
||||
// ➕ insert
|
||||
if (index === -1) {
|
||||
return [...array, item]
|
||||
}
|
||||
|
||||
// ✏️ update
|
||||
return array.map((v, i) => (i === index ? { ...v, ...item } : v))
|
||||
}
|
||||
|
||||
|
||||
function validationForm({
|
||||
kategori,
|
||||
value,
|
||||
}: {
|
||||
kategori: "dataPelengkap" | "syaratDokumen";
|
||||
value: UpdateDataItem;
|
||||
}) {
|
||||
setFormSurat((prev) => ({
|
||||
...prev,
|
||||
[kategori]: upsertById(prev[kategori], {
|
||||
id: value.id,
|
||||
key: value.key,
|
||||
value: value.value
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
function updateArrayByKey(
|
||||
list: UpdateDataItem[],
|
||||
id: string,
|
||||
value: any,
|
||||
): UpdateDataItem[] {
|
||||
return list.map((item) =>
|
||||
item.id === id ? { ...item, value } : item,
|
||||
);
|
||||
}
|
||||
|
||||
function onChecking() {
|
||||
if (formSurat.dataPelengkap.length == 0 && formSurat.syaratDokumen.length == 0)
|
||||
return notification({
|
||||
title: "Peringatan",
|
||||
message: "Tidak ada data yang diupdate",
|
||||
type: "warning",
|
||||
});
|
||||
const isFormKosong = Object.values(formSurat).some((value: UpdateDataItem[] | string) => {
|
||||
if (Array.isArray(value)) {
|
||||
return (
|
||||
value.some(
|
||||
(item) =>
|
||||
typeof item.value === "string" && item.value.trim() === "",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
return value.trim() === "";
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (isFormKosong) {
|
||||
return notification({
|
||||
title: "Gagal",
|
||||
message: "Silahkan lengkapi form surat",
|
||||
type: "error",
|
||||
});
|
||||
} else {
|
||||
open()
|
||||
}
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
setSubmitLoading(true);
|
||||
// 🔥 CLONE state SEKALI
|
||||
let finalFormSurat = structuredClone(formSurat);
|
||||
|
||||
// 2️⃣ Upload satu per satu
|
||||
for (const itemUpload of finalFormSurat.syaratDokumen) {
|
||||
const updImg = await apiFetch.api.pengaduan.upload.post({
|
||||
file: itemUpload.value,
|
||||
folder: "syarat-dokumen",
|
||||
});
|
||||
|
||||
if (updImg.status === 200) {
|
||||
// 🔥 UPDATE OBJECT LOKAL (BUKAN STATE)
|
||||
finalFormSurat.syaratDokumen = updateArrayByKey(
|
||||
finalFormSurat.syaratDokumen,
|
||||
itemUpload.id,
|
||||
updImg.data?.filename || "",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ SET STATE SEKALI (optional, untuk UI)
|
||||
setFormSurat(finalFormSurat);
|
||||
|
||||
// 4️⃣ SUBMIT KE API
|
||||
const res = await apiFetch.api.pelayanan.update.post({
|
||||
id: dataPengajuan && ('id' in dataPengajuan) ? dataPengajuan.id : "",
|
||||
dataPelengkap: finalFormSurat.dataPelengkap,
|
||||
syaratDokumen: finalFormSurat.syaratDokumen,
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
setSukses(true);
|
||||
} else {
|
||||
notification({
|
||||
title: "Gagal",
|
||||
message:
|
||||
"Pengajuan surat gagal dibuat, silahkan coba beberapa saat lagi",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
notification({
|
||||
title: "Gagal",
|
||||
message: "Server Error",
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setSubmitLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<FullScreenLoading visible={submitLoading} />
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={close}
|
||||
title={"Konfirmasi"}
|
||||
overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Text>
|
||||
Apakah anda yakin ingin mengupdate pengajuan surat ini?
|
||||
</Text>
|
||||
<Group justify="center" grow>
|
||||
<Button variant="light" onClick={close}>
|
||||
Tidak
|
||||
</Button>
|
||||
<Button
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
onSubmit();
|
||||
close();
|
||||
}}
|
||||
>
|
||||
Ya
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
{
|
||||
sukses ?
|
||||
<SuccessPengajuan
|
||||
noPengajuan={noPengajuan}
|
||||
onClose={() => {
|
||||
navigate("/darmasaba/update-data-surat");
|
||||
}}
|
||||
category="update"
|
||||
/>
|
||||
:
|
||||
<>
|
||||
{
|
||||
(status != "ditolak" && status != "antrian")
|
||||
&& <Alert variant="light" color="yellow" radius="lg" title={`Data pengajuan surat ini tidak dapat diupdate karena berstatus ${status}.`} icon={<span style={{ fontSize: '1.2rem' }}>⚠</span>} />
|
||||
}
|
||||
<FormSection
|
||||
title="Data Pelengkap"
|
||||
description="Data pelengkap yang diperlukan"
|
||||
>
|
||||
<Grid>
|
||||
{dataPelengkap.map((item: any, index: number) => (
|
||||
<Grid.Col span={6} key={index}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel label={item.name} hint={item.desc} />
|
||||
}
|
||||
placeholder={item.name}
|
||||
onChange={(e) =>
|
||||
validationForm({
|
||||
kategori: "dataPelengkap",
|
||||
value: { id: item.id, key: item.key, value: e.target.value },
|
||||
})
|
||||
}
|
||||
value={formSurat.dataPelengkap.find((n) => n.id === item.id)?.value ?? dataPelengkap.find((n: any) => n.key == item.key,)?.value}
|
||||
disabled={status != "ditolak" && status != "antrian"}
|
||||
/>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
|
||||
<FormSection
|
||||
title="Syarat Dokumen"
|
||||
description="Syarat dokumen yang diperlukan"
|
||||
>
|
||||
<Grid>
|
||||
{dataSyaratDokumen.map((item: any, index: number) => (
|
||||
<Grid.Col span={6} key={index}>
|
||||
<FileInputWrapper
|
||||
label={item.desc}
|
||||
placeholder={"Upload file terbaru untuk mengupdate"}
|
||||
accept="image/*,application/pdf"
|
||||
linkView={item.value}
|
||||
onChange={(file) =>
|
||||
validationForm({
|
||||
kategori: "syaratDokumen",
|
||||
value: { id: item.id, key: item.key, value: file },
|
||||
})
|
||||
}
|
||||
name={item.name}
|
||||
disabled={status != "ditolak" && status != "antrian"}
|
||||
/>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
|
||||
<Group justify="right" mt="md">
|
||||
<Button onClick={() => { onChecking() }}>Kirim</Button>
|
||||
</Group>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
Group,
|
||||
List,
|
||||
Modal,
|
||||
Spoiler,
|
||||
Stack,
|
||||
Table,
|
||||
Text,
|
||||
@@ -432,41 +433,43 @@ function DetailDataHistori({ data }: { data: any }) {
|
||||
<Stack gap="md">
|
||||
<Flex align="center" justify="space-between">
|
||||
<Title order={4} c="gray.2">
|
||||
Histori Pengajuan Surat
|
||||
Riwayat Pengajuan Surat
|
||||
</Title>
|
||||
</Flex>
|
||||
<Divider my={0} />
|
||||
<Table>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>Tanggal</Table.Th>
|
||||
<Table.Th>Deskripsi</Table.Th>
|
||||
<Table.Th>Status</Table.Th>
|
||||
<Table.Th>User</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{data?.map((item: any) => (
|
||||
<Table.Tr key={item.id}>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.createdAt.toLocaleString("id-ID", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
})}
|
||||
</Table.Td>
|
||||
<Table.Td>{item.deskripsi}</Table.Td>
|
||||
<Table.Td>{item.status}</Table.Td>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.nameUser ? item.nameUser : "-"}
|
||||
</Table.Td>
|
||||
<Spoiler maxHeight={200} showLabel="Show more" hideLabel="Hide" transitionDuration={1000}>
|
||||
<Table>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>Tanggal</Table.Th>
|
||||
<Table.Th>Deskripsi</Table.Th>
|
||||
<Table.Th>Status</Table.Th>
|
||||
<Table.Th>User</Table.Th>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{data?.map((item: any) => (
|
||||
<Table.Tr key={item.id}>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.createdAt.toLocaleString("id-ID", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
})}
|
||||
</Table.Td>
|
||||
<Table.Td>{item.deskripsi}</Table.Td>
|
||||
<Table.Td>{item.status}</Table.Td>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.nameUser ? item.nameUser : "-"}
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Spoiler>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
Grid,
|
||||
Group,
|
||||
Modal,
|
||||
Spoiler,
|
||||
Stack,
|
||||
Table,
|
||||
Text,
|
||||
@@ -420,41 +421,43 @@ function DetailDataHistori({ data }: { data: any }) {
|
||||
<Stack gap="md">
|
||||
<Flex align="center" justify="space-between">
|
||||
<Title order={4} c="gray.2">
|
||||
Histori Pengaduan
|
||||
Riwayat Pengaduan
|
||||
</Title>
|
||||
</Flex>
|
||||
<Divider my={0} />
|
||||
<Table>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>Tanggal</Table.Th>
|
||||
<Table.Th>Deskripsi</Table.Th>
|
||||
<Table.Th>Status</Table.Th>
|
||||
<Table.Th>User</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{data?.map((item: any) => (
|
||||
<Table.Tr key={item.id}>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.createdAt.toLocaleString("id-ID", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
})}
|
||||
</Table.Td>
|
||||
<Table.Td>{item.deskripsi}</Table.Td>
|
||||
<Table.Td>{item.status}</Table.Td>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.nameUser ? item.nameUser : "-"}
|
||||
</Table.Td>
|
||||
<Spoiler maxHeight={200} showLabel="Show more" hideLabel="Hide" transitionDuration={1000}>
|
||||
<Table>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>Tanggal</Table.Th>
|
||||
<Table.Th>Deskripsi</Table.Th>
|
||||
<Table.Th>Status</Table.Th>
|
||||
<Table.Th>User</Table.Th>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{data?.map((item: any) => (
|
||||
<Table.Tr key={item.id}>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.createdAt.toLocaleString("id-ID", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
})}
|
||||
</Table.Td>
|
||||
<Table.Td>{item.deskripsi}</Table.Td>
|
||||
<Table.Td>{item.status}</Table.Td>
|
||||
<Table.Td style={{ whiteSpace: "nowrap" }}>
|
||||
{item.nameUser ? item.nameUser : "-"}
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Spoiler>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getLastUpdated } from "../lib/get-last-updated"
|
||||
import { generateNoPengajuanSurat } from "../lib/no-pengajuan-surat"
|
||||
import { isValidPhone, normalizePhoneNumber } from "../lib/normalizePhone"
|
||||
import { prisma } from "../lib/prisma"
|
||||
import { toSlug } from "../lib/slug_converter"
|
||||
|
||||
|
||||
const PelayananRoute = new Elysia({
|
||||
@@ -20,9 +21,21 @@ const PelayananRoute = new Elysia({
|
||||
},
|
||||
orderBy: {
|
||||
name: "asc"
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
syaratDokumen: true,
|
||||
dataPelengkap: true,
|
||||
}
|
||||
})
|
||||
return data
|
||||
|
||||
const dataFix = data.map(item => ({
|
||||
...item,
|
||||
link: `${process.env.BUN_PUBLIC_BASE_URL}/darmasaba/surat?jenis=${toSlug(item.name)}`
|
||||
}));
|
||||
|
||||
return dataFix
|
||||
}, {
|
||||
detail: {
|
||||
summary: "List Kategori Pelayanan Surat",
|
||||
@@ -215,7 +228,7 @@ const PelayananRoute = new Elysia({
|
||||
select: {
|
||||
name: true,
|
||||
syaratDokumen: true,
|
||||
dataPelengkap:true
|
||||
dataPelengkap: true
|
||||
}
|
||||
},
|
||||
Warga: {
|
||||
@@ -299,15 +312,29 @@ const PelayananRoute = new Elysia({
|
||||
key: string;
|
||||
}[];
|
||||
|
||||
const dataTextFix = dataText.map((item) => {
|
||||
const nama = dataTextCategory.find((v) => v.key == item.jenis)?.name
|
||||
return {
|
||||
id: item.id,
|
||||
jenis: nama,
|
||||
value: item.value,
|
||||
}
|
||||
})
|
||||
const refMap = new Map(
|
||||
dataTextCategory.map((v, i) => [
|
||||
v.key,
|
||||
{ ...v, order: i }
|
||||
])
|
||||
);
|
||||
|
||||
const dataTextFix = dataText
|
||||
.map((item) => {
|
||||
const ref = refMap.get(item.jenis);
|
||||
const nama = dataTextCategory.find((v) => v.key == item.jenis)?.name
|
||||
return {
|
||||
id: item.id,
|
||||
jenis: nama,
|
||||
value: item.value,
|
||||
order: ref?.order ?? Infinity,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.order - b.order)
|
||||
.map(({ order, ...rest }) => rest); // hapus order
|
||||
|
||||
|
||||
console.log(dataTextFix)
|
||||
const dataHistory = await prisma.historyPelayanan.findMany({
|
||||
where: {
|
||||
idPengajuanLayanan: data?.id,
|
||||
@@ -323,6 +350,9 @@ const PelayananRoute = new Elysia({
|
||||
name: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc"
|
||||
}
|
||||
})
|
||||
|
||||
@@ -477,7 +507,7 @@ const PelayananRoute = new Elysia({
|
||||
}
|
||||
})
|
||||
|
||||
return { success: true, message: 'Pengajuan layanan surat sudah dibuat dengan nomer ' + noPengajuan + ', nomer ini akan digunakan untuk mengakses pengajuan ini' }
|
||||
return { success: true, message: 'Pengajuan layanan surat sudah dibuat dengan nomer ' + noPengajuan + ', nomer ini akan digunakan untuk mengakses pengajuan ini', noPengajuan }
|
||||
}, {
|
||||
body: t.Object({
|
||||
kategoriId: t.String({
|
||||
@@ -575,7 +605,7 @@ const PelayananRoute = new Elysia({
|
||||
CategoryPelayanan: {
|
||||
select: {
|
||||
name: true,
|
||||
dataText: true,
|
||||
dataPelengkap: true,
|
||||
syaratDokumen: true,
|
||||
}
|
||||
},
|
||||
@@ -595,7 +625,15 @@ const PelayananRoute = new Elysia({
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return { success: false, message: "Data tidak ditemukan" }
|
||||
return {
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
pengajuan: {},
|
||||
history: [],
|
||||
warga: {},
|
||||
syaratDokumen: [],
|
||||
dataPelengkap: [],
|
||||
}
|
||||
}
|
||||
|
||||
const dataSurat = await prisma.suratPelayanan.findFirst({
|
||||
@@ -621,7 +659,7 @@ const PelayananRoute = new Elysia({
|
||||
}
|
||||
})
|
||||
|
||||
const dataText = await prisma.dataTextPelayanan.findMany({
|
||||
const dataPelengkap = await prisma.dataTextPelayanan.findMany({
|
||||
where: {
|
||||
idPengajuanLayanan: data?.id,
|
||||
isActive: true
|
||||
@@ -635,25 +673,50 @@ const PelayananRoute = new Elysia({
|
||||
const syaratDokumen = (data?.CategoryPelayanan?.syaratDokumen ?? []) as {
|
||||
name: string;
|
||||
desc: string;
|
||||
key: string;
|
||||
}[];
|
||||
|
||||
const dataSyaratFix = dataSyarat.map((item) => {
|
||||
// const desc = syaratDokumen.find((v) => v.name == item.jenis)?.desc
|
||||
const desc = syaratDokumen.find((v) => v.key == item.jenis)?.desc
|
||||
const name = syaratDokumen.find((v) => v.key == item.jenis)?.name
|
||||
return {
|
||||
id: item.id,
|
||||
jenis: item.jenis,
|
||||
key: item.jenis,
|
||||
value: item.value,
|
||||
name: name ?? '',
|
||||
desc: desc ?? ''
|
||||
}
|
||||
})
|
||||
|
||||
const dataTextFix = dataText.map((item) => {
|
||||
// const desc = data?.CategoryPelayanan?.dataText.find((v) => v == item.jenis)
|
||||
return {
|
||||
id: item.id,
|
||||
jenis: item.jenis,
|
||||
value: item.value,
|
||||
}
|
||||
})
|
||||
const dataPelengkapList = (data?.CategoryPelayanan?.dataPelengkap ?? []) as {
|
||||
name: string;
|
||||
desc: string;
|
||||
key: string;
|
||||
}[];
|
||||
|
||||
const refMap = new Map(
|
||||
dataPelengkapList.map((v, i) => [
|
||||
v.key,
|
||||
{ ...v, order: i }
|
||||
])
|
||||
);
|
||||
|
||||
const dataTextFix = dataPelengkap
|
||||
.map((item) => {
|
||||
const ref = refMap.get(item.jenis);
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
key: item.jenis,
|
||||
value: item.value,
|
||||
desc: ref?.desc ?? "",
|
||||
name: ref?.name ?? "",
|
||||
order: ref?.order ?? Infinity,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.order - b.order)
|
||||
.map(({ order, ...rest }) => rest); // hapus order
|
||||
|
||||
|
||||
const dataHistory = await prisma.historyPelayanan.findMany({
|
||||
where: {
|
||||
@@ -702,14 +765,15 @@ const PelayananRoute = new Elysia({
|
||||
}
|
||||
|
||||
const datafix = {
|
||||
success: true,
|
||||
message: 'sukses',
|
||||
pengajuan: dataPengajuan,
|
||||
history: dataHistoryFix,
|
||||
warga: warga,
|
||||
syaratDokumen: dataSyaratFix,
|
||||
dataText: dataTextFix,
|
||||
dataPelengkap: dataTextFix,
|
||||
}
|
||||
|
||||
|
||||
return datafix
|
||||
|
||||
}, {
|
||||
@@ -786,12 +850,12 @@ const PelayananRoute = new Elysia({
|
||||
}
|
||||
})
|
||||
.post("/update", async ({ body }) => {
|
||||
const { nomerPengajuan, syaratDokumen, dataText } = body
|
||||
const { id, syaratDokumen, dataPelengkap } = body
|
||||
let dataUpdate = []
|
||||
|
||||
const pengajuan = await prisma.pelayananAjuan.findFirst({
|
||||
const pengajuan = await prisma.pelayananAjuan.findUnique({
|
||||
where: {
|
||||
noPengajuan: nomerPengajuan,
|
||||
id
|
||||
}
|
||||
})
|
||||
|
||||
@@ -804,29 +868,16 @@ const PelayananRoute = new Elysia({
|
||||
return { success: false, message: 'pengajuan surat tidak dapat diupdate karena status ' + pengajuan.status }
|
||||
}
|
||||
|
||||
if (dataText && dataText.length > 0) {
|
||||
for (const item of dataText) {
|
||||
dataUpdate.push(item.jenis)
|
||||
const hasil = await prisma.dataTextPelayanan.findFirst({
|
||||
where: {
|
||||
idPengajuanLayanan: pengajuan.id,
|
||||
jenis: item.jenis,
|
||||
}
|
||||
})
|
||||
if (dataPelengkap && dataPelengkap.length > 0) {
|
||||
for (const item of dataPelengkap) {
|
||||
dataUpdate.push(item.key)
|
||||
|
||||
|
||||
const upd = await prisma.dataTextPelayanan.upsert({
|
||||
const upd = await prisma.dataTextPelayanan.update({
|
||||
where: {
|
||||
id: hasil?.id
|
||||
id: item.id
|
||||
},
|
||||
update: {
|
||||
data: {
|
||||
value: item.value,
|
||||
},
|
||||
create: {
|
||||
value: item.value,
|
||||
jenis: item.jenis,
|
||||
idPengajuanLayanan: pengajuan.id,
|
||||
idCategory: pengajuan.idCategory,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -849,34 +900,15 @@ const PelayananRoute = new Elysia({
|
||||
|
||||
if (syaratDokumen && syaratDokumen.length > 0) {
|
||||
for (const item of syaratDokumen) {
|
||||
const pilih = syarat?.find((cat) => cat.desc.toLowerCase() == item.jenis.toLowerCase() || cat.name.toLowerCase() == item.jenis.toLowerCase())?.name;
|
||||
dataUpdate.push(pilih)
|
||||
|
||||
const hasil = await prisma.syaratDokumenPelayanan.findFirst({
|
||||
dataUpdate.push(item.key)
|
||||
const upd = await prisma.syaratDokumenPelayanan.update({
|
||||
where: {
|
||||
idPengajuanLayanan: pengajuan.id,
|
||||
jenis: pilih,
|
||||
id: item.id
|
||||
},
|
||||
data: {
|
||||
value: item.value,
|
||||
}
|
||||
})
|
||||
|
||||
if (hasil && hasil.id) {
|
||||
const upd = await prisma.syaratDokumenPelayanan.upsert({
|
||||
where: {
|
||||
id: hasil.id
|
||||
},
|
||||
update: {
|
||||
value: item.value,
|
||||
},
|
||||
create: {
|
||||
value: item.value,
|
||||
jenis: hasil.jenis,
|
||||
idPengajuanLayanan: pengajuan.id,
|
||||
idCategory: pengajuan.idCategory,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return { success: false, message: 'dokumen tidak dapat diupload' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,16 +938,20 @@ const PelayananRoute = new Elysia({
|
||||
|
||||
}, {
|
||||
body: t.Object({
|
||||
nomerPengajuan: t.String({
|
||||
error: "nomer pengajuan harus diisi",
|
||||
description: "Nomer pengajuan yang ingin diupdate"
|
||||
id: t.String({
|
||||
error: "id harus diisi",
|
||||
description: "ID yang ingin diupdate"
|
||||
}),
|
||||
dataText: t.Optional(t.Array(
|
||||
dataPelengkap: t.Optional(t.Array(
|
||||
t.Object({
|
||||
jenis: t.String({
|
||||
description: "Jenis field yang dibutuhkan oleh kategori pelayanan. Biasanya dinamis.",
|
||||
id: t.String({
|
||||
description: "ID Data Pelengkap.",
|
||||
error: "id harus diisi"
|
||||
}),
|
||||
key: t.String({
|
||||
description: "Key field yang dibutuhkan oleh kategori pelayanan. Biasanya dinamis.",
|
||||
examples: ["nama", "jenis kelamin", "tempat tanggal lahir", "negara", "agama", "status perkawinan", "alamat", "pekerjaan", "jenis usaha", "alamat usaha"],
|
||||
error: "jenis harus diisi"
|
||||
error: "key harus diisi"
|
||||
}),
|
||||
value: t.String({
|
||||
description: "Isi atau nilai dari jenis field terkait.",
|
||||
@@ -927,26 +963,30 @@ const PelayananRoute = new Elysia({
|
||||
description: "Kumpulan data text dinamis sesuai kategori layanan.",
|
||||
examples: [
|
||||
[
|
||||
{ jenis: "nama", value: "Budi Santoso" },
|
||||
{ jenis: "jenis kelamin", value: "Laki-laki" },
|
||||
{ jenis: "tempat tanggal lahir", value: "Denpasar, 28 Februari 1990" },
|
||||
{ jenis: "negara", value: "Indonesia" },
|
||||
{ jenis: "agama", value: "Islam" },
|
||||
{ jenis: "status perkawinan", value: "Belum menikah" },
|
||||
{ jenis: "alamat", value: "Jl. Mawar No. 10" },
|
||||
{ jenis: "pekerjaan", value: "Karyawan Swasta" },
|
||||
{ jenis: "jenis usaha", value: "usaha makanan" },
|
||||
{ jenis: "alamat usaha", value: "Jl. Melati No. 21" },
|
||||
{ id: "1", key: "nama", value: "Budi Santoso" },
|
||||
{ id: "2", key: "jenis kelamin", value: "Laki-laki" },
|
||||
{ id: "3", key: "tempat tanggal lahir", value: "Denpasar, 28 Februari 1990" },
|
||||
{ id: "4", key: "negara", value: "Indonesia" },
|
||||
{ id: "5", key: "agama", value: "Islam" },
|
||||
{ id: "6", key: "status perkawinan", value: "Belum menikah" },
|
||||
{ id: "7", key: "alamat", value: "Jl. Mawar No. 10" },
|
||||
{ id: "8", key: "pekerjaan", value: "Karyawan Swasta" },
|
||||
{ id: "9", key: "jenis usaha", value: "usaha makanan" },
|
||||
{ id: "10", key: "alamat usaha", value: "Jl. Melati No. 21" },
|
||||
]
|
||||
],
|
||||
}
|
||||
)),
|
||||
syaratDokumen: t.Optional(t.Array(
|
||||
t.Object({
|
||||
jenis: t.String({
|
||||
description: "Jenis dokumen persyaratan yang diminta oleh kategori layanan.",
|
||||
id: t.String({
|
||||
description: "ID syarat dokumen",
|
||||
error: "id harus diisi"
|
||||
}),
|
||||
key: t.String({
|
||||
description: "Key dokumen persyaratan yang diminta oleh kategori layanan.",
|
||||
examples: ["ktp", "kk", "surat_pengantar_rt"],
|
||||
error: "jenis harus diisi"
|
||||
error: "key harus diisi"
|
||||
}),
|
||||
value: t.String({
|
||||
description: "Nama file atau identifier file dokumen yang diupload.",
|
||||
@@ -958,9 +998,9 @@ const PelayananRoute = new Elysia({
|
||||
description: "Kumpulan dokumen yang wajib diupload sesuai persyaratan layanan.",
|
||||
examples: [
|
||||
[
|
||||
{ jenis: "pengantar kelian", value: "pengantar_kelurahan_budi.png" },
|
||||
{ jenis: "ktp/kk", value: "kk_budi.png" },
|
||||
{ jenis: "foto lokasi", value: "foto_lokasi_budi.png" }
|
||||
{ id: "1", key: "pengantar kelian", value: "pengantar_kelurahan_budi.png" },
|
||||
{ id: "2", key: "ktp/kk", value: "kk_budi.png" },
|
||||
{ id: "3", key: "foto lokasi", value: "foto_lokasi_budi.png" }
|
||||
]
|
||||
],
|
||||
}
|
||||
@@ -969,7 +1009,6 @@ const PelayananRoute = new Elysia({
|
||||
detail: {
|
||||
summary: "Update Data Pengajuan Pelayanan Surat",
|
||||
description: `tool untuk update data pengajuan pelayanan surat`,
|
||||
tags: ["mcp"]
|
||||
}
|
||||
})
|
||||
.get("/list", async ({ query }) => {
|
||||
@@ -1116,5 +1155,47 @@ const PelayananRoute = new Elysia({
|
||||
description: `tool untuk mendapatkan jumlah pengajuan pelayanan surat warga`,
|
||||
}
|
||||
})
|
||||
.post("/get-no-pengajuan", async ({ body }) => {
|
||||
const { phone, noPengajuan } = body;
|
||||
|
||||
if (!isValidPhone(phone)) {
|
||||
return { success: false, message: 'nomor telepon tidak valid, harap masukkan nomor yang benar' }
|
||||
}
|
||||
|
||||
const nomorHP = normalizePhoneNumber({ phone: phone })
|
||||
const data = await prisma.pelayananAjuan.findMany({
|
||||
where: {
|
||||
noPengajuan: noPengajuan,
|
||||
Warga: {
|
||||
phone: nomorHP
|
||||
}
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
noPengajuan: true,
|
||||
status: true,
|
||||
createdAt: true,
|
||||
}
|
||||
});
|
||||
|
||||
if (data.length == 0) {
|
||||
return { success: false, message: 'Data pengajuan tidak ditemukan' };
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
nomer: noPengajuan
|
||||
};
|
||||
|
||||
}, {
|
||||
body: t.Object({
|
||||
phone: t.String({ minLength: 1, error: "Nomor telepon harus diisi" }),
|
||||
noPengajuan: t.String({ minLength: 1, error: "Nomor pengajuan harus diisi" }),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Cek Nomor Pengajuan Surat",
|
||||
description: `tool untuk memeriksa apakah nomor pengajuan surat valid dan terkait dengan nomor telepon warga. Jika valid, mengembalikan nomor pengajuan.`,
|
||||
}
|
||||
})
|
||||
|
||||
export default PelayananRoute
|
||||
|
||||
@@ -436,6 +436,9 @@ const PengaduanRoute = new Elysia({
|
||||
name: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user