upd: form surat
Deskripsi: - tambah form surat - update api - fungsi No Issues
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
|
import notification from "@/components/notificationGlobal";
|
||||||
import apiFetch from "@/lib/apiFetch";
|
import apiFetch from "@/lib/apiFetch";
|
||||||
|
import { capitalizeWords, fromSlug, toSlug } from "@/server/lib/slug_converter";
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Badge,
|
Badge,
|
||||||
@@ -7,28 +9,300 @@ import {
|
|||||||
Card,
|
Card,
|
||||||
Container,
|
Container,
|
||||||
Divider,
|
Divider,
|
||||||
|
FileButton,
|
||||||
Grid,
|
Grid,
|
||||||
Group,
|
Group,
|
||||||
Select,
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Textarea,
|
|
||||||
Tooltip
|
Tooltip
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import {
|
import {
|
||||||
IconBuildingCommunity,
|
IconBuildingCommunity,
|
||||||
IconInfoCircle,
|
IconInfoCircle,
|
||||||
IconMapPin,
|
IconUpload,
|
||||||
IconUser
|
IconUser
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
// =========================
|
type DataItem = {
|
||||||
// Reusable UI components
|
jenis: string;
|
||||||
// =========================
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type FormSurat = {
|
||||||
|
kategoryId: string;
|
||||||
|
nama: string;
|
||||||
|
phone: string;
|
||||||
|
dataText: DataItem[];
|
||||||
|
syaratDokumen: DataItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default function FormSurat() {
|
||||||
|
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: "",
|
||||||
|
kategoryId: "",
|
||||||
|
dataText: [],
|
||||||
|
syaratDokumen: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const listCategory = data?.data || [];
|
||||||
|
|
||||||
|
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({
|
||||||
|
kategoryId: jenisSuratFix.id,
|
||||||
|
nama: "",
|
||||||
|
phone: "",
|
||||||
|
dataText: (get.data?.dataText || []).map((item: string) => ({
|
||||||
|
jenis: item,
|
||||||
|
value: "",
|
||||||
|
})),
|
||||||
|
syaratDokumen: (get.data?.syaratDokumen || []).map(
|
||||||
|
(item: { name: string }) => ({
|
||||||
|
jenis: item.name,
|
||||||
|
value: "",
|
||||||
|
})
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
mutate();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
if (listCategory.length > 0) {
|
||||||
|
onGetJenisSurat();
|
||||||
|
}
|
||||||
|
}, [jenisSurat, listCategory]);
|
||||||
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
if (jenisSuratFix.id != "") {
|
||||||
|
getDetailJenisSurat();
|
||||||
|
}
|
||||||
|
}, [jenisSuratFix.id]);
|
||||||
|
|
||||||
|
function onSubmit() {
|
||||||
|
const isFormKosong = Object.values(formSurat).some((value) => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return (
|
||||||
|
value.length === 0 ||
|
||||||
|
value.some((item) => !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",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("READY SUBMIT", formSurat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container size="md" w={"100%"}>
|
||||||
|
<Box>
|
||||||
|
<Stack gap="lg">
|
||||||
|
<Group justify="apart" align="center">
|
||||||
|
<Group align="center">
|
||||||
|
<IconBuildingCommunity size={28} />
|
||||||
|
<div>
|
||||||
|
<Text fw={800} size="xl">
|
||||||
|
Surat Keterangan Tidak Mampu (SKTM)
|
||||||
|
</Text>
|
||||||
|
<Text size="sm" c="dimmed">
|
||||||
|
Blangko resmi untuk pengajuan Surat Keterangan Tidak Mampu —
|
||||||
|
digunakan untuk keperluan pendidikan, kesehatan, atau
|
||||||
|
administrasi.
|
||||||
|
</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 Lengkap"
|
||||||
|
hint="Nama lengkap pemohon"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
placeholder="Budi Setiawan"
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<TextInput
|
||||||
|
label={
|
||||||
|
<FieldLabel
|
||||||
|
label="Nomor Telephone"
|
||||||
|
hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
placeholder="08123456789"
|
||||||
|
/>
|
||||||
|
</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.dataText &&
|
||||||
|
<>
|
||||||
|
<FormSection
|
||||||
|
title="Data Pelengkap"
|
||||||
|
description="Data pelengkap yang diperlukan"
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
{
|
||||||
|
dataSurat.dataText.map((item: any, index: number) => (
|
||||||
|
<Grid.Col span={6} key={index}>
|
||||||
|
<TextInput
|
||||||
|
label={
|
||||||
|
<FieldLabel
|
||||||
|
label={dataSurat.dataText[index] == "nik" ? "NIK" : capitalizeWords(dataSurat.dataText[index])}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
placeholder={dataSurat.dataText[index] == "nik" ? "NIK" : capitalizeWords(dataSurat.dataText[index])}
|
||||||
|
/>
|
||||||
|
</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}>
|
||||||
|
<FieldLabelUpload
|
||||||
|
label={item.desc}
|
||||||
|
/>
|
||||||
|
<FileButton
|
||||||
|
onChange={async (file) => {
|
||||||
|
if (!file) return;
|
||||||
|
// const base64 = await fileToBase64(file);
|
||||||
|
// form.setFieldValue("foto", base64);
|
||||||
|
// setFotoName(file.name);
|
||||||
|
}}
|
||||||
|
accept="image/*"
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<Button
|
||||||
|
leftSection={<IconUpload size={16} />}
|
||||||
|
{...props}
|
||||||
|
mt="sm"
|
||||||
|
>
|
||||||
|
Upload File
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</FileButton>
|
||||||
|
</Grid.Col>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Grid>
|
||||||
|
</FormSection>
|
||||||
|
|
||||||
|
{/* Actions */}
|
||||||
|
<Group justify="right" mt="md">
|
||||||
|
<Button variant="default" onClick={() => { }}>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<Button onClick={onSubmit}>Kirim</Button>
|
||||||
|
</Group>
|
||||||
|
</>
|
||||||
|
|
||||||
|
}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
|
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
|
||||||
return (
|
return (
|
||||||
@@ -45,6 +319,36 @@ function FieldLabel({ label, hint }: { label: string; hint?: string }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function FieldLabelUpload({
|
||||||
|
label,
|
||||||
|
description,
|
||||||
|
}: {
|
||||||
|
label: React.ReactNode;
|
||||||
|
description?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Group justify="apart" style={{ width: "100%" }}>
|
||||||
|
<Group gap={6}>
|
||||||
|
<Text size="sm" fw={600}>
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
{description && (
|
||||||
|
<ActionIcon size={18} variant="subtle" aria-hidden>
|
||||||
|
<IconInfoCircle size={16} />
|
||||||
|
</ActionIcon>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
{description && (
|
||||||
|
<Text size="sm" c="dimmed" mt={4} style={{ lineHeight: 1.2 }}>
|
||||||
|
{description}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function FormSection({
|
function FormSection({
|
||||||
title,
|
title,
|
||||||
icon,
|
icon,
|
||||||
@@ -71,261 +375,3 @@ function FormSection({
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================
|
|
||||||
// Main form component
|
|
||||||
// =========================
|
|
||||||
|
|
||||||
export default function FormSurat() {
|
|
||||||
const { data, mutate, isLoading } = useSWR("category-pelayanan-list", () =>
|
|
||||||
apiFetch.api.pelayanan.category.get(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const listCategory = data?.data || [];
|
|
||||||
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
|
||||||
mutate();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container size="md" w={"100%"}>
|
|
||||||
<Box>
|
|
||||||
<Stack gap="lg">
|
|
||||||
<Group justify="apart" align="center">
|
|
||||||
<Group align="center">
|
|
||||||
<IconBuildingCommunity size={28} />
|
|
||||||
<div>
|
|
||||||
<Text fw={800} size="xl">
|
|
||||||
Surat Keterangan Tidak Mampu (SKTM)
|
|
||||||
</Text>
|
|
||||||
<Text size="sm" c="dimmed">
|
|
||||||
Blangko resmi untuk pengajuan Surat Keterangan Tidak Mampu —
|
|
||||||
digunakan untuk keperluan pendidikan, kesehatan, atau
|
|
||||||
administrasi.
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
</Group>
|
|
||||||
<Group>
|
|
||||||
<Badge radius="sm">Form Length: 3 Sections</Badge>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<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 Lengkap"
|
|
||||||
hint="Nama lengkap pemohon"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
placeholder="Budi Setiawan"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<TextInput
|
|
||||||
label={
|
|
||||||
<FieldLabel
|
|
||||||
label="Nomor Telephone"
|
|
||||||
hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
placeholder="08123456789"
|
|
||||||
/>
|
|
||||||
</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.id,
|
|
||||||
label: item.name,
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</FormSection>
|
|
||||||
|
|
||||||
<FormSection
|
|
||||||
title="Syarat Dokumen"
|
|
||||||
description="Syarat dokumen yang diperlukan"
|
|
||||||
>
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<TextInput
|
|
||||||
label={
|
|
||||||
<FieldLabel
|
|
||||||
label="Nama Lengkap"
|
|
||||||
hint="Sesuai KTP"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
placeholder="Nama lengkap"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<TextInput
|
|
||||||
label={
|
|
||||||
<FieldLabel
|
|
||||||
label="NIK"
|
|
||||||
hint="16 digit, tanpa spasi"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
placeholder="3201xxxxxxxxxxxx"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<TextInput
|
|
||||||
label={
|
|
||||||
<FieldLabel
|
|
||||||
label="Tempat, Tanggal Lahir"
|
|
||||||
hint="Contoh: Denpasar, 31-12-1990"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
placeholder="Tempat, tanggal lahir"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<Select
|
|
||||||
label={<FieldLabel label="Jenis Kelamin" />}
|
|
||||||
placeholder="Pilih jenis kelamin"
|
|
||||||
data={["Laki-laki", "Perempuan"]}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<Select
|
|
||||||
label={<FieldLabel label="Agama" />}
|
|
||||||
placeholder="Pilih agama"
|
|
||||||
data={[
|
|
||||||
"Islam",
|
|
||||||
"Kristen",
|
|
||||||
"Katolik",
|
|
||||||
"Hindu",
|
|
||||||
"Buddha",
|
|
||||||
"Konghucu",
|
|
||||||
"Lainnya",
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<Select
|
|
||||||
label={<FieldLabel label="Status Perkawinan" />}
|
|
||||||
placeholder="Pilih status"
|
|
||||||
data={[
|
|
||||||
"Belum Kawin",
|
|
||||||
"Kawin",
|
|
||||||
"Cerai Hidup",
|
|
||||||
"Cerai Mati",
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<TextInput
|
|
||||||
label={<FieldLabel label="Pekerjaan" />}
|
|
||||||
placeholder="Pekerjaan"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={12}>
|
|
||||||
<Textarea
|
|
||||||
label={<FieldLabel label="Alamat Lengkap" />}
|
|
||||||
placeholder="Alamat domisili"
|
|
||||||
minRows={2}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={2}>
|
|
||||||
<TextInput
|
|
||||||
label={<FieldLabel label="RT" />}
|
|
||||||
placeholder="001"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={2}>
|
|
||||||
<TextInput
|
|
||||||
label={<FieldLabel label="RW" />}
|
|
||||||
placeholder="002"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={4}>
|
|
||||||
<TextInput
|
|
||||||
label={<FieldLabel label="Desa / Kelurahan" />}
|
|
||||||
placeholder="Desa"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={4}>
|
|
||||||
<TextInput
|
|
||||||
label={<FieldLabel label="Kecamatan" />}
|
|
||||||
placeholder="Kecamatan"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
|
|
||||||
<Grid.Col span={4}>
|
|
||||||
<TextInput
|
|
||||||
label={<FieldLabel label="Kabupaten / Kota" />}
|
|
||||||
placeholder="Kabupaten / Kota"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</FormSection>
|
|
||||||
|
|
||||||
{/* Keterangan Section */}
|
|
||||||
<FormSection
|
|
||||||
title="Keterangan"
|
|
||||||
icon={<IconMapPin size={18} />}
|
|
||||||
description="Isi pernyataan SKTM"
|
|
||||||
>
|
|
||||||
<Textarea
|
|
||||||
label={
|
|
||||||
<FieldLabel
|
|
||||||
label="Isi Surat"
|
|
||||||
hint="Jelaskan kondisi ekonomi secara singkat"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
placeholder="Pernyataan resmi bahwa yang bersangkutan benar-benar tergolong keluarga tidak mampu..."
|
|
||||||
minRows={4}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextInput
|
|
||||||
label={
|
|
||||||
<FieldLabel
|
|
||||||
label="Keperluan"
|
|
||||||
hint="Contoh: Beasiswa pendidikan / Perawatan kesehatan"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
placeholder="Keperluan surat"
|
|
||||||
/>
|
|
||||||
</FormSection>
|
|
||||||
|
|
||||||
{/* Actions */}
|
|
||||||
<Group justify="right" mt="md">
|
|
||||||
<Button variant="default" onClick={() => { }}>
|
|
||||||
Reset
|
|
||||||
</Button>
|
|
||||||
<Button type="submit">Kirim / Simpan</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
</form>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
18
src/server/lib/slug_converter.ts
Normal file
18
src/server/lib/slug_converter.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
export function toSlug(text: string): string {
|
||||||
|
return encodeURIComponent(
|
||||||
|
text
|
||||||
|
.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
.replace(/\s+/g, "-")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fromSlug(slug: string): string {
|
||||||
|
return decodeURIComponent(slug)
|
||||||
|
.replace(/-/g, " ")
|
||||||
|
.replace(/\b\w/g, c => c.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function capitalizeWords(text: string): string {
|
||||||
|
return text.replace(/\b\w/g, c => c.toUpperCase());
|
||||||
|
}
|
||||||
@@ -105,12 +105,36 @@ const PelayananRoute = new Elysia({
|
|||||||
.get("/category/detail", async ({ query }) => {
|
.get("/category/detail", async ({ query }) => {
|
||||||
const { id } = query
|
const { id } = query
|
||||||
const data = await prisma.categoryPelayanan.findUnique({
|
const data = await prisma.categoryPelayanan.findUnique({
|
||||||
where:{
|
where: {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return data
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataText: string[] = Array.isArray(data.dataText)
|
||||||
|
? data.dataText.filter((v): v is string => typeof v === "string")
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const syaratDokumen: { name: string }[] = Array.isArray(data.syaratDokumen)
|
||||||
|
? data.syaratDokumen.filter(
|
||||||
|
(v): v is { name: string } =>
|
||||||
|
typeof v === "object" &&
|
||||||
|
v !== null &&
|
||||||
|
"name" in v &&
|
||||||
|
typeof (v as any).name === "string"
|
||||||
|
)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: data.id,
|
||||||
|
name: data.name,
|
||||||
|
dataText,
|
||||||
|
syaratDokumen,
|
||||||
|
};
|
||||||
}, {
|
}, {
|
||||||
query: t.Object({
|
query: t.Object({
|
||||||
id: t.String({ minLength: 1, error: "id harus diisi" }),
|
id: t.String({ minLength: 1, error: "id harus diisi" }),
|
||||||
|
|||||||
Reference in New Issue
Block a user