searchPageComponent.tsx 12 KB

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