noChargingOngoingPageComponent.tsx 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import { View, Text, ScrollView, StyleSheet, ActivityIndicator, Pressable, Image } from 'react-native';
  2. import { SafeAreaView } from 'react-native-safe-area-context';
  3. import NormalButton from '../global/normal_button';
  4. import { router } from 'expo-router';
  5. import { useEffect, useState } from 'react';
  6. import { chargeStationService } from '../../service/chargeStationService';
  7. const RETRY_DELAY = 2000; // 2 seconds
  8. const MAX_RETRIES = 3; // Maximum number of retry attempts
  9. const NoChargingOngoingPageComponent = () => {
  10. //fetch charge station info
  11. const [chargeStationInfo, setChargeStationInfo] = useState([]);
  12. const [availableConnectors, setAvailableConnectors] = useState({});
  13. useEffect(() => {
  14. const fetchChargeStationInfo = async () => {
  15. try {
  16. const chargeStationInfo = await chargeStationService.fetchAllChargeStations();
  17. console.log('chargeStationInfo in noChargingOngoingPageComponent', chargeStationInfo);
  18. const onlyWaiYipStreetStation = chargeStationInfo.filter(
  19. (station) => station.id == '2405311022116801000'
  20. );
  21. setChargeStationInfo(onlyWaiYipStreetStation);
  22. // setChargeStationInfo(chargeStationInfo);
  23. } catch (error) {
  24. console.error('Error fetching charge station info:', error);
  25. }
  26. };
  27. fetchChargeStationInfo();
  28. }, []);
  29. const fetchConnectorWithRetry = async (stationId, retryCount = 0) => {
  30. try {
  31. const response = await chargeStationService.fetchAvailableConnectors(stationId);
  32. if (response === 500 || !response) {
  33. throw new Error('Server error');
  34. }
  35. return response;
  36. } catch (error) {
  37. if (retryCount < MAX_RETRIES) {
  38. console.log(`Retrying fetch for station ${stationId}, attempt ${retryCount + 1}`);
  39. await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
  40. return fetchConnectorWithRetry(stationId, retryCount + 1);
  41. }
  42. console.error(`Failed to fetch connectors for station ${stationId} after ${MAX_RETRIES} attempts:`, error);
  43. return null;
  44. }
  45. };
  46. useEffect(() => {
  47. const fetchAllConnectors = async () => {
  48. try {
  49. const connectorData = {};
  50. for (const station of chargeStationInfo) {
  51. const stationConnectors = await fetchConnectorWithRetry(station.id);
  52. if (stationConnectors !== null) {
  53. connectorData[station.id] = stationConnectors;
  54. // Update state immediately for each successful fetch
  55. setAvailableConnectors((prev) => ({
  56. ...prev,
  57. [station.id]: stationConnectors
  58. }));
  59. }
  60. }
  61. } catch (error) {
  62. console.error('Error fetching connectors:', error);
  63. }
  64. };
  65. if (chargeStationInfo.length > 0) {
  66. fetchAllConnectors();
  67. }
  68. }, [chargeStationInfo]);
  69. const StationRow = ({ item }) => (
  70. <Pressable
  71. onPress={() => {
  72. router.push({
  73. pathname: '/resultDetailPage',
  74. params: {
  75. chargeStationAddress: item.snapshot.Address,
  76. chargeStationID: item.id,
  77. chargeStationName: item.snapshot.StationName,
  78. availableConnectors: availableConnectors[item.id]
  79. }
  80. });
  81. }}
  82. >
  83. <View className="flex flex-1 flex-row w-full ">
  84. <Image style={styles.image} source={require('../../assets/dummyStationPicture.png')} />
  85. <View className="flex flex-col gap-2 mt-5 mr-2">
  86. <Text
  87. style={{
  88. fontWeight: '700',
  89. color: '#02677D',
  90. fontSize: 20
  91. }}
  92. >
  93. {item.snapshot.StationName}
  94. </Text>
  95. <View className="flex flex-row justify-between space-x-2">
  96. <Text
  97. style={{
  98. fontWeight: '400',
  99. fontSize: 16,
  100. color: '#222222'
  101. }}
  102. >
  103. {item.snapshot.Address}
  104. </Text>
  105. {/* <Text
  106. style={{
  107. fontWeight: '400',
  108. fontSize: 16,
  109. color: '#222222'
  110. }}
  111. >
  112. 已付金額:{' '}
  113. {item.actual_fee
  114. ? item.actual_fee % 1 === 0
  115. ? `$${item.actual_fee}`
  116. : `$${item.actual_fee.toFixed(1)}`
  117. : ''}
  118. </Text> */}
  119. </View>
  120. {!availableConnectors[item.id] && (
  121. <Text
  122. style={{
  123. fontWeight: '400',
  124. fontSize: 16,
  125. color: '#888888'
  126. }}
  127. >
  128. 正在查詢可用充電槍數目...
  129. </Text>
  130. )}
  131. {availableConnectors[item.id] && (
  132. <Text
  133. style={{
  134. fontWeight: '400',
  135. fontSize: 16,
  136. color: '#888888'
  137. }}
  138. >
  139. 現時可用充電槍數目: {availableConnectors[item.id]}
  140. </Text>
  141. )}
  142. </View>
  143. </View>
  144. </Pressable>
  145. );
  146. return (
  147. <SafeAreaView edges={['top', 'left', 'right']} className="flex-1 bg-white">
  148. <ScrollView className="flex-1 mt-8 " nestedScrollEnabled={true} showsVerticalScrollIndicator={false}>
  149. <View className="">
  150. <View className="">
  151. <Text className="text-5xl pt-1 pb-6 mx-[5%]">暫無正在進行的充電</Text>
  152. <View>
  153. <Text className="text-lg mx-[5%] mb-6">立刻前往Crazy Charge 充電站充電吧!</Text>
  154. <View className="">
  155. {chargeStationInfo?.map((item, index) => (
  156. <View key={index}>
  157. <View className=" border-b border-gray-200" />
  158. <StationRow item={item} key={index} />
  159. </View>
  160. ))}
  161. {/* <NormalButton
  162. title={<Text className="text-white text-lg">前往預約頁面</Text>}
  163. onPress={() => router.push('/bookingMenuPage')}
  164. /> */}
  165. </View>
  166. </View>
  167. </View>
  168. </View>
  169. </ScrollView>
  170. </SafeAreaView>
  171. );
  172. };
  173. const styles = StyleSheet.create({
  174. grayColor: {
  175. color: '#888888'
  176. },
  177. greenColor: {
  178. color: '#02677D'
  179. },
  180. image: {
  181. width: 100,
  182. height: 100,
  183. margin: 15,
  184. borderRadius: 10
  185. }
  186. });
  187. export default NoChargingOngoingPageComponent;
  188. // const styles = StyleSheet.create({
  189. // container: {
  190. // flexDirection: 'row',
  191. // width: '100%',
  192. // flex: 1
  193. // },
  194. // textContainer: {
  195. // flex: 1,
  196. // flexDirection: 'column',
  197. // gap: 8,
  198. // marginTop: 20,
  199. // marginRight: 8 // Add right margin to prevent text from touching the edge
  200. // }
  201. // });