|
@@ -0,0 +1,402 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * 地图底部充电站信息组件
|
|
|
|
|
+ * @邠心vbe on 2022/12/23
|
|
|
|
|
+ */
|
|
|
|
|
+import React, { useEffect, useState } from 'react';
|
|
|
|
|
+import { Pressable, StyleSheet, View, Text } from 'react-native';
|
|
|
|
|
+import { ElevationObject } from '../../../components/Button';
|
|
|
|
|
+import utils from '../../../utils/utils';
|
|
|
|
|
+import { ChargeStyle } from '../../charge/Charging';
|
|
|
|
|
+import { PageList } from '../../Router';
|
|
|
|
|
+import ConnectType, { ConnectTypeV2 } from '../../search/ConnectType';
|
|
|
|
|
+import app from '../../../../app.json';
|
|
|
|
|
+import TextView from '../../../components/TextView';
|
|
|
|
|
+import BottomModal from '../../../components/BottomModal';
|
|
|
|
|
+import SiteLabelView from '../../../components/SiteLabelView';
|
|
|
|
|
+import VbeSkeleton from '../../../components/VbeSkeleton';
|
|
|
|
|
+
|
|
|
|
|
+export const BottomSiteCard = ({
|
|
|
|
|
+ visible=false,
|
|
|
|
|
+ stationInfo = {},
|
|
|
|
|
+ onFavorite,
|
|
|
|
|
+ onClose
|
|
|
|
|
+}) => {
|
|
|
|
|
+ const [loading, showDialog] = useState(true);
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ if (stationInfo.id) {
|
|
|
|
|
+ showDialog(false)
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [stationInfo]);
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ showDialog(true);
|
|
|
|
|
+ }, [visible]);
|
|
|
|
|
+
|
|
|
|
|
+ const getAvailable = (type) => {
|
|
|
|
|
+ const all = stationInfo.allConnector;
|
|
|
|
|
+ if (all) {
|
|
|
|
|
+ if (type == 'box') {
|
|
|
|
|
+ return all.boxAvailable + '/' + all.boxAll;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return all.available + '/' + all.all;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return '0/0';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const getOperatingHours = () => {
|
|
|
|
|
+ if (stationInfo.endlessService) {
|
|
|
|
|
+ return "24/7";
|
|
|
|
|
+ } else if (stationInfo.operatingHours) {
|
|
|
|
|
+ return stationInfo.operatingHours;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return $t('charging.toBeUpdated');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const getParkingFee = () => {
|
|
|
|
|
+ if (stationInfo.parkingFeeFree) {
|
|
|
|
|
+ return $t('charging.free');
|
|
|
|
|
+ } else if (stationInfo.parkingFee) {
|
|
|
|
|
+ return stationInfo.parkingFee;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return $t('charging.toBeUpdated');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const toChargePage = () => {
|
|
|
|
|
+ onClose();
|
|
|
|
|
+ if (stationInfo.upcoming) {
|
|
|
|
|
+ toastShort($t("home.upcoming"))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ utils.toChargeDetailPage(stationInfo.id, 'view', PageList.home);
|
|
|
|
|
+ //startPage(PageList.chargeDetailPage, {stationInfo: stationInfo, action: 'view', from: PageList.home});
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <BottomModal
|
|
|
|
|
+ visible={visible}
|
|
|
|
|
+ onHide={() => {
|
|
|
|
|
+ onClose()
|
|
|
|
|
+ }}
|
|
|
|
|
+ backdropOpacity={0}
|
|
|
|
|
+ contentStyle={styles.bottomModal}>
|
|
|
|
|
+ { loading
|
|
|
|
|
+ ? <View style={styles.stationBarView}>
|
|
|
|
|
+ <View style={ui.flex}>
|
|
|
|
|
+ <VbeSkeleton
|
|
|
|
|
+ style={ui.flex1}
|
|
|
|
|
+ layout={[
|
|
|
|
|
+ {width: '80%', height: 20},
|
|
|
|
|
+ {width: '100%', height: 15, marginTop: 16},
|
|
|
|
|
+ {width: '60%', height: 15, marginTop: 4}
|
|
|
|
|
+ ]}
|
|
|
|
|
+ animationDirection={"horizontalRight"}
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <EndView/>
|
|
|
|
|
+ <View style={ui.flex}>
|
|
|
|
|
+ <VbeSkeleton
|
|
|
|
|
+ style={[ui.flexc, ui.flex1]}
|
|
|
|
|
+ viewStyle={ui.flex1}
|
|
|
|
|
+ layout={[
|
|
|
|
|
+ {width: '16%', height: 15, marginRight: 8, borderRadius: 30},
|
|
|
|
|
+ {width: '16%', height: 15, marginRight: 8, borderRadius: 30},
|
|
|
|
|
+ {width: '16%', height: 15, marginRight: 8, borderRadius: 30},
|
|
|
|
|
+ {width: '16%', height: 15, borderRadius: 30}
|
|
|
|
|
+ ]}
|
|
|
|
|
+ animationDirection={"horizontalRight"}
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <EndView/>
|
|
|
|
|
+ <View style={ui.flex}>
|
|
|
|
|
+ <VbeSkeleton
|
|
|
|
|
+ style={[ui.flexc, ui.flex1]}
|
|
|
|
|
+ viewStyle={ui.flex1}
|
|
|
|
|
+ layout={[
|
|
|
|
|
+ {width: '20%', height: 25, marginRight: 12, borderRadius: 30},
|
|
|
|
|
+ {width: '20%', height: 25, marginRight: 12, borderRadius: 30},
|
|
|
|
|
+ {width: '20%', height: 25, marginRight: 12, borderRadius: 30}
|
|
|
|
|
+ ]}
|
|
|
|
|
+ animationDirection={"horizontalRight"}
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ : <View style={styles.stationBarView}>
|
|
|
|
|
+ <View style={ui.flexc}>
|
|
|
|
|
+ <TextView
|
|
|
|
|
+ ellipsizeMode='tail'
|
|
|
|
|
+ numberOfLines={1}
|
|
|
|
|
+ style={styles.stationTitle}>{stationInfo.name}</TextView>
|
|
|
|
|
+ <Pressable
|
|
|
|
|
+ style={styles.closeIcon}
|
|
|
|
|
+ android_ripple={rippleLess}
|
|
|
|
|
+ onPress={onClose}>
|
|
|
|
|
+ <MaterialCommunityIcons
|
|
|
|
|
+ name="close"
|
|
|
|
|
+ size={22}
|
|
|
|
|
+ color={textSecondary}/>
|
|
|
|
|
+ </Pressable>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <TextView
|
|
|
|
|
+ style={styles.stationAddress}
|
|
|
|
|
+ ellipsizeMode='tail'
|
|
|
|
|
+ numberOfLines={3}>{stationInfo.address}</TextView>
|
|
|
|
|
+ <View style={ui.flexc}>
|
|
|
|
|
+ <TextView style={styles.siteTypes}>{stationInfo.siteType}</TextView>
|
|
|
|
|
+ { (stationInfo.allConnector && stationInfo.allConnector.available > 0) &&
|
|
|
|
|
+ <TextView style={styles.stationAvailable}>
|
|
|
|
|
+ <MaterialCommunityIcons
|
|
|
|
|
+ name="circle"
|
|
|
|
|
+ size={10}
|
|
|
|
|
+ color={colorAccent}/>
|
|
|
|
|
+ <Text> </Text>
|
|
|
|
|
+ {$t("charging.statusAvailable")}
|
|
|
|
|
+ </TextView>
|
|
|
|
|
+ }
|
|
|
|
|
+ <ConnectTypeV2 {...stationInfo?.acConnector}/>
|
|
|
|
|
+ <ConnectTypeV2 {...stationInfo?.dcConnector}/>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={styles.infoDetailsView}>
|
|
|
|
|
+ <View style={ui.flex1}>
|
|
|
|
|
+ <TextView style={styles.infoTitle}>{$t("charging.operatingHours")}</TextView>
|
|
|
|
|
+ <View style={styles.infoView}>
|
|
|
|
|
+ <TextView style={styles.infoText}>{getOperatingHours()}</TextView>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={{width: 4}}></View>
|
|
|
|
|
+ <View style={ui.flex1}>
|
|
|
|
|
+ <TextView style={styles.infoTitle}>{$t("charging.parkingFees")}</TextView>
|
|
|
|
|
+ <View style={styles.infoView}>
|
|
|
|
|
+ <TextView style={styles.infoText}>{getParkingFee()}</TextView>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={{width: 4}}></View>
|
|
|
|
|
+ <View style={ui.flex1}>
|
|
|
|
|
+ <TextView style={styles.infoTitle}>{$t("charging.additionalInfo")}</TextView>
|
|
|
|
|
+ <View style={styles.infoView}>
|
|
|
|
|
+ <TextView style={styles.infoText}>{stationInfo?.additionalNotes}</TextView>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <EndView half/>
|
|
|
|
|
+ <View style={ui.flexc}>
|
|
|
|
|
+ { stationInfo.upcoming
|
|
|
|
|
+ ? <View style={[ui.center, $margin(0, 8)]}>
|
|
|
|
|
+ <MaterialIcons
|
|
|
|
|
+ name="upcoming"
|
|
|
|
|
+ size={42}
|
|
|
|
|
+ color={colorAccent}
|
|
|
|
|
+ style={styles.upcomingIcon} />
|
|
|
|
|
+ <TextView style={styles.upcomingText}>{$t("home.upcoming")}</TextView>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ : <>
|
|
|
|
|
+ <Pressable
|
|
|
|
|
+ style={styles.directIconView}
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ utils.directMaps(stationInfo.latitude, stationInfo.longitude, stationInfo.address);
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <MaterialCommunityIcons
|
|
|
|
|
+ name="directions"
|
|
|
|
|
+ size={20}
|
|
|
|
|
+ color={textPrimary}/>
|
|
|
|
|
+ <TextView style={styles.directText}>Directions</TextView>
|
|
|
|
|
+ </Pressable>
|
|
|
|
|
+ { app.modules.bookmarks &&
|
|
|
|
|
+ <Pressable
|
|
|
|
|
+ style={[styles.directIconView, stationInfo.favorite ? styles.bookmarked : {}]}
|
|
|
|
|
+ onPress={onFavorite}>
|
|
|
|
|
+ <MaterialIcons
|
|
|
|
|
+ name="star"
|
|
|
|
|
+ size={20}
|
|
|
|
|
+ color={stationInfo.favorite ? textLight : textPrimary}/>
|
|
|
|
|
+ <TextView style={[styles.directText, stationInfo.favorite ? styles.bookmarked : {}]}>
|
|
|
|
|
+ {stationInfo.favorite ? "Saved" : "Save"}
|
|
|
|
|
+ </TextView>
|
|
|
|
|
+ </Pressable>
|
|
|
|
|
+ }
|
|
|
|
|
+ {/* <Pressable
|
|
|
|
|
+ style={styles.directIconView}
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ startPage(PageList.scanqr, {actionDetail: true});
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <MaterialCommunityIcons
|
|
|
|
|
+ name="qrcode-scan"
|
|
|
|
|
+ size={12}
|
|
|
|
|
+ color={textPrimary}
|
|
|
|
|
+ style={$padding(3)}/>
|
|
|
|
|
+ <TextView style={styles.directText}>Scan</TextView>
|
|
|
|
|
+ </Pressable> */}
|
|
|
|
|
+ <Pressable
|
|
|
|
|
+ style={styles.directIconView}
|
|
|
|
|
+ onPress={() => toChargePage()}>
|
|
|
|
|
+ <MaterialCommunityIcons
|
|
|
|
|
+ name="information-variant"
|
|
|
|
|
+ size={20}
|
|
|
|
|
+ color={textPrimary}/>
|
|
|
|
|
+ <TextView style={styles.directText}>More Info</TextView>
|
|
|
|
|
+ </Pressable>
|
|
|
|
|
+ </> }
|
|
|
|
|
+ </View>
|
|
|
|
|
+ {/* stationInfo?.labels?.length > 0 &&
|
|
|
|
|
+ <View style={styles.siteLabelsView}>
|
|
|
|
|
+ <Image
|
|
|
|
|
+ style={styles.labelIcon}
|
|
|
|
|
+ source={require('../../../images/maps/ic_marker_additional.png')}/>
|
|
|
|
|
+ { stationInfo.labels.map((item, index) =>
|
|
|
|
|
+ <SiteLabelView key={index} {...item}/>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ */}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ }
|
|
|
|
|
+ </BottomModal>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const styles = StyleSheet.create({
|
|
|
|
|
+ bottomModal: {
|
|
|
|
|
+ backgroundColor: pageBackground
|
|
|
|
|
+ },
|
|
|
|
|
+ stationBarView: {
|
|
|
|
|
+ padding: 16
|
|
|
|
|
+ },
|
|
|
|
|
+ stationBarPresed: {
|
|
|
|
|
+ backgroundColor: "#F6F6F6",
|
|
|
|
|
+ ...ElevationObject(5)
|
|
|
|
|
+ },
|
|
|
|
|
+ stationInfo: {
|
|
|
|
|
+ flex: 1,
|
|
|
|
|
+ height: 45,
|
|
|
|
|
+ paddingLeft: 4,
|
|
|
|
|
+ paddingRight: 8,
|
|
|
|
|
+ justifyContent: 'space-around'
|
|
|
|
|
+ },
|
|
|
|
|
+ stationTitle: {
|
|
|
|
|
+ flex: 1,
|
|
|
|
|
+ color: textPrimary,
|
|
|
|
|
+ fontSize: 24,
|
|
|
|
|
+ fontWeight: 'bold',
|
|
|
|
|
+ paddingBottom: 4
|
|
|
|
|
+ },
|
|
|
|
|
+ stationAddress: {
|
|
|
|
|
+ color: textSecondary,
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ paddingTop: 6,
|
|
|
|
|
+ paddingBottom: 8
|
|
|
|
|
+ },
|
|
|
|
|
+ siteTypes: {
|
|
|
|
|
+ color: textLight,
|
|
|
|
|
+ height: 20,
|
|
|
|
|
+ fontSize: 12,
|
|
|
|
|
+ marginRight: 6,
|
|
|
|
|
+ borderRadius: 30,
|
|
|
|
|
+ ...$padding(0, 10),
|
|
|
|
|
+ backgroundColor: textPrimary
|
|
|
|
|
+ },
|
|
|
|
|
+ stationAvailable: {
|
|
|
|
|
+ color: textPrimary,
|
|
|
|
|
+ height: 20,
|
|
|
|
|
+ fontSize: 12,
|
|
|
|
|
+ marginRight: 6,
|
|
|
|
|
+ borderRadius: 30,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderColor: colorAccent,
|
|
|
|
|
+ ...$padding(0, 8, 0, 4)
|
|
|
|
|
+ },
|
|
|
|
|
+ directView: {
|
|
|
|
|
+ zIndex: 1,
|
|
|
|
|
+ height: 45,
|
|
|
|
|
+ marginLeft: 8,
|
|
|
|
|
+ marginRight: 4,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'space-between'
|
|
|
|
|
+ },
|
|
|
|
|
+ distanceText: {
|
|
|
|
|
+ color: textPrimary,
|
|
|
|
|
+ fontSize: 12,
|
|
|
|
|
+ },
|
|
|
|
|
+ directIconView: {
|
|
|
|
|
+ zIndex: 1,
|
|
|
|
|
+ height: 32,
|
|
|
|
|
+ marginRight: 10,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderRadius: 30,
|
|
|
|
|
+ borderColor: textPrimary,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ ...$padding(2, 10, 2, 6)
|
|
|
|
|
+ },
|
|
|
|
|
+ bookmarked: {
|
|
|
|
|
+ color: textLight,
|
|
|
|
|
+ borderColor: colorAccent,
|
|
|
|
|
+ backgroundColor: colorAccent
|
|
|
|
|
+ },
|
|
|
|
|
+ directText: {
|
|
|
|
|
+ color: textPrimary,
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ paddingLeft: 4
|
|
|
|
|
+ },
|
|
|
|
|
+ connectView: {
|
|
|
|
|
+ flex: 1,
|
|
|
|
|
+ paddingTop: 12,
|
|
|
|
|
+ paddingBottom: 12,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ flexDirection: 'row'
|
|
|
|
|
+ },
|
|
|
|
|
+ divideLine: {
|
|
|
|
|
+ height: 1,
|
|
|
|
|
+ backgroundColor: '#AEAEAE'
|
|
|
|
|
+ },
|
|
|
|
|
+ infoDetailsView: {
|
|
|
|
|
+ paddingTop: 8,
|
|
|
|
|
+ flexDirection: 'row'
|
|
|
|
|
+ },
|
|
|
|
|
+ infoTitle: {
|
|
|
|
|
+ color: textPrimary,
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ //fontWeight: 'bold',
|
|
|
|
|
+ ...$padding(8, 0, 8)
|
|
|
|
|
+ },
|
|
|
|
|
+ infoView: {
|
|
|
|
|
+ paddingBottom: 8
|
|
|
|
|
+ },
|
|
|
|
|
+ infoText: {
|
|
|
|
|
+ color: textCancel,
|
|
|
|
|
+ fontSize: 12
|
|
|
|
|
+ },
|
|
|
|
|
+ closeIcon: {
|
|
|
|
|
+ width: 30,
|
|
|
|
|
+ height: 30,
|
|
|
|
|
+ marginTop: -16,
|
|
|
|
|
+ marginRight: -8,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ siteLabelsView: {
|
|
|
|
|
+ marginBottom: 5,
|
|
|
|
|
+ flexWrap: 'wrap',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ flexDirection: 'row'
|
|
|
|
|
+ },
|
|
|
|
|
+ labelIcon: {
|
|
|
|
|
+ width: 16,
|
|
|
|
|
+ height: 16,
|
|
|
|
|
+ marginRight: 6
|
|
|
|
|
+ },
|
|
|
|
|
+ upcomingIcon: {
|
|
|
|
|
+ marginLeft: 8,
|
|
|
|
|
+ opacity: .3
|
|
|
|
|
+ },
|
|
|
|
|
+ upcomingText: {
|
|
|
|
|
+ color: colorAccent,
|
|
|
|
|
+ fontSize: 10,
|
|
|
|
|
+ opacity: .3,
|
|
|
|
|
+ marginLeft: 8,
|
|
|
|
|
+ marginTop: -3
|
|
|
|
|
+ }
|
|
|
|
|
+})
|