@ledvance/group-ui-biz-bundle 1.0.160 → 1.0.163

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import { getStyles } from '@ledvance/group-ui-biz-bundle/src/modules/energyConsu
5
5
  import {
6
6
  useEnergyData
7
7
  } from '@ledvance/group-ui-biz-bundle/src/modules/energyConsumption/EnergyConsumptionChart/useEnergyData'
8
- import React, { useEffect, useMemo } from 'react';
8
+ import React, {useCallback, useEffect, useMemo, useRef} from 'react';
9
9
  import { ScrollView, StyleSheet, View, Text, Image, TouchableOpacity } from 'react-native';
10
10
  import { useNavigation } from '@react-navigation/core';
11
11
  import { useRoute } from '@react-navigation/core';
@@ -25,16 +25,22 @@ import {
25
25
  exchangeNumber,
26
26
  localeNumber,
27
27
  monthFormat,
28
- monthFormatShort,
28
+ monthFormatShort, showDialog,
29
29
  } from '@ledvance/base/src/utils/common';
30
- import {getEnergyGenerationValue, unitDivision, useEnergyConsumption} from './EnergyConsumptionActions';
31
- import EnergyPopup, { EnergyData } from './component/EnergyModal';
30
+ import {
31
+ getEnergyGenerationValue,
32
+ unitDivision,
33
+ useDynamicPrice,
34
+ useEnergyConsumption
35
+ } from './EnergyConsumptionActions';
36
+ import EnergyPopup, {EnergyData, EnergyType, calculateAveragePrice, PriceSegment, DynamicEnergyData} from './component/EnergyModal';
32
37
  import { carbonDioxideEmission, countryAndRegion } from './co2Data';
33
38
  import { EnergyConsumptionDetailProps } from './EnergyConsumptionDetail';
34
39
  import { EnergyConsumptionChartProps } from './EnergyConsumptionChart';
35
40
  import SegmentControl from '@ledvance/base/src/components/segmentControl';
36
41
  import ThemeType from '@ledvance/base/src/config/themeType'
37
42
  import { exportEnergyCsv } from "./EnergyConsumptionActions";
43
+ import { SetSegmentedPricesParams } from './SetSegmentedPricesScreen';
38
44
 
39
45
  const { convertX: cx } = Utils.RatioUtils;
40
46
  const { withTheme } = Utils.ThemeUtils;
@@ -71,6 +77,7 @@ interface EnergyConsumptionState {
71
77
  popupType: PopupType;
72
78
  co2Saved: string;
73
79
  isSolarMode: boolean
80
+ pricingType: EnergyType,
74
81
  loading: boolean
75
82
  collapsed: boolean
76
83
  }
@@ -80,6 +87,39 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
80
87
  const navigation = useNavigation();
81
88
  const timeZoneCity = useTimeZoneCity();
82
89
  const [energyData, setEnergyData] = useEnergyConsumption()
90
+ const [dynamicData, setDynamicData] = useDynamicPrice()
91
+ const savedDynamicUnitRef = useRef<string | undefined>(undefined)
92
+
93
+ const parsePrice = (dynamicCosts: PriceSegment[], dynamicGenerates: PriceSegment[], fixedModel?: any): string => {
94
+ const type = fixedModel?.energyType ?? 'fixed'
95
+ const usingPrice = state.isSolarMode ? (fixedModel?.generatePrice ?? fixedModel?.price) : fixedModel?.price;
96
+ if (type === 'dynamic') {
97
+ const usingIntervals = state.isSolarMode ? dynamicGenerates : dynamicCosts;
98
+ const dynamicPrice = usingIntervals && usingIntervals.length > 0
99
+ ? String(calculateAveragePrice(usingIntervals))
100
+ : (usingPrice || state.price);
101
+ return String(dynamicPrice ?? '0');
102
+ } else {
103
+ return String(usingPrice ?? '0');
104
+ }
105
+ }
106
+
107
+ const initialPrice = useMemo(() => {
108
+ const type = energyData.energyType ?? 'fixed'
109
+ const usingPrice = !params.wifiPlugGroup.length ? (energyData.generatePrice ?? energyData.price) : energyData.price;
110
+ if (type === 'dynamic') {
111
+ const usingIntervals = !params.wifiPlugGroup.length ? (dynamicData?.generatePrices || []) : (dynamicData?.intervalPrices || []);
112
+ const dynamicPrice = usingIntervals && usingIntervals.length > 0
113
+ ? String(calculateAveragePrice(usingIntervals))
114
+ : usingPrice;
115
+ // console.log("wayne_check_stateprice initialPrice dynamic", dynamicPrice)
116
+ return String(dynamicPrice ?? '0');
117
+ } else {
118
+ // console.log("wayne_check_stateprice initialPrice usingPrice", usingPrice)
119
+ return String(usingPrice ?? '0');
120
+ }
121
+ }, [energyData, dynamicData, params.wifiPlugGroup.length])
122
+
83
123
  const state = useReactive<EnergyConsumptionState>({
84
124
  solarTodayElectricity: '0',
85
125
  solarTotalElectricity: '0',
@@ -87,8 +127,9 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
87
127
  wifiTotalElectricity: '0',
88
128
  solarOverviewList: [],
89
129
  wifiOverviewList: [],
90
- price: energyData.price,
130
+ price: initialPrice,
91
131
  unit: energyData.unit,
132
+ pricingType: energyData.energyType ?? "fixed",
92
133
  showPopup: false,
93
134
  popupType: '',
94
135
  co2Saved: '0',
@@ -98,16 +139,21 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
98
139
  });
