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\Http\Request;
|
||||||
use Illuminate\Routing\Controller;
|
use Illuminate\Routing\Controller;
|
||||||
use Modules\Client\Transformers\ClaimReport\MemberResources as ClaimReportMemberResources;
|
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\MemberResources as DashboardMemberResources;
|
||||||
use Modules\Client\Transformers\Dashboard\MemberAlarmCenterResources as DashboardMemberAlarmResources;
|
use Modules\Client\Transformers\Dashboard\MemberAlarmCenterResources as DashboardMemberAlarmResources;
|
||||||
use Modules\Client\Transformers\DataMemberResource;
|
use Modules\Client\Transformers\DataMemberResource;
|
||||||
@@ -31,7 +32,7 @@ class CorporateMemberController extends Controller
|
|||||||
return response()->json(Helper::paginateResources(ClaimReportMemberResources::collection($members)));
|
return response()->json(Helper::paginateResources(ClaimReportMemberResources::collection($members)));
|
||||||
case 'claim-submit':
|
case 'claim-submit':
|
||||||
$members = $this->corporateMemberService->getAllMemberClaimReports($corporate_id, $request);
|
$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':
|
case 'alarm-center':
|
||||||
$members = $this->corporateMemberService->getAllMemberAlarmCenter($corporate_id, $request);
|
$members = $this->corporateMemberService->getAllMemberAlarmCenter($corporate_id, $request);
|
||||||
return response()->json(Helper::paginateResources(DashboardMemberAlarmResources::collection($members)));
|
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\Client\Http\Controllers\Api\TopUpController;
|
||||||
use Modules\Internal\Http\Controllers\ClaimEncounterController;
|
use Modules\Internal\Http\Controllers\ClaimEncounterController;
|
||||||
use App\Models\Encounter;
|
use App\Models\Encounter;
|
||||||
|
use Modules\Client\Http\Controllers\Api\ClaimRequestController;
|
||||||
use Modules\Client\Http\Controllers\Api\DataController;
|
use Modules\Client\Http\Controllers\Api\DataController;
|
||||||
use Modules\Internal\Transformers\EncounterResource;
|
use Modules\Internal\Transformers\EncounterResource;
|
||||||
|
|
||||||
@@ -54,5 +55,7 @@ Route::prefix('client')->group(function () {
|
|||||||
Route::post('topup', [TopUpController::class, 'store']);
|
Route::post('topup', [TopUpController::class, 'store']);
|
||||||
});
|
});
|
||||||
Route::get('claims/{id}', [ClaimController::class, 'show']);
|
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',
|
'division' => 'corporate_divisions.name',
|
||||||
default => ''
|
default => ''
|
||||||
};
|
};
|
||||||
if ($request->order){
|
if ($request->order) {
|
||||||
$query->getQuery()->orderBy($orderBy, $request->order);
|
$query->getQuery()->orderBy($orderBy, $request->order);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -48,7 +48,6 @@ class CorporateMemberService
|
|||||||
$limit = $request->has('perPage') ? $request->input('perPage') : 10;
|
$limit = $request->has('perPage') ? $request->input('perPage') : 10;
|
||||||
|
|
||||||
return Member::query()
|
return Member::query()
|
||||||
->joinClaimRequests('right')
|
|
||||||
->joinCorporateEmployees('left')
|
->joinCorporateEmployees('left')
|
||||||
->joinCorporateDivisions('left')
|
->joinCorporateDivisions('left')
|
||||||
->with('currentPlan')
|
->with('currentPlan')
|
||||||
@@ -62,11 +61,6 @@ class CorporateMemberService
|
|||||||
->orWhere('members.name', 'like', "%" . $search . "%");
|
->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) {
|
->when($request->has('orderBy'), function (Builder $query) use ($request) {
|
||||||
$orderBy = match ($request->orderBy) {
|
$orderBy = match ($request->orderBy) {
|
||||||
'memberId' => 'member_id',
|
'memberId' => 'member_id',
|
||||||
@@ -80,7 +74,7 @@ class CorporateMemberService
|
|||||||
$query->getQuery()->orderBy('corporate_divisions.name', $request->order);
|
$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);
|
->paginate($limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +116,8 @@ class CorporateMemberService
|
|||||||
->paginate($limit);
|
->paginate($limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAllEncounter(int $corporateId){
|
public function getAllEncounter(int $corporateId)
|
||||||
|
{
|
||||||
return Encounter::query()->select(['id'])->paginate(10);
|
return Encounter::query()->select(['id'])->paginate(10);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ type CardPolicyProps = {
|
|||||||
members: {
|
members: {
|
||||||
memberId: string;
|
memberId: string;
|
||||||
memberFullName: string;
|
memberFullName: string;
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -194,7 +194,6 @@ export default function CardPolicy(props: CardPolicyProps) {
|
|||||||
openDialog={openDialog}
|
openDialog={openDialog}
|
||||||
setOpenDialog={setOpenDialog}
|
setOpenDialog={setOpenDialog}
|
||||||
title={{ name: dialogTitle }}
|
title={{ name: dialogTitle }}
|
||||||
data={members}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { Search as SearchIcon } from '@mui/icons-material';
|
import { Search as SearchIcon } from '@mui/icons-material';
|
||||||
import axios from '../../utils/axios';
|
|
||||||
// components
|
// components
|
||||||
import MuiDialog from '../../components/MuiDialog';
|
import MuiDialog from '../../components/MuiDialog';
|
||||||
import Iconify from '../../components/Iconify';
|
import Iconify from '../../components/Iconify';
|
||||||
import { useSnackbar } from 'notistack';
|
|
||||||
// React
|
// React
|
||||||
import { ReactElement, useState } from 'react';
|
import { ReactElement, useContext, useEffect, useState } from 'react';
|
||||||
import DialogClaimSubmitMemberSubmission from './DialogClaimSubmitMemberSubmission';
|
import DialogRequestLog from './DialogRequestLog';
|
||||||
|
import axios from '../../utils/axios';
|
||||||
|
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ type MuiDialogProps = {
|
|||||||
openDialog: boolean;
|
openDialog: boolean;
|
||||||
setOpenDialog: Function;
|
setOpenDialog: Function;
|
||||||
content?: ReactElement;
|
content?: ReactElement;
|
||||||
data?: DataContentType[];
|
// data?: DataContent[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -68,9 +68,11 @@ export default function DialogClaimSubmitMember({
|
|||||||
title,
|
title,
|
||||||
openDialog,
|
openDialog,
|
||||||
setOpenDialog,
|
setOpenDialog,
|
||||||
data,
|
|
||||||
}: MuiDialogProps) {
|
}: MuiDialogProps) {
|
||||||
|
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||||
|
|
||||||
/* ---------------------------------- data ---------------------------------- */
|
/* ---------------------------------- data ---------------------------------- */
|
||||||
|
const [data, setData] = useState([]);
|
||||||
const [dataMemberClaim, setDataMemberClaim] = useState<DataContentType>({
|
const [dataMemberClaim, setDataMemberClaim] = useState<DataContentType>({
|
||||||
id: 0,
|
id: 0,
|
||||||
fullName: '',
|
fullName: '',
|
||||||
@@ -85,31 +87,16 @@ export default function DialogClaimSubmitMember({
|
|||||||
|
|
||||||
/* --------------------------------- Search --------------------------------- */
|
/* --------------------------------- Search --------------------------------- */
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
/* --------------------------------- Benefit--------------------------------- */
|
const [appliedParams, setAppliedParams] = useState({});
|
||||||
const {enqueueSnackbar} = useSnackbar();
|
|
||||||
const [openDialogBenefit, setOpenDialogBenefit] = useState(false);
|
|
||||||
const [currentMember, setCurrentMember] = useState(null);
|
|
||||||
const [nameMember, setNameMember] = useState('');
|
|
||||||
const [loadingBenefit, setLoadingBenefit] = useState(false);
|
|
||||||
|
|
||||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
// await new Promise((resolve) => setTimeout(resolve, 500));
|
event.preventDefault();
|
||||||
// setLoadingBenefit(true)
|
if (searchText === '') {
|
||||||
|
setAppliedParams({});
|
||||||
// axios.post('/search-member', {
|
} else {
|
||||||
// search: searchText,
|
setAppliedParams({ search: searchText });
|
||||||
// })
|
}
|
||||||
// .then((response) => {
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
// 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)
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -119,7 +106,7 @@ export default function DialogClaimSubmitMember({
|
|||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* ------------------------------ Icon On Click ----------------------------- */
|
/* ------------------------------ Icon On Click ----------------------------- */
|
||||||
const [openDialogClaimMember, setOpenDialogMemberClaim] = useState(false);
|
const [openDialogRequestLog, setOpenDialogRequestLog] = useState(false);
|
||||||
|
|
||||||
const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => {
|
const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => {
|
||||||
setDataMemberClaim({
|
setDataMemberClaim({
|
||||||
@@ -136,10 +123,22 @@ export default function DialogClaimSubmitMember({
|
|||||||
title: avatar && avatar.title,
|
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 = () => (
|
const getContent = () => (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center" paddingY={1}>
|
<Stack direction="row" justifyContent="space-between" alignItems="center" paddingY={1}>
|
||||||
@@ -168,57 +167,58 @@ export default function DialogClaimSubmitMember({
|
|||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
<Stack marginTop={2} spacing={1}>
|
<Stack marginTop={2} spacing={1}>
|
||||||
{data &&
|
{data.map((row: DataContentType, key) => (
|
||||||
data.map((row: DataContentType, key) => (
|
<Card
|
||||||
<Card key={key} sx={{ paddingY: 1, paddingX: 2 }}>
|
key={key}
|
||||||
<Stack direction="row" alignItems="center" spacing={2}>
|
sx={{ paddingY: 1, paddingX: 2 }}
|
||||||
<img
|
onClick={() =>
|
||||||
width={40}
|
clickHandler({
|
||||||
height={40}
|
id: row.id,
|
||||||
src={row.avatar ? row.avatar.url : '/images/member.png'}
|
fullName: row.fullName,
|
||||||
alt={row.avatar ? row.avatar.url : 'user-profile'}
|
memberId: row.memberId,
|
||||||
style={{ borderRadius: '50%' }}
|
limit: {
|
||||||
/>
|
current: row.limit.current,
|
||||||
<Stack sx={{ flex: '45%' }}>
|
total: row.limit.total,
|
||||||
<Typography variant="subtitle1">{row.fullName}</Typography>
|
percentage: row.limit.percentage,
|
||||||
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
|
},
|
||||||
Member ID : {row.memberId}
|
})
|
||||||
</Typography>
|
}
|
||||||
</Stack>
|
>
|
||||||
<Stack spacing={1} paddingY={1}>
|
<Stack direction="row" alignItems="center" spacing={2}>
|
||||||
<Typography color="#0A0A0A" variant="caption">
|
<img
|
||||||
Total Limit
|
width={40}
|
||||||
</Typography>
|
height={40}
|
||||||
<BorderLinearProgress
|
src={row.avatar ? row.avatar.url : '/images/member.png'}
|
||||||
variant="determinate"
|
alt={row.avatar ? row.avatar.url : 'user-profile'}
|
||||||
value={row.limit && row.limit.percentage}
|
style={{ borderRadius: '50%' }}
|
||||||
/>
|
/>
|
||||||
<Typography variant="subtitle2" sx={{ fontWeight: 500 }}>
|
<Stack sx={{ flex: '45%' }}>
|
||||||
{row.limit && row.limit.current} /{' '}
|
<Typography variant="subtitle1">{row.fullName}</Typography>
|
||||||
<Typography variant="body2" color="#757575" component="span">
|
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
|
||||||
{row.limit && row.limit.total}
|
Member ID : {row.memberId}
|
||||||
</Typography>
|
</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>
|
|
||||||
</Stack>
|
</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>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
@@ -233,10 +233,9 @@ export default function DialogClaimSubmitMember({
|
|||||||
maxWidth="sm"
|
maxWidth="sm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DialogClaimSubmitMemberSubmission
|
<DialogRequestLog
|
||||||
title={title}
|
openDialog={openDialogRequestLog}
|
||||||
openDialog={openDialogClaimMember}
|
setOpenDialog={setOpenDialogRequestLog}
|
||||||
setOpenDialog={setOpenDialogMemberClaim}
|
|
||||||
data={dataMemberClaim}
|
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
|
// load a locale
|
||||||
numeral.register('locale', 'id', {
|
numeral.register('locale', 'id', {
|
||||||
delimiters: {
|
delimiters: {
|
||||||
thousands: '.',
|
thousands: '.',
|
||||||
decimal: ','
|
decimal: ',',
|
||||||
},
|
},
|
||||||
abbreviations: {
|
abbreviations: {
|
||||||
thousand: 'k',
|
thousand: 'k',
|
||||||
million: 'm',
|
million: 'm',
|
||||||
billion: 'b',
|
billion: 'b',
|
||||||
trillion: 't'
|
trillion: 't',
|
||||||
},
|
},
|
||||||
ordinal : function (number: number) {
|
ordinal: function (number: number) {
|
||||||
return number === 1 ? 'er' : 'ème';
|
return number === 1 ? 'er' : 'ème';
|
||||||
},
|
},
|
||||||
currency: {
|
currency: {
|
||||||
symbol: 'Rp '
|
symbol: 'Rp ',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// switch between locales
|
// 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) {
|
export function fToNow(date: Date | string | number) {
|
||||||
return formatDistanceToNow(new Date(date), {
|
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) {
|
// export function fDateString(date) {
|
||||||
// const dateObj = parseISO(date);
|
// const dateObj = parseISO(date);
|
||||||
// const formattedDate = format(dateObj, 'dd MMMM yyyy');
|
// 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 datePart = date.split(' ')[0]; // Memisahkan bagian tanggal
|
||||||
// const formattedDate = fDateString(datePart); // Menggunakan fungsi sebelumnya untuk memformat tanggal
|
// const formattedDate = fDateString(datePart); // Menggunakan fungsi sebelumnya untuk memformat tanggal
|
||||||
// return formattedDate;
|
// 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