1
1
"use client" ;
2
2
3
3
import type { Project } from "@/api/projects" ;
4
+ import type { SMSCountryTiers } from "@/api/sms" ;
4
5
import { DynamicHeight } from "@/components/ui/DynamicHeight" ;
5
6
import { Spinner } from "@/components/ui/Spinner/Spinner" ;
6
7
import { UnderlineLink } from "@/components/ui/UnderlineLink" ;
@@ -36,13 +37,15 @@ import { type UseFormReturn, useFieldArray, useForm } from "react-hook-form";
36
37
import { toast } from "sonner" ;
37
38
import { toArrFromList } from "utils/string" ;
38
39
import type { Team } from "../../../@/api/team" ;
40
+ import CountrySelector from "./sms-country-select/country-selector" ;
39
41
40
42
type InAppWalletSettingsPageProps = {
41
43
trackingCategory : string ;
42
44
project : Project ;
43
45
teamId : string ;
44
46
teamSlug : string ;
45
47
validTeamPlan : Team [ "billingPlan" ] ;
48
+ smsCountryTiers : SMSCountryTiers ;
46
49
} ;
47
50
48
51
const TRACKING_CATEGORY = "embedded-wallet" ;
@@ -108,6 +111,7 @@ export function InAppWalletSettingsPage(props: InAppWalletSettingsPageProps) {
108
111
canEditAdvancedFeatures = { props . validTeamPlan !== "free" }
109
112
updateApiKey = { handleUpdateProject }
110
113
isUpdating = { updateProject . isPending }
114
+ smsCountryTiers = { props . smsCountryTiers }
111
115
/>
112
116
) ;
113
117
}
@@ -120,6 +124,7 @@ const InAppWalletSettingsPageUI: React.FC<
120
124
trackingData : UpdateAPIKeyTrackingData ,
121
125
) => void ;
122
126
isUpdating : boolean ;
127
+ smsCountryTiers : SMSCountryTiers ;
123
128
}
124
129
> = ( props ) => {
125
130
const embeddedWalletService = props . project . services . find (
@@ -185,6 +190,11 @@ export const InAppWalletSettingsUI: React.FC<
185
190
}
186
191
: undefined ) ,
187
192
redirectUrls : ( config . redirectUrls || [ ] ) . join ( "\n" ) ,
193
+ smsEnabledCountryISOs : config . smsEnabledCountryISOs
194
+ ? config . smsEnabledCountryISOs
195
+ : canEditAdvancedFeatures
196
+ ? [ "US" , "CA" ]
197
+ : [ ] ,
188
198
} ,
189
199
} ) ;
190
200
@@ -228,6 +238,7 @@ export const InAppWalletSettingsUI: React.FC<
228
238
applicationImageUrl : branding ?. applicationImageUrl ,
229
239
applicationName : branding ?. applicationName || props . project . name ,
230
240
redirectUrls : toArrFromList ( redirectUrls || "" , true ) ,
241
+ smsEnabledCountryISOs : values . smsEnabledCountryISOs ,
231
242
} ;
232
243
} ) ;
233
244
@@ -256,6 +267,8 @@ export const InAppWalletSettingsUI: React.FC<
256
267
canEditAdvancedFeatures = { canEditAdvancedFeatures }
257
268
/>
258
269
270
+ < NativeAppsFieldset form = { form } />
271
+
259
272
{ /* Authentication */ }
260
273
< Fieldset legend = "Authentication" >
261
274
< JSONWebTokenFields
@@ -269,9 +282,15 @@ export const InAppWalletSettingsUI: React.FC<
269
282
form = { form }
270
283
canEditAdvancedFeatures = { canEditAdvancedFeatures }
271
284
/>
272
- </ Fieldset >
273
285
274
- < NativeAppsFieldset form = { form } />
286
+ < div className = "h-5" />
287
+
288
+ < SMSCountryFields
289
+ form = { form }
290
+ canEditAdvancedFeatures = { canEditAdvancedFeatures }
291
+ smsCountryTiers = { props . smsCountryTiers }
292
+ />
293
+ </ Fieldset >
275
294
276
295
< div className = "flex justify-end" >
277
296
< Button type = "submit" variant = "primary" className = "gap-2" >
@@ -364,6 +383,61 @@ function BrandingFieldset(props: {
364
383
) ;
365
384
}
366
385
386
+ function SMSCountryFields ( props : {
387
+ form : UseFormReturn < ApiKeyEmbeddedWalletsValidationSchema > ;
388
+ canEditAdvancedFeatures : boolean ;
389
+ smsCountryTiers : SMSCountryTiers ;
390
+ } ) {
391
+ return (
392
+ < div >
393
+ < SwitchContainer
394
+ switchId = "sms-switch"
395
+ title = "SMS"
396
+ description = "Optionally allow users in selected countries to login via SMS OTP."
397
+ >
398
+ < GatedSwitch
399
+ id = "sms-switch"
400
+ trackingLabel = "sms"
401
+ checked = {
402
+ ! ! props . form . watch ( "smsEnabledCountryISOs" ) . length &&
403
+ props . canEditAdvancedFeatures
404
+ }
405
+ upgradeRequired = { ! props . canEditAdvancedFeatures }
406
+ onCheckedChange = { ( checked ) =>
407
+ props . form . setValue (
408
+ "smsEnabledCountryISOs" ,
409
+ checked
410
+ ? // by default, enable US and CA only
411
+ [ "US" , "CA" ]
412
+ : [ ] ,
413
+ )
414
+ }
415
+ />
416
+ </ SwitchContainer >
417
+
418
+ < AdvancedConfigurationContainer
419
+ className = "grid grid-cols-1"
420
+ show = {
421
+ props . canEditAdvancedFeatures &&
422
+ ! ! props . form . watch ( "smsEnabledCountryISOs" ) . length
423
+ }
424
+ >
425
+ < FormField
426
+ control = { props . form . control }
427
+ name = "smsEnabledCountryISOs"
428
+ render = { ( { field } ) => (
429
+ < CountrySelector
430
+ countryTiers = { props . smsCountryTiers }
431
+ selected = { field . value }
432
+ onChange = { field . onChange }
433
+ />
434
+ ) }
435
+ />
436
+ </ AdvancedConfigurationContainer >
437
+ </ div >
438
+ ) ;
439
+ }
440
+
367
441
function JSONWebTokenFields ( props : {
368
442
form : UseFormReturn < ApiKeyEmbeddedWalletsValidationSchema > ;
369
443
canEditAdvancedFeatures : boolean ;
0 commit comments