paymentSummaryPageComponent.tsx 9.5 KB

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