searchPageComponent.tsx 13 KB

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