BottomSiteInfo.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /**
  2. * 地图底部充电站信息组件
  3. * @邠心vbe on 2022/12/23
  4. */
  5. import React from 'react';
  6. import { Pressable, StyleSheet, View, Text, Image } from 'react-native';
  7. import { ElevationObject } from '../../../components/Button';
  8. import utils from '../../../utils/utils';
  9. import { ChargeStyle } from '../../charge/Charging';
  10. import { PageList } from '../../Router';
  11. import ConnectType from '../../search/ConnectType';
  12. import app from '../../../../app.json';
  13. import TextView from '../../../components/TextView';
  14. export default BottomSiteInfo = ({
  15. stationInfo = {},
  16. onFavorite,
  17. onClose,
  18. style=styles.stationBarView
  19. }) => {
  20. const getAvailable = (type) => {
  21. const all = stationInfo.allConnector;
  22. if (all) {
  23. if (type == 'box') {
  24. return all.boxAvailable + '/' + all.boxAll;
  25. } else {
  26. return all.available + '/' + all.all;
  27. }
  28. } else {
  29. return '0/0';
  30. }
  31. }
  32. const getOperatingHours = () => {
  33. if (stationInfo.endlessService) {
  34. return "24/7";
  35. } else if (stationInfo.operatingHours) {
  36. return stationInfo.operatingHours;
  37. } else {
  38. return $t('charging.toBeUpdated');
  39. }
  40. }
  41. const getParkingFee = () => {
  42. if (stationInfo.parkingFeeFree) {
  43. return $t('charging.free');
  44. } else if (stationInfo.parkingFee) {
  45. return stationInfo.parkingFee;
  46. } else {
  47. return $t('charging.toBeUpdated');
  48. }
  49. }
  50. const toChargePage = () => {
  51. if (stationInfo.upcoming) {
  52. toastShort($t("home.upcoming"))
  53. } else {
  54. startPage(PageList.chargeDetailPage, {stationInfo: stationInfo, action: 'view', from: PageList.home});
  55. }
  56. }
  57. if (stationInfo.id) {
  58. return (
  59. <Pressable
  60. style={({pressed}) => [style, pressed ? styles.stationBarPresed : {}]}
  61. onPress={() => toChargePage()}>
  62. <View style={ui.flexcw}>
  63. <TextView
  64. ellipsizeMode='tail'
  65. numberOfLines={1}
  66. style={styles.stationTitle}>{stationInfo.name}</TextView>
  67. <Pressable
  68. style={styles.closeIcon}
  69. android_ripple={rippleLess}
  70. onPress={onClose}>
  71. <MaterialCommunityIcons
  72. name="close"
  73. size={22}
  74. color={textCancel}/>
  75. </Pressable>
  76. </View>
  77. <View style={{height: 4}}></View>
  78. <View style={ui.flexc}>
  79. <TextView
  80. style={styles.stationAddress}
  81. ellipsizeMode='tail'
  82. numberOfLines={3}>{stationInfo.address}</TextView>
  83. { stationInfo.upcoming
  84. ? <View style={[ui.center, $margin(0, 8)]}>
  85. <MaterialIcons
  86. name="upcoming"
  87. size={42}
  88. color={colorAccent}
  89. style={styles.upcomingIcon} />
  90. <TextView style={styles.upcomingText}>{$t("home.upcoming")}</TextView>
  91. </View>
  92. : <>
  93. { app.modules.bookmarks &&
  94. <Pressable
  95. style={[styles.directIconView, {backgroundColor: stationInfo.favorite ? colorPrimary : colorCancel}]}
  96. android_ripple={rippleLess}
  97. onPress={onFavorite}>
  98. <MaterialIcons
  99. name="star"
  100. size={26}
  101. color={colorLight}/>
  102. </Pressable>
  103. }
  104. <Pressable
  105. style={styles.directIconView}
  106. android_ripple={rippleLess}
  107. onPress={() => {
  108. utils.directMaps(stationInfo.latitude, stationInfo.longitude, stationInfo.address);
  109. }}>
  110. <MaterialCommunityIcons
  111. name="navigation-variant"
  112. size={25}
  113. color={colorLight}/>
  114. {/* <MaterialIcons
  115. name='directions'
  116. size={28}
  117. color={colorAccent}/>
  118. <Text style={styles.distanceText}>{stationInfo.distance}</Text> */}
  119. </Pressable>
  120. </> }
  121. </View>
  122. <View style={ui.flex}>
  123. <View style={styles.connectView}>
  124. <ConnectType {...stationInfo?.acConnector}/>
  125. <ConnectType {...stationInfo?.dcConnector}/>
  126. </View>
  127. <View style={styles.stationStatusView}>
  128. { (stationInfo.allConnector && stationInfo.allConnector.available > 0) &&
  129. <TextView style={[ChargeStyle.infoStatus, ChargeStyle.statusAvailable, styles.stationStatus]}>{$t("charging.statusAvailable")}</TextView>
  130. }
  131. <TextView style={[ChargeStyle.infoStatus, stationInfo.siteType == 'Public' ? ChargeStyle.statusAvailable : ChargeStyle.statusWarning, styles.siteTypes]}>{stationInfo.siteType}</TextView>
  132. </View>
  133. </View>
  134. { stationInfo?.labels?.length > 0 &&
  135. <View style={styles.siteLabelsView}>
  136. <Image
  137. style={styles.labelIcon}
  138. source={require('../../../images/maps/ic_marker_additional.png')}/>
  139. { stationInfo.labels.map((item, index) =>
  140. <TextView
  141. key={index}
  142. style={styles.textLabel}>
  143. {item}
  144. </TextView>
  145. )}
  146. </View>
  147. }
  148. <View style={styles.divideLine}></View>
  149. <View style={styles.infoDetailsView}>
  150. <View style={ui.flex1}>
  151. <TextView style={styles.infoTitle}>{$t("charging.operatingHours")}</TextView>
  152. <View style={styles.infoView}>
  153. <TextView style={styles.infoText}>{getOperatingHours()}</TextView>
  154. </View>
  155. </View>
  156. <View style={{width: 4}}></View>
  157. <View style={ui.flex1}>
  158. <TextView style={styles.infoTitle}>{$t("charging.parkingFees")}</TextView>
  159. <View style={styles.infoView}>
  160. <TextView style={styles.infoText}>{getParkingFee()}</TextView>
  161. </View>
  162. </View>
  163. <View style={{width: 4}}></View>
  164. <View style={ui.flex1}>
  165. <TextView style={styles.infoTitle}>{$t("charging.additionalInfo")}</TextView>
  166. <View style={styles.infoView}>
  167. <TextView style={styles.infoText}>{stationInfo?.additionalNotes}</TextView>
  168. </View>
  169. </View>
  170. </View>
  171. </Pressable>
  172. );
  173. } else {
  174. return <></>;
  175. }
  176. }
  177. const styles = StyleSheet.create({
  178. stationBarView: {
  179. left: 16,
  180. right: 16,
  181. bottom: 48,
  182. zIndex: 10,
  183. borderRadius: 6,
  184. ...$padding(8, 16),
  185. position: 'absolute',
  186. backgroundColor: colorLight,
  187. ...ElevationObject(3)
  188. },
  189. stationBarPresed: {
  190. backgroundColor: "#F6F6F6",
  191. ...ElevationObject(5)
  192. },
  193. stationInfo: {
  194. flex: 1,
  195. height: 45,
  196. paddingLeft: 4,
  197. paddingRight: 8,
  198. justifyContent: 'space-around'
  199. },
  200. stationTitle: {
  201. color: '#000',
  202. fontSize: 17,
  203. fontWeight: 'bold'
  204. },
  205. stationAddress: {
  206. flex: 1,
  207. color: '#999',
  208. fontSize: 12
  209. },
  210. stationAvailable: {
  211. height: 45,
  212. paddingLeft: 8,
  213. paddingRight: 8,
  214. alignItems: 'center',
  215. justifyContent: 'space-between'
  216. },
  217. stationStatusView: {
  218. marginRight: 4,
  219. alignItems: 'center',
  220. flexDirection: 'row-reverse'
  221. },
  222. stationStatus: {
  223. fontSize: 10,
  224. ...$padding(2, 6)
  225. },
  226. siteTypes: {
  227. fontSize: 10,
  228. marginTop: 0,
  229. marginRight: 4,
  230. ...$padding(2, 6)
  231. },
  232. availableIcon: {
  233. width: 23,
  234. height: 23,
  235. },
  236. availableText: {
  237. color: textPrimary,
  238. fontSize: 13,
  239. textAlign: 'center'
  240. },
  241. directView: {
  242. zIndex: 1,
  243. height: 45,
  244. marginLeft: 8,
  245. marginRight: 4,
  246. alignItems: 'center',
  247. justifyContent: 'space-between'
  248. },
  249. distanceText: {
  250. color: textPrimary,
  251. fontSize: 12,
  252. },
  253. directIconView: {
  254. zIndex: 1,
  255. width: 42,
  256. height: 42,
  257. marginLeft: 8,
  258. marginRight: 4,
  259. borderRadius: 45,
  260. alignItems: 'center',
  261. justifyContent: 'center',
  262. backgroundColor: colorAccent,
  263. ...ElevationObject(2)
  264. },
  265. connectView: {
  266. flex: 1,
  267. paddingTop: 12,
  268. paddingBottom: 12,
  269. alignItems: 'center',
  270. flexDirection: 'row'
  271. },
  272. divideLine: {
  273. height: 1,
  274. backgroundColor: '#AEAEAE'
  275. },
  276. infoDetailsView: {
  277. flexDirection: 'row'
  278. },
  279. infoTitle: {
  280. color: '#000',
  281. fontSize: 12,
  282. fontWeight: 'bold',
  283. ...$padding(8, 0, 8)
  284. },
  285. infoView: {
  286. paddingBottom: 8
  287. },
  288. infoText: {
  289. color: '#444',
  290. fontSize: 10
  291. },
  292. closeIcon: {
  293. width: 30,
  294. height: 30,
  295. marginTop: -2,
  296. marginRight: -8,
  297. alignItems: 'center',
  298. justifyContent: 'center'
  299. },
  300. siteLabelsView: {
  301. marginBottom: 5,
  302. flexWrap: 'wrap',
  303. alignItems: 'center',
  304. flexDirection: 'row'
  305. },
  306. labelIcon: {
  307. width: 16,
  308. height: 16,
  309. marginRight: 6
  310. },
  311. textLabel: {
  312. color: textLight,
  313. fontSize: 10,
  314. marginRight: 5,
  315. marginBottom: 5,
  316. borderRadius: 4,
  317. ...$padding(2, 6),
  318. backgroundColor: colorPrimary
  319. },
  320. upcomingIcon: {
  321. marginLeft: 8,
  322. opacity: .3
  323. },
  324. upcomingText: {
  325. color: colorAccent,
  326. fontSize: 10,
  327. opacity: .3,
  328. marginLeft: 8,
  329. marginTop: -3
  330. }
  331. })