380 lines
15 KiB
TypeScript
380 lines
15 KiB
TypeScript
import { useLocation } from 'react-router-dom';
|
|
import { useLanguage } from '@/i18n';
|
|
import axios from 'axios';
|
|
import { fCurrency } from '@/utils/FormatNumber';
|
|
import { DefaultTooltip, KeenIcon } from '@/components';
|
|
import { Button } from '@/components/ui/button';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { createContext, useEffect, useState } from 'react';
|
|
import { apiConfig } from '@/config/api.config';
|
|
import moment from 'moment';
|
|
|
|
import {
|
|
statusCreditList,
|
|
toCamelCase,
|
|
toAbsoluteUrl,
|
|
ApplicationFileDownloadUrl,
|
|
getFileExtension,
|
|
snakeToTitleCase
|
|
} from '@/utils';
|
|
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue
|
|
} from '@/components/ui/select';
|
|
import { useAuthContext } from '@/auth';
|
|
import { ChatMessageIn, ChatMessageOut, Notes } from '../blocks';
|
|
import { Textarea } from '@/components/ui/textarea';
|
|
|
|
const API_URL = apiConfig.service_credit;
|
|
const CreditDetailContext = createContext<any | null>(null);
|
|
|
|
const CreditDetailContextProvider = ({ children }: { children: React.ReactNode }) => {
|
|
const navigate = useNavigate();
|
|
const [data, setData] = useState<any>({});
|
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const { isRTL } = useLanguage();
|
|
const { state } = useLocation();
|
|
const { id, code, status } = state || {};
|
|
const { auth } = useAuthContext();
|
|
|
|
const handleBackClick = () => {
|
|
navigate('/pengajuan_kredit/list');
|
|
};
|
|
|
|
useEffect(() => {
|
|
const fetchData = async () => {
|
|
if (!id) return;
|
|
setIsLoading(true);
|
|
setError(null);
|
|
try {
|
|
const response = await axios.get(`${API_URL}/application/detail/${id}`);
|
|
setData(response.data.data || {});
|
|
console.log('data:', data.form);
|
|
} catch (err) {
|
|
setError('Failed to fetch data');
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchData();
|
|
}, [id]);
|
|
|
|
const DivImageAction = (
|
|
fileName: string,
|
|
fileStatus: string,
|
|
onChange: (value: string) => void
|
|
) => (
|
|
<>
|
|
<a href={ApplicationFileDownloadUrl(API_URL, auth?.access_token, fileName)} target="_blank">
|
|
<img
|
|
src={toAbsoluteUrl(
|
|
`/media/file-types/${getFileExtension(fileName) == 'dpf' ? 'pdf.svg' : 'image.svg'}`
|
|
)}
|
|
className=""
|
|
alt=""
|
|
/>
|
|
</a>
|
|
|
|
<Select
|
|
value={fileStatus}
|
|
onValueChange={onChange}
|
|
disabled={data.status == 'revision' ? true : false}
|
|
>
|
|
<SelectTrigger size="sm" className="w-28">
|
|
<SelectValue placeholder="Action" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value={'approved'}>Approved</SelectItem>
|
|
<SelectItem value={'rejected'}>Rejected</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</>
|
|
);
|
|
|
|
if (isLoading) {
|
|
return <div className="text-center">Fetching data...</div>;
|
|
}
|
|
|
|
if (error) {
|
|
return <div>{error}</div>;
|
|
}
|
|
|
|
return (
|
|
<div className="px-5" style={{ marginTop: '-1.25rem' }}>
|
|
<div className="flex justify-between items-center mb-5">
|
|
<div className="flex items-center">
|
|
<DefaultTooltip title={'Back to list'} placement={'top'}>
|
|
<Button
|
|
variant="outline"
|
|
className="h-7.5 border-0 px-0 me-[14px]"
|
|
onClick={handleBackClick}
|
|
>
|
|
<KeenIcon icon="arrow-left" className="text-[20px] px-1 card-title" />
|
|
</Button>
|
|
</DefaultTooltip>
|
|
<p className="font-semibold text-[22px] card-title">{code}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="lg:flex md:flex-row sm:flex-row gap-5 justify-between">
|
|
<div className="flex-row gap-5 w-full">
|
|
<div className=" card shadow-none border-0 w-full ">
|
|
<div className="card-body p-3 pl-10 pr-10">
|
|
<p className="card-title text-[14px]">Credit Request</p>
|
|
<hr className="my-2 border-dashed border-gray-300" />
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">BRI Account Number</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{data?.account_number || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Amount</p>
|
|
<p className="text-[14px] text-end" style={{ color: '#212121' }}>
|
|
{fCurrency(data?.amount) || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Period</p>
|
|
<p className="text-[14px] text-end" style={{ color: '#212121' }}>
|
|
{data?.period_amount} {toCamelCase(data?.period_type) || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Status</p>
|
|
<p className="text-[14px] text-end" style={{ color: '#212121' }}>
|
|
{snakeToTitleCase(data?.status) || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="card shadow-none border-0 w-full ">
|
|
<div className="card-body p-3 pl-10 pr-10">
|
|
<p className="card-title text-[14px]">Debitur Info's</p>
|
|
<hr className="my-2 border-dashed border-gray-300" />
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Application Date</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{moment(data?.application_date).format('dddd, MMMM DD, YYYY') || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Company</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{data?.company?.name || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Employee Id</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{data?.debtor?.employee_id || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Name</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{data?.debtor?.name || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Phone Number</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{data?.debtor?.phone || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center mb-4">
|
|
<p className="text-[14px] w-3/12">Type</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{toCamelCase(data?.debtor?.type) || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
<div className="flex align-center">
|
|
<p className="text-[14px] w-3/12">Mariage</p>
|
|
<p className="text-[14px]" style={{ color: '#212121' }}>
|
|
{data?.debtor?.marriage_type || 'Loading...'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className=" card shadow-none border-0 w-full ">
|
|
<div className="card-body p-3 pl-10 pr-10">
|
|
<p className="card-title text-[14px]">Note's</p>
|
|
<hr className="my-2 border-dashed border-gray-300" />
|
|
<div className="flex flex-col gap-5 py-5">
|
|
{data?.chat
|
|
?.sort(
|
|
(a: any, b: any) =>
|
|
new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
|
|
)
|
|
.map(
|
|
(
|
|
message: {
|
|
name: string;
|
|
company: string;
|
|
message: string;
|
|
created_at: string;
|
|
},
|
|
index: number
|
|
) => (
|
|
<Notes
|
|
key={'CHATS++' + index}
|
|
userName={message.name}
|
|
avatar={
|
|
message.company == 'BRI'
|
|
? '/media/app/mini-logo.svg'
|
|
: '/media/avatars/blank.png'
|
|
}
|
|
description={''}
|
|
time={moment(message.created_at).format('ddd DD MMM, hh.mm A')}
|
|
text={message.message}
|
|
/>
|
|
)
|
|
)}
|
|
|
|
<Textarea
|
|
className="input focus-visible:ring-offset-0 focus-visible:ring-0"
|
|
// value={formField.description}
|
|
// onChange={({ target }) =>
|
|
// setFormField((prev) => ({ ...prev, description: target.value }))
|
|
// }
|
|
></Textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex-row gap-5 w-full">
|
|
<div className=" card shadow-none border-0 w-full ">
|
|
<div className="card-body p-3 pl-10 pr-10">
|
|
<p className="card-title text-[14px]">Debitur Document's</p>
|
|
<hr className="my-2 border-dashed border-gray-300" />
|
|
<div className="flex gap-3 justify-between align-center mb-4">
|
|
<p className="text-[14px]">
|
|
{toCamelCase(data?.debtor?.identity_type) || 'Loading...'}
|
|
</p>
|
|
<div className="flex justify-between gap-3 items-center">
|
|
{data?.debtor?.identity_file &&
|
|
DivImageAction(
|
|
data?.debtor?.identity_file,
|
|
data.debtor.identity_file_status,
|
|
() => {}
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="flex gap-3 justify-between align-center mb-4">
|
|
<p className="text-[14px]">Kartu Keluarga (Vica Familia)</p>
|
|
<div className="flex justify-between gap-3 items-center">
|
|
{data?.debtor?.family_file &&
|
|
DivImageAction(
|
|
data?.debtor?.family_file,
|
|
data?.debtor?.family_file_status,
|
|
() => {}
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="flex gap-3 justify-between align-center mb-4">
|
|
<p className="text-[14px]">{data?.debtor?.marriage_type || 'Loading...'}</p>
|
|
<div className="flex justify-between gap-3 items-center">
|
|
{data?.debtor?.marriage_file &&
|
|
DivImageAction(
|
|
data?.debtor?.marriage_file,
|
|
data?.debtor?.marriage_file_status,
|
|
() => {}
|
|
)}
|
|
</div>
|
|
</div>
|
|
{data?.debtor?.photo && (
|
|
<div className="flex gap-3 justify-between align-center mb-4">
|
|
<p className="text-[14px]">Photo</p>
|
|
<div className="flex justify-between gap-3 items-center">
|
|
{data?.debtor?.photo &&
|
|
DivImageAction(
|
|
data?.debtor?.photo, //
|
|
data?.debtor?.photo_status,
|
|
() => {}
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
{data?.debtor?.spouse_photo && (
|
|
<div className="flex gap-3 justify-between align-center mb-4">
|
|
<p className="text-[14px]">Spouse ({data?.debtor?.spouse_type}) Photo</p>
|
|
<div className="flex justify-between gap-3 items-center">
|
|
{data?.debtor?.spouse_photo &&
|
|
DivImageAction(
|
|
data?.debtor?.spouse_photo, //
|
|
data?.debtor?.spouse_photo_status,
|
|
() => {}
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
{data?.debtor?.spouse_type && (
|
|
<div className="flex gap-3 justify-between align-center">
|
|
<p className="text-[14px]">
|
|
Spouse ({data?.debtor?.spouse_type}) {data?.debtor?.spouse_file_type}
|
|
</p>
|
|
<div className="flex justify-between gap-3 items-center">
|
|
{data?.debtor?.spouse_file &&
|
|
DivImageAction(
|
|
data?.debtor?.spouse_file, //
|
|
data?.debtor?.spouse_file_status,
|
|
() => {}
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className=" card shadow-none border-0 w-full ">
|
|
<div className="card-body p-3 pl-10 pr-10">
|
|
<p className="card-title text-[14px]">Supporting Document's</p>
|
|
<hr className="my-2 border-dashed border-gray-300" />
|
|
{data?.form?.map(
|
|
(item: { label: string; value: string; status: string }, index: any) => (
|
|
<div
|
|
key={`appDetailSupportDocument${index}`}
|
|
className="flex gap-3 justify-between align-start mb-4"
|
|
>
|
|
<p className="text-[14px] w-8/12">{item.label}</p>
|
|
<div className="flex justify-between gap-3 items-center">
|
|
{item.value && DivImageAction(item.value, item.status, () => {})}
|
|
</div>
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-center gap-5">
|
|
<div className="">
|
|
<Button
|
|
className="px-5 text-[14px] w-48 btn btn-danger bg-danger"
|
|
style={{ borderRadius: 50 }}
|
|
>
|
|
Tolak
|
|
</Button>
|
|
</div>
|
|
<div className="">
|
|
<Button
|
|
className="px-5 text-[14px] w-48 btn btn-success bg-success"
|
|
style={{ borderRadius: 50 }}
|
|
>
|
|
Terima
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { CreditDetailContext, CreditDetailContextProvider };
|