@widergy/utilitygo-smart-bill-mobile 1.1.1 → 1.1.2
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 +1 -1
- package/src/lib/components/BillCalculation/components/DetailModalContent/index.js +85 -0
- package/src/lib/components/BillCalculation/components/DetailModalContent/styles.js +64 -0
- package/src/lib/components/BillCalculation/index.js +31 -13
- package/src/lib/components/BillCalculation/styles.js +13 -1
- package/src/lib/components/MainBillData/components/MeasurementInfo/index.js +3 -1
- package/src/lib/components/MainBillData/components/MeasurementInfo/utils.js +7 -0
- package/src/lib/components/MainBillData/components/OwnerData/index.js +5 -6
- package/src/lib/components/MainBillData/components/OwnerData/utils.js +2 -1
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/components/RateStagesGraph/components/Bars/components/Stage/components/SubStage/index.js +23 -16
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/components/RateStagesGraph/components/Bars/components/Stage/index.js +53 -13
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/components/RateStagesGraph/components/Bars/components/Stage/styles.js +9 -7
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/components/RateStagesGraph/components/Bars/index.js +20 -7
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/components/RateStagesGraph/components/Bars/styles.js +1 -1
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/components/RateStagesGraph/constants.js +1 -1
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/components/RateStagesGraph/styles.js +1 -0
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/index.js +32 -42
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/styles.js +5 -1
- package/src/lib/components/RatesDefinition/components/CategoryByConsumption/utils.js +5 -15
package/package.json
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import Collapsible from 'react-native-collapsible';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { shape, number, string, arrayOf, func } from 'prop-types';
|
|
5
|
+
|
|
6
|
+
import getStyles, { ICON_SIZE } from './styles';
|
|
7
|
+
|
|
8
|
+
const DetailModalContent = ({ onCloseModal, concepts, context }) => {
|
|
9
|
+
const {
|
|
10
|
+
Touchable,
|
|
11
|
+
Label,
|
|
12
|
+
assets: { ArrowDown, ArrowUp },
|
|
13
|
+
config: {
|
|
14
|
+
texts: {
|
|
15
|
+
mainBillData: { conceptsDetailsModalHeader },
|
|
16
|
+
commons: { close },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
} = context;
|
|
20
|
+
const [openedItem, setOpenedItem] = useState();
|
|
21
|
+
|
|
22
|
+
const styles = getStyles(context.theme, context.theme.colors);
|
|
23
|
+
return (
|
|
24
|
+
<View style={styles.upperContainer}>
|
|
25
|
+
<View style={styles.header}>
|
|
26
|
+
<Label center white h5>
|
|
27
|
+
{conceptsDetailsModalHeader}
|
|
28
|
+
</Label>
|
|
29
|
+
</View>
|
|
30
|
+
{concepts.map(concept => (
|
|
31
|
+
<Touchable
|
|
32
|
+
onPress={() => {
|
|
33
|
+
setOpenedItem(concept.title === openedItem ? '' : concept.title);
|
|
34
|
+
}}
|
|
35
|
+
borderless>
|
|
36
|
+
<View style={styles.container}>
|
|
37
|
+
<View style={styles.conceptContainer}>
|
|
38
|
+
<Label h5 semibold style={styles.conceptTitleLabel}>
|
|
39
|
+
{`${concept?.title}`}
|
|
40
|
+
</Label>
|
|
41
|
+
<View style={styles.totalContainer}>
|
|
42
|
+
<View style={styles.iconContainer}>
|
|
43
|
+
{openedItem !== concept.title ? (
|
|
44
|
+
<ArrowDown height={ICON_SIZE} width={ICON_SIZE} style={styles.icon} />
|
|
45
|
+
) : (
|
|
46
|
+
<ArrowUp height={ICON_SIZE} width={ICON_SIZE} style={styles.icon} />
|
|
47
|
+
)}
|
|
48
|
+
</View>
|
|
49
|
+
</View>
|
|
50
|
+
</View>
|
|
51
|
+
<Collapsible collapsed={openedItem !== concept.title}>
|
|
52
|
+
<View style={styles.linesContainer}>
|
|
53
|
+
<Label>{concept.description}</Label>
|
|
54
|
+
</View>
|
|
55
|
+
</Collapsible>
|
|
56
|
+
</View>
|
|
57
|
+
</Touchable>
|
|
58
|
+
))}
|
|
59
|
+
<Touchable onPress={onCloseModal} borderless style={styles.closeButton}>
|
|
60
|
+
<Label semibold white center h5 style={styles.buttonLabel}>
|
|
61
|
+
{close}
|
|
62
|
+
</Label>
|
|
63
|
+
</Touchable>
|
|
64
|
+
</View>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
DetailModalContent.propTypes = {
|
|
69
|
+
concepts: arrayOf(
|
|
70
|
+
shape({
|
|
71
|
+
title: string,
|
|
72
|
+
total: number,
|
|
73
|
+
lines: arrayOf(
|
|
74
|
+
shape({
|
|
75
|
+
title: string,
|
|
76
|
+
description: string,
|
|
77
|
+
amount: number,
|
|
78
|
+
}),
|
|
79
|
+
),
|
|
80
|
+
}),
|
|
81
|
+
),
|
|
82
|
+
onCloseModal: func,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default DetailModalContent;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const ICON_SIZE = 10;
|
|
4
|
+
const ICON_MARGIN = 5;
|
|
5
|
+
export default theme =>
|
|
6
|
+
StyleSheet.create({
|
|
7
|
+
upperContainer: {},
|
|
8
|
+
icon: {
|
|
9
|
+
top: 1,
|
|
10
|
+
},
|
|
11
|
+
header: {
|
|
12
|
+
paddingHorizontal: 20,
|
|
13
|
+
paddingVertical: 16,
|
|
14
|
+
backgroundColor: theme.BillCalculation?.detailModal?.header,
|
|
15
|
+
width: '100%',
|
|
16
|
+
},
|
|
17
|
+
conceptContainer: {
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
flexDirection: 'row',
|
|
20
|
+
justifyContent: 'space-between',
|
|
21
|
+
width: '100%',
|
|
22
|
+
borderBottomColor: theme.BillCalculation?.detailModal?.border,
|
|
23
|
+
borderBottomWidth: 1,
|
|
24
|
+
paddingHorizontal: 18,
|
|
25
|
+
paddingVertical: 18,
|
|
26
|
+
},
|
|
27
|
+
totalContainer: {
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
flexDirection: 'row',
|
|
30
|
+
flex: 1,
|
|
31
|
+
justifyContent: 'flex-end',
|
|
32
|
+
},
|
|
33
|
+
collapsable: {
|
|
34
|
+
paddingRight: ICON_SIZE + ICON_MARGIN,
|
|
35
|
+
},
|
|
36
|
+
decimal: {
|
|
37
|
+
marginTop: 0,
|
|
38
|
+
},
|
|
39
|
+
linesContainer: {
|
|
40
|
+
flexDirection: 'row',
|
|
41
|
+
flex: 1,
|
|
42
|
+
justifyContent: 'space-between',
|
|
43
|
+
paddingHorizontal: 15,
|
|
44
|
+
},
|
|
45
|
+
conceptTitleLabel: {
|
|
46
|
+
width: '90%',
|
|
47
|
+
textAlign: 'left',
|
|
48
|
+
},
|
|
49
|
+
iconContainer: {
|
|
50
|
+
marginLeft: 5,
|
|
51
|
+
},
|
|
52
|
+
linesConcept: {
|
|
53
|
+
flex: 1,
|
|
54
|
+
},
|
|
55
|
+
lineTitle: { flex: 1 },
|
|
56
|
+
closeButton: {
|
|
57
|
+
paddingVertical: 12,
|
|
58
|
+
paddingHorizontal: 28,
|
|
59
|
+
backgroundColor: theme.BillCalculation?.detailModal?.closeButton,
|
|
60
|
+
borderRadius: 4,
|
|
61
|
+
marginTop: 20,
|
|
62
|
+
alignSelf: 'center',
|
|
63
|
+
},
|
|
64
|
+
});
|
|
@@ -1,43 +1,48 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import { View, FlatList } from 'react-native';
|
|
3
|
-
import { SeparatorBar } from '@widergy/mobile-ui';
|
|
4
|
-
import { string, shape } from 'prop-types';
|
|
3
|
+
import { Modal, SeparatorBar } from '@widergy/mobile-ui';
|
|
5
4
|
|
|
6
5
|
import { billDataTypes } from '../../types/billDataTypes';
|
|
7
6
|
import { titleMapper } from '../../utils/billCalculation';
|
|
8
7
|
import NumberWithSuperIndex from '../NumberWithSuperIndex';
|
|
9
8
|
import withContext from '../../hocs/withContext';
|
|
10
9
|
import { formatInterval } from '../ConsumptionComparison/components/ComparisonTable/utils';
|
|
11
|
-
import { useSmartBill } from '../../Context';
|
|
10
|
+
import { useSmartBill, useThemedStyle } from '../../Context';
|
|
12
11
|
|
|
13
12
|
import ConceptCard from './components/ConceptCard';
|
|
14
13
|
import getStyles from './styles';
|
|
14
|
+
import DetailModalContent from './components/DetailModalContent';
|
|
15
15
|
|
|
16
|
-
const BillCalculation = ({ bill, context
|
|
16
|
+
const BillCalculation = ({ bill, context }) => {
|
|
17
|
+
const [detailModalMopen, setDetailModalOpen] = useState(false);
|
|
17
18
|
const { config } = useSmartBill();
|
|
18
19
|
const {
|
|
19
20
|
Label,
|
|
20
|
-
|
|
21
|
+
Touchable,
|
|
22
|
+
config: { texts },
|
|
21
23
|
} = context;
|
|
22
24
|
const {
|
|
23
25
|
texts: {
|
|
24
|
-
mainBillData: { billedPeriod },
|
|
26
|
+
mainBillData: { billedPeriod, conceptsDetailsButton },
|
|
25
27
|
},
|
|
26
28
|
validators: { showPeriodWithMonth },
|
|
27
29
|
} = config;
|
|
28
|
-
const styles = getStyles
|
|
30
|
+
const styles = useThemedStyle(getStyles);
|
|
29
31
|
const { periodicity, periodNumber, currentSettlement, totalSettlements, periodYear } = titleMapper(
|
|
30
32
|
bill,
|
|
31
33
|
texts,
|
|
32
34
|
);
|
|
33
35
|
const { periods } = bill;
|
|
34
36
|
const currentPeriod = periods.find(period => period.current);
|
|
35
|
-
const
|
|
36
|
-
? bill?.detail
|
|
37
|
-
: bill?.detail?.concepts?.filter(concept => concept.total);
|
|
37
|
+
const conceptsToRender = bill?.detail?.concepts?.filter(concept => concept.total);
|
|
38
38
|
const totalSettlementsIsOne = totalSettlements === 1;
|
|
39
39
|
const { number, year } = currentPeriod || {};
|
|
40
40
|
const showPeriodWithMonthLabel = showPeriodWithMonth(bill);
|
|
41
|
+
const conceptsToRenderOnModal = bill?.detail?.concepts?.filter(concept => concept?.description);
|
|
42
|
+
|
|
43
|
+
const openDetailModal = () => setDetailModalOpen(true);
|
|
44
|
+
const closeDetailModal = () => setDetailModalOpen(false);
|
|
45
|
+
|
|
41
46
|
return (
|
|
42
47
|
<View styles={styles.container}>
|
|
43
48
|
<View style={styles.upperContainer}>
|
|
@@ -64,7 +69,7 @@ const BillCalculation = ({ bill, context, colors }) => {
|
|
|
64
69
|
</View>
|
|
65
70
|
<FlatList
|
|
66
71
|
renderItem={({ item }) => <ConceptCard concept={item} />}
|
|
67
|
-
data={
|
|
72
|
+
data={conceptsToRender}
|
|
68
73
|
scrollEnabled={false}
|
|
69
74
|
keyExtractor={item => item.title}
|
|
70
75
|
showsVerticalScrollIndicator={false}
|
|
@@ -84,11 +89,24 @@ const BillCalculation = ({ bill, context, colors }) => {
|
|
|
84
89
|
{bill?.detail?.total_amount}
|
|
85
90
|
</NumberWithSuperIndex>
|
|
86
91
|
</View>
|
|
92
|
+
{conceptsToRenderOnModal.length >= 1 && (
|
|
93
|
+
<Touchable onPress={openDetailModal} borderless style={styles.openButton}>
|
|
94
|
+
<Label semibold white center h5 style={styles.buttonLabel}>
|
|
95
|
+
{conceptsDetailsButton}
|
|
96
|
+
</Label>
|
|
97
|
+
</Touchable>
|
|
98
|
+
)}
|
|
99
|
+
<Modal visible={detailModalMopen} style={styles.modal}>
|
|
100
|
+
<DetailModalContent
|
|
101
|
+
concepts={conceptsToRenderOnModal}
|
|
102
|
+
onCloseModal={closeDetailModal}
|
|
103
|
+
context={context}
|
|
104
|
+
/>
|
|
105
|
+
</Modal>
|
|
87
106
|
</View>
|
|
88
107
|
);
|
|
89
108
|
};
|
|
90
109
|
BillCalculation.propTypes = {
|
|
91
110
|
bill: billDataTypes,
|
|
92
|
-
colors: shape(string),
|
|
93
111
|
};
|
|
94
112
|
export default withContext()(BillCalculation);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
|
-
export default colors =>
|
|
3
|
+
export default (theme, colors) =>
|
|
4
4
|
StyleSheet.create({
|
|
5
5
|
container: {
|
|
6
6
|
width: '100%',
|
|
@@ -13,6 +13,10 @@ export default colors =>
|
|
|
13
13
|
decimal: {
|
|
14
14
|
marginTop: 0,
|
|
15
15
|
},
|
|
16
|
+
modal: {
|
|
17
|
+
paddingHorizontal: 0,
|
|
18
|
+
paddingVertical: 0,
|
|
19
|
+
},
|
|
16
20
|
upperContainer: {
|
|
17
21
|
marginTop: 10,
|
|
18
22
|
borderWidth: 1,
|
|
@@ -55,4 +59,12 @@ export default colors =>
|
|
|
55
59
|
headerTitle: {
|
|
56
60
|
fontWeight: '600',
|
|
57
61
|
},
|
|
62
|
+
openButton: {
|
|
63
|
+
padding: 12,
|
|
64
|
+
backgroundColor: theme.BillCalculation?.detailModal?.closeButton,
|
|
65
|
+
width: '100%',
|
|
66
|
+
borderRadius: 4,
|
|
67
|
+
marginTop: 20,
|
|
68
|
+
alignSelf: 'center',
|
|
69
|
+
},
|
|
58
70
|
});
|
|
@@ -20,7 +20,8 @@ const MeasurementInfo = ({ bill }) => {
|
|
|
20
20
|
const {
|
|
21
21
|
config: {
|
|
22
22
|
texts: { mainBillData },
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
validators: { showTransformationCenter, showFeederLine, showSupplyTitle, showNisNumber },
|
|
24
25
|
},
|
|
25
26
|
assets,
|
|
26
27
|
} = useSmartBill();
|
|
@@ -34,6 +35,7 @@ const MeasurementInfo = ({ bill }) => {
|
|
|
34
35
|
readinType,
|
|
35
36
|
showTransformationCenter(bill),
|
|
36
37
|
showFeederLine(bill),
|
|
38
|
+
showNisNumber(bill),
|
|
37
39
|
);
|
|
38
40
|
|
|
39
41
|
return (
|
|
@@ -6,6 +6,7 @@ export const measurementInfoMapper = (
|
|
|
6
6
|
readinType,
|
|
7
7
|
showTransformationCenter,
|
|
8
8
|
showFeederLine,
|
|
9
|
+
showNisNumber,
|
|
9
10
|
) =>
|
|
10
11
|
[
|
|
11
12
|
{
|
|
@@ -20,6 +21,12 @@ export const measurementInfoMapper = (
|
|
|
20
21
|
secondaryText: texts.readingType,
|
|
21
22
|
show: true,
|
|
22
23
|
},
|
|
24
|
+
{
|
|
25
|
+
Icon: assets.AccountIcon,
|
|
26
|
+
mainText: client.client_number,
|
|
27
|
+
secondaryText: texts.clientNumber,
|
|
28
|
+
show: showNisNumber,
|
|
29
|
+
},
|
|
23
30
|
{
|
|
24
31
|
Icon: assets.FeederLineIcon,
|
|
25
32
|
mainText: client?.transformation_center,
|
|
@@ -16,17 +16,16 @@ const OwnerData = ({ context, bill, theme }) => {
|
|
|
16
16
|
config: {
|
|
17
17
|
texts: { mainBillData },
|
|
18
18
|
formatters,
|
|
19
|
+
validators: { showNisNumber },
|
|
19
20
|
},
|
|
20
21
|
} = context;
|
|
21
22
|
|
|
22
23
|
const { client } = bill;
|
|
23
24
|
|
|
24
|
-
const ownerDataToRender = useMemo(
|
|
25
|
-
client,
|
|
26
|
-
assets,
|
|
27
|
-
|
|
28
|
-
formatters,
|
|
29
|
-
]);
|
|
25
|
+
const ownerDataToRender = useMemo(
|
|
26
|
+
() => ownerDataToShow(client, assets, mainBillData, formatters, showNisNumber(bill)),
|
|
27
|
+
[client, assets, mainBillData, formatters, showNisNumber, bill],
|
|
28
|
+
);
|
|
30
29
|
return (
|
|
31
30
|
<View style={[styles.root, theme.root]}>
|
|
32
31
|
<Label bold style={styles.clientDataTitle} useMarkdown={false}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const ownerDataToShow = (client, assets, texts, formatters) =>
|
|
1
|
+
export const ownerDataToShow = (client, assets, texts, formatters, showNisNumber) =>
|
|
2
2
|
[
|
|
3
3
|
{
|
|
4
4
|
Icon: assets.LocationIcon,
|
|
@@ -22,6 +22,7 @@ export const ownerDataToShow = (client, assets, texts, formatters) =>
|
|
|
22
22
|
secondaryText: texts.clientNumber,
|
|
23
23
|
tooltipMessage: texts.clientNumberTooltip,
|
|
24
24
|
mainTextProps: { semibold: false, bold: true },
|
|
25
|
+
show: () => !showNisNumber,
|
|
25
26
|
},
|
|
26
27
|
{
|
|
27
28
|
Icon: assets.AccountIcon,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { bool, string } from 'prop-types';
|
|
2
|
+
import { bool, string, number, func } from 'prop-types';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
4
|
import { Label } from '@widergy/mobile-ui';
|
|
5
5
|
|
|
@@ -8,26 +8,33 @@ import { SUB_STAGE_MARGIN, LAST_SUB_STAGE_MARGIN } from '../../../../../../const
|
|
|
8
8
|
|
|
9
9
|
import styles from './styles';
|
|
10
10
|
|
|
11
|
-
const SubStage = ({ subStage, isLast, label }) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
const SubStage = ({ subStage, isLast, label, index, getStageColor, totalSubStages, subStages }) => {
|
|
12
|
+
const margin = isLast ? LAST_SUB_STAGE_MARGIN : SUB_STAGE_MARGIN;
|
|
13
|
+
return (
|
|
14
|
+
<View
|
|
15
|
+
style={[
|
|
16
|
+
{
|
|
17
|
+
backgroundColor: subStage.color ?? getStageColor(index, totalSubStages),
|
|
18
|
+
width: `${100 / subStages - margin}%`,
|
|
19
|
+
marginRight: `${margin}%`,
|
|
20
|
+
},
|
|
21
|
+
styles.container,
|
|
22
|
+
]}>
|
|
23
|
+
<Label h6 semibold>
|
|
24
|
+
{label}
|
|
25
|
+
</Label>
|
|
26
|
+
</View>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
26
29
|
|
|
27
30
|
SubStage.propTypes = {
|
|
28
31
|
subStage: subStageType,
|
|
29
32
|
isLast: bool,
|
|
30
33
|
label: string,
|
|
34
|
+
index: number,
|
|
35
|
+
getStageColor: func,
|
|
36
|
+
totalSubStages: number,
|
|
37
|
+
subStages: number,
|
|
31
38
|
};
|
|
32
39
|
|
|
33
40
|
export default SubStage;
|
|
@@ -1,39 +1,79 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { number } from 'prop-types';
|
|
2
|
+
import { number, arrayOf } from 'prop-types';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
|
+
import _ from 'lodash';
|
|
4
5
|
|
|
5
6
|
import { contextApiInfoTypes } from '../../../../../../../../../../types/smartBillTypes';
|
|
6
7
|
import { stageType } from '../../../../../../../../../../types/rateStagesTypes';
|
|
7
8
|
import withContext from '../../../../../../../../../../hocs/withContext';
|
|
8
9
|
import { useThemedStyle } from '../../../../../../../../../../Context';
|
|
9
10
|
|
|
10
|
-
import LimitsLine from './components/LimitsLine';
|
|
11
11
|
import SubStage from './components/SubStage';
|
|
12
|
-
import getStyles from './styles';
|
|
12
|
+
import getStyles, { MIN_STAGE_WIDTH } from './styles';
|
|
13
13
|
|
|
14
|
-
const Stage = ({ context, stage,
|
|
15
|
-
const {
|
|
14
|
+
const Stage = ({ context, stage, rateStages, totalSubStages }) => {
|
|
15
|
+
const {
|
|
16
|
+
Label,
|
|
17
|
+
config: { getStageColor },
|
|
18
|
+
} = context;
|
|
19
|
+
const totalStages = rateStages.length;
|
|
16
20
|
|
|
17
|
-
const
|
|
21
|
+
const getStageWidth = () => {
|
|
22
|
+
let totalWidth = 100;
|
|
23
|
+
|
|
24
|
+
// if we have only one rate, then return max width.
|
|
25
|
+
if (rateStages.length === 1) {
|
|
26
|
+
return totalWidth;
|
|
27
|
+
}
|
|
28
|
+
// We sort the stages based in sub stages in cases that former stages are larger than later ones.
|
|
29
|
+
const sortedRateStages = _.sortBy(rateStages, _stage => _stage.sub_rate_stages.length);
|
|
30
|
+
|
|
31
|
+
// Iterate over the sorted array until finished.
|
|
32
|
+
for (let index = 0; index < sortedRateStages.length; index += 1) {
|
|
33
|
+
// If we reached our stage then we break, we need to know the space former ones ocuppy and not the laters.
|
|
34
|
+
if (sortedRateStages[index].group === stage.group) {
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
const currentSubStages = sortedRateStages[index].sub_rate_stages.length;
|
|
38
|
+
|
|
39
|
+
// Maximum a stage can ocuppy (since minimum is MIN_STAGE_WIDTH), is MIN_STAGE_WIDTH times the other stages.
|
|
40
|
+
const width = Math.min(
|
|
41
|
+
Math.max((100 * currentSubStages) / totalSubStages, MIN_STAGE_WIDTH),
|
|
42
|
+
MIN_STAGE_WIDTH * rateStages.length,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
totalWidth -= width;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Final width will be the minimum value between the calculated width and the total width left.
|
|
49
|
+
return Math.min(
|
|
50
|
+
Math.max((100 * stage.sub_rate_stages.length) / totalSubStages, MIN_STAGE_WIDTH),
|
|
51
|
+
totalWidth,
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const subStages = stage.sub_rate_stages.length;
|
|
56
|
+
const stageWidth = getStageWidth();
|
|
18
57
|
|
|
19
58
|
const styles = useThemedStyle(getStyles);
|
|
20
59
|
return (
|
|
21
|
-
<View style={[{
|
|
60
|
+
<View style={[{ width: `${stageWidth}%` }, styles.container]}>
|
|
22
61
|
{totalStages !== 1 && (
|
|
23
62
|
<View style={styles.label}>
|
|
24
63
|
<View style={styles.rateLabelContainer}>
|
|
25
|
-
<Label
|
|
26
|
-
{subStageIndex}
|
|
27
|
-
</Label>
|
|
64
|
+
<Label small>{stage.group}</Label>
|
|
28
65
|
</View>
|
|
29
66
|
</View>
|
|
30
67
|
)}
|
|
31
|
-
<LimitsLine />
|
|
32
68
|
<View style={styles.bars}>
|
|
33
69
|
{stage.sub_rate_stages.map((subStage, index) => (
|
|
34
70
|
<SubStage
|
|
35
71
|
key={subStage.category}
|
|
72
|
+
totalSubStages={totalSubStages}
|
|
73
|
+
getStageColor={getStageColor}
|
|
36
74
|
stage={stage}
|
|
75
|
+
subStages={subStages}
|
|
76
|
+
index={index}
|
|
37
77
|
subStage={subStage}
|
|
38
78
|
isLast={index === stage.sub_rate_stages.length - 1}
|
|
39
79
|
label={subStage.name}
|
|
@@ -47,8 +87,8 @@ const Stage = ({ context, stage, totalStages, subStageIndex }) => {
|
|
|
47
87
|
Stage.propTypes = {
|
|
48
88
|
context: contextApiInfoTypes,
|
|
49
89
|
stage: stageType,
|
|
50
|
-
|
|
51
|
-
|
|
90
|
+
totalSubStages: number,
|
|
91
|
+
rateStages: arrayOf(stageType),
|
|
52
92
|
};
|
|
53
93
|
|
|
54
94
|
export default withContext()(Stage);
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
|
+
export const MIN_STAGE_WIDTH = 20;
|
|
4
|
+
|
|
3
5
|
export default theme =>
|
|
4
6
|
StyleSheet.create({
|
|
5
|
-
container: {
|
|
6
|
-
flex: 1,
|
|
7
|
-
},
|
|
8
7
|
bars: {
|
|
9
8
|
flexDirection: 'row',
|
|
10
9
|
flex: 1,
|
|
11
|
-
marginTop:
|
|
10
|
+
marginTop: 6,
|
|
12
11
|
},
|
|
13
12
|
label: {
|
|
14
13
|
alignItems: 'center',
|
|
@@ -16,10 +15,13 @@ export default theme =>
|
|
|
16
15
|
},
|
|
17
16
|
rateLabelContainer: {
|
|
18
17
|
backgroundColor: theme.RateAndCategory.rateLabelBackground,
|
|
19
|
-
borderRadius: 50,
|
|
20
18
|
paddingHorizontal: 9,
|
|
21
|
-
paddingVertical:
|
|
19
|
+
paddingVertical: 8,
|
|
20
|
+
width: '100%',
|
|
21
|
+
alignItems: 'center',
|
|
22
22
|
alignContent: 'center',
|
|
23
|
-
|
|
23
|
+
},
|
|
24
|
+
container: {
|
|
25
|
+
marginRight: 2,
|
|
24
26
|
},
|
|
25
27
|
});
|
|
@@ -6,13 +6,26 @@ import { rateStagesTypes } from '../../../../../../../../types/rateStagesTypes';
|
|
|
6
6
|
import Stage from './components/Stage';
|
|
7
7
|
import styles from './styles';
|
|
8
8
|
|
|
9
|
-
const Bars = ({ rateStages }) =>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
const Bars = ({ rateStages }) => {
|
|
10
|
+
const totalSubStages = rateStages.reduce(
|
|
11
|
+
(previous, current) => previous + current.sub_rate_stages.length,
|
|
12
|
+
0,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<View style={styles.container}>
|
|
17
|
+
{rateStages.map((stage, index) => (
|
|
18
|
+
<Stage
|
|
19
|
+
key={stage.group}
|
|
20
|
+
stage={stage}
|
|
21
|
+
rateStages={rateStages}
|
|
22
|
+
totalSubStages={totalSubStages}
|
|
23
|
+
subStageIndex={index}
|
|
24
|
+
/>
|
|
25
|
+
))}
|
|
26
|
+
</View>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
16
29
|
|
|
17
30
|
Bars.propTypes = {
|
|
18
31
|
rateStages: rateStagesTypes,
|
|
@@ -8,5 +8,5 @@ export const INITIAL_INDICATOR_POSITION = -5;
|
|
|
8
8
|
export const BARS_MARGIN = 0;
|
|
9
9
|
export const LAST_STAGE_MARGIN = 0;
|
|
10
10
|
export const STAGE_MARGIN = 1;
|
|
11
|
-
export const SUB_STAGE_MARGIN =
|
|
11
|
+
export const SUB_STAGE_MARGIN = 0.5;
|
|
12
12
|
export const LAST_SUB_STAGE_MARGIN = 0;
|
|
@@ -5,56 +5,46 @@ import { View } from 'react-native';
|
|
|
5
5
|
import { contextApiInfoTypes } from '../../../../types/smartBillTypes';
|
|
6
6
|
import withContext from '../../../../hocs/withContext';
|
|
7
7
|
import CategoryLabel from '../../../CategoryLabel';
|
|
8
|
-
import Magnitude from '../../../Magnitude';
|
|
9
|
-
import { MAX_VALUE, MIN_VALUE } from '../../../../constants/stagesGraph';
|
|
10
8
|
import { useThemedStyle } from '../../../../Context';
|
|
9
|
+
import Magnitude from '../../../Magnitude';
|
|
11
10
|
|
|
12
11
|
import RateStagesGraph from './components/RateStagesGraph';
|
|
13
12
|
import getStyles from './styles';
|
|
14
|
-
import {
|
|
13
|
+
import { MAX_VALUE, MIN_VALUE } from './components/RateStagesGraph/constants';
|
|
14
|
+
import { getSubRateStages } from './utils';
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
const { config, Label
|
|
18
|
-
const { rateStages, texts
|
|
19
|
-
const { consumptionUpTo,
|
|
16
|
+
const CategoryByConsumption = ({ context, value, unit, category, rate }) => {
|
|
17
|
+
const { config, Label } = context;
|
|
18
|
+
const { rateStages, texts } = config;
|
|
19
|
+
const { consumptionUpTo, consumptionMoreThan } = config.texts.ratesDefinition;
|
|
20
20
|
|
|
21
21
|
const valueCorrected = value < 0 ? 0 : value && Math.round(value);
|
|
22
22
|
|
|
23
|
-
const formattedRateStages = getStageColor ? formatRateStages(rateStages, getStageColor) : rateStages;
|
|
24
|
-
|
|
25
23
|
const styles = useThemedStyle(getStyles);
|
|
26
24
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
</View>
|
|
36
|
-
<Label h6>{description}</Label>
|
|
37
|
-
</View>
|
|
38
|
-
<View style={styles.magnitude}>
|
|
39
|
-
<Magnitude
|
|
40
|
-
semibold
|
|
41
|
-
medium
|
|
42
|
-
unitProps={{ xsmall: false, h6: true }}
|
|
43
|
-
valueProps={{ h4: true }}
|
|
44
|
-
value={
|
|
45
|
-
index === 0
|
|
46
|
-
? formattedRateStages[index].range[MAX_VALUE]
|
|
47
|
-
: formattedRateStages[index].range[MIN_VALUE]
|
|
48
|
-
}
|
|
49
|
-
unity={unit}
|
|
50
|
-
Icon={assets.EnergyIconBlack}
|
|
51
|
-
iconProps={{ color: 'red', fill: 'red' }}
|
|
52
|
-
style={{ icon: styles.icon }}
|
|
53
|
-
/>
|
|
54
|
-
</View>
|
|
25
|
+
const subRateStages = getSubRateStages(rateStages);
|
|
26
|
+
const categoryDescriptions = subRateStages.map((subStage, index) => (
|
|
27
|
+
<View style={styles.categoryDescriptionContainer}>
|
|
28
|
+
<View style={styles.descriptionLabel}>
|
|
29
|
+
<Label bold h6 style={styles.scale}>
|
|
30
|
+
{index + 1}
|
|
31
|
+
</Label>
|
|
32
|
+
<Label h6>{index === 0 ? consumptionUpTo : consumptionMoreThan}</Label>
|
|
55
33
|
</View>
|
|
56
|
-
|
|
57
|
-
|
|
34
|
+
<View style={styles.magnitude}>
|
|
35
|
+
<Magnitude
|
|
36
|
+
semibold
|
|
37
|
+
medium
|
|
38
|
+
unitProps={{ xsmall: false, h6: true }}
|
|
39
|
+
valueProps={{ h4: true }}
|
|
40
|
+
value={index === 0 ? subStage.range[MAX_VALUE] : subStage.range[MIN_VALUE]}
|
|
41
|
+
unity={unit}
|
|
42
|
+
iconProps={{ color: 'red', fill: 'red' }}
|
|
43
|
+
style={{ icon: styles.icon }}
|
|
44
|
+
/>
|
|
45
|
+
</View>
|
|
46
|
+
</View>
|
|
47
|
+
));
|
|
58
48
|
|
|
59
49
|
return (
|
|
60
50
|
<View style={styles.container}>
|
|
@@ -69,7 +59,7 @@ const CategoryBrConsumption = ({ context, value, unit, category, rate }) => {
|
|
|
69
59
|
</Label>
|
|
70
60
|
<CategoryLabel rate={rate} category={category} style={styles.categoryLabel} />
|
|
71
61
|
{(valueCorrected === 0 || valueCorrected) && (
|
|
72
|
-
<RateStagesGraph value={valueCorrected} unit={unit} rateStages={
|
|
62
|
+
<RateStagesGraph value={valueCorrected} unit={unit} rateStages={rateStages} />
|
|
73
63
|
)}
|
|
74
64
|
</View>
|
|
75
65
|
<View style={styles.descriptionsContainer}>
|
|
@@ -79,7 +69,7 @@ const CategoryBrConsumption = ({ context, value, unit, category, rate }) => {
|
|
|
79
69
|
);
|
|
80
70
|
};
|
|
81
71
|
|
|
82
|
-
|
|
72
|
+
CategoryByConsumption.propTypes = {
|
|
83
73
|
context: contextApiInfoTypes,
|
|
84
74
|
value: number,
|
|
85
75
|
unit: string,
|
|
@@ -87,4 +77,4 @@ CategoryBrConsumption.propTypes = {
|
|
|
87
77
|
rate: string,
|
|
88
78
|
};
|
|
89
79
|
|
|
90
|
-
export default withContext()(
|
|
80
|
+
export default withContext()(CategoryByConsumption);
|
|
@@ -7,7 +7,7 @@ export default theme =>
|
|
|
7
7
|
borderColor: '#DFDFDF',
|
|
8
8
|
borderWidth: 1,
|
|
9
9
|
borderRadius: 5,
|
|
10
|
-
|
|
10
|
+
width: '100%',
|
|
11
11
|
marginBottom: 16,
|
|
12
12
|
},
|
|
13
13
|
rateLabelContainer: {
|
|
@@ -48,6 +48,7 @@ export default theme =>
|
|
|
48
48
|
justifyContent: 'center',
|
|
49
49
|
paddingVertical: 24,
|
|
50
50
|
alignItems: 'center',
|
|
51
|
+
width: '100%',
|
|
51
52
|
},
|
|
52
53
|
descriptionsContainer: {
|
|
53
54
|
borderTopWidth: 1,
|
|
@@ -57,4 +58,7 @@ export default theme =>
|
|
|
57
58
|
descriptionsInnerContainer: {
|
|
58
59
|
paddingHorizontal: 15,
|
|
59
60
|
},
|
|
61
|
+
scale: {
|
|
62
|
+
marginRight: 10,
|
|
63
|
+
},
|
|
60
64
|
});
|
|
@@ -1,21 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const formatRateStages = (rateStages, getColor) => {
|
|
4
|
-
const newRateStages = _.cloneDeep(rateStages);
|
|
5
|
-
|
|
1
|
+
export const getSubRateStages = rateStages => {
|
|
6
2
|
const plainSubRateStages = [];
|
|
7
3
|
|
|
8
|
-
|
|
9
|
-
rateStage.sub_rate_stages.forEach(
|
|
10
|
-
plainSubRateStages.push(
|
|
4
|
+
rateStages.forEach(rateStage => {
|
|
5
|
+
rateStage.sub_rate_stages.forEach(subRateStage => {
|
|
6
|
+
plainSubRateStages.push(subRateStage);
|
|
11
7
|
});
|
|
12
8
|
});
|
|
13
9
|
|
|
14
|
-
plainSubRateStages
|
|
15
|
-
const color = getColor(i, plainSubRateStages.length);
|
|
16
|
-
|
|
17
|
-
newRateStages[subRateStage.groupIndex].sub_rate_stages[subRateStage.ownIndex].color = color;
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
return newRateStages;
|
|
10
|
+
return plainSubRateStages;
|
|
21
11
|
};
|