Merge branch 'staging' of itcorp.primaya.id:rajif/aso into staging

This commit is contained in:
Linksehat Staging Server
2023-10-10 10:37:02 +07:00
20 changed files with 1000 additions and 355 deletions

View File

@@ -25,6 +25,7 @@ class ClaimReportController extends Controller
$corporateEmployee->where('corporate_id', $corporateId); $corporateEmployee->where('corporate_id', $corporateId);
}); });
}) })
->whereHas('claim', fn ($query) => $query->where('status', 'approved'))
->where('status', 'approved') ->where('status', 'approved')
->get(); ->get();
@@ -38,10 +39,21 @@ class ClaimReportController extends Controller
->where('status', 'approved') ->where('status', 'approved')
->get(); ->get();
$disbrusments = ClaimRequest::query()
->whereHas('member', function ($query) use ($corporateId) {
$query->whereHas('employeds', function ($corporateEmployee) use ($corporateId) {
$corporateEmployee->where('corporate_id', $corporateId);
});
})
->whereHas('claim', fn ($query) => $query->where('status', 'disbrusmented'))
->where('status', 'approved')
->get();
return Helper::responseJson([ return Helper::responseJson([
'requesteds' => count($requesteds), 'requesteds' => count($requesteds),
'approveds' => count($approveds), 'approveds' => count($approveds),
'rejecteds' => count($rejecteds) 'rejecteds' => count($rejecteds),
'disbrusments' => count($disbrusments)
]); ]);
} }

View File

