Overview.js 8.2 KB

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