searchPageComponent.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. // data={bookingHistoryData}
  216. data={extractedInfo}
  217. renderItem={({ item }) => (
  218. <View className="flex-column py-2 pt-4 border-b border-gray-300">
  219. <Pressable
  220. // onPress={() => console.log('abc')}
  221. onPress={() => {
  222. router.push({
  223. pathname: '/resultDetailPage',
  224. params: {
  225. chargeStationAddress: item.address,
  226. chargeStationID: item.stationID,
  227. chargeStationName: item.stationName
  228. // chargeStationLng: item.lng,
  229. // chargeStationLat: item.lat
  230. }
  231. });
  232. }}
  233. >
  234. <Text className="text-base text-[#222222]">{item.stationName}</Text>
  235. <Text className="text-sm text-[#888888]">{item.address}</Text>
  236. </Pressable>
  237. </View>
  238. )}
  239. />
  240. </View> */}
  241. </View>
  242. </ScrollView>
  243. </SafeAreaView>
  244. );
  245. };
  246. export default SearchPageComponent;
  247. const styles = StyleSheet.create({
  248. leftArrowBackButton: {
  249. width: '15%',
  250. maxWidth: '100%',
  251. fontSize: 16,
  252. padding: 20,
  253. paddingLeft: 30,
  254. borderBottomLeftRadius: 12,
  255. borderTopLeftRadius: 12,
  256. borderColor: '#bbbbbb',
  257. borderTopWidth: 1,
  258. borderBottomWidth: 1,
  259. borderLeftWidth: 1,
  260. alignItems: 'center',
  261. justifyContent: 'center'
  262. },
  263. textInput: {
  264. // width: '100',
  265. // maxWidth: '100%',
  266. flex: 1,
  267. fontSize: 16,
  268. padding: 20,
  269. paddingLeft: 0,
  270. borderLeftWidth: 0,
  271. borderTopWidth: 1,
  272. borderBottomWidth: 1,
  273. borderRightWidth: 1,
  274. borderBottomRightRadius: 12,
  275. borderTopRightRadius: 12,
  276. borderRadius: 0,
  277. borderColor: '#bbbbbb'
  278. },
  279. dropdown: {
  280. backgroundColor: 'white',
  281. borderWidth: 1,
  282. borderBottomLeftRadius: 12,
  283. borderBottomRightRadius: 12,
  284. borderLeftWidth: 1,
  285. borderRightWidth: 1,
  286. // borderBottomWidth: 1,
  287. marginTop: 10,
  288. maxHeight: 200,
  289. width: '96%',
  290. position: 'absolute',
  291. top: 50,
  292. zIndex: 2,
  293. borderColor: '#bbbbbb'
  294. },
  295. // dropdown: {
  296. // backgroundColor: 'white',
  297. // borderBottomLeftRadius: 12,
  298. // borderBottomRightRadius: 12,
  299. // borderLeftWidth: 1,
  300. // borderRightWidth: 1,
  301. // borderBottomWidth: 1,
  302. // marginTop: 10,
  303. // maxHeight: 200,
  304. // width: '100%',
  305. // position: 'absolute',
  306. // top: 50,
  307. // zIndex: 2,
  308. // borderColor: '#bbbbbb'
  309. // },
  310. dropdownItem: {
  311. padding: 10,
  312. borderBottomColor: '#ddd'
  313. },
  314. dropdownItemPress: {
  315. backgroundColor: '#e8f8fc'
  316. }
  317. });