@widergy/utilitygo-smart-bill-mobile 3.0.0 → 3.1.0
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/lib/components/SmartBillSummary/index.js +18 -5
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/ActionCards/index.js +43 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/ActionCards/styles.js +11 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/BillHeader/index.js +55 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/BillHeader/styles.js +28 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/TitularCard/index.js +93 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/TitularCard/styles.js +29 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/TotalCard/index.js +49 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/components/TotalCard/styles.js +17 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/constants.js +11 -0
- package/src/lib/components/SmartBillSummary/tabs/Billing/index.js +46 -171
- package/src/lib/components/SmartBillSummary/tabs/Billing/styles.js +9 -71
- package/src/lib/components/SmartBillSummary/tabs/Consumptions/components/BimestralConsumption/constants.js +6 -0
- package/src/lib/components/SmartBillSummary/tabs/Consumptions/components/BimestralConsumption/index.js +30 -6
- package/src/lib/components/SmartBillSummary/tabs/Consumptions/index.js +14 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [3.1.0](https://github.com/widergy/UtilityGO-Smart-Bill-Mobile/compare/v3.0.0...v3.1.0) (2025-09-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* [EVEP-34] billing new structure ([#46](https://github.com/widergy/UtilityGO-Smart-Bill-Mobile/issues/46)) ([a4788b6](https://github.com/widergy/UtilityGO-Smart-Bill-Mobile/commit/a4788b6b4d77d83b375028734d3550820a32f8b4))
|
|
7
|
+
|
|
1
8
|
# [3.0.0](https://github.com/widergy/UtilityGO-Smart-Bill-Mobile/compare/v2.8.0...v3.0.0) (2025-09-22)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/* eslint-disable react/jsx-fragments */
|
|
3
3
|
import React, { Fragment, useEffect, useState, useMemo } from 'react';
|
|
4
4
|
import { UTButton, UTLoading, UTTabs } from '@widergy/mobile-ui';
|
|
5
|
-
import {
|
|
6
|
-
import { arrayOf, bool, func, object, shape, string } from 'prop-types';
|
|
5
|
+
import { ScrollView } from 'react-native';
|
|
6
|
+
import { array, arrayOf, bool, func, object, shape, string } from 'prop-types';
|
|
7
7
|
import isEmpty from 'lodash/isEmpty';
|
|
8
8
|
import debounce from 'lodash/debounce';
|
|
9
9
|
|
|
@@ -11,9 +11,11 @@ import { TAB_COMPONENT_MAPPER } from './constants';
|
|
|
11
11
|
import { getDefaultCurrentTab, getTabOptions } from './utils';
|
|
12
12
|
import styles from './styles';
|
|
13
13
|
import AIDrawer from './components/AIDrawer';
|
|
14
|
+
import BillHeader from './tabs/Billing/components/BillHeader';
|
|
14
15
|
|
|
15
16
|
const SmartBillSummary = ({
|
|
16
17
|
assets,
|
|
18
|
+
billingLayout,
|
|
17
19
|
colors,
|
|
18
20
|
components,
|
|
19
21
|
constants = {},
|
|
@@ -114,10 +116,20 @@ const SmartBillSummary = ({
|
|
|
114
116
|
tabs={filteredTabOptions}
|
|
115
117
|
value={currentTab}
|
|
116
118
|
/>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
<ScrollView>
|
|
120
|
+
{filteredTabOptions.find(tab => tab.value === currentTab)?.header && (
|
|
121
|
+
<BillHeader
|
|
122
|
+
assets={assets}
|
|
123
|
+
colors={colors}
|
|
124
|
+
header={translations?.billingTab.header}
|
|
125
|
+
debtStatusLabel={smartBill?.debt_status_label}
|
|
126
|
+
smartBill={smartBill}
|
|
127
|
+
billNumber={smartBill?.bill_number}
|
|
128
|
+
/>
|
|
129
|
+
)}
|
|
119
130
|
{TAB_COMPONENT_MAPPER?.[currentTab]?.({
|
|
120
131
|
assets,
|
|
132
|
+
billingLayout,
|
|
121
133
|
colors,
|
|
122
134
|
constants,
|
|
123
135
|
handlers,
|
|
@@ -127,7 +139,7 @@ const SmartBillSummary = ({
|
|
|
127
139
|
translations,
|
|
128
140
|
utils
|
|
129
141
|
})}
|
|
130
|
-
</
|
|
142
|
+
</ScrollView>
|
|
131
143
|
|
|
132
144
|
{aiQuestionsPanelEnabled && (
|
|
133
145
|
<Fragment>
|
|
@@ -162,6 +174,7 @@ const SmartBillSummary = ({
|
|
|
162
174
|
|
|
163
175
|
SmartBillSummary.propTypes = {
|
|
164
176
|
assets: object,
|
|
177
|
+
billingLayout: array,
|
|
165
178
|
colors: object,
|
|
166
179
|
components: object,
|
|
167
180
|
constants: object,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { UTActionCard } from '@widergy/mobile-ui';
|
|
4
|
+
import { View } from 'react-native';
|
|
5
|
+
import { arrayOf, object } from 'prop-types';
|
|
6
|
+
|
|
7
|
+
import styles from './styles';
|
|
8
|
+
|
|
9
|
+
const ActionCards = ({ actionCards }) => {
|
|
10
|
+
return (
|
|
11
|
+
<View style={styles.actionCardsContainer}>
|
|
12
|
+
{actionCards?.map(({ onPress, Icon = 'IconChevronRight', statusAttributes = {}, title }) => (
|
|
13
|
+
<UTActionCard
|
|
14
|
+
classNames={{ headerTitles: styles.headerAndChildrenContainer }}
|
|
15
|
+
disabled={!onPress}
|
|
16
|
+
headerActions={
|
|
17
|
+
onPress
|
|
18
|
+
? [
|
|
19
|
+
{
|
|
20
|
+
colorTheme: 'accent',
|
|
21
|
+
Icon,
|
|
22
|
+
isPrimary: true
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
: []
|
|
26
|
+
}
|
|
27
|
+
key={title}
|
|
28
|
+
mainAction={onPress}
|
|
29
|
+
title={title}
|
|
30
|
+
titleProps={{ style: styles.titleActionCard }}
|
|
31
|
+
{...statusAttributes}
|
|
32
|
+
/>
|
|
33
|
+
))}
|
|
34
|
+
</View>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
ActionCards.propTypes = {
|
|
39
|
+
actionCards: arrayOf(object),
|
|
40
|
+
colors: object
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default ActionCards;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Surface, UTLabel } from '@widergy/mobile-ui';
|
|
4
|
+
import { View, Image } from 'react-native';
|
|
5
|
+
import { string, object } from 'prop-types';
|
|
6
|
+
|
|
7
|
+
import DebtStatusLabel from '../DebtStatusLabel';
|
|
8
|
+
import { getCurrentPeriod, getFormattedDate } from '../../utils';
|
|
9
|
+
|
|
10
|
+
import { createStyles } from './styles';
|
|
11
|
+
|
|
12
|
+
const BillHeader = ({ assets, colors, header, debtStatusLabel, smartBill, billNumber }) => {
|
|
13
|
+
const styles = createStyles(colors);
|
|
14
|
+
const { UtilityLogo } = assets.billingTab;
|
|
15
|
+
|
|
16
|
+
const { billIssueDate, billTypeHelpText } = header;
|
|
17
|
+
const currentPeriod = getCurrentPeriod(smartBill);
|
|
18
|
+
const issuedOnDate = getFormattedDate(currentPeriod?.settlements?.current?.issued_on);
|
|
19
|
+
const debtStatusValidation = debtStatusLabel !== null;
|
|
20
|
+
return (
|
|
21
|
+
<Surface elevation={1} style={styles.billHeader}>
|
|
22
|
+
{UtilityLogo && <Image resizeMode="contain" source={UtilityLogo} height={35} />}
|
|
23
|
+
<View style={styles.billHeaderLabels}>
|
|
24
|
+
<View style={styles.valueAndHelpText}>
|
|
25
|
+
<UTLabel variant="small">{billNumber}</UTLabel>
|
|
26
|
+
<UTLabel colorTheme="gray" variant="small">
|
|
27
|
+
{billTypeHelpText}
|
|
28
|
+
</UTLabel>
|
|
29
|
+
</View>
|
|
30
|
+
|
|
31
|
+
<View style={styles.valueAndHelpText}>
|
|
32
|
+
<UTLabel variant="small">{issuedOnDate}</UTLabel>
|
|
33
|
+
<UTLabel colorTheme="gray" variant="small">
|
|
34
|
+
{billIssueDate}
|
|
35
|
+
</UTLabel>
|
|
36
|
+
</View>
|
|
37
|
+
|
|
38
|
+
{debtStatusValidation && (
|
|
39
|
+
<DebtStatusLabel colors={colors} debtStatusLabel={debtStatusLabel} isWarning={smartBill?.warning} />
|
|
40
|
+
)}
|
|
41
|
+
</View>
|
|
42
|
+
</Surface>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
BillHeader.propTypes = {
|
|
47
|
+
assets: object,
|
|
48
|
+
colors: object,
|
|
49
|
+
header: object,
|
|
50
|
+
debtStatusLabel: string,
|
|
51
|
+
smartBill: object,
|
|
52
|
+
billNumber: string
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default BillHeader;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const createStyles = colors =>
|
|
4
|
+
StyleSheet.create({
|
|
5
|
+
billHeaderLabels: {
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
columnGap: 32,
|
|
8
|
+
flexDirection: 'row',
|
|
9
|
+
justifyContent: 'space-between',
|
|
10
|
+
paddingTop: 16,
|
|
11
|
+
rowGap: 16,
|
|
12
|
+
flexWrap: 'wrap'
|
|
13
|
+
},
|
|
14
|
+
valueAndHelpText: {
|
|
15
|
+
flexDirection: 'column',
|
|
16
|
+
gap: 4
|
|
17
|
+
},
|
|
18
|
+
billHeader: {
|
|
19
|
+
backgroundColor: colors.light01,
|
|
20
|
+
borderRadius: 8,
|
|
21
|
+
flexDirection: 'column',
|
|
22
|
+
gap: 12,
|
|
23
|
+
justifyContent: 'space-between',
|
|
24
|
+
padding: 16,
|
|
25
|
+
marginHorizontal: 16,
|
|
26
|
+
marginTop: 16
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Surface, UTLabel } from '@widergy/mobile-ui';
|
|
4
|
+
import { View } from 'react-native';
|
|
5
|
+
import { object } from 'prop-types';
|
|
6
|
+
|
|
7
|
+
import { createStyles } from './styles';
|
|
8
|
+
|
|
9
|
+
const TitularCard = ({ utils, client, titularCard, colors }) => {
|
|
10
|
+
const styles = createStyles(colors);
|
|
11
|
+
const { formatters = {} } = utils;
|
|
12
|
+
const { clientNumberFormatter } = formatters;
|
|
13
|
+
const {
|
|
14
|
+
account_address: accountAddress,
|
|
15
|
+
client_number: clientNumber = '',
|
|
16
|
+
holder_name: titularName,
|
|
17
|
+
postal_address: postalAddress,
|
|
18
|
+
iva_condition: ivaCondition
|
|
19
|
+
} = client || {};
|
|
20
|
+
const {
|
|
21
|
+
title: titularCardTitle,
|
|
22
|
+
addressHelpText,
|
|
23
|
+
titularHelpText,
|
|
24
|
+
clientNumberHelpText,
|
|
25
|
+
ivaConditionHelpText
|
|
26
|
+
} = titularCard;
|
|
27
|
+
const renderTitularFooter = clientNumber || ivaCondition;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Surface elevation={1} style={styles.titularCard}>
|
|
31
|
+
<UTLabel variant="title3" weight="medium">
|
|
32
|
+
{titularCardTitle}
|
|
33
|
+
</UTLabel>
|
|
34
|
+
|
|
35
|
+
<View style={styles.titularDataContainer}>
|
|
36
|
+
{accountAddress && (
|
|
37
|
+
<View style={styles.titularData}>
|
|
38
|
+
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
39
|
+
{accountAddress}
|
|
40
|
+
</UTLabel>
|
|
41
|
+
|
|
42
|
+
{accountAddress !== postalAddress && <UTLabel>{postalAddress}</UTLabel>}
|
|
43
|
+
|
|
44
|
+
<UTLabel colorTheme="gray">{addressHelpText}</UTLabel>
|
|
45
|
+
</View>
|
|
46
|
+
)}
|
|
47
|
+
|
|
48
|
+
{titularName && (
|
|
49
|
+
<View style={styles.titularData}>
|
|
50
|
+
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
51
|
+
{titularName}
|
|
52
|
+
</UTLabel>
|
|
53
|
+
|
|
54
|
+
<UTLabel colorTheme="gray">{titularHelpText}</UTLabel>
|
|
55
|
+
</View>
|
|
56
|
+
)}
|
|
57
|
+
|
|
58
|
+
{renderTitularFooter && (
|
|
59
|
+
<View style={styles.titularFooter}>
|
|
60
|
+
{clientNumber && (
|
|
61
|
+
<View style={styles.titularData}>
|
|
62
|
+
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
63
|
+
{clientNumberFormatter?.(clientNumber) || clientNumber}
|
|
64
|
+
</UTLabel>
|
|
65
|
+
|
|
66
|
+
<UTLabel colorTheme="gray">{clientNumberHelpText}</UTLabel>
|
|
67
|
+
</View>
|
|
68
|
+
)}
|
|
69
|
+
|
|
70
|
+
{ivaCondition && (
|
|
71
|
+
<View style={styles.titularData}>
|
|
72
|
+
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
73
|
+
{ivaCondition}
|
|
74
|
+
</UTLabel>
|
|
75
|
+
|
|
76
|
+
<UTLabel colorTheme="gray">{ivaConditionHelpText}</UTLabel>
|
|
77
|
+
</View>
|
|
78
|
+
)}
|
|
79
|
+
</View>
|
|
80
|
+
)}
|
|
81
|
+
</View>
|
|
82
|
+
</Surface>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
TitularCard.propTypes = {
|
|
87
|
+
colors: object,
|
|
88
|
+
titularCard: object,
|
|
89
|
+
utils: object,
|
|
90
|
+
client: object
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default TitularCard;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const createStyles = colors =>
|
|
4
|
+
StyleSheet.create({
|
|
5
|
+
titularCard: {
|
|
6
|
+
backgroundColor: colors.light01,
|
|
7
|
+
borderRadius: 8,
|
|
8
|
+
padding: 16,
|
|
9
|
+
flexDirection: 'column',
|
|
10
|
+
gap: 24
|
|
11
|
+
},
|
|
12
|
+
titularDataContainer: {
|
|
13
|
+
flexDirection: 'column'
|
|
14
|
+
},
|
|
15
|
+
titularData: {
|
|
16
|
+
flex: 1,
|
|
17
|
+
flexDirection: 'column',
|
|
18
|
+
gap: 8,
|
|
19
|
+
paddingVertical: 12
|
|
20
|
+
},
|
|
21
|
+
titularDataTitle: {
|
|
22
|
+
paddingVertical: 4
|
|
23
|
+
},
|
|
24
|
+
titularFooter: {
|
|
25
|
+
flexDirection: 'row',
|
|
26
|
+
justifyContent: 'space-between',
|
|
27
|
+
gap: 16
|
|
28
|
+
}
|
|
29
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* eslint-disable react/forbid-prop-types */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Surface, UTLabel } from '@widergy/mobile-ui';
|
|
4
|
+
import { View } from 'react-native';
|
|
5
|
+
import { arrayOf, object, func, string } from 'prop-types';
|
|
6
|
+
|
|
7
|
+
import { getFormattedDate } from '../../utils';
|
|
8
|
+
|
|
9
|
+
import { createStyles } from './styles';
|
|
10
|
+
|
|
11
|
+
const TotalCard = ({ detail, expirations, formatAmount, totalAmountLabel, totalCard, colors }) => {
|
|
12
|
+
const styles = createStyles(colors);
|
|
13
|
+
const { firstExpiration, secondExpiration } = totalCard;
|
|
14
|
+
|
|
15
|
+
const firstExpirationDate = getFormattedDate(expirations?.[0]?.date);
|
|
16
|
+
const secondExpirationDate = getFormattedDate(expirations?.[1]?.date);
|
|
17
|
+
const { total_amount: totalAmount } = detail || {};
|
|
18
|
+
return (
|
|
19
|
+
<Surface elevation={1} style={styles.totalCardStyles}>
|
|
20
|
+
<View style={styles.total}>
|
|
21
|
+
<UTLabel variant="subtitle1" weight="medium">
|
|
22
|
+
{totalAmountLabel}
|
|
23
|
+
</UTLabel>
|
|
24
|
+
<UTLabel colorTheme="accent" variant="title2" weight="medium">
|
|
25
|
+
{formatAmount?.(totalAmount, true)}
|
|
26
|
+
</UTLabel>
|
|
27
|
+
</View>
|
|
28
|
+
<View>
|
|
29
|
+
<UTLabel colorTheme="gray" variant="small" weight="medium">
|
|
30
|
+
{firstExpiration?.(firstExpirationDate)}
|
|
31
|
+
</UTLabel>
|
|
32
|
+
<UTLabel colorTheme="gray" variant="small" weight="medium">
|
|
33
|
+
{secondExpiration?.(secondExpirationDate)}
|
|
34
|
+
</UTLabel>
|
|
35
|
+
</View>
|
|
36
|
+
</Surface>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
TotalCard.propTypes = {
|
|
41
|
+
detail: object,
|
|
42
|
+
expirations: arrayOf(object),
|
|
43
|
+
formatAmount: func,
|
|
44
|
+
totalAmountLabel: string,
|
|
45
|
+
totalCard: object,
|
|
46
|
+
colors: object
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default TotalCard;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const createStyles = colors =>
|
|
4
|
+
StyleSheet.create({
|
|
5
|
+
totalCardStyles: {
|
|
6
|
+
backgroundColor: colors.light01,
|
|
7
|
+
borderRadius: 4,
|
|
8
|
+
flexDirection: 'column',
|
|
9
|
+
padding: 16,
|
|
10
|
+
gap: 24
|
|
11
|
+
},
|
|
12
|
+
total: {
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
justifyContent: 'space-between',
|
|
15
|
+
gap: 8
|
|
16
|
+
}
|
|
17
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import ActionCards from './components/ActionCards';
|
|
2
|
+
import TotalCard from './components/TotalCard';
|
|
3
|
+
import RateCard from './components/RateCard';
|
|
4
|
+
import TitularCard from './components/TitularCard';
|
|
5
|
+
|
|
6
|
+
export const COMPONENTS = {
|
|
7
|
+
ActionCards,
|
|
8
|
+
TotalCard,
|
|
9
|
+
RateCard,
|
|
10
|
+
TitularCard
|
|
11
|
+
};
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/* eslint-disable react/forbid-prop-types */
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { func, object, shape, string } from 'prop-types';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { array, func, object, shape, string } from 'prop-types';
|
|
6
5
|
|
|
7
|
-
import { getCurrentPeriod
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import RateCard from './components/RateCard';
|
|
6
|
+
import { getCurrentPeriod } from './utils';
|
|
7
|
+
import styles from './styles';
|
|
8
|
+
import { COMPONENTS } from './constants';
|
|
11
9
|
|
|
12
10
|
const Billing = ({
|
|
13
11
|
assets,
|
|
@@ -15,15 +13,14 @@ const Billing = ({
|
|
|
15
13
|
constants,
|
|
16
14
|
currentAccount = {},
|
|
17
15
|
handlers = {},
|
|
16
|
+
billingLayout,
|
|
18
17
|
smartBill = {},
|
|
19
18
|
translations,
|
|
20
19
|
utils = {}
|
|
21
20
|
}) => {
|
|
22
|
-
const styles = createStyles(colors);
|
|
23
|
-
const { UtilityLogo } = assets;
|
|
24
21
|
const { adherenceStatus, consumptionLevels = [], subsidyLevels } = constants;
|
|
25
22
|
const { formatters = {} } = utils;
|
|
26
|
-
const {
|
|
23
|
+
const { formatAmount } = formatters;
|
|
27
24
|
const {
|
|
28
25
|
bill_number: billNumber,
|
|
29
26
|
client,
|
|
@@ -31,13 +28,6 @@ const Billing = ({
|
|
|
31
28
|
detail,
|
|
32
29
|
expirations
|
|
33
30
|
} = smartBill;
|
|
34
|
-
const {
|
|
35
|
-
account_address: accountAddress,
|
|
36
|
-
client_number: clientNumber = '',
|
|
37
|
-
holder_name: titularName,
|
|
38
|
-
postal_address: postalAddress,
|
|
39
|
-
iva_condition: ivaCondition
|
|
40
|
-
} = client || {};
|
|
41
31
|
const {
|
|
42
32
|
adhered,
|
|
43
33
|
automaticDebit = {},
|
|
@@ -51,20 +41,7 @@ const Billing = ({
|
|
|
51
41
|
totalAmountLabel,
|
|
52
42
|
totalCard = {}
|
|
53
43
|
} = translations;
|
|
54
|
-
const {
|
|
55
|
-
title: titularCardTitle,
|
|
56
|
-
addressHelpText,
|
|
57
|
-
titularHelpText,
|
|
58
|
-
clientNumberHelpText,
|
|
59
|
-
ivaConditionHelpText
|
|
60
|
-
} = titularCard;
|
|
61
|
-
const { firstExpiration } = totalCard;
|
|
62
|
-
const { billIssueDate, billTypeHelpText } = header;
|
|
63
44
|
const currentPeriod = getCurrentPeriod(smartBill);
|
|
64
|
-
const issuedOnDate = getFormattedDate(currentPeriod?.settlements?.current?.issued_on);
|
|
65
|
-
const debtStatusValidation = debtStatusLabel !== null;
|
|
66
|
-
const firstExpirationDate = getFormattedDate(expirations?.[0]?.date);
|
|
67
|
-
const { total_amount: totalAmount } = detail || {};
|
|
68
45
|
const {
|
|
69
46
|
handleAutomaticDebitAdherence = () => {},
|
|
70
47
|
handleDownloadBill = () => {},
|
|
@@ -81,7 +58,6 @@ const Billing = ({
|
|
|
81
58
|
const { title: automaticDebitTitle } = automaticDebit;
|
|
82
59
|
const isAdheredToDigitalBill = client?.adherence_to_digital_bill;
|
|
83
60
|
const isAdheredToAutomaticDebit = adherenceToAutomaticDebit === adherenceStatus?.subscribed;
|
|
84
|
-
const renderTitularFooter = clientNumber || ivaCondition;
|
|
85
61
|
|
|
86
62
|
const actionCards = [
|
|
87
63
|
{
|
|
@@ -117,147 +93,45 @@ const Billing = ({
|
|
|
117
93
|
}
|
|
118
94
|
};
|
|
119
95
|
});
|
|
120
|
-
|
|
96
|
+
const props = {
|
|
97
|
+
actionCards,
|
|
98
|
+
assets,
|
|
99
|
+
billNumber,
|
|
100
|
+
client,
|
|
101
|
+
colors,
|
|
102
|
+
constants,
|
|
103
|
+
consumptionLevels,
|
|
104
|
+
currentAccount,
|
|
105
|
+
currentPeriod,
|
|
106
|
+
debtStatusLabel,
|
|
107
|
+
detail,
|
|
108
|
+
expirations,
|
|
109
|
+
formatAmount,
|
|
110
|
+
handlers,
|
|
111
|
+
header,
|
|
112
|
+
normalizedRate,
|
|
113
|
+
rateCardTranslations,
|
|
114
|
+
ratesTableLink,
|
|
115
|
+
titularCard,
|
|
116
|
+
smartBill,
|
|
117
|
+
subsidy,
|
|
118
|
+
subsidyLevels,
|
|
119
|
+
totalAmountLabel,
|
|
120
|
+
totalCard,
|
|
121
|
+
trackRedirectionToExternalLink,
|
|
122
|
+
translations,
|
|
123
|
+
utils
|
|
124
|
+
};
|
|
121
125
|
return (
|
|
122
|
-
<
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
</UTLabel>
|
|
132
|
-
</View>
|
|
133
|
-
|
|
134
|
-
<View style={styles.valueAndHelpText}>
|
|
135
|
-
<UTLabel variant="small">{issuedOnDate}</UTLabel>
|
|
136
|
-
<UTLabel colorTheme="gray" variant="small">
|
|
137
|
-
{billIssueDate}
|
|
138
|
-
</UTLabel>
|
|
139
|
-
</View>
|
|
140
|
-
|
|
141
|
-
{debtStatusValidation && (
|
|
142
|
-
<DebtStatusLabel
|
|
143
|
-
colors={colors}
|
|
144
|
-
debtStatusLabel={debtStatusLabel}
|
|
145
|
-
isWarning={smartBill?.warning}
|
|
146
|
-
/>
|
|
147
|
-
)}
|
|
148
|
-
</View>
|
|
149
|
-
</Surface>
|
|
150
|
-
|
|
151
|
-
<Surface elevation={1} style={styles.totalCard}>
|
|
152
|
-
<View style={styles.total}>
|
|
153
|
-
<UTLabel variant="subtitle1" weight="medium">
|
|
154
|
-
{totalAmountLabel}
|
|
155
|
-
</UTLabel>
|
|
156
|
-
<UTLabel colorTheme="accent" variant="title2" weight="medium">
|
|
157
|
-
{formatAmount?.(totalAmount, true)}
|
|
158
|
-
</UTLabel>
|
|
159
|
-
</View>
|
|
160
|
-
|
|
161
|
-
<UTLabel colorTheme="gray" variant="small" weight="medium">
|
|
162
|
-
{firstExpiration?.(firstExpirationDate)}
|
|
163
|
-
</UTLabel>
|
|
164
|
-
</Surface>
|
|
165
|
-
|
|
166
|
-
<RateCard
|
|
167
|
-
{...{
|
|
168
|
-
colors,
|
|
169
|
-
consumptionLevels,
|
|
170
|
-
currentPeriod,
|
|
171
|
-
formatAmount,
|
|
172
|
-
normalizedRate,
|
|
173
|
-
rateCardTranslations,
|
|
174
|
-
ratesTableLink,
|
|
175
|
-
smartBill,
|
|
176
|
-
subsidy,
|
|
177
|
-
subsidyLevels,
|
|
178
|
-
trackRedirectionToExternalLink,
|
|
179
|
-
translations
|
|
180
|
-
}}
|
|
181
|
-
/>
|
|
182
|
-
|
|
183
|
-
{actionCards?.map(({ onPress, Icon = 'IconChevronRight', statusAttributes = {}, title }) => (
|
|
184
|
-
<UTActionCard
|
|
185
|
-
classNames={{ headerTitles: styles.headerAndChildrenContainer }}
|
|
186
|
-
disabled={!onPress}
|
|
187
|
-
headerActions={
|
|
188
|
-
onPress
|
|
189
|
-
? [
|
|
190
|
-
{
|
|
191
|
-
colorTheme: 'accent',
|
|
192
|
-
Icon,
|
|
193
|
-
isPrimary: true
|
|
194
|
-
}
|
|
195
|
-
]
|
|
196
|
-
: []
|
|
197
|
-
}
|
|
198
|
-
key={title}
|
|
199
|
-
mainAction={onPress}
|
|
200
|
-
title={title}
|
|
201
|
-
titleProps={{ style: styles.titleActionCard }}
|
|
202
|
-
{...statusAttributes}
|
|
203
|
-
/>
|
|
204
|
-
))}
|
|
205
|
-
|
|
206
|
-
<Surface elevation={1} style={styles.titularCard}>
|
|
207
|
-
<UTLabel variant="title3" weight="medium">
|
|
208
|
-
{titularCardTitle}
|
|
209
|
-
</UTLabel>
|
|
210
|
-
|
|
211
|
-
<View style={styles.titularDataContainer}>
|
|
212
|
-
{accountAddress && (
|
|
213
|
-
<View style={styles.titularData}>
|
|
214
|
-
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
215
|
-
{accountAddress}
|
|
216
|
-
</UTLabel>
|
|
217
|
-
|
|
218
|
-
{accountAddress !== postalAddress && <UTLabel>{postalAddress}</UTLabel>}
|
|
219
|
-
|
|
220
|
-
<UTLabel colorTheme="gray">{addressHelpText}</UTLabel>
|
|
221
|
-
</View>
|
|
222
|
-
)}
|
|
223
|
-
|
|
224
|
-
{titularName && (
|
|
225
|
-
<View style={styles.titularData}>
|
|
226
|
-
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
227
|
-
{titularName}
|
|
228
|
-
</UTLabel>
|
|
229
|
-
|
|
230
|
-
<UTLabel colorTheme="gray">{titularHelpText}</UTLabel>
|
|
231
|
-
</View>
|
|
232
|
-
)}
|
|
233
|
-
|
|
234
|
-
{renderTitularFooter && (
|
|
235
|
-
<View style={styles.titularFooter}>
|
|
236
|
-
{clientNumber && (
|
|
237
|
-
<View style={styles.titularData}>
|
|
238
|
-
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
239
|
-
{clientNumberFormatter?.(clientNumber) || clientNumber}
|
|
240
|
-
</UTLabel>
|
|
241
|
-
|
|
242
|
-
<UTLabel colorTheme="gray">{clientNumberHelpText}</UTLabel>
|
|
243
|
-
</View>
|
|
244
|
-
)}
|
|
245
|
-
|
|
246
|
-
{ivaCondition && (
|
|
247
|
-
<View style={styles.titularData}>
|
|
248
|
-
<UTLabel style={styles.titularDataTitle} weight="bold">
|
|
249
|
-
{ivaCondition}
|
|
250
|
-
</UTLabel>
|
|
251
|
-
|
|
252
|
-
<UTLabel colorTheme="gray">{ivaConditionHelpText}</UTLabel>
|
|
253
|
-
</View>
|
|
254
|
-
)}
|
|
255
|
-
</View>
|
|
256
|
-
)}
|
|
257
|
-
</View>
|
|
258
|
-
</Surface>
|
|
259
|
-
</View>
|
|
260
|
-
</ScrollView>
|
|
126
|
+
<View style={styles.generalContainer}>
|
|
127
|
+
{billingLayout.map(item => {
|
|
128
|
+
if (item.enabled) {
|
|
129
|
+
const Component = COMPONENTS[item.name];
|
|
130
|
+
return Component && <Component key={item.name} {...props} />;
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
})}
|
|
134
|
+
</View>
|
|
261
135
|
);
|
|
262
136
|
};
|
|
263
137
|
|
|
@@ -266,6 +140,7 @@ Billing.propTypes = {
|
|
|
266
140
|
colors: object,
|
|
267
141
|
constants: object,
|
|
268
142
|
currentAccount: object,
|
|
143
|
+
billingLayout: array,
|
|
269
144
|
handlers: shape({ [string]: func }),
|
|
270
145
|
smartBill: object,
|
|
271
146
|
translations: object,
|
|
@@ -1,73 +1,11 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
billHeader: {
|
|
13
|
-
backgroundColor: colors.light01,
|
|
14
|
-
borderRadius: 8,
|
|
15
|
-
flexDirection: 'column',
|
|
16
|
-
gap: 12,
|
|
17
|
-
justifyContent: 'space-between',
|
|
18
|
-
padding: 16
|
|
19
|
-
},
|
|
20
|
-
billHeaderLabels: {
|
|
21
|
-
alignItems: 'center',
|
|
22
|
-
columnGap: 32,
|
|
23
|
-
flexDirection: 'row',
|
|
24
|
-
justifyContent: 'space-between',
|
|
25
|
-
paddingTop: 16,
|
|
26
|
-
rowGap: 16,
|
|
27
|
-
flexWrap: 'wrap'
|
|
28
|
-
},
|
|
29
|
-
valueAndHelpText: {
|
|
30
|
-
flexDirection: 'column',
|
|
31
|
-
gap: 4
|
|
32
|
-
},
|
|
33
|
-
totalCard: {
|
|
34
|
-
backgroundColor: colors.light01,
|
|
35
|
-
borderRadius: 4,
|
|
36
|
-
flexDirection: 'column',
|
|
37
|
-
padding: 16,
|
|
38
|
-
gap: 24
|
|
39
|
-
},
|
|
40
|
-
total: {
|
|
41
|
-
flexDirection: 'row',
|
|
42
|
-
justifyContent: 'space-between',
|
|
43
|
-
gap: 8
|
|
44
|
-
},
|
|
45
|
-
titularCard: {
|
|
46
|
-
backgroundColor: colors.light01,
|
|
47
|
-
borderRadius: 8,
|
|
48
|
-
padding: 16,
|
|
49
|
-
flexDirection: 'column',
|
|
50
|
-
gap: 24
|
|
51
|
-
},
|
|
52
|
-
titularDataContainer: {
|
|
53
|
-
flexDirection: 'column'
|
|
54
|
-
},
|
|
55
|
-
titularData: {
|
|
56
|
-
flex: 1,
|
|
57
|
-
flexDirection: 'column',
|
|
58
|
-
gap: 8,
|
|
59
|
-
paddingVertical: 12
|
|
60
|
-
},
|
|
61
|
-
titularDataTitle: {
|
|
62
|
-
paddingVertical: 4
|
|
63
|
-
},
|
|
64
|
-
titularFooter: {
|
|
65
|
-
flexDirection: 'row',
|
|
66
|
-
justifyContent: 'space-between',
|
|
67
|
-
gap: 16
|
|
68
|
-
},
|
|
69
|
-
titleActionCard: {
|
|
70
|
-
marginBottom: 'auto',
|
|
71
|
-
marginTop: 'auto'
|
|
72
|
-
}
|
|
73
|
-
});
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
generalContainer: {
|
|
5
|
+
flexDirection: 'column',
|
|
6
|
+
gap: 24,
|
|
7
|
+
paddingVertical: 24,
|
|
8
|
+
paddingHorizontal: 16,
|
|
9
|
+
marginBottom: 48
|
|
10
|
+
}
|
|
11
|
+
});
|
|
@@ -8,3 +8,9 @@ export const CONSUMPTION_CARDS = [
|
|
|
8
8
|
key: 'billingCard'
|
|
9
9
|
}
|
|
10
10
|
];
|
|
11
|
+
|
|
12
|
+
export const START = 'inicio';
|
|
13
|
+
export const END = 'fin';
|
|
14
|
+
export const DATE_FORMAT = 'D [de] MMMM';
|
|
15
|
+
export const DATE_FORMAT_WITH_YEAR = 'D [de] MMMM [de] YYYY';
|
|
16
|
+
export const DAY = 'day';
|
|
@@ -3,15 +3,35 @@ import React from 'react';
|
|
|
3
3
|
import { UTActionCard, UTLabel } from '@widergy/mobile-ui';
|
|
4
4
|
import { object } from 'prop-types';
|
|
5
5
|
import { View } from 'react-native';
|
|
6
|
+
import dayjs from 'dayjs';
|
|
6
7
|
|
|
7
|
-
import { CONSUMPTION_CARDS } from './constants';
|
|
8
|
+
import { CONSUMPTION_CARDS, START, END, DAY, DATE_FORMAT, DATE_FORMAT_WITH_YEAR } from './constants';
|
|
8
9
|
import styles, { markdownStyles } from './styles';
|
|
9
10
|
|
|
10
|
-
const BimestralConsumption = ({ assets, colors, texts }) => {
|
|
11
|
+
const BimestralConsumption = ({ assets, colors, texts, smartBill }) => {
|
|
11
12
|
const bimestralConsumptionTexts = texts?.bimestralConsumption;
|
|
12
13
|
const { title: bimestralTitle, description: bimestralDescription } = bimestralConsumptionTexts || {};
|
|
13
14
|
const { BackgroundVector } = assets?.bimestral || {};
|
|
15
|
+
const readingPeriods = smartBill?.reading_periods || [];
|
|
16
|
+
const startDate = readingPeriods.find(period => period.moment === START)?.date;
|
|
17
|
+
const endDate = readingPeriods.find(period => period.moment === END)?.date;
|
|
14
18
|
|
|
19
|
+
const formatDate = (dateString, includeYear = false) => {
|
|
20
|
+
if (!dateString) return '';
|
|
21
|
+
const format = includeYear ? DATE_FORMAT_WITH_YEAR : DATE_FORMAT;
|
|
22
|
+
return dayjs(dateString).locale('es').format(format);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const calculateTotalDays = (start, end) => {
|
|
26
|
+
if (!start || !end) return 0;
|
|
27
|
+
const startMoment = dayjs(start);
|
|
28
|
+
const endMoment = dayjs(end);
|
|
29
|
+
return endMoment.diff(startMoment, DAY);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const formattedStartDate = formatDate(startDate, false);
|
|
33
|
+
const formattedEndDate = formatDate(endDate, true);
|
|
34
|
+
const totalDays = calculateTotalDays(startDate, endDate);
|
|
15
35
|
return (
|
|
16
36
|
<View>
|
|
17
37
|
<View style={styles.bimestralConsumptionHeader}>
|
|
@@ -22,9 +42,12 @@ const BimestralConsumption = ({ assets, colors, texts }) => {
|
|
|
22
42
|
</View>
|
|
23
43
|
<View style={styles.bimestralConsumptionCards}>
|
|
24
44
|
{CONSUMPTION_CARDS.map(({ icon, key }) => {
|
|
25
|
-
const title =
|
|
26
|
-
|
|
27
|
-
|
|
45
|
+
const { title, description } =
|
|
46
|
+
bimestralConsumptionTexts?.[key]?.({
|
|
47
|
+
formattedStartDate,
|
|
48
|
+
formattedEndDate,
|
|
49
|
+
totalDays
|
|
50
|
+
}) || {};
|
|
28
51
|
return (
|
|
29
52
|
<UTActionCard
|
|
30
53
|
adornment={{
|
|
@@ -58,7 +81,8 @@ const BimestralConsumption = ({ assets, colors, texts }) => {
|
|
|
58
81
|
BimestralConsumption.propTypes = {
|
|
59
82
|
assets: object,
|
|
60
83
|
colors: object,
|
|
61
|
-
texts: object
|
|
84
|
+
texts: object,
|
|
85
|
+
smartBill: object
|
|
62
86
|
};
|
|
63
87
|
|
|
64
88
|
export default BimestralConsumption;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable react/forbid-prop-types */
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { UTLabel } from '@widergy/mobile-ui';
|
|
4
|
-
import {
|
|
4
|
+
import { View } from 'react-native';
|
|
5
5
|
import { object } from 'prop-types';
|
|
6
6
|
|
|
7
7
|
import styles from './styles';
|
|
@@ -13,25 +13,23 @@ const Consumptions = ({ assets, colors, smartBill, translations }) => {
|
|
|
13
13
|
const { title, description } = translations?.consumptions || {};
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
<BimestralConsumption assets={assets} colors={colors} smartBill={smartBill} texts={translations} />
|
|
16
|
+
<View style={styles.generalContainer}>
|
|
17
|
+
<BimestralConsumption assets={assets} colors={colors} smartBill={smartBill} texts={translations} />
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
<View style={styles.consumptionDetail}>
|
|
20
|
+
<View style={styles.consumptionDetailTitles}>
|
|
21
|
+
<UTLabel variant="title3" weight="medium">
|
|
22
|
+
{title}
|
|
23
|
+
</UTLabel>
|
|
24
|
+
<UTLabel>{description}</UTLabel>
|
|
25
|
+
</View>
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</View>
|
|
27
|
+
<View style={styles.consumptionDetailColumns}>
|
|
28
|
+
<CurrentConsumption colors={colors} assets={assets} smartBill={smartBill} texts={translations} />
|
|
29
|
+
<Billing colors={colors} smartBill={smartBill} texts={translations} />
|
|
32
30
|
</View>
|
|
33
31
|
</View>
|
|
34
|
-
</
|
|
32
|
+
</View>
|
|
35
33
|
);
|
|
36
34
|
};
|
|
37
35
|
|