client portal update

This commit is contained in:
Muhammad Fajar
2024-01-02 23:29:05 +07:00
parent 4e988200b2
commit 2839d537bd
8 changed files with 155 additions and 142 deletions

View File

@@ -107,19 +107,19 @@ export type TableListProps<DataType> = {
handleStatusChange: (event: SelectChangeEvent) => void;
};
};
filterStartDate: {
filterStartDate?: {
useFilter: boolean;
startDate: string;
setStartDate: Dispatch<SetStateAction<string>>;
handleStartDateChange: (event: FormEvent<HTMLFormElement>) => void;
};
filterEndDate: {
filterEndDate?: {
useFilter: boolean;
endDate: string;
setEndDate: Dispatch<SetStateAction<string>>;
handleEndDateChange: (event: FormEvent<HTMLFormElement>) => void;
};
exportReport: {
exportReport?: {
useExport: boolean;
startDate: string;
endDate: string;

View File

@@ -1,31 +1,30 @@
import { useState } from 'react';
// @mui
import { alpha } from '@mui/material/styles';
import { Box, Divider, Typography, Stack, MenuItem, Avatar } from '@mui/material';
import { Box, Divider, Typography, MenuItem, Avatar } from '@mui/material';
// components
import MenuPopover from '../../../components/MenuPopover';
import { IconButtonAnimate } from '../../../components/animate';
import { useNavigate } from 'react-router-dom';
import useAuth from '../../../hooks/useAuth';
import useLocalStorage from '../../../hooks/useLocalStorage';
import { enqueueSnackbar } from 'notistack';
// ----------------------------------------------------------------------
const MENU_OPTIONS = [
{
label: 'Home',
linkTo: '/',
},
{
label: 'Profile',
linkTo: '/',
},
{
label: 'Settings',
linkTo: '/',
},
];
// const MENU_OPTIONS = [
// {
// label: 'Home',
// linkTo: '/',
// },
// {
// label: 'Profile',
// linkTo: '/',
// },
// {
// label: 'Settings',
// linkTo: '/',
// },
// ];
// ----------------------------------------------------------------------
@@ -34,6 +33,8 @@ export default function AccountPopover() {
const navigate = useNavigate();
const { logout, user } = useAuth();
console.log(user);
const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
setOpen(event.currentTarget);
};
@@ -67,10 +68,7 @@ export default function AccountPopover() {
}),
}}
>
{user && user.user.avatar_url && (<Avatar
src={user ? user.user.avatar_url : ''}
alt={user ? user.user.full_name : ''}
/>)}
<Avatar src={user?.user.avatar_url || ''} alt={user?.user.full_name || ''} />
</IconButtonAnimate>
<MenuPopover
@@ -89,10 +87,10 @@ export default function AccountPopover() {
>
<Box sx={{ my: 1.5, px: 2.5 }}>
<Typography variant="subtitle2" noWrap>
{ user ? user.user.full_name ?? 'Hi, ' : 'Hi, '}
{`Hi, ${user?.user?.full_name || 'User'}`}
</Typography>
<Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
{ user ? user.user.email : 'Please Wait'}
{user ? user.user.email : 'Please Wait'}
</Typography>
</Box>

View File

@@ -13,11 +13,7 @@ import Logo from '../../../components/Logo';
import Iconify from '../../../components/Iconify';
import { IconButtonAnimate } from '../../../components/animate';
//
import Searchbar from './Searchbar';
import AccountPopover from './AccountPopover';
import LanguagePopover from './LanguagePopover';
import ContactsPopover from './ContactsPopover';
import NotificationsPopover from './NotificationsPopover';
import CorporatePopover from './CorporatePopover';
// ----------------------------------------------------------------------
@@ -46,11 +42,11 @@ const RootStyle = styled(AppBar, {
width: `calc(100% - ${NAVBAR.DASHBOARD_COLLAPSE_WIDTH}px)`,
}),
...(isOffset && {
height: HEADER.DASHBOARD_DESKTOP_OFFSET_HEIGHT,
height: HEADER.DASHBOARD_DESKTOP_HEIGHT,
}),
...(verticalLayout && {
width: '100%',
height: HEADER.DASHBOARD_DESKTOP_OFFSET_HEIGHT,
height: HEADER.DASHBOARD_DESKTOP_HEIGHT,
backgroundColor: theme.palette.background.default,
}),
},
@@ -89,15 +85,15 @@ export default function DashboardHeader({
</IconButtonAnimate>
)}
<Searchbar />
{/* <Searchbar /> */}
<Box sx={{ flexGrow: 1 }} />
<Stack direction="row" alignItems="center" spacing={{ xs: 0.5, sm: 1.5 }}>
<CorporatePopover />
<Divider orientation="vertical" flexItem />
<LanguagePopover />
<NotificationsPopover />
<ContactsPopover />
{/* <LanguagePopover /> */}
{/* <NotificationsPopover /> */}
{/* <ContactsPopover /> */}
<AccountPopover />
</Stack>
</Toolbar>

View File

@@ -23,10 +23,8 @@ type Props = {
};
export default function NavbarAccount({ isCollapse }: Props) {
const { user } = useAuth();
// console.log('current user is ', user)
return (
<Link underline="none" color="inherit">
<RootStyle
@@ -36,10 +34,9 @@ export default function NavbarAccount({ isCollapse }: Props) {
}),
}}
>
{user && user.user.avatar_url && (<Avatar
src={user ? user.user.avatar_url : ''}
alt={user ? user.user.full_name : ''}
/>)}
{user && user.user.avatar_url && (
<Avatar src={user?.user.avatar_url || ''} alt={user?.user.full_name || ''} />
)}
<Box
sx={{
@@ -55,10 +52,10 @@ export default function NavbarAccount({ isCollapse }: Props) {
}}
>
<Typography variant="subtitle2" noWrap>
{ user ? user.user.full_name ?? 'Hi, ' : 'Hi, '}
{`Hi, ${user?.user?.full_name || 'User'}`}
</Typography>
<Typography variant="body2" noWrap sx={{ color: 'text.secondary', fontSize: '11px' }}>
{ user ? user.user.email : 'Please Wait'}
{user ? user.user.email : 'Please Wait'}
</Typography>
</Box>
</RootStyle>

View File

@@ -24,13 +24,7 @@ import { HeadCell, Order, PaginationTableProps } from '../../@types/table';
import { useLocation, useSearchParams } from 'react-router-dom';
import palette from '../../theme/palette';
import { fSplit } from '../../utils/formatNumber';
// const itemList = [
// { info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
// { info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
// { info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
// { info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
// ];
import { closeSnackbar, enqueueSnackbar } from 'notistack';
/* ------------------------------ default data ------------------------------ */
type DataMember = {
@@ -175,7 +169,7 @@ export default function Index() {
};
const searchs = {
// useSearchs: true,
useSearchs: false,
searchText: searchText,
setSearchText: setSearchText,
handleSearchSubmit: handleSearchSubmit,
@@ -257,6 +251,11 @@ export default function Index() {
useEffect(() => {
(async () => {
setIsLoading(true);
const loadNotif = enqueueSnackbar('Data sedang di load, harap tunggu!', {
variant: 'info',
autoHideDuration: null,
anchorOrigin: { horizontal: 'right', vertical: 'bottom' },
});
const parameters =
Object.keys(appliedParams).length !== 0
@@ -343,7 +342,12 @@ export default function Index() {
setPage(currentPage);
}
closeSnackbar(loadNotif);
setIsLoading(false);
enqueueSnackbar('Data sudah di load!', {
variant: 'info',
anchorOrigin: { horizontal: 'right', vertical: 'bottom' },
});
})();
}, [appliedParams, searchParams, order, orderBy, setSearchParams, corporateValue]);

View File

@@ -20,20 +20,20 @@ import DialogClaimSubmitMember from './DialogClaimSubmitMember';
/* ---------------------------------- types --------------------------------- */
type DataMember = {
id: number;
fullName: string;
memberId: string;
limit: {
current: number;
total: number;
percentage: number;
};
avatar?: {
url?: string;
title?: string;
};
};
// type DataMember = {
// id: number;
// fullName: string;
// memberId: string;
// limit: {
// current: number;
// total: number;
// percentage: number;
// };
// avatar?: {
// url?: string;
// title?: string;
// };
// };
type CardPolicyProps = {
data: {
@@ -99,7 +99,7 @@ export default function CardPolicy(props: CardPolicyProps) {
const [dialogTitle, setDialogTitle] = useState('');
const [isDialog, setIsDialog] = useState('');
const { limit, topUpLimit, members } = props.data || {};
const { limit, topUpLimit } = props.data || {};
if (!limit || !topUpLimit) {
return null;
}
@@ -178,14 +178,14 @@ export default function CardPolicy(props: CardPolicyProps) {
>
Submit Claim
</Button>
<Button
{/* <Button
variant="contained"
startIcon={<Iconify icon="heroicons-solid:cash" />}
fullWidth={true}
onClick={() => clickHandler('topUpLimit')}
>
Top Up
</Button>
</Button> */}
</Stack>
</>

View File

@@ -7,11 +7,12 @@ import {
LinearProgress,
linearProgressClasses,
Stack,
Skeleton,
} from '@mui/material';
// components
import Iconify from '../../components/Iconify';
// React
import { useState } from 'react';
import { Fragment, useState } from 'react';
// utils
import { fCurrency, fSplit } from '../../utils/formatNumber';
/* -------------------------------- sections -------------------------------- */
@@ -20,23 +21,23 @@ import DialogClaimSubmitMember from './DialogClaimSubmitMember';
/* ---------------------------------- types --------------------------------- */
type DataMember = {
id: number;
fullName: string;
memberId: string;
limit: {
current: number;
total: number;
percentage: number;
};
avatar?: {
url?: string;
title?: string;
};
};
// type DataMember = {
// id: number;
// fullName: string;
// memberId: string;
// limit: {
// current: number;
// total: number;
// percentage: number;
// };
// avatar?: {
// url?: string;
// title?: string;
// };
// };
type CardPolicyProps = {
data: {
data?: {
limit: {
myLimit: {
balance: number;
@@ -61,10 +62,6 @@ type CardPolicyProps = {
};
maxTopUp: number;
};
members: {
memberId: string;
memberFullName: string;
};
};
};
@@ -99,10 +96,7 @@ export default function CardPolicy(props: CardPolicyProps) {
const [dialogTitle, setDialogTitle] = useState('');
const [isDialog, setIsDialog] = useState('');
const { limit, topUpLimit, members } = props.data || {};
if (!limit || !topUpLimit) {
return null;
}
const { limit, topUpLimit } = props.data || {};
const clickHandler = (isDialog: string) => {
switch (isDialog) {
@@ -124,70 +118,108 @@ export default function CardPolicy(props: CardPolicyProps) {
return (
<RootBalanceStyle>
<>
<Stack direction="row" justifyContent="space-between" sx={{ mb: 1 }}>
<div>
<Fragment>
<Stack direction="row" justifyContent="space-between" sx={{ mb: 1 }} spacing={2}>
<Stack>
<Typography variant="body2" component="span" sx={{ opacity: 0.72 }}>
Total Limit
{limit ? (
'Total Limit'
) : (
<Skeleton sx={{ bgcolor: 'grey.300' }} animation="wave" width={75} />
)}
</Typography>
<Typography sx={{ typography: 'body2' }}>
{fCurrency(limit.myLimit ? limit.myLimit.balance : 0)}
{limit ? (
fCurrency(limit.myLimit.balance ?? 0)
) : (
<Skeleton sx={{ bgcolor: 'grey.300' }} animation="wave" width={150} />
)}
</Typography>
<Typography sx={{ typography: 'caption', color: '#919EAB' }}>
/ {fSplit(limit.myLimit ? limit.myLimit.total : 0)}
{limit ? (
`/ ${fSplit(limit.myLimit.total ?? 0)}`
) : (
<Skeleton sx={{ bgcolor: 'grey.300' }} animation="wave" />
)}
</Typography>
</div>
</Stack>
<Stack direction="row" alignItems="center" justifyContent="center">
<Typography variant="h5" sx={{ ml: 0.5 }}>
{limit.myLimit ? limit.myLimit.percentage : 0}%
{limit ? (
`${limit.myLimit.percentage ?? 0}%`
) : (
<Skeleton sx={{ bgcolor: 'grey.300' }} animation="wave" width={70} />
)}
</Typography>
</Stack>
</Stack>
<BorderLinearProgress
variant="determinate"
value={limit.myLimit ? limit.myLimit.percentage : 0}
sx={{ mb: 1 }}
/>
{limit ? (
<BorderLinearProgress
variant="determinate"
value={limit.myLimit.percentage ?? 0}
sx={{ mb: 1 }}
/>
) : (
<Skeleton sx={{ bgcolor: 'grey.300' }} animation="wave" />
)}
<Stack sx={{ backgroundColor: '#B2E8E8', paddingY: 1, paddingX: 1.5, mb: 2 }}>
<Typography sx={{ typography: 'caption', display: 'flex', alignItems: 'center' }}>
<Iconify
icon="bxs:lock-alt"
width={12}
height={13}
sx={{ color: '#424242', marginRight: '6px' }}
/>
<Typography variant="caption" component="span">
Lock Fund ( {limit.lockLimit ? limit.lockLimit.percentage : 0}% )
</Typography>
{limit ? (
<Fragment>
<Iconify
icon="bxs:lock-alt"
width={12}
height={13}
sx={{ color: '#424242', marginRight: '6px' }}
/>
<Typography variant="caption" component="span">
Lock Fund ( {limit.lockLimit.percentage ?? 0}% )
</Typography>
</Fragment>
) : (
<Skeleton sx={{ bgcolor: 'grey.300' }} animation="wave" width={130} />
)}
</Typography>
<Typography sx={{ typography: 'caption', color: '#637381' }}>
{fSplit(limit.lockLimit ? limit.lockLimit.balance : 0)} /{' '}
{fSplit(limit.myLimit ? limit.myLimit.total : 0)}
{limit ? (
`${fSplit(limit.lockLimit.balance ?? 0)} / ${fSplit(limit.myLimit.total ?? 0)}`
) : (
<Skeleton sx={{ bgcolor: 'grey.300' }} animation="wave" width={120} />
)}
</Typography>
</Stack>
<Stack direction="row" spacing={2}>
<Button
variant="outlined"
startIcon={<Iconify icon="bi:clipboard-check-fill" />}
fullWidth={true}
onClick={() => clickHandler('submitClaim')}
>
Submit Claim
</Button>
<Button
{limit ? (
<Button
variant="outlined"
startIcon={<Iconify icon="bi:clipboard-check-fill" />}
fullWidth={true}
onClick={() => clickHandler('submitClaim')}
>
Submit Claim
</Button>
) : (
<Skeleton
sx={{ bgcolor: 'grey.300' }}
animation="wave"
height={'36px'}
width={'100%'}
/>
)}
{/* <Button
variant="contained"
startIcon={<Iconify icon="heroicons-solid:cash" />}
fullWidth={true}
onClick={() => clickHandler('topUpLimit')}
>
Top Up
</Button>
</Button> */}
</Stack>
</>
</Fragment>
{isDialog === 'submitClaim' && (
<DialogClaimSubmitMember

View File

@@ -1,27 +1,13 @@
import axios from 'axios';
// config
import { HOST_API } from '../config';
import { getSession } from './token';
// ----------------------------------------------------------------------
const token = getSession();
const axiosInstance = axios.create({
baseURL: HOST_API,
// headers: {
// 'X-Requested-With': 'XMLHttpRequest',
// },
// withCredentials: true,
// headers: {
// Authorization: `Bearer ${token}`
// }
});
axiosInstance.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error) || 'Something went wrong')
(error) => Promise.reject(error || 'Something went wrong')
);
export default axiosInstance;