RegisterV4.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. /**
  2. * 带OTP的注册页面
  3. * @邠心vbe on 2023/02/06
  4. */
  5. import React from 'react';
  6. import { View, ScrollView, StyleSheet, TextInput, Pressable, Image, Linking } from 'react-native';
  7. import apiUser from '../../api/apiUser';
  8. import Button from '../../components/Button';
  9. import { PageList } from '../Router';
  10. import Dialog from '../../components/Dialog';
  11. import app from '../../../app.json';
  12. import Dropdown from '../../components/Dropdown';
  13. import ImagePicker from 'react-native-image-crop-picker';
  14. import apiUpload from '../../api/apiUpload';
  15. import { CountryDropCode, CountryDropNum, GetCountryList } from '../../components/CountryIcon';
  16. import StrengthView from './StrengthView';
  17. import CheckBox from '../../components/CheckBox';
  18. import { UploadThemes } from '../../components/ThemesConfig';
  19. import TextView from '../../components/TextView';
  20. import utils from '../../utils/utils';
  21. const options = {
  22. width: 300,
  23. height: 200,
  24. cropping: true,
  25. multiple: false,
  26. mediaType: 'photo',
  27. writeTempFile: false,
  28. compressImageQuality: 0.8,
  29. compressImageMaxWidth: 720,
  30. compressImageMaxHeight: 1280,
  31. ...UploadThemes
  32. }
  33. export default class RegisterV4 extends React.Component {
  34. constructor(props) {
  35. super(props);
  36. this.StrengthView = StrengthView.V4
  37. this.state = {
  38. agree: false,
  39. agree2: false,
  40. strength: 0,
  41. countryNum: '65',
  42. countryCode: "SG",
  43. userInfo: {
  44. email: "",
  45. verificationCode: ""
  46. },
  47. countryList: [],
  48. wrongCount: 0,
  49. params: {...this.props.route.params},
  50. email: '',
  51. password: '',
  52. fleetCompanyId: '',
  53. sendMinutes: 0,
  54. isFleetDriver: false,
  55. pdvImages: ['', ''],
  56. companyList: []
  57. };
  58. this.canChangeCalling = true;
  59. }
  60. componentDidMount() {
  61. //console.log(this.state.params);
  62. if (this.state.params.isFleetUser) {
  63. this.setState({
  64. isFleetDriver: true
  65. })
  66. this.props.navigation.setOptions({
  67. headerTitle: $t('route.driverRegister')
  68. })
  69. }
  70. this.getCountryList();
  71. this.getCompanyList();
  72. }
  73. applyStrength(text) {
  74. this.StrengthView.apply(text, strength => {
  75. if (this.state.strength != strength) {
  76. this.setState({
  77. password: text,
  78. strength: strength
  79. });
  80. } else {
  81. this.setState({
  82. password: text
  83. });
  84. }
  85. });
  86. }
  87. changeInfo(key, value) {
  88. var info = this.state.userInfo;
  89. info[key] = value;
  90. this.setState({
  91. 'userInfo': info
  92. });
  93. }
  94. getCountryList() {
  95. GetCountryList(list => {
  96. this.setState({
  97. countryList: list
  98. })
  99. })
  100. }
  101. getCompanyList() {
  102. apiUser.getConmpany().then(res => {
  103. if (res.data) {
  104. this.setState({
  105. companyList: res.data
  106. })
  107. }
  108. }).catch(err => [
  109. toastShort(err)
  110. ])
  111. }
  112. sendVerification() {
  113. var info = this.state.userInfo;
  114. if (!info.email) {
  115. toastShort($t('sign.plsInputEmail'));
  116. return;
  117. }
  118. if (!utils.isValidEmail(info.email)) {
  119. toastShort($t('sign.errEmailFormat'));
  120. return;
  121. }
  122. Dialog.showProgressDialog()
  123. apiUser.sendVerificationCodeV2({email: info.email, type: "register"}).then(res => {
  124. Dialog.dismissLoading()
  125. //this.state.sendMinutes = 60;
  126. this.state.sendMinutes = res.data?.resendTime ?? 60;
  127. toastShort($t('sign.sendOTPSuccess'));
  128. this.contdownTime();
  129. }).catch(err => {
  130. Dialog.dismissLoading()
  131. toastShort(err);
  132. });
  133. }
  134. contdownTime() {
  135. if (this.state.sendMinutes > 0) {
  136. this.setState({
  137. sendMinutes: this.state.sendMinutes - 1
  138. })
  139. setTimeout(() => {
  140. this.contdownTime();
  141. }, 1000);
  142. }
  143. }
  144. onRegister() {
  145. //console.log('sign up', this.state);
  146. var info = this.state.userInfo;
  147. if (!info.nickName) {
  148. toastShort($t('sign.plsInputDiaplayName'));
  149. return;
  150. }
  151. if (!info.email) {
  152. toastShort($t('sign.plsInputEmail'));
  153. return;
  154. }
  155. if (!utils.isValidEmail(info.email)) {
  156. toastShort($t('sign.errEmailFormat'));
  157. return;
  158. }
  159. if (!info.verificationCode) {
  160. toastShort($t('sign.plsInputOTP'));
  161. return;
  162. }
  163. if (!info.phone) {
  164. toastShort($t('sign.plsInputContactNo'));
  165. return;
  166. }
  167. if (!/^\d{6,15}$/.test(info.phone)) {
  168. toastShort($t('sign.errContactNoFormat'));
  169. return;
  170. }
  171. if (!this.state.password) {
  172. toastShort($t('sign.plsInputPassword'));
  173. return;
  174. }
  175. if (this.state.strength < this.StrengthView.maxStrength) {
  176. toastShort($t('sign.errPasswordStrong'));
  177. return;
  178. }
  179. if (!info.password) {
  180. toastShort($t('sign.plsInputPassword2'));
  181. return;
  182. }
  183. if (info.password != this.state.password) {
  184. toastShort($t('sign.errPasswordConfirm'));
  185. if (this.state.wrongCount < 3) {
  186. this.setState({
  187. wrongCount: this.state.wrongCount + 1
  188. })
  189. }
  190. return;
  191. }
  192. if (this.state.isFleetDriver) {
  193. if (!info.pdvLicence) {
  194. toastShort($t('sign.plsInputPDVLicence'));
  195. return;
  196. }
  197. if (this.state.pdvImages[0] == '' || this.state.pdvImages[1] == '') {
  198. toastShort($t('sign.plsUploadLicencePhotos'));
  199. return;
  200. }
  201. }
  202. let param = Object.assign({}, info);
  203. //param.phone = this.state.countryNum + info.phone
  204. param.callingCode = this.state.countryNum;
  205. param.countryCode = this.state.countryCode;
  206. if (this.state.isFleetDriver) {
  207. param.userType = 'Driver';
  208. param.pdvLicencePictures = this.state.pdvImages;
  209. param.fleetCompanyId = this.state.fleetCompanyId;
  210. } else {
  211. param.userType = 'Public';
  212. }
  213. param.otp = param.verificationCode;
  214. console.log('params', param);
  215. Dialog.showProgressDialog();
  216. apiUser.register(param).then(res => {
  217. Dialog.dismissLoading();
  218. //toastShort('Sign up successfully!');
  219. if (isIOS) {
  220. setTimeout(() => {
  221. this.showSuccessDialog();
  222. }, 600);
  223. } else {
  224. this.showSuccessDialog();
  225. }
  226. }).catch(err => {
  227. toastShort(err);
  228. Dialog.dismissLoading();
  229. });
  230. }
  231. showSuccessDialog() {
  232. Dialog.showResultDialog($t('sign.signUpSuccess'), $t('nav.ok'),
  233. () => {
  234. this.backToLogin();
  235. }
  236. )
  237. }
  238. getBackTopPosition() {
  239. return isIOS ? statusHeight - 16 : 8;
  240. }
  241. backToLogin() {
  242. if (this.state.params.actionLogin) {
  243. goBack()
  244. startPage(PageList.login);
  245. } else {
  246. goBack();
  247. }
  248. }
  249. uploadImage(index) {
  250. ImagePicker.openPicker({
  251. ...options,
  252. cropperToolbarTitle: $t('common.cropperTitle')
  253. }).then(image => {
  254. if (image.path) {
  255. apiUpload.uploadImage(image.path, image.mime, 'PDVL').then(res => {
  256. if (res.success && res.data.picturePath) {
  257. let imageUrl = this.state.pdvImages;
  258. imageUrl[index] = res.data.picturePath;
  259. this.setState({
  260. pdvImages: imageUrl
  261. });
  262. toastShort($t('common.uploadSuccess'));
  263. } else {
  264. toastShort($t('common.updateFailed'));
  265. }
  266. }).catch(err => {
  267. toastShort(err);
  268. });
  269. }
  270. }).catch(err1 => {
  271. //console.log(err1);
  272. });
  273. }
  274. changeAgree(ag) {
  275. this.setState({
  276. agree: ag
  277. })
  278. }
  279. changeAgree2(ag) {
  280. this.setState({
  281. agree2: ag
  282. })
  283. }
  284. changeCountry(value, index) {
  285. this.setState({
  286. countryCode: value
  287. })
  288. if (this.canChangeCalling) {
  289. const country = this.state.countryList[index]
  290. this.changeCalling(country.countryNum, -1);
  291. }
  292. }
  293. changeCalling(value, index) {
  294. this.setState({
  295. countryNum: value
  296. })
  297. if (index >= 0) {
  298. this.canChangeCalling = false;
  299. }
  300. }
  301. toPrivayPolicy() {
  302. Linking.openURL(app.storeUrl.privacyPolicyUrl)
  303. }
  304. toUserTerms() {
  305. Linking.openURL(app.storeUrl.termsUseUrl)
  306. }
  307. render() {
  308. return (
  309. <View style={styles.container}>
  310. <ScrollView
  311. style={styles.scollView}
  312. keyboardShouldPersistTaps={isIOS ? 'never' : 'handled'}>
  313. <View style={styles.signView}>
  314. {/* <View style={styles.tabView}>
  315. <Text
  316. style={[
  317. styles.tabText,
  318. this.state.isFleetDriver ? {} : styles.tabActive
  319. ]}
  320. onPress={() => this.changeTab(false)}
  321. >Public Users</Text>
  322. <Text
  323. style={[
  324. styles.tabText,
  325. this.state.isFleetDriver ? styles.tabActive: {}
  326. ]}
  327. onPress={() => this.changeTab(true)}
  328. >Fleet/PH Drivers</Text>
  329. </View> */}
  330. <View style={styles.signInput}>
  331. <TextView style={styles.inputLabel}>{$t('sign.labelDisplayName')}</TextView>
  332. <TextInput
  333. style={styles.inputView}
  334. placeholder={$t('sign.labelDisplayName')}
  335. placeholderTextColor={textPlacehoder}
  336. maxLength={50}
  337. onChangeText={v => this.changeInfo('nickName', v)}
  338. />
  339. </View>
  340. <View style={styles.signInput}>
  341. <TextView style={styles.inputLabel}>{$t('sign.labelEmail')}</TextView>
  342. <TextInput
  343. style={styles.inputView}
  344. placeholder={$t('sign.labelEmail')}
  345. placeholderTextColor={textPlacehoder}
  346. maxLength={50}
  347. keyboardType="email-address"
  348. textContentType='emailAddress'
  349. onChangeText={v => this.changeInfo('email', v)}
  350. />
  351. </View>
  352. <View style={styles.signInput}>
  353. <TextView style={[styles.inputLabel, {flex: 2}]}>{$t('sign.labelValidateEmail')}</TextView>
  354. <TextInput
  355. style={[styles.inputView, {flex: 2.2, marginLeft: 2}]}
  356. placeholder={$t('sign.labelOtp')}
  357. placeholderTextColor={textPlacehoder}
  358. maxLength={6}
  359. keyboardType="number-pad"
  360. textContentType="telephoneNumber"
  361. onChangeText={v => this.changeInfo('verificationCode', v)}
  362. />
  363. <Button
  364. text={this.state.sendMinutes > 0 ? (this.state.sendMinutes + " s") : $t('sign.btnSendOTP')}
  365. style={styles.sendBtn}
  366. disabled={this.state.sendMinutes > 0}
  367. viewStyle={styles.sendBtnView}
  368. textStyle={styles.sendBtnText}
  369. onClick={() => this.sendVerification()}
  370. />
  371. </View>
  372. <View style={styles.signInput}>
  373. <TextView style={styles.inputLabel}>{$t('sign.labelCountry')}</TextView>
  374. <Dropdown
  375. style={styles.selectView}
  376. title={$t('sign.labelCountry')}
  377. list={this.state.countryList}
  378. value={this.state.countryCode}
  379. nameKey='countryName'
  380. valueKey='countryCode'
  381. iconColor={colorDark}
  382. onChange={(value, index)=> this.changeCountry(value, index)}
  383. customerItemView={
  384. (item, index, onClick) =>
  385. <CountryDropCode
  386. key={index}
  387. country={item}
  388. value={this.state.countryCode}
  389. onClick={onClick}/>
  390. }/>
  391. </View>
  392. <View style={styles.signInput}>
  393. <TextView style={styles.inputLabel}>{$t('sign.labelPhoneNumber')}</TextView>
  394. <View style={styles.mobileView}>
  395. <View style={styles.dropView}>
  396. <TextInput style={styles.dropInput} editable={false}/>
  397. <TextView style={styles.countryText}>{"+" + this.state.countryNum}</TextView>
  398. <MaterialIcons name={'arrow-drop-down'} size={24} color={colorDark}/>
  399. <Dropdown
  400. style={styles.dropLayer}
  401. prefixText="+"
  402. list={this.state.countryList}
  403. value={this.state.countryNum}
  404. nameKey='countryNum'
  405. valueKey='countryNum'
  406. onChange={(value, index)=> this.changeCalling(value, index)}
  407. customerItemView={
  408. (item, index, onClick) =>
  409. <CountryDropNum
  410. key={index}
  411. country={item}
  412. value={this.state.countryNum}
  413. onClick={onClick}/>
  414. }/>
  415. </View>
  416. <TextInput
  417. style={styles.contactView}
  418. placeholder={$t('sign.labelMobileNumber')}
  419. placeholderTextColor={textPlacehoder}
  420. keyboardType='phone-pad'
  421. maxLength={15}
  422. onChangeText={v => this.changeInfo('phone', v)}
  423. />
  424. </View>
  425. </View>
  426. <View style={styles.signInput}>
  427. <TextView style={styles.inputLabel}>{$t('sign.labelCreatePassword')}</TextView>
  428. <TextInput
  429. secureTextEntry={this.state.wrongCount < 3}
  430. style={styles.inputView}
  431. placeholder={$t('sign.labelPassword')}
  432. placeholderTextColor={textPlacehoder}
  433. maxLength={20}
  434. onChangeText={(value) => {
  435. this.applyStrength(value);
  436. }}
  437. />
  438. </View>
  439. <View style={styles.signInput}>
  440. <TextView style={styles.inputLabel}></TextView>
  441. <View style={styles.passwordView}>
  442. <this.StrengthView.VIEW strength={this.state.strength}/>
  443. </View>
  444. </View>
  445. <View style={styles.signInput}>
  446. <TextView style={styles.inputLabel}>{$t('sign.labelConfirmPassword')}</TextView>
  447. <TextInput
  448. secureTextEntry={this.state.wrongCount < 3}
  449. style={styles.inputView}
  450. placeholder={$t('sign.labelPassword')}
  451. placeholderTextColor={textPlacehoder}
  452. maxLength={20}
  453. onChangeText={v => this.changeInfo('password', v)}
  454. />
  455. </View>
  456. { this.state.isFleetDriver &&
  457. <>
  458. <View style={styles.signInput}>
  459. <TextView style={styles.inputLabel}>{$t('sign.labelYourCompany')}</TextView>
  460. <Dropdown
  461. style={[styles.inputView, ui.flexc]}
  462. title={$t('sign.labelCompany')}
  463. list={this.state.companyList}
  464. value={this.state.fleetCompanyId}
  465. valueKey='fleetCompanyId'
  466. nameKey='fleetCompanyName'
  467. onChange={(value, index)=> {
  468. this.setState({
  469. fleetCompanyId: value
  470. })
  471. }}/>
  472. </View>
  473. <View style={styles.signInput}>
  474. <TextView style={styles.inputLabel}>{$t('sign.labelPDVLicence')}</TextView>
  475. <TextInput
  476. style={styles.inputView}
  477. placeholder={$t('sign.hintPDVLicence')}
  478. placeholderTextColor={textPlacehoder}
  479. maxLength={20}
  480. onChangeText={v => this.changeInfo('pdvLicence', v)}
  481. />
  482. </View>
  483. <View style={styles.signInput}>
  484. <TextView style={styles.inputLabel}>{$t('sign.labelPDVPhotos')}</TextView>
  485. <View style={styles.uploadGroup}>
  486. { this.state.pdvImages.map((item, index) => (
  487. <UploadView
  488. key={index}
  489. onPress={() => this.uploadImage(index)}
  490. url={item}/>
  491. ))
  492. }
  493. </View>
  494. </View>
  495. </>
  496. }
  497. {/* <View style={styles.referView}>
  498. <Text style={styles.referTitle}>Have a referral code?</Text>
  499. <View style={styles.referText}>
  500. <Text>You'll get</Text>
  501. <Text style={styles.weight}>$5</Text>
  502. <Text>Credit as registration bonus!</Text>
  503. </View>
  504. <View style={styles.codeView}>
  505. <Text style={{ color: textPrimary, fontSize: 16 }}>Referral Code</Text>
  506. <TextInput
  507. style={styles.codeText}
  508. maxLength={6}
  509. placeholder='Referral Code'
  510. placeholderTextColor={textPlacehoder}
  511. onChangeText={v => this.changeInfo('referralCode', v)}
  512. />
  513. </View>
  514. </View> */}
  515. <View style={styles.consentView}>
  516. <TextView style={styles.consentTitle}>Consent and purpose notification</TextView>
  517. <TextView style={styles.agreeText}>
  518. We collect, use and disclose your personal data for the purpose of providing Electric Vehicle (EV) charging services to you.
  519. </TextView>
  520. </View>
  521. <View style={styles.agreeView}>
  522. <CheckBox
  523. value={this.state.agree2}
  524. onValueChange={v => this.changeAgree2(v)}
  525. />
  526. <View style={styles.agreeTextRow}>
  527. <TextView style={styles.agreeText} onPress={() => this.changeAgree2(!this.state.agree2)}>
  528. I consent to Strides YTL Pte. Ltd. to collect, use and disclose my personal data for the above purposes and in accordance with the SMRT Corporation’s Privacy Statement and Personal Data Protection Act 2012.
  529. </TextView>
  530. </View>
  531. </View>
  532. <View style={styles.agreeView2}>
  533. <CheckBox
  534. value={this.state.agree}
  535. onValueChange={v => this.changeAgree(v)}
  536. />
  537. <View style={styles.agreeTextRow}>
  538. <TextView style={styles.agreeText} onPress={() => this.changeAgree(!this.state.agree)}>
  539. {$t('sign.iHaveReadAndAgree')}
  540. </TextView>
  541. <TextView style={styles.agreeLink} onPress={() => this.toUserTerms()}>{$t('drawer.termsOfUse')}</TextView>
  542. <TextView style={styles.agreeText}>{' '}</TextView>
  543. <TextView style={styles.agreeText}>{$t('sign.linkAndLink')}</TextView>
  544. <TextView style={styles.agreeLink} onPress={() => this.toPrivayPolicy()}>{$t('drawer.privacyPolicy')}</TextView>
  545. <TextView style={styles.agreeText}>{$t('sign.linkAndLinkEnd')}</TextView>
  546. </View>
  547. </View>
  548. <Button
  549. style={styles.signButton}
  550. elevation={1.5}
  551. disabled={!this.state.agree || !this.state.agree2}
  552. text={$t('sign.btnSignUp')}
  553. fontSize={14}
  554. onClick={() => {
  555. this.onRegister();
  556. }}
  557. />
  558. </View>
  559. </ScrollView>
  560. </View>
  561. );
  562. }
  563. }
  564. const UploadView = ({url, onPress}) => (
  565. <Pressable
  566. style={styles.uploadView}
  567. onPress={onPress}>
  568. { url == ''
  569. ? <Image
  570. style={styles.uploadIcon}
  571. source={require('../../images/icon/ic-add-photo.png')}/>
  572. : <Image
  573. style={styles.uploadIcon}
  574. source={{uri: utils.getImageUrl(url)}}/>
  575. }
  576. </Pressable>
  577. )
  578. const styles = StyleSheet.create({
  579. container: {
  580. flex: 1,
  581. backgroundColor: colorLight
  582. },
  583. header: {
  584. paddingTop: 56,
  585. backgroundColor: colorAccent
  586. },
  587. backView: {
  588. top: 12,
  589. zIndex: 5,
  590. padding: 16,
  591. position: 'absolute',
  592. flexDirection: 'row'
  593. },
  594. backButton: {
  595. borderRadius: 60,
  596. backgroundColor: colorLight
  597. },
  598. backButtonView: {
  599. height: 43,
  600. paddingLeft: 16,
  601. paddingRight: 16,
  602. alignItems: 'center',
  603. flexDirection: 'row'
  604. },
  605. scollView: {
  606. flex: 1
  607. },
  608. logoView: {
  609. paddingTop: 32,
  610. paddingBottom: 56,
  611. alignItems: 'center'
  612. },
  613. logoImg: {
  614. width:165.09,
  615. height: 51.94,
  616. },
  617. signView: {
  618. flex: 1,
  619. padding: 16,
  620. //marginTop: -30,
  621. borderTopLeftRadius: 20,
  622. borderTopRightRadius: 20,
  623. backgroundColor: colorLight
  624. },
  625. tabView: {
  626. marginBottom: 4,
  627. borderWidth: 1,
  628. borderRadius: 6,
  629. overflow: 'hidden',
  630. alignItems: 'center',
  631. flexDirection: 'row',
  632. borderColor: colorAccent,
  633. },
  634. tabText: {
  635. flex: 1,
  636. color: textPrimary,
  637. fontSize: 15,
  638. textAlign: 'center',
  639. ...$padding(10, 0),
  640. },
  641. tabActive: {
  642. fontWeight: 'bold',
  643. backgroundColor: colorAccent
  644. },
  645. title: {
  646. color: textPrimary,
  647. fontSize: 18,
  648. fontWeight: '700',
  649. paddingTop: 4,
  650. paddingBottom: 6,
  651. },
  652. signInput: {
  653. marginTop: 16,
  654. alignItems: 'center',
  655. flexDirection: 'row'
  656. },
  657. inputLabel: {
  658. flex: 1,
  659. color: textPrimary,
  660. fontSize: 14,
  661. marginRight: 4
  662. },
  663. inputView: {
  664. flex: 2,
  665. color: textPrimary,
  666. fontSize: 14,
  667. borderRadius: 5,
  668. minHeight: 40,
  669. paddingTop: 6,
  670. paddingLeft: 12,
  671. paddingRight: 12,
  672. paddingBottom: 6,
  673. backgroundColor: '#F5F5F5'
  674. },
  675. selectView: {
  676. flex: 2,
  677. fontSize: 14,
  678. borderRadius: 5,
  679. minHeight: 40,
  680. paddingTop: 6,
  681. paddingLeft: 12,
  682. paddingRight: 6,
  683. paddingBottom: 6,
  684. alignItems: 'center',
  685. flexDirection: 'row',
  686. backgroundColor: '#F5F5F5'
  687. },
  688. mobileView: {
  689. flex: 2,
  690. marginLeft: -12,
  691. alignItems: 'center',
  692. flexDirection: 'row'
  693. },
  694. dropView: {
  695. fontSize: 16,
  696. borderRadius: 4,
  697. paddingRight: 4,
  698. flexDirection: 'row',
  699. alignItems: 'center',
  700. backgroundColor: '#F5F5F5'
  701. },
  702. dropInput: {
  703. width: 12,
  704. padding: 6,
  705. color: textPrimary,
  706. minHeight: 40,
  707. },
  708. countryText: {
  709. color: textPrimary,
  710. fontSize: 14,
  711. paddingRight: 4
  712. },
  713. dropLayer: {
  714. left: 0,
  715. right: 0,
  716. opacity: 0,
  717. position: 'absolute'
  718. },
  719. contactView: {
  720. flex: 1,
  721. color: textPrimary,
  722. fontSize: 15,
  723. borderRadius: 4,
  724. minHeight: 40,
  725. paddingTop: 6,
  726. paddingLeft: 12,
  727. paddingRight: 12,
  728. paddingBottom: 6,
  729. marginLeft: 10,
  730. backgroundColor: '#F5F5F5'
  731. },
  732. passwordView: {
  733. flex: 2,
  734. marginTop: -8,
  735. },
  736. referView: {
  737. padding: 16,
  738. marginTop: 24,
  739. borderRadius: 6,
  740. alignItems: 'center',
  741. backgroundColor: '#F5F5F5'
  742. },
  743. referTitle: {
  744. color: textPrimary,
  745. fontSize: 18,
  746. fontWeight: 'bold'
  747. },
  748. referText: {
  749. color: textPrimary,
  750. paddingTop: 4,
  751. alignItems: 'flex-end',
  752. flexDirection: 'row'
  753. },
  754. weight: {
  755. fontSize: 18,
  756. paddingLeft: 4,
  757. paddingRight: 4,
  758. color: colorAccent,
  759. fontWeight: 'bold'
  760. },
  761. codeView: {
  762. paddingTop: 16,
  763. alignItems: 'center',
  764. flexDirection: 'row'
  765. },
  766. codeText: {
  767. color: textPrimary,
  768. fontSize: 16,
  769. paddingTop: 6,
  770. paddingLeft: 12,
  771. paddingRight: 12,
  772. paddingBottom: 6,
  773. minHeight: 40,
  774. marginLeft: 16,
  775. borderRadius: 6,
  776. textAlign: 'center',
  777. backgroundColor: colorLight
  778. },
  779. signButton: {
  780. marginTop: 24,
  781. marginBottom: 8,
  782. },
  783. uploadGroup: {
  784. flex: 2,
  785. alignItems: 'center',
  786. flexDirection: 'row',
  787. justifyContent: 'center'
  788. },
  789. uploadView: {
  790. flex: 1,
  791. alignItems: 'center'
  792. },
  793. uploadIcon: {
  794. width: $vw(28),
  795. height: $vw(28),
  796. borderRadius: 6
  797. },
  798. consentView: {
  799. paddingTop: 32
  800. },
  801. consentTitle: {
  802. color: textPrimary,
  803. fontSize: 15,
  804. paddingTop: 2,
  805. paddingBottom: 8,
  806. fontWeight: 'bold',
  807. textDecorationLine: 'underline'
  808. },
  809. agreeView: {
  810. paddingTop: 16,
  811. marginBottom: 8,
  812. flexDirection: 'row',
  813. alignItems: 'flex-start',
  814. },
  815. agreeView2: {
  816. marginTop: 8,
  817. marginBottom: 16,
  818. flexDirection: 'row',
  819. alignItems: 'flex-start',
  820. },
  821. agreeTextRow: {
  822. flex: 1,
  823. paddingTop: 4,
  824. paddingLeft: 8,
  825. flexWrap: 'wrap',
  826. flexDirection: 'row'
  827. },
  828. agreeText: {
  829. color: textPrimary,
  830. fontSize: 14,
  831. paddingTop: 2,
  832. paddingBottom: 2
  833. },
  834. agreeLink: {
  835. ...ui.link,
  836. fontSize: 14,
  837. paddingTop: 2,
  838. paddingBottom: 2,
  839. textDecorationLine: 'underline'
  840. },
  841. sendBtn: {
  842. flex: 1.8,
  843. marginLeft: 6,
  844. marginRight: 0,
  845. borderRadius: 6
  846. },
  847. sendBtnView: {
  848. flex: 1,
  849. height: 40,
  850. paddingLeft: 4,
  851. paddingRight: 4,
  852. alignItems: 'center',
  853. justifyContent: 'center'
  854. },
  855. sendBtnText: {
  856. color: colorLight,
  857. fontSize: 13,
  858. fontWeight: 'bold'
  859. },
  860. });