paymentSummaryPageComponent.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import { View, Text, ScrollView, StyleSheet, Pressable } from 'react-native';
  2. import { SafeAreaView } from 'react-native-safe-area-context';
  3. import { Alert } from 'react-native';
  4. import NormalButton from '../global/normal_button';
  5. import { router, useLocalSearchParams } from 'expo-router';
  6. import { GrayRightArrowIconSvg, RightArrowIconSvg, TickLogoSvg } from '../global/SVG';
  7. import { useEffect, useRef, useState } from 'react';
  8. import useBookingStore from '../../providers/booking_store';
  9. import useCouponStore from '../../providers/coupon_store';
  10. import { walletService } from '../../service/walletService';
  11. const PaymentSummaryPageComponent = () => {
  12. const selectedCouponName = useCouponStore((state) => state.selectedCouponName);
  13. const selectedCouponRedeemCode = useCouponStore((state) => state.selectedCouponRedeemCode);
  14. const selectedCouponPrice = useCouponStore((state) => state.selectedCouponPrice);
  15. const params = useLocalSearchParams();
  16. const setBookingInfo = useBookingStore((state) => state.setBookingInfo);
  17. const initialSetupDone = useRef(false);
  18. const [formatOrderId, setFormatOrderId] = useState('');
  19. useEffect(() => {
  20. if (!initialSetupDone.current && Object.keys(params).length > 0) {
  21. const bookingInfo = {
  22. bookTime: params.bookTime,
  23. date: params.date,
  24. carID: params.carID as string,
  25. chargingWatt: params.chargingWatt as string,
  26. connectorID: params.connectorID as string,
  27. price: params.price as string,
  28. stationID: params.stationID as string,
  29. user: params.userID as string,
  30. paymentFee: params.paymentFee as string,
  31. carCapacitance: params.carCapacitance as string
  32. };
  33. setBookingInfo(bookingInfo);
  34. console.log('Booking info stored:', bookingInfo);
  35. initialSetupDone.current = true;
  36. }
  37. }, [params, setBookingInfo]);
  38. const { bookTime, date, carID, chargingWatt, connectorID, price, stationID, user, paymentFee, carCapacitance } =
  39. useBookingStore();
  40. const calculateFinalFee = (): string => {
  41. console.log('selected coupon price:', selectedCouponPrice);
  42. if (selectedCouponRedeemCode && selectedCouponPrice) {
  43. const difference = parseFloat(paymentFee) - parseFloat(selectedCouponPrice);
  44. return Math.max(0, difference).toFixed(2);
  45. } else {
  46. return paymentFee;
  47. }
  48. };
  49. const finalFee = calculateFinalFee();
  50. const total_power = chargingWatt === '' ? carCapacitance : parseFloat(chargingWatt.split('~')[0]);
  51. const promotion_code = selectedCouponRedeemCode || '';
  52. const convertEndTime = (num1: number) => {
  53. switch (num1) {
  54. case 20:
  55. return 25;
  56. case 25:
  57. return 30;
  58. case 30:
  59. return 40;
  60. case 40:
  61. return 45;
  62. }
  63. };
  64. function convertToUTC(date, bookTime) {
  65. const currentYear = new Date().getFullYear();
  66. const [month, day] = date.split('/');
  67. const fullDate = new Date(`${currentYear}-${month}-${day}T${bookTime}:00`);
  68. fullDate.setHours(fullDate.getHours());
  69. return fullDate;
  70. }
  71. const book_time = convertToUTC(date, bookTime);
  72. const timeRequiredInMinute = convertEndTime(Number(chargingWatt.split(' ')[0]));
  73. function findEndTime(num1, book_time) {
  74. const date = new Date(book_time);
  75. date.setMinutes(date.getMinutes() + num1);
  76. return date;
  77. }
  78. let end_time;
  79. if (chargingWatt === '') {
  80. end_time = book_time;
  81. } else {
  82. const endingTime = findEndTime(timeRequiredInMinute, book_time);
  83. end_time = endingTime;
  84. }
  85. const handleSubmitPayment = async () => {
  86. let type = 'reservation';
  87. let is_ic_call = false;
  88. console.log('i am handleSubmitPayment, connectorID:', connectorID);
  89. try {
  90. const response = await walletService.submitPayment(
  91. stationID,
  92. connectorID,
  93. user,
  94. book_time,
  95. end_time,
  96. total_power,
  97. total_fee,
  98. promotion_code,
  99. carID,
  100. type,
  101. is_ic_call
  102. );
  103. if (response.status === 200 || response.status === 201) {
  104. console.log('submit payment successful');
  105. // router.push('/paymentFinishPage');
  106. router.push({
  107. pathname: '/paymentFinishPage',
  108. params: { formatOrderId: response.data.format_order_id }
  109. });
  110. } else if (response.status === 400) {
  111. console.log('400 error in paymentSummaryPageComponent');
  112. Alert.alert('餘額不足', '您的餘額不足,請充值後再試。');
  113. } else {
  114. console.log('submit payment failed:', response.status);
  115. }
  116. } catch (error) {
  117. console.log('submit payment error:', error);
  118. }
  119. };
  120. const total_fee = parseInt(finalFee, 10);
  121. // console.log(' i am only console.log all variables for clarity:', {
  122. // stationID,
  123. // connectorID,
  124. // user,
  125. // book_time,
  126. // end_time,
  127. // total_power,
  128. // total_fee,
  129. // promotion_code,
  130. // carID
  131. // });
  132. return (
  133. <SafeAreaView className="flex-1 bg-white" edges={['top', 'left', 'right']}>
  134. <ScrollView className="flex-1 mx-[5%]" showsVerticalScrollIndicator={false}>
  135. <View style={{ marginTop: 25 }}>
  136. <Text style={{ fontSize: 45, paddingBottom: 12 }}>付款概要</Text>
  137. <View className="flex-column">
  138. <Pressable onPress={() => router.push('selectCouponPage')}>
  139. <Text className="text-lg pb-4">優惠券</Text>
  140. {selectedCouponName === '' ? (
  141. <View
  142. style={{
  143. borderWidth: 1,
  144. padding: 20,
  145. borderRadius: 12,
  146. borderColor: '#bbbbbb'
  147. }}
  148. className="rounded-xl h-[9vh] items-center flex-row pl-6 justify-between"
  149. >
  150. <View className="flex-row items-center ">
  151. <Text className="color-[#999999] px-4 text-base">選擇優惠券</Text>
  152. </View>
  153. <View className="pr-4">
  154. <GrayRightArrowIconSvg />
  155. </View>
  156. </View>
  157. ) : (
  158. <View className="bg-[#e9f2f7] rounded-xl h-[9vh] items-center flex-row pl-6 justify-between">
  159. <View className="flex-row items-center ">
  160. <TickLogoSvg />
  161. <Text className="color-[#34667c] px-4 text-base">{selectedCouponName}</Text>
  162. </View>
  163. <View className="pr-4">
  164. <RightArrowIconSvg />
  165. </View>
  166. </View>
  167. )}
  168. </Pressable>
  169. </View>
  170. <View>
  171. <Text className="text-xl py-4">收費概要</Text>
  172. <View className="flex-row justify-between">
  173. <Text className="text-base">充電費用</Text>
  174. <Text className="text-base">HK ${finalFee}</Text>
  175. </View>
  176. {chargingWatt === '' ? (
  177. <Text style={styles.grayColor} className="text-base">
  178. 充滿停機預估費用
  179. </Text>
  180. ) : (
  181. <Text style={styles.grayColor} className="text-base">
  182. 按每度電結算:
  183. {chargingWatt?.split('~')[0]}
  184. </Text>
  185. )}
  186. <View className="h-0.5 my-3 bg-[#f4f4f4]" />
  187. <View className="flex-row justify-between ">
  188. <Text className="text-xl">總計</Text>
  189. <Text className="text-3xl">
  190. HK$
  191. {finalFee}
  192. </Text>
  193. </View>
  194. <View className="mt-4 ">
  195. <NormalButton
  196. title={
  197. <Text
  198. style={{
  199. color: 'white',
  200. fontSize: 16,
  201. fontWeight: '800'
  202. }}
  203. >
  204. 前往付款
  205. </Text>
  206. }
  207. onPress={
  208. // () => router.push('/paymentFinishPage')
  209. handleSubmitPayment
  210. }
  211. extendedStyle={{ padding: 24 }}
  212. />
  213. </View>
  214. <View className="h-8" />
  215. </View>
  216. </View>
  217. </ScrollView>
  218. </SafeAreaView>
  219. );
  220. };
  221. export default PaymentSummaryPageComponent;
  222. const styles = StyleSheet.create({
  223. grayColor: {
  224. color: '#888888'
  225. },
  226. greenColor: {
  227. color: '#02677D'
  228. }
  229. });