PaymentListV2.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /**
  2. * 新版支付方式选择器
  3. * @邠心vbe on 2021/04/13
  4. */
  5. import React, { Component } from 'react';
  6. import { View, StyleSheet, Pressable, ScrollView } from 'react-native';
  7. import BottomModal from '../../components/BottomModal';
  8. import BadgeSelectItem from '../../components/BadgeSelectItem';
  9. import { ChargeStyle } from './Charging';
  10. import { PAYTYPE, PaymentIcon } from '../payment/PaymentConfig';
  11. import Skeleton from "react-native-reanimated-skeleton";
  12. import TextView from '../../components/TextView';
  13. import apiCharge from '../../api/apiCharge';
  14. import Button from '../../components/Button';
  15. import Dialog from '../../components/Dialog';
  16. import app from '../../../app.json';
  17. import utils from '../../utils/utils';
  18. export default class PaymentListV2 extends Component {
  19. constructor(props) {
  20. super(props);
  21. this.state = {
  22. visible: false,
  23. isSelect: true,
  24. options: [],
  25. selectIndex: 0,
  26. selectOptions: {},
  27. isloading: true
  28. };
  29. }
  30. componentDidMount() {
  31. this.getPaymentOptions();
  32. this.setState({
  33. isSelect: (this.props.isSelect || true)
  34. })
  35. }
  36. componentDidUpdate() {
  37. if (this.props.isSelect != undefined && this.state.isSelect !== this.props.isSelect) {
  38. this.setState({
  39. isSelect: this.props.isSelect
  40. })
  41. }
  42. }
  43. getPaymentOptions() {
  44. if (utils.isEmpty(this.props.chargeBoxId)) {
  45. setTimeout(() => {
  46. this.getPaymentOptions();
  47. }, 1000);
  48. return;
  49. }
  50. apiCharge.getPaymentTypeOptions({
  51. chargeBoxId: this.props.chargeBoxId
  52. }).then(res => {
  53. if (res.data) {
  54. this.setState({
  55. options: res.data,
  56. isloading: false
  57. })
  58. if (this.props.payType && this.props.payType.code) {
  59. for (let i = 0; i < res.data.length; i++) {
  60. let type = res.data[i];
  61. if (type.code == this.props.payType.code) {
  62. this.changeMethod(i);
  63. break;
  64. }
  65. }
  66. } else {
  67. let index = 0;
  68. for (let i = 0; i < res.data.length; i++) {
  69. let type = res.data[i];
  70. if (type.def) {
  71. index = i;
  72. break;
  73. }
  74. }
  75. this.changeMethod(index);
  76. }
  77. }
  78. }).catch(err => {
  79. })
  80. }
  81. showDialog(visible) {
  82. if (this.state.isSelect) {
  83. this.setState({
  84. visible: visible
  85. })
  86. }
  87. }
  88. changeMethod(index) {
  89. const type = this.state.options[index];
  90. this.setState({
  91. selectIndex: index,
  92. selectOptions: type
  93. }, () => {
  94. if (this.props.onMethodChange) {
  95. this.props.onMethodChange(this.state.selectOptions);
  96. }
  97. })
  98. }
  99. setDefault() {
  100. const code = this.state.selectOptions?.code;
  101. if (code && !this.state.selectOptions.def) {
  102. Dialog.showProgressDialog();
  103. apiCharge.setDefaultPaymentType({
  104. defaultPaymentMethod: code
  105. }).then(res => {
  106. toastShort("success");
  107. this.getPaymentOptions();
  108. }).catch(err => {
  109. toastShort(err)
  110. }).finally(() => {
  111. Dialog.dismissLoading();
  112. })
  113. }
  114. }
  115. render() {
  116. return (
  117. <View>
  118. <BadgeSelectItem
  119. style={this.props.style ?? ChargeStyle.stationInfoView}
  120. borderColor={this.props.borderColor}
  121. checked={false}
  122. onPress={() => this.showDialog(true)}>
  123. { app.charge.version >= 4
  124. ? <MaterialIcons
  125. name="wallet"
  126. size={32}
  127. color={textPrimary}/>
  128. : <PaymentIcon
  129. method={"WALLET"}
  130. checked={true}
  131. size={35}/>
  132. }
  133. { (this.state.isSelect && this.state.options.length > 1) &&
  134. <TextView style={styles.numberDot}>{this.state.options.length}</TextView>
  135. }
  136. <View style={styles.paymentView}>
  137. <Skeleton
  138. containerStyle={ui.flex1}
  139. isLoading={this.state.isloading}
  140. animationType="pulse"
  141. layout={[{width: '60%', height: 20, marginLeft: 10}]}
  142. animationDirection={"horizontalRight"}>
  143. <TextView
  144. style={styles.valueText}
  145. numberOfLines={1}>{this.state.selectOptions?.name}</TextView>
  146. </Skeleton>
  147. <Skeleton
  148. containerStyle={ui.flex1}
  149. isLoading={this.state.isloading}
  150. animationType="pulse"
  151. layout={[{width: '60%', height: 20, marginLeft: 20}]}
  152. animationDirection={"horizontalRight"}>
  153. <TextView
  154. style={styles.paymentText}
  155. numberOfLines={1}>{this.state.selectOptions?.desc}</TextView>
  156. </Skeleton>
  157. </View>
  158. { this.state.selectOptions?.def &&
  159. <TextView style={styles.textDefault}>Default</TextView>
  160. }
  161. { this.state.isSelect &&
  162. <FontAwesome6
  163. name={"angle-right"}
  164. size={16}
  165. color={colorCancel}
  166. />
  167. }
  168. </BadgeSelectItem>
  169. <BottomModal
  170. visible={this.state.visible}
  171. onHide={() => this.showDialog(false)}>
  172. <View style={styles.dialogContent}>
  173. <TextView style={styles.titleText}>Payment Methods</TextView>
  174. <ScrollView style={styles.paymentList}>
  175. { this.state.options.map((item, index) => (
  176. <Pressable
  177. key={index}
  178. style={styles.itemPayment}
  179. onPress={() => this.changeMethod(index)}>
  180. <View style={ui.flex1}>
  181. <TextView style={styles.labelText}>{item.name}</TextView>
  182. <TextView style={styles.descText}>{item.desc}</TextView>
  183. </View>
  184. { item.def &&
  185. <TextView style={styles.tagDefault}>Default</TextView>
  186. }
  187. <MaterialCommunityIcons
  188. name={index == this.state.selectIndex ? "radiobox-marked" : "radiobox-blank"}
  189. size={24}
  190. color={index == this.state.selectIndex ? colorPrimary : textPrimary}
  191. />
  192. </Pressable>
  193. ))
  194. }
  195. </ScrollView>
  196. <EndView/><EndView/>
  197. <View style={ui.flexc}>
  198. <Button
  199. style={styles.defButton}
  200. text={"Set Default"}
  201. onClick={() => this.setDefault()}/>
  202. <EndView half/>
  203. <Button
  204. style={ui.flex1}
  205. text={"Confirm"}
  206. onClick={() => this.showDialog(false)}/>
  207. </View>
  208. </View>
  209. </BottomModal>
  210. </View>
  211. );
  212. }
  213. }
  214. const styles = StyleSheet.create({
  215. paymentView: {
  216. flex: 1,
  217. flexWrap: 'wrap',
  218. alignItems: 'center',
  219. flexDirection: 'row',
  220. justifyContent: 'space-around'
  221. },
  222. dialogContent: {
  223. padding: 16
  224. },
  225. paymentList: {
  226. height: $vh(50)
  227. },
  228. titleText: {
  229. fontSize: 16,
  230. fontWeight: 'bold',
  231. paddingBottom: 18
  232. },
  233. valueText: {
  234. flex: 1,
  235. color: textPrimary,
  236. fontSize: 14,
  237. fontWeight: 'bold',
  238. paddingLeft: 16
  239. },
  240. paymentText: {
  241. flex: 1,
  242. color: textSecondary,
  243. fontSize: 12,
  244. paddingLeft: 8,
  245. paddingRight: 16,
  246. textAlign: 'center'
  247. },
  248. labelText: {
  249. color: textPrimary,
  250. fontSize: 14,
  251. fontWeight: 'bold'
  252. },
  253. descText: {
  254. color: colorAccent,
  255. fontSize: 12,
  256. paddingTop: 2
  257. },
  258. itemPayment: {
  259. paddingTop: 8,
  260. paddingBottom: 8,
  261. alignItems: 'center',
  262. flexDirection: 'row'
  263. },
  264. tagDefault: {
  265. color: textLight,
  266. fontSize: 12,
  267. borderRadius: 4,
  268. ...$padding(4, 8),
  269. marginRight: 12,
  270. backgroundColor: colorAccent
  271. },
  272. textDefault: {
  273. color: colorAccent,
  274. fontSize: 12,
  275. marginRight: 8,
  276. fontWeight: 'bold'
  277. },
  278. defButton: {
  279. flex: 1,
  280. backgroundColor: colorPrimary
  281. },
  282. numberDot: {
  283. top: 10,
  284. left: app.charge.version >= 4 ? 32 : 35,
  285. width: 16,
  286. height: 16,
  287. color: textButton,
  288. fontSize: 10,
  289. fontWeight: 'bold',
  290. borderRadius: 32,
  291. position: 'absolute',
  292. alignItems: 'center',
  293. justifyContent: 'center',
  294. backgroundColor: app.charge.version >= 4 ? colorAccent : "#FF2622"
  295. }
  296. })