diff --git a/Modules/Client/Http/Controllers/Api/ClaimReportController.php b/Modules/Client/Http/Controllers/Api/ClaimReportController.php index a8b43216..8a3d5b5a 100644 --- a/Modules/Client/Http/Controllers/Api/ClaimReportController.php +++ b/Modules/Client/Http/Controllers/Api/ClaimReportController.php @@ -2,8 +2,10 @@ namespace Modules\Client\Http\Controllers\Api; +use App\Helpers\Helper; use Illuminate\Http\Request; use App\Http\Controllers\Controller; +use App\Models\ClaimRequest; class ClaimReportController extends Controller { @@ -12,52 +14,39 @@ class ClaimReportController extends Controller * * @return \Illuminate\Http\Response */ - public function index() + public function claimStatus($corporateId) { - } + $requesteds = ClaimRequest::query() + ->whereHas('member', function ($query) use ($corporateId) { + $query->whereHas('employeds', function ($corporateEmployee) use ($corporateId) { + $corporateEmployee->where('corporate_id', $corporateId); + }); + }) + ->where('status', 'requested') + ->get(); + $approveds = ClaimRequest::query() + ->whereHas('member', function ($query) use ($corporateId) { + $query->whereHas('employeds', function ($corporateEmployee) use ($corporateId) { + $corporateEmployee->where('corporate_id', $corporateId); + }); + }) + ->where('status', 'approved') + ->get(); - /** - * Store a newly created resource in storage. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - */ - public function store(Request $request) - { - // - } + $rejecteds = 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', 'declined')) + ->where('status', 'approved') + ->get(); - /** - * Display the specified resource. - * - * @param int $id - * @return \Illuminate\Http\Response - */ - public function show($id) - { - // - } - - /** - * Update the specified resource in storage. - * - * @param \Illuminate\Http\Request $request - * @param int $id - * @return \Illuminate\Http\Response - */ - public function update(Request $request, $id) - { - // - } - - /** - * Remove the specified resource from storage. - * - * @param int $id - * @return \Illuminate\Http\Response - */ - public function destroy($id) - { - // + return Helper::responseJson([ + 'requesteds' => count($requesteds), + 'approveds' => count($approveds), + 'rejecteds' => count($rejecteds) + ]); } } diff --git a/Modules/Client/Routes/api.php b/Modules/Client/Routes/api.php index d0dfe1aa..a83ee008 100644 --- a/Modules/Client/Routes/api.php +++ b/Modules/Client/Routes/api.php @@ -10,10 +10,9 @@ use Modules\Client\Http\Controllers\Api\UserController; use Modules\Client\Http\Controllers\Api\ClaimController; use Modules\Client\Http\Controllers\Api\TopUpController; use Modules\Internal\Http\Controllers\ClaimEncounterController; -use App\Models\Encounter; +use Modules\Client\Http\Controllers\Api\ClaimReportController; use Modules\Client\Http\Controllers\Api\ClaimRequestController; use Modules\Client\Http\Controllers\Api\DataController; -use Modules\Internal\Transformers\EncounterResource; /* |-------------------------------------------------------------------------- @@ -54,6 +53,7 @@ Route::prefix('client')->group(function () { Route::get('topup', [TopUpController::class, 'index']); // Route::get('topup', [TopUpController::class, 'get']); Route::post('topup', [TopUpController::class, 'store']); + Route::get('claim-report/claim-status', [ClaimReportController::class, 'claimStatus']); }); Route::get('claims/{id}', [ClaimController::class, 'show']); diff --git a/app/Services/CorporateMemberService.php b/app/Services/CorporateMemberService.php index 42ad8ef0..9d40ae24 100644 --- a/app/Services/CorporateMemberService.php +++ b/app/Services/CorporateMemberService.php @@ -48,6 +48,7 @@ class CorporateMemberService $limit = $request->has('perPage') ? $request->input('perPage') : 10; return Member::query() + ->joinClaimRequests('right') ->joinCorporateEmployees('left') ->joinCorporateDivisions('left') ->with('currentPlan') @@ -61,6 +62,11 @@ class CorporateMemberService ->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', @@ -74,7 +80,7 @@ class CorporateMemberService $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', 'members.active']) + ->select(['members.id', 'members.person_id', 'members.member_id', 'members.name', 'corporate_divisions.name AS division_name', 'members.active', 'claim_requests.id', 'claim_requests.member_id', 'claim_requests.submission_date']) ->paginate($limit); } diff --git a/frontend/client-portal/.env.development b/frontend/client-portal/.env.development index ced427a5..52e237c2 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://localhost:8000" +REACT_APP_HOST_API_URL="http://aso.test" -VITE_API_URL="http://localhost:8000/api/client" +VITE_API_URL="http://aso.test/api/client" diff --git a/frontend/client-portal/src/pages/ClaimReport/Index.tsx b/frontend/client-portal/src/pages/ClaimReport/Index.tsx index 7e46fa2b..35623dd7 100644 --- a/frontend/client-portal/src/pages/ClaimReport/Index.tsx +++ b/frontend/client-portal/src/pages/ClaimReport/Index.tsx @@ -20,12 +20,20 @@ import List from './List'; import ClaimItems from '../Claims/components/ClaimItems'; import DiagnosisHistory from '../Claims/components/DiagnosisHistory'; import Documents from '../Claims/components/Documents'; +// theme +import palette from '../../theme/palette'; + +interface ClaimStatusType { + name: string; + value: number; + color: string; +} export default function Drugs() { const { themeStretch } = useSettings(); const { corporateValue } = useContext(UserCurrentCorporateContext); - const [listClaimStatusItems, setListClaimStatusItems] = useState([]); + const [listClaimStatusItems, setListClaimStatusItems] = useState([]); const [listAllMemberByClaimStatus, setListAllMemberByClaimStatus] = useState([]); /* -------------------------------------------------------------------------- */ @@ -127,6 +135,26 @@ export default function Drugs() { (async () => { setIsLoading(true); + const claimStatus = await axios.get(`${corporateValue}/claim-report/claim-status`); + + setListClaimStatusItems([ + { + name: 'Requested', + value: claimStatus.data.data.requesteds, + color: palette.dark.primary.dark, + }, + { + name: 'Approval', + value: claimStatus.data.data.approveds, + color: palette.dark.warning.dark, + }, + { + name: 'Rejected', + value: claimStatus.data.data.rejecteds, + color: palette.dark.error.dark, + }, + ]); + const parameters = Object.keys(appliedParams).length !== 0 ? appliedParams @@ -142,7 +170,6 @@ export default function Drugs() { setSearchParams(parameters); - setListClaimStatusItems(claim.data.data.allClaimStatus); setListAllMemberByClaimStatus(claim.data.data.allMembersByClaimStatus.data); setPaginationTable(claim.data.data.allMembersByClaimStatus); @@ -158,8 +185,8 @@ export default function Drugs() { - - + + {/* , property: string) => void; - // order: Order; - // orderBy: string; - // } - - // function EnhancedTableHead(props: EnhancedTableProps) { - // const { order, orderBy, onRequestSort } = props; - // const createSortHandler = (property: string) => (event: React.MouseEvent) => { - // onRequestSort(event, property); - // }; - - // return ( - // - // - // No - // {headCells.map((headCell) => ( - // - // - // {headCell.label} - // {orderBy === headCell.id ? ( - // - // {order === 'desc' ? 'sorted descending' : 'sorted ascending'} - // - // ) : null} - // - // - // ))} - // - // - // ); - // } - - /* -------------------------------------------------------------------------- */ - - export default function List() { - const navigate = useNavigate(); - - const { corporateValue } = useContext(UserCurrentCorporateContext); - - const [data, setData] = useState([]); - - /* -------------------------------------------------------------------------- */ - /* setting up for the table */ - /* -------------------------------------------------------------------------- */ - const [isLoading, setIsLoading] = useState(true); - - const loadings = { - isLoading: isLoading, - setIsLoading: setIsLoading, - }; - - /* ------------------------------ handle params ----------------------------- */ - const [searchParams, setSearchParams] = useSearchParams(); - const [appliedParams, setAppliedParams] = useState({}); - - const params = { - searchParams: searchParams, - setSearchParams: setSearchParams, - appliedParams: appliedParams, - setAppliedParams: setAppliedParams, - }; - /* -------------------------------------------------------------------------- */ - - /* ------------------------------ handle order ------------------------------ */ - const [order, setOrder] = useState('asc'); - const [orderBy, setOrderBy] = useState('fullName'); - - const orders = { - order: order, - setOrder: setOrder, - orderBy: orderBy, - setOrderBy: setOrderBy, - }; - /* -------------------------------------------------------------------------- */ - - /* ---------------------------- handle pagination --------------------------- */ - const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); - - const [paginationTable, setPaginationTable] = useState({ - current_page: 0, - from: 0, - last_page: 0, - links: [], - path: '', - per_page: 0, - to: 0, - total: 0, - }); - - const paginations = { - page: page, - setPage: setPage, - rowsPerPage: rowsPerPage, - setRowsPerPage: setRowsPerPage, - paginationTable: paginationTable, - setPaginationTable: setPaginationTable, - }; - - /* -------------------------------------------------------------------------- */ - - /* ------------------------------ handle search ----------------------------- */ - const [searchText, setSearchText] = useState(''); - - const handleSearchSubmit = async (event: React.FormEvent) => { - event.preventDefault(); - - if (searchText === '') { - searchParams.delete('search'); - const params = Object.fromEntries([...searchParams.entries()]); - setAppliedParams(params); - } else { - const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]); - setAppliedParams(params); - } - }; + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, + Stack, + IconButton, + Button, + TableSortLabel, + Box, +} from '@mui/material'; +import DialogDetailClaim from '../../sections/dashboard/DialogDetailClaim'; +import { visuallyHidden } from '@mui/utils'; +import { MoreVert as MoreVertIcon } from '@mui/icons-material'; +/* ---------------------------------- axios --------------------------------- */ +// import axios from 'axios'; +import axios from '../../utils/axios'; +/* ---------------------------------- react --------------------------------- */ +import { useContext, useEffect, useState } from 'react'; - - const searchs = { - searchText: searchText, - setSearchText: setSearchText, - handleSearchSubmit: handleSearchSubmit, - }; - - /* -------------------------------- headCell -------------------------------- */ - const headCells: HeadCell[] = [ - { - id: 'memberId', - align: 'left', - label: 'Member ID', - isSort: true, - }, - { - id: 'fullName', - align: 'left', - label: 'Name', - isSort: true, - }, - - { - id: 'division', - align: 'left', - label: 'Divisi', - isSort: true, - }, - /* { +/* -------------------------------- component ------------------------------- */ +import Iconify from '../../components/Iconify'; +import BaseTablePagination from '../../components/BaseTablePagination'; +import TableComponent from '../../components/Table'; +import { Navigate } from 'react-router-dom'; + +/* ---------------------------------- hooks --------------------------------- */ +import useMap from '../../hooks/useMap'; +/* ---------------------------------- theme --------------------------------- */ +import palette from '../../theme/palette'; +import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; +import { HeadCell, Order, PaginationTableProps } from '../../@types/table'; +import { useSearchParams, useNavigate } from 'react-router-dom'; + +/* ---------------------------------- types --------------------------------- */ + +// type PaginationTableProps = { +// current_page: number; +// from: number; +// last_page: number; +// links: []; +// path: string; +// per_page: number; +// to: number; +// total: number; +// }; + +// type DataTableProps = { +// fullName: string; +// memberId: string; +// service: string; +// start_date: string; +// end_date: string; +// status: boolean | number; +// }; + +// /* -------------------------------------------------------------------------- */ + +// /* -------------------------- enchanced table head -------------------------- */ + +// type Order = 'asc' | 'desc'; + +// interface HeadCell { +// id: string; +// label: string; +// } + +// const headCells: readonly HeadCell[] = [ +// { +// id: 'name', +// label: 'Name', +// }, +// { +// id: 'member_id', +// label: 'Member ID', +// }, +// { +// id: 'service', +// label: 'Service', +// }, +// { +// id: 'start_date', +// label: 'Start Date', +// }, +// { +// id: 'end_date', +// label: 'End Date', +// }, +// { +// id: 'status', +// label: 'Status', +// }, +// ]; + +// interface EnhancedTableProps { +// onRequestSort: (event: React.MouseEvent, property: string) => void; +// order: Order; +// orderBy: string; +// } + +// function EnhancedTableHead(props: EnhancedTableProps) { +// const { order, orderBy, onRequestSort } = props; +// const createSortHandler = (property: string) => (event: React.MouseEvent) => { +// onRequestSort(event, property); +// }; + +// return ( +// +// +// No +// {headCells.map((headCell) => ( +// +// +// {headCell.label} +// {orderBy === headCell.id ? ( +// +// {order === 'desc' ? 'sorted descending' : 'sorted ascending'} +// +// ) : null} +// +// +// ))} +// +// +// ); +// } + +/* -------------------------------------------------------------------------- */ + +export default function List() { + const navigate = useNavigate(); + + const { corporateValue } = useContext(UserCurrentCorporateContext); + + const [data, setData] = useState([]); + + /* -------------------------------------------------------------------------- */ + /* setting up for the table */ + /* -------------------------------------------------------------------------- */ + const [isLoading, setIsLoading] = useState(true); + + const loadings = { + isLoading: isLoading, + setIsLoading: setIsLoading, + }; + + /* ------------------------------ handle params ----------------------------- */ + const [searchParams, setSearchParams] = useSearchParams(); + const [appliedParams, setAppliedParams] = useState({}); + + const params = { + searchParams: searchParams, + setSearchParams: setSearchParams, + appliedParams: appliedParams, + setAppliedParams: setAppliedParams, + }; + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle order ------------------------------ */ + const [order, setOrder] = useState('asc'); + const [orderBy, setOrderBy] = useState('fullName'); + + const orders = { + order: order, + setOrder: setOrder, + orderBy: orderBy, + setOrderBy: setOrderBy, + }; + /* -------------------------------------------------------------------------- */ + + /* ---------------------------- handle pagination --------------------------- */ + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(10); + + const [paginationTable, setPaginationTable] = useState({ + current_page: 0, + from: 0, + last_page: 0, + links: [], + path: '', + per_page: 0, + to: 0, + total: 0, + }); + + const paginations = { + page: page, + setPage: setPage, + rowsPerPage: rowsPerPage, + setRowsPerPage: setRowsPerPage, + paginationTable: paginationTable, + setPaginationTable: setPaginationTable, + }; + + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle search ----------------------------- */ + const [searchText, setSearchText] = useState(''); + + const handleSearchSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + if (searchText === '') { + searchParams.delete('search'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]); + setAppliedParams(params); + } + }; + + const searchs = { + searchText: searchText, + setSearchText: setSearchText, + handleSearchSubmit: handleSearchSubmit, + }; + + /* -------------------------------- headCell -------------------------------- */ + const headCells: HeadCell[] = [ + { + id: 'memberId', + align: 'left', + label: 'Member ID', + isSort: true, + }, + { + id: 'fullName', + align: 'left', + label: 'Name', + isSort: true, + }, + + { + id: 'division', + align: 'left', + label: 'Divisi', + isSort: true, + }, + /* { id: 'end_date', align: 'center', label: 'End Date', isSort: false, }, */ - { - id: 'status', - align: 'center', - label: 'Status', - isSort: true, - }, - { - id: 'action', - align: 'right', - label: '', - isSort: false, - }, - - ]; + { + id: 'status', + align: 'center', + label: 'Status', + isSort: true, + }, + { + id: 'action', + align: 'right', + label: '', + isSort: false, + }, + ]; - const [open, setOpen] = useState(null); + const [open, setOpen] = useState(null); - const handleOpen = (event: React.MouseEvent) => { + const handleOpen = (event: React.MouseEvent) => { setOpen(event.currentTarget); - }; + }; - const handleClose = () => { + const handleClose = () => { setOpen(null); - }; + }; - /* const clickHandler = (isDialog: string) => { + /* const clickHandler = (isDialog: string) => { switch (isDialog) { - + case 'infoDetail': setDialogTitle('Claim Details'); setIsDialog(isDialog); setOpenDialog(true); break; - + default: break; } }; */ - /* -------------------------------------------------------------------------- */ - - + /* -------------------------------------------------------------------------- */ - useEffect(() => { - (async () => { - setIsLoading(true); - - await new Promise((resolve) => setTimeout(resolve, 250)); - - const parameters = - Object.keys(appliedParams).length !== 0 - ? appliedParams - : Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]); - - const response = await axios.get(`${corporateValue}/members`, { - params: { ...parameters }, - }); - - setData( - response.data.data.map((obj: any) => { + useEffect(() => { + (async () => { + setIsLoading(true); + await new Promise((resolve) => setTimeout(resolve, 250)); - return { - ...obj, - - /* memberId: , */ - status: - obj.status === 1 ? ( - - - - ) : ( - - ), - /* action: ( + const parameters = + Object.keys(appliedParams).length !== 0 + ? appliedParams + : Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]); + + const response = await axios.get(`${corporateValue}/members`, { + params: { ...parameters, type: 'claim-report' }, + }); + + setData( + response.data.data.map((obj: any) => ({ + ...obj, + + /* memberId: , */ + status: + obj.status === 1 ? ( + + ) : ( + + ), + /* action: ( clickHandler('infoDetail')}> ), */ - - }; - }) - ); - - setPaginationTable(response.data); - setRowsPerPage(response.data.per_page); - - if (searchParams.get('page')) { - //@ts-ignore - const currentPage = parseInt(searchParams.get('page')) - 1; - - paginationTable.current_page = currentPage; - setPage(currentPage); - } - - setIsLoading(false); - })(); - }, [appliedParams, searchParams, order, orderBy, setSearchParams, corporateValue]); - - return ( - - - + })) + ); - - ); - } - \ No newline at end of file + setPaginationTable(response.data); + setRowsPerPage(response.data.per_page); + + if (searchParams.get('page')) { + //@ts-ignore + const currentPage = parseInt(searchParams.get('page')) - 1; + + paginationTable.current_page = currentPage; + setPage(currentPage); + } + + setIsLoading(false); + })(); + }, [appliedParams, searchParams, order, orderBy, setSearchParams, corporateValue]); + + return ( + + + + ); +} diff --git a/frontend/client-portal/src/sections/claim-report/CardClaimStatus.tsx b/frontend/client-portal/src/sections/claim-report/CardClaimStatus.tsx index fdfd94b5..5349d055 100644 --- a/frontend/client-portal/src/sections/claim-report/CardClaimStatus.tsx +++ b/frontend/client-portal/src/sections/claim-report/CardClaimStatus.tsx @@ -45,7 +45,7 @@ export default function CardClaimStatus({ data }: PropsCardClaimStatus) { {data ? data.map(({ name, value, color }: ClaimStatusType, key) => ( - + )) : defaultData.map(({ name, value, color }: ClaimStatusType, key) => ( - +