revamp template
This commit is contained in:
@ -0,0 +1,379 @@
|
||||
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 };
|
||||
Reference in New Issue
Block a user