@@ -62,8 +62,8 @@ class ClaimRequestController extends Controller
'system_origin' => 'client-portal' 'system_origin' => 'client-portal'
]); ]);
if ($request->hasFile('result_files')) { if ($request->hasFile('laboratorium')) {
foreach ($request->result_files[$key] as $file) { foreach ($request->laboratorium[$key] as $file) {
$pathFile = File::storeFile('claim-result', $newClaimRequest->id, $file); $pathFile = File::storeFile('claim-result', $newClaimRequest->id, $file);
$newClaimRequest->files()->updateOrCreate([ $newClaimRequest->files()->updateOrCreate([
'type' => 'claim-result', 'type' => 'claim-result',
@@ -77,8 +77,8 @@ class ClaimRequestController extends Controller
} }
} }
if ($request->hasFile('diagnosa_files')) { if ($request->hasFile('prescription')) {
foreach ($request->diagnosa_files[$key] as $file) { foreach ($request->prescription[$key] as $file) {
$pathFile = File::storeFile('claim-diagnosis', $newClaimRequest->id, $file); $pathFile = File::storeFile('claim-diagnosis', $newClaimRequest->id, $file);
$newClaimRequest->files()->updateOrCreate([ $newClaimRequest->files()->updateOrCreate([
'type' => 'claim-diagnosis', 'type' => 'claim-diagnosis',
@@ -92,8 +92,8 @@ class ClaimRequestController extends Controller
} }
} }
if ($request->hasFile('kondisi_files')) { if ($request->hasFile('invoice')) {
foreach ($request->kondisi_files[$key] as $file) { foreach ($request->invoice[$key] as $file) {
$pathFile = File::storeFile('claim-kondisi', $newClaimRequest->id, $file); $pathFile = File::storeFile('claim-kondisi', $newClaimRequest->id, $file);
$newClaimRequest->files()->updateOrCreate([ $newClaimRequest->files()->updateOrCreate([
'type' => 'claim-kondisi', 'type' => 'claim-kondisi',

View File

@@ -12,6 +12,7 @@ use Modules\Client\Transformers\ClaimReport\MemberResources as ClaimReportMember
use Modules\Client\Transformers\Dashboard\MemberResources as ClaimSubmitMemberResources; 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\Dashboard\MemberEmployeeDataResources as DashboardMemberEmployeeDataResources;
use Modules\Client\Transformers\DataMemberResource; use Modules\Client\Transformers\DataMemberResource;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@@ -29,8 +30,8 @@ class CorporateMemberController extends Controller
{ {
switch ($request->input('type')) { switch ($request->input('type')) {
case 'employee-data': case 'employee-data':
$members = $this->corporateMemberService->getAllMemberAlarmCenter($corporate_id, $request); $members = $this->corporateMemberService->getAllMemberEmployeeData($corporate_id, $request);
return response()->json(Helper::paginateResources(DashboardMemberAlarmResources::collection($members))); return response()->json(Helper::paginateResources(DashboardMemberEmployeeDataResources::collection($members)));
case 'claim-report': case 'claim-report':
$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(ClaimReportMemberResources::collection($members)));

View File

@@ -16,13 +16,13 @@ class MemberResources extends JsonResource
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
'codeRequest' => $this->code, 'code' => $this->code,
'memberId' => $this->member_id, 'member_id' => $this->member_id,
'fullName' => $this->full_name, 'full_name' => $this->full_name,
'division' => $this->division_name ?? '', 'division_name' => $this->division_name ?? '',
'status' => $this->status, 'status' => $this->status,
'claimRequestId' => $this->claim_request_id, 'claimRequestId' => $this->claim_request_id,
'submissionDate' => $this->submission_date, 'submission_date' => $this->submission_date,
]; ];
} }
} }

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\Client\Transformers\Dashboard;
use Illuminate\Http\Resources\Json\JsonResource;
class MemberEmployeeDataResources extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'personId' => $this->person_id,
'memberId' => $this->member_id,
'fullName' => $this->full_name,
'service' => $this->service_code,
'start_date' => $this->start_date,
'end_date' => $this->end_date,
'status' => $this->active,
];
}
}

View File

@@ -6,6 +6,7 @@ use App\Models\Member;
use App\Models\Encounter; use App\Models\Encounter;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class CorporateMemberService class CorporateMemberService
{ {
@@ -47,42 +48,43 @@ class CorporateMemberService
{ {
$limit = $request->has('perPage') ? $request->input('perPage') : 10; $limit = $request->has('perPage') ? $request->input('perPage') : 10;
return Member::query() $results = DB::table('claim_requests')
->joinClaimRequests('right') ->leftJoin('claims', 'claim_requests.id', '=', 'claims.claim_request_id')
->joinCorporateEmployees('left') ->leftJoin('members', 'claim_requests.member_id', '=', 'members.id')
->joinCorporateDivisions('left') ->leftJoin('corporate_employees', 'members.id', '=', 'corporate_employees.member_id')
->with('person:id,name_prefix,name_suffix,gender,name,birth_date') ->leftJoin('corporate_divisions', 'corporate_employees.division_id', '=', 'corporate_divisions.id')
->withSum('claims', 'total_claim') ->where('corporate_employees.corporate_id', '=', $corporateId)
->whereHas('employeds', function (Builder $corporateEmployee) use ($corporateId) { ->when($request->input('search'), function ($query, $search) {
$corporateEmployee->where('corporate_id', $corporateId); $query->where(function ($query) use ($search) {
}) $query->orWhere('claim_requests.code', 'like', "%" . $search . "%")
->when($request->input('search'), function (Builder $query, $search) { ->orWhere('members.member_id', 'like', "%" . $search . "%")
$query->where(function (Builder $query) use ($search) { ->orWhere('members.name', 'like', "%" . $search . "%")
$query->orWhere('members.member_id', 'like', "%" . $search . "%") ->orWhere('corporate_divisions.name', 'like', "%" . $search . "%")
->orWhere('members.name', 'like', "%" . $search . "%"); ->orWhere('claim_requests.status', 'like', "%" . $search . "%")
}); ->orWhere('claim_requests.submission_date', 'like', "%" . $search . "%");
}) });
->when($request->input('division'), function (Builder $division, $value) { })
$division->whereHas('division', function (Builder $corporateEmployee) use ($value) { ->when($request->has('orderBy'), function ($query) use ($request) {
$corporateEmployee->where('division_id', $value); $orderBy = $request->orderBy;
}); $direction = $request->order ?? 'asc';
})
->when($request->has('orderBy'), function (Builder $query) use ($request) {
$orderBy = match ($request->orderBy) {
'memberId' => 'member_id',
'fullName' => 'name',
'codeRequest' => 'code',
default => ''
};
if (in_array($orderBy, ['member_id', 'name', 'active', 'code'])) { $query->orderBy($orderBy, $direction);
$query->getQuery()->orderBy($orderBy, $request->order); })
} elseif ($request->orderBy === 'division') { ->select('members.id', 'claim_requests.code','members.member_id', 'members.name as full_name', 'corporate_divisions.name AS division_name',
$query->getQuery()->orderBy('corporate_divisions.name', $request->order); DB::raw('
} CASE
}) WHEN claim_requests.status = "requested" THEN "requested"
->select(['members.id', 'members.person_id', 'members.member_id', 'members.name', 'corporate_divisions.name AS division_name', 'claim_requests.status', 'claim_requests.code', 'claim_requests.id AS claim_request_id','claim_requests.submission_date']) WHEN claim_requests.status = "approved" AND claims.status = "approved" THEN "approved"
->paginate($limit); WHEN claim_requests.status = "approved" AND claims.status = "declined" THEN "declined"
WHEN claim_requests.status = "approved" AND claims.status = "disbrusmented" THEN "disbrusmented"
WHEN claim_requests.status = "approved" AND claims.status = "received" THEN "pending"
WHEN claim_requests.status = "approved" AND claims.status = "received" THEN "review"
ELSE ""
END AS status
'),
'claim_requests.id AS claim_request_id', 'claim_requests.submission_date')
->paginate($limit);
return $results;
} }
public function getAllMemberClaimSubmits(int $corporateId, Request $request) public function getAllMemberClaimSubmits(int $corporateId, Request $request)
@@ -165,6 +167,44 @@ class CorporateMemberService
->paginate($limit); ->paginate($limit);
} }
public function getAllMemberEmployeeData(int $corporateId, Request $request)
{
$limit = $request->has('perPage') ? $request->input('perPage') : 10;
return Member::query()
->joinCorporateEmployees('left')
->joinMemberPlans('left')
->joinPlans('left')
->with(['currentPlan', 'person'])
->where('corporate_employees.corporate_id', $corporateId)
->when($request->input('search'), function (Builder $query, $search) {
$query->where(function (Builder $query) use ($search) {
$query->orWhere('members.member_id', 'like', "%" . $search . "%")
->orWhere('members.name', 'like', "%" . $search . "%");
});
})
->when($request->input('division'), function (Builder $query, $value) {
$query->where('corporate_employees.division_id', $value);
})
->when($request->has('orderBy'), function (Builder $query) use ($request) {
$orderBy = match ($request->input('orderBy')) {
'memberId' => 'member_id',
'fullName' => 'name',
'status' => 'active',
'start_date' => 'member_plans.start',
'end_date' => 'member_plans.end',
'service' => 'plans.service_code',
default => ''
};
$query->getQuery()->orderBy($orderBy, $request->order);
})
->select(['members.id', 'members.person_id', 'members.member_id', 'members.name', 'member_plans.start AS start_date', 'member_plans.end AS end_date', 'plans.active', 'plans.service_code'])
->selectRaw("(select sum(`claims`.`total_claim`) from `claims` where `members`.`id` = `claims`.`member_id` AND `claims`.`deleted_at` IS NULL) AS `claims_sum_total_claim`")
->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);

View File

@@ -2,6 +2,6 @@ GENERATE_SOURCEMAP=false
PORT=8083 PORT=8083
REACT_APP_HOST_API_URL="http://aso.test" REACT_APP_HOST_API_URL="https://aso-api.linksehat.dev/api/client"
VITE_API_URL="http://aso.test/api/client" VITE_API_URL="https://aso-api.linksehat.dev/api/client"

View File

@@ -52,6 +52,7 @@
"@mui/utils": "^5.11.13", "@mui/utils": "^5.11.13",
"@mui/x-data-grid": "^5.17.26", "@mui/x-data-grid": "^5.17.26",
"@mui/x-date-pickers": "5.0.0-beta.2", "@mui/x-date-pickers": "5.0.0-beta.2",
"@reduxjs/toolkit": "^1.9.7",
"@vitejs/plugin-react": "^1.3.2", "@vitejs/plugin-react": "^1.3.2",
"apexcharts": "^3.37.2", "apexcharts": "^3.37.2",
"axios": "^0.27.2", "axios": "^0.27.2",
@@ -78,6 +79,7 @@
"react-lazy-load-image-component": "^1.5.6", "react-lazy-load-image-component": "^1.5.6",
"react-number-format": "^5.1.4", "react-number-format": "^5.1.4",
"react-quill": "2.0.0-beta.4", "react-quill": "2.0.0-beta.4",
"react-redux": "^8.1.3",
"react-router": "^6.9.0", "react-router": "^6.9.0",
"react-router-dom": "^6.9.0", "react-router-dom": "^6.9.0",
"simplebar": "^5.3.9", "simplebar": "^5.3.9",

View File

@@ -47,6 +47,9 @@ dependencies:
'@mui/x-date-pickers': '@mui/x-date-pickers':
specifier: 5.0.0-beta.2 specifier: 5.0.0-beta.2
version: 5.0.0-beta.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.14)(@mui/system@5.11.14)(date-fns@2.29.3)(react-dom@17.0.2)(react@17.0.2) version: 5.0.0-beta.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.14)(@mui/system@5.11.14)(date-fns@2.29.3)(react-dom@17.0.2)(react@17.0.2)
'@reduxjs/toolkit':
specifier: ^1.9.7
version: 1.9.7(react-redux@8.1.3)(react@17.0.2)
'@vitejs/plugin-react': '@vitejs/plugin-react':
specifier: ^1.3.2 specifier: ^1.3.2
version: 1.3.2 version: 1.3.2
@@ -125,6 +128,9 @@ dependencies:
react-quill: react-quill:
specifier: 2.0.0-beta.4 specifier: 2.0.0-beta.4
version: 2.0.0-beta.4(react-dom@17.0.2)(react@17.0.2) version: 2.0.0-beta.4(react-dom@17.0.2)(react@17.0.2)
react-redux:
specifier: ^8.1.3
version: 8.1.3(@types/react-dom@17.0.19)(@types/react@17.0.53)(react-dom@17.0.2)(react@17.0.2)(redux@4.2.1)
react-router: react-router:
specifier: ^6.9.0 specifier: ^6.9.0
version: 6.9.0(react@17.0.2) version: 6.9.0(react@17.0.2)
@@ -2336,6 +2342,25 @@ packages:
resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==}
dev: false dev: false
/@reduxjs/toolkit@1.9.7(react-redux@8.1.3)(react@17.0.2):
resolution: {integrity: sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==}
peerDependencies:
react: ^16.9.0 || ^17.0.0 || ^18
react-redux: ^7.2.1 || ^8.0.2
peerDependenciesMeta:
react:
optional: true
react-redux:
optional: true
dependencies:
immer: 9.0.21
react: 17.0.2
react-redux: 8.1.3(@types/react-dom@17.0.19)(@types/react@17.0.53)(react-dom@17.0.2)(react@17.0.2)(redux@4.2.1)
redux: 4.2.1
redux-thunk: 2.4.2(redux@4.2.1)
reselect: 4.1.8
dev: false
/@remix-run/router@1.4.0: /@remix-run/router@1.4.0:
resolution: {integrity: sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==} resolution: {integrity: sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==}
engines: {node: '>=14'} engines: {node: '>=14'}
@@ -2572,6 +2597,13 @@ packages:
'@types/range-parser': 1.2.4 '@types/range-parser': 1.2.4
dev: false dev: false
/@types/hoist-non-react-statics@3.3.2:
resolution: {integrity: sha512-YIQtIg4PKr7ZyqNPZObpxfHsHEmuB8dXCxd6qVcGuQVDK2bpsF7bYNnBJ4Nn7giuACZg+WewExgrtAJ3XnA4Xw==}
dependencies:
'@types/react': 17.0.53
hoist-non-react-statics: 3.3.2
dev: false
/@types/json-schema@7.0.11: /@types/json-schema@7.0.11:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true dev: true
@@ -2619,7 +2651,6 @@ packages:
resolution: {integrity: sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==} resolution: {integrity: sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==}
dependencies: dependencies:
'@types/react': 17.0.53 '@types/react': 17.0.53
dev: true
/@types/react-is@17.0.3: /@types/react-is@17.0.3:
resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==} resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==}
@@ -2668,6 +2699,10 @@ packages:
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==} resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
dev: true dev: true
/@types/use-sync-external-store@0.0.3:
resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==}
dev: false
/@typescript-eslint/eslint-plugin@5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@4.9.5): /@typescript-eslint/eslint-plugin@5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@4.9.5):
resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==} resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -4467,6 +4502,10 @@ packages:
engines: {node: '>= 4'} engines: {node: '>= 4'}
dev: true dev: true
/immer@9.0.21:
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
dev: false
/import-fresh@3.3.0: /import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -5341,6 +5380,40 @@ packages:
react-dom: 17.0.2(react@17.0.2) react-dom: 17.0.2(react@17.0.2)
dev: false dev: false
/react-redux@8.1.3(@types/react-dom@17.0.19)(@types/react@17.0.53)(react-dom@17.0.2)(react@17.0.2)(redux@4.2.1):
resolution: {integrity: sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==}
peerDependencies:
'@types/react': ^16.8 || ^17.0 || ^18.0
'@types/react-dom': ^16.8 || ^17.0 || ^18.0
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
react-native: '>=0.59'
redux: ^4 || ^5.0.0-beta.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
react-dom:
optional: true
react-native:
optional: true
redux:
optional: true
dependencies:
'@babel/runtime': 7.21.0
'@types/hoist-non-react-statics': 3.3.2
'@types/react': 17.0.53
'@types/react-dom': 17.0.19
'@types/use-sync-external-store': 0.0.3
hoist-non-react-statics: 3.3.2
react: 17.0.2
react-dom: 17.0.2(react@17.0.2)
react-is: 18.2.0
redux: 4.2.1
use-sync-external-store: 1.2.0(react@17.0.2)
dev: false
/react-refresh@0.13.0: /react-refresh@0.13.0:
resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==} resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -5391,6 +5464,20 @@ packages:
object-assign: 4.1.1 object-assign: 4.1.1
dev: false dev: false
/redux-thunk@2.4.2(redux@4.2.1):
resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==}
peerDependencies:
redux: ^4
dependencies:
redux: 4.2.1
dev: false
/redux@4.2.1:
resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==}
dependencies:
'@babel/runtime': 7.21.0
dev: false
/regenerate-unicode-properties@10.1.0: /regenerate-unicode-properties@10.1.0:
resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -5447,6 +5534,10 @@ packages:
resolution: {integrity: sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==} resolution: {integrity: sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==}
dev: false dev: false
/reselect@4.1.8:
resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==}
dev: false
/resolve-from@4.0.0: /resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -6009,6 +6100,14 @@ packages:
punycode: 2.3.0 punycode: 2.3.0
dev: true dev: true
/use-sync-external-store@1.2.0(react@17.0.2):
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
react: 17.0.2
dev: false
/vite-plugin-pwa@0.12.8(vite@3.2.5)(workbox-build@6.5.4)(workbox-window@6.5.4): /vite-plugin-pwa@0.12.8(vite@3.2.5)(workbox-build@6.5.4)(workbox-window@6.5.4):
resolution: {integrity: sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==} resolution: {integrity: sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==}
peerDependencies: peerDependencies:

