Overview.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /**
  2. * 钱包概述页面
  3. * @邠心vbe on 2021/05/08
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
  7. import { ElevationObject } from '../../components/Button';
  8. import {Bar, VictoryAxis, VictoryBar, VictoryChart, VictoryTheme} from 'victory-native';
  9. import apiWallet from '../../api/apiWallet';
  10. import Svg from 'react-native-svg';
  11. import utils from '../../utils/utils';
  12. const chartThemes = "#6672B8"; //配置柱状图颜色
  13. export default class Overview extends Component {
  14. constructor(props) {
  15. super(props);
  16. this.state = {
  17. glanceData: {},
  18. monthData: [],
  19. weekdayData: [],
  20. weekIndex: 0,
  21. monthIndex: 0
  22. };
  23. this.nowDataString = new Date().toDateString()
  24. this.refreshing = false;
  25. }
  26. componentDidMount() {
  27. this.getOverview();
  28. }
  29. componentDidUpdate() {
  30. if (this.props.refresh && !this.refreshing && this.props.shown) {
  31. this.refreshing = true;
  32. this.getOverview();
  33. }
  34. }
  35. getOverview() {
  36. apiWallet.getOverviewData().then(res => {
  37. var glanceData = {}
  38. var weekdayData = []
  39. var monthData = []
  40. var weekIndex = 0
  41. var monthIndex = 0
  42. if (res.data) {
  43. if (res.data.atAGlance) {
  44. glanceData = res.data.atAGlance
  45. }
  46. if (res.data.statisticsForThisWeek) {
  47. res.data.statisticsForThisWeek.forEach((item, index) => {
  48. if (this.nowDataString.indexOf(item.x) >= 0) {
  49. weekIndex = index;
  50. }
  51. //item.y += index + 2;
  52. item.label = currency + item.y;
  53. item.title = item.dateTimeStr + ' | ' + item.label + ' | ' + item.power + 'kw';
  54. weekdayData.push(item);
  55. });
  56. }
  57. if (res.data.pastSixMonths) {
  58. res.data.pastSixMonths.forEach((item, index) => {
  59. if (this.nowDataString.indexOf(item.x) >= 0) {
  60. monthIndex = index;
  61. }
  62. //item.y += index + 3;
  63. item.label = currency + item.y;
  64. item.title = item.x + ' | ' + item.label + ' | ' + item.power + 'kw';
  65. monthData.push(item);
  66. });
  67. }
  68. }
  69. this.setState({
  70. glanceData: glanceData,
  71. weekIndex: weekIndex,
  72. monthIndex: monthIndex,
  73. weekdayData: weekdayData,
  74. monthData: monthData,
  75. });
  76. this.stopRefresh();
  77. }).catch(err => {
  78. toastShort(err);
  79. this.stopRefresh();
  80. });
  81. }
  82. stopRefresh() {
  83. if (this.props.refreshed) {
  84. this.props.refreshed();
  85. }
  86. this.refreshing = false;
  87. }
  88. barTheme = (active) => ({
  89. data: {
  90. fill: ({datum, index}) => {
  91. return (datum.y > 0 ? (index == active ? colorPrimary : chartThemes) : "#999999");
  92. }
  93. },
  94. labels: {
  95. fontSize: 12,
  96. fill: ({index}) => (index == active ? "#000" : "#555")
  97. }
  98. })
  99. getFill = ({datum, index}) => (datum.y > 0 ? (index == this.state.monthIndex ? colorPrimary : chartThemes) : "#999999");
  100. render() {
  101. return (
  102. <View style={this.props.shown ? ui.flex1 : styles.hide}>
  103. <View style={styles.glanceView}>
  104. <Text style={styles.glanceTitle}>At a glance</Text>
  105. <View style={styles.overviewRow}>
  106. <View style={ui.flex1}>
  107. <Text style={styles.valueText}>{this.state.glanceData.averageCharge ?? 0}</Text>
  108. <Text style={styles.titleText}>kWh/Week</Text>
  109. <Text style={styles.subTitleText}>Average Charge</Text>
  110. </View>
  111. <View style={ui.flex1}>
  112. <Text style={styles.valueText}>{this.state.glanceData.averageSpend ?? 0}</Text>
  113. <Text style={styles.titleText}>{currency}/Week</Text>
  114. <Text style={styles.subTitleText}>Average Spend</Text>
  115. </View>
  116. <View style={ui.flex1}>
  117. <Text style={styles.valueText}>{utils.hour2HHmm(this.state.glanceData.averageTime)}</Text>
  118. <Text style={styles.titleText}>Hr/Week</Text>
  119. <Text style={styles.subTitleText}>Average Time</Text>
  120. </View>
  121. </View>
  122. </View>
  123. { this.props.shown &&
  124. <View style={ui.flex1}>
  125. { this.state.weekdayData.length > 0 &&
  126. <View style={styles.statisticView}>
  127. <Text style={styles.sectionTitle}>Statistics for this week</Text>
  128. <Text style={styles.statisticTitle}>{this.state.weekdayData[this.state.weekIndex].title}</Text>
  129. <Svg height={200}>
  130. <VictoryChart
  131. theme={VictoryTheme.material}
  132. animate={animate}
  133. height={200}>
  134. <VictoryAxis style={axisTheme}/>
  135. <VictoryBar
  136. barWidth={25}
  137. style={this.barTheme(this.state.weekIndex)}
  138. data={this.state.weekdayData}
  139. events={[{
  140. target: "data",
  141. eventHandlers: {
  142. onPress: () => {
  143. return [{
  144. target: "data",
  145. mutation: (props) => {
  146. this.setState({
  147. weekIndex: props.index
  148. });
  149. }
  150. }];
  151. }
  152. }
  153. }]}
  154. />
  155. </VictoryChart>
  156. </Svg>
  157. </View>
  158. }
  159. { this.state.monthData.length > 0 &&
  160. <View style={styles.statisticView}>
  161. <Text style={styles.sectionTitle}>Past 6 Months</Text>
  162. <Text style={styles.statisticTitle}>{this.state.monthData[this.state.monthIndex].title}</Text>
  163. <Svg height={200}>
  164. <VictoryChart
  165. theme={VictoryTheme.material}
  166. height={200}>
  167. <VictoryAxis style={axisTheme}/>
  168. <VictoryBar
  169. barWidth={28}
  170. data={this.state.monthData}
  171. style={this.barTheme(this.state.monthIndex)}
  172. events={[{
  173. target: "data",
  174. eventHandlers: {
  175. onPress: () => {
  176. return [{
  177. target: "data",
  178. mutation: (props) => {
  179. this.setState({
  180. monthIndex: props.index
  181. });
  182. }
  183. }];
  184. }
  185. }
  186. }]}
  187. />
  188. </VictoryChart>
  189. </Svg>
  190. </View>
  191. }
  192. </View>
  193. }
  194. </View>
  195. );
  196. }
  197. }
  198. const animate = {
  199. duration: 500,
  200. onLoad: {
  201. duration: 200
  202. }
  203. }
  204. const axisTheme = {
  205. axis: {stroke: "#fff"},
  206. grid: {strokeWidth: 0},
  207. ticks: {size: 0},
  208. tickLabels: {color: '#666', fontSize: 12, padding: 8},
  209. }
  210. const styles = StyleSheet.create({
  211. hide: {
  212. display: 'none'
  213. },
  214. glanceView: {
  215. marginTop: 16,
  216. marginLeft: 16,
  217. marginRight: 16,
  218. marginBottom: 4,
  219. ...ElevationObject(2),
  220. overflow: 'hidden',
  221. borderTopLeftRadius: 6,
  222. borderTopRightRadius: 6,
  223. backgroundColor: 'white'
  224. },
  225. glanceTitle: {
  226. color: '#333',
  227. fontSize: 16,
  228. paddingTop: 4,
  229. paddingLeft: 16,
  230. paddingBottom: 4,
  231. backgroundColor: '#C4C8DF'
  232. },
  233. overviewRow: {
  234. paddingTop: 16,
  235. paddingBottom: 10,
  236. alignItems: 'center',
  237. flexDirection: 'row'
  238. },
  239. valueText: {
  240. color: '#000',
  241. fontSize: 22,
  242. paddingBottom: 8,
  243. textAlign: 'center'
  244. },
  245. titleText: {
  246. color: '#333',
  247. fontSize: 14,
  248. textAlign: 'center'
  249. },
  250. subTitleText: {
  251. color: '#999',
  252. fontSize: 11,
  253. textAlign: 'center'
  254. },
  255. statisticView: {
  256. marginTop: 16,
  257. paddingTop: 16,
  258. backgroundColor: 'white'
  259. },
  260. sectionTitle: {
  261. color: '#333',
  262. fontSize: 16,
  263. paddingLeft: 16
  264. },
  265. statisticTitle: {
  266. color: '#333',
  267. fontSize: 14,
  268. paddingTop: 24,
  269. paddingBottom: 8,
  270. textAlign: 'center'
  271. },
  272. statisticChart: {
  273. height: 120
  274. }
  275. })