penaltyPaymentPageComponent.tsx 7.7 KB

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