View File

@@ -9,27 +9,31 @@ import { ProgressBarStyle } from './components/ProgressBar';
import ThemeColorPresets from './components/ThemeColorPresets'; import ThemeColorPresets from './components/ThemeColorPresets';
import MotionLazyContainer from './components/animate/MotionLazyContainer'; import MotionLazyContainer from './components/animate/MotionLazyContainer';
import { SnackbarProvider } from 'notistack'; import { SnackbarProvider } from 'notistack';
import { Provider } from 'react-redux';
import store from './store';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
export default function App() { export default function App() {
return ( return (
<ThemeProvider> <Provider store={store}>
<SnackbarProvider <ThemeProvider>
autoHideDuration={2000} <SnackbarProvider
anchorOrigin={{ vertical: 'top', horizontal: 'right' }} autoHideDuration={2000}
> anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
<ThemeColorPresets> >
<RtlLayout> <ThemeColorPresets>
<MotionLazyContainer> <RtlLayout>
<ProgressBarStyle /> <MotionLazyContainer>
{/* <Settings /> */} <ProgressBarStyle />
<ScrollToTop /> {/* <Settings /> */}
<Router /> <ScrollToTop />
</MotionLazyContainer> <Router />
</RtlLayout> </MotionLazyContainer>
</ThemeColorPresets> </RtlLayout>
</SnackbarProvider> </ThemeColorPresets>
</ThemeProvider> </SnackbarProvider>
</ThemeProvider>
</Provider>
); );
} }

View File

