11import FolderIcon from '@mui/icons-material/Folder' ;
22import {
3- CircularProgress , Dialog , DialogContent , DialogTitle , List , ListItemButton ,
4- ListItemIcon , ListItemText , Typography
3+ Button ,
4+ Checkbox ,
5+ CircularProgress , Dialog , DialogActions , DialogContent , DialogTitle , List , ListItemButton ,
6+ ListItemIcon , ListItemText , Typography
57} from '@mui/material' ;
68import { getAlbums } from 'api/albumApi' ;
79import { Album } from 'models/Album' ;
@@ -10,7 +12,7 @@ import * as React from 'react';
1012type Props = {
1113 open : boolean ;
1214 onClose : ( ) => void ;
13- onSelect : ( albumId : string ) => void ;
15+ onSelect : ( albumId : string [ ] ) => void ;
1416 title ?: string ;
1517 hideSystemAlbums ?: boolean ;
1618} ;
@@ -19,18 +21,34 @@ export const AddToAlbumDialog: React.FC<Props> = ({
1921 open,
2022 onClose,
2123 onSelect,
22- title = 'Choose album' ,
24+ title = 'Choose album(s) ' ,
2325 hideSystemAlbums = false ,
2426} ) => {
2527 const { data : albums , isLoading, isError, error } = getAlbums ( ) ;
2628
29+ const [ selectedIds , setSelectedIds ] = React . useState < string [ ] > ( [ ] ) ;
30+ React . useEffect ( ( ) => {
31+ if ( ! open ) {
32+ setSelectedIds ( [ ] ) ;
33+ }
34+ } , [ open ] ) ;
35+
36+
2737 const visibleAlbums = React . useMemo < Album [ ] > ( ( ) => {
2838 const list = albums ?? [ ] ;
29- return hideSystemAlbums ? list . filter ( a => ! a . isSystem ) : list ;
39+ return hideSystemAlbums ? list . filter ( ( a ) => ! a . isSystem ) : list ;
3040 } , [ albums , hideSystemAlbums ] ) ;
3141
32- const handlePick = ( id : string ) => {
33- onSelect ( id ) ;
42+ const handleToggle = ( id : string ) => {
43+ setSelectedIds ( ( prev ) =>
44+ prev . includes ( id ) ? prev . filter ( ( x ) => x !== id ) : [ ...prev , id ] ,
45+ ) ;
46+ } ;
47+
48+ const handleConfirm = ( ) => {
49+ if ( selectedIds . length === 0 ) return ;
50+
51+ onSelect ( selectedIds ) ;
3452 onClose ( ) ;
3553 } ;
3654
@@ -59,31 +77,54 @@ export const AddToAlbumDialog: React.FC<Props> = ({
5977
6078 { ! isLoading && ! isError && visibleAlbums . length > 0 && (
6179 < List dense disablePadding >
62- { visibleAlbums . map ( ( album ) => (
63- < ListItemButton
64- key = { album . id }
65- onClick = { ( ) => handlePick ( album . id ) }
66- sx = { {
67- borderRadius : 1 ,
68- mb : 0.5 ,
69- '&:hover' : { bgcolor : 'action.hover' } ,
70- } }
71- >
72- < ListItemIcon >
73- < FolderIcon />
74- </ ListItemIcon >
75-
76- < ListItemText
77- primary = { album . name }
78- secondary = { new Date ( album . dateCreated ) . toLocaleDateString ( ) }
79- primaryTypographyProps = { { noWrap : true , fontWeight : 600 } }
80- secondaryTypographyProps = { { noWrap : true } }
81- />
82- </ ListItemButton >
83- ) ) }
80+ { visibleAlbums . map ( ( album ) => {
81+ const checked = selectedIds . includes ( album . id ) ;
82+ return (
83+ < ListItemButton
84+ key = { album . id }
85+ onClick = { ( ) => handleToggle ( album . id ) }
86+ selected = { checked }
87+ sx = { {
88+ borderRadius : 1 ,
89+ mb : 0.5 ,
90+ '&:hover' : { bgcolor : 'action.hover' } ,
91+ } }
92+ >
93+ < ListItemIcon sx = { { minWidth : 40 } } >
94+ < Checkbox
95+ edge = "start"
96+ checked = { checked }
97+ tabIndex = { - 1 }
98+ disableRipple
99+ />
100+ </ ListItemIcon >
101+
102+ < ListItemIcon sx = { { minWidth : 36 } } >
103+ < FolderIcon />
104+ </ ListItemIcon >
105+
106+ < ListItemText
107+ primary = { album . name }
108+ secondary = { new Date ( album . dateCreated ) . toLocaleDateString ( ) }
109+ primaryTypographyProps = { { noWrap : true , fontWeight : 600 } }
110+ secondaryTypographyProps = { { noWrap : true } }
111+ />
112+ </ ListItemButton >
113+ ) ;
114+ } ) }
84115 </ List >
85116 ) }
86117 </ DialogContent >
118+ < DialogActions >
119+ < Button onClick = { onClose } > Cancel</ Button >
120+ < Button
121+ onClick = { handleConfirm }
122+ variant = "contained"
123+ disabled = { selectedIds . length === 0 }
124+ >
125+ Add
126+ </ Button >
127+ </ DialogActions >
87128 </ Dialog >
88129 ) ;
89130} ;
0 commit comments