fix: pelayanan surat

Deskripsi:
- mandatory pada form tambah pelayanan surat
- mandatory pada form update pelayanan surat

No Issues
This commit is contained in:
2026-01-20 17:15:16 +08:00
parent f86703e7d1
commit a8d3a3a9ff
4 changed files with 293 additions and 317 deletions

View File

@@ -42,6 +42,7 @@ import useSWR from "swr";
type DataItem = {
key: string;
value: string;
required: boolean;
};
type FormSurat = {
@@ -119,15 +120,17 @@ export default function FormSurat() {
nama: "",
phone: "",
dataPelengkap: (get.data?.dataPelengkap || []).map(
(item: { key: string }) => ({
(item: { key: string, required: boolean }) => ({
key: item.key,
value: "",
required: item.required
}),
),
syaratDokumen: (get.data?.syaratDokumen || []).map(
(item: { key: string }) => ({
(item: { key: string, required: boolean }) => ({
key: item.key,
value: "",
required: item.required
}),
),
});
@@ -167,10 +170,10 @@ export default function FormSurat() {
if (Array.isArray(value)) {
return value.some(
(item) =>
typeof item.value === "string" && item.value.trim() === "",
(typeof item.value === "string" && item.value.trim() === "" && item.required) || (typeof item.value === "object" && item.value === null && item.required),
);
}
return typeof value === "string" && value.trim() === "";
return typeof value === "string" && value.trim() === "" ;
});
if (isFormKosong) {
@@ -276,13 +279,14 @@ export default function FormSurat() {
value: any;
}) {
if (key === "dataPelengkap" || key === "syaratDokumen") {
const errorMsg = validateField(value.key, value.value);
setErrors((prev) => ({
...prev,
[value.key]: errorMsg,
}));
if (value.required == true) {
const errorMsg = validateField(value.key, value.value);
setErrors((prev) => ({
...prev,
[value.key]: errorMsg,
}));
}
setFormSurat((prev) => ({
...prev,
[key]: updateArrayByKey(prev[key], value.key, value.value),
@@ -400,7 +404,7 @@ export default function FormSurat() {
<Grid>
<Grid.Col span={6}>
<TextInput
label={<FieldLabel label="Nama" hint="Nama kontak" />}
label={<FieldLabel label="Nama" hint="Nama kontak" required />}
placeholder="Budi Setiawan"
value={formSurat.nama}
error={errors.nama_kontak}
@@ -414,6 +418,7 @@ export default function FormSurat() {
<TextInput
label={
<FieldLabel
required
label="Nomor Telephone"
hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
/>
@@ -450,6 +455,7 @@ export default function FormSurat() {
<FieldLabel
label={item.name}
hint={item.desc}
required={item.required}
/>
}
data={item.options ?? []}
@@ -457,7 +463,7 @@ export default function FormSurat() {
onChange={(e) => {
validationForm({
key: "dataPelengkap",
value: { key: item.key, value: e },
value: { key: item.key, value: e, required: item.required },
});
}}
value={
@@ -474,6 +480,7 @@ export default function FormSurat() {
<FieldLabel
label={item.name}
hint={item.desc}
required={item.required}
/>
}
placeholder={item.name}
@@ -488,6 +495,7 @@ export default function FormSurat() {
value: {
key: item.key,
value: formatted,
required: item.required,
},
});
}}
@@ -500,6 +508,7 @@ export default function FormSurat() {
<FieldLabel
label={item.name}
hint={item.desc}
required={item.required}
/>
}
placeholder={item.name}
@@ -509,6 +518,7 @@ export default function FormSurat() {
value: {
key: item.key,
value: e.target.value,
required: item.required,
},
})
}
@@ -545,6 +555,7 @@ export default function FormSurat() {
})
}
name={item.name}
required={item.required}
/>
</Grid.Col>
),
@@ -569,10 +580,20 @@ export default function FormSurat() {
);
}
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
function FieldLabel({ label, hint, required = false, }: { label: string; hint?: string; required?: boolean; }) {
return (
<Group justify="apart" gap="xs" align="center">
<Text fw={600}>{label}</Text>
<Group gap={4} align="center">
<Text fw={600}>
{label}
{required && (
<Text span c="red" ml={4}>
*
</Text>
)}
</Text>
</Group>
{hint && (
<Tooltip label={hint} withArrow>
<ActionIcon size={24} variant="subtle">
@@ -584,6 +605,7 @@ function FieldLabel({ label, hint }: { label: string; hint?: string }) {
);
}
function FormSection({
title,
icon,
@@ -619,6 +641,7 @@ function FileInputWrapper({
preview,
name,
description,
required = false,
}: {
label: string;
placeholder?: string;
@@ -627,12 +650,20 @@ function FileInputWrapper({
preview?: string | null;
name: string;
description?: string;
required?: boolean;
}) {
return (
<Stack gap="xs">
<Flex direction={"column"}>
<Group justify="apart" align="center">
<Text fw={500}>{label}</Text>
<Text fw={500}>
{label}
{required && (
<Text span c="red" ml={4}>
*
</Text>
)}
</Text>
</Group>
{description && (
<Text size="sm" c="dimmed" mt={4} style={{ lineHeight: 1.2 }}>

View File

@@ -50,6 +50,7 @@ type UpdateDataItem = {
id: string;
key: string;
value: any;
required: boolean;
};
type FormSurat = {
@@ -125,10 +126,20 @@ export default function UpdateDataSurat() {
);
}
function FieldLabel({ label, hint }: { label: string; hint?: string }) {
function FieldLabel({ label, hint, required = false, }: { label: string; hint?: string; required?: boolean; }) {
return (
<Group justify="apart" gap="xs" align="center">
<Text fw={600}>{label}</Text>
<Group gap={4} align="center">
<Text fw={600}>
{label}
{required && (
<Text span c="red" ml={4}>
*
</Text>
)}
</Text>
</Group>
{hint && (
<Tooltip label={hint} withArrow>
<ActionIcon size={24} variant="subtle">
@@ -139,7 +150,6 @@ function FieldLabel({ label, hint }: { label: string; hint?: string }) {
</Group>
);
}
function FormSection({
title,
icon,
@@ -185,6 +195,8 @@ function FileInputWrapper({
description,
linkView,
disabled,
required = false,
}: {
label: string;
placeholder?: string;
@@ -195,6 +207,7 @@ function FileInputWrapper({
name: string;
description?: string;
disabled?: boolean;
required?: boolean;
}) {
const [viewImg, setViewImg] = useState("");
const [openedPreviewFile, setOpenedPreviewFile] = useState(false);
@@ -219,7 +232,14 @@ function FileInputWrapper({
<Stack gap="xs">
<Flex direction={"column"}>
<Group justify="apart" align="center">
<Text fw={500}>{label}</Text>
<Text fw={500}>
{label}
{required && (
<Text span c="red" ml={4}>
*
</Text>
)}
</Text>
</Group>
{description && (
<Text size="sm" c="dimmed" mt={4} style={{ lineHeight: 1.2 }}>
@@ -478,21 +498,33 @@ function DataUpdate({
kategori: "dataPelengkap" | "syaratDokumen";
value: UpdateDataItem;
}) {
const errorMsg = validateField(value.key, value.value);
if (kategori == "syaratDokumen" && value.value == null) {
setFormSurat((prev) => ({
...prev,
syaratDokumen: prev.syaratDokumen.filter(
(item) => item.id !== value.id
),
}));
} else {
if (value.required == true) {
const errorMsg = validateField(value.key, value.value);
setErrors((prev) => ({
...prev,
[value.id]: errorMsg,
}));
}
setErrors((prev) => ({
...prev,
[value.id]: errorMsg,
}));
setFormSurat((prev) => ({
...prev,
[kategori]: upsertById(prev[kategori], {
id: value.id,
key: value.key,
value: value.value,
}),
}));
setFormSurat((prev) => ({
...prev,
[kategori]: upsertById(prev[kategori], {
id: value.id,
key: value.key,
value: value.value,
required: value.required,
}),
}));
}
}
@@ -529,7 +561,7 @@ function DataUpdate({
if (Array.isArray(value)) {
return value.some(
(item) =>
typeof item.value === "string" && item.value.trim() === "",
(typeof item.value === "string" && item.value.trim() === "" && item.required) || (typeof item.value === "object" && item.value === null && item.required),
);
}
@@ -677,13 +709,13 @@ function DataUpdate({
<Select
disabled={status != "ditolak" && status != "antrian"}
allowDeselect={false}
label={<FieldLabel label={item.name} hint={item.desc} />}
label={<FieldLabel label={item.name} hint={item.desc} required={item.required} />}
data={item.options ?? []}
placeholder={item.name}
onChange={(e) => {
validationForm({
kategori: "dataPelengkap",
value: { id: item.id, key: item.key, value: e },
value: { id: item.id, key: item.key, value: e, required: item.required },
});
}}
value={
@@ -698,7 +730,7 @@ function DataUpdate({
disabled={status != "ditolak" && status != "antrian"}
locale="id"
valueFormat="DD MMMM YYYY"
label={<FieldLabel label={item.name} hint={item.desc} />}
label={<FieldLabel label={item.name} hint={item.desc} required={item.required} />}
placeholder={item.name}
onChange={(e) => {
const formatted = e
@@ -710,6 +742,7 @@ function DataUpdate({
id: item.id,
key: item.key,
value: formatted,
required: item.required
},
});
}}
@@ -728,7 +761,7 @@ function DataUpdate({
) : (
<TextInput
error={errors[item.id]}
label={<FieldLabel label={item.name} hint={item.desc} />}
label={<FieldLabel label={item.name} hint={item.desc} required={item.required} />}
placeholder={item.name}
type={item.type}
onChange={(e) =>
@@ -738,6 +771,7 @@ function DataUpdate({
id: item.id,
key: item.key,
value: e.target.value,
required: item.required,
},
})
}
@@ -763,6 +797,7 @@ function DataUpdate({
{dataSyaratDokumen.map((item: any, index: number) => (
<Grid.Col span={6} key={index}>
<FileInputWrapper
required={item.required}
label={item.desc}
placeholder={"Upload file terbaru untuk mengupdate"}
accept="image/*,application/pdf"
@@ -770,7 +805,7 @@ function DataUpdate({
onChange={(file) =>
validationForm({
kategori: "syaratDokumen",
value: { id: item.id, key: item.key, value: file },
value: { id: item.id, key: item.key, value: file, required: item.required },
})
}
name={item.name}