chargingPageComponent.tsx 13 KB

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