boxpay-checkout-reactnative-sdk 1.0.11-beta → 1.0.11-beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/lib/module/components/checkboxContainer.js +1 -1
  2. package/lib/module/components/header.js +1 -1
  3. package/lib/module/components/header.js.map +1 -1
  4. package/lib/module/components/paymentSelector.js +1 -1
  5. package/lib/module/components/paymentSelector.js.map +1 -1
  6. package/lib/module/components/paymentSuccess.js +2 -7
  7. package/lib/module/components/paymentSuccess.js.map +1 -1
  8. package/lib/module/components/savedCardComponent.js +1 -1
  9. package/lib/module/components/savedCardComponent.js.map +1 -1
  10. package/lib/module/components/subscriptionRow.js +33 -0
  11. package/lib/module/components/subscriptionRow.js.map +1 -0
  12. package/lib/module/interface.js +1 -0
  13. package/lib/module/interface.js.map +1 -1
  14. package/lib/module/screens/addressScreen.js +11 -60
  15. package/lib/module/screens/addressScreen.js.map +1 -1
  16. package/lib/module/screens/cardScreen.js +488 -447
  17. package/lib/module/screens/cardScreen.js.map +1 -1
  18. package/lib/module/screens/emiScreen.js +2 -6
  19. package/lib/module/screens/emiScreen.js.map +1 -1
  20. package/lib/module/screens/instantOfferList.js +2 -6
  21. package/lib/module/screens/instantOfferList.js.map +1 -1
  22. package/lib/module/screens/mainScreen.js +50 -2
  23. package/lib/module/screens/mainScreen.js.map +1 -1
  24. package/lib/module/screens/netBankingScreen.js +2 -6
  25. package/lib/module/screens/netBankingScreen.js.map +1 -1
  26. package/lib/module/screens/upiScreen.js +2 -6
  27. package/lib/module/screens/upiScreen.js.map +1 -1
  28. package/lib/module/screens/walletScreen.js +2 -6
  29. package/lib/module/screens/walletScreen.js.map +1 -1
  30. package/lib/module/sdk-version.json +1 -1
  31. package/lib/module/sharedContext/checkoutDetailsHandler.js +8 -2
  32. package/lib/module/sharedContext/checkoutDetailsHandler.js.map +1 -1
  33. package/lib/module/sharedContext/getTextInputTheme.js +15 -0
  34. package/lib/module/sharedContext/getTextInputTheme.js.map +1 -0
  35. package/lib/module/styles/indexStyles.js +1 -1
  36. package/lib/module/styles/indexStyles.js.map +1 -1
  37. package/lib/module/styles/screens/bnplScreenStyles.js +2 -3
  38. package/lib/module/styles/screens/bnplScreenStyles.js.map +1 -1
  39. package/lib/module/styles/screens/cardScreenStyles.js +9 -4
  40. package/lib/module/styles/screens/cardScreenStyles.js.map +1 -1
  41. package/lib/module/styles/screens/netBankingScreenStyles.js +2 -3
  42. package/lib/module/styles/screens/netBankingScreenStyles.js.map +1 -1
  43. package/lib/module/styles/screens/walletScreenStyles.js +2 -3
  44. package/lib/module/styles/screens/walletScreenStyles.js.map +1 -1
  45. package/lib/module/utility.js +16 -0
  46. package/lib/module/utility.js.map +1 -1
  47. package/lib/typescript/src/components/subscriptionRow.d.ts +9 -0
  48. package/lib/typescript/src/components/subscriptionRow.d.ts.map +1 -0
  49. package/lib/typescript/src/interface.d.ts +26 -2
  50. package/lib/typescript/src/interface.d.ts.map +1 -1
  51. package/lib/typescript/src/screens/addressScreen.d.ts.map +1 -1
  52. package/lib/typescript/src/screens/cardScreen.d.ts +1 -1
  53. package/lib/typescript/src/screens/cardScreen.d.ts.map +1 -1
  54. package/lib/typescript/src/screens/emiScreen.d.ts.map +1 -1
  55. package/lib/typescript/src/screens/instantOfferList.d.ts.map +1 -1
  56. package/lib/typescript/src/screens/mainScreen.d.ts.map +1 -1
  57. package/lib/typescript/src/screens/netBankingScreen.d.ts.map +1 -1
  58. package/lib/typescript/src/screens/upiScreen.d.ts.map +1 -1
  59. package/lib/typescript/src/screens/walletScreen.d.ts.map +1 -1
  60. package/lib/typescript/src/sharedContext/checkoutDetailsHandler.d.ts.map +1 -1
  61. package/lib/typescript/src/sharedContext/getTextInputTheme.d.ts +7 -0
  62. package/lib/typescript/src/sharedContext/getTextInputTheme.d.ts.map +1 -0
  63. package/lib/typescript/src/styles/indexStyles.d.ts +1 -1
  64. package/lib/typescript/src/styles/screens/bnplScreenStyles.d.ts +1 -2
  65. package/lib/typescript/src/styles/screens/bnplScreenStyles.d.ts.map +1 -1
  66. package/lib/typescript/src/styles/screens/cardScreenStyles.d.ts +8 -3
  67. package/lib/typescript/src/styles/screens/cardScreenStyles.d.ts.map +1 -1
  68. package/lib/typescript/src/styles/screens/netBankingScreenStyles.d.ts +1 -2
  69. package/lib/typescript/src/styles/screens/netBankingScreenStyles.d.ts.map +1 -1
  70. package/lib/typescript/src/styles/screens/walletScreenStyles.d.ts +1 -2
  71. package/lib/typescript/src/styles/screens/walletScreenStyles.d.ts.map +1 -1
  72. package/lib/typescript/src/utility.d.ts +2 -0
  73. package/lib/typescript/src/utility.d.ts.map +1 -1
  74. package/package.json +2 -2
  75. package/src/components/checkboxContainer.tsx +1 -1
  76. package/src/components/header.tsx +1 -1
  77. package/src/components/paymentSelector.tsx +1 -1
  78. package/src/components/paymentSuccess.tsx +3 -5
  79. package/src/components/savedCardComponent.tsx +1 -1
  80. package/src/components/subscriptionRow.tsx +19 -0
  81. package/src/interface.ts +24 -2
  82. package/src/screens/addressScreen.tsx +11 -60
  83. package/src/screens/cardScreen.tsx +188 -124
  84. package/src/screens/emiScreen.tsx +2 -6
  85. package/src/screens/instantOfferList.tsx +2 -6
  86. package/src/screens/mainScreen.tsx +54 -3
  87. package/src/screens/netBankingScreen.tsx +2 -6
  88. package/src/screens/upiScreen.tsx +2 -6
  89. package/src/screens/walletScreen.tsx +2 -6
  90. package/src/sdk-version.json +1 -1
  91. package/src/sharedContext/checkoutDetailsHandler.ts +8 -2
  92. package/src/sharedContext/getTextInputTheme.ts +12 -0
  93. package/src/styles/indexStyles.ts +1 -1
  94. package/src/styles/screens/bnplScreenStyles.ts +2 -3
  95. package/src/styles/screens/cardScreenStyles.ts +3 -4
  96. package/src/styles/screens/netBankingScreenStyles.ts +2 -3
  97. package/src/styles/screens/walletScreenStyles.ts +2 -3
  98. package/src/utility.ts +24 -1
