1
1
import { VoiceLibraryAccent } from '@/api' ;
2
2
import { DEFAULT_QUERY_OPTIONS } from '@/api/config' ;
3
3
import { client } from '@/client' ;
4
- import { Button } from '@/components/ui/button' ;
5
4
import { Input } from '@/components/ui/input' ;
6
5
import {
7
6
Select ,
@@ -25,6 +24,7 @@ interface AccentSelectProps {
25
24
accents : { accent : string } [ ] | null ;
26
25
filterParams : FilterParams ;
27
26
setFilterParams : ( filterParams : FilterParams ) => void ;
27
+ provider : string ;
28
28
}
29
29
30
30
export interface FilterParams {
@@ -40,7 +40,7 @@ export const FILTER_PARAMS_DEFAULT = {
40
40
page : 1 ,
41
41
} ;
42
42
interface VoiceLibrarySearchProps {
43
- accents : string [ ] ;
43
+ voices : any [ ] ;
44
44
handleProviderChange : ( provider : VOICE_PROVIDERS ) => void ;
45
45
provider : VOICE_PROVIDERS ;
46
46
filterParams : FilterParams ;
@@ -53,8 +53,10 @@ interface SearchInputProps {
53
53
}
54
54
55
55
interface GenderSelectProps {
56
+ voices : any [ ] ;
56
57
filterParams : FilterParams ;
57
58
setFilterParams : ( filterParams : FilterParams ) => void ;
59
+ provider : string ;
58
60
}
59
61
60
62
const useSelectFilter = (
@@ -74,8 +76,7 @@ const useSelectFilter = (
74
76
const timeout = setTimeout ( ( ) => {
75
77
if ( value !== filterParams ?. [ property ] ) {
76
78
if ( value === '' || emptyCondition ?. includes ( value ) ) {
77
- const newFilterParams = { ...filterParams } ;
78
- delete newFilterParams [ property ] ;
79
+ const { [ property ] : removed , ...newFilterParams } = filterParams ;
79
80
setFilterParams ( newFilterParams ) ;
80
81
} else {
81
82
setFilterParams ( { ...filterParams , [ property ] : value } ) ;
@@ -149,32 +150,70 @@ const ProviderSelect: React.FC<ProviderSelectProps> = ({
149
150
} ;
150
151
151
152
const GenderSelect : React . FC < GenderSelectProps > = ( {
153
+ voices,
152
154
filterParams,
153
155
setFilterParams,
156
+ provider,
154
157
} ) => {
155
158
const [ value , setValue ] = useSelectFilter (
156
159
filterParams ,
157
160
setFilterParams ,
158
161
'gender' ,
159
- 0 ,
160
- VOICE_GENDERS . All ,
161
- [ VOICE_GENDERS . All ] ,
162
+ 1 ,
163
+ undefined ,
162
164
) ;
163
165
166
+ const handleClear = ( e : React . MouseEvent ) => {
167
+ e . stopPropagation ( ) ;
168
+ setValue ( undefined ) ;
169
+ const { accent, ...rest } = filterParams ;
170
+ setFilterParams ( rest ) ;
171
+ } ;
172
+
173
+ const hasGender = voices ?. some ( ( voice ) => voice . gender ) ;
174
+ let accentList = [
175
+ VOICE_GENDERS . Male ,
176
+ VOICE_GENDERS . Female ,
177
+ ...( voices
178
+ ?. filter ( ( voices ) => voices . gender )
179
+ ?. map ( ( voices ) => voices . gender ) ?? [ ] ) ,
180
+ ] ;
181
+ if ( provider === VOICE_PROVIDERS . ELEVEN_LABS ) {
182
+ accentList . push ( VOICE_GENDERS . Neutral ) ;
183
+ }
184
+ accentList = Array . from ( new Set ( accentList ) ) ;
164
185
return (
165
- < div className = "w-[20%]" >
166
- < Select value = { value } onValueChange = { ( value ) => setValue ( value ) } >
186
+ < div className = "w-[20%] relative" >
187
+ < Select
188
+ key = { `gender-select-${ provider } -${ value } ` }
189
+ value = { value }
190
+ onValueChange = { ( newValue ) => setValue ( newValue ) }
191
+ disabled = { ! hasGender }
192
+ >
167
193
< SelectTrigger >
168
194
< SelectValue placeholder = "Select Gender" />
169
195
</ SelectTrigger >
170
196
< SelectContent >
171
- { Object . values ( VOICE_GENDERS ) . map ( ( gender ) => (
197
+ { accentList . map ( ( gender ) => (
172
198
< SelectItem key = { gender } value = { gender } >
173
199
{ gender }
174
200
</ SelectItem >
175
201
) ) }
176
202
</ SelectContent >
177
203
</ Select >
204
+ { value && (
205
+ < button
206
+ type = "button"
207
+ className = "absolute right-10 top-1/2 transform -translate-y-1/2"
208
+ onClick = { handleClear }
209
+ >
210
+ < IconXmarkCircle
211
+ className = "fill-gray-400 w-[14px]"
212
+ width = { 14 }
213
+ height = { 14 }
214
+ />
215
+ </ button >
216
+ ) }
178
217
</ div >
179
218
) ;
180
219
} ;
@@ -183,50 +222,79 @@ const AccentSelect: React.FC<AccentSelectProps> = ({
183
222
accents,
184
223
filterParams,
185
224
setFilterParams,
225
+ provider,
186
226
} ) => {
187
227
const [ value , setValue ] = useSelectFilter (
188
228
filterParams ,
189
229
setFilterParams ,
190
230
'accent' ,
191
- 0 ,
231
+ 1 ,
192
232
undefined ,
193
233
) ;
194
234
235
+ const handleClear = ( e : React . MouseEvent ) => {
236
+ e . stopPropagation ( ) ;
237
+ setValue ( undefined ) ;
238
+ const { accent, ...rest } = filterParams ;
239
+ setFilterParams ( rest ) ;
240
+ } ;
241
+
242
+ const accentList = Array . from (
243
+ new Set (
244
+ accents ?. filter ( ( accent ) => accent . accent ) . map ( ( accent ) => accent . accent ) ,
245
+ ) ,
246
+ ) ;
247
+
195
248
return (
196
- < div className = "w-[20%]" >
197
- < Select value = { value } onValueChange = { ( value ) => setValue ( value ) } >
249
+ < div className = "w-[20%] relative" >
250
+ < Select
251
+ key = { `accent-select-${ provider } -${ value } ` }
252
+ disabled = { accentList . length === 0 }
253
+ value = { value }
254
+ onValueChange = { ( newValue ) => setValue ( newValue ) }
255
+ >
198
256
< SelectTrigger >
199
257
< SelectValue placeholder = "Select Accent" />
200
258
</ SelectTrigger >
201
259
< SelectContent className = "max-h-[200px]" >
202
- { accents &&
203
- accents . length &&
204
- accents
205
- . filter ( ( accent ) => accent . accent !== '' )
206
- . map ( ( accent , index ) => (
207
- < SelectItem key = { index } value = { accent . accent } >
208
- { accent . accent }
209
- </ SelectItem >
210
- ) ) }
260
+ { accentList . map ( ( accent , index ) => (
261
+ < SelectItem key = { index } value = { accent } >
262
+ { accent }
263
+ </ SelectItem >
264
+ ) ) }
211
265
</ SelectContent >
212
266
</ Select >
267
+ { value && (
268
+ < button
269
+ type = "button"
270
+ className = "absolute right-10 top-1/2 transform -translate-y-1/2"
271
+ onClick = { handleClear }
272
+ >
273
+ < IconXmarkCircle
274
+ className = "fill-gray-400 w-[14px]"
275
+ width = { 14 }
276
+ height = { 14 }
277
+ />
278
+ </ button >
279
+ ) }
213
280
</ div >
214
281
) ;
215
282
} ;
216
283
217
284
const VoiceLibrarySearch : React . FC < VoiceLibrarySearchProps > = ( {
285
+ voices,
218
286
handleProviderChange,
219
287
provider,
220
288
filterParams,
221
289
setFilterParams,
222
290
} ) => {
223
291
const [ accents , setAccents ] = useState < VoiceLibraryAccent [ ] > ( [ ] ) ;
224
292
225
- const { data : dataAccents } = useQuery ( {
293
+ const { data : dataAccents , refetch } = useQuery ( {
226
294
queryKey : [ 'accents' , provider ] ,
227
295
queryFn : async ( ) => {
228
296
const response =
229
- await client . voiceLibrary . voiceLibraryControllerAccentsGetByProvider (
297
+ await client . voiceLibrary . voiceLibraryControllerVoiceGetAccentsByProvider (
230
298
provider ,
231
299
) ;
232
300
if ( response . data ) {
@@ -240,6 +308,10 @@ const VoiceLibrarySearch: React.FC<VoiceLibrarySearchProps> = ({
240
308
useEffect ( ( ) => {
241
309
setAccents ( dataAccents ) ;
242
310
} , [ dataAccents ] ) ;
311
+ useEffect ( ( ) => {
312
+ refetch ( ) ;
313
+ } , [ provider , refetch ] ) ;
314
+
243
315
return (
244
316
provider && (
245
317
< >
@@ -255,26 +327,16 @@ const VoiceLibrarySearch: React.FC<VoiceLibrarySearchProps> = ({
255
327
< GenderSelect
256
328
filterParams = { filterParams }
257
329
setFilterParams = { setFilterParams }
330
+ provider = { provider }
331
+ voices = { voices }
258
332
/>
259
333
< AccentSelect
260
334
accents = { accents }
261
335
filterParams = { filterParams }
262
336
setFilterParams = { setFilterParams }
337
+ provider = { provider }
263
338
/>
264
339
</ div >
265
- < div className = "flex mt-24 mb-4 justify-end px-4" >
266
- { Object . prototype . hasOwnProperty . call ( filterParams , 'gender' ) ||
267
- ( Object . prototype . hasOwnProperty . call ( filterParams , 'accent' ) && (
268
- < Button
269
- size = "sm"
270
- className = "w-[100px] text-gray-500 text-xs"
271
- variant = "ghost"
272
- onClick = { ( ) => setFilterParams ( FILTER_PARAMS_DEFAULT ) }
273
- >
274
- Clear Filters
275
- </ Button >
276
- ) ) }
277
- </ div >
278
340
</ >
279
341
)
280
342
) ;
0 commit comments