chargingDetailsPageComponent.tsx 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import { View, Text, Pressable, Dimensions,Image, StyleSheet } from 'react-native';
  2. import { SafeAreaView } from 'react-native-safe-area-context';
  3. import { router, useLocalSearchParams } from 'expo-router';
  4. import { CrossLogoSvg } from '../global/SVG';
  5. import CouponTabViewComponent from '../global/couponTabView';
  6. import { useEffect, useMemo, useState, useRef } from 'react';
  7. import { chargeStationService } from '../../service/chargeStationService';
  8. import BookingTabViewComponent from '../global/bookingTabViewComponent';
  9. import { set } from 'lodash';
  10. import { ChargingDetails, Remark, ElectricityPrice, Special } from '../../service/type/chargeStationType';
  11. import { format, parseISO } from 'date-fns';
  12. const ChargingDetailsPageComponent = () => {
  13. const screenHeight = Dimensions.get('window').height;
  14. const params = useLocalSearchParams();
  15. const [list, setList] = useState<ChargingDetails>({} as ChargingDetails);
  16. const [time, setTime] = useState<string>('');
  17. useEffect(() => {
  18. const fetchData = async () => {
  19. const res = await chargeStationService.fetchChargingDetails(params.id.toString())
  20. if (res) {
  21. // If res is an array, take the first item; otherwise, set as is
  22. setList(Array.isArray(res) ? res[0] : {} as ChargingDetails);
  23. // 解析并格式化日期
  24. const startTime = parseISO(res[0].actual_start_time);
  25. const endTime = parseISO(res[0].actual_end_time);
  26. // 格式化为指定格式
  27. const formattedDate = `${format(startTime, 'yyyy/MM/dd HH:mm:ss')}-${format(endTime, 'HH:mm:ss')}`;
  28. setTime(formattedDate)
  29. }
  30. };
  31. fetchData();
  32. }, [])
  33. const totalPrice = useMemo(() => {
  34. if (list.total_fee && list.withdraw_fee) {
  35. let actual_fee = list.total_fee - list.withdraw_fee
  36. const value = actual_fee <= 0? '0': actual_fee % 1 === 0? `${actual_fee}`: `${actual_fee.toFixed(1)}`
  37. return value
  38. }
  39. return '0';
  40. }, [list]);
  41. return (
  42. <SafeAreaView className="flex-1 bg-white" edges={['top']}>
  43. <View style={{ minHeight: screenHeight, flex: 1 }}>
  44. <View className="mx-[5%]" style={{ marginTop: 25}}>
  45. <Pressable
  46. onPress={() => {
  47. if (router.canGoBack()) {
  48. router.back();
  49. } else {
  50. router.replace('/accountMainPage');
  51. }
  52. }}
  53. >
  54. <CrossLogoSvg />
  55. </Pressable>
  56. <View className="items-center px-3">
  57. {/* <View className="flex-3 items-center justify-end" style={{}}> */}
  58. <Image
  59. source={require('../../assets/ccLogo.png')}
  60. resizeMode="contain"
  61. style={{
  62. width: screenHeight > 750 ? 200 : 110,
  63. height: screenHeight > 750 ? 200 : 110
  64. }}
  65. />
  66. <Text style={styles.totalPrice}>- {totalPrice}</Text>
  67. <View style={styles.viewLine}></View>
  68. <View className='w-full flex-row justify-between mt-6 pr-10'>
  69. <Text style={styles.leftLable}>訂單编號: </Text>
  70. <Text style={styles.rightLable}>{list.format_order_id}</Text>
  71. </View>
  72. <View className='w-full flex-row justify-between my-3 pr-10'>
  73. <Text style={styles.leftLable}>充電時間: </Text>
  74. <Text style={styles.rightLable}>{time}</Text>
  75. </View>
  76. <View className='w-full flex-row justify-between pr-10 mb-4'>
  77. <Text style={styles.leftLable}>充電站位置:</Text>
  78. <Text style={styles.rightLable}>{params.chargeStationName}</Text>
  79. </View>
  80. <View style={styles.viewLine}></View>
  81. <ChargingDataComponent list={list} totalPrice={totalPrice}/>
  82. <View style={styles.viewLine}></View>
  83. <View className='w-full flex-row justify-between mt-6 pr-10'>
  84. <View>
  85. <Text style={styles.leftLable}>實付:</Text>
  86. {list.promotion_name ? <Text style={{fontSize: 12, color:'#888888'}}>優惠券支付</Text>: null}
  87. </View>
  88. <Text style={styles.rightLable}>${totalPrice}</Text>
  89. </View>
  90. </View>
  91. </View>
  92. <View style={{ width: "100%",height: 130 }} />
  93. </View>
  94. </SafeAreaView>
  95. );
  96. };
  97. interface ChargingDataComponentProps {
  98. list: ChargingDetails;
  99. totalPrice: string;
  100. }
  101. const ChargingDataComponent: React.FC<ChargingDataComponentProps> = ({
  102. list,
  103. totalPrice
  104. }) => {
  105. const [data, setData] = useState<Remark>({} as Remark);
  106. const [price, setPrice] = useState<number>(0);
  107. const hasFetchedPrice = useRef(false); // 添加 ref 跟踪是否已获取过价格
  108. useEffect(() => {
  109. const data = JSON.parse(list?.remark || '{}') as Remark;
  110. setData(data)
  111. if (!list.promotion_name && !hasFetchedPrice.current && list.actual_start_time) {
  112. chargeStationService.fetchElectricityPrice().then(res => {
  113. hasFetchedPrice.current = true; // 标记为已调用
  114. const date = new Date(list.actual_start_time);
  115. const str = date.toLocaleString('en-US', { weekday: 'short' }).toLowerCase();
  116. if (res && res.length > 0) {
  117. if (data.RushKwh) {
  118. const obj = (res[1][str as keyof ElectricityPrice]) as Special
  119. setPrice(obj.price)
  120. }
  121. if (data.ElseKwh) {
  122. const obj = (res[2][str as keyof ElectricityPrice]) as Special
  123. setPrice(obj.price)
  124. }
  125. if (data.OffKwh) {
  126. const obj = (res[0][str as keyof ElectricityPrice]) as Special
  127. setPrice(obj.price)
  128. }
  129. }
  130. })
  131. }
  132. }, [list.promotion_name, list.actual_start_time, list.remark])
  133. if (!list.promotion_name) {
  134. return (
  135. <View>
  136. {(data.RushKwh) ?
  137. <View>
  138. <View className='w-full flex-row justify-between mt-4 pr-10'>
  139. <Text style={styles.leftLable}>峰時總電量: </Text>
  140. <Text style={styles.rightLable}>{data.RushKwh?.toFixed(1)}</Text>
  141. </View>
  142. <View className='w-full flex-row justify-between my-3 pr-10'>
  143. <Text style={styles.leftLable}>峰時電價(09:00-20:59): </Text>
  144. <Text style={styles.rightLable}>${price}</Text>
  145. </View>
  146. <View className='w-full flex-row justify-between pr-10 mb-3'>
  147. <Text style={styles.leftLable}>峰時總電費:</Text>
  148. <Text style={styles.rightLable}>${totalPrice}</Text>
  149. </View>
  150. </View>: null }
  151. {(data.ElseKwh) ?
  152. <View>
  153. <View className='w-full flex-row justify-between mt-4 pr-10'>
  154. <Text style={styles.leftLable}>平時總電量: </Text>
  155. <Text style={styles.rightLable}>{data.RushKwh?.toFixed(1)}</Text>
  156. </View>
  157. <View className='w-full flex-row justify-between my-3 pr-10'>
  158. <Text style={styles.leftLable}>平時電價(09:00-20:59): </Text>
  159. <Text style={styles.rightLable}>${price}</Text>
  160. </View>
  161. <View className='w-full flex-row justify-between pr-10 mb-3'>
  162. <Text style={styles.leftLable}>平時總電費:</Text>
  163. <Text style={styles.rightLable}>${totalPrice}</Text>
  164. </View>
  165. </View>: null }
  166. {(data.OffKwh) ?
  167. <View>
  168. <View className='w-full flex-row justify-between mt-4 pr-10'>
  169. <Text style={styles.leftLable}>穀時總電量: </Text>
  170. <Text style={styles.rightLable}>{data.RushKwh?.toFixed(1)}</Text>
  171. </View>
  172. <View className='w-full flex-row justify-between my-3 pr-10'>
  173. <Text style={styles.leftLable}>穀時電價(09:00-20:59): </Text>
  174. <Text style={styles.rightLable}>${price}</Text>
  175. </View>
  176. <View className='w-full flex-row justify-between pr-10 mb-3'>
  177. <Text style={styles.leftLable}>穀時總電費:</Text>
  178. <Text style={styles.rightLable}>${totalPrice}</Text>
  179. </View>
  180. </View>: null }
  181. </View>
  182. )
  183. } else {
  184. return (
  185. <View>
  186. <View className='w-full flex-row justify-between mt-4 pr-10'>
  187. <Text style={styles.leftLable}>總電量: </Text>
  188. <Text style={styles.rightLable}>{data.TotalPower?.toFixed(1)}</Text>
  189. </View>
  190. <View className='w-full flex-row justify-between my-3 pr-10'>
  191. <Text style={styles.leftLable}>電價: </Text>
  192. <Text style={styles.rightLable}>${list?.connector?.EquipmentID?.StationID?.price}</Text>
  193. </View>
  194. <View className='w-full flex-row justify-between pr-10 mb-3'>
  195. <Text style={styles.leftLable}>總電費: </Text>
  196. <Text style={styles.rightLable}>${totalPrice}</Text>
  197. </View>
  198. </View>
  199. )
  200. }
  201. }
  202. const styles = StyleSheet.create({
  203. viewLine: {
  204. width: '100%',
  205. height: 1,
  206. backgroundColor: '#E5E5E5',
  207. },
  208. totalPrice: {
  209. fontSize: 26,
  210. fontWeight: 'bold',
  211. marginBottom: 25,
  212. },
  213. leftLable: {
  214. fontSize: 18,
  215. color:'#888888',
  216. },
  217. rightLable: {
  218. fontSize: 17
  219. },
  220. })
  221. export default ChargingDetailsPageComponent;