This commit is contained in:
2023-06-13 11:33:42 +07:00
parent cbc7dfdb99
commit 8f532e655f
10 changed files with 320 additions and 7 deletions

View File

@@ -13,10 +13,14 @@ class MemberController extends Controller
* Display a listing of the resource.
* @return Renderable
*/
public function index()
public function index(Request $request)
{
return Member::query()
->with('currentPlan')
->when($request->search, function ($query, $search) {
return $query->where('name', 'LIKE', '%' . $search . '%')
->orWhere('member_id', 'LIKE', '%' . $search . '%');
})
->with('currentPlan', 'currentCorporate')
->paginate();
}

View File

@@ -29,7 +29,8 @@ class MemberResource extends JsonResource
'code' => $currentMemberPlan->plan->code ?? null,
'start' => $currentMemberPlan->start,
'end' => $currentMemberPlan->end,
'limit' => $this->currentPlan->limit_rules
'limit' => $this->currentPlan->limit_rules,
'limit_consultation' => 6
] : null,
'policy_code' => $this->currentPolicy?->code ?? null,
'corporate' => [

View File

@@ -224,6 +224,7 @@ class Plan extends Model
return $this->belongsTo(CorporatePlan::class);
}
// public function Corporate()
// {
// return $this->belongsTo(Corporate::class);

View File

@@ -16,7 +16,7 @@ return new class extends Migration
Schema::table('claim_requests', function (Blueprint $table) {
//
$table->string('service_code')->after('payment_type')->nullable();
$table->string('policy_id')->after('service_code')->nullable();
$table->unsignedBigInteger('policy_id')->after('service_code')->nullable();
});
}

View File