@@ -1,38 +1,43 @@
1
+ import type { NavigationProp, RouteProp } from '@react-navigation/native';
2
+ import LottieView from 'lottie-react-native';
3
+ import { useEffect, useRef, useState } from 'react';
1
4
  import {
2
- View,
3
- Text,
4
- Image,
5
5
  BackHandler,
6
+ Image,
7
+ InputAccessoryView,
8
+ Keyboard,
9
+ Platform,
6
10
  Pressable,
11
+ ScrollView,
12
+ Text,
7
13
  TouchableOpacity,
8
- ScrollView
14
+ View
9
15
  } from 'react-native';
10
- import { useEffect, useRef, useState } from 'react';
11
- import Header from '../components/header';
12
- import type { RouteProp, NavigationProp } from '@react-navigation/native';
13
16
  import { TextInput } from 'react-native-paper';
14
- import LottieView from 'lottie-react-native';
15
- import fetchCardDetails from '../postRequest/fetchCardDetails';
16
- import { checkoutDetailsHandler, setCheckOutDetailsHandlerToDefault } from '../sharedContext/checkoutDetailsHandler';
17
- import cardPostRequest from '../postRequest/cardPostRequest';
17
+ import ShimmerPlaceHolder from 'react-native-shimmer-placeholder';
18
+ import { SvgUri } from 'react-native-svg';
19
+ import Toast from 'react-native-toast-message';
20
+ import CheckBoxContainer from '../components/checkboxContainer';
21
+ import CvvInfoBottomSheet from '../components/cvvInfoBottomSheet';
22
+ import Header from '../components/header';
23
+ import KnowMoreBottomSheet from '../components/knowMoreBottomSheet';
18
24
  import PaymentFailed from '../components/paymentFailed';
19
25
  import PaymentSuccess from '../components/paymentSuccess';
20
26
  import SessionExpire from '../components/sessionExpire';
21
- import { APIStatus, type PaymentResultObject , type CardScreenParams} from '../interface';
22
- import { paymentHandler } from '../sharedContext/paymentStatusHandler';
23
- import CvvInfoBottomSheet from '../components/cvvInfoBottomSheet';
24
- import WebViewScreen from './webViewScreen';
25
- import fetchStatus from '../postRequest/fetchStatus';
26
- import { SvgUri } from 'react-native-svg';
27
- import ShimmerPlaceHolder from 'react-native-shimmer-placeholder';
27
+ import { APIStatus, type CardScreenParams, type PaymentResultObject } from '../interface';
28
+ import type { CheckoutStackParamList } from '../navigation';
29
+ import cardPostRequest from '../postRequest/cardPostRequest';
28
30
  import emiPostRequest from '../postRequest/emiPostRequest';
