Compare commits
3 Commits
amalia/19-
...
amalia/22-
| Author | SHA1 | Date | |
|---|---|---|---|
| da86f5f10a | |||
| 91a3dfdb5d | |||
| 3904527c2a |
@@ -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,
|
||||
@@ -233,15 +232,15 @@ export default function KategoriPelayananSurat({
|
||||
}
|
||||
/>
|
||||
</Input.Wrapper>
|
||||
<TagsInput
|
||||
{/* <TagsInput
|
||||
label="Data Pelengkap"
|
||||
placeholder="Tambah data pelengkap"
|
||||
splitChars={[","]}
|
||||
value={dataChoose.dataText}
|
||||
value={dataChoose.dataPelengkap}
|
||||
onChange={(value) =>
|
||||
setDataChoose({ ...dataChoose, dataText: value })
|
||||
setDataChoose({ ...dataChoose, dataPelengkap: value })
|
||||
}
|
||||
/>
|
||||
/> */}
|
||||
<Flex direction={"column"} gap={"md"}>
|
||||
<Group>
|
||||
<Text size="sm" c={"white"}>
|
||||
@@ -295,6 +294,7 @@ export default function KategoriPelayananSurat({
|
||||
value={v.name}
|
||||
onChange={(e) =>
|
||||
handleEditSyarat(i, {
|
||||
key: v.key,
|
||||
name: e.target.value,
|
||||
desc: v.desc,
|
||||
})
|
||||
@@ -308,6 +308,7 @@ export default function KategoriPelayananSurat({
|
||||
value={v.desc}
|
||||
onChange={(e) =>
|
||||
handleEditSyarat(i, {
|
||||
key: v.key,
|
||||
name: v.name,
|
||||
desc: e.target.value,
|
||||
})
|
||||
@@ -347,7 +348,7 @@ export default function KategoriPelayananSurat({
|
||||
}
|
||||
/>
|
||||
</Input.Wrapper>
|
||||
<TagsInput
|
||||
{/* <TagsInput
|
||||
label="Data Pelengkap"
|
||||
placeholder="Tambah data pelengkap"
|
||||
splitChars={[","]}
|
||||
@@ -355,7 +356,7 @@ export default function KategoriPelayananSurat({
|
||||
onChange={(value) =>
|
||||
setDataTambah({ ...dataTambah, dataText: value })
|
||||
}
|
||||
/>
|
||||
/> */}
|
||||
<Flex direction={"column"} gap={"md"}>
|
||||
<Group>
|
||||
<Text size="sm" c={"white"}>
|
||||
@@ -372,7 +373,7 @@ export default function KategoriPelayananSurat({
|
||||
...dataTambah,
|
||||
syaratDokumen: [
|
||||
...dataTambah.syaratDokumen,
|
||||
{ name: "", desc: "" },
|
||||
{ key: "", name: "", desc: "" },
|
||||
],
|
||||
});
|
||||
}}
|
||||
@@ -524,8 +525,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>
|
||||
|
||||
@@ -4,11 +4,13 @@ import { IconCheck } from "@tabler/icons-react";
|
||||
type SuccessPengajuanProps = {
|
||||
noPengajuan: string;
|
||||
onClose?: () => void;
|
||||
category?: 'create' | 'update';
|
||||
};
|
||||
|
||||
export default function SuccessPengajuan({
|
||||
noPengajuan,
|
||||
onClose,
|
||||
category
|
||||
}: SuccessPengajuanProps) {
|
||||
return (
|
||||
<Center h="100vh">
|
||||
@@ -17,11 +19,11 @@ export default function SuccessPengajuan({
|
||||
<IconCheck size={56} color="green" />
|
||||
|
||||
<Title order={3} ta="center">
|
||||
Pengajuan Berhasil Dibuat
|
||||
{category == 'create' ? 'Pengajuan Berhasil Dibuat' : 'Pengajuan Berhasil Diupdate'}
|
||||
</Title>
|
||||
|
||||
<Text ta="center" size="sm" c="dimmed">
|
||||
Pengajuan layanan surat sudah dibuat dengan nomor:
|
||||
{category == 'create' ? 'Pengajuan layanan surat sudah dibuat dengan nomor:' : 'Pengajuan layanan surat sudah diupdate dengan nomor:'}
|
||||
</Text>
|
||||
|
||||
<Badge size="xl" variant="light" color="green">
|
||||
|
||||
@@ -15,13 +15,14 @@ import {
|
||||
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,
|
||||
@@ -46,6 +47,7 @@ type FormSurat = {
|
||||
};
|
||||
|
||||
export default function FormSurat() {
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const [noPengajuan, setNoPengajuan] = useState("");
|
||||
const [submitLoading, setSubmitLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
@@ -141,7 +143,7 @@ export default function FormSurat() {
|
||||
}
|
||||
}, [jenisSuratFix.id]);
|
||||
|
||||
async function onSubmit() {
|
||||
function onChecking() {
|
||||
const isFormKosong = Object.values(formSurat).some((value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return (
|
||||
@@ -166,8 +168,12 @@ export default function FormSurat() {
|
||||
message: "Silahkan lengkapi form surat",
|
||||
type: "error",
|
||||
});
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
setSubmitLoading(true);
|
||||
// 🔥 CLONE state SEKALI
|
||||
@@ -197,11 +203,7 @@ export default function FormSurat() {
|
||||
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",
|
||||
});
|
||||
setNoPengajuan(res.data?.noPengajuan || "");
|
||||
} else {
|
||||
notification({
|
||||
title: "Gagal",
|
||||
@@ -252,161 +254,192 @@ export default function FormSurat() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Container size="md" w={"100%"}>
|
||||
<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 != "" && (
|
||||
{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>
|
||||
)
|
||||
:
|
||||
<Box>
|
||||
<Stack gap="lg">
|
||||
{/* 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>
|
||||
<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 */}
|
||||
<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="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 span={6}>
|
||||
<TextInput
|
||||
label={
|
||||
<FieldLabel
|
||||
label="Nomor Telephone"
|
||||
hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
|
||||
/>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
}
|
||||
placeholder="08123456789"
|
||||
value={formSurat.phone}
|
||||
onChange={(e) =>
|
||||
validationForm({ key: "phone", value: e.target.value })
|
||||
}
|
||||
/>
|
||||
</Grid.Col>
|
||||
|
||||
<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 span={12}>
|
||||
<Select
|
||||
label={
|
||||
<FieldLabel
|
||||
label="Jenis Surat"
|
||||
hint="Jenis surat yang ingin diajukan"
|
||||
/>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
</FormSection>
|
||||
}
|
||||
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>
|
||||
|
||||
{/* Actions */}
|
||||
<Group justify="right" mt="md">
|
||||
<Button variant="default" onClick={() => {}}>
|
||||
{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>
|
||||
|
||||
{/* Actions */}
|
||||
<Group justify="right" mt="md">
|
||||
{/* <Button variant="default" onClick={() => { }}>
|
||||
Reset
|
||||
</Button>
|
||||
<Button onClick={onSubmit}>Kirim</Button>
|
||||
</Group>
|
||||
</>
|
||||
)}
|
||||
</Button> */}
|
||||
<Button onClick={onChecking}>Kirim</Button>
|
||||
</Group>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
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,
|
||||
@@ -15,12 +17,13 @@ import {
|
||||
Flex,
|
||||
Grid,
|
||||
Group,
|
||||
Modal,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
|
||||
import {
|
||||
IconBuildingCommunity,
|
||||
IconInfoCircle,
|
||||
@@ -336,6 +339,10 @@ function SearchData() {
|
||||
|
||||
|
||||
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 | {}>({})
|
||||
@@ -406,69 +413,208 @@ function DataUpdate({ noPengajuan }: { noPengajuan: string }) {
|
||||
}));
|
||||
}
|
||||
|
||||
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>
|
||||
{
|
||||
(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>} />
|
||||
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>
|
||||
</>
|
||||
}
|
||||
<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={() => console.log('Submit clicked')}>Kirim</Button>
|
||||
</Group>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
@@ -299,14 +312,26 @@ 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
|
||||
|
||||
const dataHistory = await prisma.historyPelayanan.findMany({
|
||||
where: {
|
||||
@@ -477,7 +502,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({
|
||||
@@ -664,18 +689,29 @@ const PelayananRoute = new Elysia({
|
||||
key: string;
|
||||
}[];
|
||||
|
||||
const dataTextFix = dataPelengkap.map((item) => {
|
||||
const ini = dataPelengkapList.find((v) => v.key == item.jenis)
|
||||
const desc = ini?.desc
|
||||
const name = ini?.name
|
||||
return {
|
||||
id: item.id,
|
||||
key: item.jenis,
|
||||
value: item.value,
|
||||
desc: desc ?? '',
|
||||
name: name ?? ''
|
||||
}
|
||||
})
|
||||
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: {
|
||||
@@ -733,7 +769,6 @@ const PelayananRoute = new Elysia({
|
||||
dataPelengkap: dataTextFix,
|
||||
}
|
||||
|
||||
|
||||
return datafix
|
||||
|
||||
}, {
|
||||
|
||||
Reference in New Issue
Block a user