Переглянути джерело

add app/pages/search/SearchV3.js

wudebin 5 місяців тому
батько
коміт
ebc5fb7125
1 змінених файлів з 290 додано та 0 видалено
  1. 290 0
      Strides-SPAPP/app/pages/search/SearchV3.js

+ 290 - 0
Strides-SPAPP/app/pages/search/SearchV3.js

@@ -0,0 +1,290 @@
+/**
+ * V3版搜索页
+ * @邠心vbe on 2024/05/11
+ */
+import React, { Component } from 'react';
+import { View, Text, StyleSheet, TextInput, FlatList, Image } from 'react-native';
+import apiStation from '../../api/apiStation';
+import Dialog from '../../components/Dialog';
+import utils from '../../utils/utils';
+import { PageList } from '../Router';
+import ListViewV3 from './ListViewV3';
+
+export default class SearchV3 extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      isSearch: false,
+      searchResult: [{id:0}],
+      searchWorld: "",
+      latlng: {
+        lat: 0.00001,
+        lng: 0.00001
+      }
+    };
+  }
+
+  componentDidMount() {
+    this.getGeoLocation();
+  }
+
+  changeWord(word) {
+    this.setState({
+      searchWorld: word
+    });
+  }
+
+  getGeoLocation() {
+    navigator.geolocation.getCurrentPosition(location => {
+      let latlng = {
+        lat: location.coords.latitude,
+        lng: location.coords.longitude
+      }
+      this.setState({
+        latlng: latlng
+      })
+      this.searchStation(latlng);
+    }, error => {
+      console.info("[Search] getGeoLocation", error);
+      this.searchStation(this.state.latlng);
+    });
+  }
+
+  searchStation(latlng, time=100) {
+    this.setState({
+      isSearch: true
+    });
+    latlng.siteName = this.state.searchWorld
+    apiStation.searchStation(latlng).then(res => {
+      if (res.data.sites) {
+        const list = [];
+        res.data.sites.forEach(item => {
+          list.push({
+            id: item.sitePk,
+            name: item.siteName,
+            address: item.siteAddress,
+            latitude: item.locationLatitude,
+            longitude: item.locationLongitude,
+            acConnector: item.acConnector,
+            allConnector: item.allConnector,
+            dcConnector: item.dcConnector,
+            siteType: item.siteType,
+            favorite: item.favorite,
+            upcoming: item.upcoming,
+            labels: item.siteLabels,
+            distance: utils.getDistance(item.distance),
+            serviceProvider: item.serviceProvider
+          });
+        });
+        setTimeout(() => {
+          this.setState({
+            isSearch: false,
+            searchResult: list
+          });
+        }, time);
+      }
+    }).catch(err => {
+      console.log('searchStation-err', err);
+      this.setState({
+        isSearch: false,
+        searchResult: []
+      });
+    });
+  }
+
+  favoriteSite(index, info) {
+    if (info?.id) {
+      Dialog.showProgressDialog();
+      apiStation.bookmarkSite(info.id).then(res => {
+        if (index >= 0) {
+          const list = [...this.state.searchResult];
+          list[index].favorite = !info.favorite;
+          this.setState({
+            searchResult: list
+          });
+        }
+      }).catch(err => {
+        toastShort(err);
+      }).finally(() => {
+        Dialog.dismissLoading();
+      })
+    }
+  }
+
+  intoStation(info) {
+    if (info.upcoming) {
+      toastShort($t("home.upcoming"))
+    } else {
+      utils.toChargeDetailPage(info.id, 'search', PageList.search);
+      //startPage(PageList.chargeDetailPage, {stationInfo: info, action: 'search', from: PageList.search});
+    }
+  }
+
+  listItem = (props) => {
+    return (
+      <ListViewV3 
+        {...props}
+        onPress={() => this.intoStation(props.item)}
+        onFavorite={() => this.favoriteSite(props.index, props.item)}/>
+    )
+  }
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <View style={styles.searchView}>
+          <Feather
+            name={'search'}
+            size={20}
+            color={textSecondary}/>
+          <TextInput
+            style={styles.searchInput}
+            autoFocus={true}
+            maxLength={50}
+            numberOfLines={1}
+            returnKeyType={'search'}
+            clearButtonMode={'while-editing'}
+            placeholder={"Search by Postal Code, Address, Site Name"}
+            placeholderTextColor={textPlacehoder}
+            value={this.state.searchWorld}
+            onChangeText={text => this.changeWord(text)}
+            onSubmitEditing={() => {
+              //this.getGeoLocation();
+              this.searchStation(this.state.latlng, 300);
+            }}/>
+          { utils.isNotEmpty(this.state.searchWorld) &&
+            <MaterialCommunityIcons
+              name="close-circle"
+              size={20}
+              color={textCancel}
+              onPress={() => this.changeWord("")}/>
+          }
+        </View>
+        { this.state.isSearch
+        ? <View style={styles.searchingView}>
+            <Image
+              style={styles.seachingIcon}
+              source={require('../../images/icon/search-loading.gif')}/>
+          </View>
+        : <FlatList
+            style={styles.listView}
+            data={this.state.searchResult}
+            renderItem={this.listItem}
+            keyExtractor={item => item.id}
+            keyboardShouldPersistTaps="always"
+            ListEmptyComponent={<Text style={styles.noResult}>{$t('home.noSearch')}</Text>}
+          />
+        }
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    backgroundColor: pageBackground
+  },
+  searchView: {
+    margin: 16,
+    ...$padding(2, 16),
+    borderRadius: 60,
+    borderWidth: 1,
+    borderColor: '#E5E5E5',
+    alignItems: 'center',
+    flexDirection: 'row',
+    backgroundColor: '#F5F5F5'
+  },
+  searchInput: {
+    flex: 1,
+    color: textPrimary,
+    ...$padding(6, 8),
+    fontSize: 15,
+    marginLeft: 4,
+    lineHeight: 20
+  },
+  searchingView: {
+    padding: 16,
+    alignItems: 'center'
+  },
+  seachingIcon: {
+    width: 60,
+    height: 60
+  },
+  noResult: {
+    color: '#999',
+    fontSize: 14,
+    padding: 20,
+    textAlign: 'center',
+  },
+  listView: {
+    flex: 1
+  },
+  itemView: {
+    alignItems: 'center',
+    flexDirection: 'row',
+    borderBottomWidth: 1,
+    borderBottomColor: '#eee'
+  },
+  stationInfo: {
+    flex: 1,
+    padding: 16
+  },
+  nameView: {
+    paddingTop: 3,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  stationName: {
+    color: textPrimary,
+    fontSize: 18,
+    fontWeight: 'bold'
+  },
+  stationAddress: {
+    color: '#666',
+    fontSize: 14,
+    paddingBottom: 8
+  },
+  infoStatus: {
+    fontSize: 10,
+    paddingTop: 3,
+    paddingLeft: 8,
+    paddingRight: 8,
+    paddingBottom: 3,
+    borderRadius: 5,
+    marginLeft: 12,
+  },
+  selected: {
+    color: textPrimary,
+    backgroundColor: colorAccent
+  },
+  available: {
+    color: textLight,
+    backgroundColor: '#90DB0A'
+  },
+  unavailable: {
+    color: '#999',
+    fontSize: 10.5,
+    paddingTop: 7,
+    paddingLeft: 9,
+    paddingRight: 9,
+    paddingBottom: 7,
+    backgroundColor: '#CCC'
+  },
+  connectView: {
+    paddingTop: 4,
+    paddingBottom: 4,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  directView: {
+    zIndex: 1,
+    paddingRight: 16,
+    alignItems: 'center'
+  },
+  distanceText: {
+    color: textPrimary,
+    fontSize: 12,
+    paddingTop: 2
+  }
+});