@@ -15,6 +15,7 @@ import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate
import List from './List'; import List from './List';
// theme // theme
import palette from '../../theme/palette'; import palette from '../../theme/palette';
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
interface ClaimStatusType { interface ClaimStatusType {
name: string; name: string;
@@ -35,17 +36,22 @@ export default function Drugs() {
{ {
name: 'Requested', name: 'Requested',
value: claimStatus.data.data.requesteds, value: claimStatus.data.data.requesteds,
color: palette.dark.primary.dark, color: '#159C9C',
}, },
{ {
name: 'Approval', name: 'Approval',
value: claimStatus.data.data.approveds, value: claimStatus.data.data.approveds,
color: palette.dark.warning.dark, color: '#229A16',
}, },
{ {
name: 'Rejected', name: 'Disbrusment',
value: claimStatus.data.data.disbrusments,
color: '#BF6919',
},
{
name: 'Decline',
value: claimStatus.data.data.rejecteds, value: claimStatus.data.data.rejecteds,
color: palette.dark.error.dark, color: '#B72136',
}, },
]); ]);
})(); })();
@@ -54,6 +60,13 @@ export default function Drugs() {
return ( return (
<Page title="Claim Reports"> <Page title="Claim Reports">
<Container maxWidth={themeStretch ? false : 'xl'}> <Container maxWidth={themeStretch ? false : 'xl'}>
<HeaderBreadcrumbs
heading={'Claim Report'}
links={[
{ name: 'Case Management', href: '/claim-report' },
{ name: 'Claim Report', href: '/claim-report'}
]}
/>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} lg={12} md={12}> <Grid item xs={12} lg={12} md={12}>
<CardClaimStatus data={listClaimStatusItems} /> <CardClaimStatus data={listClaimStatusItems} />

View File

@@ -1,5 +1,5 @@
/* ---------------------------------- @mui ---------------------------------- */ /* ---------------------------------- @mui ---------------------------------- */
import { Stack, Button } from '@mui/material'; import { Stack, Button, MenuItem } from '@mui/material';
/* ---------------------------------- axios --------------------------------- */ /* ---------------------------------- axios --------------------------------- */
// import axios from 'axios'; // import axios from 'axios';
import axios from '../../utils/axios'; import axios from '../../utils/axios';
@@ -15,6 +15,12 @@ import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate
import { HeadCell, Order, PaginationTableProps } from '../../@types/table'; import { HeadCell, Order, PaginationTableProps } from '../../@types/table';
import { useSearchParams, useNavigate } from 'react-router-dom'; import { useSearchParams, useNavigate } from 'react-router-dom';
import { fDate } from '../../utils/formatTime'; import { fDate } from '../../utils/formatTime';
import Typography from '@mui/material/Typography';
import { format } from 'date-fns';
import TableMoreMenu from '../../components/table/TableMoreMenu';
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
import HistoryIcon from '@mui/icons-material/History';
import SearchIcon from '@mui/icons-material/Search';
export default function List() { export default function List() {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -47,7 +53,7 @@ export default function List() {
/* ------------------------------ handle order ------------------------------ */ /* ------------------------------ handle order ------------------------------ */
const [order, setOrder] = useState<Order>('desc'); const [order, setOrder] = useState<Order>('desc');
const [orderBy, setOrderBy] = useState('codeRequest'); const [orderBy, setOrderBy] = useState('code');
const orders = { const orders = {
order: order, order: order,
@@ -109,41 +115,41 @@ export default function List() {
/* -------------------------------- headCell -------------------------------- */ /* -------------------------------- headCell -------------------------------- */
const headCells: HeadCell<never>[] = [ const headCells: HeadCell<never>[] = [
{ {
id: 'memberId', id: 'submission_date',
align: 'center',
label: 'Request Date',
isSort: true,
},
{
id: 'member_id',
align: 'left', align: 'left',
label: 'Member ID', label: 'Member ID',
isSort: true, isSort: true,
}, },
{ {
id: 'codeRequest', id: 'code',
align: 'left', align: 'left',
label: 'Code Request', label: 'Claim Code',
isSort: true, isSort: true,
}, },
{ {
id: 'submissionDate', id: 'full_name',
align: 'left',
label: 'Request Date',
isSort: true,
},
{
id: 'fullName',
align: 'left', align: 'left',
label: 'Name', label: 'Name',
isSort: true, isSort: true,
}, },
{ {
id: 'division', id: 'division_name',
align: 'left', align: 'left',
label: 'Divisi', label: 'Division',
isSort: false, isSort: true,
}, },
{ {
id: 'status', id: 'status',
align: 'center', align: 'center',
label: 'Status', label: 'Status',
isSort: false, isSort: true,
}, },
{ {
id: 'action', id: 'action',
@@ -168,49 +174,99 @@ export default function List() {
params: { ...parameters, type: 'claim-report' }, params: { ...parameters, type: 'claim-report' },
}); });
console.log(response.data.data);
setData( setData(
response.data.data.map((obj: any) => ({ response.data.data.map((obj: any) => ({
...obj, ...obj,
status: status:
obj.status === 'requested' ? ( obj.status === 'requested' ? (
<Button <Typography
onClick={() => navigate(`dialog-detail/${obj.claimRequestId}`)} variant="body2"
sx={{ sx={{
backgroundColor: 'rgba(84, 214, 44, 0.16)', width: 'Hug (6px)',
color: palette.dark.success.dark, height: 'Hug (22px)',
paddingX: 1.5, left: '862px',
paddingY: 1, top: '17px',
'&:hover': { color: '#159C9C',
backgroundColor: 'rgba(84, 214, 44, 0.16)', backgroundColor: '#00AB5529',
color: palette.dark.success.dark, padding: '1px, 8px',
}, borderRadius: '6px',
}} }}
> >
Request Request
</Button> </Typography>
) : obj.status === 'approved' ? ( ) : obj.status === 'approved' ? (
<Button <Typography
onClick={() => navigate(`dialog-detail/${obj.claimRequestId}`)} variant="body2"
sx={{ sx={{
backgroundColor: (theme) => theme.palette.secondary.main, width: 'Hug (6px)',
color: '#FFFF', height: 'Hug (22px)',
paddingX: 1.5, left: '862px',
paddingY: 1, top: '17px',
'&:hover': { color: '#229A16',
backgroundColor: (theme) => theme.palette.secondary.dark, backgroundColor: '#54D62C29',
color: '#FFFF', padding: '1px, 8px',
}, borderRadius: '6px',
}} }}
> >
Approved Approval
</Button> </Typography>
) : obj.status === 'declined' ? (
<Typography
variant="body2"
sx={{
width: 'Hug (6px)',
height: 'Hug (22px)',
left: '862px',
top: '17px',
color: '#B72136',
backgroundColor: '#FF484229',
padding: '1px, 8px',
borderRadius: '6px',
}}
>
Decline
</Typography>
) : obj.status === 'pending' ? (
<Typography
variant="body2"
sx={{
width: 'Hug (6px)',
height: 'Hug (22px)',
left: '862px',
top: '17px',
color: '#BF6919',
backgroundColor: '#FFC10729',
padding: '1px, 8px',
borderRadius: '6px',
}}
>
Pending
</Typography>
) : obj.status === 'review' ? (
<Typography
variant="body2"
sx={{
width: 'Hug (6px)',
height: 'Hug (22px)',
left: '862px',
top: '17px',
color: '#0C53B7',
backgroundColor: '#1890FF29',
padding: '1px, 8px',
borderRadius: '6px',
}}
>
Review
</Typography>
) : ( ) : (
<Button <Button
startIcon={<Iconify icon="fa6-solid:clock" />} startIcon={<Iconify icon="fa6-solid:clock" />}
sx={{ sx={{
backgroundColor: '#CD7B2E', backgroundColor: '#CD7B2E',
color: '#FFFF', color: '#FFFF',
paddingX: 1.5, padding: '1px, 8px',
paddingY: 1, paddingY: 1,
'&:hover': { '&:hover': {
backgroundColor: '#BF6919', backgroundColor: '#BF6919',
@@ -221,8 +277,31 @@ export default function List() {
Ongoing Ongoing
</Button> </Button>
), ),
submissionDate: submission_date:
obj.submissionDate ? fDate(obj.submissionDate) : '' <Typography
sx={{
backgroundColor: (theme) => theme.palette.grey[300],
borderRadius: '4px',
width: '70%',
}}
variant="body2"
>
{obj.submission_date ? format(new Date(obj.submission_date), "d MMM yyyy") : ''}
</Typography>
,
action:
<TableMoreMenu actions={
<>
<MenuItem onClick={() => navigate ('/employee-data/user-profile/'+obj.personId)}>
<SearchIcon />
Detail
</MenuItem>
<MenuItem onClick={() => navigate ('/employee-data/user-profile/'+obj.personId)}>
<HistoryIcon />
History
</MenuItem>
</>
} />
})) }))
); );

View File

@@ -14,6 +14,7 @@ import {
Stack, Stack,
Grid, Grid,
Avatar, Avatar,
ButtonBase,
} from '@mui/material'; } from '@mui/material';
import { Add } from '@mui/icons-material'; import { Add } from '@mui/icons-material';
// components // components
@@ -23,10 +24,17 @@ import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
// theme // theme
import palette from '../../theme/palette'; import palette from '../../theme/palette';
// React // React
import { ReactElement, useRef, useState } from 'react'; import { Fragment, ReactElement, useEffect, useRef, useState } from 'react';
import { useSearchParams, useNavigate, Link } from 'react-router-dom'; import { useSearchParams, useNavigate, Link } from 'react-router-dom';
import { fPostFormat } from '../../utils/formatTime'; import { fPostFormat } from '../../utils/formatTime';
import { fCurrency } from '../../utils/formatNumber'; import { fCurrency } from '../../utils/formatNumber';
import { LoadingButton } from '@mui/lab';
import Iconify from '../../components/Iconify';
import { useSelector } from 'react-redux';
import { RootState } from '../../store';
import { makeFormData } from '../../utils/jsonToFormData';
import { useSnackbar } from 'notistack';
import axiosInstance from '../../utils/axios';
// -------------------------------- type -------------------------------------- // -------------------------------- type --------------------------------------
type DataContentType = { type DataContentType = {
@@ -44,6 +52,24 @@ type DataContentType = {
}; };
}; };
type ClaimSubmission = {
id: number;
personID: string;
personName: string;
typePatient: string;
limit: {
current: number;
total: number;
percentage: number;
};
avatar: {
url: string;
};
fileRealInvoice: any[];
anotherDocument: any[];
laboratoryResult: any[];
};
type MuiDialogProps = { type MuiDialogProps = {
title?: { title?: {
name?: string; name?: string;
@@ -69,188 +95,435 @@ const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
})); }));
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
const steps = ['Review', 'Approval', 'Disbursement']; const steps = ['Review', 'Approval', 'Disbursement'];
const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => { const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => {
function clickHandler(arg0: string) {
throw new Error('Function not implemented.');
}
const navigate = useNavigate(); const navigate = useNavigate();
const [serviceCode, setServiceCode] = useState('IP'); const { enqueueSnackbar } = useSnackbar();
// const getContent = () => ( const [submitLoading, setSubmitLoading] = useState(false);
const selectedData = useSelector((state: RootState) => state.claims.data);
const [dataContent, setDataContent] = useState<ClaimSubmission[]>([]);
// ); useEffect(() => {
if (selectedData.length > 0) {
let temp: ClaimSubmission[] = selectedData.map((item) => ({
id: item.id,
avatar: {
url: '',
},
limit: item.limit,
personID: item.memberId,
personName: item.fullName,
typePatient: 'IP',
anotherDocument: [],
fileRealInvoice: [],
laboratoryResult: [],
}));
setDataContent(temp);
} else {
navigate('/claim-submit', { replace: true });
}
}, [selectedData]);
const handleServiceCode = (data: ClaimSubmission, index?: number) => {
let temp = dataContent.map((item) => {
if (item.personID === data.personID) {
return {
...item,
typePatient: item.typePatient === 'IP' ? 'OP' : 'IP',
};
} else {
return item;
}
});
setDataContent(temp);
};
const handleInputFile = (
event: any,
data: ClaimSubmission,
typeFile: 'invoice' | 'another' | 'lab'
) => {
if (event.target.files[0]) {
let temp = dataContent.map((item) => {
if (item.personID === data.personID) {
if (typeFile === 'invoice') {
return {
...item,
fileRealInvoice: [...item.fileRealInvoice, event.target.files[0]],
};
} else if (typeFile === 'another') {
return {
...item,
anotherDocument: [...item.anotherDocument, event.target.files[0]],
};
} else {
return {
...item,
laboratoryResult: [...item.laboratoryResult, event.target.files[0]],
};
}
} else {
return item;
}
});
setDataContent(temp);
} else {
console.log('NO FILE');
}
};
const handleRemoveFile = (
data: ClaimSubmission,
typeFile: 'invoice' | 'another' | 'lab',
index: number
) => {
let temp = dataContent.map((item) => {
if (item.personID === data.personID) {
if (typeFile === 'invoice') {
return {
...item,
fileRealInvoice: item.fileRealInvoice.filter((file, fileIndex) => fileIndex != index),
};
} else if (typeFile === 'another') {
return {
...item,
anotherDocument: item.anotherDocument.filter((file, fileIndex) => fileIndex != index),
};
} else {
return {
...item,
laboratoryResult: item.laboratoryResult.filter((file, fileIndex) => fileIndex != index),
};
}
} else {
return item;
}
});
setDataContent(temp);
};
const onSubmit = () => {
setSubmitLoading(true);
const mapArrayToFormData = (claims: ClaimSubmission[]): FormData => {
const formData = new FormData();
claims.forEach((claim, index) => {
formData.append(`member_id[${index}]`, claim.id.toString());
formData.append(`service_code[${index}]`, claim.typePatient);
claim.laboratoryResult.forEach((file, fileIndex) => {
formData.append(`laboratorium[${index}][${fileIndex}]`, file);
});
claim.anotherDocument.forEach((file, fileIndex) => {
formData.append(`prescription[${index}][${fileIndex}]`, file);
});
claim.fileRealInvoice.forEach((file, fileIndex) => {
formData.append(`invoice[${index}][${fileIndex}]`, file);
});
});
return formData;
};
const formData = mapArrayToFormData(dataContent);
axiosInstance
.post('/claim-requests', formData)
.then((response) => {
enqueueSnackbar(response.data.message ?? 'Berhasil membuat data', { variant: 'success' });
navigate('/claim-submit', { replace: true });
})
.catch(({ response }) => {
enqueueSnackbar(response.data.message ?? 'Something Went Wrong', { variant: 'error' });
})
.finally(() => {
setSubmitLoading(false);
});
};
return ( return (
<> <>
<Grid container> <Grid container spacing={8}>
{/* Field 1 */} {/* Field 1 */}
<Grid item xs={12} paddingX="24px" paddingY="20px"> <Grid item xs={12} paddingX="24px" paddingY="20px">
<Stack direction="row" alignItems="center"> <Stack direction="row" alignItems="center">
<ArrowBackIosIcon onClick={() => navigate(`/corporate`)} sx={{ cursor: "pointer" }} /> <ArrowBackIosIcon
<Typography variant="h5" sx={{ flexGrow: 1 }}>Claim Submission </Typography> onClick={() => navigate(`/claim-submit`)}
<Typography variant="inherit" sx={{ textAlign: "center", flexBasis: "15%" }}>Submission Date </Typography> sx={{ cursor: 'pointer' }}
<Typography textAlign={'right'} variant="h6" sx={{ textAlign: "right" }}> />
<Typography variant="h5" sx={{ flexGrow: 1 }}>
Claim Submission{' '}
</Typography>
<Typography variant="inherit" sx={{ textAlign: 'center', flexBasis: '15%' }}>
Submission Date{' '}
</Typography>
<Typography textAlign={'right'} variant="h6" sx={{ textAlign: 'right' }}>
{fPostFormat(new Date(), 'dd MMM yyyy')} {fPostFormat(new Date(), 'dd MMM yyyy')}
</Typography> </Typography>
</Stack> </Stack>
</Grid> </Grid>
<Grid item xs={12} paddingX="24px" paddingY="20px"> {dataContent.map((row, index) => {
<Stack direction="row" spacing={4}> return (
<Button <Grid item xs={12} key={index}>
sx={{ padding: 2, width: '50%', border: serviceCode === 'OP' ? '1px solid #919EAB52' : '1px solid #19BBBB' }} <Card sx={{ p: 3 }}>
variant={serviceCode == 'IP' ? 'outlined' : ''} <Grid container spacing={4} key={index}>
onClick={() => { <Grid item xs={12} paddingX="24px" paddingY="20px">
setServiceCode('IP'); <Stack direction="row" spacing={4}>
}} <Button
> sx={{
Inpatient padding: 2,
</Button> width: '50%',
<Button border:
sx={{ padding: 2, width: '50%',border: serviceCode === 'IP' ? '1px solid #919EAB52' : '1px solid #19BBBB' }} row.typePatient === 'OP' ? '1px solid #919EAB52' : '1px solid #19BBBB',
variant={serviceCode == 'OP' ? 'outlined' : ''} }}
onClick={() => { variant="outlined"
setServiceCode('OP'); color={row.typePatient === 'IP' ? 'primary' : 'inherit'}
}} onClick={() => {
> handleServiceCode(row);
Outpatient }}
</Button> >
</Stack> Inpatient
</Grid> </Button>
<Grid item xs={12}> <Button
<Card sx={{ p: 2, marginBottom: 2 }}> sx={{
<Stack direction="row" alignContent={'center'}> padding: 2,
<Avatar width: '50%',
src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg" border:
alt={'test'} row.typePatient === 'IP' ? '1px solid #919EAB52' : '1px solid #19BBBB',
sx={{ margin: 1, width: 56, height: 56 }} }}
/> variant="outlined"
<Stack sx={{ p: 1 }}> color={row.typePatient === 'OP' ? 'primary' : 'inherit'}
<Typography variant='h5'>{'Alexandra Rhea Putranto'}</Typography> onClick={() => {
<Typography variant='subtitle1' color={'#637381'}>{'KM002-01'}</Typography> handleServiceCode(row);
</Stack> }}
<Stack sx={{ p: 1 }}> >
<Typography variant="body1" sx={{ marginBottom: 1, fontWeight: 600 }}> Outpatient
Total Limit </Button>
</Typography> </Stack>
<BorderLinearProgress variant="determinate" value={80} /> </Grid>
<Typography sx={{ textAlign: 'right', marginTop: 1 }}> <Grid item xs={12}>
{fCurrency(8000000)} / {fCurrency(100000)} <Card sx={{ p: 2 }}>
</Typography> <Stack direction="row" alignContent={'center'}>
</Stack> <Avatar
</Stack> src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg"
</Card> alt={'test'}
</Grid> sx={{ margin: 1, width: 56, height: 56 }}
/>
<Stack sx={{ p: 1 }}>
<Typography variant="h5">{row.personName}</Typography>
<Typography variant="subtitle1" color="#637381">
{row.personID}
</Typography>
</Stack>
<Stack sx={{ p: 1 }}>
<Typography variant="body1" sx={{ marginBottom: 1, fontWeight: 600 }}>
Total Limit
</Typography>
<BorderLinearProgress
variant="determinate"
value={row.limit && row.limit.percentage}
sx={{ mb: 1 }}
/>
<Typography sx={{ textAlign: 'right', marginTop: 1 }}>
{fCurrency(8000000)} / {fCurrency(100000)}
</Typography>
</Stack>
</Stack>
</Card>
</Grid>
{/* REAL INVOICE */}
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="h6">Real Invoice</Typography>
</Grid>
{row.fileRealInvoice &&
row.fileRealInvoice.map((file, fileIndex) => (
<Grid item xs={12} key={fileIndex}>
<Stack direction="row" justifyContent={'space-between'}>
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
<Iconify
icon="eva:trash-2-outline"
color={'darkred'}
onClick={() => {
handleRemoveFile(row, 'invoice', fileIndex);
}}
/>
</Stack>
</Grid>
))}
<Grid item xs={12}>
<Box
sx={{
display: 'flex',
placeContent: 'center',
placeItems: 'center',
border: '2px dashed #F9FAFB',
bgcolor: '#919EAB52',
borderRadius: '8px',
p: 0,
}}
>
<Buttons handle={handleInputFile} row={row} type="invoice" />
</Box>
</Grid>
</Grid>
</Grid>
{/* DOCTOR'S PRESCRIPTION AND ANOTHER DOCUMENTS */}
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="h6">
Doctor's Prescription and Another Documents
</Typography>
</Grid>
{row.anotherDocument &&
row.anotherDocument.map((file, fileIndex) => (
<Grid item xs={12} key={fileIndex}>
<Stack direction="row" justifyContent={'space-between'}>
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
<Iconify
icon="eva:trash-2-outline"
color={'darkred'}
onClick={() => {
handleRemoveFile(row, 'another', fileIndex);
}}
/>
</Stack>
</Grid>
))}
<Grid item xs={12}>
<Box
sx={{
display: 'flex',
placeContent: 'center',
placeItems: 'center',
border: '2px dashed #F9FAFB',
bgcolor: '#919EAB52',
borderRadius: '8px',
p: 0,
}}
>
<Buttons handle={handleInputFile} row={row} type="another" />
</Box>
</Grid>
</Grid>
</Grid>
{/* LABORATORY RESULTS */}
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="h6">Laboraroty Results</Typography>
</Grid>
{row.laboratoryResult &&
row.laboratoryResult.map((file, fileIndex) => (
<Grid item xs={12} key={fileIndex}>
<Stack direction="row" justifyContent={'space-between'}>
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
<Iconify
icon="eva:trash-2-outline"
color={'darkred'}
onClick={() => {
handleRemoveFile(row, 'lab', fileIndex);
}}
/>
</Stack>
</Grid>
))}
</Grid>
<Grid item xs={12}>
<Box
sx={{
display: 'flex',
placeContent: 'center',
placeItems: 'center',
border: '2px dashed #F9FAFB',
bgcolor: '#919EAB52',
borderRadius: '8px',
p: 0,
}}
>
<Buttons handle={handleInputFile} row={row} type="lab" />
</Box>
</Grid>
</Grid>
</Grid>
</Card>
</Grid>
);
})}
<Grid item xs={12}>
<LoadingButton
variant="contained"
sx={{ marginTop: 2, p: 2, margin: '10px' }}
fullWidth
onClick={onSubmit}
loading={submitLoading}
>
Claim Submit
</LoadingButton>
</Grid>
</Grid> </Grid>
<Stack marginTop={2}>
<Typography variant="subtitle1" paddingY={2}>
17 Mei 2022
</Typography>
</Stack>
<Stack direction="row" spacing={2}>
<Divider orientation="vertical" flexItem sx={{ borderStyle: 'dashed' }} />
<Stack spacing={2} sx={{ flex: 1, maxWidth: '100%' }}>
{/* Item 1 */}
<Card sx={{ paddingY: 2, paddingX: 3 }}>
<Stack direction="row" justifyContent="space-between" alignItems="center">
<Typography variant="body1">09:10 WIB</Typography>
<Typography
sx={{
backgroundColor: palette.light.warning.lighter,
color: palette.light.warning.dark,
borderColor: palette.light.warning.dark,
border: '1px solid',
borderRadius: '6px',
padding: 1,
}}
variant="caption"
>
Approval
</Typography>
</Stack>
<Divider sx={{ marginY: 2 }} />
<Stack>
<Typography variant="subtitle2" color="#404040">
Details : mohon melengkapi kekurangan dokumen
</Typography>
<Typography variant="caption" color="#757575" sx={{ marginTop: 2, marginBottom: 1 }}>
Lab pemeriksaan darah
</Typography>
<Button
variant="outlined"
startIcon={<Add />}
fullWidth
sx={{ typography: 'subtitle2', borderColor: '#F5F5F5' }}
// onClick={() => clickHandler('topUpLimit')}
>
Hasil Pemeriksaan Laboratorium
</Button>
</Stack>
</Card>
{/* Item 2 */}
<Card sx={{ flex: 1, maxWidth: '100%', paddingY: 2, paddingX: 3 }}>
<Stack direction="row" justifyContent="space-between" alignItems="center">
<Typography variant="body1">09:00 WIB</Typography>
<Typography
sx={{
backgroundColor: palette.light.warning.lighter,
color: palette.light.warning.dark,
borderColor: palette.light.warning.dark,
border: '1px solid',
borderRadius: '6px',
padding: 1,
}}
variant="caption"
>
Approval
</Typography>
</Stack>
<Divider sx={{ marginY: 2 }} />
<Stack>
<Typography variant="subtitle2" color="#404040">
Details : Penilaian Dokter
</Typography>
</Stack>
</Card>
{/* Item 3 */}
<Card sx={{ flex: 1, maxWidth: '100%', paddingY: 2, paddingX: 3 }}>
<Stack direction="row" justifyContent="space-between" alignItems="center">
<Typography variant="body1">08:00 WIB</Typography>
<Typography
sx={{
backgroundColor: '#F5F5F5',
color: '#757575',
borderColor: '#757575',
border: '1px solid',
borderRadius: '6px',
padding: 1,
}}
variant="caption"
>
Review
</Typography>
</Stack>
<Divider sx={{ marginY: 2 }} />
<Stack>
<Typography variant="subtitle2" color="#404040">
Details : Klaim Diajukan
</Typography>
</Stack>
</Card>
</Stack>
</Stack>
</> </>
// <MuiDialog
// title={title}
// openDialog={openDialog}
// setOpenDialog={setOpenDialog}
// content={getContent()}
// />
); );
}; };
// let temp = [
// {
// member: "",
// result_file: [
// "file.pdf",
// "file2.pdf"
// ]
// }
// ]
export default DialogDetailClaim; export default DialogDetailClaim;
type ButtonIProp = {
row: ClaimSubmission;
type: 'invoice' | 'another' | 'lab';
handle: (event: any, row: any, type: any) => void;
};
const Buttons = ({ handle, row, type }: ButtonIProp) => {
const ref = useRef<HTMLInputElement>(null);
return (
<ButtonBase sx={{ p: 4 }} onClick={() => ref.current?.click()}>
<Box
sx={{
display: 'flex',
placeItems: 'center',
gap: 1,
placeContent: 'center',
}}
>
<Iconify icon="icon-park-outline:upload-one" fontSize="3em" />
<Typography variant="body1" fontWeight="bold">
Add Invoice
</Typography>
</Box>
<input
ref={ref}
hidden
accept="application/pdf"
type="file"
name="file"
multiple
onChange={(event) => handle(event, row, type)}
/>
</ButtonBase>
);
};

View File

@@ -106,7 +106,6 @@ export default function List() {
handleSearchSubmit: handleSearchSubmit, handleSearchSubmit: handleSearchSubmit,
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/*-------------------------------- handlle checkbox ------------------------ */ /*-------------------------------- handlle checkbox ------------------------ */
const handleCheckboxChange = async (event: React.FormEvent<HTMLFormElement>) => { const handleCheckboxChange = async (event: React.FormEvent<HTMLFormElement>) => {
@@ -122,18 +121,11 @@ export default function List() {
} }
}; };
/* -------------------------------- headCell -------------------------------- */ /* -------------------------------- headCell -------------------------------- */
return ( return (
<Stack> <Stack>
<CardClaimSubmit <CardClaimSubmit rows={data} loadings={loadings} params={params} searchs={searchs} />
rows={data}
loadings={loadings}
params={params}
searchs={searchs}
/>
</Stack> </Stack>
); );
} }

View File

@@ -250,24 +250,24 @@ export default function List() {
{ {
id: 'start_date', id: 'start_date',
align: 'left', align: 'center',
label: 'Start Date', label: 'Start Date',
isSort: true, isSort: true,
}, },
{ {
id: 'end_date', id: 'end_date',
align: 'left', align: 'center',
label: 'End Date', label: 'End Date',
isSort: true, isSort: true,
}, },
{ {
id: 'status', id: 'status',
align: 'left', align: 'center',
label: 'Status', label: 'Status',
isSort: true, isSort: true,
}, },
{ {
id: 'view', id: 'action',
align: 'center', align: 'center',
label: '', label: '',
isSort: true, isSort: true,
@@ -289,9 +289,7 @@ export default function List() {
const response = await axios.get(`${corporateValue}/members?type=employee-data`, { const response = await axios.get(`${corporateValue}/members?type=employee-data`, {
params: { ...parameters }, params: { ...parameters },
}); });
console.log(response.data.data);
setData( setData(
response.data.data.map((obj: any) => { response.data.data.map((obj: any) => {
return { return {
@@ -303,34 +301,48 @@ export default function List() {
// , // ,
status: status:
obj.status === 1 ? ( obj.status === 1 ? (
<Button <Typography
variant="outlined" variant="body2"
color="success" sx={{
size="small" width: 'Hug (6px)',
sx={{cursor:'default'}} height: 'Hug (22px)',
left: '862px',
top: '17px',
color: '#229A16',
backgroundColor: '#54D62C29',
padding: '1px, 8px',
borderRadius: '6px',
}}
> >
Active Active
</Button> </Typography>
) : ( ) : (
<Button <Typography
variant="outlined" variant="body2"
color="error" sx={{
size="small" width: 'Hug (6px)',
sx={{cursor:'default'}} height: 'Hug (22px)',
left: '862px',
top: '17px',
color: '#B72136',
backgroundColor: '#FF484229',
padding: '1px, 8px',
borderRadius: '6px',
}}
> >
Inactive Inactive
</Button> </Typography>
), ),
start_date: start_date:
<Typography <Typography
sx={{ sx={{
backgroundColor: (theme) => theme.palette.grey[300], backgroundColor: (theme) => theme.palette.grey[300],
borderRadius: '4px', borderRadius: '4px',
width: '95%', width: '70%',
}} }}
variant="body2" variant="body2"
> >
{obj.start_date ? format(new Date(obj.start_date), "dd MMMM yyyy HH:mm:ss") : ''} {obj.start_date ? format(new Date(obj.start_date), "dd MMM yyyy") : ''}
</Typography> </Typography>
, ,
end_date: end_date:
@@ -338,11 +350,11 @@ export default function List() {
sx={{ sx={{
backgroundColor: (theme) => theme.palette.grey[300], backgroundColor: (theme) => theme.palette.grey[300],
borderRadius: '4px', borderRadius: '4px',
width: '95%', width: '70%',
}} }}
variant="body2" variant="body2"
> >
{obj.end_date ? format(new Date(obj.end_date), "d MMMM yyyy HH:mm:ss") : ''} {obj.end_date ? format(new Date(obj.end_date), "d MMM yyyy") : ''}
</Typography> </Typography>
, ,
fullName: fullName:
@@ -359,7 +371,7 @@ export default function List() {
{obj.memberId} {obj.memberId}
</Typography> </Typography>
, ,
view: action:
<TableMoreMenu actions={ <TableMoreMenu actions={
<> <>
<MenuItem onClick={() => navigate ('/employee-data/user-profile/'+obj.personId)}> <MenuItem onClick={() => navigate ('/employee-data/user-profile/'+obj.personId)}>

View File

@@ -39,13 +39,13 @@ const defaultData = [
export default function CardClaimStatus({ data }: PropsCardClaimStatus) { export default function CardClaimStatus({ data }: PropsCardClaimStatus) {
return ( return (
<RootStyle> <RootStyle>
<Stack sx={{ mb: 1 }}> {/*<Stack sx={{ mb: 1 }}>
<Typography variant="body2">Claim Status</Typography> <Typography variant="body2">Claim Status</Typography>
</Stack> </Stack>*/}
<Grid container spacing={2}> <Grid container spacing={2}>
{data {data
? data.map(({ name, value, color }: ClaimStatusType, key) => ( ? data.map(({ name, value, color }: ClaimStatusType, key) => (
<Grid item key={key} xs={6} sm={4}> <Grid item key={key} xs={12} sm={3}>
<Card <Card
sx={{ sx={{
paddingX: 1, paddingX: 1,
@@ -71,7 +71,7 @@ export default function CardClaimStatus({ data }: PropsCardClaimStatus) {
</Grid> </Grid>
)) ))
: defaultData.map(({ name, value, color }: ClaimStatusType, key) => ( : defaultData.map(({ name, value, color }: ClaimStatusType, key) => (
<Grid item key={key} xs={6} sm={4}> <Grid item key={key} xs={12} sm={3}>
<Card <Card
sx={{ sx={{
paddingX: 1, paddingX: 1,

View File

@@ -26,6 +26,9 @@ import { useSearchParams, useNavigate, Link } from 'react-router-dom';
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
import { fSplit } from '../../utils/formatNumber'; import { fSplit } from '../../utils/formatNumber';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '../../store';
import { claimSubmitAction, claimSubmitType } from '../../store/claimSubmit';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@@ -80,6 +83,10 @@ export default function DialogClaimSubmitMember({
/* ---------------------------------- data ---------------------------------- */ /* ---------------------------------- data ---------------------------------- */
const [data, setData] = useState([]); const [data, setData] = useState([]);
const dispatch = useDispatch();
const selectedData = useSelector((state: RootState) => state.claims.data);
const [dataMemberClaim, setDataMemberClaim] = useState<DataContentType>({ const [dataMemberClaim, setDataMemberClaim] = useState<DataContentType>({
id: 0, id: 0,
fullName: '', fullName: '',
@@ -108,7 +115,6 @@ export default function DialogClaimSubmitMember({
}; };
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* ------------------------------ Icon On Click ----------------------------- */ /* ------------------------------ Icon On Click ----------------------------- */
const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => { const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => {
setDataMemberClaim({ setDataMemberClaim({
@@ -126,6 +132,15 @@ export default function DialogClaimSubmitMember({
}, },
}); });
}; };
const handleCheck = (data: DataContentType, isChecked: boolean) => {
if (isChecked) {
dispatch(claimSubmitAction.patch([...selectedData, data]));
} else {
let temp = selectedData.filter((row) => row.memberId !== data.memberId);
dispatch(claimSubmitAction.patch(temp));
}
};
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
useEffect(() => { useEffect(() => {
@@ -140,6 +155,10 @@ export default function DialogClaimSubmitMember({
})(); })();
}, [corporateValue, openDialog, appliedParams]); }, [corporateValue, openDialog, appliedParams]);
useEffect(() => {
dispatch(claimSubmitAction.dispatch());
}, [dispatch]);
const getContent = () => ( const getContent = () => (
<Stack> <Stack>
<Stack marginTop={2} spacing={1}> <Stack marginTop={2} spacing={1}>
@@ -147,47 +166,54 @@ export default function DialogClaimSubmitMember({
<Card <Card
key={key} key={key}
sx={{ paddingY: 1, paddingX: 2 }} sx={{ paddingY: 1, paddingX: 2 }}
onClick={() => // onClick={() =>
clickHandler({ // clickHandler({
id: row.id, // id: row.id,
fullName: row.fullName, // fullName: row.fullName,
memberId: row.memberId, // memberId: row.memberId,
limit: { // limit: {
current: row.limit.current, // current: row.limit.current,
total: row.limit.total, // total: row.limit.total,
percentage: row.limit.percentage, // percentage: row.limit.percentage,
}, // },
}) // })
} // }
> >
<Stack direction="row" alignItems="center" > <Stack direction="row" alignItems="center">
<Grid item xs={1} lg={1} xl={1} > <Grid item xs={1} lg={1} xl={1}>
<form> <form>
<FormControlLabel <FormControlLabel
value="end" value="end"
control={<Checkbox />} control={<Checkbox onChange={(e) => handleCheck(row, e.target.checked)} />}
label="" label=""
labelPlacement="end" labelPlacement="end"
sx={{marginLeft: '20px'}} sx={{ marginLeft: '20px' }}
/> />
</form> </form>
</Grid> </Grid>
<div style={{ position: 'relative', flex: 'none', height: 'fit-content', margin: '15px'}}> <div
<img style={{
width={52} position: 'relative',
height={52} flex: 'none',
src="/images/user-profile.png" height: 'fit-content',
alt="user-profile" margin: '15px',
style={{ borderRadius: '50%' }} }}
/> >
</div> <img
<Grid item xs={7} lg={7} xl={7} > width={52}
height={52}
src="/images/user-profile.png"
alt="user-profile"
style={{ borderRadius: '50%' }}
/>
</div>
<Grid item xs={7} lg={7} xl={7}>
<Typography variant="subtitle1">{row.fullName}</Typography> <Typography variant="subtitle1">{row.fullName}</Typography>
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}> <Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
{row.memberId} {row.memberId}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={3} lg={3} xl={3} > <Grid item xs={3} lg={3} xl={3}>
<BorderLinearProgress <BorderLinearProgress
variant="determinate" variant="determinate"
value={row.limit && row.limit.percentage} value={row.limit && row.limit.percentage}
@@ -196,27 +222,40 @@ export default function DialogClaimSubmitMember({
/> />
<Stack direction={'row'}> <Stack direction={'row'}>
<Grid item xs={3}> <Grid item xs={3}>
<Typography variant='overline' sx={{textAlign:'left'}}> <Typography variant="overline" sx={{ textAlign: 'left' }}>
LIMIT LIMIT
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={7} sx={{ display: 'flex', justifyContent: 'flex-end' }}> <Grid item xs={7} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Stack direction={'row'}> <Stack direction={'row'}>
<Typography variant='overline'> <Typography variant="overline">
{fSplit(row.limit && row.limit.current)} {fSplit(row.limit && row.limit.current)}
</Typography> </Typography>
<Typography variant='overline'> <Typography variant="overline">
/ {fSplit(row.limit && row.limit.total)} / {fSplit(row.limit && row.limit.total)}
</Typography> </Typography>
</Stack> </Stack>
</Grid> </Grid>
</Stack> </Stack>
</Grid> </Grid>
<Grid item xs={2} lg={2} xl={2} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}> <Grid
<IconButton > item
xs={2}
lg={2}
xl={2}
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
>
<IconButton>
<Iconify icon="ic:history" /> <Iconify icon="ic:history" />
</IconButton> </IconButton>
<IconButton sx={{marginLeft: '10px'}} onClick={() => navigate(`/claim-request/${row.id}`)} > <IconButton
disabled={selectedData.length > 0}
sx={{ marginLeft: '10px' }}
onClick={() => {
dispatch(claimSubmitAction.patch([row]));
navigate(`/claim-request/${row.id}`);
}}
>
<Iconify icon="ic:round-chevron-right" /> <Iconify icon="ic:round-chevron-right" />
</IconButton> </IconButton>
</Grid> </Grid>
@@ -225,7 +264,6 @@ export default function DialogClaimSubmitMember({
))} ))}
</Stack> </Stack>
</Stack> </Stack>
); );
return ( return (
@@ -254,13 +292,15 @@ export default function DialogClaimSubmitMember({
<Grid item xs={12}> <Grid item xs={12}>
<LoadingButton <LoadingButton
variant="contained" variant="contained"
sx={{ marginTop: 2, p: 2, margin: '10px', color:'#212B36', backgroundColor:'#DFE3E8' }} // sx={{ marginTop: 2, p: 2, margin: '10px', color: '#212B36', backgroundColor: '#DFE3E8' }}
sx={{ marginTop: 2, p: 2, margin: '10px' }}
fullWidth fullWidth
disabled={selectedData.length === 0}
onClick={() => navigate('/claim-request/bulk')}
> >
Claim Submit Selected Claim Submit Selected
</LoadingButton> </LoadingButton>
</Grid> </Grid>
</Grid> </Grid>
) );
} }

View File

@@ -0,0 +1,37 @@
import { createSlice } from '@reduxjs/toolkit';
export type claimSubmitType = {
id: number;
fullName: string;
memberId: string;
limit: {
current: number;
total: number;
percentage: number;
};
};
type initState = {
data: claimSubmitType[];
};
let initState: initState = {
data: [],
};
const claimSubmitSlice = createSlice({
name: 'claimsubmit',
initialState: initState,
reducers: {
patch(state, action) {
state.data = action.payload;
},
dispatch(state) {
state.data = [];
},
},
});
export const claimSubmitAction = claimSubmitSlice.actions;
export default claimSubmitSlice.reducer;

View File

@@ -0,0 +1,12 @@
import { configureStore } from '@reduxjs/toolkit';
import claimSubmit from './claimSubmit';
const store = configureStore({
reducer: {
claims: claimSubmit,
},
});
export type RootState = ReturnType<typeof store.getState>;
export default store;

View File

@@ -51,6 +51,7 @@
"@mui/system": "^5.14.6", "@mui/system": "^5.14.6",
"@mui/x-data-grid": "^5.17.26", "@mui/x-data-grid": "^5.17.26",
"@mui/x-date-pickers": "5.0.0-beta.2", "@mui/x-date-pickers": "5.0.0-beta.2",
"@reduxjs/toolkit": "^1.9.6",
"@vitejs/plugin-react": "^1.3.2", "@vitejs/plugin-react": "^1.3.2",
"apexcharts": "^3.42.0", "apexcharts": "^3.42.0",
"axios": "^0.27.2", "axios": "^0.27.2",
@@ -76,6 +77,7 @@
"react-intersection-observer": "^8.34.0", "react-intersection-observer": "^8.34.0",
"react-lazy-load-image-component": "^1.6.0", "react-lazy-load-image-component": "^1.6.0",
"react-quill": "2.0.0-beta.4", "react-quill": "2.0.0-beta.4",
"react-redux": "^8.1.2",
"react-router": "^6.15.0", "react-router": "^6.15.0",
"react-router-dom": "^6.15.0", "react-router-dom": "^6.15.0",
"simplebar": "^5.3.9", "simplebar": "^5.3.9",