29
- import KnowMoreBottomSheet from '../components/knowMoreBottomSheet';
30
- import styles from '../styles/screens/cardScreenStyles';
31
- import Toast from 'react-native-toast-message'
31
+ import fetchCardDetails from '../postRequest/fetchCardDetails';
32
+ import fetchStatus from '../postRequest/fetchStatus';
33
+ import { checkoutDetailsHandler, setCheckOutDetailsHandlerToDefault } from '../sharedContext/checkoutDetailsHandler';
32
34
  import { handleFetchStatusResponseHandler, handlePaymentResponse } from '../sharedContext/handlePaymentResponseHandler';
33
- import type { CheckoutStackParamList } from '../navigation';
35
+ import { paymentHandler } from '../sharedContext/paymentStatusHandler';
34
36
  import { setUserDataHandlerToDefault } from '../sharedContext/userdataHandler';
35
- import CheckBoxContainer from '../components/checkboxContainer';
37
+ import styles from '../styles/screens/cardScreenStyles';
38
+ import WebViewScreen from './webViewScreen';
39
+ import SubscriptionRow from '../components/subscriptionRow';
40
+ import { getTextInputTheme } from '../sharedContext/getTextInputTheme';
36
41
 
37
42
  type CardScreenRouteProp = RouteProp<CheckoutStackParamList, 'CardScreen'>;
38
43
 
@@ -75,7 +80,7 @@ const CardScreen = ({ route, navigation }: Props) => {
75
80
  const [cardNickNameText, setCardNickNameText] = useState<string | null>(null);
76
81
 
77
82
  const [cardSelectedIcon, setCardSelectedIcon] = useState(
78
- require('../../assets/images/ic_default_card.png')
83
+ require('../../assets/images/ic_card.png')
79
84
  );
80
85
  const [maxCvvLength, setMaxCvvLength] = useState(4);
81
86
  const [maxCardNumberLength, setMaxCardNumberLength] = useState(19);
@@ -137,6 +142,12 @@ const CardScreen = ({ route, navigation }: Props) => {
137
142
  const [emiIssuer, setEmiIssuer] = useState('');
138
143
  const [shopperToken, setShopperToken] = useState<string | null>(null);
139
144
 
145
+ const cardNumberAccessoryID = "cardNumberAccessoryID";
146
+ const cardExpiryAccessoryID = "cardExpiryAccessoryID";
147
+ const cardCvvAccessoryID = "cardCvvAccessoryID";
148
+ const cardHolderNameAccessoryID = "cardHolderNameAccessoryID";
149
+ const cardNickNameAccessoryID = "cardNickNameAccessoryID";
150
+
140
151
  const handleCardNumberTextChange = async (text: string) => {
141
152
  if (text == '') {
142
153
  setCardNumberText(text);
@@ -191,7 +202,7 @@ const CardScreen = ({ route, navigation }: Props) => {
191
202
  setMaxCardNumberLength(19);
192
203
  } else {
193
204
  setCardSelectedIcon(
194
- require('../../assets/images/ic_default_card.png')
205
+ require('../../assets/images/ic_card.png')
195
206
  );
196
207
  setMaxCvvLength(3);
197
208
  setMaxCardNumberLength(19);
@@ -214,13 +225,17 @@ const CardScreen = ({ route, navigation }: Props) => {
214
225
  });
215
226
  }
216
227
  } else {
217
- setCardSelectedIcon(require('../../assets/images/ic_default_card.png'));
228
+ setCardSelectedIcon(require('../../assets/images/ic_card.png'));
218
229
  setMaxCvvLength(3);
219
230
  setMaxCardNumberLength(19);
220
231
  }
221
232
  }
222
233
  };
223
234
 