@@ -74,7 +74,10 @@ const navConfig = [
},
{
title: 'CUSTOMER SERVICES',
children: [{ title: 'Request', path: '/cs-request' }],
children: [
{ title: 'Request', path: '/cs-request' },
{ title: 'Membership', path: '/cs-membership' },
],
},
{
title: 'REPORT',

View File

@@ -84,7 +84,7 @@ export default function List() {
onChange={handleSearchChange}
value={searchText}
/>
<Tooltip title="Export Excel">
<Tooltip title="Benefit Usage Report">
<Button variant="outlined" startIcon={<AssessmentIcon />} sx={{ p: 1.8 }} onClick={handleGetData}/>
</Tooltip>
</Stack>

View File

@@ -0,0 +1,267 @@
// @mui
import {
Box,
Button,
Card,
Collapse,
IconButton,
MenuItem,
Table,
TableBody,
TableCell,
TableRow,
TextField,
Typography,
Stack,
Menu,
ButtonGroup,
Tooltip,
} from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import AddIcon from '@mui/icons-material/Add';
import AssessmentIcon from '@mui/icons-material/Assessment';
import UploadIcon from '@mui/icons-material/Upload';
import CancelIcon from '@mui/icons-material/Cancel';
// hooks
import React, { ChangeEvent, useEffect, useRef, useState } from 'react';
import { Link, Navigate, useNavigate, useSearchParams } from 'react-router-dom';
// components
import axios from '../../../utils/axios';
import { LaravelPaginatedData, LaravelPaginatedDataDefault } from '../../../@types/paginated-data';
import DataTable from '../../../components/LaravelTable';
import { fCurrency } from '../../../utils/formatNumber';
import EditRoundedIcon from '@mui/icons-material/EditRounded';
import { Chip } from '@mui/material';
import Iconify from '@/components/Iconify';
import { enqueueSnackbar } from 'notistack';
export default function List() {
const [searchParams, setSearchParams] = useSearchParams();
const [importResult, setImportResult] = useState(null);
const navigate = useNavigate();
function SearchInput(props: any) {
// SEARCH
const searchInput = useRef<HTMLInputElement>(null);
const [searchText, setSearchText] = useState('');
const handleSearchChange = (event: any) => {
const newSearchText = event.target.value ?? '';
setSearchText(newSearchText);
};
const handleSearchSubmit = (event: any) => {
event.preventDefault();
props.onSearch({ search: searchText }); // Trigger to Parent
};
const handleGetData = (type :string) => {
axios.get(`members`)
.then((response) => {
const link = document.createElement('a');
link.href = response.data.data.file_url;
link.setAttribute('download', response.data.data.file_name);
document.body.appendChild(link);
link.click();
})
}
useEffect(() => {
// Trigger First Search
setSearchText(searchParams.get('search') ?? '');
}, []);
return (
<form onSubmit={handleSearchSubmit} style={{ width: '100%' }}>
<Stack direction={'row'} spacing={2} sx={{ mb: 2 }}>
<TextField
id="search-input"
ref={searchInput}
label="Search"
variant="outlined"
fullWidth
onChange={handleSearchChange}
value={searchText}
/>
</Stack>
</form>
);
}
function ImportForm(props: any) {
// IMPORT
// Create Button Menu
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
return (
<div>
<Stack direction={'row'} spacing={2} sx={{ p: 2 }}>
<SearchInput onSearch={applyFilter} />
{/* <Button
variant="outlined"
startIcon={<AddIcon />}
sx={{ p: 1.8 }}
onClick={() => {
navigate('/claims/create');
}}
>
Create
</Button> */}
</Stack>
</div>
);
}
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = useState(true);
const [dataTableData, setDataTableData] = useState<LaravelPaginatedData>(
LaravelPaginatedDataDefault
);
const loadDataTableData = async (appliedFilter: any | null = null) => {
setDataTableLoading(true);
const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]);
const response = await axios.get('/members', { params: filter });
// console.log(response.data);
setDataTableLoading(false);
setDataTableData(response.data);
};
const applyFilter = async (searchFilter: { search: string }) => {
await loadDataTableData(searchFilter);
setSearchParams(searchFilter);
};
const handlePageChange = (event: ChangeEvent, value: number): void => {
const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]);
loadDataTableData(filter);
setSearchParams(filter);
};
useEffect(() => {
loadDataTableData();
}, []);
const headStyle = {
fontWeight: 'bold',
};
// Called on every row to map the data to the columns
function createData(data: any): any {
return {
...data,
};
}
{
/* ------------------ TABLE ROW ------------------ */
}
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
{/* <TableCell>
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell> */}
<TableCell align="left">{row.member_id}</TableCell>
<TableCell align="left">{row.person?.name}</TableCell>
<TableCell align="left">{row.current_corporate?.name}</TableCell>
<TableCell align="left">{row.person?.nik}</TableCell>
<TableCell align="left">{row.current_plan?.code}</TableCell>
<TableCell align="left">{row.active == 1 ? 'Active' : 'Inactive'}</TableCell>
<TableCell align="center">
{row.member_id == 'draft' && (<Chip label='Draft' color="default" variant="outlined" />)}
{row.member_id == 'requested' && (<Chip label='Requested' color="primary" />)}
{row.member_id == 'received' && (<Chip label='Received' color="success" variant='outlined' />)}
{row.member_id == 'approved' && (<Chip label='Approved' color="success" />)}
{row.member_id == 'postpone' && (<Chip label='Postpone' color="primary" variant="outlined" />)}
{row.member_id == 'paid' && (<Chip label='Paid' color="warning" />)}
{row.member_id == 'declined' && (<Chip label='Declined' color="error" />)}
</TableCell>
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={99}>
<Collapse in={open} timeout="auto" unmountOnExit>
{/* <Box sx={{ borderBottom: 1 }}>
<Typography variant="body2" gutterBottom component="div">
Description : {row.description}
</Typography>
</Box> */}
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
{
/* ------------------ END TABLE ROW ------------------ */
}
function TableContent() {
return (
<Table aria-label="collapsible table">
{/* ------------------ TABLE HEADER ------------------ */}
<TableBody>
<TableRow>
{/* <TableCell style={headStyle} align="left">Detail</TableCell> */}
<TableCell style={headStyle} align="left">MemberID</TableCell>
<TableCell style={headStyle} align="left">Name</TableCell>
<TableCell style={headStyle} align="left">Corporate Name</TableCell>
<TableCell style={headStyle} align="left">NIK</TableCell>
<TableCell style={headStyle} align="left">Plan</TableCell>
<TableCell style={headStyle} align="left">Status</TableCell>
</TableRow>
</TableBody>
{/* ------------------ END TABLE HEADER ------------------ */}
{/* ------------------ TABLE ROW ------------------ */}
{dataTableIsLoading ? (
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
Loading
</TableCell>
</TableRow>
</TableBody>
) : dataTableData.data.length === 0 ? (
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
No Data
</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData.data.map((row) => (
<Row key={row.id} row={row} />
))}
</TableBody>
)}
{/* ------------------ END TABLE ROW ------------------ */}
</Table>
);
}
return (
<Card>
<ImportForm />
<DataTable
isLoading={dataTableIsLoading}
lastRequest={0}
data={dataTableData}
handlePageChange={handlePageChange}
TableContent={<TableContent />}
/>
</Card>
);
}

View File

@@ -0,0 +1,30 @@
import { Card, Stack } from "@mui/material";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import Page from "../../../components/Page";
import List from "./List";
export default function Claims() {
const pageTitle = 'Claim Request';
return (
<Page title={ pageTitle } sx={{ mx: 2}}>
<HeaderBreadcrumbs
heading={ pageTitle }
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Claim Request',
href: '/claim-requests',
},
]}
/>
{/* <Stack> */}
<List />
{/* </Stack> */}
</Page>
);
}

View File

@@ -310,6 +310,10 @@ export default function Router() {
path: 'profile',
element: <Profile />,
},
{
path: 'cs-membership',
element: <Membership />,
},
],
},
// {
@@ -440,4 +444,7 @@ const Claims = Loadable(lazy(() => import('../pages/Claims/Index')));
const ClaimsCreate = Loadable(lazy(() => import('../pages/Claims/CreateUpdate')));
const ClaimShow = Loadable(lazy(() => import('../pages/Claims/Show')));
const ClaimRequests = Loadable(lazy(() => import('../pages/ClaimRequests/Index')));
const ClaimRequests = Loadable(lazy(() => import('../pages/ClaimRequests/Index')));
const Membership = Loadable(lazy(() => import('../pages/Service/Membership/index')));