Files
cpost-front/src/components/common/StatusChangePopup/index.tsx
azizziy c01e852a59 init
2025-05-20 17:02:10 +05:00

152 lines
5.5 KiB
TypeScript

import * as React from 'react';
import { styled, alpha } from '@mui/material/styles';
import Menu, { MenuProps } from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import { Box, CircularProgress, IconButton, PopoverOrigin, SvgIcon, Typography } from '@mui/material';
import { ArrowDropDown, MoreVert } from '@mui/icons-material';
import { getBoxStatusStyles } from '@/theme/getStatusBoxStyles';
import { BoxStatus, IBox } from '@/data/box/box.model';
import { PartyStatus } from '@/data/party/party.model';
import BaseButton from '@/components/ui-kit/BaseButton';
type PlacementType = {
anchorOrigin?: PopoverOrigin;
transformOrigin?: PopoverOrigin;
};
const StyledMenu = styled((props: MenuProps & { placement: Required<PlacementType> }) => (
<Menu elevation={0} anchorOrigin={props.placement.anchorOrigin} transformOrigin={props.placement.transformOrigin} {...props} />
))(({ theme }) => ({
'& .MuiPaper-root': {
borderRadius: 6,
marginTop: theme.spacing(1),
minWidth: 180,
color: theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[300],
boxShadow:
'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
'& .MuiMenu-list': {
padding: '4px 0',
},
'& .MuiMenuItem-root': {
'& .MuiSvgIcon-root': {
fontSize: 18,
color: theme.palette.text.secondary,
marginRight: theme.spacing(1.5),
},
'&:active': {
backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
},
},
},
}));
type StatusChangePopupProps = {
mainIcon?: React.ReactNode;
buttons: {
icon: React.ReactNode;
label: string;
onClick: () => void;
disabled?: boolean;
dontCloseOnClick?: boolean;
}[];
loading?: boolean;
placement?: PlacementType;
anchor: {
text: React.ReactNode;
status: BoxStatus | PartyStatus;
};
};
export default function StatusChangePopup({ buttons, mainIcon, placement, anchor, loading }: StatusChangePopupProps) {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<BaseButton
id='demo-customized-button'
aria-controls={open ? 'demo-customized-menu' : undefined}
aria-haspopup='true'
aria-expanded={open ? 'true' : undefined}
onClick={handleClick}
sx={{ ...getBoxStatusStyles(anchor.status), alignItems: 'center', whiteSpace: 'nowrap' }}
endIcon={<ArrowDropDown />}
loading={loading}
fullWidth
>
{anchor.text}
</BaseButton>
<StyledMenu
id='demo-customized-menu'
MenuListProps={{
'aria-labelledby': 'demo-customized-button',
}}
anchorEl={anchorEl}
open={open}
onClose={handleClose}
placement={{
anchorOrigin: placement?.anchorOrigin ?? {
vertical: 'bottom',
horizontal: 'center',
},
transformOrigin: placement?.transformOrigin ?? {
vertical: 'top',
horizontal: 'center',
},
}}
sx={{
'.MuiMenu-list': {
padding: '4px',
borderRadius: '8px',
},
}}
>
{buttons.map((btn, index) => {
return (
<MenuItem
onClick={event => {
btn.onClick();
if (!btn.dontCloseOnClick) handleClose();
}}
disableRipple
key={index}
sx={{
padding: '8px 12px',
gap: '8px',
}}
>
<SvgIcon
sx={{
width: '16px',
height: '16px',
padding: 0,
}}
>
{btn.icon}
</SvgIcon>
<Typography
sx={{
fontSize: '14px',
fontWeight: 500,
lineHeight: '16px',
letterSpacing: '-0.4px',
whiteSpace: 'nowrap',
}}
>
{btn.label}
</Typography>
</MenuItem>
);
})}
</StyledMenu>
</div>
);
}