diff --git a/Modules/Client/Http/Controllers/Api/ClaimReportController.php b/Modules/Client/Http/Controllers/Api/ClaimReportController.php
index b3edd3a6..b83234ad 100644
--- a/Modules/Client/Http/Controllers/Api/ClaimReportController.php
+++ b/Modules/Client/Http/Controllers/Api/ClaimReportController.php
@@ -25,6 +25,7 @@ class ClaimReportController extends Controller
$corporateEmployee->where('corporate_id', $corporateId);
});
})
+ ->whereHas('claim', fn ($query) => $query->where('status', 'approved'))
->where('status', 'approved')
->get();
@@ -38,10 +39,21 @@ class ClaimReportController extends Controller
->where('status', 'approved')
->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([
'requesteds' => count($requesteds),
'approveds' => count($approveds),
- 'rejecteds' => count($rejecteds)
+ 'rejecteds' => count($rejecteds),
+ 'disbrusments' => count($disbrusments)
]);
}
diff --git a/Modules/Client/Http/Controllers/Api/ClaimRequestController.php b/Modules/Client/Http/Controllers/Api/ClaimRequestController.php
index 9d194472..637ea2b4 100644
--- a/Modules/Client/Http/Controllers/Api/ClaimRequestController.php
+++ b/Modules/Client/Http/Controllers/Api/ClaimRequestController.php
@@ -62,8 +62,8 @@ class ClaimRequestController extends Controller
'system_origin' => 'client-portal'
]);
- if ($request->hasFile('result_files')) {
- foreach ($request->result_files[$key] as $file) {
+ if ($request->hasFile('laboratorium')) {
+ foreach ($request->laboratorium[$key] as $file) {
$pathFile = File::storeFile('claim-result', $newClaimRequest->id, $file);
$newClaimRequest->files()->updateOrCreate([
'type' => 'claim-result',
@@ -77,8 +77,8 @@ class ClaimRequestController extends Controller
}
}
- if ($request->hasFile('diagnosa_files')) {
- foreach ($request->diagnosa_files[$key] as $file) {
+ if ($request->hasFile('prescription')) {
+ foreach ($request->prescription[$key] as $file) {
$pathFile = File::storeFile('claim-diagnosis', $newClaimRequest->id, $file);
$newClaimRequest->files()->updateOrCreate([
'type' => 'claim-diagnosis',
@@ -92,8 +92,8 @@ class ClaimRequestController extends Controller
}
}
- if ($request->hasFile('kondisi_files')) {
- foreach ($request->kondisi_files[$key] as $file) {
+ if ($request->hasFile('invoice')) {
+ foreach ($request->invoice[$key] as $file) {
$pathFile = File::storeFile('claim-kondisi', $newClaimRequest->id, $file);
$newClaimRequest->files()->updateOrCreate([
'type' => 'claim-kondisi',
diff --git a/Modules/Client/Http/Controllers/Api/CorporateMemberController.php b/Modules/Client/Http/Controllers/Api/CorporateMemberController.php
index 05032d18..58266885 100644
--- a/Modules/Client/Http/Controllers/Api/CorporateMemberController.php
+++ b/Modules/Client/Http/Controllers/Api/CorporateMemberController.php
@@ -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 DashboardMemberResources;
use Modules\Client\Transformers\Dashboard\MemberAlarmCenterResources as DashboardMemberAlarmResources;
+use Modules\Client\Transformers\Dashboard\MemberEmployeeDataResources as DashboardMemberEmployeeDataResources;
use Modules\Client\Transformers\DataMemberResource;
use Illuminate\Support\Facades\DB;
@@ -29,8 +30,8 @@ class CorporateMemberController extends Controller
{
switch ($request->input('type')) {
case 'employee-data':
- $members = $this->corporateMemberService->getAllMemberAlarmCenter($corporate_id, $request);
- return response()->json(Helper::paginateResources(DashboardMemberAlarmResources::collection($members)));
+ $members = $this->corporateMemberService->getAllMemberEmployeeData($corporate_id, $request);
+ return response()->json(Helper::paginateResources(DashboardMemberEmployeeDataResources::collection($members)));
case 'claim-report':
$members = $this->corporateMemberService->getAllMemberClaimReports($corporate_id, $request);
return response()->json(Helper::paginateResources(ClaimReportMemberResources::collection($members)));
diff --git a/Modules/Client/Transformers/ClaimReport/MemberResources.php b/Modules/Client/Transformers/ClaimReport/MemberResources.php
index a798dfcf..18f5e077 100644
--- a/Modules/Client/Transformers/ClaimReport/MemberResources.php
+++ b/Modules/Client/Transformers/ClaimReport/MemberResources.php
@@ -16,13 +16,13 @@ class MemberResources extends JsonResource
{
return [
'id' => $this->id,
- 'codeRequest' => $this->code,
- 'memberId' => $this->member_id,
- 'fullName' => $this->full_name,
- 'division' => $this->division_name ?? '',
+ 'code' => $this->code,
+ 'member_id' => $this->member_id,
+ 'full_name' => $this->full_name,
+ 'division_name' => $this->division_name ?? '',
'status' => $this->status,
'claimRequestId' => $this->claim_request_id,
- 'submissionDate' => $this->submission_date,
+ 'submission_date' => $this->submission_date,
];
}
}
diff --git a/Modules/Client/Transformers/Dashboard/MemberEmployeeDataResources.php b/Modules/Client/Transformers/Dashboard/MemberEmployeeDataResources.php
new file mode 100644
index 00000000..23d66c0e
--- /dev/null
+++ b/Modules/Client/Transformers/Dashboard/MemberEmployeeDataResources.php
@@ -0,0 +1,27 @@
+ $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,
+ ];
+ }
+}
diff --git a/app/Services/CorporateMemberService.php b/app/Services/CorporateMemberService.php
index 8eb40c0a..3a6192df 100644
--- a/app/Services/CorporateMemberService.php
+++ b/app/Services/CorporateMemberService.php
@@ -6,6 +6,7 @@ use App\Models\Member;
use App\Models\Encounter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
class CorporateMemberService
{
@@ -47,42 +48,43 @@ class CorporateMemberService
{
$limit = $request->has('perPage') ? $request->input('perPage') : 10;
- return Member::query()
- ->joinClaimRequests('right')
- ->joinCorporateEmployees('left')
- ->joinCorporateDivisions('left')
- ->with('person:id,name_prefix,name_suffix,gender,name,birth_date')
- ->withSum('claims', 'total_claim')
- ->whereHas('employeds', function (Builder $corporateEmployee) use ($corporateId) {
- $corporateEmployee->where('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 $division, $value) {
- $division->whereHas('division', function (Builder $corporateEmployee) use ($value) {
- $corporateEmployee->where('division_id', $value);
- });
- })
- ->when($request->has('orderBy'), function (Builder $query) use ($request) {
- $orderBy = match ($request->orderBy) {
- 'memberId' => 'member_id',
- 'fullName' => 'name',
- 'codeRequest' => 'code',
- default => ''
- };
+ $results = DB::table('claim_requests')
+ ->leftJoin('claims', 'claim_requests.id', '=', 'claims.claim_request_id')
+ ->leftJoin('members', 'claim_requests.member_id', '=', 'members.id')
+ ->leftJoin('corporate_employees', 'members.id', '=', 'corporate_employees.member_id')
+ ->leftJoin('corporate_divisions', 'corporate_employees.division_id', '=', 'corporate_divisions.id')
+ ->where('corporate_employees.corporate_id', '=', $corporateId)
+ ->when($request->input('search'), function ($query, $search) {
+ $query->where(function ($query) use ($search) {
+ $query->orWhere('claim_requests.code', 'like', "%" . $search . "%")
+ ->orWhere('members.member_id', 'like', "%" . $search . "%")
+ ->orWhere('members.name', 'like', "%" . $search . "%")
+ ->orWhere('corporate_divisions.name', 'like', "%" . $search . "%")
+ ->orWhere('claim_requests.status', 'like', "%" . $search . "%")
+ ->orWhere('claim_requests.submission_date', 'like', "%" . $search . "%");
+ });
+ })
+ ->when($request->has('orderBy'), function ($query) use ($request) {
+ $orderBy = $request->orderBy;
+ $direction = $request->order ?? 'asc';
- if (in_array($orderBy, ['member_id', 'name', 'active', 'code'])) {
- $query->getQuery()->orderBy($orderBy, $request->order);
- } elseif ($request->orderBy === 'division') {
- $query->getQuery()->orderBy('corporate_divisions.name', $request->order);
- }
- })
- ->select(['members.id', 'members.person_id', 'members.member_id', 'members.name', 'corporate_divisions.name AS division_name', 'claim_requests.status', 'claim_requests.code', 'claim_requests.id AS claim_request_id','claim_requests.submission_date'])
- ->paginate($limit);
+ $query->orderBy($orderBy, $direction);
+ })
+ ->select('members.id', 'claim_requests.code','members.member_id', 'members.name as full_name', 'corporate_divisions.name AS division_name',
+ DB::raw('
+ CASE
+ WHEN claim_requests.status = "requested" THEN "requested"
+ WHEN claim_requests.status = "approved" AND claims.status = "approved" THEN "approved"
+ 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)
@@ -165,6 +167,44 @@ class CorporateMemberService
->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)
{
return Encounter::query()->select(['id'])->paginate(10);
diff --git a/frontend/client-portal/.env.development b/frontend/client-portal/.env.development
index 52e237c2..d7d23df0 100644
--- a/frontend/client-portal/.env.development
+++ b/frontend/client-portal/.env.development
@@ -2,6 +2,6 @@ GENERATE_SOURCEMAP=false
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"
diff --git a/frontend/client-portal/package.json b/frontend/client-portal/package.json
index 92b2650a..b9acad50 100644
--- a/frontend/client-portal/package.json
+++ b/frontend/client-portal/package.json
@@ -52,6 +52,7 @@
"@mui/utils": "^5.11.13",
"@mui/x-data-grid": "^5.17.26",
"@mui/x-date-pickers": "5.0.0-beta.2",
+ "@reduxjs/toolkit": "^1.9.7",
"@vitejs/plugin-react": "^1.3.2",
"apexcharts": "^3.37.2",
"axios": "^0.27.2",
@@ -78,6 +79,7 @@
"react-lazy-load-image-component": "^1.5.6",
"react-number-format": "^5.1.4",
"react-quill": "2.0.0-beta.4",
+ "react-redux": "^8.1.3",
"react-router": "^6.9.0",
"react-router-dom": "^6.9.0",
"simplebar": "^5.3.9",
diff --git a/frontend/client-portal/pnpm-lock.yaml b/frontend/client-portal/pnpm-lock.yaml
index 1df57c98..587278ef 100644
--- a/frontend/client-portal/pnpm-lock.yaml
+++ b/frontend/client-portal/pnpm-lock.yaml
@@ -47,6 +47,9 @@ dependencies:
'@mui/x-date-pickers':
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)
+ '@reduxjs/toolkit':
+ specifier: ^1.9.7
+ version: 1.9.7(react-redux@8.1.3)(react@17.0.2)
'@vitejs/plugin-react':
specifier: ^1.3.2
version: 1.3.2
@@ -125,6 +128,9 @@ dependencies:
react-quill:
specifier: 2.0.0-beta.4
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:
specifier: ^6.9.0
version: 6.9.0(react@17.0.2)
@@ -2336,6 +2342,25 @@ packages:
resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==}
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:
resolution: {integrity: sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==}
engines: {node: '>=14'}
@@ -2572,6 +2597,13 @@ packages:
'@types/range-parser': 1.2.4
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:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true
@@ -2619,7 +2651,6 @@ packages:
resolution: {integrity: sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==}
dependencies:
'@types/react': 17.0.53
- dev: true
/@types/react-is@17.0.3:
resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==}
@@ -2668,6 +2699,10 @@ packages:
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
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):
resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -4467,6 +4502,10 @@ packages:
engines: {node: '>= 4'}
dev: true
+ /immer@9.0.21:
+ resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
+ dev: false
+
/import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
@@ -5341,6 +5380,40 @@ packages:
react-dom: 17.0.2(react@17.0.2)
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:
resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==}
engines: {node: '>=0.10.0'}
@@ -5391,6 +5464,20 @@ packages:
object-assign: 4.1.1
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:
resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==}
engines: {node: '>=4'}
@@ -5447,6 +5534,10 @@ packages:
resolution: {integrity: sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==}
dev: false
+ /reselect@4.1.8:
+ resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==}
+ dev: false
+
/resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@@ -6009,6 +6100,14 @@ packages:
punycode: 2.3.0
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):
resolution: {integrity: sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==}
peerDependencies:
diff --git a/frontend/client-portal/src/App.tsx b/frontend/client-portal/src/App.tsx
index 8ff04cf4..38581096 100644
--- a/frontend/client-portal/src/App.tsx
+++ b/frontend/client-portal/src/App.tsx
@@ -9,27 +9,31 @@ import { ProgressBarStyle } from './components/ProgressBar';
import ThemeColorPresets from './components/ThemeColorPresets';
import MotionLazyContainer from './components/animate/MotionLazyContainer';
import { SnackbarProvider } from 'notistack';
+import { Provider } from 'react-redux';
+import store from './store';
// ----------------------------------------------------------------------
export default function App() {
return (
-
-
-
-
-
-
- {/* */}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+
+
+
+
+
);
}
diff --git a/frontend/client-portal/src/pages/ClaimReport/Index.tsx b/frontend/client-portal/src/pages/ClaimReport/Index.tsx
index fc83c0e9..053634e8 100644
--- a/frontend/client-portal/src/pages/ClaimReport/Index.tsx
+++ b/frontend/client-portal/src/pages/ClaimReport/Index.tsx
@@ -15,6 +15,7 @@ import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate
import List from './List';
// theme
import palette from '../../theme/palette';
+import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
interface ClaimStatusType {
name: string;
@@ -35,17 +36,22 @@ export default function Drugs() {
{
name: 'Requested',
value: claimStatus.data.data.requesteds,
- color: palette.dark.primary.dark,
+ color: '#159C9C',
},
{
name: 'Approval',
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,
- color: palette.dark.error.dark,
+ color: '#B72136',
},
]);
})();
@@ -54,6 +60,13 @@ export default function Drugs() {
return (
+
diff --git a/frontend/client-portal/src/pages/ClaimReport/List.tsx b/frontend/client-portal/src/pages/ClaimReport/List.tsx
index 5c86067e..03d3db7d 100644
--- a/frontend/client-portal/src/pages/ClaimReport/List.tsx
+++ b/frontend/client-portal/src/pages/ClaimReport/List.tsx
@@ -1,5 +1,5 @@
/* ---------------------------------- @mui ---------------------------------- */
-import { Stack, Button } from '@mui/material';
+import { Stack, Button, MenuItem } from '@mui/material';
/* ---------------------------------- axios --------------------------------- */
// import axios from 'axios';
import axios from '../../utils/axios';
@@ -15,6 +15,12 @@ import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate
import { HeadCell, Order, PaginationTableProps } from '../../@types/table';
import { useSearchParams, useNavigate } from 'react-router-dom';
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() {
const navigate = useNavigate();
@@ -47,7 +53,7 @@ export default function List() {
/* ------------------------------ handle order ------------------------------ */
const [order, setOrder] = useState('desc');
- const [orderBy, setOrderBy] = useState('codeRequest');
+ const [orderBy, setOrderBy] = useState('code');
const orders = {
order: order,
@@ -109,41 +115,41 @@ export default function List() {
/* -------------------------------- headCell -------------------------------- */
const headCells: HeadCell[] = [
{
- id: 'memberId',
+ id: 'submission_date',
+ align: 'center',
+ label: 'Request Date',
+ isSort: true,
+ },
+ {
+ id: 'member_id',
align: 'left',
label: 'Member ID',
isSort: true,
},
{
- id: 'codeRequest',
+ id: 'code',
align: 'left',
- label: 'Code Request',
+ label: 'Claim Code',
isSort: true,
},
{
- id: 'submissionDate',
- align: 'left',
- label: 'Request Date',
- isSort: true,
- },
- {
- id: 'fullName',
+ id: 'full_name',
align: 'left',
label: 'Name',
isSort: true,
},
{
- id: 'division',
+ id: 'division_name',
align: 'left',
- label: 'Divisi',
- isSort: false,
+ label: 'Division',
+ isSort: true,
},
{
id: 'status',
align: 'center',
label: 'Status',
- isSort: false,
+ isSort: true,
},
{
id: 'action',
@@ -168,49 +174,99 @@ export default function List() {
params: { ...parameters, type: 'claim-report' },
});
+ console.log(response.data.data);
+
setData(
response.data.data.map((obj: any) => ({
...obj,
status:
obj.status === 'requested' ? (
-
+
) : obj.status === 'approved' ? (
-
+ Approval
+
+ ) : obj.status === 'declined' ? (
+
+ Decline
+
+ ) : obj.status === 'pending' ? (
+
+ Pending
+
+ ) : obj.status === 'review' ? (
+
+ Review
+
) : (
}
sx={{
backgroundColor: '#CD7B2E',
color: '#FFFF',
- paddingX: 1.5,
+ padding: '1px, 8px',
paddingY: 1,
'&:hover': {
backgroundColor: '#BF6919',
@@ -221,8 +277,31 @@ export default function List() {
Ongoing
),
- submissionDate:
- obj.submissionDate ? fDate(obj.submissionDate) : ''
+ submission_date:
+ theme.palette.grey[300],
+ borderRadius: '4px',
+ width: '70%',
+ }}
+ variant="body2"
+ >
+ {obj.submission_date ? format(new Date(obj.submission_date), "d MMM yyyy") : ''}
+
+ ,
+ action:
+
+
+
+ >
+ } />
}))
);
diff --git a/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx b/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx
index ace7af39..0f0536bc 100644
--- a/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx
+++ b/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx
@@ -14,6 +14,7 @@ import {
Stack,
Grid,
Avatar,
+ ButtonBase,
} from '@mui/material';
import { Add } from '@mui/icons-material';
// components
@@ -23,10 +24,17 @@ import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
// theme
import palette from '../../theme/palette';
// React
-import { ReactElement, useRef, useState } from 'react';
+import { Fragment, ReactElement, useEffect, useRef, useState } from 'react';
import { useSearchParams, useNavigate, Link } from 'react-router-dom';
import { fPostFormat } from '../../utils/formatTime';
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 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 = {
title?: {
name?: string;
@@ -69,188 +95,435 @@ const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
}));
/* -------------------------------------------------------------------------- */
-
const steps = ['Review', 'Approval', 'Disbursement'];
const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => {
- function clickHandler(arg0: string) {
- throw new Error('Function not implemented.');
- }
-
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([]);
- // );
+ 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 (
<>
-
+
{/* Field 1 */}
- navigate(`/corporate`)} sx={{ cursor: "pointer" }} />
- Claim Submission
- Submission Date
-
+ navigate(`/claim-submit`)}
+ sx={{ cursor: 'pointer' }}
+ />
+
+ Claim Submission{' '}
+
+
+ Submission Date{' '}
+
+
{fPostFormat(new Date(), 'dd MMM yyyy')}
-
-
-
-
-
-
-
-
-
-
-
- {'Alexandra Rhea Putranto'}
- {'KM002-01'}
-
-
-
- Total Limit
-
-
-
- {fCurrency(8000000)} / {fCurrency(100000)}
-
-
-
-
-
+ {dataContent.map((row, index) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {row.personName}
+
+ {row.personID}
+
+
+
+
+ Total Limit
+
+
+
+ {fCurrency(8000000)} / {fCurrency(100000)}
+
+
+
+
+
+ {/* REAL INVOICE */}
+
+
+
+ Real Invoice
+
+ {row.fileRealInvoice &&
+ row.fileRealInvoice.map((file, fileIndex) => (
+
+
+ {file.name}
+ {
+ handleRemoveFile(row, 'invoice', fileIndex);
+ }}
+ />
+
+
+ ))}
+
+
+
+
+
+
+
+
+ {/* DOCTOR'S PRESCRIPTION AND ANOTHER DOCUMENTS */}
+
+
+
+
+ Doctor's Prescription and Another Documents
+
+
+ {row.anotherDocument &&
+ row.anotherDocument.map((file, fileIndex) => (
+
+
+ {file.name}
+ {
+ handleRemoveFile(row, 'another', fileIndex);
+ }}
+ />
+
+
+ ))}
+
+
+
+
+
+
+
+
+ {/* LABORATORY RESULTS */}
+
+
+
+ Laboraroty Results
+
+ {row.laboratoryResult &&
+ row.laboratoryResult.map((file, fileIndex) => (
+
+
+ {file.name}
+ {
+ handleRemoveFile(row, 'lab', fileIndex);
+ }}
+ />
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ );
+ })}
+
+
+ Claim Submit
+
+
-
-
- 17 Mei 2022
-
-
-
-
-
- {/* Item 1 */}
-
-
- 09:10 WIB
-
- Approval
-
-
-
-
-
- Details : mohon melengkapi kekurangan dokumen
-
-
- Lab pemeriksaan darah
-
- }
- fullWidth
- sx={{ typography: 'subtitle2', borderColor: '#F5F5F5' }}
- // onClick={() => clickHandler('topUpLimit')}
- >
- Hasil Pemeriksaan Laboratorium
-
-
-
- {/* Item 2 */}
-
-
- 09:00 WIB
-
- Approval
-
-
-
-
-
- Details : Penilaian Dokter
-
-
-
- {/* Item 3 */}
-
-
- 08:00 WIB
-
- Review
-
-
-
-
-
- Details : Klaim Diajukan
-
-
-
-
-
>
- //
);
};
+// let temp = [
+// {
+// member: "",
+// result_file: [
+// "file.pdf",
+// "file2.pdf"
+// ]
+// }
+// ]
+
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(null);
+
+ return (
+ ref.current?.click()}>
+
+
+
+ Add Invoice
+
+
+ handle(event, row, type)}
+ />
+
+ );
+};
diff --git a/frontend/client-portal/src/pages/ClaimSubmit/List.tsx b/frontend/client-portal/src/pages/ClaimSubmit/List.tsx
index 5685cea5..620ec685 100644
--- a/frontend/client-portal/src/pages/ClaimSubmit/List.tsx
+++ b/frontend/client-portal/src/pages/ClaimSubmit/List.tsx
@@ -106,7 +106,6 @@ export default function List() {
handleSearchSubmit: handleSearchSubmit,
};
-
/* ------------------------------------------------------------------------- */
/*-------------------------------- handlle checkbox ------------------------ */
const handleCheckboxChange = async (event: React.FormEvent) => {
@@ -122,18 +121,11 @@ export default function List() {
}
};
-
/* -------------------------------- headCell -------------------------------- */
-
return (
-
+
);
}
diff --git a/frontend/client-portal/src/pages/EmployeeData/List.tsx b/frontend/client-portal/src/pages/EmployeeData/List.tsx
index 1d8a0476..36dba3d6 100644
--- a/frontend/client-portal/src/pages/EmployeeData/List.tsx
+++ b/frontend/client-portal/src/pages/EmployeeData/List.tsx
@@ -250,24 +250,24 @@ export default function List() {
{
id: 'start_date',
- align: 'left',
+ align: 'center',
label: 'Start Date',
isSort: true,
},
{
id: 'end_date',
- align: 'left',
+ align: 'center',
label: 'End Date',
isSort: true,
},
{
id: 'status',
- align: 'left',
+ align: 'center',
label: 'Status',
isSort: true,
},
{
- id: 'view',
+ id: 'action',
align: 'center',
label: '',
isSort: true,
@@ -289,9 +289,7 @@ export default function List() {
const response = await axios.get(`${corporateValue}/members?type=employee-data`, {
params: { ...parameters },
});
-
- console.log(response.data.data);
-
+
setData(
response.data.data.map((obj: any) => {
return {
@@ -303,34 +301,48 @@ export default function List() {
// ,
status:
obj.status === 1 ? (
-
+
) : (
-
+
),
start_date:
theme.palette.grey[300],
borderRadius: '4px',
- width: '95%',
+ width: '70%',
}}
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") : ''}
,
end_date:
@@ -338,11 +350,11 @@ export default function List() {
sx={{
backgroundColor: (theme) => theme.palette.grey[300],
borderRadius: '4px',
- width: '95%',
+ width: '70%',
}}
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") : ''}
,
fullName:
@@ -359,7 +371,7 @@ export default function List() {
{obj.memberId}
,
- view:
+ action: