diff --git a/Modules/Client/Http/Controllers/Api/CorporateMemberController.php b/Modules/Client/Http/Controllers/Api/CorporateMemberController.php
index e711c470..05032d18 100644
--- a/Modules/Client/Http/Controllers/Api/CorporateMemberController.php
+++ b/Modules/Client/Http/Controllers/Api/CorporateMemberController.php
@@ -28,6 +28,9 @@ class CorporateMemberController extends Controller
public function index(Request $request, $corporate_id)
{
switch ($request->input('type')) {
+ case 'employee-data':
+ $members = $this->corporateMemberService->getAllMemberAlarmCenter($corporate_id, $request);
+ return response()->json(Helper::paginateResources(DashboardMemberAlarmResources::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/Http/Controllers/Api/DataController.php b/Modules/Client/Http/Controllers/Api/DataController.php
index f824b1e2..ae383356 100644
--- a/Modules/Client/Http/Controllers/Api/DataController.php
+++ b/Modules/Client/Http/Controllers/Api/DataController.php
@@ -46,12 +46,15 @@ class DataController extends Controller
Member::where('person_id', $person_id)->update([
'name' => $familyMember['name'],
'email' => $familyMember['email'],
+ 'relation_with_principal' => $familyMember['relation_with_principal'],
+ 'birth_date' => $familyMember['birth_date'],
]);
Person::where('id', $person_id)->update([
'name' => $familyMember['name'],
'email' => $familyMember['email'],
'phone' => $familyMember['phone'],
+ 'birth_date' => $familyMember['birth_date']
]);
}
diff --git a/frontend/client-portal/src/layouts/dashboard/navbar/NavConfig.tsx b/frontend/client-portal/src/layouts/dashboard/navbar/NavConfig.tsx
index f7cfa648..633d8a1b 100644
--- a/frontend/client-portal/src/layouts/dashboard/navbar/NavConfig.tsx
+++ b/frontend/client-portal/src/layouts/dashboard/navbar/NavConfig.tsx
@@ -26,6 +26,10 @@ const navConfig = [
{
subheader: 'Case Management',
items: [
+ {
+ title: 'Employee Data',
+ path: '/employee-data',
+ },
{
title: 'Alarm Center',
path: '/alarm-center',
diff --git a/frontend/client-portal/src/pages/EmployeeData/Index.tsx b/frontend/client-portal/src/pages/EmployeeData/Index.tsx
new file mode 100644
index 00000000..64129bbc
--- /dev/null
+++ b/frontend/client-portal/src/pages/EmployeeData/Index.tsx
@@ -0,0 +1,126 @@
+/* ---------------------------------- react --------------------------------- */
+import { useState, SyntheticEvent } from 'react';
+/* ---------------------------------- @mui ---------------------------------- */
+import { Box, Tabs, Tab, Container, Grid, Card, Stack } from '@mui/material';
+import { styled } from '@mui/material/styles';
+/* ------------------------------- components ------------------------------- */
+import Page from '../../components/Page';
+/* ---------------------------------- hooks --------------------------------- */
+import useSettings from '../../hooks/useSettings';
+import List from './List';
+import ServiceMonitoring from './ServiceMonitoring';
+import UserProfile from './UserProfile';
+
+import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
+
+/* ------------------------------ tabs setting ------------------------------ */
+
+/* ---------------------------------- types --------------------------------- */
+
+interface TabPanelProps {
+ children?: React.ReactNode;
+ index: number;
+ value: number;
+}
+
+interface StyledTabsProps {
+ children?: React.ReactNode;
+ value: number;
+ onChange: (event: React.SyntheticEvent, newValue: number) => void;
+}
+
+interface StyledTabProps {
+ label: string;
+ icon?: string | React.ReactElement;
+}
+
+/* -------------------------------- tab style ------------------------------- */
+
+function TabPanel(props: TabPanelProps) {
+ const { children, value, index, ...other } = props;
+
+ return (
+
+ {value === index && {children}}
+
+ );
+}
+
+function a11yProps(index: number) {
+ return {
+ id: `simple-tab-${index}`,
+ 'aria-controls': `simple-tabpanel-${index}`,
+ };
+}
+
+const StyledTabs = styled((props: StyledTabsProps) => )({
+ backgroundColor: '#F4F6F8',
+ padding: '0 24px',
+ '& .MuiTabs-indicator': {
+ display: 'flex',
+ justifyContent: 'space-between',
+ backgroundColor: 'transparent',
+ },
+ '& .MuiTabs-indicatorSpan': {
+ maxWidth: 40,
+ backgroundColor: '#635ee7',
+ },
+});
+
+const StyledTab = styled((props: StyledTabProps) => )(
+ ({ theme }) => ({
+ textTransform: 'none',
+ fontWeight: 600,
+ color: theme.palette.grey[600],
+ marginRight: '5rem',
+ '&.Mui-selected': {
+ color: '#212B36',
+ borderBottom: '2px solid ' + theme.palette.primary.main,
+ },
+ '&:hover': {
+ color: '#212B36',
+ opacity: 1,
+ borderBottom: '2px solid ' + theme.palette.primary.main,
+ },
+ })
+);
+
+/* -------------------------------------------------------------------------- */
+
+export default function Drugs() {
+ const { themeStretch } = useSettings();
+
+ const [value, setValue] = useState(0);
+ const handleChange = (event: SyntheticEvent, newValue: number) => {
+ setValue(newValue);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/client-portal/src/pages/EmployeeData/List.tsx b/frontend/client-portal/src/pages/EmployeeData/List.tsx
new file mode 100644
index 00000000..b6b8a19b
--- /dev/null
+++ b/frontend/client-portal/src/pages/EmployeeData/List.tsx
@@ -0,0 +1,402 @@
+/* ---------------------------------- @mui ---------------------------------- */
+import {
+ Paper,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ TextField,
+ Stack,
+ Button,
+ TableSortLabel,
+ Box,
+ MenuItem
+} from '@mui/material';
+import { visuallyHidden } from '@mui/utils';
+/* ---------------------------------- axios --------------------------------- */
+// import axios from 'axios';
+import axios from '../../utils/axios';
+/* ---------------------------------- react --------------------------------- */
+import { useContext, useEffect, useState } from 'react';
+
+/* -------------------------------- component ------------------------------- */
+import Iconify from '../../components/Iconify';
+import BaseTablePagination from '../../components/BaseTablePagination';
+import TableComponent from '../../components/Table';
+
+/* ---------------------------------- 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, Link } from 'react-router-dom';
+import { fDate } from '../../utils/formatTime';
+import { format } from 'date-fns';
+import Typography from '@mui/material/Typography';
+import TableMoreMenu from '../../components/table/TableMoreMenu';
+import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
+import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
+
+
+/* ---------------------------------- 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: 'start_date',
+ align: 'left',
+ label: 'Start Date',
+ isSort: true,
+ },
+ {
+ id: 'end_date',
+ align: 'left',
+ label: 'End Date',
+ isSort: false,
+ },
+ {
+ id: 'status',
+ align: 'left',
+ label: 'Status',
+ isSort: true,
+ },
+ {
+ id: 'view',
+ align: 'center',
+ label: '',
+ isSort: true,
+ },
+ ];
+ /* -------------------------------------------------------------------------- */
+
+ 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?type=employee-data`, {
+ params: { ...parameters },
+ });
+
+ console.log(response.data.data);
+
+ setData(
+ response.data.data.map((obj: any) => {
+ return {
+ ...obj,
+ // memberId:
+ //
+ // ,
+ status:
+ obj.status === 1 ? (
+
+ ) : (
+
+ ),
+ start_date:
+ theme.palette.grey[300],
+ borderRadius: '4px',
+ width: '70%',
+ }}
+ >
+ {obj.start_date ? format(new Date(obj.start_date), "dd MMMM yyyy HH:mm:ss") : ''}
+
+ ,
+ end_date:
+ theme.palette.grey[300],
+ borderRadius: '4px',
+ width: '70%',
+ }}
+ >
+ {obj.end_date ? format(new Date(obj.end_date), "d MMMM yyyy HH:mm:ss") : ''}
+
+ ,
+ fullName:
+
+ {obj.fullName}
+
+ ,
+ memberId:
+
+ {obj.memberId}
+
+ ,
+ view:
+
+
+ >
+ } />
+ };
+ })
+ );
+
+ 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/pages/EmployeeData/UserProfile.tsx b/frontend/client-portal/src/pages/EmployeeData/UserProfile.tsx
new file mode 100644
index 00000000..e5afd27e
--- /dev/null
+++ b/frontend/client-portal/src/pages/EmployeeData/UserProfile.tsx
@@ -0,0 +1,66 @@
+// mui
+import { IconButton, Container, Grid, Stack, Typography } from '@mui/material';
+// components
+import Page from '../../components/Page';
+import Iconify from '../../components/Iconify';
+// utils
+import useSettings from '../../hooks/useSettings';
+// section
+import CardPersonalInformation from '../../sections/alarm-center/user-profile/CardPersonalInformation';
+import CardFamilyInformation from '../../sections/alarm-center/user-profile/CardFamilyInformation';
+import CardPolicyNumber from '../../sections/alarm-center/user-profile/CardPolicyNumber';
+import CardBenefitSummary from '../../sections/alarm-center/user-profile/CardBenefitSummary';
+import CardClaimHistory from '../../sections/alarm-center/user-profile/CardClaimHistory';
+// 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';
+
+// ----------------------------------------------------------------------
+
+export default function UserProfile() {
+ const { themeStretch } = useSettings();
+ // const navigate = useNavigate();
+ const [data, setData] = useState();
+
+ const { corporateValue } = useContext(UserCurrentCorporateContext);
+ const { id } = useParams();
+
+ useEffect(() => {
+ axios
+ .get(corporateValue + '/members/' + id)
+ .then((response) => {
+ setData(response.data);
+ })
+ .catch((error) => {
+ console.error(error);
+ });
+ }, []);
+
+// console.log('data', data);
+
+ return (
+
+
+
+ {/* navigate()}>
+
+ */}
+
+ Profile
+
+
+ {/* Row 1 */}
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/client-portal/src/routes/index.tsx b/frontend/client-portal/src/routes/index.tsx
index 1a10761c..5f7db4af 100644
--- a/frontend/client-portal/src/routes/index.tsx
+++ b/frontend/client-portal/src/routes/index.tsx
@@ -73,6 +73,26 @@ export default function Router() {
},
],
},
+ {
+ path: '/employee-data',
+ element: (
+
+
+
+
+
+ ),
+ children: [
+ {
+ element: ,
+ index: true,
+ },
+ {
+ path: '/employee-data/user-profile/:id',
+ element: ,
+ }
+ ],
+ },
{
path: '/alarm-center',
element: (
@@ -196,6 +216,10 @@ const Login = Loadable(lazy(() => import('../pages/auth/Login')));
const Dashboard = Loadable(lazy(() => import('../pages/Dashboard/Index')));
const NotFound = Loadable(lazy(() => import('../pages/Page404')));
+// Employee Data
+const EmployeeData = Loadable(lazy(() => import('../pages/EmployeeData/Index')));
+const EmployeeDataUserProfile = Loadable(lazy(() => import('../pages/EmployeeData/UserProfile')));
+
// Alarm Center
const AlarmCenter = Loadable(lazy(() => import('../pages/AlarmCenter/Index')));
const AlarmCenterServiceMonitoring = Loadable(
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 575ffc77..ad1ce189 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
@@ -1,8 +1,11 @@
// mui
-import { Button, Card, Stack, Typography, Grid, Switch, TextField } from '@mui/material';
+import { FormHelperText, FormControl, Button, Card, Stack, Typography, Grid, Switch, TextField, IconButton, Select, MenuItem, InputLabel } from '@mui/material';
+import CloseIcon from '@mui/icons-material/Close';
+import { DatePicker, LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers';
+import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
// components
import Iconify from '../../../components/Iconify';
-import { fDate } from '../../../utils/formatTime';
+import { fDate, fPostFormat } from '../../../utils/formatTime';
import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
import { useContext, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
@@ -16,10 +19,39 @@ export default function CardFamilyInformation({ data }) {
const [editedFamilyData, setEditedFamilyData] = useState({});
const { id } = useParams();
+ //Check Required
+ //State Field
+ const [nameField, setNameField] = useState('');
+ const [relationshipField, setRelationshipField] = useState('');
+ const [birthDateField, setBirthDateField] = useState('');
+ const [birthDateFieldCheck, setBirthDateFieldCheck] = useState(1);
+ const [emailField, setEmailField] = useState('');
+ const [emailFieldCheck, setEmailFieldCheck] = useState(false);
+ const [phoneField, setPhoneField] = useState('');
+ //State Field Error
+ const [nameFieldError, setNameFieldError] = useState('');
+ const [relationshipFieldError, setRelationshipFieldError] = useState('');
+ const [birthDateFieldError, setBirthDateFieldError] = useState('');
+ const [emailFieldError, setEmailFieldError] = useState('');
+ const [phoneFieldError, setPhoneFieldError] = useState('');
+
const handleEditData = (index) => {
setEditIndex(index);
setEditedFamilyData(data?.family[index] || {});
setOpenDialog(true);
+
+ setNameField(data?.family[index].name);
+ setRelationshipField(data?.family[index].relation_with_principal);
+ setBirthDateField(data?.family[index].birth_date);
+ setEmailField(data?.family[index].email);
+ setEmailFieldCheck(isValidEmail(data?.family[index].email));
+ setPhoneField(data?.family[index].phone);
+
+ setNameFieldError('');
+ setRelationshipFieldError('');
+ setBirthDateFieldError('');
+ setEmailFieldError('');
+ setPhoneFieldError('');
};
const handleCloseDialog = () => {
@@ -37,10 +69,14 @@ export default function CardFamilyInformation({ data }) {
updatedFamily[editIndex] = editedFamilyData;
// Perbarui data utama dengan data keluarga yang telah diperbarui
- const updatedData = { ...data, family: updatedFamily };
+ const updatedData = { ...data, family: updatedFamily[editIndex]};
+
+ updatedData.family.birth_date = fPostFormat(updatedData.family.birth_date, 'yyyy-MM-dd') ;
+
+ const familyArray = [updatedData.family];
axios
- .post('/update-family', updatedData.family)
+ .post('/update-family', familyArray)
.then((response) => {
enqueueSnackbar('Data updated successfully', { variant: 'success' });
setOpenDialog(false);
@@ -55,6 +91,17 @@ export default function CardFamilyInformation({ data }) {
}
}
};
+
+ console.log(data?.family);
+
+ const isValidEmail = (email) => {
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ return emailRegex.test(email);
+ };
+
+ const isRequiredFieldsFilled = () => {
+ return nameField.trim() !== '' && relationshipField.trim() !== '' && birthDateField !== '' && birthDateFieldCheck !== 0 && emailField.trim() !== '' && emailFieldCheck && phoneField.trim() !== '';
+ };
return (
@@ -66,17 +113,17 @@ export default function CardFamilyInformation({ data }) {
sx={{ paddingY: 1, paddingX: 3 }}
>
Beneficiary / Family
- } disabled>Add Member
+ {/*} disabled>Add Member*/}
{/* Stack 2 */}
-
+
{data?.family.map((familyMember, index) => (
{/* Stack 1 */}
+
+ {familyMember?.name}
+
+
{familyMember.relation_with_principal === 'H'
? 'Husband'
: familyMember.relation_with_principal === 'W'
@@ -101,29 +152,72 @@ export default function CardFamilyInformation({ data }) {
? 'Daughter'
: ''}
+
{/* Row 2 */}
-
+
Suspend
-
- {familyMember?.name}
-
-
- {familyMember?.birth_date ? fDate(familyMember?.birth_date) : ''}
-
-
- {familyMember?.phone}
-
- {/* Stack 2 */}
+
+ Date of Birth
+
+
+ {familyMember?.birth_date ? fDate(familyMember?.birth_date) : ''}
+
+
+
+
+ Email
+
+
+ {familyMember?.email}
+
+
+
+
+ Phone Number
+
+
+ {familyMember?.phone}
+
+
+
+
+ Status
+
+
+ {
+ familyMember?.phone === '1'
+ ? 'Active'
+ : 'Inactive'
+ }
+
+
+ {/* Stack 2 */}
+
} disabled>
Remove
@@ -136,32 +230,117 @@ export default function CardFamilyInformation({ data }) {
))}
{/* Dialog */}
-