searchPageComponent.tsx 13 KB

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