diff --git a/Modules/Client/Http/Controllers/Api/ClaimReportController.php b/Modules/Client/Http/Controllers/Api/ClaimReportController.php index b3edd3a6..2ced9d97 100644 --- a/Modules/Client/Http/Controllers/Api/ClaimReportController.php +++ b/Modules/Client/Http/Controllers/Api/ClaimReportController.php @@ -6,6 +6,8 @@ use App\Helpers\Helper; use App\Http\Controllers\Controller; use App\Models\ClaimRequest; use Modules\Client\Transformers\ClaimReport\ShowResources; +use Illuminate\Support\Facades\Crypt; +use Illuminate\Support\Facades\DB; class ClaimReportController extends Controller { @@ -25,6 +27,7 @@ class ClaimReportController extends Controller $corporateEmployee->where('corporate_id', $corporateId); }); }) + ->whereHas('claim', fn ($query) => $query->where('status', 'approved')) ->where('status', 'approved') ->get(); @@ -38,13 +41,148 @@ 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) ]); } + public function claimDetail($corporate_id, $claimRequestId) + { + $claimRequestId = Crypt::decrypt($claimRequestId); + + $status = 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', '=', $corporate_id) + ->where('claim_requests.id', '=', $claimRequestId) + ->select( + 'claim_requests.submission_date', + 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 "reviewed" + ELSE "" + END AS status + ') + ) + ->first(); + $results['status'] = $status; + $timeline = DB::table('claim_logs') + ->where('claim_logs.claim_request_id', '=', $claimRequestId) + ->select( + DB::raw(' + CASE + WHEN claim_logs.status = "requested" THEN "Request" + WHEN claim_logs.status = "reviewed" THEN "Review" + WHEN claim_logs.status = "approved" THEN "Approval" + ELSE "-" + END AS txt_status + '), + DB::raw(' + CASE + WHEN claim_logs.status = "requested" THEN "#159C9C" + WHEN claim_logs.status = "reviewed" THEN "#0C53B7" + WHEN claim_logs.status = "approved" THEN "#229A16" + ELSE "-" + END AS txt_status_color + '), + DB::raw(' + CASE + WHEN claim_logs.status = "requested" THEN "#00AB5529" + WHEN claim_logs.status = "reviewed" THEN "#1890FF29" + WHEN claim_logs.status = "approved" THEN "#54D62C29" + ELSE "-" + END AS txt_status_backgroundColor + '), + 'claim_logs.date', + 'claim_logs.description', + 'claim_logs.status' + ) + ->orderBy('claim_logs.id', 'desc') + ->get(); + $results['timeline'] = $timeline; + $request_files = DB::table('claim_request_files') + ->where('claim_request_files.claim_request_id', '=', $claimRequestId) + ->get(); + $results['request_files'] = $request_files; + + return Helper::responseJson($results); + } + + public function claimDetailHistory($corporate_id, $claimRequestId) + { + $claimRequestId = Crypt::decrypt($claimRequestId); + + $member = 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', '=', $corporate_id) + ->where('claim_requests.id', '=', $claimRequestId) + ->select( + 'claim_requests.code','members.member_id', 'members.name' + ) + ->first(); + $results['member'] = $member; + $claim_item = DB::table('claim_items') + ->leftJoin('claims','claim_items.claim_id', '=', 'claims.id') + ->leftJoin('benefits', 'claim_items.claim_itemable_id', '=', 'benefits.id') + ->leftJoin('claim_requests', 'claims.claim_request_id', '=', 'claim_requests.id') + ->leftJoin('members', 'claim_requests.member_id', '=', 'members.id') + ->leftJoin('corporate_employees', 'members.id', '=', 'corporate_employees.member_id') + ->where('corporate_employees.corporate_id', '=', $corporate_id) + ->where('claim_requests.id', '=', $claimRequestId) + ->select( + 'claim_items.nominal_ditagihkan', + 'claim_items.nominal_dicover', + 'benefits.description', + 'claim_requests.submission_date' + ) + ->orderBy('claim_items.id', 'desc') + ->get(); + $results['claim_item'] = $claim_item; + $tot_claim_item = DB::table('claim_items') + ->leftJoin('claims','claim_items.claim_id', '=', 'claims.id') + ->leftJoin('benefits', 'claim_items.claim_itemable_id', '=', 'benefits.id') + ->leftJoin('claim_requests', 'claims.claim_request_id', '=', 'claim_requests.id') + ->leftJoin('members', 'claim_requests.member_id', '=', 'members.id') + ->leftJoin('corporate_employees', 'members.id', '=', 'corporate_employees.member_id') + ->where('corporate_employees.corporate_id', '=', $corporate_id) + ->where('claim_requests.id', '=', $claimRequestId) + ->select( + DB::raw('SUM(claim_items.nominal_ditagihkan) AS nominal_ditagihkan'), + DB::raw('SUM(claim_items.nominal_dicover) AS nominal_dicover'), + DB::raw('(SUM(claim_items.nominal_ditagihkan) - SUM(claim_items.nominal_dicover)) AS difference'), + ) + ->groupBy('claim_items.id') + ->orderBy('claim_items.id', 'desc') + ->first(); + $results['tot_claim_item'] = $tot_claim_item; + + + return Helper::responseJson($results); + } + public function show($corporateId, $claimRequestId) { $data = ClaimRequest::query() diff --git a/Modules/Client/Http/Controllers/Api/CorporateMemberController.php b/Modules/Client/Http/Controllers/Api/CorporateMemberController.php index 23a17981..3ea308fe 100644 --- a/Modules/Client/Http/Controllers/Api/CorporateMemberController.php +++ b/Modules/Client/Http/Controllers/Api/CorporateMemberController.php @@ -16,6 +16,7 @@ use Modules\Client\Transformers\AlarmCenter\DataServiceMonitoring; 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; @@ -33,8 +34,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/Routes/api.php b/Modules/Client/Routes/api.php index 1dbb8497..5e7b94e1 100644 --- a/Modules/Client/Routes/api.php +++ b/Modules/Client/Routes/api.php @@ -57,6 +57,8 @@ Route::prefix('client')->group(function () { // Route::get('topup', [TopUpController::class, 'get']); Route::post('topup', [TopUpController::class, 'store']); Route::get('claim-report/claim-status', [ClaimReportController::class, 'claimStatus']); + Route::get('claim-report/detail/{id}', [ClaimReportController::class, 'claimDetail']); + Route::get('claim-report/detail-history/{id}', [ClaimReportController::class, 'claimDetailHistory']); Route::get('corporate', [CorporateCurrentController::class, 'index']); Route::put('corporate-update', [CorporateCurrentController::class, 'update']); diff --git a/Modules/Client/Transformers/ClaimReport/MemberResources.php b/Modules/Client/Transformers/ClaimReport/MemberResources.php index a798dfcf..aae5a707 100644 --- a/Modules/Client/Transformers/ClaimReport/MemberResources.php +++ b/Modules/Client/Transformers/ClaimReport/MemberResources.php @@ -3,6 +3,7 @@ namespace Modules\Client\Transformers\ClaimReport; use Illuminate\Http\Resources\Json\JsonResource; +use Illuminate\Support\Facades\Crypt; class MemberResources extends JsonResource { @@ -16,13 +17,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, + 'claimRequestId' => Crypt::encrypt($this->claim_request_id), + '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 09314cb5..d66fa83b 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 "reviewed" + 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) @@ -177,6 +179,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/database/migrations/2023_10_11_131156_create_claim_logs_table.php b/database/migrations/2023_10_11_131156_create_claim_logs_table.php new file mode 100644 index 00000000..998c4e2d --- /dev/null +++ b/database/migrations/2023_10_11_131156_create_claim_logs_table.php @@ -0,0 +1,37 @@ +id(); + $table->bigInteger('claim_request_id'); + $table->string('status', 255); + $table->dateTime('date'); + $table->text('description')->nullable(); + $table->text('device')->nullable(); + $table->bigInteger('created_by'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('claim_logs'); + } +}; diff --git a/database/migrations/2023_10_11_145555_create_claim_request_files_table.php b/database/migrations/2023_10_11_145555_create_claim_request_files_table.php new file mode 100644 index 00000000..73e07d98 --- /dev/null +++ b/database/migrations/2023_10_11_145555_create_claim_request_files_table.php @@ -0,0 +1,36 @@ +id(); + $table->bigInteger('claim_request_id'); + $table->dateTime('date'); + $table->string('type', 255); + $table->text('description')->nullable(); + $table->bigInteger('created_by'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('claim_request_files'); + } +}; diff --git a/frontend/client-portal/public/icons/ic_gmail.svg b/frontend/client-portal/public/icons/ic_gmail.svg new file mode 100644 index 00000000..c71a7032 --- /dev/null +++ b/frontend/client-portal/public/icons/ic_gmail.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/frontend/client-portal/public/images/gmail.png b/frontend/client-portal/public/images/gmail.png new file mode 100644 index 00000000..fe8d5f99 Binary files /dev/null and b/frontend/client-portal/public/images/gmail.png differ diff --git a/frontend/client-portal/src/pages/ClaimReport/Detail.tsx b/frontend/client-portal/src/pages/ClaimReport/Detail.tsx new file mode 100644 index 00000000..8fd44714 --- /dev/null +++ b/frontend/client-portal/src/pages/ClaimReport/Detail.tsx @@ -0,0 +1,69 @@ +// mui +import { Container, Grid, Stack, Typography } from '@mui/material'; +// components +import Page from '../../components/Page'; +// utils +import useSettings from '../../hooks/useSettings'; +// section +import CardFamilyInformation from '../../sections/alarm-center/user-profile/CardFamilyInformation'; +// react +import { useNavigate, useParams } from 'react-router-dom'; +import ButtonBack from '../../components/ButtonBack'; +import { useEffect, useState, useContext } from 'react'; +import axios from '../../utils/axios'; +import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; +// pages +import DetailTimeline from '../../pages/ClaimReport/DetailTimeline'; +import DetailStepper from '../../pages/ClaimReport/DetailStepper'; +import { format } from 'date-fns'; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; + +// ---------------------------------------------------------------------- + +export default function UserProfile() { + const navigate = useNavigate(); + const { themeStretch } = useSettings(); + const [data, setData] = useState(); + + const { corporateValue } = useContext(UserCurrentCorporateContext); + const { id } = useParams(); + + useEffect(() => { + axios + .get(corporateValue + '/claim-report/detail/' + id) + .then((response) => { + setData(response.data); + }) + .catch((error) => { + console.error(error); + }); + + }, []); + + return ( + + + + navigate(-1)} sx={{cursor:'pointer'}}/> + Detail + {data ? ( + + Submission Date + {(data && data.data) ? format(new Date(data.data.status.submission_date), "d MMM yyyy") : ''} + + ) : ''} + + {data ? ( + + + + + + + + + ) : ''} + + + ); +} \ No newline at end of file diff --git a/frontend/client-portal/src/pages/ClaimReport/DetailHistory.tsx b/frontend/client-portal/src/pages/ClaimReport/DetailHistory.tsx new file mode 100644 index 00000000..f50494f1 --- /dev/null +++ b/frontend/client-portal/src/pages/ClaimReport/DetailHistory.tsx @@ -0,0 +1,291 @@ +// mui +import { + Container, + Grid, + Stack, + Typography, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, + Button, + Box, + TableSortLabel, + Avatar } from '@mui/material'; +// components +import Page from '../../components/Page'; +// utils +import useSettings from '../../hooks/useSettings'; +// section +import CardFamilyInformation from '../../sections/alarm-center/user-profile/CardFamilyInformation'; +// react +import { useNavigate, useParams } from 'react-router-dom'; +import ButtonBack from '../../components/ButtonBack'; +import { useEffect, useState, useContext } from 'react'; +import axios from '../../utils/axios'; +import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; +import { format } from 'date-fns'; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; +import { fCurrency } from '../../utils/formatNumber'; + +// ---------------------------------------------------------------------- + +export default function DetailHistory() { + const navigate = useNavigate(); + const { themeStretch } = useSettings(); + const [data, setData] = useState(); + + const { corporateValue } = useContext(UserCurrentCorporateContext); + const { id } = useParams(); + + useEffect(() => { + axios + .get(corporateValue + '/claim-report/detail-history/' + id) + .then((response) => { + setData(response.data); + }) + .catch((error) => { + console.error(error); + }); + + }, []); + + return ( + + + + navigate(-1)} sx={{cursor:'pointer'}}/> + History + + {data ? ( + + + + Name + {data.data.member.name} + + + Member ID + {data.data.member.member_id} + + + Claim Code + {data.data.member.code} + + + + + + {/* Table Header */} + + + + No + + + Date + + + Requirment + + + Request Claim + + + Approval Claim + + + + {/* End Table Header */} + {/* Table Body */} + + {data?.data?.claim_item?.length === 0 ? ( + + + No data available + + + ) : ( + data.data.claim_item?.map((dataItem, index) => ( + + + {parseInt(index)+1} + + + + {format(new Date(dataItem.submission_date), "d MMM yyyy")} + + + + {dataItem.description} + + + {fCurrency(dataItem.nominal_ditagihkan)} + + + {fCurrency(dataItem.nominal_dicover)} + + + )) + )} + + + {/* End Table Body */} +
+
+
+ {data.data.tot_claim_item ? ( + + + + {/* Table Body */} + + + + + + + + + + + + + Request Claim + + + {data.data.tot_claim_item.nominal_ditagihkan ? fCurrency(data.data.tot_claim_item.nominal_ditagihkan) : '-'} + + + + + + + + + + + + + + Approval Claim + + + {data.data.tot_claim_item.nominal_dicover ? fCurrency(data.data.tot_claim_item.nominal_dicover) : '-'} + + + + + + + + + + + + + + Difference + + + {data.data.tot_claim_item.difference ? fCurrency(data.data.tot_claim_item.difference) : '-'} + + + + {/* End Table Body */} +
+
+ + Note : Apabila terdapat perbedaan nominal silahkan hubungi kami + Gmail Icon + +
+ ) : ''} +
+ ) : ''} +
+
+ ); +} \ No newline at end of file diff --git a/frontend/client-portal/src/pages/ClaimReport/DetailStepper.tsx b/frontend/client-portal/src/pages/ClaimReport/DetailStepper.tsx new file mode 100644 index 00000000..18dc959a --- /dev/null +++ b/frontend/client-portal/src/pages/ClaimReport/DetailStepper.tsx @@ -0,0 +1,58 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stepper from '@mui/material/Stepper'; +import Step from '@mui/material/Step'; +import StepLabel from '@mui/material/StepLabel'; +import { useEffect, useState } from 'react'; +import ClearIcon from '@mui/icons-material/Clear'; + +const steps = [ + 'Request', + 'Review', + 'Approval', + 'Decline', +]; + +export default function HorizontalLinearAlternativeLabelStepper({data}) { + const [active, setActive] = useState(0); + const [status, SetStatus] = useState(null); + let updatedSteps = [...steps]; + useEffect(() => { + if (data && data.data) { + if (data.data.status.status === 'requested') { + setActive(1); + updatedSteps = updatedSteps.filter(step => step !== 'Decline'); + } + else if (data.data.status.status === 'reviewed') { + setActive(2); + updatedSteps = updatedSteps.filter(step => step !== 'Decline'); + } + else if (data.data.status.status === 'approved') + { + setActive(3); + updatedSteps = updatedSteps.filter(step => step !== 'Decline'); + } + else if(data.data.status.status === 'declined') + { + setActive(4) + updatedSteps = updatedSteps.filter(step => step !== 'Approval'); + } + } + SetStatus(updatedSteps); + }, [data]); + + + + + return ( + + + {status?.map((label) => ( + + : ''}>{label} + + ))} + + + ); +} diff --git a/frontend/client-portal/src/pages/ClaimReport/DetailTimeline.tsx b/frontend/client-portal/src/pages/ClaimReport/DetailTimeline.tsx new file mode 100644 index 00000000..4a1b2064 --- /dev/null +++ b/frontend/client-portal/src/pages/ClaimReport/DetailTimeline.tsx @@ -0,0 +1,106 @@ +import * as React from 'react'; +import Timeline from '@mui/lab/Timeline'; +import TimelineItem, { timelineItemClasses } from '@mui/lab/TimelineItem'; +import TimelineSeparator from '@mui/lab/TimelineSeparator'; +import TimelineConnector from '@mui/lab/TimelineConnector'; +import TimelineContent from '@mui/lab/TimelineContent'; +import TimelineDot from '@mui/lab/TimelineDot'; +import {Typography, Card, Stack} from '@mui/material'; +import { styled } from '@mui/material/styles'; +import Paper from '@mui/material/Paper'; +import Button from '@mui/material/Button'; +import AddIcon from '@mui/icons-material/Add'; +import Iconify from '../../components/Iconify'; +import { useEffect, useState } from 'react'; +import { format } from 'date-fns'; + +const Item1 = styled(Paper)(({ theme }) => ({ + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + backgroundColor: '#919EAB29', + color: '#637381', + width: 'fit-content', + marginRight: 'auto', +})); + +const Item2 = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, + width: 'fit-content', + marginLeft: 'auto', +})); + +export default function NoOppositeContent({data}) { + const [timeline, setTimeline] = useState(null); + const [requestFile, setRequestFile] = useState(null); + useEffect(() => { + if (data && data.data) { + setTimeline(data.data.timeline); + setRequestFile(data.data.request_files); + } + + }, [data]); + console.log(timeline); + console.log(requestFile); + return ( + <> + {timeline?.map((dataTimeline, index) => ( + + {dataTimeline.date ? format(new Date(dataTimeline.date), "d MMM yyyy") : ''} + + + + + + + + + + {dataTimeline.date ? format(new Date(dataTimeline.date), "HH : ii") : ''} + {dataTimeline.txt_status} + + + Detail: + {dataTimeline.description} + + {dataTimeline.status === 'reviewed' && requestFile ? ( + <> + {requestFile?.map((dataRequestFile, index) => ( + + {dataRequestFile.description} + + + ))} + + ) : ''} + + + + + + ))} + + ); +} diff --git a/frontend/client-portal/src/pages/ClaimReport/Index.tsx b/frontend/client-portal/src/pages/ClaimReport/Index.tsx index fc83c0e9..aa00441f 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: 'Disbrusment', + // value: claimStatus.data.data.disbrusments, + // color: '#BF6919', + // }, { - name: 'Rejected', + 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..4c3417f6 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('member_id'); 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', @@ -173,44 +179,92 @@ export default function List() { ...obj, status: obj.status === 'requested' ? ( - + ) : obj.status === 'approved' ? ( - + Approval + + ) : obj.status === 'declined' ? ( + + Decline + + ) : obj.status === 'pending' ? ( + + Pending + + ) : obj.status === 'reviewed' ? ( + + Review + ) : ( ), - 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: + + navigate ('/claim-report/detail/'+obj.claimRequestId)}> + + Detail + + navigate ('/claim-report/detail-history/'+obj.claimRequestId)}> + + History + + + } /> })) ); diff --git a/frontend/client-portal/src/pages/EmployeeData/Index.tsx b/frontend/client-portal/src/pages/EmployeeData/Index.tsx index 64129bbc..8f182c77 100644 --- a/frontend/client-portal/src/pages/EmployeeData/Index.tsx +++ b/frontend/client-portal/src/pages/EmployeeData/Index.tsx @@ -113,11 +113,9 @@ export default function Drugs() { /> - - 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: navigate ('/employee-data/user-profile/'+obj.personId)}> diff --git a/frontend/client-portal/src/pages/EmployeeData/UserProfile.tsx b/frontend/client-portal/src/pages/EmployeeData/UserProfile.tsx index e5afd27e..1bd40e40 100644 --- a/frontend/client-portal/src/pages/EmployeeData/UserProfile.tsx +++ b/frontend/client-portal/src/pages/EmployeeData/UserProfile.tsx @@ -17,12 +17,13 @@ import ButtonBack from '../../components/ButtonBack'; import { useEffect, useState, useContext } from 'react'; import axios from '../../utils/axios'; import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; // ---------------------------------------------------------------------- export default function UserProfile() { const { themeStretch } = useSettings(); - // const navigate = useNavigate(); + const navigate = useNavigate(); const [data, setData] = useState(); const { corporateValue } = useContext(UserCurrentCorporateContext); @@ -44,13 +45,14 @@ export default function UserProfile() { return ( - + {/* navigate()}> */} - - Profile + navigate(-1)}/> + Profile + {data ? ( {/* Row 1 */} @@ -60,6 +62,7 @@ export default function UserProfile() { + ) : ''} ); diff --git a/frontend/client-portal/src/routes/index.tsx b/frontend/client-portal/src/routes/index.tsx index 7e346267..4eac0cdd 100644 --- a/frontend/client-portal/src/routes/index.tsx +++ b/frontend/client-portal/src/routes/index.tsx @@ -174,9 +174,13 @@ export default function Router() { index: true, }, { - path: 'dialog-detail/:id', - element: , + path: '/claim-report/detail/:id', + element: , }, + { + path: '/claim-report/detail-history/:id', + element: , + } ], }, { @@ -259,6 +263,8 @@ const ClaimReport = Loadable(lazy(() => import('../pages/ClaimReport/Index'))); const Claims = Loadable(lazy(() => import('../pages/Claims/Index'))); const ClaimShow = Loadable(lazy(() => import('../pages/Claims/Show'))); const DialogDetailClaim = Loadable(lazy(()=> import('../pages/ClaimReport/DialogDetailClaim'))); +const DetailClaimReport = Loadable(lazy(()=> import('../pages/ClaimReport/Detail'))); +const DetailHitoryClaimReport = Loadable(lazy(()=> import('../pages/ClaimReport/DetailHistory'))); // Claim submit const ClaimSubmit = Loadable(lazy(() => import('../pages/ClaimSubmit/Index'))); diff --git a/frontend/client-portal/src/sections/alarm-center/user-profile/CardFamilyInformation.tsx b/frontend/client-portal/src/sections/alarm-center/user-profile/CardFamilyInformation.tsx index 4f69e709..a0803051 100644 --- a/frontend/client-portal/src/sections/alarm-center/user-profile/CardFamilyInformation.tsx +++ b/frontend/client-portal/src/sections/alarm-center/user-profile/CardFamilyInformation.tsx @@ -117,7 +117,7 @@ export default function CardFamilyInformation({ data }) { {data?.family.map((familyMember, index) => ( - + {/* Stack 1 */} ({ const defaultData = [ { name: 'Requested', value: 5, color: palette.dark.primary.dark }, { name: 'Approval', value: 1, color: palette.dark.warning.dark }, - { name: 'Disbrusment', value: 0, color: palette.dark.success.dark }, + //{ name: 'Disbrusment', value: 0, color: palette.dark.success.dark }, { name: 'Rejected', value: 3, color: palette.dark.error.dark }, ]; @@ -39,13 +39,13 @@ const defaultData = [ export default function CardClaimStatus({ data }: PropsCardClaimStatus) { return ( - + {/* Claim Status - + */} {data ? data.map(({ name, value, color }: ClaimStatusType, key) => ( - + )) : defaultData.map(({ name, value, color }: ClaimStatusType, key) => ( - + Dokumen Diagnosa - - Dokumen Diagnosa -