99
140
 
100
141
  useUpdateEffect(() => {
101
- state.price = energyData.price
102
- state.unit = energyData.unit
103
- }, [JSON.stringify(energyData)])
142
+ state.pricingType = energyData.energyType ?? 'fixed'
143
+ state.price = parsePrice(dynamicData?.intervalPrices || [], dynamicData?.generatePrices || [], energyData)
144
+ // console.log("wayne_check_stateprice useUpdateEffect", state.price)
145
+ state.unit = state.pricingType === 'dynamic'
146
+ ? (savedDynamicUnitRef.current ?? energyData.unit)
147
+ : energyData.unit
148
+ actions.setPriceAndUnit(state.price, state.unit)
149
+ }, [JSON.stringify(energyData), JSON.stringify(dynamicData), state.isSolarMode])
104
150
 
105
151
  const chartHeadline = useMemo(() => {
106
152
  const overview = state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList
107
153
  const len = overview.length;
108
154
  return overview?.length
109
- ? `${overview[len - 1].key} - ${overview[0].key}`
110
- : '';
155
+ ? `${overview[len - 1].key} - ${overview[0].key}`
156
+ : '';
111
157
  }, [state.solarOverviewList, state.wifiOverviewList, state.isSolarMode]);
112
158
 
113
159
  const chartParams = useMemo(() => {
@@ -123,9 +169,11 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
123
169
  displayMode: state.isSolarMode ? 'generation' : 'consumption',
124
170
  consumptionDeviceIds: params.wifiPlugGroup,
125
171
  generationDeviceIds: params.solarPlugGroup,
172
+ energyType: state.pricingType,
173
+ dynamicData: dynamicData,
126
174
  }
127
- }, [backTitle, chartHeadline, state.price, state.unit, params.addEleDpCode, state.isSolarMode, params.wifiPlugGroup, params.solarPlugGroup])
128
-
175
+ }, [backTitle, chartHeadline, state.price, state.unit, params.addEleDpCode, state.isSolarMode, params.wifiPlugGroup, params.solarPlugGroup, state.pricingType, dynamicData])
176
+
129
177
  const { state: chartState, actions } = useEnergyData(chartParams);
130
178
  const chartStyles = useMemo(() => getStyles(props.theme), [props.theme]);
131
179
 
@@ -142,16 +190,16 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
142
190
 
143
191
  const getElectricity = async () => {
144
192
  const solarPromise = params.solarPlugGroup.map(devId =>
145
- getDpResultByMonth(devId, params.addEleDpCode, 'sum').catch(error => ({ error }))
193
+ getDpResultByMonth(devId, params.addEleDpCode, 'sum').catch(error => ({ error }))
146
194
  );
147
195
  const solarEnergyGenerationPromise = params.solarPlugGroup.map(devId =>
148
- getEnergyGenerationValue(devId)
196
+ getEnergyGenerationValue(devId)
149
197
  );
150
198
  const wifiPromise = params.wifiPlugGroup.map(devId =>
151
- getDpResultByMonth(devId, params.addEleDpCode, 'sum').catch(error => ({ error }))
199
+ getDpResultByMonth(devId, params.addEleDpCode, 'sum').catch(error => ({ error }))
152
200
  );
153
201
  const wifiEnergyGenerationPromise = params.wifiPlugGroup.map(devId =>
154
- getEnergyGenerationValue(devId)
202
+ getEnergyGenerationValue(devId)
155
203
  );
156
204
  state.loading = true
157
205
  const solarRes = await Promise.all(solarPromise);
@@ -225,11 +273,44 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
225
273
  }
226
274
  }
227
275
 
228
- const updateEnergyData = (data: EnergyData) => {
229
- setEnergyData(data).then()
230
- state.price = data.price;
231
- state.unit = data.unit;
232
- actions.setPriceAndUnit(data.price, data.unit)
276
+ const showAlerDialog = useCallback((content: string) => {
277
+ showDialog({
278
+ method: 'alert',
279
+ title: I18n.getLang('title_tips'),
280
+ subTitle: content,
281
+ onConfirm: async (_, { close }) => {
282
+ close()
283
+ }
284
+ })
285
+ }, [])
286
+ const updateEnergyData = async (data: EnergyData): Promise<boolean> => {
287
+ const internationalPrice = exchangeNumber(data.price)
288
+ const newEnergyData = {
289
+ ...energyData,
290
+ unit: data.unit,
291
+ energyType: 'fixed',
292
+ [state.isSolarMode ? 'generatePrice' : 'price']: internationalPrice,
293
+ }
294
+ state.loading = true
295
+ try {
296
+ const result = await setEnergyData(newEnergyData)
297
+ if (!result?.success) {
298
+ console.warn('Failed to update fixed energy price', result)
299
+ showAlerDialog(I18n.getLang('common_server_api_error'))
300
+ return false
301
+ }
302
+ state.price = internationalPrice || '0'
303
+ savedDynamicUnitRef.current = undefined
304
+ state.unit = data.unit
305
+ state.pricingType = 'fixed'
306
+ actions.setPriceAndUnit(state.price, data.unit)
307
+ return true
308
+ } catch (error) {
309
+ console.error('Failed to update fixed energy price', error)
310
+ return false
311
+ } finally {
312
+ state.loading = false
313
+ }
233
314
  };
234
315
 
235
316
  const backTitle = useMemo(() => {
@@ -306,300 +387,388 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
306
387
 
307
388
  const ConsumedEnergyItem = (props: { value: number; unit: string }) => {
308
389
  return (
309
- <View style={styles.subContent}>
310
- <Text style={styles.valueText}>{props.value || 0}</Text>
311
- <Spacer height={cx(4)} />
312
- <Text style={styles.titleText}>{unitDivision(props.unit)[0]}</Text>
313
- <Text style={styles.titleText}>{unitDivision(props.unit)[1]}</Text>
314
- </View>
390
+ <View style={styles.subContent}>
391
+ <Text style={styles.valueText}>{props.value || 0}</Text>
392
+ <Spacer height={cx(4)} />
393
+ <Text style={styles.titleText}>{unitDivision(props.unit)[0]}</Text>
394
+ <Text style={styles.titleText}>{unitDivision(props.unit)[1]}</Text>
395
+ </View>
315
396
  );
316
397
  };
317
398
 
318
399
  return (
319
- <Page
320
- style={{ position: 'relative' }}
321
- backText={backTitle}
322
- headlineText={I18n.getLang(
323
- state.isSolarMode
324
- ? 'sockets_headline_power'
325
- : 'consumption_data_annual_bar_chart_system_back_text'
326
- )}
327
- headlineIcon={(state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList).length ? res.download_icon : undefined}
328
- onHeadlineIconClick={() => {
329
- const headers = [I18n.getLang('date'), `${I18n.getLang('consumption_data_annual_bar_chart_system_back_text')} (kWh)`, `Price(${state.unit})`]
330
- const values = (state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList).map(item => [item.key, item.value, (Number(state.price) * Number(item.value)).toFixed(2)])
331
- exportEnergyCsv(headers, values)
332
- }}
333
- showGreenery={state.isSolarMode}
334
- greeneryIcon={res.energy_consumption_greenery}
335
- headlineTopContent={
336
- (params.solarPlugGroup.length && params.wifiPlugGroup.length) ?
337
- <View style={{ marginBottom: cx(5) }}>
338
- <SegmentControl
339
- title1={I18n.getLang('consumption_data_annual_bar_chart_system_back_text')}
340
- title2={I18n.getLang('sockets_headline_power')}
341
- isFirst={!state.isSolarMode}
342
- tabStyle={{paddingHorizontal: cx(15)}}
343
- setIsFirst={(v) => {
344
- state.isSolarMode = !v
345
- actions.setDisplayMode(!v ? 'generation' : 'consumption')
346
- }} />
347
- </View> : undefined
348
- }
349
- loading={state.loading}
350
- >
351
- <ScrollView nestedScrollEnabled={true}>
352
- <View>
353
- {/* tip */}
354
- <Spacer height={cx(15)} />
355
- <View style={styles.showTip}>
356
- <Text style={{ fontSize: cx(14), color: props.theme?.global.fontColor, }}>
357
- {I18n.getLang(
358
- state.isSolarMode
359
- ? 'generation_data_description_text'
360
- : 'consumption_data_description_text'
361
- )}
362
- </Text>
363
- </View>
364
- <Spacer />
365
- <Card
366
- style={styles.cardContainer}
367
- onPress={() => {
368
- navigation.navigate(ui_biz_routerKey.group_ui_biz_energy_consumption_chart, {
369
- backTitle,
370
- headlineText: chartHeadline,
371
- chartData: state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList,
372
- price: state.price,
373
- unit: state.unit,
374
- addEleDpCode: params.addEleDpCode,
375
- date: (new Date()).getFullYear().toString(),
376
- deviceIdGroup: state.isSolarMode ? params.solarPlugGroup : params.wifiPlugGroup,
377
- displayMode: (params.wifiPlugGroup.length && params.solarPlugGroup.length) ? 'both' : (params.wifiPlugGroup.length ? 'consumption' : 'generation'),
378
- consumptionDeviceIds: params.wifiPlugGroup,
379
- generationDeviceIds: params.solarPlugGroup,
380
- } as EnergyConsumptionChartProps)
381
- }}
382
- >
383
- <View style={{
384
- flexDirection: 'row',
385
- justifyContent: 'space-between',
386
- alignItems: 'center',
387
- }}>
388
- <Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field2_headline_text')}</Text>
389
- <Image
390
- source={{ uri: res.energy_consumption_chart}}
391
- style={{ width: cx(16), height: cx(16), marginLeft: cx(8) }}
392
- />
393
- </View>
400
+ <Page
401
+ style={{ position: 'relative' }}
402
+ backText={backTitle}
403
+ headlineText={I18n.getLang(
404
+ state.isSolarMode
405
+ ? 'sockets_headline_power'
406
+ : 'consumption_data_annual_bar_chart_system_back_text'
407
+ )}
408
+ headlineIcon={(state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList).length ? res.download_icon : undefined}
409
+ onHeadlineIconClick={() => {
410
+ const headers = [I18n.getLang('date'), `${I18n.getLang('consumption_data_annual_bar_chart_system_back_text')} (kWh)`, `Price(${state.unit})`]
411
+ const values = (state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList).map(item => [item.key, item.value, (Number(state.price) * Number(item.value)).toFixed(2)])
412
+ exportEnergyCsv(headers, values)
413
+ }}
414
+ showGreenery={state.isSolarMode}
415
+ greeneryIcon={res.energy_consumption_greenery}
416
+ headlineTopContent={
417
+ (params.solarPlugGroup.length && params.wifiPlugGroup.length) ?
418
+ <View style={{ marginBottom: cx(5) }}>
419
+ <SegmentControl
420
+ marginHorizontal={cx(0)}
421
+ title1={I18n.getLang('consumption_data_annual_bar_chart_system_back_text')}
422
+ title2={I18n.getLang('sockets_headline_power')}
423
+ isFirst={!state.isSolarMode}
424
+ tabStyle={{paddingHorizontal: cx(15)}}
425
+ setIsFirst={(v) => {
426
+ state.isSolarMode = !v
427
+ actions.setDisplayMode(!v ? 'generation' : 'consumption')
428
+ }} />
429
+ </View> : undefined
430
+ }
431
+ loading={state.loading}
432
+ >
433
+ <ScrollView nestedScrollEnabled={true}>
434
+ <View>
435
+ {/* tip */}
394
436
  <Spacer height={cx(15)} />
395
- <View style={styles.consumedEnergyContent}>
396
- <ConsumedEnergyItem
397
- value={state.isSolarMode ? params.solarPowerSum : params.wifiPowerSum}
398
- unit={I18n.getLang('consumption_data_field2_value_text1')}
399
- />
400
- <ConsumedEnergyItem
401
- value={state.isSolarMode ? params.solarCurrentSum : params.wifiCurrentSum}
402
- unit={I18n.getLang('consumption_data_field2_value_text2')}
403
- />
437
+ <View style={styles.showTip}>
438
+ <Text style={{ fontSize: cx(14), color: props.theme?.global.fontColor, }}>
439
+ {I18n.getLang(
440
+ state.isSolarMode
441
+ ? 'generation_data_description_text'
442
+ : 'consumption_data_description_text'
443
+ )}
444
+ </Text>
404
445
  </View>
405
- </Card>
406
- <Spacer />
407
- {/* 365 day */}
408
- <Card style={styles.cardContainer}>
409
- <View style={{ flexDirection: 'row', alignItems: 'center' }}>
410
- <View>
411
- <View style={{height: cx(35), justifyContent: 'center'}}>
412
- <Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field1_headline_text')}</Text>
413
- </View>
414
- <View style={{height: cx(35), justifyContent: 'center'}}>
415
- <Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field3_headline_text')}</Text>
416
- </View>
446
+ <Spacer />
447
+ <Card
448
+ style={styles.cardContainer}
449
+ onPress={() => {
450
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_energy_consumption_chart, {
451
+ backTitle,
452
+ headlineText: chartHeadline,
453
+ chartData: state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList,
454
+ price: state.price,
455
+ unit: state.unit,
456
+ addEleDpCode: params.addEleDpCode,
457
+ date: (new Date()).getFullYear().toString(),
458
+ deviceIdGroup: state.isSolarMode ? params.solarPlugGroup : params.wifiPlugGroup,
459
+ displayMode: (params.wifiPlugGroup.length && params.solarPlugGroup.length) ? 'both' : (params.wifiPlugGroup.length ? 'consumption' : 'generation'),
460
+ consumptionDeviceIds: params.wifiPlugGroup,
461
+ generationDeviceIds: params.solarPlugGroup,
462
+ } as EnergyConsumptionChartProps)
463
+ }}
464
+ >
465
+ <View style={{
466
+ flexDirection: 'row',
467
+ justifyContent: 'space-between',
468
+ alignItems: 'center',
469
+ }}>
470
+ <Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field2_headline_text')}</Text>
471
+ <Image
472
+ source={{ uri: res.energy_consumption_chart}}
473
+ style={{ width: cx(16), height: cx(16), marginLeft: cx(8) }}
474
+ />
475
+ </View>
476
+ <Spacer height={cx(15)} />
477
+ <View style={styles.consumedEnergyContent}>
478
+ <ConsumedEnergyItem
479
+ value={state.isSolarMode ? params.solarPowerSum : params.wifiPowerSum}
480
+ unit={I18n.getLang('consumption_data_field2_value_text1')}
481
+ />
482
+ <ConsumedEnergyItem
483
+ value={state.isSolarMode ? params.solarCurrentSum : params.wifiCurrentSum}
484
+ unit={I18n.getLang('consumption_data_field2_value_text2')}
485
+ />
417
486
  </View>
418
- <View>
419
- <View style={{ flexDirection: 'row', alignItems: 'flex-end', marginLeft: cx(10) }}>
420
- <Text style={[styles.consumptionNum, { fontSize: cx(30), marginRight: cx(8) }]}>
421
- {localeNumber(state.isSolarMode ? state.solarTodayElectricity : state.wifiTodayElectricity)}
422
- </Text>
423
- <Text style={[styles.consumptionNum, { fontSize: cx(20), marginBottom: cx(4) }]}>kWh</Text>
487
+ </Card>
488
+ <Spacer />
489
+ {/* pricing radio button*/}
490
+ <View style={{ marginBottom: cx(5) }}>
491
+ <SegmentControl
492
+ marginHorizontal={cx(24)}
493
+ title1={I18n.getLang('consumption_energy_type_fixed')}
494
+ title2={I18n.getLang('consumption_energy_type_dynamic')}
495
+ isFirst={state.pricingType === 'fixed'}
496
+ tabStyle={{paddingHorizontal: cx(15)}}
497
+ setIsFirst={(v) => {
498
+ const value = v ? 'fixed' : 'dynamic'
499
+ const fixedModel = energyData ?? {
500
+ price: '0',
501
+ unit: '$',
502
+ energyType: 'fixed',
503
+ generatePrice: '0',
504
+ }
505
+ state.loading = true
506
+ setEnergyData({
507
+ ...fixedModel,
508
+ energyType: value,
509
+ }).then((res) => {
510
+ state.loading = false
511
+ if (res && res.success) {
512
+ state.pricingType = value
513
+ if (value === 'fixed') {
514
+ savedDynamicUnitRef.current = undefined
515
+ state.price = state.isSolarMode ? (fixedModel.generatePrice || fixedModel.price) : fixedModel.price
516
+ } else {
517
+ // console.log("check isSolar -> ", state.isSolarMode)
518
+ // console.log("wayne_check_stateprice segment ->", JSON.stringify(dynamicData))
519
+ const segments = state.isSolarMode ? (dynamicData?.generatePrices || []) : (dynamicData?.intervalPrices || [])
520
+ state.price = String(calculateAveragePrice(segments))
521
+ }
522
+ actions.setPriceAndUnit(state.price, state.unit)
523
+ }
524
+ })
525
+ }} />
526
+ </View>
527
+ {/* 365 day */}
528
+ <Card style={styles.cardContainer}>
529
+ <View style={{ flexDirection: 'row', alignItems: 'center' }}>
530
+ <View>
531
+ <View style={{height: cx(35), justifyContent: 'center'}}>
532
+ <Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field1_headline_text')}</Text>
533
+ </View>
534
+ <View style={{height: cx(35), justifyContent: 'center'}}>
535
+ <Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field3_headline_text')}</Text>
536
+ </View>
424
537
  </View>
425
- <View style={{ flexDirection: 'row', alignItems: 'flex-end', marginLeft: cx(10) }}>
426
- <Text style={[styles.consumptionNum, { fontSize: cx(30), marginRight: cx(8) }]}>
427
- {localeNumber(state.isSolarMode ? state.solarTotalElectricity : state.wifiTotalElectricity)}
428
- </Text>
429
- <Text style={[styles.consumptionNum, { fontSize: cx(20), marginBottom: cx(4) }]}>kWh</Text>
538
+ <View>
539
+ <View style={{ flexDirection: 'row', alignItems: 'flex-end', marginLeft: cx(10) }}>
540
+ <Text style={[styles.consumptionNum, { fontSize: cx(30), marginRight: cx(8) }]}>
541
+ {localeNumber(state.isSolarMode ? state.solarTodayElectricity : state.wifiTodayElectricity)}
542
+ </Text>
543
+ <Text style={[styles.consumptionNum, { fontSize: cx(20), marginBottom: cx(4) }]}>kWh</Text>
544
+ </View>
545
+ <View style={{ flexDirection: 'row', alignItems: 'flex-end', marginLeft: cx(10) }}>
546
+ <Text style={[styles.consumptionNum, { fontSize: cx(30), marginRight: cx(8) }]}>
547
+ {localeNumber(state.isSolarMode ? state.solarTotalElectricity : state.wifiTotalElectricity)}
548
+ </Text>
549
+ <Text style={[styles.consumptionNum, { fontSize: cx(20), marginBottom: cx(4) }]}>kWh</Text>
550
+ </View>
430
551
  </View>
431
552
  </View>
432
- </View>
433
- <Spacer />
434
- {/* CO2 */}
435
- {state.isSolarMode && (
436
- <>
437
- <View style={{ flexDirection: 'row', alignItems: 'center' }}>
438
- <View style={styles.priceBg}>
439
- <Image
553
+ <Spacer />
554
+ {/* CO2 */}
555
+ {state.isSolarMode && (
556
+ <>
557
+ <View style={{ flexDirection: 'row', alignItems: 'center' }}>
558
+ <View style={styles.priceBg}>
559
+ <Image
560
+ source={{ uri: res.energy_consumption_cash}}
561
+ resizeMode="contain"
562
+ style={{
563
+ height: cx(20),
564
+ width: cx(20),
565
+ tintColor: props.theme?.button.primary,
566
+ }}
567
+ />
568
+ </View>
569
+ <View style={styles.priceNum}>
570
+ <View style={{ flexDirection: 'row' }}>
571
+ <Text
572
+ style={{ color: props.theme?.global.secondFontColor, marginRight: cx(5) }}
573
+ >
574
+ {I18n.getLang('consumption_data_field3_co2_topic_text')}
575
+ </Text>
576
+ <TouchableOpacity
577
+ onPress={() => {
578
+ state.showPopup = true;
579
+ state.popupType = 'co2';
580
+ }}
581
+ >
582
+ <Image
583
+ source={{ uri: res.co2_icon}}
584
+ resizeMode="contain"
585
+ style={{
586
+ height: cx(20),
587
+ width: cx(20),
588
+ tintColor: props.theme?.button.primary,
589
+ }}
590
+ />
591
+ </TouchableOpacity>
592
+ </View>
593
+ <Text
594
+ style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}
595
+ >{`${state.co2Saved} kg`}</Text>
596
+ </View>
597
+ </View>
598
+ <Spacer height={cx(10)} />
599
+ </>
600
+ )}
601
+ {/* money */}
602
+ <View style={{ flexDirection: 'row', alignItems: 'center' }}>
603
+ <View style={styles.priceBg}>
604
+ <Image
440
605
  source={{ uri: res.energy_consumption_cash}}
441
606
  resizeMode="contain"
442
- style={{
443
- height: cx(20),
444
- width: cx(20),
445
- tintColor: props.theme?.button.primary,
446
- }}
447
- />
448
- </View>
607
+ style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.primary }}
608
+ />
609
+ </View>
610
+ <View>
449
611
  <View style={styles.priceNum}>
450
- <View style={{ flexDirection: 'row' }}>
451
- <Text
452
- style={{ color: props.theme?.global.secondFontColor, marginRight: cx(5) }}
453
- >
454
- {I18n.getLang('consumption_data_field3_co2_topic_text')}
612
+ <Text style={{ color: props.theme?.global.secondFontColor }}>
613
+ {I18n.getLang(
614
+ state.isSolarMode
615
+ ? 'consumption_data_monthly_overview_field1_text2'
616
+ : 'consumption_data_field3_value_text2'
617
+ )}
618
+ </Text>
619
+ <Text style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}>
620
+ {state.price
621
+ ? `${localeNumber(Number(state.price) * Number(state.isSolarMode ? state.solarTotalElectricity : state.wifiTotalElectricity), 2)} ${state.unit
622
+ }`
623
+ : '-'}
624
+ </Text>
625
+ </View>
626
+ {state.pricingType === 'fixed' &&<TouchableOpacity
627
+ onPress={() => {
628
+ state.showPopup = true;
629
+ state.popupType = 'money';
630
+ }}
631
+ >
632
+ <View style={styles.priceButton}>
633
+ <Text style={{ color: props.theme?.button.fontColor }}>
634
+ {I18n.getLang('consumption_data_field3_button_text')}
455
635
  </Text>
636
+ </View>
637
+ </TouchableOpacity>
638
+ }
639
+ {state.pricingType === 'dynamic' && (
456
640
  <TouchableOpacity
457
- onPress={() => {
458
- state.showPopup = true;
459
- state.popupType = 'co2';
460
- }}
461
- >
462
- <Image
463
- source={{ uri: res.co2_icon}}
464
- resizeMode="contain"
465
- style={{
466
- height: cx(20),
467
- width: cx(20),
468
- tintColor: props.theme?.button.primary,
641
+ onPress={() => {
642
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_set_segmented_prices, {
643
+ backTitle: backTitle,
644
+ dynamicData: dynamicData ?? {
645
+ intervalPrices: [],
646
+ generatePrices: [],
647
+ },
648
+ priceUnit: state.unit,
649
+ isGenerate: state.isSolarMode,
650
+ onSetPriceSements: async (segments: PriceSegment[], currency: string): Promise<boolean> => {
651
+ console.log("onSetPriceSements ", JSON.stringify(segments), currency)
652
+ const fixedModel = energyData ?? {
653
+ price: '0',
654
+ unit: '$',
655
+ energyType: 'fixed',
656
+ generatePrice: '0',
657
+ }
658
+ const dynamicModel = {
659
+ ...dynamicData,
660
+ [state.isSolarMode ? 'generatePrices' : 'intervalPrices']: segments
661
+ }
662
+ const [fixedRes, dynamicRes] = await Promise.all([
663
+ setEnergyData({ ...fixedModel, energyType: 'dynamic', unit: currency }),
664
+ setDynamicData(dynamicModel)
665
+ ])
666
+ const isDynamicSuccess = dynamicRes && dynamicRes.success
667
+ const isRegularSuccess = fixedRes && fixedRes.success
668
+ const isAllSuccess = isDynamicSuccess && isRegularSuccess
669
+ if (isAllSuccess) {
670
+ savedDynamicUnitRef.current = currency
671
+ state.price = String(calculateAveragePrice(segments)) // 价格
672
+ // console.log("wayne_check_stateprice onPress isAllSucess", state.price)
673
+ state.pricingType = 'dynamic'
674
+ state.unit = currency
675
+ actions.setPriceAndUnit(state.price, currency)
676
+ }
677
+ return !!isAllSuccess
678
+ }
679
+ } as SetSegmentedPricesParams)
469
680
  }}
470
- />
681
+ >
682
+ <View style={styles.priceButton}>
683
+ <Text style={{ color: props.theme?.button.fontColor }}>
684
+ {I18n.getLang('consumption_data_field_dynamic_money')}
685
+ </Text>
686
+ </View>
471
687
  </TouchableOpacity>
472
- </View>
473
- <Text
474
- style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}
475
- >{`${state.co2Saved} kg`}</Text>
476
- </View>
477
- </View>
478
- <Spacer height={cx(10)} />
479
- </>
480
- )}
481
- {/* money */}
482
- <View style={{ flexDirection: 'row', alignItems: 'center' }}>
483
- <View style={styles.priceBg}>
484
- <Image
485
- source={{ uri: res.energy_consumption_cash}}
486
- resizeMode="contain"
487
- style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.primary }}
488
- />
489
- </View>
490
- <View>
491
- <View style={styles.priceNum}>
492
- <Text style={{ color: props.theme?.global.secondFontColor }}>
493
- {I18n.getLang(
494
- state.isSolarMode
495
- ? 'consumption_data_monthly_overview_field1_text2'
496
- : 'consumption_data_field3_value_text2'
497
- )}
498
- </Text>
499
- <Text style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}>
500
- {state.price
501
- ? `${localeNumber(Number(state.price) * Number(state.isSolarMode ? state.solarTotalElectricity : state.wifiTotalElectricity), 2)} ${state.unit
502
- }`
503
- : '-'}
504
- </Text>
688
+ )}
689
+
505
690
  </View>
506
- <TouchableOpacity
507
- onPress={() => {
508
- state.showPopup = true;
509
- state.popupType = 'money';
510
- }}
511
- >
512
- <View style={styles.priceButton}>
513
- <Text style={{ color: props.theme?.button.fontColor }}>
514
- {I18n.getLang('consumption_data_field3_button_text')}
515
- </Text>
516
- </View>
517
- </TouchableOpacity>
518
691
  </View>
692
+ </Card>
693
+ <Spacer height={cx(30)} />
694
+ <View style={{ marginHorizontal: cx(24) }}>
695
+ <ChartSection
696
+ state={chartState}
697
+ actions={actions}
698
+ params={chartParams}
699
+ styles={chartStyles}
700
+ theme={props.theme}
701
+ chartHeight={cx(400)}
702
+ />
519
703
  </View>
520
- </Card>
521
- <Spacer height={cx(30)} />
522
- <View style={{ marginHorizontal: cx(24) }}>
523
- <ChartSection
524
- state={chartState}
525
- actions={actions}
526
- params={chartParams}
527
- styles={chartStyles}
528
- theme={props.theme}
529
- chartHeight={cx(400)}
704
+ <Spacer height={cx(30)} />
705
+ {/* Annual overview */}
706
+ <OverView
707
+ style={{marginHorizontal: cx(24)}}
708
+ headlineText={I18n.getLang('consumption_data_field4_headline_text')}
709
+ headlineClick={() => {
710
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_energy_consumption_chart, {
711
+ backTitle,
712
+ headlineText: chartHeadline,
713
+ chartData: state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList,
714
+ price: state.price,
715
+ unit: state.unit,
716
+ addEleDpCode: params.addEleDpCode,
717
+ date: (new Date()).getFullYear().toString(),
718
+ deviceIdGroup: state.isSolarMode ? params.solarPlugGroup : params.wifiPlugGroup,
719
+ displayMode: (params.wifiPlugGroup.length && params.solarPlugGroup.length) ? 'both' : (params.wifiPlugGroup.length ? 'consumption' : 'generation'),
720
+ consumptionDeviceIds: params.wifiPlugGroup,
721
+ generationDeviceIds: params.solarPlugGroup,
722
+ } as EnergyConsumptionChartProps)
723
+ }}
724
+ overviewItemClick={(item) => {
725
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_energy_consumption_detail, {
726
+ backTitle,
727
+ addEleDpCode: params.addEleDpCode,
728
+ curMonth: item,
729
+ price: state.price,
730
+ unit: state.unit,
731
+ isSolarMode: state.isSolarMode,
732
+ deviceIdGroup: state.isSolarMode ? params.solarPlugGroup : params.wifiPlugGroup,
733
+ displayMode: (params.wifiPlugGroup.length && params.solarPlugGroup.length) ? 'both' : (params.wifiPlugGroup.length ? 'consumption' : 'generation'),
734
+ consumptionDeviceIds: params.wifiPlugGroup,
735
+ generationDeviceIds: params.solarPlugGroup,
736
+ updateEnergyData
737
+ } as EnergyConsumptionDetailProps)
738
+ }}
739
+ overViewList={state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList}
740
+ />
741
+ {/* modal */}
742
+ <EnergyPopup
743
+ visible={!!(state.popupType && state.showPopup)}
744
+ popupType={state.popupType || 'co2'}
745
+ title={
746
+ state.popupType === 'co2'
747
+ ? I18n.getLang('consumption_data_field3_co2_topic_text')
748
+ : ''
749
+ }
750
+ cancelText={state.popupType === 'co2' ? '' : I18n.getLang('auto_scan_system_cancel')}
751
+ confirmText={I18n.getLang(
752
+ state.popupType === 'co2'
753
+ ? 'home_screen_home_dialog_yes_con'
754
+ : 'auto_scan_system_wifi_confirm'
755
+ )}
756
+ energyData={{ price: state.price, unit: state.unit }}
757
+ onConfirm={async popupEnergyData => {
758
+ state.popupType = '';
759
+ state.showPopup = false;
760
+ if (popupEnergyData) {
761
+ await updateEnergyData(popupEnergyData)
762
+ }
763
+ }}
764
+ onCancel={() => {
765
+ state.popupType = '';
766
+ state.showPopup = false;
767
+ }}
530
768
  />
531
769
  </View>
532
- <Spacer height={cx(30)} />
533
- {/* Annual overview */}
534
- <OverView
535
- style={{marginHorizontal: cx(24)}}
536
- headlineText={I18n.getLang('consumption_data_field4_headline_text')}
537
- headlineClick={() => {
538
- navigation.navigate(ui_biz_routerKey.group_ui_biz_energy_consumption_chart, {
539
- backTitle,
540
- headlineText: chartHeadline,
541
- chartData: state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList,
542
- price: state.price,
543
- unit: state.unit,
544
- addEleDpCode: params.addEleDpCode,
545
- date: (new Date()).getFullYear().toString(),
546
- deviceIdGroup: state.isSolarMode ? params.solarPlugGroup : params.wifiPlugGroup,
547
- displayMode: (params.wifiPlugGroup.length && params.solarPlugGroup.length) ? 'both' : (params.wifiPlugGroup.length ? 'consumption' : 'generation'),
548
- consumptionDeviceIds: params.wifiPlugGroup,
549
- generationDeviceIds: params.solarPlugGroup,
550
- } as EnergyConsumptionChartProps)
551
- }}
552
- overviewItemClick={(item) => {
553
- navigation.navigate(ui_biz_routerKey.group_ui_biz_energy_consumption_detail, {
554
- backTitle,
555
- addEleDpCode: params.addEleDpCode,
556
- curMonth: item,
557
- price: state.price,
558
- unit: state.unit,
559
- isSolarMode: state.isSolarMode,
560
- deviceIdGroup: state.isSolarMode ? params.solarPlugGroup : params.wifiPlugGroup,
561
- displayMode: (params.wifiPlugGroup.length && params.solarPlugGroup.length) ? 'both' : (params.wifiPlugGroup.length ? 'consumption' : 'generation'),
562
- consumptionDeviceIds: params.wifiPlugGroup,
563
- generationDeviceIds: params.solarPlugGroup,
564
- updateEnergyData
565
- } as EnergyConsumptionDetailProps)
566
- }}
567
- overViewList={state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList}
568
- />
569
- {/* modal */}
570
- <EnergyPopup
571
- visible={!!(state.popupType && state.showPopup)}
572
- popupType={state.popupType || 'co2'}
573
- title={
574
- state.popupType === 'co2'
575
- ? I18n.getLang('consumption_data_field3_co2_topic_text')
576
- : ''
577
- }
578
- cancelText={state.popupType === 'co2' ? '' : I18n.getLang('auto_scan_system_cancel')}
579
- confirmText={I18n.getLang(
580
- state.popupType === 'co2'
581
- ? 'home_screen_home_dialog_yes_con'
582
- : 'auto_scan_system_wifi_confirm'
583
- )}
584
- energyData={{ price: state.price, unit: state.unit }}
585
- onConfirm={energyData => {
586
- state.popupType = '';
587
- state.showPopup = false;
588
- if (energyData) {
589
- updateEnergyData({
590
- ...energyData,
591
- price: exchangeNumber(energyData.price),
592
- });
593
- }
594
- }}
595
- onCancel={() => {
596
- state.popupType = '';
597
- state.showPopup = false;
598
- }}
599
- />
600
- </View>
601
- </ScrollView>
602
- </Page>
770
+ </ScrollView>
771
+ </Page>
603
772
  );
604
773
  };
605
774