feat: initial commit
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user