@thecb/components 5.9.1 → 5.10.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/dist/index.cjs.js +350 -157
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +350 -157
- package/dist/index.esm.js.map +1 -1
- package/package.json +11 -11
- package/src/components/atoms/amount-callout/AmountCallout.theme.js +1 -1
- package/src/components/atoms/button-with-action/ButtonWithAction.js +2 -0
- package/src/components/atoms/button-with-link/ButtonWithLink.js +10 -1
- package/src/components/atoms/icons/AutopayOnIcon.js +4 -10
- package/src/components/atoms/layouts/Box.styled.js +3 -5
- package/src/components/atoms/layouts/Cluster.js +1 -1
- package/src/components/atoms/layouts/Cluster.styled.js +1 -1
- package/src/components/atoms/layouts/examples/cluster-example/ClusterExample.stories.js +5 -12
- package/src/components/atoms/layouts/examples/cover-example/CoverExample.stories.js +2 -6
- package/src/components/atoms/layouts/examples/grid-example/GridExample.stories.js +3 -6
- package/src/components/atoms/layouts/examples/sidebar-example/SidebarExample.stories.js +3 -6
- package/src/components/atoms/layouts/examples/stack-example/StackExample.stories.js +5 -12
- package/src/components/atoms/layouts/examples/switcher-example/SwitcherExample.stories.js +4 -9
- package/src/components/atoms/link/ExternalLink.js +2 -0
- package/src/components/atoms/link/InternalLink.js +2 -0
- package/src/components/atoms/placeholder/Placeholder.js +1 -1
- package/src/components/atoms/text/Text.js +2 -0
- package/src/components/atoms/text/Text.styled.js +1 -0
- package/src/components/molecules/obligation/Obligation.js +46 -16
- package/src/components/molecules/obligation/modules/AmountModule.js +1 -0
- package/src/components/molecules/obligation/modules/AutopayModalModule.js +80 -47
- package/src/components/molecules/obligation/modules/InactiveControlsModule.js +20 -10
- package/src/components/molecules/obligation/modules/InactiveTitleModule.js +2 -2
- package/src/components/molecules/obligation/modules/PaymentDetailsActions.js +8 -9
- package/src/components/molecules/obligation/modules/RemoveAccountModalModule.js +62 -0
- package/src/components/molecules/obligation/modules/index.js +3 -1
- package/src/components/molecules/payment-details/PaymentDetails.js +80 -7
- package/src/components/molecules/payment-details/PaymentDetails.stories.js +93 -3
- package/src/components/molecules/tab-sidebar/TabSidebar.js +3 -2
- package/src/components/molecules/workflow-tile/WorkflowTile.js +1 -0
- package/src/components/templates/center-single/CenterSingle.js +2 -1
- package/src/components/templates/center-stack/CenterStack.js +2 -1
- package/src/components/templates/default-page-template/DefaultPageTemplate.js +2 -1
- package/src/components/templates/sidebar-single-content/SidebarSingleContent.js +2 -1
- package/src/components/templates/sidebar-stack-content/SidebarStackContent.js +2 -1
- package/src/components/templates/templates.theme.js +1 -1
- package/src/constants/colors.js +10 -8
|
@@ -16,13 +16,16 @@ const AutopayModal = ({
|
|
|
16
16
|
modalOpen,
|
|
17
17
|
deactivatePaymentSchedule,
|
|
18
18
|
navigateToSettings,
|
|
19
|
-
|
|
19
|
+
controlType = "tertiary",
|
|
20
20
|
isMobile,
|
|
21
21
|
themeValues,
|
|
22
22
|
isPaymentPlan,
|
|
23
|
-
nextAutopayDate
|
|
23
|
+
nextAutopayDate,
|
|
24
|
+
dueDate,
|
|
25
|
+
inactive
|
|
24
26
|
}) => {
|
|
25
27
|
const planType = isPaymentPlan ? "Payment Plan" : "Autopay";
|
|
28
|
+
const nextDate = dueDate || nextAutopayDate;
|
|
26
29
|
const modalExtraProps = {
|
|
27
30
|
modalHeaderText: autoPayActive
|
|
28
31
|
? `Deactivate ${planType}`
|
|
@@ -30,7 +33,11 @@ const AutopayModal = ({
|
|
|
30
33
|
modalBodyText: autoPayActive
|
|
31
34
|
? `Are you sure you want to deactivate ${
|
|
32
35
|
isPaymentPlan ? "your payment plan" : "autopay"
|
|
33
|
-
}?
|
|
36
|
+
}? ${
|
|
37
|
+
!inactive && nextDate
|
|
38
|
+
? `Your next payment will be due on ${nextDate}.`
|
|
39
|
+
: ""
|
|
40
|
+
}`
|
|
34
41
|
: `To set up ${
|
|
35
42
|
isPaymentPlan ? "a payment plan" : "autopay"
|
|
36
43
|
} you must save a payment method and address in your profile. Do you want to save these now?`,
|
|
@@ -62,6 +69,75 @@ const AutopayModal = ({
|
|
|
62
69
|
const defaultStyles = `
|
|
63
70
|
.autopayIcon { fill: ${themeValues.color}; text-decoration: underline; }
|
|
64
71
|
`;
|
|
72
|
+
const renderAutoPayControl = () => {
|
|
73
|
+
switch (controlType) {
|
|
74
|
+
case "secondary": {
|
|
75
|
+
return (
|
|
76
|
+
<ButtonWithAction
|
|
77
|
+
text={autoPayActive ? `Turn off ${planType}` : `Set Up ${planType}`}
|
|
78
|
+
variant="secondary"
|
|
79
|
+
action={() => {
|
|
80
|
+
toggleModal(true);
|
|
81
|
+
}}
|
|
82
|
+
dataQa="Turn off Autopay"
|
|
83
|
+
extraStyles={
|
|
84
|
+
isMobile
|
|
85
|
+
? `flex-grow: 1; width: 100%; margin: 0;`
|
|
86
|
+
: `flex-grow: 1; min-width: 165px;`
|
|
87
|
+
}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
case "tertiary": {
|
|
92
|
+
return (
|
|
93
|
+
<ButtonWithAction
|
|
94
|
+
text={autoPayActive ? `Manage ${planType}` : `Set Up ${planType}`}
|
|
95
|
+
variant="tertiary"
|
|
96
|
+
action={() => {
|
|
97
|
+
toggleModal(true);
|
|
98
|
+
}}
|
|
99
|
+
dataQa="Manage Autopay"
|
|
100
|
+
extraStyles={isMobile && `flex-grow: 1; width: 100%;`}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
case "link": {
|
|
105
|
+
return (
|
|
106
|
+
<Box
|
|
107
|
+
padding="0"
|
|
108
|
+
onClick={() => {
|
|
109
|
+
toggleModal(true);
|
|
110
|
+
}}
|
|
111
|
+
hoverStyles={hoverStyles}
|
|
112
|
+
activeStyles={activeStyles}
|
|
113
|
+
extraStyles={defaultStyles}
|
|
114
|
+
>
|
|
115
|
+
<Cluster
|
|
116
|
+
justify={isMobile ? "flex-start" : "flex-end"}
|
|
117
|
+
align="center"
|
|
118
|
+
>
|
|
119
|
+
<AutopayOnIcon />
|
|
120
|
+
<Text
|
|
121
|
+
variant="pS"
|
|
122
|
+
onClick={() => toggleModal(true)}
|
|
123
|
+
onKeyPress={e => {
|
|
124
|
+
e.key === "Enter" && toggleModal(true);
|
|
125
|
+
}}
|
|
126
|
+
tabIndex="0"
|
|
127
|
+
dataQa={`${planType} On`}
|
|
128
|
+
color={SEA_GREEN}
|
|
129
|
+
weight={themeValues.fontWeight}
|
|
130
|
+
hoverStyles={themeValues.modalLinkHoverFocus}
|
|
131
|
+
extraStyles={`padding-left: 0.25rem;`}
|
|
132
|
+
>
|
|
133
|
+
{`${planType} ${nextAutopayDate}`}
|
|
134
|
+
</Text>
|
|
135
|
+
</Cluster>
|
|
136
|
+
</Box>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
65
141
|
return (
|
|
66
142
|
<Modal
|
|
67
143
|
showModal={() => toggleModal(true)}
|
|
@@ -69,50 +145,7 @@ const AutopayModal = ({
|
|
|
69
145
|
modalOpen={modalOpen}
|
|
70
146
|
{...modalExtraProps}
|
|
71
147
|
>
|
|
72
|
-
{
|
|
73
|
-
<ButtonWithAction
|
|
74
|
-
text={autoPayActive ? `Manage ${planType}` : `Set Up ${planType}`}
|
|
75
|
-
variant="tertiary"
|
|
76
|
-
action={() => {
|
|
77
|
-
toggleModal(true);
|
|
78
|
-
}}
|
|
79
|
-
dataQa="Manage Autopay"
|
|
80
|
-
extraStyles={isMobile && `flex-grow: 1; width: 100%;`}
|
|
81
|
-
/>
|
|
82
|
-
) : (
|
|
83
|
-
<Box
|
|
84
|
-
padding="0"
|
|
85
|
-
onClick={() => {
|
|
86
|
-
toggleModal(true);
|
|
87
|
-
}}
|
|
88
|
-
hoverStyles={hoverStyles}
|
|
89
|
-
activeStyles={activeStyles}
|
|
90
|
-
extraStyles={defaultStyles}
|
|
91
|
-
>
|
|
92
|
-
<Cluster
|
|
93
|
-
justify={isMobile ? "flex-start" : "flex-end"}
|
|
94
|
-
align="center"
|
|
95
|
-
>
|
|
96
|
-
<AutopayOnIcon />
|
|
97
|
-
<Text
|
|
98
|
-
variant="pS"
|
|
99
|
-
onClick={() => toggleModal(true)}
|
|
100
|
-
onKeyPress={e => {
|
|
101
|
-
console.log({ e });
|
|
102
|
-
e.key === "Enter" && toggleModal(true);
|
|
103
|
-
}}
|
|
104
|
-
tabIndex="0"
|
|
105
|
-
dataQa={`${planType} On`}
|
|
106
|
-
color={SEA_GREEN}
|
|
107
|
-
weight={themeValues.fontWeight}
|
|
108
|
-
hoverStyles={themeValues.modalLinkHoverFocus}
|
|
109
|
-
extraStyles={`padding-left: 0.25rem;`}
|
|
110
|
-
>
|
|
111
|
-
{`${planType} ${nextAutopayDate}`}
|
|
112
|
-
</Text>
|
|
113
|
-
</Cluster>
|
|
114
|
-
</Box>
|
|
115
|
-
)}
|
|
148
|
+
{renderAutoPayControl()}
|
|
116
149
|
</Modal>
|
|
117
150
|
);
|
|
118
151
|
};
|
|
@@ -3,6 +3,7 @@ import { GHOST_GREY } from "../../../../constants/colors";
|
|
|
3
3
|
import ButtonWithAction from "../../../atoms/button-with-action";
|
|
4
4
|
import { Box, Cluster } from "../../../atoms/layouts";
|
|
5
5
|
import { AutopayModalModule } from "./AutopayModalModule";
|
|
6
|
+
import RemoveAccountModalModule from "./RemoveAccountModalModule";
|
|
6
7
|
|
|
7
8
|
const InactiveControlsModule = ({
|
|
8
9
|
autoPayEnabled,
|
|
@@ -14,18 +15,26 @@ const InactiveControlsModule = ({
|
|
|
14
15
|
isPaymentPlan,
|
|
15
16
|
nextAutopayDate,
|
|
16
17
|
obligationAssocID,
|
|
18
|
+
dueDate,
|
|
19
|
+
agencyName,
|
|
20
|
+
configType,
|
|
17
21
|
actions
|
|
18
22
|
}) => {
|
|
19
23
|
const [modalOpen, toggleModal] = useState(false);
|
|
20
|
-
const {
|
|
21
|
-
const handleRemoveAccount = () =>
|
|
24
|
+
const { deleteObligationAssoc } = actions;
|
|
25
|
+
const handleRemoveAccount = () => deleteObligationAssoc(obligationAssocID);
|
|
22
26
|
return (
|
|
23
27
|
<Box
|
|
24
28
|
padding={isMobile ? "18px 0 0 0" : "0"}
|
|
25
29
|
border={isMobile ? `1px solid ${GHOST_GREY}` : `0px`}
|
|
26
30
|
borderWidthOverride={isMobile ? `1px 0 0 0` : `0px`}
|
|
27
31
|
>
|
|
28
|
-
<Cluster
|
|
32
|
+
<Cluster
|
|
33
|
+
childGap={autoPayEnabled ? `8px` : "0"}
|
|
34
|
+
nowrap
|
|
35
|
+
justify={isMobile && autoPayEnabled && "center"}
|
|
36
|
+
align={isMobile && autoPayEnabled && "center"}
|
|
37
|
+
>
|
|
29
38
|
{autoPayEnabled && (
|
|
30
39
|
<Box padding="0" extraStyles={`flex-grow: 1;`}>
|
|
31
40
|
<AutopayModalModule
|
|
@@ -35,22 +44,23 @@ const InactiveControlsModule = ({
|
|
|
35
44
|
modalOpen={modalOpen}
|
|
36
45
|
navigateToSettings={navigateToSettings}
|
|
37
46
|
deactivatePaymentSchedule={deactivatePaymentSchedule}
|
|
38
|
-
buttonLinkType
|
|
39
47
|
isMobile={isMobile}
|
|
40
48
|
paymentPlanSchedule={paymentPlanSchedule}
|
|
41
49
|
isPaymentPlan={isPaymentPlan}
|
|
42
50
|
nextAutopayDate={nextAutopayDate}
|
|
43
51
|
obligationAssocID={obligationAssocID}
|
|
52
|
+
dueDate={dueDate}
|
|
53
|
+
controlType="secondary"
|
|
54
|
+
inactive
|
|
44
55
|
/>
|
|
45
56
|
</Box>
|
|
46
57
|
)}
|
|
47
58
|
<Box padding="0" extraStyles={`flex-grow: 1;`}>
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
extraStyles={isMobile && `flex-grow: 1; width: 100%;`}
|
|
59
|
+
<RemoveAccountModalModule
|
|
60
|
+
agencyName={agencyName}
|
|
61
|
+
removeAccount={handleRemoveAccount}
|
|
62
|
+
accountType={configType === "ACCOUNT" ? "Account" : "Property"}
|
|
63
|
+
isMobile={isMobile}
|
|
54
64
|
/>
|
|
55
65
|
</Box>
|
|
56
66
|
</Cluster>
|
|
@@ -28,9 +28,9 @@ const InactiveTitleModule = ({ title, subtitle, autoPayEnabled }) => (
|
|
|
28
28
|
Unable to load account details
|
|
29
29
|
</Detail>
|
|
30
30
|
<Detail variant="extraSmall" as="p" color={BLACK}>
|
|
31
|
-
{`This may mean that the
|
|
31
|
+
{`This may mean that the balance has been paid, or there was an error loading it.${
|
|
32
32
|
autoPayEnabled
|
|
33
|
-
? " You may disable
|
|
33
|
+
? " You may disable autopay for this account by pressing the 'Turn off Autopay' button."
|
|
34
34
|
: ""
|
|
35
35
|
}`}
|
|
36
36
|
</Detail>
|
|
@@ -18,7 +18,9 @@ const PaymentDetailsActions = ({
|
|
|
18
18
|
autoPaySchedule,
|
|
19
19
|
paymentPlanSchedule,
|
|
20
20
|
isPaymentPlan,
|
|
21
|
-
nextAutopayDate
|
|
21
|
+
nextAutopayDate,
|
|
22
|
+
obligationAssocID,
|
|
23
|
+
dueDate
|
|
22
24
|
}) => {
|
|
23
25
|
const planType = isPaymentPlan ? "Payment Plan" : "Autopay";
|
|
24
26
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -38,7 +40,7 @@ const PaymentDetailsActions = ({
|
|
|
38
40
|
createPaymentFromProfile(obligations, config);
|
|
39
41
|
};
|
|
40
42
|
const handleDetailsClick = () => {
|
|
41
|
-
setDetailedObligation(obligations, config);
|
|
43
|
+
setDetailedObligation(obligations, config, obligationAssocID);
|
|
42
44
|
navigateToDetailedObligation(detailsSlug);
|
|
43
45
|
};
|
|
44
46
|
return (
|
|
@@ -120,26 +122,23 @@ const PaymentDetailsActions = ({
|
|
|
120
122
|
modalOpen={modalOpen}
|
|
121
123
|
navigateToSettings={navigateToSettings}
|
|
122
124
|
deactivatePaymentSchedule={deactivatePaymentSchedule}
|
|
123
|
-
|
|
125
|
+
controlType="tertiary"
|
|
124
126
|
isMobile={isMobile}
|
|
125
127
|
paymentPlanSchedule={paymentPlanSchedule}
|
|
126
128
|
isPaymentPlan={isPaymentPlan}
|
|
127
129
|
nextAutopayDate={nextAutopayDate}
|
|
130
|
+
dueDate={dueDate}
|
|
128
131
|
/>
|
|
129
132
|
)}
|
|
130
133
|
</Box>
|
|
131
134
|
{!isMobile && (
|
|
132
|
-
<Box
|
|
133
|
-
padding={isMobile ? "0 0 0 8px" : "0"}
|
|
134
|
-
extraStyles={isMobile && `flex-grow: 1;`}
|
|
135
|
-
>
|
|
135
|
+
<Box padding={"0"}>
|
|
136
136
|
<ButtonWithAction
|
|
137
137
|
isLoading={isLoading}
|
|
138
138
|
action={() => handleClick(obligations)}
|
|
139
139
|
text="Pay Now"
|
|
140
140
|
variant={isMobile ? "smallSecondary" : "secondary"}
|
|
141
141
|
dataQa="Pay Now"
|
|
142
|
-
extraStyles={isMobile && `flex-grow: 1; width: 100%;`}
|
|
143
142
|
/>
|
|
144
143
|
</Box>
|
|
145
144
|
)}
|
|
@@ -152,7 +151,7 @@ const PaymentDetailsActions = ({
|
|
|
152
151
|
text="Pay Now"
|
|
153
152
|
variant={isMobile ? "smallSecondary" : "secondary"}
|
|
154
153
|
dataQa="Pay Now"
|
|
155
|
-
extraStyles={isMobile && `flex-grow: 1; width: 100
|
|
154
|
+
extraStyles={isMobile && `flex-grow: 1; width: 100%; margin: 0;`}
|
|
156
155
|
/>
|
|
157
156
|
</Box>
|
|
158
157
|
)}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import Modal from "../../modal";
|
|
3
|
+
import ButtonWithAction from "../../../atoms/button-with-action";
|
|
4
|
+
import { Box } from "../../../atoms/layouts";
|
|
5
|
+
|
|
6
|
+
const RemoveAccountModalModule = ({
|
|
7
|
+
agencyName,
|
|
8
|
+
obligations = [],
|
|
9
|
+
removeAccount,
|
|
10
|
+
accountType,
|
|
11
|
+
isMobile
|
|
12
|
+
}) => {
|
|
13
|
+
const [modalIsOpen, setModalIsOpen] = useState(false);
|
|
14
|
+
const lastItem = [...obligations].pop();
|
|
15
|
+
const accounts = obligations.length
|
|
16
|
+
? obligations.reduce((acc, curr) => {
|
|
17
|
+
const account = curr.details.description;
|
|
18
|
+
const formattedAccount =
|
|
19
|
+
curr !== lastItem ? `${account} and ` : `${account}`;
|
|
20
|
+
return formattedAccount === agencyName
|
|
21
|
+
? agencyName
|
|
22
|
+
: acc + formattedAccount;
|
|
23
|
+
}, `${agencyName} - `)
|
|
24
|
+
: "";
|
|
25
|
+
const identifier =
|
|
26
|
+
accountType === "Account" && obligations.length > 1
|
|
27
|
+
? "accounts"
|
|
28
|
+
: accountType === "Property" && obligations.length > 1
|
|
29
|
+
? "properties"
|
|
30
|
+
: accountType.toLowerCase();
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Modal
|
|
34
|
+
showModal={() => setModalIsOpen(true)}
|
|
35
|
+
hideModal={() => setModalIsOpen(false)}
|
|
36
|
+
modalOpen={modalIsOpen}
|
|
37
|
+
modalHeaderText={`Remove ${accountType}`}
|
|
38
|
+
modalBodyText={`Are you sure you want to remove the ${identifier} ${accounts} from your profile? Any autopay scheduled against ${
|
|
39
|
+
obligations.length > 1 ? "them" : "it"
|
|
40
|
+
} will be deactivated.`}
|
|
41
|
+
continueButtonText="Remove"
|
|
42
|
+
continueAction={() => {
|
|
43
|
+
removeAccount();
|
|
44
|
+
setModalIsOpen(false);
|
|
45
|
+
}}
|
|
46
|
+
useDangerButton
|
|
47
|
+
>
|
|
48
|
+
<Box padding="0" extraStyles={`flex-grow: 1;`}>
|
|
49
|
+
<ButtonWithAction
|
|
50
|
+
text="Remove"
|
|
51
|
+
variant="secondary"
|
|
52
|
+
action={() => setModalIsOpen(true)}
|
|
53
|
+
dataQa="Remove Account"
|
|
54
|
+
extraStyles={
|
|
55
|
+
isMobile ? `flex-grow: 1; width: 100%; margin: 0;` : `flex-grow: 1;`
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
</Box>
|
|
59
|
+
</Modal>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
export default RemoveAccountModalModule;
|
|
@@ -4,6 +4,7 @@ import AmountModule from "./AmountModule";
|
|
|
4
4
|
import PaymentDetailsActions from "./PaymentDetailsActions";
|
|
5
5
|
import InactiveControlsModule from "./InactiveControlsModule";
|
|
6
6
|
import InactiveTitleModule from "./InactiveTitleModule";
|
|
7
|
+
import RemoveAccountModalModule from "./RemoveAccountModalModule";
|
|
7
8
|
|
|
8
9
|
export {
|
|
9
10
|
IconModule,
|
|
@@ -11,5 +12,6 @@ export {
|
|
|
11
12
|
AmountModule,
|
|
12
13
|
PaymentDetailsActions,
|
|
13
14
|
InactiveControlsModule,
|
|
14
|
-
InactiveTitleModule
|
|
15
|
+
InactiveTitleModule,
|
|
16
|
+
RemoveAccountModalModule
|
|
15
17
|
};
|
|
@@ -10,7 +10,14 @@ import LabeledAmount from "../../atoms/labeled-amount";
|
|
|
10
10
|
import LineItem from "../../atoms/line-item";
|
|
11
11
|
import Title from "../../atoms/title";
|
|
12
12
|
import SolidDivider from "../../atoms/solid-divider";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
FONT_WEIGHT_BOLD,
|
|
15
|
+
FONT_WEIGHT_REGULAR
|
|
16
|
+
} from "../../../constants/style_constants";
|
|
17
|
+
import { ATHENS_GREY } from "../../../constants/colors";
|
|
18
|
+
import ButtonWithAction from "../../atoms/button-with-action";
|
|
19
|
+
import Text from "../../atoms/text";
|
|
20
|
+
import { noop } from "../../../util/general";
|
|
14
21
|
|
|
15
22
|
const PaymentDetailsContent = ({
|
|
16
23
|
lineItemElems,
|
|
@@ -18,11 +25,49 @@ const PaymentDetailsContent = ({
|
|
|
18
25
|
subtotal,
|
|
19
26
|
total,
|
|
20
27
|
variant,
|
|
21
|
-
themeValues
|
|
28
|
+
themeValues,
|
|
29
|
+
hasVoidablePaymentsSection,
|
|
30
|
+
voidableTransactionDetails,
|
|
31
|
+
voidableAmountPaid,
|
|
32
|
+
partialVoidAction
|
|
22
33
|
}) => (
|
|
23
34
|
<Stack childGap="16px">
|
|
24
35
|
{lineItemElems}
|
|
25
|
-
|
|
36
|
+
{hasVoidablePaymentsSection && (
|
|
37
|
+
<Box background={ATHENS_GREY}>
|
|
38
|
+
<Text variant="p" color={themeValues.text} weight="400">
|
|
39
|
+
Paid
|
|
40
|
+
</Text>
|
|
41
|
+
{voidableTransactionDetails.map(t => (
|
|
42
|
+
<Cluster key={t.id} justify="space-between" align="center">
|
|
43
|
+
<Cluster padding="0" align="center">
|
|
44
|
+
<Box padding="0">{t.voidText}</Box>
|
|
45
|
+
<ButtonWithAction
|
|
46
|
+
variant="ghost"
|
|
47
|
+
action={() => partialVoidAction(t)}
|
|
48
|
+
text="Void"
|
|
49
|
+
extraStyles={"min-width: 75px; margin: 0px;"}
|
|
50
|
+
textExtraStyles={`font-weight: ${FONT_WEIGHT_REGULAR}; font-size: 16px;`}
|
|
51
|
+
/>
|
|
52
|
+
</Cluster>
|
|
53
|
+
<Box padding="0" key={t.id}>
|
|
54
|
+
{displayCurrency(t.amount_given)}
|
|
55
|
+
</Box>
|
|
56
|
+
</Cluster>
|
|
57
|
+
))}
|
|
58
|
+
<Box padding="8px 0px 16px 0px">
|
|
59
|
+
<SolidDivider />
|
|
60
|
+
</Box>
|
|
61
|
+
<LabeledAmount
|
|
62
|
+
fontWeight={FONT_WEIGHT_REGULAR}
|
|
63
|
+
label="Amount paid"
|
|
64
|
+
amount={displayCurrency(voidableAmountPaid)}
|
|
65
|
+
/>
|
|
66
|
+
</Box>
|
|
67
|
+
)}
|
|
68
|
+
{!hasVoidablePaymentsSection && !!lineItemElems.length && (
|
|
69
|
+
<SolidDivider /> // avoids duplicate dividers -> case of voidable payment section, that acts as divider
|
|
70
|
+
)}
|
|
26
71
|
<Box padding="0.5rem 0">
|
|
27
72
|
<LabeledAmount
|
|
28
73
|
variant={themeValues.labeledAmountSubtotal}
|
|
@@ -35,7 +80,7 @@ const PaymentDetailsContent = ({
|
|
|
35
80
|
<LabeledAmount
|
|
36
81
|
as="p"
|
|
37
82
|
variant={themeValues.labeledAmountTotal}
|
|
38
|
-
label="Total"
|
|
83
|
+
label={hasVoidablePaymentsSection ? "Remaining amount due" : "Total"}
|
|
39
84
|
amount={displayCurrency(total)}
|
|
40
85
|
extraStyles={variant === "small" && `font-weight: ${FONT_WEIGHT_BOLD};`}
|
|
41
86
|
/>
|
|
@@ -85,7 +130,13 @@ const PaymentDetails = ({
|
|
|
85
130
|
collapsibleOnMobile = true,
|
|
86
131
|
isMobile,
|
|
87
132
|
supportsTouch,
|
|
88
|
-
themeValues
|
|
133
|
+
themeValues,
|
|
134
|
+
// partial void section (optional)
|
|
135
|
+
hasVoidablePaymentsSection = false,
|
|
136
|
+
voidableTransactionDetails = [],
|
|
137
|
+
partialVoidAction = noop,
|
|
138
|
+
voidableAmountPaid = 0
|
|
139
|
+
// end partial void section
|
|
89
140
|
}) => {
|
|
90
141
|
const [isOpen, setIsOpen] = useState(initiallyOpen);
|
|
91
142
|
const fees = _fees
|
|
@@ -118,12 +169,34 @@ const PaymentDetails = ({
|
|
|
118
169
|
<SolidDivider />
|
|
119
170
|
<Box padding="8px" />
|
|
120
171
|
<PaymentDetailsContent
|
|
121
|
-
{...{
|
|
172
|
+
{...{
|
|
173
|
+
lineItemElems,
|
|
174
|
+
feeElems,
|
|
175
|
+
subtotal,
|
|
176
|
+
total,
|
|
177
|
+
themeValues,
|
|
178
|
+
variant,
|
|
179
|
+
hasVoidablePaymentsSection,
|
|
180
|
+
voidableTransactionDetails,
|
|
181
|
+
voidableAmountPaid,
|
|
182
|
+
partialVoidAction
|
|
183
|
+
}}
|
|
122
184
|
/>
|
|
123
185
|
</Stack>
|
|
124
186
|
) : (
|
|
125
187
|
<PaymentDetailsContent
|
|
126
|
-
{...{
|
|
188
|
+
{...{
|
|
189
|
+
lineItemElems,
|
|
190
|
+
feeElems,
|
|
191
|
+
subtotal,
|
|
192
|
+
total,
|
|
193
|
+
themeValues,
|
|
194
|
+
variant,
|
|
195
|
+
hasVoidablePaymentsSection,
|
|
196
|
+
voidableTransactionDetails,
|
|
197
|
+
voidableAmountPaid,
|
|
198
|
+
partialVoidAction
|
|
199
|
+
}}
|
|
127
200
|
/>
|
|
128
201
|
);
|
|
129
202
|
const title = hideTitle ? (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { text, boolean } from "@storybook/addon-knobs";
|
|
2
|
+
import { text, boolean, number } from "@storybook/addon-knobs";
|
|
3
3
|
import PaymentDetails from "./PaymentDetails";
|
|
4
4
|
import page from "../../../../.storybook/page";
|
|
5
5
|
|
|
@@ -52,18 +52,108 @@ const payment = {
|
|
|
52
52
|
total: 79033
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
+
const voidableTransactionDetails = [
|
|
56
|
+
{
|
|
57
|
+
status: "successful",
|
|
58
|
+
id: 3,
|
|
59
|
+
warnings: [],
|
|
60
|
+
payment_type: "Card Payment",
|
|
61
|
+
amount_given: 100,
|
|
62
|
+
amount_processed: 100,
|
|
63
|
+
change_due: 0,
|
|
64
|
+
service_fee: 0,
|
|
65
|
+
credit_card: {
|
|
66
|
+
last_four: "0043"
|
|
67
|
+
},
|
|
68
|
+
bank_account: {
|
|
69
|
+
account_number_last_four: null
|
|
70
|
+
},
|
|
71
|
+
voidText: "Card ending in 0043"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
status: "successful",
|
|
75
|
+
id: 5,
|
|
76
|
+
warnings: [],
|
|
77
|
+
payment_type: "Card Payment",
|
|
78
|
+
amount_given: 100,
|
|
79
|
+
amount_processed: 100,
|
|
80
|
+
change_due: 0,
|
|
81
|
+
service_fee: 0,
|
|
82
|
+
credit_card: {
|
|
83
|
+
last_four: "0043"
|
|
84
|
+
},
|
|
85
|
+
bank_account: {
|
|
86
|
+
account_number_last_four: null
|
|
87
|
+
},
|
|
88
|
+
voidText: "Card ending in 0043"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
status: "successful",
|
|
92
|
+
id: 6,
|
|
93
|
+
warnings: [],
|
|
94
|
+
payment_type: "Check Payment",
|
|
95
|
+
amount_given: 200,
|
|
96
|
+
amount_processed: 200,
|
|
97
|
+
change_due: 0,
|
|
98
|
+
service_fee: 0,
|
|
99
|
+
credit_card: {
|
|
100
|
+
last_four: null
|
|
101
|
+
},
|
|
102
|
+
bank_account: {
|
|
103
|
+
account_number_last_four: "123"
|
|
104
|
+
},
|
|
105
|
+
voidText: "Account ending in 123"
|
|
106
|
+
}
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
const lineItems2 = [
|
|
110
|
+
{
|
|
111
|
+
amount: 500,
|
|
112
|
+
description: "Point of Sale Manual Entry - CLERK",
|
|
113
|
+
quantity: 1,
|
|
114
|
+
subDescription: "Test description"
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
|
|
55
118
|
export const paymentDetails = () => (
|
|
56
119
|
<PaymentDetails
|
|
57
|
-
subtotal={text("subtotal", payment.subtotal, "props")}
|
|
120
|
+
subtotal={text("subtotal", String(payment.subtotal), "props")}
|
|
58
121
|
lineItems={payment.lineItems}
|
|
59
122
|
fees={payment.fees}
|
|
60
|
-
total={text("total", payment.total, "props")}
|
|
123
|
+
total={text("total", String(payment.total), "props")}
|
|
124
|
+
collapsibleOnMobile={boolean("collapsibleOnMobile", false, "props")}
|
|
125
|
+
initiallyOpen={boolean("initiallyOpen", true, "props")}
|
|
126
|
+
hideTitle={boolean("hideTitle", false, "props")}
|
|
127
|
+
/>
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
export const paymentDetailsWithPartialVoids = () => (
|
|
131
|
+
<PaymentDetails
|
|
132
|
+
subtotal={100}
|
|
133
|
+
lineItems={lineItems2}
|
|
134
|
+
fees={[]}
|
|
135
|
+
total={100}
|
|
61
136
|
collapsibleOnMobile={boolean("collapsibleOnMobile", false, "props")}
|
|
62
137
|
initiallyOpen={boolean("initiallyOpen", true, "props")}
|
|
63
138
|
hideTitle={boolean("hideTitle", false, "props")}
|
|
139
|
+
// partial voids section (optional)
|
|
140
|
+
hasVoidablePaymentsSection={boolean(
|
|
141
|
+
"hasVoidablePaymentsSection",
|
|
142
|
+
true,
|
|
143
|
+
"props"
|
|
144
|
+
)}
|
|
145
|
+
voidableTransactionDetails={voidableTransactionDetails}
|
|
146
|
+
partialVoidAction={transaction => {
|
|
147
|
+
console.log(`Your function to void payment id: ${transaction.id}`);
|
|
148
|
+
}}
|
|
149
|
+
voidableAmountPaid={number("voidableAmountPaid", 400)}
|
|
150
|
+
// end partial void section
|
|
64
151
|
/>
|
|
65
152
|
);
|
|
66
153
|
|
|
154
|
+
paymentDetailsWithPartialVoids.storyName =
|
|
155
|
+
"Payment Details (with partial voids)";
|
|
156
|
+
|
|
67
157
|
const story = page({
|
|
68
158
|
title: "Components|Molecules/PaymentDetails",
|
|
69
159
|
Component: PaymentDetails
|
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
BRIGHT_GREY,
|
|
5
5
|
GHOST_GREY,
|
|
6
6
|
ATHENS_GREY,
|
|
7
|
-
TRANSPARENT
|
|
7
|
+
TRANSPARENT,
|
|
8
|
+
COOL_GREY_05
|
|
8
9
|
} from "../../../constants/colors";
|
|
9
10
|
import Text from "../../atoms/text";
|
|
10
11
|
import { InternalLink } from "../../atoms/link";
|
|
@@ -18,7 +19,7 @@ import { fallbackValues } from "./TabSidebar.theme";
|
|
|
18
19
|
const TabSidebar = ({ links, isMobile, themeValues }) => (
|
|
19
20
|
<Box
|
|
20
21
|
padding="0"
|
|
21
|
-
background={
|
|
22
|
+
background={COOL_GREY_05}
|
|
22
23
|
minHeight="100%"
|
|
23
24
|
role="region"
|
|
24
25
|
aria-label="Profile tabs"
|
|
@@ -4,6 +4,7 @@ import { fallbackValues } from "../templates.theme";
|
|
|
4
4
|
import { themeComponent } from "../../../util/themeUtils";
|
|
5
5
|
import withWindowResize from "../../withWindowSize";
|
|
6
6
|
import { Box, Center, Cover } from "../../atoms/layouts";
|
|
7
|
+
import { COOL_GREY_05 } from "../../../constants/colors";
|
|
7
8
|
|
|
8
9
|
const CenterSingle = ({
|
|
9
10
|
header,
|
|
@@ -23,7 +24,7 @@ const CenterSingle = ({
|
|
|
23
24
|
<Box
|
|
24
25
|
padding="0"
|
|
25
26
|
minWidth="100%"
|
|
26
|
-
background={
|
|
27
|
+
background={COOL_GREY_05}
|
|
27
28
|
extraStyles="flex-grow: 1;"
|
|
28
29
|
>
|
|
29
30
|
<Cover centerOverride={isMobile && !centeredMobileContent}>
|
|
@@ -4,6 +4,7 @@ import { fallbackValues } from "../templates.theme";
|
|
|
4
4
|
import { themeComponent } from "../../../util/themeUtils";
|
|
5
5
|
import withWindowResize from "../../withWindowSize";
|
|
6
6
|
import { Box, Center, Cover, Stack } from "../../atoms/layouts";
|
|
7
|
+
import { COOL_GREY_05 } from "../../../constants/colors";
|
|
7
8
|
|
|
8
9
|
const CenterStack = ({
|
|
9
10
|
header,
|
|
@@ -23,7 +24,7 @@ const CenterStack = ({
|
|
|
23
24
|
<Box
|
|
24
25
|
padding="0"
|
|
25
26
|
minWidth="100%"
|
|
26
|
-
background={
|
|
27
|
+
background={COOL_GREY_05}
|
|
27
28
|
extraStyles="flex-grow: 1;"
|
|
28
29
|
>
|
|
29
30
|
<Cover>
|