progress 2 feature/dashboard-create-claim-request
This commit is contained in:
@@ -48,17 +48,17 @@ class ClaimRequestController extends Controller
|
|||||||
]);
|
]);
|
||||||
if ($request->member_id){
|
if ($request->member_id){
|
||||||
foreach($request->member_id as $key => $member_id){
|
foreach($request->member_id as $key => $member_id){
|
||||||
|
|
||||||
$code = $this->getNextCode();
|
$code = $this->getNextCode();
|
||||||
$member = Member::find($member_id);
|
$member = Member::find($member_id);
|
||||||
$newClaimRequest = ClaimRequestService::storeClaimRequest(
|
$newClaimRequest = ClaimRequestService::storeClaimRequest(
|
||||||
row: [],
|
row: [],
|
||||||
code: $code,
|
code: $code,
|
||||||
member: $member,
|
member: $member,
|
||||||
paymentType: 'reimbursement',
|
paymentType: 'reimbursement',
|
||||||
serviceCode: $request->service_code[$key],
|
serviceCode: $request->service_code[$key],
|
||||||
);
|
);
|
||||||
|
|
||||||
ClaimRequested::dispatch($newClaimRequest);
|
ClaimRequested::dispatch($newClaimRequest);
|
||||||
// Log History
|
// Log History
|
||||||
$newClaimRequest->histories()->create([
|
$newClaimRequest->histories()->create([
|
||||||
@@ -127,9 +127,9 @@ class ClaimRequestController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return Helper::responseJson(data: $request->toArray(), message: 'Claim Request berhasil ajukan!');
|
return Helper::responseJson(data: $request->toArray(), message: 'Claim Request berhasil ajukan!');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ use App\Models\Member;
|
|||||||
|
|
||||||
class ClaimRequestController extends Controller
|
class ClaimRequestController extends Controller
|
||||||
{
|
{
|
||||||
|
private static $code_prefix = 'CRQ-C';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
* @return Renderable
|
* @return Renderable
|
||||||
@@ -64,14 +66,109 @@ class ClaimRequestController extends Controller
|
|||||||
return view('internal::create');
|
return view('internal::create');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function createNew(Request $request)
|
||||||
* Store a newly created resource in storage.
|
|
||||||
* @param Request $request
|
|
||||||
* @return Renderable
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
{
|
||||||
//
|
$request->validate([
|
||||||
|
'member_id' => 'required|array',
|
||||||
|
'member_id.*' => 'required',
|
||||||
|
'service_code.*' => 'required|in:OP,IP'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->member_id){
|
||||||
|
foreach($request->member_id as $key => $member_id){
|
||||||
|
|
||||||
|
$code = $this->getNextCode();
|
||||||
|
$member = Member::find($member_id);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$newClaimRequest = ClaimRequestService::storeClaimRequest(
|
||||||
|
row: [],
|
||||||
|
code: $code,
|
||||||
|
member: $member,
|
||||||
|
paymentType: 'reimbursement',
|
||||||
|
serviceCode: $request->service_code[$key],
|
||||||
|
);
|
||||||
|
|
||||||
|
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' => 'client-portal'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Claim Log
|
||||||
|
DB::table('claim_logs') ->insert([
|
||||||
|
'claim_request_id' => $newClaimRequest->id,
|
||||||
|
'status' => 'requested',
|
||||||
|
'date' => date('Y-m-d H:i:s'),
|
||||||
|
'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})",
|
||||||
|
'system_origin' => 'hospital-portal',
|
||||||
|
'created_by' => auth()->user()->id,
|
||||||
|
'created_at' => date('Y-m-d H:i:s'),
|
||||||
|
'updated_at'=> date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->hasFile('laboratorium')) {
|
||||||
|
foreach ($request->laboratorium[$key] 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('prescription')) {
|
||||||
|
foreach ($request->prescription[$key] 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('invoice')) {
|
||||||
|
foreach ($request->invoice[$key] 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,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
}
|
||||||
|
catch (\Throwable $th) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
return Helper::responseJson(status: 'failed', statusCode: 500, message: $th->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Helper::responseJson(status: 'success', statusCode: 201, message: 'Claim Request berhasil ajukan!', data: $request->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -510,4 +607,34 @@ class ClaimRequestController extends Controller
|
|||||||
]
|
]
|
||||||
],200);
|
],200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getNextCode()
|
||||||
|
{
|
||||||
|
// $last_number = ClaimRequest::max('code');
|
||||||
|
// $next_number = empty($last_number) ? 1 : ((int) explode('-', $last_number)[2] + 1);
|
||||||
|
// return self::makeCode($next_number);
|
||||||
|
|
||||||
|
$last_numeric_code = ClaimRequest::select(DB::raw('MAX(CAST(SUBSTRING_INDEX(code, "-", -1) AS SIGNED)) as max_numeric_code'))
|
||||||
|
->whereRaw('SUBSTRING_INDEX(code, "-", -1) REGEXP "^[0-9]+$"')
|
||||||
|
->value('max_numeric_code');
|
||||||
|
// $next_number = 1;
|
||||||
|
if ($last_numeric_code) {
|
||||||
|
// // Jika ada kode sebelumnya, pecah kode dan tambahkan 1 ke angka terakhir
|
||||||
|
// $parts = explode('-', $last_code);
|
||||||
|
// $last_number = (int) end($parts);
|
||||||
|
$next_number = $last_numeric_code + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::makeCode($next_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function makeCode($next_number)
|
||||||
|
{
|
||||||
|
// Pastikan $next_number adalah integer positif
|
||||||
|
$next_number = max(1, (int) $next_number);
|
||||||
|
|
||||||
|
// Menghasilkan kode dengan format yang diinginkan
|
||||||
|
return self::$code_prefix . '-' . str_pad($next_number, 5, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class DailyMonitoringController extends Controller
|
|||||||
->leftJoin('claim_requests', 'claims.claim_request_id', '=', 'claim_requests.id')
|
->leftJoin('claim_requests', 'claims.claim_request_id', '=', 'claim_requests.id')
|
||||||
->leftJoin('services', 'claim_requests.service_code', '=', 'services.code')
|
->leftJoin('services', 'claim_requests.service_code', '=', 'services.code')
|
||||||
->leftJoin('members', 'claims.member_id', '=', 'members.id')
|
->leftJoin('members', 'claims.member_id', '=', 'members.id')
|
||||||
->select('claims.id AS claim_id','claims.admission_dates','claims.discharge_dates','claim_requests.code AS claim_code','services.name AS service_type','claims.status AS claim_status','members.member_id',)
|
->select('claims.id AS claim_id','claim_requests.code AS claim_code','services.name AS service_type','claims.status AS claim_status','members.member_id',)
|
||||||
->where("claims.member_id", "=", $memberDetail->id)
|
->where("claims.member_id", "=", $memberDetail->id)
|
||||||
->orderBy("claims.created_at", "desc")
|
->orderBy("claims.created_at", "desc")
|
||||||
->get();
|
->get();
|
||||||
|
|||||||
@@ -245,9 +245,10 @@ Route::prefix('internal')->group(function () {
|
|||||||
Route::post('files-mcu', 'filesMcu');
|
Route::post('files-mcu', 'filesMcu');
|
||||||
});
|
});
|
||||||
Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index');
|
Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index');
|
||||||
Route::get('claim-requests/list-member', [ClaimRequestController::class, 'getClaimMemberInfiniteScroll']); // Bagaskoro, BSD 31 Oktober 2023
|
Route::get('claim-requests/list-member', [ClaimRequestController::class, 'getClaimMemberInfiniteScroll']); // Bagaskoro, BSD 31 Oktober 2023
|
||||||
Route::post('claim-requests/{id}/approve', [ClaimRequestController::class, 'approve'])->name('claim-requests.approve');
|
Route::post('claim-requests/{id}/approve', [ClaimRequestController::class, 'approve'])->name('claim-requests.approve');
|
||||||
Route::get('claim-requests/{id}', [ClaimRequestController::class, 'show'])->name('claim-requests.show');
|
Route::get('claim-requests/{id}', [ClaimRequestController::class, 'show'])->name('claim-requests.show');
|
||||||
|
Route::post('claim-requests', [ClaimRequestController::class, 'createNew']); // Bagaskoro, BSD 2 November 2023
|
||||||
Route::put('claim-requests/{id}', [ClaimRequestController::class, 'update'])->name('claim-requests.update');
|
Route::put('claim-requests/{id}', [ClaimRequestController::class, 'update'])->name('claim-requests.update');
|
||||||
Route::post('claim-requests/import', [ClaimRequestController::class, 'importClaim'])->name('claim-requests.importClaim');
|
Route::post('claim-requests/import', [ClaimRequestController::class, 'importClaim'])->name('claim-requests.importClaim');
|
||||||
Route::get('claim-requests/detail/{id}', [ClaimRequestController::class, 'claimRequestDetail']);
|
Route::get('claim-requests/detail/{id}', [ClaimRequestController::class, 'claimRequestDetail']);
|
||||||
|
|||||||
@@ -4,4 +4,6 @@ PORT=8083
|
|||||||
|
|
||||||
REACT_APP_HOST_API_URL="https://aso-api.linksehat.dev/api/client"
|
REACT_APP_HOST_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||||
|
|
||||||
VITE_API_URL="https://aso-api.linksehat.dev/api/client"
|
# VITE_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||||
|
VITE_API_URL="http://localhost:8000/api/client"
|
||||||
|
|
||||||
|
|||||||
@@ -32,12 +32,6 @@ export default function Claim() {
|
|||||||
const [memberDetail, setMemberDetail] = useState<MemberDetailType>();
|
const [memberDetail, setMemberDetail] = useState<MemberDetailType>();
|
||||||
const [claimList, setClaimList] = useState<ClaimListType[]>();
|
const [claimList, setClaimList] = useState<ClaimListType[]>();
|
||||||
|
|
||||||
// Use Effect
|
|
||||||
// --------------------
|
|
||||||
useEffect(() => {
|
|
||||||
loadDataTableData();
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// Load Data
|
// Load Data
|
||||||
// -------------------
|
// -------------------
|
||||||
const loadDataTableData = async () => {
|
const loadDataTableData = async () => {
|
||||||
@@ -47,6 +41,10 @@ export default function Claim() {
|
|||||||
setClaimList(response.claim_list);
|
setClaimList(response.claim_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadDataTableData();
|
||||||
|
}, [loadDataTableData])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title={ `claims | ${memberDetail?.name??'_ _ _'}` } sx={{ px: 2 }}>
|
<Page title={ `claims | ${memberDetail?.name??'_ _ _'}` } sx={{ px: 2 }}>
|
||||||
<Grid container gap={6}>
|
<Grid container gap={6}>
|
||||||
|
|||||||
@@ -25,12 +25,6 @@ export default function DailyMonitoringList() {
|
|||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use Effect
|
|
||||||
// --------------------
|
|
||||||
useEffect(() => {
|
|
||||||
loadDataTableData();
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// Load Data
|
// Load Data
|
||||||
// -------------------
|
// -------------------
|
||||||
const loadDataTableData = async () => {
|
const loadDataTableData = async () => {
|
||||||
@@ -42,6 +36,10 @@ export default function DailyMonitoringList() {
|
|||||||
setDataTableData(response);
|
setDataTableData(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadDataTableData();
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<TableContainer component={Paper}>
|
<TableContainer component={Paper}>
|
||||||
|
|||||||
@@ -0,0 +1,361 @@
|
|||||||
|
/**
|
||||||
|
* Core
|
||||||
|
* ============================================
|
||||||
|
*/
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useNavigate } from 'react-router';
|
||||||
|
import { Box, FormControlLabel, Grid, Checkbox, Typography, CircularProgress , Button, styled, Stack, IconButton, Card} from '@mui/material';
|
||||||
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Components
|
||||||
|
* ============================================
|
||||||
|
*/
|
||||||
|
// - Global -
|
||||||
|
import Label from '@/components/Label';
|
||||||
|
// - Local -
|
||||||
|
import FormCreateSearch from './FormCreateSearch';
|
||||||
|
import FormCreateListChoose from './FormCreateListChoose';
|
||||||
|
import FormCreateBtnUpload from './FormCreateBtnUpload';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon, Utils, Types, Functions, theme, hook
|
||||||
|
* ============================================
|
||||||
|
*/
|
||||||
|
import { ArrowBackIosNew } from '@mui/icons-material';
|
||||||
|
import { fDateTimesecond } from '@/utils/formatTime';
|
||||||
|
import { MemberListType } from '../Model/Types';
|
||||||
|
import { addClaimRequest, getMemberList } from '../Model/Functions';
|
||||||
|
import palette from '@/theme/palette';
|
||||||
|
import FormCreateFilesUpload from './FormCreateFilesUpload';
|
||||||
|
import useLoadOnScroll from '@/hooks/useLoadOnScroll';
|
||||||
|
import useCollapseDrawer from '@/hooks/useCollapseDrawer';
|
||||||
|
import FormCreateBtnChoose from './FormCreateBtnChoose';
|
||||||
|
|
||||||
|
export default function FormCreate() {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const defaultListChoosed:MemberListType[] = [];
|
||||||
|
|
||||||
|
// State
|
||||||
|
// -------------------------
|
||||||
|
const [keyword, setKeyword] = useState<string>('');
|
||||||
|
const [listChoosed, setListChoosed] = useState<MemberListType[]>([]);
|
||||||
|
const [isChoosed, setIsChoosed] = useState<boolean>(false);
|
||||||
|
const [formIsLoading, setFormIsLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
// List Choose - auto Scroll
|
||||||
|
// -------------------------
|
||||||
|
const fetchFunction = async (page: number): Promise<MemberListType[]> => getMemberList(page, keyword)
|
||||||
|
|
||||||
|
const {data: MemberList, isLoading: scrollIsLoading, setData, resetLastPage, refetchData} = useLoadOnScroll<MemberListType>(fetchFunction);
|
||||||
|
|
||||||
|
// List Choose - Search
|
||||||
|
// -------------------------
|
||||||
|
const handleSearch = (keyword: string) => {
|
||||||
|
setData([])
|
||||||
|
resetLastPage()
|
||||||
|
setKeyword(keyword)
|
||||||
|
refetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function - Clear Form
|
||||||
|
// -----------------------------
|
||||||
|
const clearForm = () => {
|
||||||
|
setListChoosed(defaultListChoosed);
|
||||||
|
setIsChoosed(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function - Choose Patien Type
|
||||||
|
// -----------------------------
|
||||||
|
const handleChoosePatienType = (data: MemberListType, type: string) => {
|
||||||
|
let newListChoosed = listChoosed.map((list) => {
|
||||||
|
if (data.id == list.id) {
|
||||||
|
list.patien_type = type
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
})
|
||||||
|
|
||||||
|
setListChoosed(newListChoosed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function - Handle Btn Upload
|
||||||
|
// -----------------------------
|
||||||
|
const handleChangeInput = (data: MemberListType, type_file: 'invoice'|'prescription'|'laboratorium', file: any) => {
|
||||||
|
let newListChoosed = listChoosed.map((list) => {
|
||||||
|
if (data.id == list.id) {
|
||||||
|
if (type_file == 'invoice') {
|
||||||
|
if (list.invoice_files == undefined) {
|
||||||
|
list.invoice_files = [file];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list.invoice_files.push(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_file == 'prescription') {
|
||||||
|
if (list.prescription_files == undefined) {
|
||||||
|
list.prescription_files = [file];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list.prescription_files.push(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_file == 'laboratorium') {
|
||||||
|
if (list.laboratorium_files == undefined) {
|
||||||
|
list.laboratorium_files = [file];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list.laboratorium_files.push(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
})
|
||||||
|
|
||||||
|
setListChoosed(newListChoosed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function - Handle Remove Fle
|
||||||
|
// -----------------------------
|
||||||
|
const handleRemoveFile = (data: MemberListType, type_file: 'invoice'|'prescription'|'laboratorium', target_index: number) => {
|
||||||
|
let newListChoosed = listChoosed.map((list) => {
|
||||||
|
if (data.id == list.id) {
|
||||||
|
if (type_file == 'invoice') {
|
||||||
|
list.invoice_files = list.invoice_files?.filter((file: any, index: number) =>{
|
||||||
|
if (target_index !== index) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_file == 'prescription') {
|
||||||
|
list.prescription_files = list.prescription_files?.filter((file: any, index: number) =>{
|
||||||
|
if (target_index !== index) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_file == 'laboratorium') {
|
||||||
|
list.laboratorium_files = list.laboratorium_files?.filter((file: any, index: number) =>{
|
||||||
|
if (target_index !== index) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
})
|
||||||
|
|
||||||
|
setListChoosed(newListChoosed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function - Handle Submit Form
|
||||||
|
// -----------------------------
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
setFormIsLoading(true)
|
||||||
|
let response = await addClaimRequest(listChoosed)
|
||||||
|
setFormIsLoading(false)
|
||||||
|
|
||||||
|
if (response == true) {
|
||||||
|
clearForm()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let isDirty = listChoosed.some((row) => {
|
||||||
|
if (row.patien_type == undefined) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
{/* Back Button */}
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', mb: 5}}>
|
||||||
|
<IconButton size='large' color='inherit' onClick={() => isChoosed==false ? navigate(`/claim-requests`) : setIsChoosed(false)} >
|
||||||
|
<ArrowBackIosNew/>
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
<Typography variant="h5" sx={{ marginLeft: '24px' }}>
|
||||||
|
{'Create Claim Requests'}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Choose Section */}
|
||||||
|
<Grid container spacing={4} sx={{ px: 2, position: 'relative', display: isChoosed==false ? 'inherit' : 'none' }}>
|
||||||
|
{/* Search */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<FormCreateSearch onEmpty={() => handleSearch('')} onSubmit={(keyword) => handleSearch(keyword)} />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{/* List */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{
|
||||||
|
MemberList.map((row, index) => {
|
||||||
|
return (
|
||||||
|
<FormCreateListChoose
|
||||||
|
key={index}
|
||||||
|
data={row}
|
||||||
|
ListChoosed={listChoosed}
|
||||||
|
handleCheckedProp={(checked, data) => {
|
||||||
|
checked ? setListChoosed((prevData) => [...prevData, data]) : setListChoosed((items) => items.filter(item => item.id != data.id))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Loading */}
|
||||||
|
<Grid item xs={12} sx={{ display: scrollIsLoading === false ? 'none' : 'flex', justifyContent: 'center', marginTop: '40px' }}>
|
||||||
|
<CircularProgress />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Submit List */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<FormCreateBtnChoose disabled={listChoosed.length==0} title={`Create Number Batch (${listChoosed.length})`} handleClickProp={() => setIsChoosed(true)} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Input Section */}
|
||||||
|
<Grid container spacing={10} sx={{ px: 2, display: isChoosed==true ? 'inherit' : 'none' }}>
|
||||||
|
{
|
||||||
|
listChoosed.map((row, index) => {
|
||||||
|
return (
|
||||||
|
<Grid key={index} item xs={12}>
|
||||||
|
<Grid container spacing={6}>
|
||||||
|
{/* Patien Name */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Card sx={{ border: '1px solid rgba(0,0,0,0.05)', display: 'flex', justifyContent: 'space-between', borderRadius: '12px', px: '24px', py: '16px' }}>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
||||||
|
{row.name}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="caption" color={palette.light.grey[500]} sx={{ fontWeight: 600 }}>
|
||||||
|
{row.member_id}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Label variant="ghost" color="default">
|
||||||
|
{fDateTimesecond(new Date())}
|
||||||
|
</Label>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Patien Type */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Button
|
||||||
|
sx={{ padding: 2, width: '100%',border: row.patien_type === 'IP' ? '1px solid #19BBBB' : '1px solid #919EAB52' }}
|
||||||
|
variant="outlined"
|
||||||
|
color={row.patien_type === 'IP' ? 'primary' : 'inherit'}
|
||||||
|
onClick={() => {
|
||||||
|
handleChoosePatienType(row, 'IP')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Inpatient
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Button
|
||||||
|
sx={{ padding: 2, width: '100%',border: row.patien_type === 'OP' ? '1px solid #19BBBB' : '1px solid #919EAB52' }}
|
||||||
|
variant="outlined"
|
||||||
|
color={row.patien_type === 'OP' ? 'primary' : 'inherit'}
|
||||||
|
onClick={() => {
|
||||||
|
handleChoosePatienType(row, 'OP')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Outpatient
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Invoice */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6">Real Invoice</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{row.invoice_files && row.invoice_files.map((file, index) => (
|
||||||
|
<Grid item xs={12} key={index}>
|
||||||
|
<FormCreateFilesUpload file={file} handleRemoveFileProp={() => handleRemoveFile(row, 'invoice', index)} />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Grid item xs={12} sx={{display: 'flex', gap: 1}}>
|
||||||
|
<FormCreateBtnUpload handleChangeInputProp={(file) => handleChangeInput(row, 'invoice', file)} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Prescription */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6">Doctor's Prescription and Another Documents</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{row.prescription_files && row.prescription_files.map((file, index) => (
|
||||||
|
<Grid item xs={12} key={index}>
|
||||||
|
<FormCreateFilesUpload file={file} handleRemoveFileProp={() => handleRemoveFile(row, 'prescription', index)} />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Grid item xs={12} sx={{display: 'flex', gap: 1}}>
|
||||||
|
<FormCreateBtnUpload handleChangeInputProp={(file) => handleChangeInput(row, 'prescription', file)} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Laboratorium */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6">Laboratory Results</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{row.laboratorium_files && row.laboratorium_files.map((file, index) => (
|
||||||
|
<Grid item xs={12} key={index}>
|
||||||
|
<FormCreateFilesUpload file={file} handleRemoveFileProp={() => handleRemoveFile(row, 'laboratorium', index)} />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Grid item xs={12} sx={{display: 'flex', gap: 1}}>
|
||||||
|
<FormCreateBtnUpload handleChangeInputProp={(file) => handleChangeInput(row, 'laboratorium', file)} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
|
<Box display="flex" gap={1}>
|
||||||
|
<Button variant="outlined" color="inherit" onClick={() => clearForm()}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<LoadingButton disabled={isDirty} type="submit" variant="contained" loading={formIsLoading} onClick={() => handleSubmit()}>
|
||||||
|
Save Changes
|
||||||
|
</LoadingButton>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { styled, Button } from "@mui/material";
|
||||||
|
import useCollapseDrawer from "@/hooks/useCollapseDrawer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom Style
|
||||||
|
* ============================================
|
||||||
|
*/
|
||||||
|
const DivCustom1 = styled('div')(({ theme }) => ({
|
||||||
|
background: 'white',
|
||||||
|
position: 'fixed',
|
||||||
|
left: '350px',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
paddingLeft: '32px',
|
||||||
|
paddingRight: '32px',
|
||||||
|
paddingTop: '32px',
|
||||||
|
paddingBottom: '48px',
|
||||||
|
[theme.breakpoints.between('sm', 'lg')]: {
|
||||||
|
left: '0px',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
disabled: boolean,
|
||||||
|
title : string,
|
||||||
|
handleClickProp: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FormCreateBtnChoose ({disabled, title, handleClickProp}: Props) {
|
||||||
|
const { collapseClick } = useCollapseDrawer();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DivCustom1 sx={{ left: collapseClick ? '80px' : '350px' }}>
|
||||||
|
<Button variant="contained" color="primary" disabled={disabled} sx={{ width: '100%', p: '11px' }} onClick={handleClickProp}>
|
||||||
|
{title}
|
||||||
|
</Button>
|
||||||
|
</DivCustom1>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { useRef } from "react";
|
||||||
|
import { Box, ButtonBase, Typography } from "@mui/material";
|
||||||
|
import Iconify from "@/components/Iconify";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
handleChangeInputProp: (event: any) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FormCreateBtnUpload ({handleChangeInputProp}: Props) {
|
||||||
|
const fileInput = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonBase sx={{ py: 5, border: '2px dashed #F9FAFB',bgcolor: '#919EAB52',borderRadius: '8px',width: '100%', height: '60px'}} onClick={() => fileInput.current?.click()}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
placeItems: 'center',
|
||||||
|
gap: 1,
|
||||||
|
placeContent: 'center',
|
||||||
|
py:'11px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Iconify icon="icon-park-outline:upload-one" fontSize="1.5em" />
|
||||||
|
<Typography variant="body1" fontWeight="bold" fontSize={'15px'}>
|
||||||
|
Upload Result
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id="file"
|
||||||
|
ref={fileInput}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
multiple
|
||||||
|
onChange={(event) => handleChangeInputProp(event.target.files ? event.target.files[0] : {})}
|
||||||
|
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain, application/pdf"
|
||||||
|
/>
|
||||||
|
</ButtonBase>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import Iconify from "@/components/Iconify";
|
||||||
|
import { ArrowBackIosNew, InsertDriveFile } from '@mui/icons-material';
|
||||||
|
import { Stack, Typography } from "@mui/material";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
file: any,
|
||||||
|
handleRemoveFileProp: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FormCreateFilesUpload({ file, handleRemoveFileProp }: Props) {
|
||||||
|
return (
|
||||||
|
<Stack direction="row" justifyContent={'space-between'} sx={{ mb: '16px' }}>
|
||||||
|
<Stack direction="row" spacing={1} sx={{color: '#19BBBB'}}>
|
||||||
|
<InsertDriveFile />
|
||||||
|
<Typography variant="body2" gutterBottom>{file.name ? file.name : '-'}</Typography>
|
||||||
|
</Stack>
|
||||||
|
<Iconify
|
||||||
|
icon="eva:trash-2-outline"
|
||||||
|
color={'darkred'}
|
||||||
|
onClick={() => {handleRemoveFileProp()}}
|
||||||
|
sx={{cursor: 'pointer'}}
|
||||||
|
></Iconify>
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ import Label from '@/components/Label';
|
|||||||
* ============================================
|
* ============================================
|
||||||
*/
|
*/
|
||||||
import { fDateTimesecond } from '@/utils/formatTime';
|
import { fDateTimesecond } from '@/utils/formatTime';
|
||||||
import { MemberListType } from './Model/Types';
|
import { MemberListType } from '../Model/Types';
|
||||||
import palette from '@/theme/palette';
|
import palette from '@/theme/palette';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,7 +19,7 @@ import { FormProvider, RHFTextField } from '@/components/hook-form';
|
|||||||
* ============================================
|
* ============================================
|
||||||
*/
|
*/
|
||||||
import { Search } from '@mui/icons-material';
|
import { Search } from '@mui/icons-material';
|
||||||
import { SearchType } from './Model/Types';
|
import { SearchType } from '../Model/Types';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSubmit: (keyword: string) => void,
|
onSubmit: (keyword: string) => void,
|
||||||
@@ -4,8 +4,8 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import React, { useRef, useEffect, useMemo, useState } from 'react';
|
import React, { useRef, useEffect, useMemo, useState } from 'react';
|
||||||
import axios from '../../utils/axios';
|
import axios from '../../../utils/axios';
|
||||||
import { FormProvider, RHFTextField } from '../../components/hook-form';
|
import { FormProvider, RHFTextField } from '../../../components/hook-form';
|
||||||
|
|
||||||
import { makeFormData } from '@/utils/jsonToFormData';
|
import { makeFormData } from '@/utils/jsonToFormData';
|
||||||
import {
|
import {
|
||||||
@@ -32,12 +32,12 @@ import {
|
|||||||
ButtonBase,
|
ButtonBase,
|
||||||
Box,
|
Box,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Iconify from '../../components/Iconify';
|
import Iconify from '../../../components/Iconify';
|
||||||
import CalendarTodayIcon from '@mui/icons-material/CalendarToday';
|
import CalendarTodayIcon from '@mui/icons-material/CalendarToday';
|
||||||
import { LoadingButton } from '@mui/lab';
|
import { LoadingButton } from '@mui/lab';
|
||||||
import { fCurrency } from '../../utils/formatNumber';
|
import { fCurrency } from '../../../utils/formatNumber';
|
||||||
import MemberSelectDialog from '../../components/dialogs/MemberSelectDialog';
|
import MemberSelectDialog from '../../../components/dialogs/MemberSelectDialog';
|
||||||
import { Add, DeleteOutline } from '@mui/icons-material';
|
import { Add, ArrowBackIosNew, DeleteOutline } from '@mui/icons-material';
|
||||||
import { ClaimRequest, Files } from '@/@types/claims';
|
import { ClaimRequest, Files } from '@/@types/claims';
|
||||||
import { fDateTimesecond } from '@/utils/formatTime';
|
import { fDateTimesecond } from '@/utils/formatTime';
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ type Props = {
|
|||||||
currentClaim?: ClaimRequest;
|
currentClaim?: ClaimRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
export default function FormEdit({ isEdit, currentClaim }: Props) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
@@ -90,7 +90,7 @@ export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
|||||||
resolver: yupResolver(EditClaimSchema),
|
resolver: yupResolver(EditClaimSchema),
|
||||||
defaultValues,
|
defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
reset,
|
reset,
|
||||||
watch,
|
watch,
|
||||||
@@ -188,8 +188,8 @@ export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
|||||||
_method: 'PUT'
|
_method: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await axios.post(`/claim-requests/${data.id}`, formData);
|
const response = await axios.put(`/claim-requests/${data.id}`, formData);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
enqueueSnackbar('Claim Request Updated Successfully!', { variant: 'success' });
|
enqueueSnackbar('Claim Request Updated Successfully!', { variant: 'success' });
|
||||||
navigate('/claim-requests');
|
navigate('/claim-requests');
|
||||||
@@ -208,6 +208,18 @@ export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<Stack direction="row" alignItems="center" sx={{ mb: 5 }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center'}}>
|
||||||
|
<IconButton size='large' color='inherit' onClick={() => navigate(`/claim-requests`)} >
|
||||||
|
<ArrowBackIosNew/>
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
<Typography variant="h5" sx={{ marginLeft: '24px' }}>
|
||||||
|
{'Edit Claim Requests'}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<Card sx={{paddingX:2, paddingY:2}}>
|
<Card sx={{paddingX:2, paddingY:2}}>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={5}>
|
<Grid item xs={5}>
|
||||||
@@ -224,7 +236,7 @@ export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
|||||||
</Grid>
|
</Grid>
|
||||||
{/* <input type="hidden" name="id"/> */}
|
{/* <input type="hidden" name="id"/> */}
|
||||||
|
|
||||||
|
|
||||||
<Grid item xs={12}></Grid>
|
<Grid item xs={12}></Grid>
|
||||||
|
|
||||||
<Grid item xs={3}>
|
<Grid item xs={3}>
|
||||||
@@ -246,7 +258,7 @@ export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
|||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
<CalendarTodayIcon />
|
<CalendarTodayIcon />
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
), }}
|
), }}
|
||||||
name="date" label="Date of Submission" disabled/>
|
name="date" label="Date of Submission" disabled/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={3}>
|
<Grid item xs={3}>
|
||||||
@@ -310,7 +322,7 @@ export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
|||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
</Grid>
|
</Grid>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
{/* -------------------------------Upload Dokumen Diagnosa------------------------------- */}
|
{/* -------------------------------Upload Dokumen Diagnosa------------------------------- */}
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant='h6'> Diagnosis Document</Typography>
|
<Typography variant='h6'> Diagnosis Document</Typography>
|
||||||
@@ -360,7 +372,7 @@ export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
|||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
</Grid>
|
</Grid>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
{/* -------------------------------Upload Result Hasil Penunjang------------------------------- */}
|
{/* -------------------------------Upload Result Hasil Penunjang------------------------------- */}
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant='h6'> Supporting Result Document</Typography>
|
<Typography variant='h6'> Supporting Result Document</Typography>
|
||||||
@@ -4,7 +4,7 @@ import { ArrowBackIosNew } from '@mui/icons-material';
|
|||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
import { Autocomplete, Button, Card, Collapse, Container, Divider, Grid, Stack, Table, TableBody, TableCell, TableRow, TextField, Typography } from '@mui/material';
|
import { Autocomplete, Button, Card, Collapse, Container, Divider, Grid, Stack, Table, TableBody, TableCell, TableRow, TextField, Typography } from '@mui/material';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { useParams, useNavigate } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
|
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
|
||||||
import { FormProvider, RHFCheckbox, RHFSelect, RHFTextField } from '../../components/hook-form';
|
import { FormProvider, RHFCheckbox, RHFSelect, RHFTextField } from '../../components/hook-form';
|
||||||
import Page from '../../components/Page';
|
import Page from '../../components/Page';
|
||||||
@@ -18,12 +18,11 @@ import { LoadingButton } from '@mui/lab';
|
|||||||
import { fCurrency } from '../../utils/formatNumber';
|
import { fCurrency } from '../../utils/formatNumber';
|
||||||
import Iconify from '../../components/Iconify';
|
import Iconify from '../../components/Iconify';
|
||||||
import { ClaimRequest } from '@/@types/claims';
|
import { ClaimRequest } from '@/@types/claims';
|
||||||
import Form from './Form';
|
import FormEdit from './Components/FormEdit';
|
||||||
import FormCreate from './FormCreate';
|
import FormCreate from './Components/FormCreate';
|
||||||
|
|
||||||
export default function ClaimsCreateUpdate() {
|
export default function ClaimsCreateUpdate() {
|
||||||
|
|
||||||
const navigate = useNavigate()
|
|
||||||
const { themeStretch } = useSettings();
|
const { themeStretch } = useSettings();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
@@ -46,18 +45,6 @@ export default function ClaimsCreateUpdate() {
|
|||||||
return (
|
return (
|
||||||
<Page title={isEdit ? `Edit Claim Request` : "Create New Claim"}>
|
<Page title={isEdit ? `Edit Claim Request` : "Create New Claim"}>
|
||||||
<Container maxWidth={themeStretch ? false : 'xl'}>
|
<Container maxWidth={themeStretch ? false : 'xl'}>
|
||||||
<Stack direction="row" alignItems="center" sx={{ mb: 5 }}>
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center'}}>
|
|
||||||
<IconButton size='large' color='inherit' onClick={() => navigate(`/claim-requests`)} >
|
|
||||||
<ArrowBackIosNew/>
|
|
||||||
</IconButton>
|
|
||||||
|
|
||||||
<Typography variant="h5" sx={{ marginLeft: '24px' }}>
|
|
||||||
{id == undefined ? 'Create Claim Requests' : 'Edit Claim Requests'}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{
|
{
|
||||||
id == undefined
|
id == undefined
|
||||||
?
|
?
|
||||||
@@ -66,7 +53,7 @@ export default function ClaimsCreateUpdate() {
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
(
|
(
|
||||||
<Form isEdit={isEdit} currentClaim={currentClaim} />
|
<FormEdit isEdit={isEdit} currentClaim={currentClaim} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
/**
|
|
||||||
* Core
|
|
||||||
* ============================================
|
|
||||||
*/
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { Box, FormControlLabel, Grid, Checkbox, Typography, CircularProgress , Button, styled} from '@mui/material';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Components
|
|
||||||
* ============================================
|
|
||||||
*/
|
|
||||||
// - Global -
|
|
||||||
import Label from '@/components/Label';
|
|
||||||
// - Local -
|
|
||||||
import FormCreateSearch from './FormCreateSearch';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Icon, Utils, Types, Functions, theme, hook
|
|
||||||
* ============================================
|
|
||||||
*/
|
|
||||||
import { MemberListType } from './Model/Types';
|
|
||||||
import { getMemberList } from './Model/Functions';
|
|
||||||
import useLoadOnScroll from '@/hooks/useLoadOnScroll';
|
|
||||||
import FormCreateListChoose from './FormCreateListChoose';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom Style
|
|
||||||
* ============================================
|
|
||||||
*/
|
|
||||||
const DivCustom1 = styled('div')(({ theme }) => ({
|
|
||||||
left: '350px',
|
|
||||||
[theme.breakpoints.between('sm', 'lg')]: {
|
|
||||||
left: '0px',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default function FormCreate() {
|
|
||||||
// State
|
|
||||||
// -------------------------
|
|
||||||
const [keyword, setKeyword] = useState<string>('');
|
|
||||||
const [listChoosed, setListChoosed] = useState<MemberListType[]>([]);
|
|
||||||
const [isChoosed, setIsChoosed] = useState<boolean>(false);
|
|
||||||
|
|
||||||
// List Choose - auto Scroll
|
|
||||||
// -------------------------
|
|
||||||
const fetchFunction = async (page: number): Promise<MemberListType[]> => getMemberList(page, keyword)
|
|
||||||
const {data: MemberList, isLoading, setData, resetLastPage, refetchData} = useLoadOnScroll<MemberListType>(fetchFunction);
|
|
||||||
|
|
||||||
// List Choose - Search
|
|
||||||
// -------------------------
|
|
||||||
const handleSearch = (keyword: string) => {
|
|
||||||
setData([])
|
|
||||||
resetLastPage()
|
|
||||||
setKeyword(keyword)
|
|
||||||
refetchData()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box sx={{ position: 'relative' }}>
|
|
||||||
{/* Choose Section */}
|
|
||||||
<Grid container spacing={4} sx={{ px: 2, display: isChoosed==false ? 'inherit' : 'none' }}>
|
|
||||||
{/* Search */}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<FormCreateSearch onEmpty={() => handleSearch('')} onSubmit={(keyword) => handleSearch(keyword)} />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
{/* List */}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
{
|
|
||||||
MemberList.map((row, index) => {
|
|
||||||
return (
|
|
||||||
<FormCreateListChoose
|
|
||||||
key={index}
|
|
||||||
data={row}
|
|
||||||
ListChoosed={listChoosed}
|
|
||||||
handleCheckedProp={(checked, data) => {
|
|
||||||
checked ? setListChoosed((prevData) => [...prevData, data]) : setListChoosed((items) => items.filter(item => item.id != data.id))
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{/* Loading */}
|
|
||||||
<Grid item xs={12} sx={{ display: isLoading === false ? 'none' : 'flex', justifyContent: 'center', marginTop: '40px' }}>
|
|
||||||
<CircularProgress />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{/* Submit List */}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<DivCustom1 sx={{ position: 'fixed', bottom: 0, right: 0, background: 'white', px: 4, pt: 4, pb: 6}}>
|
|
||||||
<Button variant="contained" color="primary" disabled={listChoosed.length==0} sx={{ width: '100%', p: '11px' }} onClick={() => {setIsChoosed(true)}}>
|
|
||||||
Create Number Batch ({listChoosed.length})
|
|
||||||
</Button>
|
|
||||||
</DivCustom1>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{/* Input Section */}
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import axios from '@/utils/axios';
|
import axios from '@/utils/axios';
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import { MemberListType } from './Types';
|
import { MemberListType } from './Types';
|
||||||
|
import { makeFormData } from '@/utils/jsonToFormData';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listing Member
|
* Listing Member
|
||||||
@@ -20,3 +21,53 @@ export const getMemberList = async ( page: number, keyword: string ): Promise<Me
|
|||||||
|
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Claim Request
|
||||||
|
*/
|
||||||
|
export const addClaimRequest = async ( data: MemberListType[] ): Promise<boolean> => {
|
||||||
|
// Mapping
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
data.map((row, index) => {
|
||||||
|
formData.append(`member_id[${index}]`, row.id.toString());
|
||||||
|
formData.append(`service_code[${index}]`, row.patien_type??'');
|
||||||
|
|
||||||
|
if (row.invoice_files != undefined) {
|
||||||
|
row.invoice_files.forEach((file, file_index) => {
|
||||||
|
formData.append(`invoice[${index}][${file_index}]`, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.prescription_files != undefined) {
|
||||||
|
row.prescription_files.forEach((file, file_index) => {
|
||||||
|
formData.append(`prescription[${index}][${file_index}]`, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.laboratorium_files != undefined) {
|
||||||
|
row.laboratorium_files.forEach((file, file_index) => {
|
||||||
|
formData.append(`laboratorium[${index}][${file_index}]`, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Axios
|
||||||
|
const response = await axios.post(`/claim-requests`, formData)
|
||||||
|
.then((res) =>{
|
||||||
|
enqueueSnackbar("Berhasil membuat data !", {
|
||||||
|
variant: 'success',
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.catch((res) => {
|
||||||
|
enqueueSnackbar("server error !", {
|
||||||
|
variant: 'error',
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return response;
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ export type SearchType = {
|
|||||||
* Member List
|
* Member List
|
||||||
*/
|
*/
|
||||||
export type MemberListType = {
|
export type MemberListType = {
|
||||||
id : string,
|
id : string,
|
||||||
member_id : string,
|
member_id : string,
|
||||||
name : string,
|
name : string,
|
||||||
|
patien_type? : string,
|
||||||
|
invoice_files? : any[],
|
||||||
|
laboratorium_files? : any[],
|
||||||
|
prescription_files? : any[]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user