Files
donetick/src/views/Chores/IconButtonWithMenu.jsx
Mo Tarbin 2c353628a3 feat: implement offline support for labels and projects, enhance advanced settings with offline feature toggle, and add sync status indicator
- Added offline support for fetching and caching labels and projects using `offlineDB`.
- Enhanced `AdvancedSettings` to include an offline feature toggle with confirmation modal for disabling offline support.
- Introduced `SyncStatusIndicator` component to display sync status, pending commands, and failed commands.
- Created `PendingBadge` component to manage and display pending actions for synchronization.
- Removed deprecated offline mode toggle from `StorageSettings`.
- Improved error handling and user notifications for offline actions and sync processes.
2026-05-11 17:27:29 -04:00

131 lines
3.2 KiB
JavaScript

import { Button, Chip, Menu, MenuItem, Typography } from '@mui/joy'
import IconButton from '@mui/joy/IconButton'
import { useEffect, useRef, useState } from 'react'
import { getTextColorFromBackgroundColor } from '../../utils/Colors.jsx'
const IconButtonWithMenu = ({
label,
k,
icon,
options,
onItemSelect,
selectedItem,
setSelectedItem,
isActive,
useChips,
title,
}) => {
const [anchorEl, setAnchorEl] = useState(null)
const menuRef = useRef(null)
const menuOptions = Array.isArray(options) ? options : []
const handleMenuOpen = event => {
setAnchorEl(event.currentTarget)
}
const handleMenuClose = () => {
setAnchorEl(null)
}
useEffect(() => {
document.addEventListener('mousedown', handleMenuOutsideClick)
return () => {
document.removeEventListener('mousedown', handleMenuOutsideClick)
}
}, [anchorEl])
const handleMenuOutsideClick = event => {
if (menuRef.current && !menuRef.current.contains(event.target)) {
handleMenuClose()
}
}
return (
<>
{!label && (
<IconButton
onClick={handleMenuOpen}
variant='outlined'
color={isActive ? 'primary' : 'neutral'}
size='sm'
sx={{
height: 24,
borderRadius: 24,
}}
>
{icon}
{label ? label : null}
</IconButton>
)}
{label && (
<Button
onClick={handleMenuOpen}
variant='outlined'
color={isActive ? 'primary' : 'neutral'}
size='sm'
startDecorator={icon}
sx={{
height: 24,
borderRadius: 24,
}}
>
{label}
</Button>
)}
<Menu
key={k}
ref={menuRef}
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleMenuClose}
>
{title && (
<MenuItem key={`${k}-title`} disabled>
<Typography level='body-sm' sx={{ fontWeight: 'bold' }}>
{title}
</Typography>
</MenuItem>
)}
{menuOptions.map(item => (
<MenuItem
key={`${k}-${item?.id}`}
onClick={() => {
onItemSelect(item)
setSelectedItem?.selectedItem(item.name)
handleMenuClose()
}}
>
{useChips ? (
<Chip
sx={{
backgroundColor: item.color ? item.color : null,
color: getTextColorFromBackgroundColor(item.color),
}}
>
{item.name}
</Chip>
) : (
<>
{item?.icon}
{item.name}
</>
)}
</MenuItem>
))}
{/* {selectedItem && selectedItem !== 'All' && (
<MenuItem
id={`${id}cancel-all-filters`}
onClick={() => {
onItemSelect(null)
setSelectedItem?.setSelectedItem('All')
}}
>
Cancel All Filters
</MenuItem>
)} */}
</Menu>
</>
)
}
export default IconButtonWithMenu