diff --git a/Modules/Client/Http/Controllers/Api/ClaimReportController.php b/Modules/Client/Http/Controllers/Api/ClaimReportController.php
index b83234ad..8e2ee1f0 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
{
@@ -57,6 +59,130 @@ class ClaimReportController extends Controller
]);
}
+ 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(
+ DB::raw('ROW_NUMBER() OVER (ORDER BY claim_items.id DESC) as claim_item_number'),
+ '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'),
+ )
+ ->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/Routes/api.php b/Modules/Client/Routes/api.php
index cd3acf81..02e0be16 100644
--- a/Modules/Client/Routes/api.php
+++ b/Modules/Client/Routes/api.php
@@ -55,6 +55,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 18f5e077..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
{
@@ -21,7 +22,7 @@ class MemberResources extends JsonResource
'full_name' => $this->full_name,
'division_name' => $this->division_name ?? '',
'status' => $this->status,
- 'claimRequestId' => $this->claim_request_id,
+ 'claimRequestId' => Crypt::encrypt($this->claim_request_id),
'submission_date' => $this->submission_date,
];
}
diff --git a/app/Services/CorporateMemberService.php b/app/Services/CorporateMemberService.php
index 3a6192df..d4380631 100644
--- a/app/Services/CorporateMemberService.php
+++ b/app/Services/CorporateMemberService.php
@@ -77,8 +77,8 @@ class CorporateMemberService
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"
+ /*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
'),
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/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..c9e45f76
--- /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);
+ });
+
+ }, []);
+
+ console.log(data?.data?.claim_item.length);
+
+ 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) => (
+
+
+ {dataItem.claim_item_number}
+
+
+
+ {format(new Date(dataItem.submission_date), "d MMM yyyy")}
+
+
+
+ {dataItem.description}
+
+
+ {fCurrency(dataItem.nominal_ditagihkan)}
+
+
+ {fCurrency(dataItem.nominal_dicover)}
+
+
+ ))
+ )}
+
+
+ {/* End Table Body */}
+
+
+
+
+
+
+ {/* 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
+
+
+
+
+ ) : ''}
+
+
+ );
+}
\ 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..18399f23
--- /dev/null
+++ b/frontend/client-portal/src/pages/ClaimReport/DetailTimeline.tsx
@@ -0,0 +1,108 @@
+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 }) => ({
+ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
+ ...theme.typography.body2,
+ padding: theme.spacing(1),
+ textAlign: 'center',
+ color: theme.palette.text.secondary,
+ 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}
+ }>
+
+ {dataRequestFile.type === 'claim-diagnosis' ?
+ 'Dokumen Diagnosa'
+ : dataRequestFile.type === 'claim-kondisi' ?
+ 'Dokumen Kondisi'
+ : dataRequestFile.type === 'claim-result' ?
+ 'Dokumen Hasil Penunjang'
+ : ''}
+
+
+
+ ))}
+ >
+ ) : ''}
+
+
+
+
+
+ ))}
+ >
+ );
+}
diff --git a/frontend/client-portal/src/pages/ClaimReport/List.tsx b/frontend/client-portal/src/pages/ClaimReport/List.tsx
index 03d3db7d..4c3417f6 100644
--- a/frontend/client-portal/src/pages/ClaimReport/List.tsx
+++ b/frontend/client-portal/src/pages/ClaimReport/List.tsx
@@ -53,7 +53,7 @@ export default function List() {
/* ------------------------------ handle order ------------------------------ */
const [order, setOrder] = useState('desc');
- const [orderBy, setOrderBy] = useState('code');
+ const [orderBy, setOrderBy] = useState('member_id');
const orders = {
order: order,
@@ -174,8 +174,6 @@ export default function List() {
params: { ...parameters, type: 'claim-report' },
});
- console.log(response.data.data);
-
setData(
response.data.data.map((obj: any) => ({
...obj,
@@ -244,7 +242,7 @@ export default function List() {
>
Pending
- ) : obj.status === 'review' ? (
+ ) : obj.status === 'reviewed' ? (
-