commit client portal
This commit is contained in:
147
Modules/Client/Http/Controllers/Api/ClaimRequestController.php
Normal file
147
Modules/Client/Http/Controllers/Api/ClaimRequestController.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Client\Http\Controllers\Api;
|
||||
|
||||
use App\Events\ClaimRequested;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\File;
|
||||
use App\Models\Member;
|
||||
use App\Services\ClaimRequestService;
|
||||
use Illuminate\Contracts\Support\Renderable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class ClaimRequestController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* @return Renderable
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('client::index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
* @return Renderable
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('client::create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* @param Request $request
|
||||
* @return Renderable
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'member_id' => 'required',
|
||||
'service_code' => 'required|in:OP,IP'
|
||||
]);
|
||||
|
||||
$member = Member::find($request->member_id);
|
||||
$newClaimRequest = ClaimRequestService::storeClaimRequest(member: $member, paymentType: 'reimbursement', serviceCode: $request->service_code);
|
||||
|
||||
ClaimRequested::dispatch($newClaimRequest);
|
||||
|
||||
// Log History
|
||||
$newClaimRequest->histories()->create([
|
||||
'title' => 'New Claim Requested',
|
||||
'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})",
|
||||
'type' => 'info',
|
||||
'system_origin' => 'hospital-portal'
|
||||
]);
|
||||
|
||||
if ($request->hasFile('result_files')) {
|
||||
foreach ($request->result_files as $file) {
|
||||
$pathFile = File::storeFile('claim-result', $newClaimRequest->id, $file);
|
||||
$newClaimRequest->files()->updateOrCreate([
|
||||
'type' => 'claim-result',
|
||||
'name' => File::getFileName('claim-result', $newClaimRequest->id, $file),
|
||||
'original_name' => $file->getClientOriginalName(),
|
||||
'extension' => $file->getClientOriginalExtension(),
|
||||
'path' => $pathFile,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->hasFile('diagnosa_files')) {
|
||||
foreach ($request->diagnosa_files as $file) {
|
||||
$pathFile = File::storeFile('claim-diagnosis', $newClaimRequest->id, $file);
|
||||
$newClaimRequest->files()->updateOrCreate([
|
||||
'type' => 'claim-diagnosis',
|
||||
'name' => File::getFileName('claim-diagnosis', $newClaimRequest->id, $file),
|
||||
'original_name' => $file->getClientOriginalName(),
|
||||
'extension' => $file->getClientOriginalExtension(),
|
||||
'path' => $pathFile,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->hasFile('kondisi_files')) {
|
||||
foreach ($request->kondisi_files as $file) {
|
||||
$pathFile = File::storeFile('claim-kondisi', $newClaimRequest->id, $file);
|
||||
$newClaimRequest->files()->updateOrCreate([
|
||||
'type' => 'claim-kondisi',
|
||||
'name' => File::getFileName('claim-kondisi', $newClaimRequest->id, $file),
|
||||
'original_name' => $file->getClientOriginalName(),
|
||||
'extension' => $file->getClientOriginalExtension(),
|
||||
'path' => $pathFile,
|
||||
'created_by' => auth()->user()->id,
|
||||
'updated_by' => auth()->user()->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return Helper::responseJson(data: $request->toArray(), message: 'Claim Request berhasil ajukan!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
return view('client::show');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
return view('client::edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use Illuminate\Contracts\Support\Renderable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Client\Transformers\ClaimReport\MemberResources as ClaimReportMemberResources;
|
||||
use Modules\Client\Transformers\Dashboard\MemberResources as ClaimSubmitMemberResources;
|
||||
use Modules\Client\Transformers\Dashboard\MemberResources as DashboardMemberResources;
|
||||
use Modules\Client\Transformers\Dashboard\MemberAlarmCenterResources as DashboardMemberAlarmResources;
|
||||
use Modules\Client\Transformers\DataMemberResource;
|
||||
@@ -31,7 +32,7 @@ class CorporateMemberController extends Controller
|
||||
return response()->json(Helper::paginateResources(ClaimReportMemberResources::collection($members)));
|
||||
case 'claim-submit':
|
||||
$members = $this->corporateMemberService->getAllMemberClaimReports($corporate_id, $request);
|
||||
return response()->json(Helper::paginateResources(ClaimReportMemberResources::collection($members)));
|
||||
return response()->json(Helper::paginateResources(ClaimSubmitMemberResources::collection($members)));
|
||||
case 'alarm-center':
|
||||
$members = $this->corporateMemberService->getAllMemberAlarmCenter($corporate_id, $request);
|
||||
return response()->json(Helper::paginateResources(DashboardMemberAlarmResources::collection($members)));
|
||||
|
||||
@@ -11,6 +11,7 @@ use Modules\Client\Http\Controllers\Api\ClaimController;
|
||||
use Modules\Client\Http\Controllers\Api\TopUpController;
|
||||
use Modules\Internal\Http\Controllers\ClaimEncounterController;
|
||||
use App\Models\Encounter;
|
||||
use Modules\Client\Http\Controllers\Api\ClaimRequestController;
|
||||
use Modules\Client\Http\Controllers\Api\DataController;
|
||||
use Modules\Internal\Transformers\EncounterResource;
|
||||
|
||||
@@ -54,5 +55,7 @@ Route::prefix('client')->group(function () {
|
||||
Route::post('topup', [TopUpController::class, 'store']);
|
||||
});
|
||||
Route::get('claims/{id}', [ClaimController::class, 'show']);
|
||||
|
||||
Route::post('claim-requests', [ClaimRequestController::class, 'store'])->name('claim-requests.store');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ class CorporateMemberService
|
||||
'division' => 'corporate_divisions.name',
|
||||
default => ''
|
||||
};
|
||||
if ($request->order){
|
||||
if ($request->order) {
|
||||
$query->getQuery()->orderBy($orderBy, $request->order);
|
||||
}
|
||||
})
|
||||
@@ -48,7 +48,6 @@ class CorporateMemberService
|
||||
$limit = $request->has('perPage') ? $request->input('perPage') : 10;
|
||||
|
||||
return Member::query()
|
||||
->joinClaimRequests('right')
|
||||
->joinCorporateEmployees('left')
|
||||
->joinCorporateDivisions('left')
|
||||
->with('currentPlan')
|
||||
@@ -62,11 +61,6 @@ class CorporateMemberService
|
||||
->orWhere('members.name', 'like', "%" . $search . "%");
|
||||
});
|
||||
})
|
||||
->when($request->input('division'), function (Builder $division, $value) {
|
||||
$division->whereHas('division', function (Builder $corporateEmployee) use ($value) {
|
||||
$corporateEmployee->where('division_id', $value);
|
||||
});
|
||||
})
|
||||
->when($request->has('orderBy'), function (Builder $query) use ($request) {
|
||||
$orderBy = match ($request->orderBy) {
|
||||
'memberId' => 'member_id',
|
||||
@@ -80,7 +74,7 @@ class CorporateMemberService
|
||||
$query->getQuery()->orderBy('corporate_divisions.name', $request->order);
|
||||
}
|
||||
})
|
||||
->select(['members.id', 'members.person_id', 'members.member_id', 'members.name', 'corporate_divisions.name AS division_name', 'members.active', 'claim_requests.id', 'claim_requests.member_id', 'claim_requests.submission_date'])
|
||||
->select(['members.id', 'members.person_id', 'members.member_id', 'members.name', 'corporate_divisions.name AS division_name', 'members.active'])
|
||||
->paginate($limit);
|
||||
}
|
||||
|
||||
@@ -122,8 +116,8 @@ class CorporateMemberService
|
||||
->paginate($limit);
|
||||
}
|
||||
|
||||
public function getAllEncounter(int $corporateId){
|
||||
public function getAllEncounter(int $corporateId)
|
||||
{
|
||||
return Encounter::query()->select(['id'])->paginate(10);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ type CardPolicyProps = {
|
||||
members: {
|
||||
memberId: string;
|
||||
memberFullName: string;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -194,7 +194,6 @@ export default function CardPolicy(props: CardPolicyProps) {
|
||||
openDialog={openDialog}
|
||||
setOpenDialog={setOpenDialog}
|
||||
title={{ name: dialogTitle }}
|
||||
data={members}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ import {
|
||||
IconButton,
|
||||
} from '@mui/material';
|
||||
import { Search as SearchIcon } from '@mui/icons-material';
|
||||
import axios from '../../utils/axios';
|
||||
// components
|
||||
import MuiDialog from '../../components/MuiDialog';
|
||||
import Iconify from '../../components/Iconify';
|
||||
import { useSnackbar } from 'notistack';
|
||||
// React
|
||||
import { ReactElement, useState } from 'react';
|
||||
import DialogClaimSubmitMemberSubmission from './DialogClaimSubmitMemberSubmission';
|
||||
import { ReactElement, useContext, useEffect, useState } from 'react';
|
||||
import DialogRequestLog from './DialogRequestLog';
|
||||
import axios from '../../utils/axios';
|
||||
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -45,7 +45,7 @@ type MuiDialogProps = {
|
||||
openDialog: boolean;
|
||||
setOpenDialog: Function;
|
||||
content?: ReactElement;
|
||||
data?: DataContentType[];
|
||||
// data?: DataContent[];
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -68,9 +68,11 @@ export default function DialogClaimSubmitMember({
|
||||
title,
|
||||
openDialog,
|
||||
setOpenDialog,
|
||||
data,
|
||||
}: MuiDialogProps) {
|
||||
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||
|
||||
/* ---------------------------------- data ---------------------------------- */
|
||||
const [data, setData] = useState([]);
|
||||
const [dataMemberClaim, setDataMemberClaim] = useState<DataContentType>({
|
||||
id: 0,
|
||||
fullName: '',
|
||||
@@ -85,31 +87,16 @@ export default function DialogClaimSubmitMember({
|
||||
|
||||
/* --------------------------------- Search --------------------------------- */
|
||||
const [searchText, setSearchText] = useState('');
|
||||
/* --------------------------------- Benefit--------------------------------- */
|
||||
const {enqueueSnackbar} = useSnackbar();
|
||||
const [openDialogBenefit, setOpenDialogBenefit] = useState(false);
|
||||
const [currentMember, setCurrentMember] = useState(null);
|
||||
const [nameMember, setNameMember] = useState('');
|
||||
const [loadingBenefit, setLoadingBenefit] = useState(false);
|
||||
const [appliedParams, setAppliedParams] = useState({});
|
||||
|
||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
// await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
// setLoadingBenefit(true)
|
||||
|
||||
// axios.post('/search-member', {
|
||||
// search: searchText,
|
||||
// })
|
||||
// .then((response) => {
|
||||
// setOpenDialogBenefit(true)
|
||||
// setCurrentMember(response.data.data)
|
||||
// setNameMember(response.data.data.name);
|
||||
// })
|
||||
// .catch(({response}) => {
|
||||
// enqueueSnackbar(response.data.errors ? response.data.errors[0] : (response.data ? response.data.meta.message : 'Opps, Something went Wrong!'), {variant : "error"})
|
||||
// })
|
||||
// .then(() => {
|
||||
// setLoadingBenefit(false)
|
||||
// });
|
||||
event.preventDefault();
|
||||
if (searchText === '') {
|
||||
setAppliedParams({});
|
||||
} else {
|
||||
setAppliedParams({ search: searchText });
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@@ -119,7 +106,7 @@ export default function DialogClaimSubmitMember({
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ Icon On Click ----------------------------- */
|
||||
const [openDialogClaimMember, setOpenDialogMemberClaim] = useState(false);
|
||||
const [openDialogRequestLog, setOpenDialogRequestLog] = useState(false);
|
||||
|
||||
const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => {
|
||||
setDataMemberClaim({
|
||||
@@ -136,10 +123,22 @@ export default function DialogClaimSubmitMember({
|
||||
title: avatar && avatar.title,
|
||||
},
|
||||
});
|
||||
setOpenDialogMemberClaim(true);
|
||||
setOpenDialogRequestLog(true);
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (openDialog === true) {
|
||||
const response = await axios.get(`${corporateValue}/members`, {
|
||||
params: { ...appliedParams, type: 'claim-submit' },
|
||||
});
|
||||
|
||||
setData(response.data.data);
|
||||
}
|
||||
})();
|
||||
}, [corporateValue, openDialog, appliedParams]);
|
||||
|
||||
const getContent = () => (
|
||||
<Stack>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" paddingY={1}>
|
||||
@@ -168,57 +167,58 @@ export default function DialogClaimSubmitMember({
|
||||
/>
|
||||
</form>
|
||||
<Stack marginTop={2} spacing={1}>
|
||||
{data &&
|
||||
data.map((row: DataContentType, key) => (
|
||||
<Card key={key} sx={{ paddingY: 1, paddingX: 2 }}>
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<img
|
||||
width={40}
|
||||
height={40}
|
||||
src={row.avatar ? row.avatar.url : '/images/member.png'}
|
||||
alt={row.avatar ? row.avatar.url : 'user-profile'}
|
||||
style={{ borderRadius: '50%' }}
|
||||
/>
|
||||
<Stack sx={{ flex: '45%' }}>
|
||||
<Typography variant="subtitle1">{row.fullName}</Typography>
|
||||
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
|
||||
Member ID : {row.memberId}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Stack spacing={1} paddingY={1}>
|
||||
<Typography color="#0A0A0A" variant="caption">
|
||||
Total Limit
|
||||
</Typography>
|
||||
<BorderLinearProgress
|
||||
variant="determinate"
|
||||
value={row.limit && row.limit.percentage}
|
||||
/>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 500 }}>
|
||||
{row.limit && row.limit.current} /{' '}
|
||||
<Typography variant="body2" color="#757575" component="span">
|
||||
{row.limit && row.limit.total}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Stack>
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
clickHandler({
|
||||
id: row.id,
|
||||
fullName: row.fullName,
|
||||
memberId: row.memberId,
|
||||
limit: {
|
||||
current: row.limit.current,
|
||||
total: row.limit.total,
|
||||
percentage: row.limit.percentage,
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
<Iconify icon="ic:round-chevron-right" />
|
||||
</IconButton>
|
||||
{data.map((row: DataContentType, key) => (
|
||||
<Card
|
||||
key={key}
|
||||
sx={{ paddingY: 1, paddingX: 2 }}
|
||||
onClick={() =>
|
||||
clickHandler({
|
||||
id: row.id,
|
||||
fullName: row.fullName,
|
||||
memberId: row.memberId,
|
||||
limit: {
|
||||
current: row.limit.current,
|
||||
total: row.limit.total,
|
||||
percentage: row.limit.percentage,
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<img
|
||||
width={40}
|
||||
height={40}
|
||||
src={row.avatar ? row.avatar.url : '/images/member.png'}
|
||||
alt={row.avatar ? row.avatar.url : 'user-profile'}
|
||||
style={{ borderRadius: '50%' }}
|
||||
/>
|
||||
<Stack sx={{ flex: '45%' }}>
|
||||
<Typography variant="subtitle1">{row.fullName}</Typography>
|
||||
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
|
||||
Member ID : {row.memberId}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Card>
|
||||
))}
|
||||
<Stack spacing={1} paddingY={1}>
|
||||
<Typography color="#0A0A0A" variant="caption">
|
||||
Total Limit
|
||||
</Typography>
|
||||
<BorderLinearProgress
|
||||
variant="determinate"
|
||||
value={row.limit && row.limit.percentage}
|
||||
/>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 500 }}>
|
||||
{row.limit && row.limit.current} /{' '}
|
||||
<Typography variant="body2" color="#757575" component="span">
|
||||
{row.limit && row.limit.total}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Stack>
|
||||
<IconButton>
|
||||
<Iconify icon="ic:round-chevron-right" />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
@@ -233,10 +233,9 @@ export default function DialogClaimSubmitMember({
|
||||
maxWidth="sm"
|
||||
/>
|
||||
|
||||
<DialogClaimSubmitMemberSubmission
|
||||
title={title}
|
||||
openDialog={openDialogClaimMember}
|
||||
setOpenDialog={setOpenDialogMemberClaim}
|
||||
<DialogRequestLog
|
||||
openDialog={openDialogRequestLog}
|
||||
setOpenDialog={setOpenDialogRequestLog}
|
||||
data={dataMemberClaim}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -1,371 +0,0 @@
|
||||
// @mui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import {
|
||||
Typography,
|
||||
LinearProgress,
|
||||
linearProgressClasses,
|
||||
Stack,
|
||||
Card,
|
||||
Button,
|
||||
Link,
|
||||
Switch,
|
||||
SwitchProps,
|
||||
ButtonGroup,
|
||||
} from '@mui/material';
|
||||
import { Add as AddIcon, Cancel as CancelIcon } from '@mui/icons-material';
|
||||
// components
|
||||
import MuiDialog from '../../components/MuiDialog';
|
||||
import Iconify from '../../components/Iconify';
|
||||
import { FormProvider } from '../../components/hook-form';
|
||||
// React
|
||||
import { ReactElement, useEffect, useState } from 'react';
|
||||
// yup
|
||||
import * as Yup from 'yup';
|
||||
// form
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { fSplit } from '../../utils/formatNumber';
|
||||
|
||||
/* ---------------------------------- types --------------------------------- */
|
||||
type DataContentType = {
|
||||
id: number;
|
||||
fullName: string;
|
||||
memberId: string;
|
||||
limit: {
|
||||
current: number;
|
||||
total: number;
|
||||
percentage: number;
|
||||
};
|
||||
avatar?: {
|
||||
url?: string;
|
||||
title?: string;
|
||||
};
|
||||
};
|
||||
|
||||
type MuiDialogProps = {
|
||||
title?: {
|
||||
name?: string;
|
||||
icon?: string;
|
||||
};
|
||||
openDialog: boolean;
|
||||
setOpenDialog: Function;
|
||||
content?: ReactElement;
|
||||
data: DataContentType;
|
||||
};
|
||||
|
||||
type BorderLinearProgressProps = {
|
||||
percentage: number;
|
||||
};
|
||||
|
||||
type FormValuesProps = {
|
||||
invoice: '';
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* --------------------------------- styles --------------------------------- */
|
||||
const BorderLinearProgress = styled(LinearProgress)<BorderLinearProgressProps>(
|
||||
({ theme, percentage }) => ({
|
||||
height: 10,
|
||||
borderRadius: 6,
|
||||
[`&.${linearProgressClasses.colorPrimary}`]: {
|
||||
backgroundColor: theme.palette.grey[theme.palette.mode === 'light' ? 300 : 800],
|
||||
},
|
||||
[`& .${linearProgressClasses.bar}`]: {
|
||||
borderRadius: 6,
|
||||
background: 'linear-gradient(270deg, #19BBBB 38.42%, #FF9565 76.21%, #FE7253 104.02%)',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: 0,
|
||||
width: `${100 - percentage}%`,
|
||||
zIndex: 1,
|
||||
bottom: 0,
|
||||
background: '#DFE3E8',
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const DialogClaimSubmitMemberSubmission = ({
|
||||
title,
|
||||
openDialog,
|
||||
setOpenDialog,
|
||||
data,
|
||||
}: MuiDialogProps) => {
|
||||
/* ---------------------------- Get Current Date ---------------------------- */
|
||||
const current = new Date();
|
||||
const date = `${current.getDate()} / ${current.getMonth() + 1} / ${current.getFullYear()}`;
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------- file input ------------------------------- */
|
||||
// const [multipleImages, setMultipleImages] = useState([]);
|
||||
|
||||
// Functions to preview multiple images
|
||||
// const changeMultipleFiles = (e) => {
|
||||
// if (e.target.files) {
|
||||
// const imageArray = Array.from(e.target.files).map((file) => URL.createObjectURL(file));
|
||||
// setMultipleImages((prevImages) => prevImages.concat(imageArray));
|
||||
// }
|
||||
// };
|
||||
|
||||
// const render = (data) => {
|
||||
// data.map((image) => {
|
||||
// <Typography key={image}>{image}</Typography>;
|
||||
// });
|
||||
// };
|
||||
|
||||
// const FileForm = (props: any) => (
|
||||
// <input
|
||||
// type="file"
|
||||
// multiple
|
||||
// {...register('invoice', { required: true })}
|
||||
// onChange={changeMultipleFiles}
|
||||
// />
|
||||
// );
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------- Form Submit ------------------------------ */
|
||||
const ClaimSubmitSchema = Yup.object().shape({
|
||||
invoice: Yup.mixed()
|
||||
.required('You need to provide a file')
|
||||
// @ts-ignore
|
||||
.test('fileSize', 'The file is too large', (value) => {
|
||||
for (let index = 0; index < value.length; index++) {
|
||||
return value ? value[index].size <= 2000000 : false;
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
const methods = useForm<FormValuesProps>({
|
||||
resolver: yupResolver(ClaimSubmitSchema),
|
||||
});
|
||||
|
||||
const {
|
||||
register,
|
||||
reset,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting, errors },
|
||||
} = methods;
|
||||
|
||||
// const {
|
||||
// register,
|
||||
// reset,
|
||||
// handleSubmit,
|
||||
// formState: { isSubmitting },
|
||||
// } = useForm({ resolver: yupResolver(ClaimSubmitSchema) });
|
||||
|
||||
const onSubmit = ({ invoice }: FormValuesProps) => {
|
||||
// console.log(invoice);
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ---------------------------- Ios Switch Style ---------------------------- */
|
||||
const IosSwitch = styled((props: SwitchProps) => (
|
||||
<Switch focusVisibleClassName=".Mui-focusVisible" disableRipple {...props} />
|
||||
))(({ theme }) => ({
|
||||
width: 28,
|
||||
height: 16,
|
||||
padding: 0,
|
||||
marginRight: '10px',
|
||||
'& .MuiSwitch-switchBase': {
|
||||
padding: 0,
|
||||
margin: 2,
|
||||
transitionDuration: '300ms',
|
||||
'&.Mui-checked': {
|
||||
transform: 'translateX(12px)',
|
||||
color: '#fff',
|
||||
'& + .MuiSwitch-track': {
|
||||
opacity: 1,
|
||||
border: 0,
|
||||
},
|
||||
'&.Mui-disabled + .MuiSwitch-track': {
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
'&.Mui-focusVisible .MuiSwitch-thumb': {
|
||||
color: '#33cf4d',
|
||||
border: '6px solid #fff',
|
||||
},
|
||||
'&.Mui-disabled .MuiSwitch-thumb': {
|
||||
color: theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[600],
|
||||
},
|
||||
'&.Mui-disabled + .MuiSwitch-track': {
|
||||
opacity: theme.palette.mode === 'light' ? 0.7 : 0.3,
|
||||
},
|
||||
},
|
||||
'& .MuiSwitch-thumb': {
|
||||
boxSizing: 'border-box',
|
||||
width: 12,
|
||||
height: 12,
|
||||
},
|
||||
'& .MuiSwitch-track': {
|
||||
borderRadius: 26 / 2,
|
||||
opacity: 1,
|
||||
transition: theme.transitions.create(['background-color'], {
|
||||
duration: 500,
|
||||
}),
|
||||
},
|
||||
}));
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
useEffect(() => {
|
||||
if (openDialog === false) {
|
||||
reset();
|
||||
}
|
||||
}, [openDialog, reset]);
|
||||
|
||||
const getContent = () => (
|
||||
<Stack>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" paddingY={1}>
|
||||
<Typography variant="subtitle1">Claim Submission</Typography>
|
||||
<Stack sx={{ color: '#757575' }}>
|
||||
<Typography variant="caption">Submission date</Typography>
|
||||
<Typography variant="caption">{date}</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Card sx={{ paddingY: 1, paddingX: 2, marginTop: 2, backgroundColor: '#F4F6F8' }}>
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<img
|
||||
width={40}
|
||||
height={40}
|
||||
src="/images/member.png"
|
||||
alt="user-profile"
|
||||
style={{ borderRadius: '50%' }}
|
||||
/>
|
||||
<Stack sx={{ flex: '45%' }}>
|
||||
<Typography variant="subtitle1">{data && data.fullName}</Typography>
|
||||
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
|
||||
Member ID : {data && data.memberId}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Card>
|
||||
<Card sx={{ paddingY: 1, paddingX: 2, marginTop: 2 }}>
|
||||
<Stack spacing={1} paddingY={1}>
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<Typography color="#0A0A0A" variant="caption">
|
||||
Total Limit
|
||||
</Typography>
|
||||
<Link variant="caption" textAlign="center" href="#">
|
||||
Details Benefits <Iconify icon="ic:round-chevron-right" />
|
||||
</Link>
|
||||
</Stack>
|
||||
<BorderLinearProgress
|
||||
variant="determinate"
|
||||
value={100}
|
||||
percentage={data && data.limit ? data.limit.percentage : 100}
|
||||
/>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 500 }}>
|
||||
{fSplit(data && data.limit ? data.limit.current : 0)} /{' '}
|
||||
<Typography variant="body2" color="#757575" component="span">
|
||||
{fSplit(data && data.limit ? data.limit.total : 0)}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Card>
|
||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||
{/* Invoice */}
|
||||
<Stack marginTop={2} spacing={1}>
|
||||
<Stack>
|
||||
<Typography variant="subtitle2">Real Invoice</Typography>
|
||||
<Typography color="#9E9E9E" variant="caption">
|
||||
Real invoice required
|
||||
</Typography>
|
||||
</Stack>
|
||||
<input {...register('invoice')} type="file" />
|
||||
{errors.invoice && errors.invoice.message ? <p>{errors.invoice.message}</p> : ''}
|
||||
</Stack>
|
||||
{/* Prescription */}
|
||||
{/* <Stack marginTop={2} spacing={1}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Stack>
|
||||
<Typography variant="subtitle2">
|
||||
Doctor's Prescription and Another Documents
|
||||
</Typography>
|
||||
<Typography color="#9E9E9E" variant="caption">
|
||||
Doctor's Prescription required
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction="row"
|
||||
padding={1}
|
||||
alignItems="center"
|
||||
sx={{
|
||||
backgroundColor: 'white',
|
||||
border: '1px solid #E0E0E0',
|
||||
borderRadius: '6px',
|
||||
height: 32,
|
||||
}}
|
||||
>
|
||||
<IosSwitch defaultChecked />
|
||||
<Typography color="#404040" variant="body2">
|
||||
Yes
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<ImportForm label="Add Prescription" />
|
||||
</Stack> */}
|
||||
{/* Laboratory */}
|
||||
{/* <Stack marginTop={2} spacing={1}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Stack>
|
||||
<Typography variant="subtitle2">
|
||||
Doctor's Prescription and Another Documents
|
||||
</Typography>
|
||||
<Typography color="#9E9E9E" variant="caption">
|
||||
Doctor's Prescription required
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction="row"
|
||||
padding={1}
|
||||
alignItems="center"
|
||||
sx={{
|
||||
backgroundColor: 'white',
|
||||
border: '1px solid #E0E0E0',
|
||||
borderRadius: '6px',
|
||||
height: 32,
|
||||
}}
|
||||
>
|
||||
<IosSwitch defaultChecked />
|
||||
<Typography color="#404040" variant="body2">
|
||||
Yes
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<ImportForm label="Add Result" />
|
||||
</Stack> */}
|
||||
{/* Submit */}
|
||||
<Stack marginTop={1}>
|
||||
<LoadingButton
|
||||
fullWidth
|
||||
size="large"
|
||||
type="submit"
|
||||
variant="contained"
|
||||
loading={isSubmitting}
|
||||
sx={{ marginTop: 2 }}
|
||||
>
|
||||
Ajukan Permintaan
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
</FormProvider>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MuiDialog
|
||||
title={title}
|
||||
openDialog={openDialog}
|
||||
setOpenDialog={setOpenDialog}
|
||||
content={getContent()}
|
||||
maxWidth="sm"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DialogClaimSubmitMemberSubmission;
|
||||
@@ -0,0 +1,353 @@
|
||||
// @mui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import {
|
||||
Typography,
|
||||
LinearProgress,
|
||||
linearProgressClasses,
|
||||
Stack,
|
||||
Card,
|
||||
Button,
|
||||
Divider,
|
||||
Avatar,
|
||||
} from '@mui/material';
|
||||
// components
|
||||
import MuiDialog from '../../components/MuiDialog';
|
||||
import Iconify from '../../components/Iconify';
|
||||
// React
|
||||
import { ReactElement, useRef, useState } from 'react';
|
||||
// form
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import axios from '../../utils/axios';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { fPostFormat } from '../../utils/formatTime';
|
||||
import { fCurrency } from '../../utils/formatNumber';
|
||||
|
||||
/* ---------------------------------- types --------------------------------- */
|
||||
type DataContentType = {
|
||||
id: number;
|
||||
fullName: string;
|
||||
memberId: string;
|
||||
limit: {
|
||||
current: number;
|
||||
total: number;
|
||||
percentage: number;
|
||||
};
|
||||
avatar?: {
|
||||
url?: string;
|
||||
title?: string;
|
||||
};
|
||||
};
|
||||
|
||||
type MuiDialogProps = {
|
||||
title?: {
|
||||
name?: string;
|
||||
icon?: string;
|
||||
};
|
||||
openDialog: boolean;
|
||||
setOpenDialog: Function;
|
||||
content?: ReactElement;
|
||||
data: DataContentType;
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* --------------------------------- styles --------------------------------- */
|
||||
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
||||
height: 10,
|
||||
borderRadius: 6,
|
||||
[`&.${linearProgressClasses.colorPrimary}`]: {
|
||||
backgroundColor: theme.palette.grey[theme.palette.mode === 'light' ? 300 : 800],
|
||||
},
|
||||
[`& .${linearProgressClasses.bar}`]: {
|
||||
borderRadius: 6,
|
||||
background: 'linear-gradient(270deg, #19BBBB 38.42%, #FF9565 76.21%, #FE7253 104.02%)',
|
||||
},
|
||||
}));
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const DialogRequestLog = ({ openDialog, setOpenDialog, data }: MuiDialogProps) => {
|
||||
const [serviceCode, setServiceCode] = useState('IP');
|
||||
|
||||
const fileDiagnosaInput = useRef<HTMLInputElement>(null);
|
||||
const [fileDiagnosas, setFileDiagnosas] = useState([]);
|
||||
|
||||
const handleDiagnosaInputChange = (event) => {
|
||||
if (event.target.files[0]) {
|
||||
setFileDiagnosas([...fileDiagnosas, ...event.target.files]);
|
||||
} else {
|
||||
console.log('NO FILE');
|
||||
}
|
||||
};
|
||||
const removeDiagnosaFiles = (filesState, index) => {
|
||||
setFileDiagnosas(filesState.filter((file, fileIndex) => fileIndex != index));
|
||||
};
|
||||
|
||||
const fileKondisiInput = useRef<HTMLInputElement>(null);
|
||||
const [fileKondisis, setFileKondisis] = useState([]);
|
||||
|
||||
const handleKondisiInputChange = (event) => {
|
||||
if (event.target.files[0]) {
|
||||
setFileKondisis([...fileKondisis, ...event.target.files]);
|
||||
} else {
|
||||
console.log('NO FILE');
|
||||
}
|
||||
};
|
||||
const removeKondisiFiles = (filesState, index) => {
|
||||
setFileKondisis(filesState.filter((file, fileIndex) => fileIndex != index));
|
||||
};
|
||||
|
||||
const fileHasilPenunjangInput = useRef<HTMLInputElement>(null);
|
||||
const [fileHasilPenunjangs, setFileHasilPenunjangs] = useState([]);
|
||||
|
||||
const handleResultInputChange = (event) => {
|
||||
if (event.target.files[0]) {
|
||||
setFileHasilPenunjangs([...fileHasilPenunjangs, ...event.target.files]);
|
||||
} else {
|
||||
console.log('NO FILE');
|
||||
}
|
||||
};
|
||||
const removeFiles = (filesState, index) => {
|
||||
setFileHasilPenunjangs(filesState.filter((file, fileIndex) => fileIndex != index));
|
||||
};
|
||||
|
||||
const [submitLoading, setSubmitLoading] = useState(false);
|
||||
function submitRequest() {
|
||||
setSubmitLoading(true);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('member_id', data.id);
|
||||
formData.append('result_files', fileHasilPenunjangs);
|
||||
formData.append('diagnosa_files', fileDiagnosas);
|
||||
formData.append('kondisi_files', fileKondisis);
|
||||
formData.append('service_code', serviceCode);
|
||||
|
||||
axios
|
||||
.post('/claim-requests', formData)
|
||||
.then((response) => {
|
||||
enqueueSnackbar(response.data.message ?? 'Berhasil membuat data', { variant: 'success' });
|
||||
})
|
||||
.catch(({ response }) => {
|
||||
enqueueSnackbar(response.data.message ?? 'Something Went Wrong', { variant: 'error' });
|
||||
})
|
||||
.then(() => {
|
||||
setSubmitLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
const getContent = () => (
|
||||
<Stack paddingY={1}>
|
||||
<Stack direction="row" justifyContent={'end'} sx={{ marginBottom: 2 }}>
|
||||
<Typography textAlign={'right'} variant="body2">
|
||||
Submission Date : <br /> {fPostFormat(new Date(), 'dd/MM/yyyy')}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
<Card sx={{ p: 1, background: '#f4f6f8', marginBottom: 2 }}>
|
||||
<Stack direction="row" spacing={2}>
|
||||
<Button
|
||||
sx={{ padding: 2, width: '100%' }}
|
||||
variant={serviceCode == 'IP' ? 'contained' : ''}
|
||||
onClick={() => {
|
||||
setServiceCode('IP');
|
||||
}}
|
||||
>
|
||||
Rawat Inap
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ padding: 2, width: '100%' }}
|
||||
variant={serviceCode == 'OP' ? 'contained' : ''}
|
||||
onClick={() => {
|
||||
setServiceCode('OP');
|
||||
}}
|
||||
>
|
||||
Rawat Jalan
|
||||
</Button>
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
<Card sx={{ p: 1, background: '#f4f6f8', marginBottom: 2 }}>
|
||||
<Stack direction="row">
|
||||
<Avatar
|
||||
src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg"
|
||||
alt={data.fullName}
|
||||
sx={{ marginTop: 1, width: 48, height: 48 }}
|
||||
/>
|
||||
<Stack sx={{ p: 1 }}>
|
||||
<Typography>{data.fullName}</Typography>
|
||||
<Typography>{data.memberId}</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
<Card sx={{ paddingY: 1, paddingX: 2 }}>
|
||||
<Typography variant="body1" sx={{ marginBottom: 1, fontWeight: 600 }}>
|
||||
Total Limit
|
||||
</Typography>
|
||||
<BorderLinearProgress variant="determinate" value={data.limit.percentage} />
|
||||
<Typography sx={{ textAlign: 'right', marginTop: 1 }}>
|
||||
{fCurrency(data.limit.current)} / {fCurrency(data.limit.total)}
|
||||
</Typography>
|
||||
</Card>
|
||||
|
||||
<Stack
|
||||
divider={<Divider orientation="horizontal" flexItem />}
|
||||
spacing={4}
|
||||
sx={{ marginY: 2 }}
|
||||
>
|
||||
<Stack sx={{ marginTop: 2 }}>
|
||||
<Typography variant="body1" fontWeight={600}>
|
||||
<Iconify icon="eva:file-text-fill" /> Dokumen Kondisi
|
||||
</Typography>
|
||||
<Stack
|
||||
divider={<Divider orientation="horizontal" flexItem />}
|
||||
spacing={1}
|
||||
sx={{ marginY: 2 }}
|
||||
>
|
||||
{fileKondisis &&
|
||||
fileKondisis.map((file, index) => (
|
||||
<Stack direction="row" justifyContent={'space-between'} key={index}>
|
||||
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
|
||||
<Iconify
|
||||
icon="eva:trash-2-outline"
|
||||
color={'darkred'}
|
||||
onClick={() => {
|
||||
removeKondisiFiles(fileKondisis, index);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
ref={fileKondisiInput}
|
||||
style={{ display: 'none' }}
|
||||
multiple
|
||||
onChange={handleKondisiInputChange}
|
||||
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain"
|
||||
/>
|
||||
<LoadingButton
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
fileKondisiInput?.current?.click();
|
||||
}}
|
||||
>
|
||||
<Iconify icon="eva:plus-fill" />
|
||||
Add Result
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
|
||||
<Stack sx={{ marginTop: 2 }}>
|
||||
<Typography variant="body1" fontWeight={600}>
|
||||
<Iconify icon="eva:file-text-fill" /> Dokumen Diagnosa
|
||||
</Typography>
|
||||
{/* <Typography variant="body2">Hasil Lab, </Typography> */}
|
||||
<Stack
|
||||
divider={<Divider orientation="horizontal" flexItem />}
|
||||
spacing={1}
|
||||
sx={{ marginY: 2 }}
|
||||
>
|
||||
{fileDiagnosas &&
|
||||
fileDiagnosas.map((file, index) => (
|
||||
<Stack direction="row" justifyContent={'space-between'} key={index}>
|
||||
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
|
||||
<Iconify
|
||||
icon="eva:trash-2-outline"
|
||||
color={'darkred'}
|
||||
onClick={() => {
|
||||
removeDiagnosaFiles(fileDiagnosas, index);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
ref={fileDiagnosaInput}
|
||||
style={{ display: 'none' }}
|
||||
multiple
|
||||
onChange={handleDiagnosaInputChange}
|
||||
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain"
|
||||
/>
|
||||
<LoadingButton
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
fileDiagnosaInput?.current?.click();
|
||||
}}
|
||||
>
|
||||
<Iconify icon="eva:plus-fill" />
|
||||
Add Result
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
|
||||
<Stack sx={{ marginTop: 2 }}>
|
||||
<Typography variant="body1" fontWeight={600}>
|
||||
<Iconify icon="eva:file-text-fill" /> Dokumen Hasil Penunjang
|
||||
</Typography>
|
||||
<Stack
|
||||
divider={<Divider orientation="horizontal" flexItem />}
|
||||
spacing={1}
|
||||
sx={{ marginY: 2 }}
|
||||
>
|
||||
{fileHasilPenunjangs &&
|
||||
fileHasilPenunjangs.map((file, index) => (
|
||||
<Stack direction="row" justifyContent={'space-between'} key={index}>
|
||||
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
|
||||
<Iconify
|
||||
icon="eva:trash-2-outline"
|
||||
color={'darkred'}
|
||||
onClick={() => {
|
||||
removeFiles(fileHasilPenunjangs, index);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
ref={fileHasilPenunjangInput}
|
||||
style={{ display: 'none' }}
|
||||
multiple
|
||||
onChange={handleResultInputChange}
|
||||
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain"
|
||||
/>
|
||||
<LoadingButton
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
fileHasilPenunjangInput?.current?.click();
|
||||
}}
|
||||
>
|
||||
<Iconify icon="eva:plus-fill" />
|
||||
Add File
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<LoadingButton
|
||||
variant="contained"
|
||||
sx={{ marginTop: 2, p: 2 }}
|
||||
onClick={() => {
|
||||
submitRequest();
|
||||
}}
|
||||
loading={submitLoading}
|
||||
>
|
||||
LOG Request
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MuiDialog
|
||||
title={{ name: data.fullName }}
|
||||
openDialog={openDialog}
|
||||
setOpenDialog={setOpenDialog}
|
||||
content={getContent()}
|
||||
maxWidth="sm"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DialogRequestLog;
|
||||
@@ -4,21 +4,21 @@ import numeral from 'numeral';
|
||||
// load a locale
|
||||
numeral.register('locale', 'id', {
|
||||
delimiters: {
|
||||
thousands: '.',
|
||||
decimal: ','
|
||||
thousands: '.',
|
||||
decimal: ',',
|
||||
},
|
||||
abbreviations: {
|
||||
thousand: 'k',
|
||||
million: 'm',
|
||||
billion: 'b',
|
||||
trillion: 't'
|
||||
thousand: 'k',
|
||||
million: 'm',
|
||||
billion: 'b',
|
||||
trillion: 't',
|
||||
},
|
||||
ordinal : function (number: number) {
|
||||
return number === 1 ? 'er' : 'ème';
|
||||
ordinal: function (number: number) {
|
||||
return number === 1 ? 'er' : 'ème';
|
||||
},
|
||||
currency: {
|
||||
symbol: 'Rp '
|
||||
}
|
||||
symbol: 'Rp ',
|
||||
},
|
||||
});
|
||||
|
||||
// switch between locales
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { format,parseISO, getTime, setHours, setMinutes , formatDistanceToNow } from 'date-fns';
|
||||
import { format, parseISO, getTime, setHours, setMinutes, formatDistanceToNow } from 'date-fns';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -21,10 +21,14 @@ export function fDateTimeSuffix(date: Date | string | number) {
|
||||
|
||||
export function fToNow(date: Date | string | number) {
|
||||
return formatDistanceToNow(new Date(date), {
|
||||
addSuffix: true
|
||||
addSuffix: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function fPostFormat(date: Date | string | number, dateFormat = 'yyyy-MM-dd HH:mm:ss') {
|
||||
return format(new Date(date), dateFormat);
|
||||
}
|
||||
|
||||
// export function fDateString(date) {
|
||||
// const dateObj = parseISO(date);
|
||||
// const formattedDate = format(dateObj, 'dd MMMM yyyy');
|
||||
@@ -36,4 +40,4 @@ export function fToNow(date: Date | string | number) {
|
||||
// const datePart = date.split(' ')[0]; // Memisahkan bagian tanggal
|
||||
// const formattedDate = fDateString(datePart); // Menggunakan fungsi sebelumnya untuk memformat tanggal
|
||||
// return formattedDate;
|
||||
// }
|
||||
// }
|
||||
|
||||
2387
frontend/hospital-portal/pnpm-lock.yaml
generated
2387
frontend/hospital-portal/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user