paymentSummaryPageComponent.tsx 10 KB

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