@@ -21,17 +21,23 @@ import { Group } from "@/interfaces/Group";
2121
2222interface MultiSelectProps {
2323 values : string [ ] ;
24- onChange : ( items : string [ ] ) => void ;
24+ exactValue ?: string ;
25+ onChange : ( items : string [ ] , exactItem ?: string ) => void ;
2526 disabled ?: boolean ;
2627 popoverWidth ?: "auto" | number ;
2728 groups : Group [ ] | undefined ;
29+ unassignedCount ?: number ;
30+ defaultGroupName ?: string ;
2831}
2932export function GroupSelector ( {
3033 onChange,
3134 values,
35+ exactValue,
3236 disabled = false ,
3337 popoverWidth = 400 ,
3438 groups,
39+ unassignedCount,
40+ defaultGroupName = "All" , //defined as a property, no clue if this value may change in the future
3541} : MultiSelectProps ) {
3642 const searchRef = React . useRef < HTMLInputElement > ( null ) ;
3743 const [ inputRef , { width } ] = useElementSize < HTMLButtonElement > ( ) ;
@@ -40,9 +46,20 @@ export function GroupSelector({
4046 const toggle = ( code : string ) => {
4147 const isSelected = values . find ( ( c ) => c == code ) != undefined ;
4248 if ( isSelected ) {
43- onChange && onChange ( values . filter ( ( c ) => c != code ) ) ;
49+ onChange && onChange ( values . filter ( ( c ) => c != code ) , undefined ) ;
4450 } 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 ) ;
4663 setSearch ( "" ) ;
4764 }
4865 } ;
@@ -62,14 +79,16 @@ export function GroupSelector({
6279 } }
6380 >
6481 < PopoverTrigger asChild = { true } >
65- < Button variant = { "secondary" } disabled = { disabled } ref = { inputRef } >
82+ < Button variant = { "secondary" } disabled = { disabled } ref = { inputRef } className = "w-[200px] justify-between" >
6683 < FolderGit2 size = { 16 } className = { "shrink-0" } />
6784 < 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+ }
7392 < div className = { "pl-2" } >
7493 < ChevronsUpDown size = { 18 } className = { "shrink-0" } />
7594 </ div >
@@ -132,7 +151,6 @@ export function GroupSelector({
132151 </ div >
133152 </ div >
134153 </ div >
135-
136154 < ScrollArea
137155 className = {
138156 "max-h-[380px] overflow-y-auto flex flex-col gap-1 pl-2 py-2 pr-3"
@@ -141,7 +159,48 @@ export function GroupSelector({
141159 < CommandGroup >
142160 < div className = { "" } >
143161 < 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 ) => {
145204 const value = item ?. name || "" ;
146205 if ( value === "" ) return null ;
147206 const isSelected =
0 commit comments