setVehiclesOne.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. import React, { useEffect, useState } from 'react';
  2. import { View, Text, Image, Pressable, StyleSheet, ScrollView, ActivityIndicator } from 'react-native';
  3. import { FlashList } from '@shopify/flash-list';
  4. import { router } from 'expo-router';
  5. import { SafeAreaView } from 'react-native-safe-area-context';
  6. import useVehicleStore from '../../../../../providers/vehicle_store';
  7. import { chargeStationService } from '../../../../../service/chargeStationService';
  8. import { PreviousPageBlackSvg } from '../../../../../component/global/SVG';
  9. interface AlphabetSection {
  10. letter: string;
  11. brands: CarBrand[];
  12. }
  13. interface CarBrand {
  14. id: number;
  15. name: string;
  16. img_url: string;
  17. car_types: any[];
  18. }
  19. const brandLogos = {
  20. audi: require('../../../../../assets/audi.png'),
  21. benz: require('../../../../../assets/benz.png'),
  22. bmw: require('../../../../../assets/bmw.png'),
  23. byd: require('../../../../../assets/byd.png'),
  24. lexus: require('../../../../../assets/lexus.png'),
  25. mg: require('../../../../../assets/mg.png'),
  26. porsche: require('../../../../../assets/porsche.png'),
  27. tesla: require('../../../../../assets/tesla.png'),
  28. toyota: require('../../../../../assets/toyota.png'),
  29. xiaomi: require('../../../../../assets/xiaomi.png')
  30. };
  31. const SetVehiclesOne = () => {
  32. const [loading, setLoading] = useState(true);
  33. const [processedCarData, setProcessedCarData] = useState<CarBrand[]>([]);
  34. const { vehicleBrand, vehicleModel, BrandID, ModelID, setVehicleBrand, setBrandID } = useVehicleStore();
  35. useEffect(() => {
  36. const fetchCarBrand = async () => {
  37. try {
  38. const response = await chargeStationService.fetchCarBrand();
  39. if (response) {
  40. setProcessedCarData(response.data);
  41. console.log(
  42. 'All brand names:',
  43. response.data.map((brand) => brand.name)
  44. );
  45. }
  46. } catch (error) {
  47. console.log(error);
  48. } finally {
  49. setLoading(false);
  50. }
  51. };
  52. fetchCarBrand();
  53. }, []);
  54. useEffect(() => {
  55. console.log('Zustand VehicleBrand', vehicleBrand);
  56. console.log('Zustand BrandID', BrandID);
  57. console.log('Zustand VehicleModel', vehicleModel);
  58. console.log('Zustand ModelID', ModelID);
  59. }, [processedCarData]);
  60. const renderBrandItem = ({ item: brand }: { item: CarBrand }) => (
  61. <Pressable
  62. key={brand.id}
  63. style={styles.brandItem}
  64. onPress={() => {
  65. setVehicleBrand(brand.name);
  66. setBrandID(brand.id);
  67. router.push({
  68. pathname: 'setVehiclesTwo',
  69. params: {
  70. brandId: brand.id.toString(),
  71. brandName: brand.name,
  72. carTypes: JSON.stringify(brand.car_types)
  73. }
  74. });
  75. }}
  76. >
  77. <Image source={brandLogos[brand.name.toLowerCase()]} style={styles.logo} resizeMode="contain" />
  78. <Text style={styles.brandName}>{brand.name}</Text>
  79. </Pressable>
  80. );
  81. const renderAlphabetSection = ({ item: section }: { item: AlphabetSection }) => (
  82. <View>
  83. <View style={styles.letterHeader} className="h-9">
  84. <Text style={styles.letterText}>{section.letter}</Text>
  85. </View>
  86. <View style={styles.brandRow}>{section.brands.map((brand) => renderBrandItem({ item: brand }))}</View>
  87. </View>
  88. );
  89. return (
  90. <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
  91. <ScrollView showsVerticalScrollIndicator={false} className="flex-1 mx-[5%]">
  92. <View style={{ marginTop: 25 }}>
  93. <Pressable
  94. className="self-start"
  95. onPress={() => {
  96. if (router.canGoBack()) {
  97. router.back();
  98. } else {
  99. router.replace('/accountMainPage');
  100. }
  101. }}
  102. >
  103. <PreviousPageBlackSvg />
  104. </Pressable>
  105. <Text
  106. style={{
  107. fontSize: 30,
  108. marginTop: 25,
  109. marginBottom: 10
  110. }}
  111. >
  112. 選擇品牌
  113. </Text>
  114. </View>
  115. {loading ? (
  116. <View className="flex h-full items-center justify-center">
  117. <ActivityIndicator />
  118. </View>
  119. ) : (
  120. <View className="flex-1 min-h-[80vh]">
  121. <FlashList
  122. estimatedItemSize={100}
  123. data={processedCarData
  124. .sort((a, b) => a.name.localeCompare(b.name))
  125. .reduce((acc, brand) => {
  126. const letter = brand.name[0].toUpperCase();
  127. const existingSection = acc.find((section) => section.letter === letter);
  128. if (existingSection) {
  129. existingSection.brands.push(brand);
  130. } else {
  131. acc.push({ letter, brands: [brand] });
  132. }
  133. return acc;
  134. }, [] as AlphabetSection[])}
  135. renderItem={renderAlphabetSection}
  136. keyExtractor={(item) => item.letter}
  137. />
  138. </View>
  139. )}
  140. </ScrollView>
  141. </SafeAreaView>
  142. );
  143. };
  144. const styles = StyleSheet.create({
  145. letterHeader: {
  146. backgroundColor: '#E3F2F8',
  147. padding: 10,
  148. marginVertical: 10
  149. },
  150. letterText: {
  151. color: '#02677D',
  152. fontSize: 14,
  153. fontWeight: 'bold'
  154. },
  155. brandRow: {
  156. flexDirection: 'row',
  157. flexWrap: 'wrap'
  158. },
  159. brandItem: {
  160. width: '33.33%',
  161. alignItems: 'center',
  162. padding: 10
  163. },
  164. logo: {
  165. width: 80,
  166. height: 80
  167. },
  168. brandName: {
  169. marginTop: 5,
  170. textAlign: 'center'
  171. }
  172. });
  173. export default SetVehiclesOne;
  174. // interface AlphabetSection {
  175. // letter: string;
  176. // brands: CarBrand[];
  177. // }
  178. // import React, { useEffect, useState } from 'react';
  179. // import { View, Text, Image, Pressable, StyleSheet, ScrollView, ActivityIndicator } from 'react-native';
  180. // import { FlashList } from '@shopify/flash-list';
  181. // import { router } from 'expo-router';
  182. // import useVehicleStore from '../../../../../providers/vehicle_store';
  183. // import { PreviousPageBlackSvg } from '../../../../../component/global/SVG';
  184. // import { SafeAreaView } from 'react-native-safe-area-context';
  185. // import { chargeStationService } from '../../../../../service/chargeStationService';
  186. // const SetVehiclesOne = () => {
  187. // const [loading, setLoading] = useState(true);
  188. // const [carData, setCarData] = useState();
  189. // const [extractedCarNameAndImgUrl, setExtractedCarNameAndImgUrl] = useState('');
  190. // const [processedCarData, setProcessedCarData] = useState([]);
  191. // const {
  192. // vehicleBrand,
  193. // vehicleModel,
  194. // BrandID,
  195. // ModelID,
  196. // licensePlate,
  197. // setVehicleBrand,
  198. // setVehicleModel,
  199. // setBrandID,
  200. // setModelID,
  201. // setLicensePlate
  202. // } = useVehicleStore();
  203. // //this uses getCarBrand to create an array of object with 2 keys: name and img_url
  204. // useEffect(() => {
  205. // const fetchCarBrand = async () => {
  206. // try {
  207. // const response = await chargeStationService.fetchCarBrand();
  208. // if (response) {
  209. // const processedData = await Promise.all(
  210. // response.data.map(async (car) => ({
  211. // ...car,
  212. // logo: await chargeStationService.getProcessedCarImageUrl(car.img_url)
  213. // }))
  214. // );
  215. // setProcessedCarData(processedData);
  216. // }
  217. // } catch (error) {
  218. // console.log(error);
  219. // } finally {
  220. // setLoading(false);
  221. // }
  222. // };
  223. // fetchCarBrand();
  224. // }, []);
  225. // useEffect(() => {
  226. // console.log('Zustand VehicleBrand', vehicleBrand);
  227. // console.log('Zustand BrandID', BrandID);
  228. // console.log('Zustand VehicleModel', vehicleModel);
  229. // console.log('Zustand ModelID', ModelID);
  230. // }, [processedCarData]);
  231. // const renderBrandItem = ({ item: brand }: { item }) => (
  232. // <Pressable
  233. // key={brand.id}
  234. // style={styles.brandItem}
  235. // onPress={() => {
  236. // setVehicleBrand(brand.name);
  237. // setBrandID(brand.id);
  238. // router.push({
  239. // pathname: 'setVehiclesTwo',
  240. // params: {
  241. // brandId: brand.id.toString(),
  242. // brandName: brand.name,
  243. // carTypes: JSON.stringify(brand.car_types)
  244. // }
  245. // });
  246. // }}
  247. // >
  248. // <Image source={{ uri: brand.logo }} style={styles.logo} resizeMode="contain" />
  249. // <Text style={styles.brandName}>{brand.name}</Text>
  250. // </Pressable>
  251. // );
  252. // const renderAlphabetSection = ({ item: section }: { item: AlphabetSection }) => (
  253. // <View>
  254. // <View style={styles.letterHeader} className="h-9">
  255. // <Text style={styles.letterText}>{section.letter}</Text>
  256. // </View>
  257. // <View style={styles.brandRow}>{section.brands.map((brand) => renderBrandItem({ item: brand }))}</View>
  258. // </View>
  259. // );
  260. // return (
  261. // <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
  262. // <ScrollView showsVerticalScrollIndicator={false} className="flex-1 mx-[5%]">
  263. // <View style={{ marginTop: 25 }}>
  264. // <Pressable
  265. // className="self-start"
  266. // onPress={() => {
  267. // if (router.canGoBack()) {
  268. // router.back();
  269. // } else {
  270. // router.replace('/accountMainPage');
  271. // }
  272. // }}
  273. // >
  274. // <PreviousPageBlackSvg />
  275. // </Pressable>
  276. // <Text
  277. // style={{
  278. // fontSize: 30,
  279. // marginTop: 25,
  280. // marginBottom: 10
  281. // }}
  282. // >
  283. // 選擇品牌
  284. // </Text>
  285. // </View>
  286. // {loading ? (
  287. // <View className="flex h-full items-center justify-center">
  288. // <ActivityIndicator />
  289. // </View>
  290. // ) : (
  291. // <View className="flex-1 min-h-[80vh]">
  292. // <FlashList
  293. // estimatedItemSize={100}
  294. // data={processedCarData
  295. // .sort((a, b) => a.name.localeCompare(b.name))
  296. // .reduce((acc, brand) => {
  297. // const letter = brand.name[0].toUpperCase();
  298. // const existingSection = acc.find((section) => section.letter === letter);
  299. // if (existingSection) {
  300. // existingSection.brands.push(brand);
  301. // } else {
  302. // acc.push({ letter, brands: [brand] });
  303. // }
  304. // return acc;
  305. // }, [] as AlphabetSection[])}
  306. // renderItem={renderAlphabetSection}
  307. // keyExtractor={(item) => item.letter}
  308. // />
  309. // </View>
  310. // )}
  311. // {/* <View className="flex-1 min-h-[80vh]">
  312. // <FlashList
  313. // estimatedItemSize={100}
  314. // data={processedCarData.reduce((acc, brand) => {
  315. // const letter = brand.name[0].toUpperCase();
  316. // const existingSection = acc.find((section) => section.letter === letter);
  317. // if (existingSection) {
  318. // existingSection.brands.push(brand);
  319. // } else {
  320. // acc.push({ letter, brands: [brand] });
  321. // }
  322. // return acc;
  323. // }, [] as AlphabetSection[])}
  324. // renderItem={renderAlphabetSection}
  325. // keyExtractor={(item) => item.letter}
  326. // />
  327. // </View> */}
  328. // </ScrollView>
  329. // </SafeAreaView>
  330. // );
  331. // };
  332. // const styles = StyleSheet.create({
  333. // letterHeader: {
  334. // backgroundColor: '#E3F2F8',
  335. // padding: 10,
  336. // marginVertical: 10
  337. // },
  338. // letterText: {
  339. // color: '#02677D',
  340. // fontSize: 14,
  341. // fontWeight: 'bold'
  342. // },
  343. // brandRow: {
  344. // flexDirection: 'row',
  345. // flexWrap: 'wrap'
  346. // },
  347. // brandItem: {
  348. // width: '33.33%',
  349. // alignItems: 'center',
  350. // padding: 10
  351. // },
  352. // logo: {
  353. // width: 80,
  354. // height: 80
  355. // },
  356. // brandName: {
  357. // marginTop: 5,
  358. // textAlign: 'center'
  359. // }
  360. // });
  361. // export default SetVehiclesOne;