searchPageComponent.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. import { ScrollView, Text, View, StyleSheet, Pressable, ImageSourcePropType } from 'react-native';
  2. import NormalInput from '../global/normal_input';
  3. import NormalButton from '../global/normal_button';
  4. import { FlashList } from '@shopify/flash-list';
  5. import { ArrowIconSvg } from '../global/SVG';
  6. import { SafeAreaView } from 'react-native-safe-area-context';
  7. import { useEffect, useRef, useState } from 'react';
  8. import { router } from 'expo-router';
  9. import extractedInfoStore from '../../providers/extractedReservationInfo_store';
  10. interface BookingHistory {
  11. charingStationName: string;
  12. chargingStationAddress: string;
  13. }
  14. interface SearchPageComponentProps {}
  15. interface TabItem {
  16. imgURL: ImageSourcePropType;
  17. date: string;
  18. time: string;
  19. chargeStationName: string;
  20. chargeStationAddress: string;
  21. distance: string;
  22. latitude: number;
  23. longitude: number;
  24. }
  25. const dummyTabItems: TabItem[] = [
  26. {
  27. imgURL: require('../../assets/dummyStationPicture.png'),
  28. date: '今天',
  29. time: '16:30',
  30. chargeStationName: '觀塘偉業街充電站',
  31. chargeStationAddress: '九龍觀塘偉業街143號地下',
  32. distance: '400米',
  33. latitude: 22.310958,
  34. longitude: 114.226065
  35. },
  36. {
  37. imgURL: require('../../assets/dummyStationPicture2.png'),
  38. date: '3月15',
  39. time: '17:45',
  40. chargeStationName: '中環IFC充電站',
  41. chargeStationAddress: '香港中環皇后大道中999號',
  42. distance: '680米',
  43. latitude: 22.28552,
  44. longitude: 114.15769
  45. }
  46. ];
  47. const SearchPageComponent: React.FC<SearchPageComponentProps> = () => {
  48. const inputRef = useRef(null);
  49. const extractedInfo = extractedInfoStore((state) => state.extractedInfo);
  50. console.log('extracted: ', extractedInfo);
  51. const [searchInput, setSearchInput] = useState<string>('');
  52. const [filteredItems, setFilteredItems] = useState<TabItem[]>([]);
  53. useEffect(() => {
  54. if (inputRef.current) {
  55. inputRef.current.focus();
  56. }
  57. }, []);
  58. useEffect(() => {
  59. if (searchInput === '') {
  60. setFilteredItems([]);
  61. } else {
  62. const filteredData = dummyTabItems.filter((item) =>
  63. item.chargeStationName.includes(searchInput.toLocaleUpperCase())
  64. );
  65. setFilteredItems(filteredData);
  66. }
  67. }, [searchInput]);
  68. return (
  69. <SafeAreaView edges={['top', 'right', 'left']} className="flex-1 bg-white">
  70. <ScrollView className=" flex-1 mx-[5%] pt-6 " showsVerticalScrollIndicator={false}>
  71. <View className="flex-column gap-4 ">
  72. <View className=" flex-1 flex-row ">
  73. <Pressable
  74. style={styles.leftArrowBackButton}
  75. onPress={() => {
  76. if (router.canGoBack()) {
  77. router.back();
  78. } else {
  79. router.replace('/(auth)/(tabs)/(home)');
  80. }
  81. }}
  82. >
  83. <ArrowIconSvg />
  84. </Pressable>
  85. <NormalInput
  86. placeholder="搜尋這裡"
  87. onChangeText={(text) => {
  88. setSearchInput(text);
  89. console.log(text);
  90. }}
  91. extendedStyle={styles.textInput}
  92. ref={inputRef}
  93. />
  94. </View>
  95. {filteredItems.length > 0 && (
  96. <View style={styles.dropdown}>
  97. <View>
  98. {filteredItems.map((item, index) => (
  99. <Pressable
  100. key={index}
  101. onPress={() => {
  102. setSearchInput(item.chargeStationName);
  103. setFilteredItems([]);
  104. router.push({
  105. pathname: '/searchResultPage',
  106. params: {
  107. latitude: item.latitude,
  108. longitude: item.longitude,
  109. chargeStationName: item.chargeStationName
  110. }
  111. });
  112. }}
  113. style={({ pressed }) => [
  114. styles.dropdownItem,
  115. pressed && styles.dropdownItemPress
  116. ]}
  117. >
  118. <Text>{item.chargeStationName}</Text>
  119. </Pressable>
  120. ))}
  121. </View>
  122. </View>
  123. )}
  124. <ScrollView horizontal={true} className="space-x-4" showsHorizontalScrollIndicator={false}>
  125. <View>
  126. <NormalButton
  127. title={<Text style={{ color: '#061E25' }}>瀏覽地圖查看現有充電站</Text>}
  128. // onPress={() => console.log('附近的充電站')}
  129. onPress={() => router.push('/(auth)/(tabs)/(home)/(booking)/searchResultPage')}
  130. buttonPressedStyle={{
  131. backgroundColor: '#CFDEE4'
  132. }}
  133. extendedStyle={{
  134. backgroundColor: '#E3F2F8',
  135. borderRadius: 8,
  136. paddingVertical: 12
  137. }}
  138. />
  139. </View>
  140. {/* <View>
  141. <NormalButton
  142. title={
  143. <Text style={{ color: '#061E25' }}>
  144. 可Walk-in的充電站
  145. </Text>
  146. }
  147. onPress={() => console.log('可Walk-in的充電站')}
  148. buttonPressedStyle={{
  149. backgroundColor: '#CFDEE4'
  150. }}
  151. extendedStyle={{
  152. backgroundColor: '#E3F2F8',
  153. borderRadius: 8,
  154. paddingVertical: 12
  155. }}
  156. />
  157. </View>
  158. <View>
  159. <NormalButton
  160. title={
  161. <Text style={{ color: '#061E25' }}>
  162. Test Tab #1
  163. </Text>
  164. }
  165. onPress={() => console.log('Test Tab #1')}
  166. buttonPressedStyle={{
  167. backgroundColor: '#CFDEE4'
  168. }}
  169. extendedStyle={{
  170. backgroundColor: '#E3F2F8',
  171. borderRadius: 8,
  172. paddingVertical: 12
  173. }}
  174. />
  175. </View>
  176. <View>
  177. <NormalButton
  178. title={
  179. <Text style={{ color: '#061E25' }}>
  180. Test Tab #2
  181. </Text>
  182. }
  183. onPress={() => console.log('Test Tab #2')}
  184. buttonPressedStyle={{
  185. backgroundColor: '#CFDEE4'
  186. }}
  187. extendedStyle={{
  188. backgroundColor: '#E3F2F8',
  189. borderRadius: 8,
  190. paddingVertical: 12
  191. }}
  192. />
  193. </View> */}
  194. </ScrollView>
  195. <View className="h-[1000px]">
  196. <Text
  197. style={{
  198. fontWeight: 400,
  199. fontSize: 16,
  200. color: '#222222',
  201. paddingTop: 6
  202. }}
  203. >
  204. 預約記錄
  205. </Text>
  206. <FlashList
  207. estimatedItemSize={10}
  208. // data={bookingHistoryData}
  209. data={extractedInfo}
  210. renderItem={({ item }) => (
  211. <View className="flex-column py-2 pt-4 border-b border-gray-300">
  212. <Pressable
  213. // onPress={() => console.log('abc')}
  214. onPress={() => {
  215. router.push({
  216. pathname: '/resultDetailPage',
  217. params: {
  218. chargeStationAddress: item.address,
  219. chargeStationID: item.stationID,
  220. chargeStationName: item.stationName
  221. // chargeStationLng: item.lng,
  222. // chargeStationLat: item.lat
  223. }
  224. });
  225. }}
  226. >
  227. <Text className="text-base text-[#222222]">{item.stationName}</Text>
  228. <Text className="text-sm text-[#888888]">{item.address}</Text>
  229. </Pressable>
  230. </View>
  231. )}
  232. />
  233. </View>
  234. </View>
  235. </ScrollView>
  236. </SafeAreaView>
  237. );
  238. };
  239. export default SearchPageComponent;
  240. const styles = StyleSheet.create({
  241. leftArrowBackButton: {
  242. width: '15%',
  243. maxWidth: '100%',
  244. fontSize: 16,
  245. padding: 20,
  246. paddingLeft: 30,
  247. borderBottomLeftRadius: 12,
  248. borderTopLeftRadius: 12,
  249. borderColor: '#bbbbbb',
  250. borderTopWidth: 1,
  251. borderBottomWidth: 1,
  252. borderLeftWidth: 1,
  253. alignItems: 'center',
  254. justifyContent: 'center'
  255. },
  256. textInput: {
  257. // width: '100',
  258. // maxWidth: '100%',
  259. flex: 1,
  260. fontSize: 16,
  261. padding: 20,
  262. paddingLeft: 0,
  263. borderLeftWidth: 0,
  264. borderTopWidth: 1,
  265. borderBottomWidth: 1,
  266. borderRightWidth: 1,
  267. borderBottomRightRadius: 12,
  268. borderTopRightRadius: 12,
  269. borderRadius: 0,
  270. borderColor: '#bbbbbb'
  271. },
  272. dropdown: {
  273. backgroundColor: 'white',
  274. borderWidth: 1,
  275. borderBottomLeftRadius: 12,
  276. borderBottomRightRadius: 12,
  277. borderLeftWidth: 1,
  278. borderRightWidth: 1,
  279. // borderBottomWidth: 1,
  280. marginTop: 10,
  281. maxHeight: 200,
  282. width: '96%',
  283. position: 'absolute',
  284. top: 50,
  285. zIndex: 2,
  286. borderColor: '#bbbbbb'
  287. },
  288. // dropdown: {
  289. // backgroundColor: 'white',
  290. // borderBottomLeftRadius: 12,
  291. // borderBottomRightRadius: 12,
  292. // borderLeftWidth: 1,
  293. // borderRightWidth: 1,
  294. // borderBottomWidth: 1,
  295. // marginTop: 10,
  296. // maxHeight: 200,
  297. // width: '100%',
  298. // position: 'absolute',
  299. // top: 50,
  300. // zIndex: 2,
  301. // borderColor: '#bbbbbb'
  302. // },
  303. dropdownItem: {
  304. padding: 10,
  305. borderBottomColor: '#ddd'
  306. },
  307. dropdownItemPress: {
  308. backgroundColor: '#e8f8fc'
  309. }
  310. });