235
+ const isSubscriptionDetailsVisible =
236
+ checkoutDetails.isSubscriptionCheckout &&
237
+ (isSICheckBoxClicked || !checkoutDetails.isSICheckboxVisible);
238
+
224
239
  const isValidCardNumberByLuhn = (stringInputCardNumber: string): boolean => {
225
240
  const minCardLength = 13;
226
241
 
@@ -254,7 +269,7 @@ const CardScreen = ({ route, navigation }: Props) => {
254
269
  const cleanedLength = maxCardNumberLength == 19 ? 16 : 15;
255
270
  setCardNumberErrorText(
256
271
  cleaned.length < 1
257
- ? 'Required'
272
+ ? 'Card Number is required'
258
273
  : checkoutDetails.env === 'test'
259
274
  ? ''
260
275
  : cleaned.length < cleanedLength
@@ -377,7 +392,7 @@ const CardScreen = ({ route, navigation }: Props) => {
377
392
  const cleaned = cardExpiryText?.replace(/ /g, '') || '';
378
393
  setCardExpiryErrorText(
379
394
  cleaned.length < 1
380
- ? 'Required'
395
+ ? 'Expiry is required'
381
396
  : cleaned.length < 5 || !cardExpiryValid
382
397
  ? 'Expiry is invalid'
383
398
  : ''
@@ -390,7 +405,7 @@ const CardScreen = ({ route, navigation }: Props) => {
390
405
  const cleaned = cardCvvText?.replace(/ /g, '') || '';
391
406
  setCardCvvErrorText(
392
407
  cleaned.length < 1
393
- ? 'Required'
408
+ ? 'CVV is required'
394
409
  : cleaned.length < maxCvvLength
395
410
  ? 'CVV is invalid'
396
411
  : ''
@@ -401,7 +416,7 @@ const CardScreen = ({ route, navigation }: Props) => {
401
416
 
402
417
  const handleCardHolderNameBlur = () => {
403
418
  const cleaned = cardHolderNameText?.replace(/ /g, '') || '';
404
- setCardHolderNameErrorText(cleaned.length < 1 ? 'Required' : '');
419
+ setCardHolderNameErrorText(cleaned.length < 1 ? 'Name is required' : '');
405
420
  setCardHolderNameFocused(false);
406
421
  setCardHolderNameError(cleaned.length < 1);
407
422
  };
@@ -409,7 +424,7 @@ const CardScreen = ({ route, navigation }: Props) => {
409
424
  const handleCardCvvTextChange = (text: string) => {
410
425
  setCardCvvText(text);
411
426
  if (text == '') {
412
- setCardCvvErrorText('Required');
427
+ setCardCvvErrorText('CVV is required');
413
428
  setCardCvvError(true);
414
429
  } else {
415
430
  setCardCvvError(false);
@@ -582,7 +597,8 @@ const CardScreen = ({ route, navigation }: Props) => {
582
597
  }, [paymentHtml]);
583
598
 
584
599
  return (
585
- <View style={styles.screenView}>
600
+ <>
601
+ <View style={styles.screenView}>
586
602
  {loading ? (
587
603
  <View
588
604
  style={styles.loadingContainer}
@@ -685,21 +701,18 @@ const CardScreen = ({ route, navigation }: Props) => {
685
701
  fontFamily: checkoutDetails.fontFamily.regular,
686
702
  }]}
687
703
  >
688
- Card Number
704
+ Card Number*
689
705
  </Text>
690
706
  }
691
707
  value={cardNumberText || ''}
692
708
  onChangeText={(it) => {
693
709
  handleCardNumberTextChange(it);
694
710
  }}
695
- theme={{
696
- colors: {
697
- primary: '#2D2B32',
698
- outline: '#E6E6E6',
699
- },
700
- }}
711
+ theme={getTextInputTheme()}
712
+ inputAccessoryViewID={Platform.OS === 'ios' ? cardNumberAccessoryID : undefined}
701
713
  style={[styles.textInput, { marginTop: 28, marginHorizontal: 16, fontFamily: checkoutDetails.fontFamily.regular, }]}
702
714
  error={cardNumberError}
715
+ returnKeyType="done"
703
716
  right={
704
717
  cardNumberError ? (
705
718
  <TextInput.Icon
@@ -715,7 +728,10 @@ const CardScreen = ({ route, navigation }: Props) => {
715
728
  icon={() => (
716
729
  <Image
717
730
  source={cardSelectedIcon}
718
- style={{ width: 35, height: 20 }}
731
+ style={{ width: 32, height: 20,tintColor:
732
+ cardSelectedIcon === require('../../assets/images/ic_card.png')
733
+ ? '#6B7280' // Cool Grey 500
734
+ : undefined, }}
719
735
  />
720
736
  )}
721
737
  />
@@ -735,11 +751,65 @@ const CardScreen = ({ route, navigation }: Props) => {
735
751
  />
736
752
  {cardNumberError && (
737
753
  <Text
738
- style={[styles.errorText, { fontFamily: checkoutDetails.fontFamily.regular,}]}
754
+ style={[styles.errorText, { fontFamily: checkoutDetails.fontFamily.regular,marginHorizontal : 16}]}
739
755
  >
740
756
  {cardNumberErrorText}
741
757
  </Text>
742
758
  )}
759
+ <TextInput
760
+ mode="outlined"
761
+ label={
762
+ <Text
763
+ style={[styles.textFieldLabel,{
764
+ color: cardHolderNameFocused
765
+ ? '#2D2B32'
766
+ : cardHolderNameText != '' && cardHolderNameText != null
767
+ ? '#2D2B32'
768
+ : '#ADACB0',
769
+ fontFamily: checkoutDetails.fontFamily.regular,
770
+ }]}
771
+ >
772
+ Cardholder Name*
773
+ </Text>
774
+ }
775
+ value={cardHolderNameText || ''}
776
+ onChangeText={(it) => {
777
+ handleCardHolderNameTextChange(it);
778
+ }}
779
+ theme={getTextInputTheme()}
780
+ style={[styles.textInput, { marginHorizontal: 16, marginTop: 16, fontFamily: checkoutDetails.fontFamily.regular, }]}
781
+ error={cardHolderNameError}
782
+ inputAccessoryViewID={Platform.OS === 'ios' ? cardHolderNameAccessoryID : undefined}
783
+ returnKeyType="done"
784
+ right={
785
+ cardHolderNameError ? (
786
+ <TextInput.Icon
787
+ icon={() => (
788
+ <Image
789
+ source={require('../../assets/images/ic_upi_error.png')}
790
+ style={{ width: 24, height: 24 }}
791
+ />
792
+ )}
793
+ />
794
+ ) : null
795
+ }
796
+ outlineStyle={{
797
+ borderRadius: 8, // Add this
798
+ borderWidth: 1.5,
799
+ }}
800
+ onBlur={handleCardHolderNameBlur}
801
+ onFocus={() => {
802
+ setCardHolderNameFocused(true);
803
+ setCardHolderNameError(false);
804
+ }}
805
+ />
806
+ {cardHolderNameError && (
807
+ <Text
808
+ style={[styles.errorText, { fontFamily: checkoutDetails.fontFamily.regular,marginHorizontal : 16}]}
809
+ >
810
+ {cardHolderNameErrorText}
811
+ </Text>
812
+ )}
743
813
  <View
744
814
  style={styles.expiryCvvContainer}
745
815
  >
@@ -757,21 +827,18 @@ const CardScreen = ({ route, navigation }: Props) => {
757
827
  fontFamily: checkoutDetails.fontFamily.regular,
758
828
  }]}
759
829
  >
760
- Expiry (MM/YY)
830
+ Expiry (MM/YY)*
761
831
  </Text>
762
832
  }
763
833
  value={cardExpiryText || ''}
764
834
  onChangeText={(it) => {
765
835
  handleCardExpiryTextChange(it);
766
836
  }}
767
- theme={{
768
- colors: {
769
- primary: '#2D2B32',
770
- outline: '#E6E6E6',
771
- },
772
- }}
837
+ theme={getTextInputTheme()}
838
+ inputAccessoryViewID={Platform.OS === 'ios' ? cardExpiryAccessoryID : undefined}
773
839
  style={[styles.textInput, {fontFamily: checkoutDetails.fontFamily.regular,}]}
774
840
  error={cardExpiryError}
841
+ returnKeyType="done"
775
842
  right={
776
843
  cardExpiryError ? (
777
844
  <TextInput.Icon
@@ -818,21 +885,18 @@ const CardScreen = ({ route, navigation }: Props) => {
818
885
  fontFamily: checkoutDetails.fontFamily.regular,
819
886
  }]}
820
887
  >
821
- CVV
888
+ CVV*
822
889
  </Text>
823
890
  }
824
891
  value={cardCvvText || ''}
825
892
  onChangeText={(it) => {
826
893
  handleCardCvvTextChange(it);
827
894
  }}
828
- theme={{
829
- colors: {
830
- primary: '#2D2B32',
831
- outline: '#E6E6E6',
832
- },
833
- }}
895
+ theme={getTextInputTheme()}
896
+ inputAccessoryViewID={Platform.OS === 'ios' ? cardCvvAccessoryID : undefined}
834
897
  style={[styles.textInput, {fontFamily: checkoutDetails.fontFamily.regular,}]}
835
898
  error={cardCvvError}
899
+ returnKeyType="done"
836
900
  right={
837
901
  cardCvvError ? (
838
902
  <TextInput.Icon
@@ -847,8 +911,8 @@ const CardScreen = ({ route, navigation }: Props) => {
847
911
  <TextInput.Icon
848
912
  icon={() => (
849
913
  <Image
850
- source={require('../../assets/images/ic_cvv_info.png')}
851
- style={{ width: 24, height: 24 }}
914
+ source={require('../../assets/images/ic_info.png')}
915
+ style={{ width: 24, height: 24, tintColor : checkoutDetails.buttonColor }}
852
916
  />
853
917
  )}
854
918
  onPress={() => {
@@ -879,63 +943,6 @@ const CardScreen = ({ route, navigation }: Props) => {
879
943
  )}
880
944
  </View>
881
945
  </View>
882
- <TextInput
883
- mode="outlined"
884
- label={
885
- <Text
886
- style={[styles.textFieldLabel,{
887
- color: cardHolderNameFocused
888
- ? '#2D2B32'
889
- : cardHolderNameText != '' && cardHolderNameText != null
890
- ? '#2D2B32'
891
- : '#ADACB0',
892
- fontFamily: checkoutDetails.fontFamily.regular,
893
- }]}
894
- >
895
- Name on the Card
896
- </Text>
897
- }
898
- value={cardHolderNameText || ''}
899
- onChangeText={(it) => {
900
- handleCardHolderNameTextChange(it);
901
- }}
902
- theme={{
903
- colors: {
904
- primary: '#2D2B32',
905
- outline: '#E6E6E6',
906
- },
907
- }}
908
- style={[styles.textInput, { marginHorizontal: 16, marginTop: 16, fontFamily: checkoutDetails.fontFamily.regular, }]}
909
- error={cardHolderNameError}
910
- right={
911
- cardHolderNameError ? (
912
- <TextInput.Icon
913
- icon={() => (
914
- <Image
915
- source={require('../../assets/images/ic_upi_error.png')}
916
- style={{ width: 24, height: 24 }}
917
- />
918
- )}
919
- />
920
- ) : null
921
- }
922
- outlineStyle={{
923
- borderRadius: 8, // Add this
924
- borderWidth: 1.5,
925
- }}
926
- onBlur={handleCardHolderNameBlur}
927
- onFocus={() => {
928
- setCardHolderNameFocused(true);
929
- setCardHolderNameError(false);
930
- }}
931
- />
932
- {cardHolderNameError && (
933
- <Text
934
- style={[styles.errorText, { fontFamily: checkoutDetails.fontFamily.regular,}]}
935
- >
936
- {cardHolderNameErrorText}
937
- </Text>
938
- )}
939
946
  {shopperToken != null && shopperToken != '' && (
940
947
  <>
941
948
  <TextInput
@@ -958,16 +965,13 @@ const CardScreen = ({ route, navigation }: Props) => {
958
965
  onChangeText={(it) => {
959
966
  setCardNickNameText(it);
960
967
  }}
961
- theme={{
962
- colors: {
963
- primary: '#2D2B32',
964
- outline: '#E6E6E6',
965
- },
966
- }}
968
+ inputAccessoryViewID={Platform.OS === 'ios' ? cardNickNameAccessoryID : undefined}
969
+ theme={getTextInputTheme()}
967
970
  style={[
968
971
  styles.textInput,
969
972
  { marginHorizontal: 16, marginTop: 16 , fontFamily: checkoutDetails.fontFamily.regular,},
970
973
  ]}
974
+ returnKeyType="done"
971
975
  outlineStyle={{
972
976
  borderRadius: 8, // Add this
973
977
  borderWidth: 1.5,
@@ -1042,6 +1046,20 @@ const CardScreen = ({ route, navigation }: Props) => {
1042
1046
  }}
1043
1047
  />
1044
1048
  )}
1049
+
1050
+ {isSubscriptionDetailsVisible && (
1051
+ <View style = {styles.subscriptionContainer}>
1052
+ {checkoutDetails.subscriptionDetails && checkoutDetails.subscriptionDetails.map((item) => item.value && (
1053
+ <SubscriptionRow
1054
+ key={item.label}
1055
+ checkoutDetails={checkoutDetails}
1056
+ heading={item.label}
1057
+ value={item.value}
1058
+ />
1059
+ ))}
1060
+ </View>
1061
+ )}
1062
+
1045
1063
  </ScrollView>
1046
1064
  <View>
1047
1065
  {cardValid ? (
@@ -1054,14 +1072,38 @@ const CardScreen = ({ route, navigation }: Props) => {
1054
1072
  onProceedForward();
1055
1073
  }}
1056
1074
  >
1057
- <Text style={[styles.buttonText, {fontFamily: checkoutDetails.fontFamily.semiBold,}]}>Make Payment</Text>
1058
- </Pressable>
1075
+ <Text style={[styles.buttonText, {fontFamily: checkoutDetails.fontFamily.semiBold,}]}>
1076
+ Pay{' '}
1077
+ <Text
1078
+ style={{
1079
+ fontFamily: 'Inter-SemiBold',
1080
+ fontSize: 16,
1081
+ color: 'white',
1082
+ }}
1083
+ >
1084
+ {' '}
1085
+ {checkoutDetails.currencySymbol}
1086
+ </Text>
1087
+ {checkoutDetails.amount}
1088
+ </Text>
1089
+ </Pressable>
1059
1090
  ) : (
1060
1091
  <Pressable
1061
1092
  style={[styles.buttonContainer, { backgroundColor: '#E6E6E6' , borderRadius: checkoutDetails.ctaBorderRadius,}]}
1062
1093
  >
1063
- <Text style={[styles.buttonText, { color: checkoutDetails.buttonTextColor, fontFamily: checkoutDetails.fontFamily.semiBold, }]}>
1064
- Make Payment
1094
+ <Text style={[styles.buttonText, {fontFamily: checkoutDetails.fontFamily.semiBold,}]}>
1095
+ Pay{' '}
1096
+ <Text
1097
+ style={{
1098
+ fontFamily: 'Inter-SemiBold',
1099
+ fontSize: 16,
1100
+ color: 'white',
1101
+ }}
1102
+ >
1103
+ {' '}
1104
+ {checkoutDetails.currencySymbol}
1105
+ </Text>
1106
+ {checkoutDetails.amount}
1065
1107
  </Text>
1066
1108
  </Pressable>
1067
1109
  )}
@@ -1118,6 +1160,28 @@ const CardScreen = ({ route, navigation }: Props) => {
1118
1160
  </View>
1119
1161
  )}
1120
1162
  </View>
1163
+ {Platform.OS === 'ios' && (
1164
+ <>
1165
+ {[
1166
+ cardNumberAccessoryID,
1167
+ cardExpiryAccessoryID,
1168
+ cardCvvAccessoryID,
1169
+ cardHolderNameAccessoryID,
1170
+ cardNickNameAccessoryID,
1171
+ ].map((id) => (
1172
+ <InputAccessoryView key={id} nativeID={id}>
1173
+ <View style={{ backgroundColor: '#f1f1f1', padding: 10, alignItems: 'flex-end' }}>
1174
+ <TouchableOpacity onPress={() => Keyboard.dismiss()}>
1175
+ <Text style={{ fontSize: 16, fontFamily: checkoutDetails.fontFamily.semiBold }}>
1176
+ Done
1177
+ </Text>
1178
+ </TouchableOpacity>
1179
+ </View>
1180
+ </InputAccessoryView>
1181
+ ))}
1182
+ </>
1183
+ )}
1184
+ </>
1121
1185
  );
1122
1186
  };
1123
1187
 
@@ -38,6 +38,7 @@ import { handleFetchStatusResponseHandler, handlePaymentResponse } from '../shar
38
38
  import type { CheckoutStackParamList } from '../navigation';
39
39
  import type { NavigationProp, RouteProp } from '@react-navigation/native';
40
40
  import { setUserDataHandlerToDefault } from '../sharedContext/userdataHandler';
41
+ import { getTextInputTheme } from '../sharedContext/getTextInputTheme';
41
42
 
42
43
  type EmiScreenRouteProp = RouteProp<CheckoutStackParamList, 'EmiScreen'>;
43
44
 
@@ -633,12 +634,7 @@ const EmiScreen = ({ navigation, route }: Props) => {
633
634
  onChangeText={(it) => {
634
635
  setSearchText(it);
635
636
  }}
636
- theme={{
637
- colors: {
638
- primary: '#2D2B32',
639
- outline: '#E6E6E6',
640
- },
641
- }}
637
+ theme={getTextInputTheme()}
642
638
  style={[styles.textInputStyle, {fontFamily: checkoutDetails.fontFamily.regular,}]}
643
639
  left={
644
640
  <TextInput.Icon
@@ -14,6 +14,7 @@ import type { RouteProp, NavigationProp } from '@react-navigation/native';
14
14
  import Header from '../components/header';
15
15
  import styles from '../styles/screens/instantOfferScreenStyles';
16
16
  import { checkoutDetailsHandler } from '../sharedContext/checkoutDetailsHandler';
17
+ import { getTextInputTheme } from '../sharedContext/getTextInputTheme';
17
18
 
18
19
  export interface InstantOfferProps {
19
20
  couponList: GetInstantOffersResponse[];
@@ -98,12 +99,7 @@ const InstantOfferScreen = ({ route, navigation } : Props) => {
98
99
  onChangeText={(it) => {
99
100
  handleSearchTextChange(it);
100
101
  }}
101
- theme={{
102
- colors: {
103
- primary: '#2D2B32',
104
- outline: '#E6E6E6',
105
- },
106
- }}
102
+ theme={getTextInputTheme()}
107
103
  style={[styles.searchTextInput, {fontFamily: checkoutDetails.fontFamily.regular,}]}
108
104
  left={
109
105
  <TextInput.Icon
@@ -15,7 +15,7 @@ import type { CheckoutStackParamList } from '../navigation';
15
15
  import { paymentHandler, setPaymentHandler } from "../sharedContext/paymentStatusHandler";
16
16
  import { loadBoxpayFonts } from '../components/fontFamily';
17
17
  import { setUserDataHandler, setUserDataHandlerToDefault, userDataHandler } from '../sharedContext/userdataHandler';
18
- import { type PaymentResultObject, type PaymentClass, type InstrumentDetails, type PaymentMethod, type OrderItem, APIStatus, AnalyticsEvents, type DeliveryAddress, type BoxpayCheckoutProps, type GetInstantOffersResponse, UIConfigurationOptions, TransactionStatus } from '../interface';
18
+ import { type PaymentResultObject, type PaymentClass, type InstrumentDetails, type PaymentMethod, type OrderItem, APIStatus, AnalyticsEvents, type DeliveryAddress, type BoxpayCheckoutProps, type GetInstantOffersResponse, UIConfigurationOptions, TransactionStatus, type SubscriptionDetails } from '../interface';
19
19
  import { checkoutDetailsHandler, setCheckoutDetailsHandler, setCheckOutDetailsHandlerToDefault } from '../sharedContext/checkoutDetailsHandler';
20
20
  import WebViewScreen from '../screens/webViewScreen';
21
21
  import styles from '../styles/indexStyles';
@@ -30,7 +30,7 @@ import fetchSessionDetails from '../postRequest/fetchSessionDetails';
30
30
  import MorePaymentMethods from '../components/morePaymentMethods';
31
31
  import { fetchSavedInstrumentsHandler, handleFetchStatusResponseHandler, handlePaymentResponse } from '../sharedContext/handlePaymentResponseHandler';
32
32
  import callUIAnalytics from '../postRequest/callUIAnalytics';
33
- import { formatAddress, getPhoneNumberCodeAndCountryName, useCountdown } from '../utility';
33
+ import { formatAddress, formatDate, getPhoneNumberCodeAndCountryName, isEmpty, useCountdown } from '../utility';
34
34
  import fetchSurCharge from '../postRequest/fetchSurcharge';
35
35
  import fetchInstantOffer from '../postRequest/fetchInstantOffer';
36
36
  import ApplyCouponCard from '../components/applyCouponCard';
@@ -552,6 +552,8 @@ const MainScreen = ({route, navigation} : MainScreenProps) => {
552
552
  },
553
553
  ctaBorderRadius : uiConfiguration?.[UIConfigurationOptions.CTABorderRadius] ? uiConfiguration[UIConfigurationOptions.CTABorderRadius] : 12,
554
554
  buttonColor: response.data.merchantDetails.checkoutTheme.primaryButtonColor,
555
+ textInputFieldFocusedOutlineColor: uiConfiguration?.[UIConfigurationOptions.TextInputFields]?.focusedBorderColor ? uiConfiguration[UIConfigurationOptions.TextInputFields].focusedBorderColor : '#2D2B32',
556
+ textInputFieldUnFocusedOutlineColor : uiConfiguration?.[UIConfigurationOptions.TextInputFields]?.borderColor ? uiConfiguration[UIConfigurationOptions.TextInputFields].borderColor : '#E6E6E6',
555
557
  buttonTextColor : response.data.merchantDetails.checkoutTheme.buttonTextColor,
556
558
  headerColor : response.data.merchantDetails.checkoutTheme.headerColor,
557
559
  headerTextColor : response.data.merchantDetails.checkoutTheme.headerTextColor,
@@ -586,7 +588,8 @@ const MainScreen = ({route, navigation} : MainScreenProps) => {
586
588
  isUPIOtmQRMethodEnabled : methodFlags.isUPIOtmQRVisible,
587
589
  isOrderItemDetailsVisible : isFieldEnabled('ORDER_ITEM_DETAILS'),
588
590
  isSICheckboxVisible : configurationOptions?.SHOW_SI_CHECKBOX ? true : false,
589
- isSubscriptionCheckout : paymentDetails.subscriptionDetails != null ? true : false
591
+ isSubscriptionCheckout : paymentDetails.subscriptionDetails != null ? true : false,
592
+ subscriptionDetails : getSubscriptionDetails(paymentDetails.subscriptionDetails, paymentDetails.money.amountLocaleFull, symbol)
590
593
  },
591
594
  });
592
595
  setPaymentHandler({
@@ -614,6 +617,54 @@ const MainScreen = ({route, navigation} : MainScreenProps) => {
614
617
  loadSession()
615
618
  }, []);
616
619
 
620
+ const getSubscriptionDetails = (data: SubscriptionDetails | null, amount : string, currencySymbol : string) => {
621
+ if (isEmpty(data)) return null;
622
+
623
+ const { billingCycle } = data!;
624
+
625
+ // Frequency
626
+ let frequency: string | null = null;
627
+ if (!isEmpty(billingCycle)) {
628
+ const { billingCycleValue, count, billingTimeUnit } = billingCycle!;
629
+
630
+ if (count === 1) {
631
+ frequency = billingTimeUnit;
632
+ } else {
633
+ frequency = `Every ${count} ${billingCycleValue}`;
634
+ }
635
+ }
636
+
637
+ // Validity
638
+ let validity: string | null = null;
639
+ if (!isEmpty(data!.expiryDateLocale)) {
640
+ const date = formatDate(data!.expiryDateLocale!.split(' ')[0] ?? "");
641
+ validity = `Till ${date}`;
642
+ } else if (!isEmpty(data!.recurringExpiryDateLocale)) {
643
+ const date = formatDate(data!.recurringExpiryDateLocale!.split(' ')[0] ?? "");
644
+ validity = `${date}`;
645
+ }
646
+
647
+ const rows = [
648
+ {
649
+ label: 'To be paid now',
650
+ value: !isEmpty(amount) ? `${currencySymbol}${amount}` : null,
651
+ },
652
+ {
653
+ label: 'Recurring Amount',
654
+ value: !isEmpty(data!.maxAmountLocaleFull) ? `Up to ${currencySymbol}${data!.maxAmountLocaleFull}` : null,
655
+ },
656
+ {
657
+ label: 'Frequency',
658
+ value: frequency,
659
+ },
660
+ {
661
+ label: 'Expiry Date',
662
+ value: validity,
663
+ },
664
+ ];
665
+ return rows.filter(row => !isEmpty(row.value));
666
+ };
667
+
617
668
  const handleSurchargeDetails = async() => {
618
669
  const response = await fetchSurCharge()
619
670
  switch (response.apiStatus) {
@@ -26,6 +26,7 @@ import styles from '../styles/screens/netBankingScreenStyles';
26
26
  import type { CheckoutStackParamList } from '../navigation';
27
27
  import type { NavigationProp, RouteProp } from '@react-navigation/native';
28
28
  import { setUserDataHandlerToDefault } from '../sharedContext/userdataHandler';
29
+ import { getTextInputTheme } from '../sharedContext/getTextInputTheme';
29
30
 
30
31
  type NetBankingScreenRouteProp = RouteProp<CheckoutStackParamList, 'NetBankingScreen'>;
31
32
 
@@ -314,12 +315,7 @@ const NetBankingScreen = ({ navigation, route }: Props) => {
314
315
  onChangeText={(it) => {
315
316
  handleSearchTextChange(it);
316
317
  }}
317
- theme={{
318
- colors: {
319
- primary: '#2D2B32',
320
- outline: '#E6E6E6',
321
- },
322
- }}
318
+ theme={getTextInputTheme()}
323
319
  style={[styles.searchTextInput, {fontFamily: checkoutDetails.fontFamily.regular,}]}
324
320
  left={
325
321
  <TextInput.Icon