@@ -21,17 +21,23 @@ import { Group } from "@/interfaces/Group";
21
21
22
22
interface MultiSelectProps {
23
23
values : string [ ] ;
24
- onChange : ( items : string [ ] ) => void ;
24
+ exactValue ?: string ;
25
+ onChange : ( items : string [ ] , exactItem ?: string ) => void ;
25
26
disabled ?: boolean ;
26
27
popoverWidth ?: "auto" | number ;
27
28
groups : Group [ ] | undefined ;
29
+ unassignedCount ?: number ;
30
+ defaultGroupName ?: string ;
28
31
}
29
32
export function GroupSelector ( {
30
33
onChange,
31
34
values,
35
+ exactValue,
32
36
disabled = false ,
33
37
popoverWidth = 400 ,
34
38
groups,
39
+ unassignedCount,
40
+ defaultGroupName = "All" , //defined as a property, no clue if this value may change in the future
35
41
} : MultiSelectProps ) {
36
42
const searchRef = React . useRef < HTMLInputElement > ( null ) ;
37
43
const [ inputRef , { width } ] = useElementSize < HTMLButtonElement > ( ) ;
@@ -40,9 +46,20 @@ export function GroupSelector({
40
46
const toggle = ( code : string ) => {
41
47
const isSelected = values . find ( ( c ) => c == code ) != undefined ;
42
48
if ( isSelected ) {
43
- onChange && onChange ( values . filter ( ( c ) => c != code ) ) ;
49
+ onChange && onChange ( values . filter ( ( c ) => c != code ) , undefined ) ;
44
50
} else {
45
- onChange && onChange ( [ ...values , code ] ) ;
51
+ onChange && onChange ( [ ...values , code ] , undefined ) ;
52
+ setSearch ( "" ) ;
53
+ }
54
+ } ;
55
+
56
+ const toggleExactGroup = ( code : string ) => {
57
+ const isSelected = exactValue == code ;
58
+ if ( isSelected ) {
59
+ onChange && onChange ( [ ] , undefined ) ;
60
+ setSearch ( "" ) ;
61
+ } else {
62
+ onChange && onChange ( [ ] , code ) ;
46
63
setSearch ( "" ) ;
47
64
}
48
65
} ;
@@ -62,14 +79,16 @@ export function GroupSelector({
62
79
} }
63
80
>
64
81
< PopoverTrigger asChild = { true } >
65
- < Button variant = { "secondary" } disabled = { disabled } ref = { inputRef } >
82
+ < Button variant = { "secondary" } disabled = { disabled } ref = { inputRef } className = "w-[200px] justify-between" >
66
83
< FolderGit2 size = { 16 } className = { "shrink-0" } />
67
84
< div className = { "w-full flex justify-between" } >
68
- { values . length > 0 ? (
69
- < div > { values . length } Group(s)</ div >
70
- ) : (
71
- "All Groups"
72
- ) }
85
+ {
86
+ exactValue != undefined
87
+ ? ( "Unassigned peers" )
88
+ : values . length > 0
89
+ ? ( `${ values . length } Group(s)` )
90
+ : ( "All Groups" )
91
+ }
73
92
< div className = { "pl-2" } >
74
93
< ChevronsUpDown size = { 18 } className = { "shrink-0" } />
75
94
</ div >
@@ -132,7 +151,6 @@ export function GroupSelector({
132
151
</ div >
133
152
</ div >
134
153
</ div >
135
-
136
154
< ScrollArea
137
155
className = {
138
156
"max-h-[380px] overflow-y-auto flex flex-col gap-1 pl-2 py-2 pr-3"
@@ -141,7 +159,48 @@ export function GroupSelector({
141
159
< CommandGroup >
142
160
< div className = { "" } >
143
161
< div className = { "grid grid-cols-1 gap-1" } >
144
- { orderBy ( groups , "name" ) ?. map ( ( item ) => {
162
+ < CommandItem
163
+ className = { "p-1" }
164
+ onSelect = { ( ) => {
165
+ toggleExactGroup ( defaultGroupName ) ;
166
+ searchRef . current ?. focus ( ) ;
167
+ } }
168
+ onClick = { ( e ) => e . preventDefault ( ) }
169
+ >
170
+ < div
171
+ className = {
172
+ "text-neutral-500 dark:text-nb-gray-300 font-medium flex items-center gap-3 py-1 px-1 w-full"
173
+ }
174
+ >
175
+ < Checkbox checked = { exactValue == defaultGroupName } />
176
+ < div
177
+ className = {
178
+ "flex justify-between items-center w-full"
179
+ }
180
+ >
181
+ < div
182
+ className = {
183
+ "flex items-center gap-2 whitespace-nowrap text-sm"
184
+ }
185
+ >
186
+ < FolderGit2 size = { 13 } className = { "shrink-0" } />
187
+ < TextWithTooltip text = { "Unassigned peers" } />
188
+ </ div >
189
+ < div
190
+ className = {
191
+ "flex items-center gap-2 text-xs text-nb-gray-200/60"
192
+ }
193
+ >
194
+ < MonitorSmartphoneIcon size = { 13 } />
195
+ { unassignedCount } Peer(s)
196
+ </ div >
197
+ </ div >
198
+ </ div >
199
+ </ CommandItem >
200
+ < hr />
201
+ { orderBy ( groups , "name" )
202
+ ?. filter ( ( group ) => group . name != defaultGroupName ) // Ignore default group
203
+ ?. map ( ( item ) => {
145
204
const value = item ?. name || "" ;
146
205
if ( value === "" ) return null ;
147
206
const isSelected =
0 commit comments