@ledvance/group-ui-biz-bundle 1.0.135 → 1.0.137
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.
- package/package.json +2 -1
- package/src/modules/energyConsumption/EnergyConsumptionChart/ChartSection.tsx +53 -0
- package/src/modules/energyConsumption/EnergyConsumptionChart/EmptyDataView.tsx +21 -0
- package/src/modules/energyConsumption/EnergyConsumptionChart/LandscapeView.tsx +32 -0
- package/src/modules/energyConsumption/EnergyConsumptionChart/PortraitView.tsx +58 -0
- package/src/modules/energyConsumption/EnergyConsumptionChart/index.tsx +27 -0
- package/src/modules/energyConsumption/EnergyConsumptionChart/styles.ts +83 -0
- package/src/modules/energyConsumption/EnergyConsumptionChart/useEnergyData.ts +112 -0
- package/src/modules/energyConsumption/EnergyConsumptionChart.tsx +2 -212
- package/src/modules/energyConsumption/EnergyConsumptionPage.tsx +34 -31
- package/src/modules/energyConsumption/Router.ts +1 -1
- package/src/modules/energyConsumption/component/DateSelectedItem.tsx +2 -2
- package/src/modules/flags/FlagItem.tsx +14 -6
- package/src/modules/mood_new/MoodItem.tsx +13 -7
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"name": "@ledvance/group-ui-biz-bundle",
|
|
5
5
|
"pid": [],
|
|
6
6
|
"uiid": "",
|
|
7
|
-
"version": "1.0.
|
|
7
|
+
"version": "1.0.137",
|
|
8
8
|
"scripts": {},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@ledvance/base": "^1.x",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"prop-types": "^15.6.1",
|
|
18
18
|
"react": "16.8.3",
|
|
19
19
|
"react-native": "0.59.10",
|
|
20
|
+
"react-native-orientation-locker": "^1.7.0",
|
|
20
21
|
"react-native-svg": "5.5.1",
|
|
21
22
|
"tuya-panel-kit": "^4.9.4"
|
|
22
23
|
},
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import I18n from '@ledvance/base/src/i18n'
|
|
2
|
+
import React, { useCallback } from 'react'
|
|
3
|
+
import { View } from 'react-native'
|
|
4
|
+
import { DateType } from '../co2Data'
|
|
5
|
+
import DateSelectedItem from '../component/DateSelectedItem'
|
|
6
|
+
import DateTypeItem from '../component/DateTypeItem'
|
|
7
|
+
import NewBarChart from '../component/NewBarChart'
|
|
8
|
+
import { EmptyDataView } from './EmptyDataView'
|
|
9
|
+
|
|
10
|
+
export const ChartSection = ({ state, actions, params, styles, theme, chartHeight }) => {
|
|
11
|
+
const getEmptyDataTip = useCallback(() => {
|
|
12
|
+
if (state.over365Days && state.dateType !== DateType.Day) {
|
|
13
|
+
return I18n.getLang('energyconsumption_Daylimit')
|
|
14
|
+
}
|
|
15
|
+
if (state.dateType === DateType.Day && state.over7Days) {
|
|
16
|
+
return I18n.getLang('energyconsumption_hourlylimit')
|
|
17
|
+
}
|
|
18
|
+
return I18n.getLang('energyconsumption_emptydata')
|
|
19
|
+
}, [state.dateType, state.over365Days, state.over7Days])
|
|
20
|
+
|
|
21
|
+
const isDataEmpty = state.chartData.length <= 0
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
<View style={styles.dateControlsContainer}>
|
|
26
|
+
<DateTypeItem
|
|
27
|
+
style={styles.dateTypeItem}
|
|
28
|
+
dateType={state.dateType}
|
|
29
|
+
onDateTypeChange={actions.setDateType}
|
|
30
|
+
/>
|
|
31
|
+
<DateSelectedItem
|
|
32
|
+
style={styles.dateSelectedItem}
|
|
33
|
+
dateType={state.dateType}
|
|
34
|
+
date={state.date}
|
|
35
|
+
onDateChange={actions.setDate}
|
|
36
|
+
/>
|
|
37
|
+
</View>
|
|
38
|
+
|
|
39
|
+
{isDataEmpty ? (
|
|
40
|
+
<EmptyDataView text={getEmptyDataTip()} theme={theme} styles={styles}/>
|
|
41
|
+
) : (
|
|
42
|
+
!state.loading && (
|
|
43
|
+
<NewBarChart
|
|
44
|
+
height={chartHeight}
|
|
45
|
+
data={state.chartData}
|
|
46
|
+
price={state.price}
|
|
47
|
+
unit={params.unit}
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
)}
|
|
51
|
+
</>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import InfoText from '@ledvance/base/src/components/InfoText'
|
|
2
|
+
import Spacer from '@ledvance/base/src/components/Spacer'
|
|
3
|
+
import res from '@ledvance/base/src/res'
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import { Image, View } from 'react-native'
|
|
6
|
+
import { Utils } from 'tuya-panel-kit'
|
|
7
|
+
|
|
8
|
+
const { convertX: cx } = Utils.RatioUtils
|
|
9
|
+
|
|
10
|
+
export const EmptyDataView = ({ text, theme, styles, height }) => (
|
|
11
|
+
<View style={[styles.listEmptyView, { height }]}>
|
|
12
|
+
<Image style={styles.listEmptyImage} source={{ uri: res.ldv_timer_empty }}/>
|
|
13
|
+
<Spacer height={cx(5)}/>
|
|
14
|
+
<InfoText
|
|
15
|
+
text={text}
|
|
16
|
+
icon={res.ic_info}
|
|
17
|
+
textStyle={styles.listEmptyText}
|
|
18
|
+
contentColor={theme?.global.fontColor}
|
|
19
|
+
/>
|
|
20
|
+
</View>
|
|
21
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import I18n from '@ledvance/base/src/i18n'
|
|
2
|
+
import res from '@ledvance/base/src/res'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { Image, Text, TouchableOpacity, View } from 'react-native'
|
|
5
|
+
import { Utils } from 'tuya-panel-kit'
|
|
6
|
+
import { ChartSection } from './ChartSection'
|
|
7
|
+
|
|
8
|
+
const { convertX: cx, width } = Utils.RatioUtils
|
|
9
|
+
|
|
10
|
+
export const LandscapeView = ({ state, actions, params, styles, theme }) => (
|
|
11
|
+
<View style={styles.landscapeContainer}>
|
|
12
|
+
<View style={styles.landscapeHeader}>
|
|
13
|
+
<Text style={styles.landscapeTitle}>
|
|
14
|
+
{I18n.getLang('chartdisplay_energy')}
|
|
15
|
+
</Text>
|
|
16
|
+
<TouchableOpacity onPress={actions.toggleLandscape}>
|
|
17
|
+
<Image source={{ uri: res.screen_normal }} style={styles.normalScreenIcon}/>
|
|
18
|
+
</TouchableOpacity>
|
|
19
|
+
</View>
|
|
20
|
+
|
|
21
|
+
<View style={styles.landscapeContent}>
|
|
22
|
+
<ChartSection
|
|
23
|
+
state={state}
|
|
24
|
+
actions={actions}
|
|
25
|
+
params={params}
|
|
26
|
+
styles={styles}
|
|
27
|
+
theme={theme}
|
|
28
|
+
chartHeight={cx(width - 120)}
|
|
29
|
+
/>
|
|
30
|
+
</View>
|
|
31
|
+
</View>
|
|
32
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Page from '@ledvance/base/src/components/Page'
|
|
2
|
+
import res from '@ledvance/base/src/res'
|
|
3
|
+
import React, { useCallback } from 'react'
|
|
4
|
+
import { Image, ScrollView, TouchableOpacity, View } from 'react-native'
|
|
5
|
+
import { Utils } from 'tuya-panel-kit'
|
|
6
|
+
import DateSwitch from '../component/DateSwitch'
|
|
7
|
+
import { exportEnergyCsv } from '../EnergyConsumptionActions'
|
|
8
|
+
import { ChartSection } from './ChartSection'
|
|
9
|
+
|
|
10
|
+
const { convertX: cx } = Utils.RatioUtils
|
|
11
|
+
|
|
12
|
+
export const PortraitView = ({ state, actions, params, styles, theme }) => {
|
|
13
|
+
|
|
14
|
+
const handleExportCsv = useCallback(() => {
|
|
15
|
+
const values = state.chartData.map(item => [item.key, item.value, (Number(params.price) * Number(item.value)).toFixed(2)])
|
|
16
|
+
exportEnergyCsv(values, params.unit)
|
|
17
|
+
}, [state.chartData, params.price, params.unit])
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Page
|
|
21
|
+
backText={params.backTitle}
|
|
22
|
+
showGreenery={false}
|
|
23
|
+
loading={state.loading}
|
|
24
|
+
greeneryIcon={res.energy_consumption_greenery}
|
|
25
|
+
rightButtonIcon={state.isSupportLandscape ? res.screen_full : undefined}
|
|
26
|
+
rightButtonStyle={styles.fullScreenIcon}
|
|
27
|
+
rightButtonIconClick={actions.toggleLandscape}
|
|
28
|
+
headlineContent={
|
|
29
|
+
<View style={styles.headlineContainer}>
|
|
30
|
+
<DateSwitch
|
|
31
|
+
style={styles.dateSwitch}
|
|
32
|
+
date={state.date}
|
|
33
|
+
dateType={state.dateType}
|
|
34
|
+
headlineText={state.headlineText}
|
|
35
|
+
onDateChange={actions.setDate}
|
|
36
|
+
/>
|
|
37
|
+
<TouchableOpacity style={styles.downloadButton} onPress={handleExportCsv}>
|
|
38
|
+
<Image
|
|
39
|
+
style={styles.downloadIcon}
|
|
40
|
+
source={{ uri: !(state.chartData.length <= 0) ? res.download_icon : undefined }}
|
|
41
|
+
/>
|
|
42
|
+
</TouchableOpacity>
|
|
43
|
+
</View>
|
|
44
|
+
}
|
|
45
|
+
>
|
|
46
|
+
<ScrollView nestedScrollEnabled={true} style={styles.scrollViewContent}>
|
|
47
|
+
<ChartSection
|
|
48
|
+
state={state}
|
|
49
|
+
actions={actions}
|
|
50
|
+
params={params}
|
|
51
|
+
styles={styles}
|
|
52
|
+
theme={theme}
|
|
53
|
+
chartHeight={cx(400)}
|
|
54
|
+
/>
|
|
55
|
+
</ScrollView>
|
|
56
|
+
</Page>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
2
|
+
import { useRoute } from '@react-navigation/core'
|
|
3
|
+
import React, { useMemo } from 'react'
|
|
4
|
+
import { Utils } from 'tuya-panel-kit'
|
|
5
|
+
import { EnergyConsumptionChartProps } from '../EnergyConsumptionChart'
|
|
6
|
+
import { LandscapeView } from './LandscapeView'
|
|
7
|
+
import { PortraitView } from './PortraitView'
|
|
8
|
+
import { getStyles } from './styles'
|
|
9
|
+
|
|
10
|
+
import { useEnergyData } from './useEnergyData'
|
|
11
|
+
|
|
12
|
+
const { withTheme } = Utils.ThemeUtils;
|
|
13
|
+
|
|
14
|
+
const EnergyConsumptionGroupChartComponent = (props: { theme?: ThemeType }) => {
|
|
15
|
+
const params = useRoute().params as EnergyConsumptionChartProps;
|
|
16
|
+
|
|
17
|
+
const { state, actions } = useEnergyData(params);
|
|
18
|
+
const styles = useMemo(() => getStyles(props.theme), [props.theme]);
|
|
19
|
+
|
|
20
|
+
if (state.isLandscape) {
|
|
21
|
+
return <LandscapeView state={state} actions={actions} params={params} styles={styles} theme={props.theme} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return <PortraitView state={state} actions={actions} params={params} styles={styles} theme={props.theme} />;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default withTheme(EnergyConsumptionGroupChartComponent);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
2
|
+
import { StyleSheet } from 'react-native'
|
|
3
|
+
import { Utils } from 'tuya-panel-kit'
|
|
4
|
+
|
|
5
|
+
const { convertX: cx, height } = Utils.RatioUtils
|
|
6
|
+
|
|
7
|
+
export const getStyles = (theme: ThemeType | undefined) => StyleSheet.create({
|
|
8
|
+
// Portrait Styles
|
|
9
|
+
scrollViewContent: {
|
|
10
|
+
marginHorizontal: cx(24),
|
|
11
|
+
},
|
|
12
|
+
dateControlsContainer: {
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
},
|
|
15
|
+
dateTypeItem: {
|
|
16
|
+
flex: 1,
|
|
17
|
+
},
|
|
18
|
+
dateSelectedItem: {
|
|
19
|
+
flex: 1,
|
|
20
|
+
marginStart: cx(10),
|
|
21
|
+
marginBottom: cx(15),
|
|
22
|
+
},
|
|
23
|
+
fullScreenIcon: {
|
|
24
|
+
tintColor: theme?.global.brand,
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// Landscape Styles
|
|
28
|
+
landscapeContainer: {
|
|
29
|
+
flex: 1,
|
|
30
|
+
backgroundColor: theme?.global.background,
|
|
31
|
+
width: cx(height + 20),
|
|
32
|
+
paddingVertical: cx(30),
|
|
33
|
+
paddingHorizontal: cx(20),
|
|
34
|
+
},
|
|
35
|
+
landscapeHeader: {
|
|
36
|
+
flexDirection: 'row',
|
|
37
|
+
justifyContent: 'space-between',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
},
|
|
40
|
+
landscapeTitle: {
|
|
41
|
+
color: theme?.global.fontColor,
|
|
42
|
+
fontSize: cx(16),
|
|
43
|
+
fontWeight: 'bold',
|
|
44
|
+
},
|
|
45
|
+
landscapeContent: {
|
|
46
|
+
flex: 1,
|
|
47
|
+
},
|
|
48
|
+
normalScreenIcon: {
|
|
49
|
+
width: cx(50),
|
|
50
|
+
height: cx(50),
|
|
51
|
+
tintColor: theme?.icon.normal
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Common Styles
|
|
55
|
+
listEmptyView: {
|
|
56
|
+
alignItems: 'center',
|
|
57
|
+
},
|
|
58
|
+
listEmptyImage: {
|
|
59
|
+
width: cx(180),
|
|
60
|
+
height: cx(180),
|
|
61
|
+
},
|
|
62
|
+
listEmptyText: {
|
|
63
|
+
flex: 0,
|
|
64
|
+
},
|
|
65
|
+
headlineContainer: {
|
|
66
|
+
width: '100%',
|
|
67
|
+
flexDirection: 'row'
|
|
68
|
+
},
|
|
69
|
+
dateSwitch: {
|
|
70
|
+
flex: 1,
|
|
71
|
+
},
|
|
72
|
+
downloadButton: {
|
|
73
|
+
width: cx(30),
|
|
74
|
+
},
|
|
75
|
+
downloadIcon: {
|
|
76
|
+
width: cx(24),
|
|
77
|
+
height: cx(24),
|
|
78
|
+
tintColor: theme?.global.brand,
|
|
79
|
+
position: 'absolute',
|
|
80
|
+
right: 0,
|
|
81
|
+
top: cx(10),
|
|
82
|
+
},
|
|
83
|
+
})
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { OrientationService } from '@ledvance/base/src/api/OrientationService'
|
|
2
|
+
import { overDays } from '@ledvance/base/src/utils'
|
|
3
|
+
import { loopsText, monthFormat } from '@ledvance/base/src/utils/common'
|
|
4
|
+
import { useReactive, useUpdateEffect } from 'ahooks'
|
|
5
|
+
import dayjs from 'dayjs'
|
|
6
|
+
import { useCallback } from 'react'
|
|
7
|
+
import { DateType } from '../co2Data'
|
|
8
|
+
import { getElectricity } from '../EnergyConsumptionActions'
|
|
9
|
+
import { EnergyConsumptionChartProps } from '../EnergyConsumptionChart'
|
|
10
|
+
|
|
11
|
+
export const useEnergyData = (params: EnergyConsumptionChartProps) => {
|
|
12
|
+
const { addEleDpCode, price, date, over365Days, over7Days, chartData, deviceIdGroup } = params
|
|
13
|
+
|
|
14
|
+
const getDateType = useCallback((d: string) => {
|
|
15
|
+
const datejs = dayjs(d)
|
|
16
|
+
if (datejs.isValid()) {
|
|
17
|
+
if (datejs.format('YYYY') === d) return DateType.Year
|
|
18
|
+
if (datejs.format('YYYYMM') === d) return DateType.Month
|
|
19
|
+
if (datejs.format('YYYY/MM/DD') === d) return DateType.Day
|
|
20
|
+
}
|
|
21
|
+
return DateType.Day
|
|
22
|
+
}, [])
|
|
23
|
+
|
|
24
|
+
const initialDateType = getDateType(date)
|
|
25
|
+
const state = useReactive({
|
|
26
|
+
loading: false,
|
|
27
|
+
isSupportLandscape: OrientationService.isSupported(),
|
|
28
|
+
isLandscape: false,
|
|
29
|
+
dateType: initialDateType,
|
|
30
|
+
date: date,
|
|
31
|
+
headlineText: initialDateType === DateType.Year ? date : params.headlineText,
|
|
32
|
+
chartData: chartData.filter((item) => initialDateType !== DateType.Year || item.headlineText.startsWith(date)),
|
|
33
|
+
price: isNaN(Number(price)) ? 0 : Number(price),
|
|
34
|
+
over365Days: over365Days,
|
|
35
|
+
over7Days: over7Days,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const updateHeadlineText = useCallback((date: dayjs.Dayjs) => {
|
|
39
|
+
const year = date.year().toString();
|
|
40
|
+
const month = (date.month() + 1).toString().padStart(2, '0');
|
|
41
|
+
const day = date.date().toString().padStart(2, '0');
|
|
42
|
+
const dayOfWeek = date.day() % 7;
|
|
43
|
+
switch (state.dateType) {
|
|
44
|
+
case DateType.Year:
|
|
45
|
+
state.headlineText = year;
|
|
46
|
+
break
|
|
47
|
+
case DateType.Month:
|
|
48
|
+
state.headlineText = `${monthFormat(month)} ${year}`;
|
|
49
|
+
break
|
|
50
|
+
case DateType.Day:
|
|
51
|
+
state.headlineText = `${day}.${month}.${year} (${loopsText[dayOfWeek]})`;
|
|
52
|
+
break
|
|
53
|
+
}
|
|
54
|
+
}, [state.dateType])
|
|
55
|
+
|
|
56
|
+
useUpdateEffect(() => {
|
|
57
|
+
state.loading = true
|
|
58
|
+
getElectricity(deviceIdGroup, addEleDpCode, state.date, state.dateType)
|
|
59
|
+
.then((res) => {
|
|
60
|
+
state.chartData = res
|
|
61
|
+
state.loading = false
|
|
62
|
+
})
|
|
63
|
+
.catch(() => {
|
|
64
|
+
state.loading = false
|
|
65
|
+
})
|
|
66
|
+
}, [state.date])
|
|
67
|
+
|
|
68
|
+
useUpdateEffect(() => {
|
|
69
|
+
state.over365Days = overDays(state.date, 365)
|
|
70
|
+
state.over7Days = overDays(state.date, 7)
|
|
71
|
+
updateHeadlineText(dayjs(state.date))
|
|
72
|
+
}, [state.date])
|
|
73
|
+
|
|
74
|
+
useUpdateEffect(() => {
|
|
75
|
+
const d = dayjs()
|
|
76
|
+
const year = d.year().toString()
|
|
77
|
+
const month = (d.month() + 1).toString().padStart(2, '0')
|
|
78
|
+
const day = d.date().toString().padStart(2, '0')
|
|
79
|
+
switch (state.dateType) {
|
|
80
|
+
case DateType.Year:
|
|
81
|
+
state.date = year
|
|
82
|
+
break
|
|
83
|
+
case DateType.Month:
|
|
84
|
+
state.date = `${year}${month}`
|
|
85
|
+
break
|
|
86
|
+
case DateType.Day:
|
|
87
|
+
state.date = `${year}${month}${day}`
|
|
88
|
+
break
|
|
89
|
+
}
|
|
90
|
+
}, [state.dateType])
|
|
91
|
+
|
|
92
|
+
const actions = {
|
|
93
|
+
setDate: useCallback((newDate: string) => {
|
|
94
|
+
state.date = newDate
|
|
95
|
+
}, []),
|
|
96
|
+
setDateType: useCallback((type: DateType) => {
|
|
97
|
+
state.dateType = type
|
|
98
|
+
}, []),
|
|
99
|
+
toggleLandscape: useCallback(() => {
|
|
100
|
+
if (!state.isSupportLandscape) return
|
|
101
|
+
const newIsLandscape = !state.isLandscape
|
|
102
|
+
state.isLandscape = newIsLandscape
|
|
103
|
+
if (newIsLandscape) {
|
|
104
|
+
OrientationService.lockToLandscape()
|
|
105
|
+
} else {
|
|
106
|
+
OrientationService.lockToPortrait()
|
|
107
|
+
}
|
|
108
|
+
}, []),
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return { state, actions }
|
|
112
|
+
}
|
|
@@ -1,27 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { View, StyleSheet, Image, TouchableOpacity } from "react-native";
|
|
3
|
-
import { useRoute } from '@react-navigation/core'
|
|
4
|
-
import Page from "@ledvance/base/src/components/Page";
|
|
5
|
-
import res from "@ledvance/base/src/res";
|
|
6
|
-
import I18n from "@ledvance/base/src/i18n";
|
|
7
|
-
import { Utils } from "tuya-panel-kit";
|
|
8
|
-
import { loopsText, monthFormat } from "@ledvance/base/src/utils/common";
|
|
9
|
-
import { OverviewItem } from "./EnergyConsumptionPage";
|
|
10
|
-
import Spacer from "@ledvance/base/src/components/Spacer";
|
|
11
|
-
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
12
|
-
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
13
|
-
import { overDays } from "@ledvance/base/src/utils/index";
|
|
14
|
-
import dayjs from "dayjs";
|
|
15
|
-
import { DateType } from "./co2Data";
|
|
16
|
-
import { useReactive, useUpdateEffect } from "ahooks";
|
|
17
|
-
import DateTypeItem from "./component/DateTypeItem";
|
|
18
|
-
import DateSelectedItem from "./component/DateSelectedItem";
|
|
19
|
-
import NewBarChart from "./component/NewBarChart";
|
|
20
|
-
import { exportEnergyCsv, getElectricity } from "./EnergyConsumptionActions";
|
|
21
|
-
import DateSwitch from "./component/DateSwitch";
|
|
22
|
-
|
|
23
|
-
const { convertX: cx } = Utils.RatioUtils
|
|
24
|
-
const { withTheme } = Utils.ThemeUtils
|
|
1
|
+
import { OverviewItem } from './EnergyConsumptionPage'
|
|
25
2
|
|
|
26
3
|
export interface EnergyConsumptionChartProps {
|
|
27
4
|
addEleDpCode: string
|
|
@@ -34,191 +11,4 @@ export interface EnergyConsumptionChartProps {
|
|
|
34
11
|
price: string,
|
|
35
12
|
unit: string,
|
|
36
13
|
date: string,
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
|
|
40
|
-
const params = useRoute().params as EnergyConsumptionChartProps
|
|
41
|
-
const { backTitle, price, unit, date, addEleDpCode, deviceIdGroup, over365Days, over7Days } = params;
|
|
42
|
-
|
|
43
|
-
const styles = StyleSheet.create({
|
|
44
|
-
listEmptyView: {
|
|
45
|
-
alignItems: 'center',
|
|
46
|
-
},
|
|
47
|
-
listEmptyImage: {
|
|
48
|
-
width: cx(200),
|
|
49
|
-
height: cx(200),
|
|
50
|
-
},
|
|
51
|
-
listEmptyText: {
|
|
52
|
-
flex: 0
|
|
53
|
-
},
|
|
54
|
-
downloadIcon: {
|
|
55
|
-
width: cx(24),
|
|
56
|
-
height: cx(24),
|
|
57
|
-
tintColor: props.theme?.global.brand,
|
|
58
|
-
position: 'absolute',
|
|
59
|
-
right: 0,
|
|
60
|
-
top: cx(10)
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const getDateType = useCallback((date: string) => {
|
|
65
|
-
const datejs = dayjs(date);
|
|
66
|
-
if (datejs.isValid()) {
|
|
67
|
-
if (datejs.format('YYYY') === date) {
|
|
68
|
-
return DateType.Year;
|
|
69
|
-
} else if (datejs.format('YYYYMM') === date) {
|
|
70
|
-
return DateType.Month;
|
|
71
|
-
} else if (datejs.format('YYYY/MM/DD') === date) {
|
|
72
|
-
return DateType.Day;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return DateType.Day;
|
|
76
|
-
}, []);
|
|
77
|
-
|
|
78
|
-
const dateType = getDateType(date);
|
|
79
|
-
const state = useReactive({
|
|
80
|
-
loading: false,
|
|
81
|
-
dateType: dateType,
|
|
82
|
-
date: date,
|
|
83
|
-
headlineText: dateType === DateType.Year ? date : params.headlineText,
|
|
84
|
-
chartData: params.chartData.filter((item) => {
|
|
85
|
-
return dateType !== DateType.Year || item.headlineText.startsWith(date)
|
|
86
|
-
}),
|
|
87
|
-
price: isNaN(Number(price)) ? 0 : Number(price),
|
|
88
|
-
over365Days: over365Days,
|
|
89
|
-
over7Days: over7Days,
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
useUpdateEffect(() => {
|
|
93
|
-
state.over365Days = overDays(state.date, 365);
|
|
94
|
-
state.over7Days = overDays(state.date, 7);
|
|
95
|
-
updateHeadlineText(dayjs(state.date));
|
|
96
|
-
state.loading = true;
|
|
97
|
-
getElectricity(deviceIdGroup, addEleDpCode, state.date, state.dateType).then((res) => {
|
|
98
|
-
state.chartData = res;
|
|
99
|
-
state.loading = false;
|
|
100
|
-
}).catch(() => {
|
|
101
|
-
state.loading = false;
|
|
102
|
-
});
|
|
103
|
-
}, [state.date]);
|
|
104
|
-
|
|
105
|
-
useUpdateEffect(() => {
|
|
106
|
-
const date = dayjs();
|
|
107
|
-
const year = date.year().toString();
|
|
108
|
-
const month = (date.month() + 1).toString().padStart(2, '0');
|
|
109
|
-
const day = date.date().toString().padStart(2, '0');
|
|
110
|
-
switch (state.dateType) {
|
|
111
|
-
case DateType.Year:
|
|
112
|
-
state.date = year;
|
|
113
|
-
break
|
|
114
|
-
case DateType.Month:
|
|
115
|
-
state.date = `${year}${month}`
|
|
116
|
-
break
|
|
117
|
-
case DateType.Day:
|
|
118
|
-
state.date = `${year}${month}${day}`
|
|
119
|
-
break
|
|
120
|
-
}
|
|
121
|
-
}, [state.dateType]);
|
|
122
|
-
|
|
123
|
-
const updateHeadlineText = useCallback((date: dayjs.Dayjs) => {
|
|
124
|
-
const year = date.year().toString();
|
|
125
|
-
const month = (date.month() + 1).toString().padStart(2, '0');
|
|
126
|
-
const day = date.date().toString().padStart(2, '0');
|
|
127
|
-
const dayOfWeek = date.day() % 7;
|
|
128
|
-
switch (state.dateType) {
|
|
129
|
-
case DateType.Year:
|
|
130
|
-
state.headlineText = year;
|
|
131
|
-
break
|
|
132
|
-
case DateType.Month:
|
|
133
|
-
state.headlineText = `${monthFormat(month)} ${year}`;
|
|
134
|
-
break
|
|
135
|
-
case DateType.Day:
|
|
136
|
-
state.headlineText = `${day}.${month}.${year} (${loopsText[dayOfWeek]})`;
|
|
137
|
-
break
|
|
138
|
-
}
|
|
139
|
-
}, [state.dateType, state.headlineText]);
|
|
140
|
-
|
|
141
|
-
const getEmptyDataTip = useCallback(() => {
|
|
142
|
-
if (state.over365Days && state.dateType !== DateType.Day) {
|
|
143
|
-
return I18n.getLang('energyconsumption_Daylimit')
|
|
144
|
-
}
|
|
145
|
-
if (state.dateType === DateType.Day && state.over7Days) {
|
|
146
|
-
return I18n.getLang('energyconsumption_hourlylimit')
|
|
147
|
-
}
|
|
148
|
-
return I18n.getLang('energyconsumption_emptydata')
|
|
149
|
-
}, [state.dateType, state.over365Days, state.over7Days]);
|
|
150
|
-
|
|
151
|
-
return (
|
|
152
|
-
<Page
|
|
153
|
-
backText={backTitle}
|
|
154
|
-
showGreenery={false}
|
|
155
|
-
greeneryIcon={res.energy_consumption_greenery}
|
|
156
|
-
loading={state.loading}
|
|
157
|
-
headlineContent={
|
|
158
|
-
<View style={{ width: '100%', flexDirection: 'row' }}>
|
|
159
|
-
<DateSwitch
|
|
160
|
-
style={{ flex: 1 }}
|
|
161
|
-
date={state.date}
|
|
162
|
-
dateType={state.dateType}
|
|
163
|
-
headlineText={state.headlineText}
|
|
164
|
-
onDateChange={(date) => {
|
|
165
|
-
state.date = date;
|
|
166
|
-
}} />
|
|
167
|
-
<TouchableOpacity
|
|
168
|
-
style={{ width: cx(30) }}
|
|
169
|
-
onPress={() => {
|
|
170
|
-
const values = state.chartData.map(item => [item.key, item.value, (Number(params.price) * Number(item.value)).toFixed(2)])
|
|
171
|
-
exportEnergyCsv(values, params.unit)
|
|
172
|
-
}}>
|
|
173
|
-
<Image
|
|
174
|
-
style={styles.downloadIcon}
|
|
175
|
-
source={{ uri: state.chartData?.length ? res.download_icon : undefined}} />
|
|
176
|
-
</TouchableOpacity>
|
|
177
|
-
</View>
|
|
178
|
-
}
|
|
179
|
-
>
|
|
180
|
-
<View style={{ marginHorizontal: cx(24) }}>
|
|
181
|
-
<View style={{ flexDirection: 'row' }}>
|
|
182
|
-
<DateTypeItem
|
|
183
|
-
style={{ flex: 1 }}
|
|
184
|
-
dateType={state.dateType}
|
|
185
|
-
onDateTypeChange={(dateType) => {
|
|
186
|
-
state.dateType = dateType;
|
|
187
|
-
}} />
|
|
188
|
-
<DateSelectedItem
|
|
189
|
-
style={{ flex: 1, marginStart: cx(10), marginBottom: cx(15) }}
|
|
190
|
-
dateType={state.dateType}
|
|
191
|
-
date={state.date}
|
|
192
|
-
onDateChange={date => {
|
|
193
|
-
state.date = date;
|
|
194
|
-
}}
|
|
195
|
-
/>
|
|
196
|
-
|
|
197
|
-
</View>
|
|
198
|
-
{
|
|
199
|
-
(state.chartData.length <= 0) ? (
|
|
200
|
-
<View style={styles.listEmptyView}>
|
|
201
|
-
<Spacer height={cx(26)} />
|
|
202
|
-
<Image
|
|
203
|
-
style={styles.listEmptyImage}
|
|
204
|
-
source={{ uri: res.ldv_timer_empty }} />
|
|
205
|
-
<Spacer height={cx(14)} />
|
|
206
|
-
<InfoText
|
|
207
|
-
text={getEmptyDataTip()}
|
|
208
|
-
icon={res.ic_info}
|
|
209
|
-
textStyle={styles.listEmptyText}
|
|
210
|
-
contentColor={props.theme?.global.fontColor}
|
|
211
|
-
/>
|
|
212
|
-
</View>
|
|
213
|
-
) : (
|
|
214
|
-
state.chartData.length > 0 && !state.loading &&
|
|
215
|
-
<NewBarChart height={cx(400)} data={state.chartData} price={state.price}
|
|
216
|
-
unit={unit} />
|
|
217
|
-
)
|
|
218
|
-
}
|
|
219
|
-
</View>
|
|
220
|
-
</Page>
|
|
221
|
-
)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export default withTheme(EnergyConsumptionChart)
|
|
14
|
+
}
|
|
@@ -333,23 +333,6 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
333
333
|
</Text>
|
|
334
334
|
</View>
|
|
335
335
|
<Spacer />
|
|
336
|
-
{/* Today */}
|
|
337
|
-
<Card style={styles.cardContainer}>
|
|
338
|
-
<Text style={styles.cardTitle}>
|
|
339
|
-
{I18n.getLang('consumption_data_field1_headline_text')}
|
|
340
|
-
</Text>
|
|
341
|
-
<Spacer height={cx(15)} />
|
|
342
|
-
<View style={{ flexDirection: 'row', alignItems: 'flex-end' }}>
|
|
343
|
-
<Text style={[styles.consumptionNum, { fontSize: cx(38), marginRight: cx(8) }]}>
|
|
344
|
-
{localeNumber(state.isSolarMode ? state.solarTodayElectricity : state.wifiTodayElectricity)}
|
|
345
|
-
</Text>
|
|
346
|
-
<Text style={[styles.consumptionNum, { fontSize: cx(22), marginBottom: cx(4) }]}>
|
|
347
|
-
kWh
|
|
348
|
-
</Text>
|
|
349
|
-
</View>
|
|
350
|
-
<Spacer height={cx(10)} />
|
|
351
|
-
</Card>
|
|
352
|
-
<Spacer />
|
|
353
336
|
<Card
|
|
354
337
|
style={styles.cardContainer}
|
|
355
338
|
onPress={() => {
|
|
@@ -365,9 +348,17 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
365
348
|
} as EnergyConsumptionChartProps)
|
|
366
349
|
}}
|
|
367
350
|
>
|
|
368
|
-
<
|
|
369
|
-
|
|
370
|
-
|
|
351
|
+
<View style={{
|
|
352
|
+
flexDirection: 'row',
|
|
353
|
+
justifyContent: 'space-between',
|
|
354
|
+
alignItems: 'center',
|
|
355
|
+
}}>
|
|
356
|
+
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field2_headline_text')}</Text>
|
|
357
|
+
<Image
|
|
358
|
+
source={{ uri: res.energy_consumption_chart}}
|
|
359
|
+
style={{ width: cx(16), height: cx(16), marginLeft: cx(8) }}
|
|
360
|
+
/>
|
|
361
|
+
</View>
|
|
371
362
|
<Spacer height={cx(15)} />
|
|
372
363
|
<View style={styles.consumedEnergyContent}>
|
|
373
364
|
<ConsumedEnergyItem
|
|
@@ -383,17 +374,29 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
383
374
|
<Spacer />
|
|
384
375
|
{/* 365 day */}
|
|
385
376
|
<Card style={styles.cardContainer}>
|
|
386
|
-
<
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
377
|
+
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
378
|
+
<View>
|
|
379
|
+
<View style={{height: cx(35), justifyContent: 'center'}}>
|
|
380
|
+
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field1_headline_text')}</Text>
|
|
381
|
+
</View>
|
|
382
|
+
<View style={{height: cx(35), justifyContent: 'center'}}>
|
|
383
|
+
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field3_headline_text')}</Text>
|
|
384
|
+
</View>
|
|
385
|
+
</View>
|
|
386
|
+
<View>
|
|
387
|
+
<View style={{ flexDirection: 'row', alignItems: 'flex-end', marginLeft: cx(10) }}>
|
|
388
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(30), marginRight: cx(8) }]}>
|
|
389
|
+
{localeNumber(state.isSolarMode ? state.solarTodayElectricity : state.wifiTodayElectricity)}
|
|
390
|
+
</Text>
|
|
391
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(20), marginBottom: cx(4) }]}>kWh</Text>
|
|
392
|
+
</View>
|
|
393
|
+
<View style={{ flexDirection: 'row', alignItems: 'flex-end', marginLeft: cx(10) }}>
|
|
394
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(30), marginRight: cx(8) }]}>
|
|
395
|
+
{localeNumber(state.isSolarMode ? state.solarTotalElectricity : state.wifiTotalElectricity)}
|
|
396
|
+
</Text>
|
|
397
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(20), marginBottom: cx(4) }]}>kWh</Text>
|
|
398
|
+
</View>
|
|
399
|
+
</View>
|
|
397
400
|
</View>
|
|
398
401
|
<Spacer />
|
|
399
402
|
{/* CO2 */}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {NavigationRoute} from "tuya-panel-kit";
|
|
2
2
|
import EnergyConsumptionPage from "./EnergyConsumptionPage";
|
|
3
3
|
import EnergyConsumptionDetail from "./EnergyConsumptionDetail";
|
|
4
|
-
import EnergyConsumptionChart from "./EnergyConsumptionChart";
|
|
4
|
+
import EnergyConsumptionChart from "./EnergyConsumptionChart/index";
|
|
5
5
|
import {ui_biz_routerKey} from "../../navigation/Routers";
|
|
6
6
|
|
|
7
7
|
const EnergyConsumptionPageRouters: NavigationRoute[] = [
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import ThemeType from "@ledvance/base/src/config/themeType";
|
|
2
|
-
import React, {PropsWithChildren,
|
|
2
|
+
import React, {PropsWithChildren, useEffect} from "react";
|
|
3
3
|
import {StyleSheet, Text, TouchableOpacity, View, ViewProps} from "react-native";
|
|
4
4
|
import {DatePicker, Modal, Utils} from "tuya-panel-kit";
|
|
5
5
|
import {useReactive} from "ahooks";
|
|
6
6
|
import I18n from "@ledvance/base/src/i18n/index";
|
|
7
7
|
import dayjs from "dayjs";
|
|
8
|
-
import {DateType} from "
|
|
8
|
+
import {DateType} from "../co2Data";
|
|
9
9
|
|
|
10
10
|
const {convertX: cx} = Utils.RatioUtils
|
|
11
11
|
const {withTheme} = Utils.ThemeUtils
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { StyleSheet, View, Text, ViewStyle, Image } from 'react-native'
|
|
1
|
+
import { StyleSheet, View, Text, ViewStyle, Image, TouchableOpacity } from 'react-native'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import Card from '@ledvance/base/src/components/Card'
|
|
4
|
-
import {
|
|
4
|
+
import { Utils } from 'tuya-panel-kit'
|
|
5
5
|
import MoodColorsLine from '@ledvance/base/src/components/MoodColorsLine'
|
|
6
6
|
import Spacer from '@ledvance/base/src/components/Spacer'
|
|
7
7
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
8
|
+
import res from "@ledvance/base/src/res"
|
|
8
9
|
|
|
9
10
|
const cx = Utils.RatioUtils.convertX
|
|
10
11
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -31,6 +32,7 @@ const FlagItem = (props: RecommendMoodItemProps) => {
|
|
|
31
32
|
flexDirection: 'row',
|
|
32
33
|
marginHorizontal: cx(16),
|
|
33
34
|
justifyContent: 'space-between',
|
|
35
|
+
alignItems: 'center',
|
|
34
36
|
},
|
|
35
37
|
headText: {
|
|
36
38
|
color: props.theme?.global.fontColor,
|
|
@@ -39,6 +41,13 @@ const FlagItem = (props: RecommendMoodItemProps) => {
|
|
|
39
41
|
lineHeight: cx(20),
|
|
40
42
|
flex: 1
|
|
41
43
|
},
|
|
44
|
+
checkbox: {
|
|
45
|
+
width: cx(45),
|
|
46
|
+
height: cx(45),
|
|
47
|
+
marginTop: cx(-5),
|
|
48
|
+
marginBottom: cx(-10),
|
|
49
|
+
fontWeight: 'bold',
|
|
50
|
+
},
|
|
42
51
|
gradientItem: {
|
|
43
52
|
alignItems: 'center',
|
|
44
53
|
},
|
|
@@ -58,10 +67,9 @@ const FlagItem = (props: RecommendMoodItemProps) => {
|
|
|
58
67
|
{props.title ? <Text style={styles.headText}>{props.title}</Text> : undefined}
|
|
59
68
|
{props.icon ? <Image source={icon} style={{ width: cx(60), aspectRatio: 2.14, marginRight: cx(10) }} /> : undefined}
|
|
60
69
|
</View>
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
onValueChange={props.onSwitch} />
|
|
70
|
+
<TouchableOpacity style={styles.checkbox} onPress={() => props.onSwitch(!props.enable)}>
|
|
71
|
+
<Image source={{ uri: res.ic_check}} width={cx(44)} height={cx(44)} style={[styles.checkbox, { tintColor: props.enable ? props.theme?.icon.primary : props.theme?.icon.disable}]} />
|
|
72
|
+
</TouchableOpacity>
|
|
65
73
|
</View>
|
|
66
74
|
<Spacer />
|
|
67
75
|
<View style={styles.gradientItem}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
-
import { StyleSheet, Text, View, ViewProps, ViewStyle, Image } from 'react-native';
|
|
3
|
-
import {
|
|
2
|
+
import { StyleSheet, Text, View, ViewProps, ViewStyle, Image, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { Utils } from 'tuya-panel-kit';
|
|
4
4
|
import { hsv2Hex } from '@ledvance/base/src/utils';
|
|
5
5
|
import { cctToColor } from '@ledvance/base/src/utils/cctUtils';
|
|
6
6
|
import { mapFloatToRange } from '@ledvance/base/src/utils';
|
|
@@ -50,6 +50,7 @@ const MoodItem = (props: MoodItemProps) => {
|
|
|
50
50
|
headline: {
|
|
51
51
|
flexDirection: 'row',
|
|
52
52
|
marginHorizontal: cx(16),
|
|
53
|
+
alignItems: 'center',
|
|
53
54
|
},
|
|
54
55
|
headText: {
|
|
55
56
|
flex: 1,
|
|
@@ -58,6 +59,13 @@ const MoodItem = (props: MoodItemProps) => {
|
|
|
58
59
|
fontFamily: 'helvetica_neue_lt_std_bd',
|
|
59
60
|
lineHeight: cx(20),
|
|
60
61
|
},
|
|
62
|
+
checkbox: {
|
|
63
|
+
width: cx(45),
|
|
64
|
+
height: cx(45),
|
|
65
|
+
marginTop: cx(-5),
|
|
66
|
+
marginBottom: cx(-10),
|
|
67
|
+
fontWeight: 'bold',
|
|
68
|
+
},
|
|
61
69
|
moodTypeItem: {
|
|
62
70
|
flexDirection: 'row',
|
|
63
71
|
},
|
|
@@ -83,11 +91,9 @@ const MoodItem = (props: MoodItemProps) => {
|
|
|
83
91
|
<Spacer height={cx(16)} />
|
|
84
92
|
<View style={styles.headline}>
|
|
85
93
|
<Text style={styles.headText}>{mood.name}</Text>
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
onValueChange={props.onSwitch}
|
|
90
|
-
/>
|
|
94
|
+
<TouchableOpacity style={styles.checkbox} onPress={() => props.onSwitch(!props.enable)}>
|
|
95
|
+
<Image source={{ uri: res.ic_check}} width={cx(44)} height={cx(44)} style={[styles.checkbox, { tintColor: props.enable ? props.theme?.icon.primary : props.theme?.icon.disable}]} />
|
|
96
|
+
</TouchableOpacity>
|
|
91
97
|
</View>
|
|
92
98
|
<Spacer />
|
|
93
99
|
<MixMoodColorsLine mixSubLight={mood.mainLamp} isMix={isMix} type={mood.mainLamp.mode === gradientMode ? 'gradient' : 'separate'}/>
|