chargingPageComponent.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import { View, Text, ScrollView, StyleSheet, Image, ActivityIndicator } from 'react-native';
  2. import { SafeAreaView } from 'react-native-safe-area-context';
  3. import RippleEffectBatteryIcon from '../global/rippleEffectBatteryIcon';
  4. import LoadingDots from '../global/loadingDots';
  5. import NormalButton from '../global/normal_button';
  6. import { router } from 'expo-router';
  7. import { BatteryIconSvg, LightingLogoSvg, TemperatureIconSvg } from '../global/SVG';
  8. import { useEffect, useState } from 'react';
  9. import { chargeStationService } from '../../service/chargeStationService';
  10. import { set } from 'date-fns';
  11. import { convertToHKTime } from '../../util/lib';
  12. import ChargingPenaltyPageComponent from './chargingPenaltyComponent';
  13. const ChargingPageComponent = ({ data }) => {
  14. const reservationData = Array.isArray(data) ? data[0] : data;
  15. const [isLoading, setIsLoading] = useState(true);
  16. const [onGoingChargingData, setOnGoingChargingData] = useState();
  17. useEffect(() => {
  18. const fetchOngoingChargingData = async () => {
  19. setIsLoading(true);
  20. try {
  21. const response = await chargeStationService.fetchOngoingChargingData(reservationData.format_order_id);
  22. if (response) {
  23. setOnGoingChargingData(response);
  24. console.log('i am ongoingchargingdata', response);
  25. } else {
  26. console.log('error fetching data');
  27. }
  28. } catch (error) {
  29. console.error('Error fetching reservation histories:', error);
  30. } finally {
  31. setIsLoading(false);
  32. }
  33. };
  34. fetchOngoingChargingData();
  35. }, [reservationData]);
  36. //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時
  37. const [timeSince, setTimeSince] = useState<string>('');
  38. useEffect(() => {
  39. const updateTimeSince = () => {
  40. if (reservationData && reservationData.actual_start_time) {
  41. setTimeSince(timeSinceBooking(reservationData.actual_start_time) || '計算中...');
  42. } else {
  43. setTimeSince('計算中...');
  44. }
  45. };
  46. updateTimeSince();
  47. // Update every minute
  48. const intervalId = setInterval(updateTimeSince, 60000);
  49. // Cleanup interval on component unmount
  50. return () => clearInterval(intervalId);
  51. }, [reservationData]);
  52. function timeSinceBooking(timeString) {
  53. if (timeString) {
  54. const startTime = new Date(timeString);
  55. const now = new Date();
  56. const diffInMilliseconds = now - startTime;
  57. const diffInMinutes = Math.floor(diffInMilliseconds / (1000 * 60));
  58. if (diffInMinutes < 1) {
  59. return '< 1 minute';
  60. } else {
  61. return `${diffInMinutes} minute${diffInMinutes !== 1 ? 's' : ''}`;
  62. }
  63. }
  64. }
  65. //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時
  66. const displayKW = (currentA: number, voltageA: number) => {
  67. if (currentA && voltageA) {
  68. return (currentA * voltageA) / 1000;
  69. } else return 30.0;
  70. };
  71. if (isLoading) {
  72. return (
  73. <SafeAreaView style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
  74. <ActivityIndicator size="large" />
  75. <Text>Loading...</Text>
  76. </SafeAreaView>
  77. );
  78. }
  79. return (
  80. <SafeAreaView style={{ flex: 1, backgroundColor: 'white' }} edges={['top', 'left', 'right']}>
  81. <ScrollView className="flex-1">
  82. <View className="flex-1 mx-[5%] space-y-4">
  83. <View className="items-center">
  84. <View className="mt-6 mb-4">
  85. <Text className="text-lg ">現正充電中:</Text>
  86. </View>
  87. <Text className="text-4xl font-light">
  88. {reservationData.car.car_brand.name} {reservationData.car.car_type.name}
  89. </Text>
  90. </View>
  91. <View className="items-center">
  92. <Text className="text-lg" style={styles.grayColor}>
  93. 充電中
  94. </Text>
  95. <View className="flex-row space-x-4 p-4 pr-8 items-center justify-center ml-10">
  96. <RippleEffectBatteryIcon />
  97. <Text
  98. style={{
  99. color: '#02677D',
  100. fontSize: 60,
  101. fontWeight: 300
  102. }}
  103. >
  104. {/* {onGoingChargingData ? `${onGoingChargingData.Soc} %` : 'Loading'} */}
  105. {`${reservationData.Soc}%`}
  106. <LoadingDots />
  107. </Text>
  108. </View>
  109. {/* 尚餘時間未知點計住 comments左先
  110. <Text className="text-lg mb-6" style={styles.grayColor}>
  111. 尚餘時間 ~48 mins
  112. </Text> */}
  113. <View className="mb-[-10] items-center justify-center ">
  114. <Image
  115. source={require('../../assets/car.png')}
  116. style={{ width: 430, height: 200 }}
  117. resizeMode="contain"
  118. />
  119. </View>
  120. </View>
  121. <View
  122. className="h-[220px] min-h-[20px] border-slate-300 rounded-2xl flex-column"
  123. style={{ borderWidth: 1 }}
  124. >
  125. {/* Top */}
  126. <View className="h-[65%] flex-row justify-evenly items-center">
  127. <View className="flex-1 flex-column items-center space-y-2">
  128. <LightingLogoSvg />
  129. <Text style={styles.grayColor} className="text-base">
  130. 充電功率
  131. </Text>
  132. {isLoading ? (
  133. <ActivityIndicator />
  134. ) : (
  135. <Text style={styles.greenColor} className="font-bold text-base">
  136. {displayKW(onGoingChargingData.CurrentA, onGoingChargingData.VoltageA)}kW
  137. </Text>
  138. )}
  139. </View>
  140. <View className="flex-1 flex-column items-center space-y-2">
  141. <BatteryIconSvg />
  142. <Text style={styles.grayColor} className="text-base">
  143. 實際功率
  144. </Text>
  145. {isLoading ? (
  146. <ActivityIndicator />
  147. ) : (
  148. <Text style={styles.greenColor} className="font-bold text-base">
  149. {displayKW(onGoingChargingData.CurrentA, onGoingChargingData.VoltageA)}kW
  150. </Text>
  151. )}
  152. </View>
  153. <View className="flex-1 flex-column items-center space-y-2">
  154. <TemperatureIconSvg />
  155. <Text style={styles.grayColor} className="text-base">
  156. 溫度
  157. </Text>
  158. {isLoading ? (
  159. <ActivityIndicator />
  160. ) : (
  161. <Text style={styles.greenColor} className="font-bold text-base">
  162. 36°c
  163. </Text>
  164. )}
  165. </View>
  166. </View>
  167. <View className="mx-[5%]">
  168. <View className="h-[1px] w-[100%] bg-[#CCCCCC]" />
  169. </View>
  170. {/* bottom container */}
  171. <View className="h-[35%] mx-[5%] justify-center ">
  172. <Text style={styles.grayColor} className="text-base">
  173. 充電歷時 ~{timeSince}
  174. </Text>
  175. </View>
  176. </View>
  177. {/* <View
  178. className="min-h-[20px] border-slate-300 rounded-2xl justify-center p-4"
  179. style={{ borderWidth: 1 }}
  180. >
  181. <View className="flex-row items-center justify-between ">
  182. <View>
  183. <Text className="text-lg">預計充電費用</Text>
  184. <Text className="text-base" style={styles.grayColor}>
  185. 按每度電結算: 50 kWh
  186. </Text>
  187. </View>
  188. <Text className="text-3xl">HK$ 175</Text>
  189. </View>
  190. </View> */}
  191. <View className="border-slate-300 rounded-2xl justify-center p-4" style={{ borderWidth: 1 }}>
  192. <Text className="text-lg pb-1 ">其他資訊</Text>
  193. <View className="flex-row">
  194. <View className="flex-1 flex-column">
  195. <Text className="text-base" style={styles.grayColor}>
  196. 開始時間
  197. </Text>
  198. <Text className="text-base">
  199. {convertToHKTime(reservationData.actual_start_time).hkTime.slice(0, 5)}
  200. </Text>
  201. </View>
  202. <View className="flex-1 flex-column">
  203. <Text className="text-base" style={styles.grayColor}>
  204. 充電座
  205. </Text>
  206. {/* <Text className="text-base">{reservationData.connector.ConnectorID}</Text> */}
  207. <Text className="text-base">A104</Text>
  208. </View>
  209. </View>
  210. </View>
  211. <View>
  212. <NormalButton
  213. onPress={() => {
  214. router.push('chargingPage');
  215. }}
  216. title={
  217. <Text className="text-xl text-white" style={{ fontWeight: 900 }}>
  218. 完成充電
  219. </Text>
  220. }
  221. />
  222. </View>
  223. <View>
  224. <NormalButton
  225. onPress={() => {
  226. router.push('/chargingPenaltyPage');
  227. }}
  228. title={
  229. <Text className="text-xl text-white" style={{ fontWeight: 900 }}>
  230. 觀看閒置/罰款狀態頁面
  231. </Text>
  232. }
  233. />
  234. </View>
  235. </View>
  236. </ScrollView>
  237. </SafeAreaView>
  238. );
  239. };
  240. export default ChargingPageComponent;
  241. const styles = StyleSheet.create({
  242. grayColor: {
  243. color: '#888888'
  244. },
  245. greenColor: {
  246. color: '#02677D'
  247. },
  248. text: {
  249. fontWeight: 300,
  250. color: '#000000'
  251. }
  252. });