noChargingOngoingPageComponent.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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, useFocusEffect } from 'expo-router';
  5. import { useCallback, 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. // useEffect(() => {
  30. // const fetchChargeStationInfo = async () => {
  31. // try {
  32. // const chargeStationInfo = await chargeStationService.fetchAllChargeStations();
  33. // setChargeStationInfo(chargeStationInfo);
  34. // } catch (error) {
  35. // console.error('Error fetching charge station info:', error);
  36. // }
  37. // };
  38. // fetchChargeStationInfo();
  39. // }, []);
  40. // const fetchConnectorWithRetry = async (stationId, retryCount = 0) => {
  41. // try {
  42. // const response = await chargeStationService.fetchAvailableConnectors(stationId);
  43. // if (response === 500 || !response) {
  44. // throw new Error('Server error');
  45. // }
  46. // return response;
  47. // } catch (error) {
  48. // if (retryCount < MAX_RETRIES) {
  49. // // console.log(`Retrying fetch for station ${stationId}, attempt ${retryCount + 1}`);
  50. // await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
  51. // return fetchConnectorWithRetry(stationId, retryCount + 1);
  52. // }
  53. // // console.error(`Failed to fetch connectors for station ${stationId} after ${MAX_RETRIES} attempts:`, error);
  54. // return null;
  55. // }
  56. // };
  57. // useEffect(() => {
  58. // const fetchAllConnectors = async () => {
  59. // try {
  60. // const connectorData = {};
  61. // for (const station of chargeStationInfo) {
  62. // const stationConnectors = await fetchConnectorWithRetry(station.id);
  63. // if (stationConnectors !== null) {
  64. // connectorData[station.id] = stationConnectors;
  65. // // Update state immediately for each successful fetch
  66. // setAvailableConnectors((prev) => ({
  67. // ...prev,
  68. // [station.id]: stationConnectors
  69. // }));
  70. // }
  71. // }
  72. // } catch (error) {
  73. // console.error('Error fetching connectors:', error);
  74. // }
  75. // };
  76. // if (chargeStationInfo.length > 0) {
  77. // fetchAllConnectors();
  78. // }
  79. // }, [chargeStationInfo]);
  80. const [newAvailableConnectors, setNewAvailableConnectors] = useState([]);
  81. useFocusEffect(
  82. useCallback(() => {
  83. let isMounted = true; // Simple cleanup flag
  84. const fetchAllConnectors = async () => {
  85. try {
  86. const newAvailableConnectors = await chargeStationService.NewfetchAvailableConnectors();
  87. console.log('Fetched connectors:', newAvailableConnectors);
  88. // Only update state if component is still mounted
  89. if (isMounted) {
  90. // Sort the connectors based on stationID
  91. const sortedConnectors = [...newAvailableConnectors].sort((a, b) => {
  92. // Custom sorting order
  93. const order = {
  94. '2405311022116801000': 1, // 觀塘偉業街
  95. '2411291610329331000': 2, // 黃竹坑
  96. '2501161430118231000': 3 // 沙頭角
  97. };
  98. return (order[a.stationID] || 999) - (order[b.stationID] || 999);
  99. });
  100. console.log('newAvailableConnectors', sortedConnectors);
  101. setNewAvailableConnectors(sortedConnectors);
  102. }
  103. } catch (error) {
  104. console.error('Fetch error:', error);
  105. }
  106. };
  107. fetchAllConnectors();
  108. // Simple cleanup - prevents state updates if component unmounts
  109. return () => {
  110. isMounted = false;
  111. };
  112. }, []) // Add any missing dependencies here if needed
  113. );
  114. const StationRow = ({ item }: { item: any }) => {
  115. //use different image for different station based on station id, if not found, use default image.
  116. const stationID = item.stationID;
  117. const stationImages = {
  118. //沙頭角
  119. '2501161430118231000': require('../../assets/dummyStationPicture5.jpeg'),
  120. //黃竹坑
  121. '2411291610329331000': require('../../assets/dummyStationPicture4.jpeg'),
  122. //觀塘
  123. '2405311022116801000': require('../../assets/dummyStationPicture.png')
  124. };
  125. // const imageSource = stationImages[stationID] || require('../../assets/dummyStationPicture.png');
  126. return (
  127. <Pressable
  128. onPress={() => {
  129. router.push({
  130. pathname: '/resultDetailPage',
  131. params: {
  132. chargeStationAddress: item.address,
  133. chargeStationID: item.stationID,
  134. chargeStationName: item.stationName,
  135. availableConnectors: item.availableConnectors,
  136. // imageSource: imageSource
  137. imageSource: item.image
  138. }
  139. });
  140. }}
  141. >
  142. <View className="flex flex-1 flex-row w-full ">
  143. <Image style={styles.image} source={{ uri: item.image }} />
  144. <View className="flex flex-col gap-2 mt-5 mr-2">
  145. <Text
  146. style={{
  147. fontWeight: '700',
  148. color: '#02677D',
  149. fontSize: 20
  150. }}
  151. >
  152. {item.stationName}
  153. </Text>
  154. <View className="flex flex-row justify-between space-x-2">
  155. <Text
  156. style={{
  157. fontWeight: '400',
  158. fontSize: 16,
  159. color: '#222222'
  160. }}
  161. >
  162. {item.address}
  163. </Text>
  164. </View>
  165. <Text
  166. style={{
  167. fontWeight: '400',
  168. fontSize: 16,
  169. color: '#888888'
  170. }}
  171. >
  172. 現時可用充電槍數目: {item.availableConnectors}
  173. </Text>
  174. </View>
  175. </View>
  176. </Pressable>
  177. );
  178. };
  179. return (
  180. <SafeAreaView edges={['top', 'left', 'right']} className="flex-1 bg-white">
  181. <ScrollView className="flex-1 mt-8 " nestedScrollEnabled={true} showsVerticalScrollIndicator={false}>
  182. <View className="">
  183. <View className="">
  184. <Text className="text-5xl pt-1 pb-6 mx-[5%]">暫無正在進行的充電</Text>
  185. <View>
  186. <Text className="text-lg mx-[5%] mb-6">立刻前往Crazy Charge 充電站充電吧!</Text>
  187. <View className="">
  188. {newAvailableConnectors?.map((item, index) => (
  189. <View key={index}>
  190. <View className=" border-b border-gray-200" />
  191. <StationRow item={item} key={index} />
  192. </View>
  193. ))}
  194. </View>
  195. </View>
  196. </View>
  197. </View>
  198. </ScrollView>
  199. </SafeAreaView>
  200. );
  201. };
  202. const styles = StyleSheet.create({
  203. grayColor: {
  204. color: '#888888'
  205. },
  206. greenColor: {
  207. color: '#02677D'
  208. },
  209. image: {
  210. width: 100,
  211. height: 100,
  212. margin: 15,
  213. borderRadius: 10
  214. }
  215. });
  216. export default NoChargingOngoingPageComponent;
  217. // const styles = StyleSheet.create({
  218. // container: {
  219. // flexDirection: 'row',
  220. // width: '100%',
  221. // flex: 1
  222. // },
  223. // textContainer: {
  224. // flex: 1,
  225. // flexDirection: 'column',
  226. // gap: 8,
  227. // marginTop: 20,
  228. // marginRight: 8 // Add right margin to prevent text from touching the edge
  229. // }
  230. // });