148 lines
3.8 KiB
React
148 lines
3.8 KiB
React
import { ArrowBack, Search } from '@mui/icons-material';
|
|
import { LoadingButton } from '@mui/lab';
|
|
import {
|
|
Box,
|
|
Grid,
|
|
InputAdornment,
|
|
TextField,
|
|
Typography,
|
|
} from '@mui/material';
|
|
import { debounce } from 'lodash';
|
|
import React, { useMemo } from 'react';
|
|
import { useNavigate } from 'react-router';
|
|
import { pxToRem } from '../theme/typography';
|
|
import { useStyles } from './styles/pageHeaderStyles';
|
|
|
|
function PageHeader({
|
|
showGoBack,
|
|
pageTitle,
|
|
hideAddButton = false,
|
|
addButtonTitle,
|
|
addButtonIcon,
|
|
buttonVariant = 'contained',
|
|
onAddButtonClick,
|
|
addButtonDisabled,
|
|
extraComponent,
|
|
showSearch,
|
|
onSearch,
|
|
searchPlaceholder,
|
|
isDetailPage,
|
|
addButtonLoading,
|
|
handleGoBack,
|
|
secondaryButton,
|
|
customChips,
|
|
titleAlignItems,
|
|
}) {
|
|
const classes = useStyles();
|
|
const navigate = useNavigate();
|
|
const debouncedSearch =
|
|
onSearch && useMemo(() => debounce(onSearch, 500), []);
|
|
|
|
// Function to render button with icon if provided
|
|
const renderButton = (disabled) => {
|
|
if (addButtonIcon) {
|
|
return (
|
|
<LoadingButton
|
|
className={
|
|
buttonVariant === 'outlined'
|
|
? classes.addButtonOutlined
|
|
: classes.addButton
|
|
}
|
|
sx={
|
|
addButtonDisabled && {
|
|
opacity: 0.56,
|
|
pointerEvents: 'none',
|
|
}
|
|
}
|
|
color="primary"
|
|
variant={buttonVariant}
|
|
onClick={onAddButtonClick}
|
|
loading={!addButtonDisabled && addButtonLoading}
|
|
startIcon={addButtonIcon}
|
|
disabled={addButtonDisabled}
|
|
>
|
|
{addButtonTitle ?? 'Add'}
|
|
</LoadingButton>
|
|
);
|
|
} else {
|
|
return (
|
|
<LoadingButton
|
|
className={classes.addButton}
|
|
sx={
|
|
addButtonDisabled && {
|
|
opacity: 0.56,
|
|
pointerEvents: 'none',
|
|
}
|
|
}
|
|
color="primary"
|
|
variant="contained"
|
|
onClick={onAddButtonClick}
|
|
loading={!addButtonDisabled && addButtonLoading}
|
|
disabled={addButtonDisabled}
|
|
>
|
|
{addButtonTitle ?? 'Add'}
|
|
</LoadingButton>
|
|
);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Grid item md={12}>
|
|
<Box className={classes.header}>
|
|
<Box className={classes.headerTitle}>
|
|
{showGoBack && (
|
|
<ArrowBack
|
|
className={classes.gobackIcon}
|
|
onClick={() => {
|
|
handleGoBack ? handleGoBack() : navigate(-1);
|
|
}}
|
|
/>
|
|
)}
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: titleAlignItems ? titleAlignItems : 'center',
|
|
}}
|
|
className={!isDetailPage ? classes.title : null}
|
|
>
|
|
<Typography
|
|
variant="Inter-SemiBold"
|
|
fontSize={pxToRem(24)}
|
|
sx={{ overflowWrap: 'break-word' }}
|
|
>
|
|
{pageTitle}
|
|
</Typography>
|
|
{customChips}
|
|
</div>
|
|
</Box>
|
|
<Box className={classes.headerActions}>
|
|
{showSearch && (
|
|
<TextField
|
|
className={classes.searchBar}
|
|
color="secondary"
|
|
id="globalSearch"
|
|
placeholder={searchPlaceholder ?? 'Search here'}
|
|
variant="outlined"
|
|
onChange={debouncedSearch}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<Search />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
)}
|
|
{extraComponent}
|
|
{secondaryButton && (
|
|
<Box className={classes.secondaryButton}>{secondaryButton}</Box>
|
|
)}
|
|
{!hideAddButton && renderButton(addButtonDisabled)}
|
|
</Box>
|
|
</Box>
|
|
</Grid>
|
|
);
|
|
}
|
|
|
|
export default PageHeader;
|