import React, { useState, useEffect, useCallback } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { useDataProvider, useTranslate, useRefresh } from 'react-admin'
import {
Box,
Chip,
ClickAwayListener,
FormControl,
FormGroup,
FormControlLabel,
Checkbox,
Typography,
Paper,
Popper,
makeStyles,
} from '@material-ui/core'
import { ExpandMore, ExpandLess, LibraryMusic } from '@material-ui/icons'
import { setSelectedLibraries, setUserLibraries } from '../actions'
import { useRefreshOnEvents } from './useRefreshOnEvents'
const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(3),
marginBottom: theme.spacing(3),
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
display: 'flex',
justifyContent: 'center',
},
chip: {
borderRadius: theme.spacing(1),
height: theme.spacing(4.8),
fontSize: '1rem',
fontWeight: 'normal',
minWidth: '210px',
justifyContent: 'flex-start',
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(1),
marginTop: theme.spacing(0.1),
'& .MuiChip-label': {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1),
},
'& .MuiChip-icon': {
fontSize: '1.2rem',
marginLeft: theme.spacing(0.5),
},
},
popper: {
zIndex: 1300,
},
paper: {
padding: theme.spacing(2),
marginTop: theme.spacing(1),
minWidth: 300,
maxWidth: 400,
},
headerContainer: {
display: 'flex',
alignItems: 'center',
marginBottom: 0,
},
masterCheckbox: {
padding: '7px',
marginLeft: '-9px',
marginRight: 0,
},
}))
const LibrarySelector = () => {
const classes = useStyles()
const dispatch = useDispatch()
const dataProvider = useDataProvider()
const translate = useTranslate()
const refresh = useRefresh()
const [anchorEl, setAnchorEl] = useState(null)
const [open, setOpen] = useState(false)
const { userLibraries, selectedLibraries } = useSelector(
(state) => state.library,
)
const loadUserLibraries = useCallback(async () => {
const userId = localStorage.getItem('userId')
if (userId) {
try {
const { data } = await dataProvider.getOne('user', { id: userId })
const libraries = data.libraries || []
dispatch(setUserLibraries(libraries))
} catch (error) {
console.warn(
'Could not load user libraries (this may be expected for non-admin users):',
error,
)
}
}
}, [dataProvider, dispatch])
useEffect(() => {
loadUserLibraries()
}, [loadUserLibraries])
useRefreshOnEvents({
events: ['library', 'user'],
onRefresh: loadUserLibraries,
})
if (!userLibraries.length || userLibraries.length === 1) {
return null
}
const handleToggle = (event) => {
setAnchorEl(event.currentTarget)
const wasOpen = open
setOpen(!open)
if (wasOpen) {
refresh()
}
}
const handleClose = () => {
setOpen(false)
refresh()
}
const handleLibraryToggle = (libraryId) => {
const newSelection = selectedLibraries.includes(libraryId)
? selectedLibraries.filter((id) => id !== libraryId)
: [...selectedLibraries, libraryId]
dispatch(setSelectedLibraries(newSelection))
}
const handleMasterCheckboxChange = () => {
if (isAllSelected) {
dispatch(setSelectedLibraries([]))
} else {
const allIds = userLibraries.map((lib) => lib.id)
dispatch(setSelectedLibraries(allIds))
}
}
const selectedCount = selectedLibraries.length
const totalCount = userLibraries.length
const isAllSelected = selectedCount === totalCount
const isNoneSelected = selectedCount === 0
const isIndeterminate = selectedCount > 0 && selectedCount < totalCount
const displayText = isNoneSelected
? translate('menu.librarySelector.none') + ` (0 of ${totalCount})`
: isAllSelected
? translate('menu.librarySelector.allLibraries', { count: totalCount })
: translate('menu.librarySelector.multipleLibraries', {
selected: selectedCount,
total: totalCount,
})
return (
<Box className={classes.root}>
<Chip
icon={<LibraryMusic />}
label={displayText}
onClick={handleToggle}
onDelete={open ? handleToggle : undefined}
deleteIcon={open ? <ExpandLess /> : <ExpandMore />}
variant="outlined"
className={classes.chip}
/>
<Popper
open={open}
anchorEl={anchorEl}
placement="bottom-start"
className={classes.popper}
>
<ClickAwayListener onClickAway={handleClose}>
<Paper className={classes.paper}>
<Box className={classes.headerContainer}>
<Checkbox
checked={isAllSelected}
indeterminate={isIndeterminate}
onChange={handleMasterCheckboxChange}
size="small"
className={classes.masterCheckbox}
/>
<Typography>
{translate('menu.librarySelector.selectLibraries')}:
</Typography>
</Box>
<FormControl component="fieldset" variant="standard" fullWidth>
<FormGroup>
{userLibraries.map((library) => (
<FormControlLabel
key={library.id}
control={
<Checkbox
checked={selectedLibraries.includes(library.id)}
onChange={() => handleLibraryToggle(library.id)}
size="small"
/>
}
label={library.name}
/>
))}
</FormGroup>
</FormControl>
</Paper>
</ClickAwayListener>
</Popper>
</Box>
)
}
export default LibrarySelector