AddCard.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /**
  2. * 添加信用卡页面
  3. * @邠心vbe on 2021/05/08
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, StyleSheet, TextInput, Switch } from 'react-native';
  7. import apiUser from '../../api/apiUser';
  8. import Button from '../../components/Button';
  9. import apiWallet from '../../api/apiWallet';
  10. import Dialog from '../../components/Dialog';
  11. import Dropdown from '../../components/Dropdown';
  12. export default class AddCard extends Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. primary: false,
  17. validTill: '',
  18. countryList: [],
  19. countryCode: '',
  20. };
  21. this.form = {}
  22. }
  23. componentDidMount() {
  24. this.getCountryList();
  25. }
  26. getCountryList() {
  27. apiUser.getCountryCode().then(res => {
  28. if (res.data) {
  29. const list = []
  30. for (let item in res.data) {
  31. if (item) {
  32. list.push({
  33. code: item,
  34. name: res.data[item]
  35. });
  36. }
  37. }
  38. this.setState({
  39. countryList: list
  40. });
  41. }
  42. }).catch(err => {
  43. });
  44. }
  45. validate() {
  46. if (!this.form.nameOnCard) {
  47. toastShort('Please type name on card');
  48. return;
  49. }
  50. if (!this.form.cardNumber) {
  51. toastShort('Please type card number');
  52. return;
  53. }
  54. if (!/^\d{9,}$/.test(this.form.cardNumber)) {
  55. toastShort('Please type a correct card number');
  56. return;
  57. }
  58. if (!this.state.validTill) {
  59. toastShort('Please type valid till');
  60. return;
  61. }
  62. if (!/^(0[1-9]|1[0-2])\/(2[1-9]|[3-5][0-9])/.test(this.state.validTill)) {
  63. toastShort('Please type a correct valid till');
  64. return;
  65. }
  66. if (!this.form.cardCvv) {
  67. toastShort('Please type CVV');
  68. return;
  69. }
  70. if (!/^\d{3}$/.test(this.form.cardCvv)) {
  71. toastShort('Please type a correct CVV');
  72. return;
  73. }
  74. const params = this.form;
  75. params.country = this.state.countryCode;
  76. params.primary = this.state.primary ? 'Y' : 'N';
  77. params.validTill = this.state.validTill;
  78. this.addCard(params);
  79. }
  80. addCard(params) {
  81. Dialog.showProgressDialog();
  82. apiWallet.addCreditCard(params).then(res => {
  83. Dialog.dismissLoading();
  84. toastShort('Add card successfully');
  85. goBack();
  86. }).catch(err => {
  87. Dialog.dismissLoading();
  88. toastShort(err);
  89. });
  90. }
  91. render() {
  92. return (
  93. <View style={styles.container}>
  94. <View style={styles.formView}>
  95. <Text style={styles.label}>Name on Card</Text>
  96. <TextInput
  97. style={styles.cardNameInput}
  98. placeholder={'Your name on card'}
  99. placeholderTextColor={textPlacehoder}
  100. maxLength={50}
  101. onChangeText={text => this.form.nameOnCard = text}/>
  102. </View>
  103. <View style={styles.formView}>
  104. <Text style={styles.label}>Card Number</Text>
  105. <View style={styles.cardNumberRow}>
  106. <FontAwesome
  107. name='credit-card'
  108. size={24}
  109. color={colorPrimary}/>
  110. <Text style={styles.leftLine}/>
  111. <TextInput
  112. style={styles.cardNumber}
  113. placeholder='Card Number'
  114. placeholderTextColor={textPlacehoder}
  115. maxLength={25}
  116. keyboardType={'numeric'}
  117. onChangeText={text => {
  118. this.form.cardNumber = text;
  119. }}/>
  120. </View>
  121. </View>
  122. <View style={styles.formRow}>
  123. <View style={styles.formColumn}>
  124. <Text style={styles.label}>Valid Till</Text>
  125. <TipInput
  126. placeholder='MM/YY'
  127. maxLength={5}
  128. keyboardType={'numeric'}
  129. value={this.state.validTill}
  130. onChangeText={text => {
  131. if (this.state.validTill.length == 2 && text.length == 3) {
  132. if (text.indexOf('/') == -1) {
  133. let s = this.state.validTill + '/' + text.substring(2)
  134. this.setState({
  135. validTill: s
  136. });
  137. } else {
  138. this.setState({
  139. validTill: text
  140. });
  141. }
  142. } else {
  143. this.setState({
  144. validTill: text
  145. });
  146. }
  147. }}/>
  148. </View>
  149. <View style={styles.formColumn}>
  150. <Text style={styles.label}>CVV</Text>
  151. <TipInput
  152. placeholder='CVV'
  153. maxLength={6}
  154. keyboardType={'numeric'}
  155. onChangeText={text => {
  156. this.form.cardCvv = text;
  157. }}/>
  158. </View>
  159. </View>
  160. <View style={styles.formView}>
  161. <Text style={styles.label}>Country where card was issued</Text>
  162. <View style={styles.countryRow}>
  163. <MaterialIcons
  164. name='flag'
  165. color={colorPrimary}
  166. size={30}/>
  167. <Dropdown
  168. style={styles.countryPicker }
  169. title='Country'
  170. list={this.state.countryList}
  171. nameKey='name'
  172. valueKey='code'
  173. showIcon={false}
  174. onChange={(value, index)=> {
  175. this.setState({
  176. countryCode: value,
  177. countryIndex: index
  178. });
  179. }}
  180. />
  181. <Text style={styles.changeText}>Change</Text>
  182. </View>
  183. </View>
  184. <View style={styles.switchRow}>
  185. <Text
  186. style={[styles.label, ui.flex1]}
  187. onPress={() => {
  188. this.setState({
  189. primary: !this.state.primary
  190. });
  191. }}>Set as Primary</Text>
  192. <Switch
  193. value={this.state.primary}
  194. trackColor={isIOS ? { false: "#B2B2B2", true: colorAccent } : null}
  195. onValueChange={v => {
  196. this.setState({
  197. primary: v
  198. });
  199. }}/>
  200. </View>
  201. <Text style={styles.tipsText}>Your card may be charged to make sure it’s vailid.That amount will be automatically refunded.</Text>
  202. <Text style={styles.tipsText}>By adding a card,you have read and agree to our terms and conditions.</Text>
  203. <Text style={ui.flex1}></Text>
  204. <View style={styles.buttonView}>
  205. <Button
  206. text='Save'
  207. elevation={1.5}
  208. onClick={() => {
  209. this.validate();
  210. }}/>
  211. </View>
  212. </View>
  213. );
  214. }
  215. }
  216. const TipInput = ({onChangeText, maxLength, placeholder, keyboardType, value}) => {
  217. return (
  218. <View style={styles.cardInputView}>
  219. <TextInput
  220. style={styles.cardInput}
  221. placeholder={placeholder}
  222. placeholderTextColor={textPlacehoder}
  223. maxLength={maxLength}
  224. keyboardType={keyboardType}
  225. onChangeText={onChangeText}
  226. value={value}/>
  227. <MaterialIcons
  228. name='info-outline'
  229. color='#999'
  230. size={16}/>
  231. </View>
  232. );
  233. }
  234. const styles = StyleSheet.create({
  235. container: {
  236. flex: 1,
  237. backgroundColor: 'white'
  238. },
  239. formView: {
  240. paddingTop: 16,
  241. paddingLeft: 16,
  242. paddingRight: 16,
  243. paddingBottom: 4
  244. },
  245. formRow: {
  246. paddingTop: 12,
  247. paddingLeft: 8,
  248. paddingRight: 8,
  249. paddingBottom: 8,
  250. alignItems: 'center',
  251. flexDirection: 'row'
  252. },
  253. formColumn: {
  254. flex: 1,
  255. paddingLeft: 8,
  256. paddingRight: 8
  257. },
  258. label: {
  259. color: '#333',
  260. fontSize: 14
  261. },
  262. leftLine: {
  263. width: 1,
  264. height: 20,
  265. marginLeft: 16,
  266. backgroundColor: colorAccent
  267. },
  268. cardNumberRow: {
  269. paddingTop: 8,
  270. alignItems: 'center',
  271. flexDirection: 'row',
  272. },
  273. cardNumber: {
  274. flex: 1,
  275. color: '#333',
  276. fontSize: 16,
  277. paddingLeft: 4,
  278. },
  279. cardNameInput: {
  280. color: '#333',
  281. fontSize: 14,
  282. paddingBottom: 2,
  283. borderBottomColor: '#EEE',
  284. borderBottomWidth: 1
  285. },
  286. cardInputView: {
  287. paddingTop: 16,
  288. paddingLeft: 2,
  289. paddingRight: 2,
  290. paddingBottom: 2,
  291. alignItems: 'center',
  292. flexDirection: 'row',
  293. borderBottomColor: '#EEE',
  294. borderBottomWidth: 1
  295. },
  296. cardInput: {
  297. flex: 1,
  298. padding: 0,
  299. color: '#333',
  300. fontSize: 14,
  301. },
  302. countryRow: {
  303. paddingTop: 8,
  304. paddingBottom: 4,
  305. alignItems: 'flex-end',
  306. flexDirection: 'row',
  307. borderBottomWidth: 1,
  308. borderBottomColor: '#EEE'
  309. },
  310. countryPicker: {
  311. flex: 1,
  312. color: '#333',
  313. fontSize: 14,
  314. paddingTop: 4,
  315. paddingLeft: 16
  316. },
  317. changeText: {
  318. right: 0,
  319. bottom: 0,
  320. padding: 10,
  321. color: '#12A5F9',
  322. fontSize: 12,
  323. position: 'absolute',
  324. backgroundColor: 'white',
  325. },
  326. switchRow: {
  327. padding: 16,
  328. alignItems: 'center',
  329. flexDirection: 'row',
  330. },
  331. tipsText: {
  332. color: '#333',
  333. fontSize: 12,
  334. padding: 16,
  335. },
  336. buttonView: {
  337. padding: 16,
  338. marginBottom: 16
  339. }
  340. })