fix: enhance FilePreview component to limit filename display and add findLastEducation utility for education level mapping
This commit is contained in:
parent
c0dd392de0
commit
7f503e7050
|
|
@ -17,6 +17,7 @@ export const FormBetter: React.FC<any> = ({
|
||||||
className,
|
className,
|
||||||
onInit,
|
onInit,
|
||||||
afterLoad,
|
afterLoad,
|
||||||
|
disabledScroll,
|
||||||
}) => {
|
}) => {
|
||||||
const [fm, setFM] = useState<any>({
|
const [fm, setFM] = useState<any>({
|
||||||
data: null as any,
|
data: null as any,
|
||||||
|
|
@ -37,55 +38,110 @@ export const FormBetter: React.FC<any> = ({
|
||||||
)}
|
)}
|
||||||
<div className="w-full flex-grow flex flex-row rounded-lg">
|
<div className="w-full flex-grow flex flex-row rounded-lg">
|
||||||
<div className="w-full flex flex-row flex-grow bg-white rounded-lg border border-gray-300 relative ">
|
<div className="w-full flex flex-row flex-grow bg-white rounded-lg border border-gray-300 relative ">
|
||||||
<ScrollArea className="flex-grow">
|
{disabledScroll ? (
|
||||||
<Form
|
<>
|
||||||
{...{
|
{" "}
|
||||||
children,
|
<Form
|
||||||
header,
|
{...{
|
||||||
onTitle,
|
children,
|
||||||
onLoad: async () => {
|
header,
|
||||||
try {
|
onTitle,
|
||||||
const res = await onLoad();
|
onLoad: async () => {
|
||||||
return res;
|
try {
|
||||||
} catch (ex: any) {
|
const res = await onLoad();
|
||||||
setShow(false);
|
return res;
|
||||||
throw new Error(
|
} catch (ex: any) {
|
||||||
get(ex, "response.data.meta.message") || ex.message
|
setShow(false);
|
||||||
);
|
throw new Error(
|
||||||
}
|
get(ex, "response.data.meta.message") || ex.message
|
||||||
},
|
);
|
||||||
onSubmit,
|
}
|
||||||
onFooter,
|
},
|
||||||
showResize,
|
onSubmit,
|
||||||
mode,
|
onFooter,
|
||||||
className: cx(className, "top-0 left-0 w-full"),
|
showResize,
|
||||||
afterLoad,
|
mode,
|
||||||
onInit: (form: any) => {
|
className: cx(className, "top-0 left-0 w-full"),
|
||||||
setFM(form);
|
afterLoad,
|
||||||
|
onInit: (form: any) => {
|
||||||
|
setFM(form);
|
||||||
|
|
||||||
const originalRender = form.render;
|
const originalRender = form.render;
|
||||||
|
|
||||||
// Buat versi baru dari `local.render`
|
// Buat versi baru dari `local.render`
|
||||||
form.render = () => {
|
form.render = () => {
|
||||||
// Panggil fungsi asli
|
// Panggil fungsi asli
|
||||||
originalRender();
|
originalRender();
|
||||||
|
|
||||||
// Tambahkan logika tambahan untuk sinkronisasi
|
// Tambahkan logika tambahan untuk sinkronisasi
|
||||||
setFM({
|
setFM({
|
||||||
...form,
|
...form,
|
||||||
submit: form.submit,
|
submit: form.submit,
|
||||||
render: form.render,
|
render: form.render,
|
||||||
data: form.data,
|
data: form.data,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
form.render();
|
form.render();
|
||||||
if (typeof onInit === "function") {
|
if (typeof onInit === "function") {
|
||||||
onInit(form);
|
onInit(form);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ScrollArea>
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<ScrollArea className="flex-grow">
|
||||||
|
<Form
|
||||||
|
{...{
|
||||||
|
children,
|
||||||
|
header,
|
||||||
|
onTitle,
|
||||||
|
onLoad: async () => {
|
||||||
|
try {
|
||||||
|
const res = await onLoad();
|
||||||
|
return res;
|
||||||
|
} catch (ex: any) {
|
||||||
|
setShow(false);
|
||||||
|
throw new Error(
|
||||||
|
get(ex, "response.data.meta.message") || ex.message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmit,
|
||||||
|
onFooter,
|
||||||
|
showResize,
|
||||||
|
mode,
|
||||||
|
className: cx(className, "top-0 left-0 w-full"),
|
||||||
|
afterLoad,
|
||||||
|
onInit: (form: any) => {
|
||||||
|
setFM(form);
|
||||||
|
|
||||||
|
const originalRender = form.render;
|
||||||
|
|
||||||
|
// Buat versi baru dari `local.render`
|
||||||
|
form.render = () => {
|
||||||
|
// Panggil fungsi asli
|
||||||
|
originalRender();
|
||||||
|
|
||||||
|
// Tambahkan logika tambahan untuk sinkronisasi
|
||||||
|
setFM({
|
||||||
|
...form,
|
||||||
|
submit: form.submit,
|
||||||
|
render: form.render,
|
||||||
|
data: form.data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
form.render();
|
||||||
|
if (typeof onInit === "function") {
|
||||||
|
onInit(form);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ScrollArea>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,11 @@ export const FilePreview = ({
|
||||||
>
|
>
|
||||||
<div className="flex flex-row gap-x-1 items-center">
|
<div className="flex flex-row gap-x-1 items-center">
|
||||||
<div className="h-[30px] flex flex-row items-center">{content}</div>
|
<div className="h-[30px] flex flex-row items-center">{content}</div>
|
||||||
<div className="text-xs filename">{file?.name}</div>
|
<div className="text-xs filename">
|
||||||
|
{limit_name && file?.name
|
||||||
|
? file?.name.substring(0, limit_name)
|
||||||
|
: file?.name}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="ml-2">
|
<div className="ml-2">
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { getNumber } from "@/lib/utils/getNumber";
|
||||||
import MaskedInput from "../../ui/MaskedInput";
|
import MaskedInput from "../../ui/MaskedInput";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { getLabel } from "@/lib/utils/getLabel";
|
import { getLabel } from "@/lib/utils/getLabel";
|
||||||
|
import { time } from "@/lib/utils/date";
|
||||||
|
|
||||||
export const TypeInput: React.FC<any> = ({
|
export const TypeInput: React.FC<any> = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -30,7 +31,7 @@ export const TypeInput: React.FC<any> = ({
|
||||||
let value: any = fm.data?.[name] || "";
|
let value: any = fm.data?.[name] || "";
|
||||||
|
|
||||||
if (type === "time") {
|
if (type === "time") {
|
||||||
value = convertToTimeOnly(value) || "";
|
value = time(value) || "";
|
||||||
}
|
}
|
||||||
const [rating, setRating] = useState(value); // State untuk menyimpan nilai rating
|
const [rating, setRating] = useState(value); // State untuk menyimpan nilai rating
|
||||||
const handleClick = (index: number) => {
|
const handleClick = (index: number) => {
|
||||||
|
|
@ -70,7 +71,7 @@ export const TypeInput: React.FC<any> = ({
|
||||||
meta.rgbValue = convertColor.toRgbString();
|
meta.rgbValue = convertColor.toRgbString();
|
||||||
meta.render();
|
meta.render();
|
||||||
} else if (type === "time") {
|
} else if (type === "time") {
|
||||||
if (fm.data?.[name]) fm.data[name] = convertToTimeOnly(fm.data[name]);
|
if (fm.data?.[name]) fm.data[name] = time(fm.data[name]);
|
||||||
fm.render();
|
fm.render();
|
||||||
} else {
|
} else {
|
||||||
setRating(value ? value - 1 : value);
|
setRating(value ? value - 1 : value);
|
||||||
|
|
@ -246,61 +247,63 @@ export const TypeInput: React.FC<any> = ({
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "money":
|
case "money":
|
||||||
return <>
|
return (
|
||||||
<Input
|
<>
|
||||||
id={name}
|
<Input
|
||||||
name={name}
|
id={name}
|
||||||
disabled={disabled}
|
name={name}
|
||||||
className={cn(
|
disabled={disabled}
|
||||||
"text-sm text-right ",
|
className={cn(
|
||||||
error
|
"text-sm text-right ",
|
||||||
? css`
|
error
|
||||||
border-color: red !important;
|
? css`
|
||||||
`
|
border-color: red !important;
|
||||||
: ``,
|
`
|
||||||
css`
|
: ``,
|
||||||
background-color: ${disabled
|
css`
|
||||||
? "rgb(243 244 246)"
|
background-color: ${disabled
|
||||||
: "transparant"}
|
? "rgb(243 244 246)"
|
||||||
? "";
|
: "transparant"}
|
||||||
`,
|
? "";
|
||||||
className
|
`,
|
||||||
)}
|
className
|
||||||
required={required}
|
)}
|
||||||
placeholder={placeholder || ""}
|
required={required}
|
||||||
value={formatCurrency(input.value)}
|
placeholder={placeholder || ""}
|
||||||
type={"text"}
|
value={formatCurrency(input.value)}
|
||||||
onKeyDown={handleKeyDown}
|
type={"text"}
|
||||||
onChange={(ev) => {
|
onKeyDown={handleKeyDown}
|
||||||
const rawValue = ev.currentTarget.value
|
onChange={(ev) => {
|
||||||
.replace(/[^0-9,-]/g, "")
|
const rawValue = ev.currentTarget.value
|
||||||
.toString();
|
.replace(/[^0-9,-]/g, "")
|
||||||
if (rawValue === "0") {
|
.toString();
|
||||||
input.value = "0";
|
if (rawValue === "0") {
|
||||||
input.render();
|
input.value = "0";
|
||||||
}
|
input.render();
|
||||||
if (
|
|
||||||
(!rawValue.startsWith(",") || !rawValue.endsWith(",")) &&
|
|
||||||
!rawValue.endsWith("-") &&
|
|
||||||
convertionCurrencyNumber(rawValue) !==
|
|
||||||
convertionCurrencyNumber(input.value)
|
|
||||||
) {
|
|
||||||
fm.data[name] = convertionCurrencyNumber(
|
|
||||||
formatCurrency(rawValue)
|
|
||||||
);
|
|
||||||
fm.render();
|
|
||||||
if (typeof onChange === "function") {
|
|
||||||
onChange(fm.data[name]);
|
|
||||||
}
|
}
|
||||||
input.value = formatCurrency(fm.data[name]);
|
if (
|
||||||
input.render();
|
(!rawValue.startsWith(",") || !rawValue.endsWith(",")) &&
|
||||||
} else {
|
!rawValue.endsWith("-") &&
|
||||||
input.value = rawValue;
|
convertionCurrencyNumber(rawValue) !==
|
||||||
input.render();
|
convertionCurrencyNumber(input.value)
|
||||||
}
|
) {
|
||||||
}}
|
fm.data[name] = convertionCurrencyNumber(
|
||||||
/>
|
formatCurrency(rawValue)
|
||||||
</>;
|
);
|
||||||
|
fm.render();
|
||||||
|
if (typeof onChange === "function") {
|
||||||
|
onChange(fm.data[name]);
|
||||||
|
}
|
||||||
|
input.value = formatCurrency(fm.data[name]);
|
||||||
|
input.render();
|
||||||
|
} else {
|
||||||
|
input.value = rawValue;
|
||||||
|
input.render();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let type_field = type;
|
let type_field = type;
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
// Create Document Component
|
// Create Document Component
|
||||||
export const DocumentBiodata: FC<any> = ({ data, onRender }) => {
|
export const DocumentBiodata: FC<any> = ({ data, onRender }) => {
|
||||||
|
console.log({ data });
|
||||||
return (
|
return (
|
||||||
<PDFViewer className="flex-grow w-full">
|
<PDFViewer className="flex-grow w-full">
|
||||||
<Document
|
<Document
|
||||||
|
|
@ -134,8 +135,14 @@ export const DocumentBiodata: FC<any> = ({ data, onRender }) => {
|
||||||
<Text>DATA DIRI 个人资料</Text>
|
<Text>DATA DIRI 个人资料</Text>
|
||||||
</View>
|
</View>
|
||||||
{[
|
{[
|
||||||
{ label: "Nama Lengkap 姓名", value: "" },
|
{ label: "Nama Lengkap 姓名", value: data?.name },
|
||||||
{ label: "Tempat & Tanggal Lahir 出生地点,日期", value: "" },
|
{
|
||||||
|
label: "Tempat & Tanggal Lahir 出生地点,日期",
|
||||||
|
value:
|
||||||
|
data?.birth_place && data?.birth_date
|
||||||
|
? `${data?.birth_place}, ${dayDate(data?.birth_date)}`
|
||||||
|
: "",
|
||||||
|
},
|
||||||
].map((row: any, rowIndex) => {
|
].map((row: any, rowIndex) => {
|
||||||
return <RowPDF row={row} rowIndex={rowIndex} key={rowIndex} />;
|
return <RowPDF row={row} rowIndex={rowIndex} key={rowIndex} />;
|
||||||
})}
|
})}
|
||||||
|
|
@ -159,7 +166,12 @@ export const DocumentBiodata: FC<any> = ({ data, onRender }) => {
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
label: "Jenis Kelamin 性别",
|
label: "Jenis Kelamin 性别",
|
||||||
value: "L 男 / P 女",
|
value:
|
||||||
|
data?.gender === "FEMALE"
|
||||||
|
? "P 女"
|
||||||
|
: data?.gender === "MALE"
|
||||||
|
? "L 男"
|
||||||
|
: "L 男 / P 女",
|
||||||
mode: "noline",
|
mode: "noline",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -180,7 +192,7 @@ export const DocumentBiodata: FC<any> = ({ data, onRender }) => {
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{ label: "No. KTP 身份证号码", value: "" },
|
{ label: "No. KTP 身份证号码", value: "" },
|
||||||
{ label: "Agama 宗教", value: "" },
|
{ label: "Agama 宗教", value: data?.religion },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{ label: "Masa Berlaku KTP 身份证有效期", value: "" },
|
{ label: "Masa Berlaku KTP 身份证有效期", value: "" },
|
||||||
|
|
@ -202,9 +214,9 @@ export const DocumentBiodata: FC<any> = ({ data, onRender }) => {
|
||||||
value: "",
|
value: "",
|
||||||
// mode: "placeholder",
|
// mode: "placeholder",
|
||||||
},
|
},
|
||||||
{ label: "Alamat Lengkap 地址", value: "" },
|
{ label: "Alamat Lengkap 地址", value: data?.address },
|
||||||
{ label: "Alamat Lengkap Asal 故乡地址", value: "" },
|
{ label: "Alamat Lengkap Asal 故乡地址", value: "" },
|
||||||
{ label: "Alamat Email 电子邮件地址", value: "" },
|
{ label: "Alamat Email 电子邮件地址", value: data?.user?.email },
|
||||||
].map((row: any, rowIndex) => {
|
].map((row: any, rowIndex) => {
|
||||||
return <RowPDF row={row} rowIndex={rowIndex} key={rowIndex} />;
|
return <RowPDF row={row} rowIndex={rowIndex} key={rowIndex} />;
|
||||||
})}
|
})}
|
||||||
|
|
@ -726,7 +738,9 @@ export const DocumentBiodata: FC<any> = ({ data, onRender }) => {
|
||||||
borderRight: 1,
|
borderRight: 1,
|
||||||
borderColor: "black",
|
borderColor: "black",
|
||||||
}}
|
}}
|
||||||
></Text>
|
>
|
||||||
|
{}
|
||||||
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
width: 200,
|
width: 200,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
export const findLastEducation = (searchTerm: string, userEducation: any[]) => {
|
||||||
|
if (!Array.isArray(userEducation) || userEducation.length === 0) {
|
||||||
|
return null; // Jika array kosong, kembalikan null
|
||||||
|
}
|
||||||
|
|
||||||
|
const educationMapping: Record<string, string | string[]> = {
|
||||||
|
SD: "10 - Junior High School",
|
||||||
|
SLTP: "9 - Senior High School",
|
||||||
|
SLTA: "3 - Bachelor",
|
||||||
|
"D 1": "4 - Diploma 1",
|
||||||
|
"D 2": "5 - Diploma 2",
|
||||||
|
"D 3": "6 - Diploma 3",
|
||||||
|
"D 1/2/3": ["4 - Diploma 1", "5 - Diploma 2", "6 - Diploma 3"], // Cari D1/D2/D3 tertinggi & terbaru
|
||||||
|
S1: ["3 - Bachelor", "7 - Diploma 4"], // S1 setara dengan D4
|
||||||
|
S2: "2 - Master Degree",
|
||||||
|
S3: "1 - Doctoral / Professor",
|
||||||
|
};
|
||||||
|
|
||||||
|
const mappedValue = educationMapping[searchTerm];
|
||||||
|
if (!mappedValue) return null;
|
||||||
|
|
||||||
|
let filteredEducations;
|
||||||
|
|
||||||
|
if (Array.isArray(mappedValue)) {
|
||||||
|
// Jika "D 1/2/3" atau "S1" (D4)
|
||||||
|
filteredEducations = userEducation.filter((edu) =>
|
||||||
|
mappedValue.includes(edu.education_level)
|
||||||
|
);
|
||||||
|
if (filteredEducations.length === 0) return null;
|
||||||
|
|
||||||
|
// Pilih jenjang tertinggi, jika sama maka pilih graduate_year terbaru
|
||||||
|
return filteredEducations.reduce((highest, current) => {
|
||||||
|
const highestIndex = mappedValue.indexOf(highest.education_level);
|
||||||
|
const currentIndex = mappedValue.indexOf(current.education_level);
|
||||||
|
|
||||||
|
if (currentIndex > highestIndex) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
if (currentIndex === highestIndex) {
|
||||||
|
return current.graduate_year > highest.graduate_year
|
||||||
|
? current
|
||||||
|
: highest;
|
||||||
|
}
|
||||||
|
return highest;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Jika hanya satu jenjang (misalnya SD, SLTP, SLTA, S2, S3)
|
||||||
|
filteredEducations = userEducation.filter(
|
||||||
|
(edu) => edu.education_level === mappedValue
|
||||||
|
);
|
||||||
|
if (filteredEducations.length === 0) return null;
|
||||||
|
|
||||||
|
// Pilih graduate_year terbaru
|
||||||
|
return filteredEducations.reduce((latest, current) =>
|
||||||
|
current.graduate_year > latest.graduate_year ? current : latest
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue