@@ -52,15 +52,11 @@ let make = (
5252 -> Option .getOr ("" )
5353 let copy = values -> Dict .copy
5454
55- // Synchronize first_name and last_name to avoid different values during confirm call
56- // Case 1: If last_name exists but first_name is empty, use last_name as first_name
57- // (full name field uses first_name for tracking, so this ensures proper population)
58- if last_name -> String .length == 0 {
59- copy -> Dict .set (BillingAddress (FullName (LastName ))-> getPaymentMethodDataFieldKey , first_name )
60- } // Case 2: If first_name exists but last_name is empty, use first_name as last_name
55+ // If first_name exists but last_name is empty, use first_name as last_name
6156 // (since full name field is not rendered, we need this sync to maintain consistency)
62- else if first_name -> String .length == 0 {
57+ if first_name -> String .length == 0 {
6358 copy -> Dict .set (BillingAddress (FullName (FirstName ))-> getPaymentMethodDataFieldKey , last_name )
59+ copy -> Dict .set (BillingAddress (FullName (LastName ))-> getPaymentMethodDataFieldKey , "" )
6460 }
6561 setFormData (_ => copy )
6662 setValidityDict (_ => validity )
@@ -191,11 +187,7 @@ let make = (
191187 -> Array .slice (~start = 1 , ~end = nameSplits -> Array .length )
192188 -> Array .join (" " )
193189 setFormData (firstNameKey , firstName )
194- if lastName -> String .length > 0 {
195- setFormData (lastNameKey , lastName )
196- } else {
197- setFormData (lastNameKey , firstName )
198- }
190+ setFormData (lastNameKey , lastName )
199191 }
200192 | _ => ()
201193 }
@@ -247,6 +239,62 @@ let make = (
247239 | _ => React .null
248240 }
249241 }
242+
243+ let getErrorStringAndClasses = (field : dynamicFieldType ) => {
244+ let key = field -> getPaymentMethodDataFieldKey
245+ let value = formData -> Dict .get (key )-> Option .getOr ("" )
246+ let isValid = validityDict -> Dict .get (key )-> Option .flatMap (key => key )
247+
248+ switch field {
249+ | BillingAddress (FullName (FirstName )) => {
250+ // Check both FirstName and LastName validity and merge error messages
251+ let firstNameKey = BillingAddress (FullName (FirstName ))-> getPaymentMethodDataFieldKey
252+ let lastNameKey = BillingAddress (FullName (LastName ))-> getPaymentMethodDataFieldKey
253+ let firstNameValue = formData -> Dict .get (firstNameKey )-> Option .getOr ("" )
254+ let lastNameValue = formData -> Dict .get (lastNameKey )-> Option .getOr ("" )
255+ let firstNameValid = validityDict -> Dict .get (firstNameKey )-> Option .flatMap (key => key )
256+ let lastNameValid = validityDict -> Dict .get (lastNameKey )-> Option .flatMap (key => key )
257+
258+ let firstNameError = switch firstNameValid {
259+ | Some (false ) =>
260+ BillingAddress (FullName (FirstName ))-> getPaymentMethodDataErrorString (
261+ firstNameValue ,
262+ localeString ,
263+ )
264+ | _ => ""
265+ }
266+
267+ let lastNameError = switch lastNameValid {
268+ | Some (false ) =>
269+ BillingAddress (FullName (LastName ))-> getPaymentMethodDataErrorString (
270+ lastNameValue ,
271+ localeString ,
272+ )
273+ | _ => ""
274+ }
275+
276+ let mergedError = switch (firstNameError , lastNameError ) {
277+ | ("" , "" ) => ""
278+ | (firstError , "" ) => firstError
279+ | ("" , lastError ) => lastError
280+ | (firstError , lastError ) => firstError ++ " " ++ lastError
281+ }
282+
283+ let hasError = mergedError !== ""
284+ (mergedError , hasError ? "text-xs text-red-950" : "" )
285+ }
286+ | _ =>
287+ // Default behavior for other fields
288+ switch isValid {
289+ | Some (false ) => (
290+ field -> getPaymentMethodDataErrorString (value , localeString ),
291+ "text-xs text-red-950" ,
292+ )
293+ | _ => ("" , "" )
294+ }
295+ }
296+ }
297+
250298 let renderInputTemplate = (field : dynamicFieldType ) => {
251299 let labelClasses = "text-sm mt-2.5 text-jp-gray-800"
252300 let inputClasses = "min-w-full border mt-1.5 px-2.5 py-2 rounded-md border-jp-gray-200"
@@ -277,14 +325,7 @@ let make = (
277325 -> Js .Re .source
278326 let key = field -> getPaymentMethodDataFieldKey
279327 let value = formData -> Dict .get (key )-> Option .getOr ("" )
280- let isValid = validityDict -> Dict .get (key )-> Option .flatMap (key => key )
281- let (errorString , errorStringClasses ) = switch isValid {
282- | Some (false ) => (
283- field -> getPaymentMethodDataErrorString (value , localeString ),
284- "text-xs text-red-950" ,
285- )
286- | _ => ("" , "" )
287- }
328+ let (errorString , errorStringClasses ) = getErrorStringAndClasses (field )
288329 <InputField
289330 id = key
290331 className = inputClasses
@@ -319,13 +360,29 @@ let make = (
319360 pattern
320361 />
321362 }
363+ let checkIfLastNameRequiredAndNone = (addressFields : array <dynamicFieldForAddress >) => {
364+ addressFields -> Array .reduce (false , (acc , field ) => {
365+ let condition = switch (field .fieldType , field .value ) {
366+ | (FullName (LastName ), None ) => true
367+ | _ => false
368+ }
369+ acc || condition
370+ })
371+ }
322372 let renderAddressForm = (addressFields : array <dynamicFieldForAddress >) =>
323373 addressFields
324374 -> Array .mapWithIndex ((field , index ) =>
325375 <React .Fragment key = {index -> Int .toString }>
326376 {switch (field .fieldType , field .value ) {
327377 | (Email , None ) => BillingAddress (Email )-> renderInputTemplate
328378 | (FullName (FirstName ), None ) => BillingAddress (FullName (FirstName ))-> renderInputTemplate
379+ | (FullName (FirstName ), Some (_ )) =>
380+ // If first_name exists, last_name is required and has null value, render first_name field to capture last_name
381+ if checkIfLastNameRequiredAndNone (addressFields ) {
382+ BillingAddress (FullName (FirstName ))-> renderInputTemplate
383+ } else {
384+ React .null
385+ }
329386 // first_name and last_name are stored in fullName
330387 | (FullName (LastName ), _ ) => React .null
331388 | (CountryCode , None ) => BillingAddress (CountryCode )-> renderInputTemplate
0 commit comments