148 lines
4.1 KiB
TypeScript
148 lines
4.1 KiB
TypeScript
import type { IDateValue } from 'src/types/common';
|
|
import type { ICalendarView } from 'src/types/calendar';
|
|
|
|
import { usePopover } from 'minimal-shared/hooks';
|
|
|
|
import Box from '@mui/material/Box';
|
|
import Badge from '@mui/material/Badge';
|
|
import Button from '@mui/material/Button';
|
|
import MenuList from '@mui/material/MenuList';
|
|
import MenuItem from '@mui/material/MenuItem';
|
|
import IconButton from '@mui/material/IconButton';
|
|
import Typography from '@mui/material/Typography';
|
|
import LinearProgress from '@mui/material/LinearProgress';
|
|
|
|
import { Iconify } from 'src/components/iconify';
|
|
import { CustomPopover } from 'src/components/custom-popover';
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
const VIEW_OPTIONS = [
|
|
{ value: 'dayGridMonth', label: 'Month', icon: 'mingcute:calendar-month-line' },
|
|
{ value: 'timeGridWeek', label: 'Week', icon: 'mingcute:calendar-week-line' },
|
|
{ value: 'timeGridDay', label: 'Day', icon: 'mingcute:calendar-day-line' },
|
|
{ value: 'listWeek', label: 'Agenda', icon: 'custom:calendar-agenda-outline' },
|
|
] as const;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
type Props = {
|
|
loading: boolean;
|
|
canReset: boolean;
|
|
view: ICalendarView;
|
|
date: IDateValue;
|
|
onToday: () => void;
|
|
onNextDate: () => void;
|
|
onPrevDate: () => void;
|
|
onOpenFilters: () => void;
|
|
onChangeView: (newView: ICalendarView) => void;
|
|
};
|
|
|
|
export function CalendarToolbar({
|
|
date,
|
|
view,
|
|
loading,
|
|
onToday,
|
|
canReset,
|
|
onNextDate,
|
|
onPrevDate,
|
|
onChangeView,
|
|
onOpenFilters,
|
|
}: Props) {
|
|
const menuActions = usePopover();
|
|
|
|
const selectedItem = VIEW_OPTIONS.filter((item) => item.value === view)[0];
|
|
|
|
const renderMenuActions = () => (
|
|
<CustomPopover
|
|
open={menuActions.open}
|
|
anchorEl={menuActions.anchorEl}
|
|
onClose={menuActions.onClose}
|
|
slotProps={{ arrow: { placement: 'top-left' } }}
|
|
>
|
|
<MenuList>
|
|
{VIEW_OPTIONS.map((viewOption) => (
|
|
<MenuItem
|
|
key={viewOption.value}
|
|
selected={viewOption.value === view}
|
|
onClick={() => {
|
|
menuActions.onClose();
|
|
onChangeView(viewOption.value);
|
|
}}
|
|
>
|
|
<Iconify icon={viewOption.icon} />
|
|
{viewOption.label}
|
|
</MenuItem>
|
|
))}
|
|
</MenuList>
|
|
</CustomPopover>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<Box
|
|
sx={{
|
|
p: 2.5,
|
|
pr: 2,
|
|
display: 'flex',
|
|
position: 'relative',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
}}
|
|
>
|
|
<Button
|
|
size="small"
|
|
color="inherit"
|
|
onClick={menuActions.onOpen}
|
|
startIcon={<Iconify icon={selectedItem.icon} />}
|
|
endIcon={<Iconify icon="eva:arrow-ios-downward-fill" sx={{ ml: -0.5 }} />}
|
|
sx={{ display: { xs: 'none', sm: 'inline-flex' } }}
|
|
>
|
|
{selectedItem.label}
|
|
</Button>
|
|
|
|
<Box sx={{ gap: 1, display: 'flex', alignItems: 'center' }}>
|
|
<IconButton onClick={onPrevDate}>
|
|
<Iconify icon="eva:arrow-ios-back-fill" />
|
|
</IconButton>
|
|
|
|
{/* FIXME: no raw json output in html */}
|
|
<Typography variant="h6">{JSON.stringify({ date })}</Typography>
|
|
|
|
<IconButton onClick={onNextDate}>
|
|
<Iconify icon="eva:arrow-ios-forward-fill" />
|
|
</IconButton>
|
|
</Box>
|
|
|
|
<Box sx={{ gap: 1, display: 'flex', alignItems: 'center' }}>
|
|
<Button size="small" color="error" variant="contained" onClick={onToday}>
|
|
Today
|
|
</Button>
|
|
|
|
<IconButton onClick={onOpenFilters}>
|
|
<Badge color="error" variant="dot" invisible={!canReset}>
|
|
<Iconify icon="ic:round-filter-list" />
|
|
</Badge>
|
|
</IconButton>
|
|
</Box>
|
|
|
|
{loading && (
|
|
<LinearProgress
|
|
color="inherit"
|
|
sx={{
|
|
left: 0,
|
|
width: 1,
|
|
height: 2,
|
|
bottom: 0,
|
|
borderRadius: 0,
|
|
position: 'absolute',
|
|
}}
|
|
/>
|
|
)}
|
|
</Box>
|
|
|
|
{renderMenuActions()}
|
|
</>
|
|
);
|
|
}
|