CustomCard.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import {
  2. Card,
  3. CardActions,
  4. CardContent,
  5. CardHeader,
  6. IconButton,
  7. makeStyles,
  8. Menu,
  9. MenuItem,
  10. Theme,
  11. Tooltip,
  12. } from '@material-ui/core';
  13. import { FC } from 'react';
  14. import * as React from 'react';
  15. import icons from '../icons/Icons';
  16. import { ICustomCardProps, IMenu } from './Types';
  17. const getStyles = makeStyles((theme: Theme) => ({
  18. root: {
  19. boxShadow: 'none',
  20. filter: 'drop-shadow(0px 8px 24px rgba(0, 0, 0, 0.1))',
  21. width: '100%',
  22. position: 'relative',
  23. },
  24. menuItem: {
  25. minWidth: '160px',
  26. textTransform: 'capitalize',
  27. '&:hover': {
  28. backgroundColor: theme.palette.primary.light,
  29. },
  30. },
  31. menuPaper: {
  32. boxShadow: '0px 8px 16px rgba(0, 0, 0, 0.15)',
  33. },
  34. menuContent: {
  35. padding: 0,
  36. '&:last-child': {
  37. paddingBottom: 0,
  38. },
  39. },
  40. actions: {
  41. '&:hover': {
  42. background:
  43. 'linear-gradient(0deg, rgba(18, 195, 244, 0.05), rgba(18, 195, 244, 0.05)), #fff',
  44. transition: 'all 0.3s',
  45. },
  46. },
  47. actionsDisable: {
  48. '&:hover': {
  49. backgroundColor: '#fff',
  50. },
  51. },
  52. actionBtn: {
  53. color: theme.palette.primary.main,
  54. },
  55. mask: {
  56. position: 'absolute',
  57. top: 0,
  58. right: 0,
  59. left: 0,
  60. bottom: 0,
  61. backgroundColor: 'rgba(196, 196, 196, 0.5)',
  62. zIndex: theme.zIndex.modal,
  63. },
  64. }));
  65. const CustomCard: FC<ICustomCardProps> = props => {
  66. const {
  67. showCardHeaderTitle = true,
  68. cardHeaderTitle = '',
  69. menu = [],
  70. content,
  71. actions,
  72. wrapperClassName = '',
  73. showMask,
  74. actionsDisabled = false,
  75. } = props;
  76. const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
  77. const handleMoreClick = (event: React.MouseEvent<HTMLButtonElement>) => {
  78. setAnchorEl(event.currentTarget);
  79. };
  80. const handleMenuClose = () => {
  81. setAnchorEl(null);
  82. };
  83. const classes = getStyles();
  84. const handleClick = (event: any, m: IMenu) => {
  85. if (m.onClick) {
  86. m.onClick(event);
  87. }
  88. handleMenuClose();
  89. };
  90. return (
  91. <Card className={`${classes.root} ${wrapperClassName}`}>
  92. {showMask && <div className={classes.mask}></div>}
  93. <CardHeader
  94. action={
  95. menu.length > 0 && (
  96. <>
  97. <IconButton aria-label="settings" onClick={handleMoreClick}>
  98. {icons.more({ classes: { root: classes.actionBtn } })}
  99. </IconButton>
  100. <Menu
  101. anchorEl={anchorEl}
  102. disableScrollLock={true}
  103. keepMounted
  104. open={Boolean(anchorEl)}
  105. onClose={handleMenuClose}
  106. getContentAnchorEl={null}
  107. anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
  108. transformOrigin={{ vertical: 'top', horizontal: 'center' }}
  109. classes={{ paper: classes.menuPaper }}
  110. >
  111. {menu.map((m, index) =>
  112. typeof m.label === 'string' ? (
  113. m.tip ? (
  114. <Tooltip
  115. key={m.label}
  116. title={m.tip}
  117. placement="right-end"
  118. >
  119. <span style={{ display: 'block' }}>
  120. <MenuItem
  121. classes={{ root: classes.menuItem }}
  122. onClick={event => handleClick(event, m)}
  123. disabled={m.disabled}
  124. >
  125. {m.label}
  126. </MenuItem>
  127. </span>
  128. </Tooltip>
  129. ) : (
  130. <MenuItem
  131. classes={{ root: classes.menuItem }}
  132. key={m.label}
  133. onClick={event => handleClick(event, m)}
  134. disabled={m.disabled}
  135. >
  136. {m.label}
  137. </MenuItem>
  138. )
  139. ) : (
  140. <span key={index}>{m.label}</span>
  141. )
  142. )}
  143. </Menu>
  144. </>
  145. )
  146. }
  147. title={showCardHeaderTitle ? cardHeaderTitle : null}
  148. />
  149. <CardContent classes={{ root: classes.menuContent }}>
  150. {content}
  151. </CardContent>
  152. {actions && (
  153. <CardActions
  154. classes={{
  155. root: actionsDisabled ? classes.actionsDisable : classes.actions,
  156. }}
  157. disableSpacing
  158. >
  159. {actions}
  160. </CardActions>
  161. )}
  162. </Card>
  163. );
  164. };
  165. export default CustomCard;