@@ -10,24 +10,22 @@ import { useDebounce } from "use-debounce";
10
10
11
11
interface DiscountPartnersTableProps {
12
12
partnerIds : string [ ] ;
13
- partners : EnrolledPartnerProps [ ] ;
14
- setPartners : ( value : string [ ] ) => void ;
13
+ setPartnerIds : ( value : string [ ] ) => void ;
14
+ discountPartners : EnrolledPartnerProps [ ] ;
15
15
loading : boolean ;
16
16
}
17
17
18
18
export function DiscountPartnersTable ( {
19
19
partnerIds,
20
- partners ,
21
- setPartners ,
20
+ setPartnerIds ,
21
+ discountPartners ,
22
22
loading,
23
23
} : DiscountPartnersTableProps ) {
24
24
const [ search , setSearch ] = useState ( "" ) ;
25
25
const [ debouncedSearch ] = useDebounce ( search , 500 ) ;
26
- const [ selectedPartners , setSelectedPartners ] =
27
- useState < Pick < EnrolledPartnerProps , "id" | "name" | "email" | "image" > [ ] > ( ) ;
28
-
29
- // Get all partners for the table
30
- const { data : allPartners } = usePartners ( { } ) ;
26
+ const [ selectedPartners , setSelectedPartners ] = useState <
27
+ Pick < EnrolledPartnerProps , "id" | "name" | "email" | "image" > [ ]
28
+ > ( [ ] ) ;
31
29
32
30
// Get filtered partners for the combobox
33
31
const { data : searchPartners } = usePartners ( {
@@ -36,7 +34,23 @@ export function DiscountPartnersTable({
36
34
} ,
37
35
} ) ;
38
36
39
- const options = useMemo (
37
+ // Create a map for faster partner lookups
38
+ const partnersMap = useMemo ( ( ) => {
39
+ if ( ! searchPartners ) return new Map ( ) ;
40
+ return new Map (
41
+ searchPartners . map ( ( partner ) => [
42
+ partner . id ,
43
+ {
44
+ id : partner . id ,
45
+ name : partner . name ,
46
+ email : partner . email ,
47
+ image : partner . image ,
48
+ } ,
49
+ ] ) ,
50
+ ) ;
51
+ } , [ searchPartners ] ) ;
52
+
53
+ const partnersOptions = useMemo (
40
54
( ) =>
41
55
searchPartners ?. map ( ( partner ) => ( {
42
56
icon : (
@@ -48,38 +62,70 @@ export function DiscountPartnersTable({
48
62
) ,
49
63
value : partner . id ,
50
64
label : partner . name ,
51
- } ) ) ,
65
+ } ) ) || [ ] ,
52
66
[ searchPartners ] ,
53
67
) ;
54
68
55
69
const selectedPartnersOptions = useMemo (
56
70
( ) =>
57
- partnerIds
58
- . map ( ( id ) => options ?. find ( ( { value } ) => value === id ) ! )
59
- . filter ( Boolean ) ,
60
- [ partnerIds , options ] ,
71
+ partnersOptions . filter ( ( partner ) => partnerIds . includes ( partner . value ) ) ,
72
+ [ partnerIds , partnersOptions ] ,
61
73
) ;
62
74
75
+ // Update selectedPartners when discountPartners changes
63
76
useEffect ( ( ) => {
64
- setSelectedPartners ( partners ) ;
65
- } , [ partners ] ) ;
77
+ if ( discountPartners && discountPartners . length > 0 ) {
78
+ setSelectedPartners ( discountPartners ) ;
79
+ }
80
+ } , [ discountPartners ] ) ;
66
81
67
82
const handlePartnerSelection = (
68
83
selectedOptions : typeof selectedPartnersOptions ,
69
84
) => {
70
- // Get all currently selected IDs
71
- const currentIds = new Set ( partnerIds ) ;
85
+ // Get all currently selected partner IDs that are not in the current search results
86
+ const currentSelectedIds = new Set ( partnerIds ) ;
72
87
73
- // Add new selections
74
- selectedOptions . forEach ( ( { value } ) => {
75
- currentIds . add ( value ) ;
88
+ // Remove deselected partners from current search results
89
+ partnersOptions . forEach ( ( option ) => {
90
+ if (
91
+ ! selectedOptions . some ( ( selected ) => selected . value === option . value )
92
+ ) {
93
+ currentSelectedIds . delete ( option . value ) ;
94
+ }
76
95
} ) ;
77
96
78
- setPartners ( Array . from ( currentIds ) ) ;
97
+ // Add newly selected partners
98
+ selectedOptions . forEach ( ( option ) => {
99
+ currentSelectedIds . add ( option . value ) ;
100
+ } ) ;
101
+
102
+ // Convert to array and update partnerIds
103
+ const newPartnerIds = Array . from ( currentSelectedIds ) ;
104
+ setPartnerIds ( newPartnerIds ) ;
105
+
106
+ // Update selectedPartners to maintain all selected partners
107
+ const newSelectedPartners = newPartnerIds
108
+ . map ( ( id ) => {
109
+ // First check existing selected partners
110
+ const existingPartner = selectedPartners ?. find ( ( p ) => p . id === id ) ;
111
+ if ( existingPartner ) return existingPartner ;
112
+
113
+ // Then check discountPartners
114
+ const discountPartner = discountPartners ?. find ( ( p ) => p . id === id ) ;
115
+ if ( discountPartner ) return discountPartner ;
116
+
117
+ // Finally check the partnersMap for new selections
118
+ return partnersMap . get ( id ) || null ;
119
+ } )
120
+ . filter (
121
+ ( partner ) : partner is NonNullable < typeof partner > => partner !== null ,
122
+ ) ;
123
+
124
+ setSelectedPartners ( newSelectedPartners ) ;
79
125
} ;
80
126
81
127
const table = useTable ( {
82
- data : selectedPartners || [ ] ,
128
+ data : selectedPartners ,
83
129
columns : [
84
130
{
85
131
header : "Partner" ,
@@ -122,7 +168,9 @@ export function DiscountPartnersTable({
122
168
icon = { < X className = "size-4" /> }
123
169
className = "size-4 rounded-md border-0 bg-neutral-50 p-0 hover:bg-neutral-100"
124
170
onClick = { ( ) => {
125
- setPartners ( partnerIds . filter ( ( id ) => id !== row . original . id ) ) ;
171
+ setPartnerIds (
172
+ partnerIds . filter ( ( id ) => id !== row . original . id ) ,
173
+ ) ;
126
174
setSelectedPartners (
127
175
selectedPartners ?. filter (
128
176
( partner ) => partner . id !== row . original . id ,
@@ -154,7 +202,7 @@ export function DiscountPartnersTable({
154
202
</ label >
155
203
156
204
< Combobox
157
- options = { options }
205
+ options = { partnersOptions }
158
206
selected = { selectedPartnersOptions }
159
207
setSelected = { handlePartnerSelection }
160
208
caret
0 commit comments