penaltyPaymentPageComponent.tsx 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import { View, Text, ScrollView, Pressable, StyleSheet, Alert } from 'react-native';
  2. import { SafeAreaView } from 'react-native-safe-area-context';
  3. import { router, useLocalSearchParams, useNavigation } from 'expo-router';
  4. import NormalButton from '../global/normal_button';
  5. import { useEffect } from 'react';
  6. import { chargeStationService } from '../../service/chargeStationService';
  7. import useUserInfoStore from '../../providers/userinfo_store';
  8. import { PreviousPageBlackSvg } from '../global/SVG';
  9. const PenaltyPaymentPageComponent = () => {
  10. const params = useLocalSearchParams();
  11. const { userID } = useUserInfoStore();
  12. console.log('params in penaltyPaymentPageComponent', params);
  13. const navigation = useNavigation();
  14. useEffect(() => {
  15. navigation.setOptions({
  16. gestureEnabled: false
  17. });
  18. }, [navigation]);
  19. const convertBookingDateTime = (isoDateString: string): { date: string; time: string } => {
  20. const bookingDate = new Date(isoDateString);
  21. // Adjust to local time (+8 hours)
  22. bookingDate.setHours(bookingDate.getHours());
  23. // Format date as "MM-DD"
  24. const date = `${(bookingDate.getMonth() + 1).toString().padStart(2, '0')}-${bookingDate
  25. .getDate()
  26. .toString()
  27. .padStart(2, '0')}`;
  28. // Format time as "HH:mm"
  29. const time = `${bookingDate.getHours().toString().padStart(2, '0')}:${bookingDate
  30. .getMinutes()
  31. .toString()
  32. .padStart(2, '0')}`;
  33. return { date, time };
  34. };
  35. const calculateUserEndTime = (actualEndTimeStr: string, penaltyFee: string): string => {
  36. const actualEndTime = new Date(actualEndTimeStr);
  37. const penaltyMinutes = Math.floor(parseFloat(penaltyFee) / 3); // $3 per minute
  38. const userEndTime = new Date(actualEndTime.getTime() + penaltyMinutes * 60000); // add minutes
  39. return userEndTime.toISOString();
  40. };
  41. const { date, time } = convertBookingDateTime(params.book_time);
  42. const { date: end_date, time: end_time } = convertBookingDateTime(params.end_time as string);
  43. const { date: actual_end_date, time: actual_end_time } = convertBookingDateTime(params.actual_end_time as string);
  44. const { time: user_end_time } = convertBookingDateTime(
  45. calculateUserEndTime(params.actual_end_time as string, params.penalty_fee as string)
  46. );
  47. const payload = {
  48. userId: userID,
  49. amount: parseFloat(params.penalty_fee as string),
  50. reservationId: params.id
  51. };
  52. const handlePayment = async () => {
  53. try {
  54. const result = await chargeStationService.payPenalty(payload);
  55. console.log('Payment result:', result);
  56. if (result.status) {
  57. Alert.alert('支付成功', '罰款已成功支付', [
  58. { text: '確認', onPress: () => router.replace('/mainPage') }
  59. ]);
  60. } else {
  61. Alert.alert('支付失敗', '餘額不足,即將跳轉到錢包', [
  62. { text: '確認', onPress: () => router.push('/(account)/(wallet)/walletPage') }
  63. ]);
  64. }
  65. } catch (error) {
  66. console.error('Payment error:', error);
  67. Alert.alert('支付錯誤', '發生錯誤,請稍後再試');
  68. }
  69. };
  70. return (
  71. <SafeAreaView style={{ flex: 1, backgroundColor: 'white' }} edges={['top', 'left', 'right']}>
  72. <ScrollView className="flex-1" showsVerticalScrollIndicator={false}>
  73. <View style={{ marginTop: 25 }} className="mx-[5%]">
  74. <Pressable
  75. onPress={() => {
  76. if (router.canGoBack()) {
  77. router.back();
  78. } else {
  79. router.replace('/mainPage');
  80. }
  81. }}
  82. >
  83. <PreviousPageBlackSvg />
  84. </Pressable>
  85. <Text className="text-3xl my-8 text-center">尚未繳付罰款的充電記錄</Text>
  86. </View>
  87. {/* <View className="pl-8 pt-8">
  88. <Text className="text-3xl mt-8">尚未繳付罰款的充電記錄</Text>
  89. </View> */}
  90. <View className="flex-1 mt-4 mx-[5%]">
  91. <View className="flex-1 flex-row items-center pb-3">
  92. <View className="flex-1 flex-column">
  93. <Text style={styles.grayColor} className="text-base">
  94. 實際充電到期時間
  95. </Text>
  96. <Text style={styles.greenColor} className="text-4xl text-center pt-2">
  97. {actual_end_time}
  98. </Text>
  99. </View>
  100. <View className="flex-1 flex-column">
  101. <Text style={styles.grayColor} className="text-base pl-7">
  102. 實際充電結束時間
  103. </Text>
  104. <Text style={styles.greenColor} className="text-4xl text-center pt-2">
  105. {user_end_time}
  106. </Text>
  107. </View>
  108. </View>
  109. <View className="flex-1 flex-column justify-center space-y-1 pb-3">
  110. <Text style={styles.grayColor} className="text-base">
  111. 充電日期
  112. </Text>
  113. <Text style={styles.greenColor} className="text-base">
  114. {date}
  115. </Text>
  116. </View>
  117. {/* <View className="flex-1 flex-column justify-center space-y-1 pb-3">
  118. <Text style={styles.grayColor} className="text-base">
  119. 充電地點
  120. </Text>
  121. <Text style={styles.greenColor} className="text-base ">
  122. Crazy Charge(偉業街)
  123. </Text>
  124. </View> */}
  125. <View className="flex-1 flex-column justify-center space-y-1 pb-3">
  126. <Text style={styles.grayColor} className="text-base">
  127. 罰款金額
  128. </Text>
  129. <Text style={styles.greenColor} className="text-lg ">
  130. {params.penalty_fee}
  131. </Text>
  132. </View>
  133. <View className="flex-1 flex-column justify-center space-y-1 pb-3">
  134. <Text style={styles.grayColor} className="text-base">
  135. 訂單編號
  136. </Text>
  137. <Text style={styles.greenColor} className=" ">
  138. {params.format_order_id}
  139. </Text>
  140. </View>
  141. </View>
  142. <View className="border-t mx-4 border-[#CCCCCC]"></View>
  143. <View className="flex-1 mx-[5%] mt-4 space-y-1">
  144. <View className="mt-4">
  145. <NormalButton
  146. title={
  147. <Text
  148. style={{
  149. color: 'white',
  150. fontSize: 16,
  151. fontWeight: '800'
  152. }}
  153. >
  154. 支付罰款
  155. </Text>
  156. }
  157. // onPress={handlePayment}
  158. onPress={() => {
  159. Alert.alert('將會從錢包餘額扣除款項以繳交罰款', '', [
  160. { text: '取消', style: 'cancel' },
  161. { text: '確認', onPress: handlePayment }
  162. ]);
  163. }}
  164. extendedStyle={{ padding: 24, marginTop: 24 }}
  165. />
  166. </View>
  167. </View>
  168. </ScrollView>
  169. </SafeAreaView>
  170. );
  171. };
  172. export default PenaltyPaymentPageComponent;
  173. const styles = StyleSheet.create({
  174. grayColor: {
  175. color: '#888888'
  176. },
  177. greenColor: {
  178. color: '#02677D'
  179. }
  180. });