@comicrelief/component-library 8.52.2 → 8.53.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/.github/workflows/main.yml +1 -1
- package/dist/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.md +1 -0
- package/dist/components/Molecules/CTA/CTAMultiCard/__snapshots__/CTAMultiCard.test.js.snap +280 -232
- package/dist/components/Molecules/CTA/CTASingleCard/__snapshots__/CTASingleCard.test.js.snap +68 -28
- package/dist/components/Molecules/CTA/shared/CTACard.js +1 -1
- package/dist/components/Molecules/CTA/shared/CTACard.style.js +11 -7
- package/dist/components/Organisms/Donate/Donate.js +3 -0
- package/dist/components/Organisms/Donate/Form/Form.js +0 -1
- package/dist/components/Organisms/DonateBanner/DonateBanner.js +132 -0
- package/dist/components/Organisms/DonateBanner/DonateBanner.md +168 -0
- package/dist/components/Organisms/DonateBanner/DonateBanner.style.js +291 -0
- package/dist/components/Organisms/DonateBanner/DonateBanner.test.js +134 -0
- package/dist/components/Organisms/DonateBanner/Form/Form.js +214 -0
- package/dist/components/Organisms/DonateBanner/Form/PopUpComponent.js +70 -0
- package/dist/components/Organisms/DonateBanner/GivingSelector/GivingSelector.js +50 -0
- package/dist/components/Organisms/DonateBanner/GivingSelector/GivingSelector.style.js +73 -0
- package/dist/components/Organisms/DonateBanner/MoneyBuy/MoneyBuy.js +83 -0
- package/dist/components/Organisms/DonateBanner/__snapshots__/DonateBanner.test.js.snap +3170 -0
- package/dist/components/Organisms/DonateBanner/_utils.js +41 -0
- package/dist/components/Organisms/DonateBanner/assets/close.svg +3 -0
- package/dist/components/Organisms/DonateBanner/dev-data/data-high-value.js +33 -0
- package/dist/components/Organisms/DonateBanner/dev-data/data-monthly.js +22 -0
- package/dist/components/Organisms/DonateBanner/dev-data/data-single.js +22 -0
- package/dist/components/Organisms/DonateBanner/dev-data/data.js +33 -0
- package/dist/index.js +7 -0
- package/package.json +1 -1
- package/src/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.md +1 -0
- package/src/components/Molecules/CTA/CTAMultiCard/__snapshots__/CTAMultiCard.test.js.snap +280 -232
- package/src/components/Molecules/CTA/CTASingleCard/__snapshots__/CTASingleCard.test.js.snap +68 -28
- package/src/components/Molecules/CTA/shared/CTACard.js +6 -3
- package/src/components/Molecules/CTA/shared/CTACard.style.js +8 -0
- package/src/components/Organisms/Donate/Donate.js +5 -0
- package/src/components/Organisms/Donate/Form/Form.js +0 -1
- package/src/components/Organisms/DonateBanner/DonateBanner.js +210 -0
- package/src/components/Organisms/DonateBanner/DonateBanner.md +168 -0
- package/src/components/Organisms/DonateBanner/DonateBanner.style.js +320 -0
- package/src/components/Organisms/DonateBanner/DonateBanner.test.js +151 -0
- package/src/components/Organisms/DonateBanner/Form/Form.js +332 -0
- package/src/components/Organisms/DonateBanner/Form/PopUpComponent.js +110 -0
- package/src/components/Organisms/DonateBanner/GivingSelector/GivingSelector.js +61 -0
- package/src/components/Organisms/DonateBanner/GivingSelector/GivingSelector.style.js +71 -0
- package/src/components/Organisms/DonateBanner/MoneyBuy/MoneyBuy.js +58 -0
- package/src/components/Organisms/DonateBanner/__snapshots__/DonateBanner.test.js.snap +3170 -0
- package/src/components/Organisms/DonateBanner/_utils.js +34 -0
- package/src/components/Organisms/DonateBanner/assets/close.svg +3 -0
- package/src/components/Organisms/DonateBanner/dev-data/data-high-value.js +41 -0
- package/src/components/Organisms/DonateBanner/dev-data/data-monthly.js +23 -0
- package/src/components/Organisms/DonateBanner/dev-data/data-single.js +23 -0
- package/src/components/Organisms/DonateBanner/dev-data/data.js +41 -0
- package/src/index.js +1 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useState, useRef, useEffect, useCallback
|
|
3
|
+
} from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
|
|
6
|
+
import PopUpComponent from './PopUpComponent';
|
|
7
|
+
import MoneyBuy from '../MoneyBuy/MoneyBuy';
|
|
8
|
+
import {
|
|
9
|
+
handleDonateSubmission,
|
|
10
|
+
isAmountValid,
|
|
11
|
+
amountFormatter
|
|
12
|
+
} from '../../../../utils/Membership';
|
|
13
|
+
import {
|
|
14
|
+
Button,
|
|
15
|
+
Copy,
|
|
16
|
+
Error,
|
|
17
|
+
FormFieldset,
|
|
18
|
+
FormWrapper,
|
|
19
|
+
Label,
|
|
20
|
+
Form,
|
|
21
|
+
MoneyBuys,
|
|
22
|
+
AmountField,
|
|
23
|
+
OuterFieldset,
|
|
24
|
+
Legend,
|
|
25
|
+
PrimaryTitleText
|
|
26
|
+
} from '../DonateBanner.style';
|
|
27
|
+
import GivingSelector from '../GivingSelector/GivingSelector';
|
|
28
|
+
|
|
29
|
+
const Signup = ({
|
|
30
|
+
data: { singleGiving, regularGiving },
|
|
31
|
+
donateLink,
|
|
32
|
+
otherAmountText,
|
|
33
|
+
clientID,
|
|
34
|
+
cartID,
|
|
35
|
+
mbshipID,
|
|
36
|
+
donateOrientation = 'right',
|
|
37
|
+
noMoneyBuys = false,
|
|
38
|
+
popUpText,
|
|
39
|
+
chooseAmountText = null,
|
|
40
|
+
monthlyChooseAmountText = null,
|
|
41
|
+
submitButtonColor = 'red',
|
|
42
|
+
changeGivingType,
|
|
43
|
+
givingType = null,
|
|
44
|
+
hasTopImage = false,
|
|
45
|
+
shouldShowTitleSection = false,
|
|
46
|
+
...rest
|
|
47
|
+
}) => {
|
|
48
|
+
const [errorMsg, setErrorMsg] = useState(false);
|
|
49
|
+
const [amountDonate, setAmountDonate] = useState(10);
|
|
50
|
+
const [moneyBuyCopy, setMoneyBuyCopy] = useState(true);
|
|
51
|
+
const [popOpen, setPopOpen] = useState(false);
|
|
52
|
+
// In order to keep track of whether the user has ever been shown the popup
|
|
53
|
+
const [popUpShown, setPopUpShown] = useState(false);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (givingType) {
|
|
57
|
+
const givingData = givingType === 'single' ? singleGiving : regularGiving;
|
|
58
|
+
|
|
59
|
+
// Check the 2nd moneybuy exists before using it;
|
|
60
|
+
// 'philantrophy' carts have been set up to use a single moneybuy.
|
|
61
|
+
// See ENG-1685 for more details
|
|
62
|
+
const thisAmount = givingData.moneybuys[1]
|
|
63
|
+
? givingData.moneybuys[1].value
|
|
64
|
+
: givingData.moneybuys[0].value;
|
|
65
|
+
|
|
66
|
+
setAmountDonate(thisAmount);
|
|
67
|
+
}
|
|
68
|
+
// Pass givingType up to parent for copy-switching logic:
|
|
69
|
+
changeGivingType(givingType);
|
|
70
|
+
}, [givingType, singleGiving, regularGiving, changeGivingType]);
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (givingType) {
|
|
74
|
+
const givingData = givingType === 'single' ? singleGiving : regularGiving;
|
|
75
|
+
|
|
76
|
+
let moneyBuyUpdatedDescription = otherAmountText;
|
|
77
|
+
|
|
78
|
+
givingData.moneybuys.map((moneyBuy, index) => {
|
|
79
|
+
// Only show the MB-associated copy when we're actually showing moneybuys
|
|
80
|
+
if (moneyBuy.value === amountDonate && !noMoneyBuys) {
|
|
81
|
+
moneyBuyUpdatedDescription = moneyBuy.description;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
index === 1
|
|
86
|
+
&& amountDonate === undefined
|
|
87
|
+
&& (setMoneyBuyCopy(moneyBuy.description),
|
|
88
|
+
setAmountDonate(moneyBuy.value))
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!isAmountValid(amountDonate)) {
|
|
93
|
+
if (moneyBuyCopy) setMoneyBuyCopy(false);
|
|
94
|
+
if (!errorMsg) setErrorMsg(true);
|
|
95
|
+
} else {
|
|
96
|
+
if (errorMsg) setErrorMsg(false);
|
|
97
|
+
setMoneyBuyCopy(moneyBuyUpdatedDescription);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}, [
|
|
101
|
+
errorMsg,
|
|
102
|
+
moneyBuyCopy,
|
|
103
|
+
singleGiving,
|
|
104
|
+
regularGiving,
|
|
105
|
+
givingType,
|
|
106
|
+
amountDonate,
|
|
107
|
+
otherAmountText,
|
|
108
|
+
noMoneyBuys
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
// Updates our flag that differentiates between the popup
|
|
112
|
+
// being *currently* open and it *ever* having been shown to user
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (popOpen && !popUpShown) setPopUpShown(true);
|
|
115
|
+
}, [popOpen, popUpShown]);
|
|
116
|
+
|
|
117
|
+
// On load, determine what should actually be the default giving type
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
const newGivingType = singleGiving !== null ? 'single' : 'monthly';
|
|
120
|
+
|
|
121
|
+
changeGivingType(newGivingType);
|
|
122
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
123
|
+
}, []);
|
|
124
|
+
|
|
125
|
+
const submitDonation = (
|
|
126
|
+
event,
|
|
127
|
+
amount,
|
|
128
|
+
clientId,
|
|
129
|
+
cartId,
|
|
130
|
+
mbshipId,
|
|
131
|
+
donateURL
|
|
132
|
+
) => {
|
|
133
|
+
event.preventDefault();
|
|
134
|
+
if (isAmountValid(amount) && !errorMsg) {
|
|
135
|
+
handleDonateSubmission(
|
|
136
|
+
amount,
|
|
137
|
+
clientId,
|
|
138
|
+
cartId,
|
|
139
|
+
mbshipId,
|
|
140
|
+
donateURL,
|
|
141
|
+
givingType,
|
|
142
|
+
popUpShown
|
|
143
|
+
);
|
|
144
|
+
} else {
|
|
145
|
+
setErrorMsg(true);
|
|
146
|
+
setMoneyBuyCopy(false);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Create money buy boxes
|
|
151
|
+
const givingData = givingType === 'single' ? singleGiving : regularGiving;
|
|
152
|
+
const showGivingSelector = singleGiving !== null && regularGiving !== null;
|
|
153
|
+
|
|
154
|
+
// Create ref for amount input
|
|
155
|
+
const amountRef = useRef(null);
|
|
156
|
+
// Create ref for amount button
|
|
157
|
+
const buttonRef = useRef(null);
|
|
158
|
+
|
|
159
|
+
const handleClickOutside = useCallback(event => {
|
|
160
|
+
if (!errorMsg) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (buttonRef.current && event.target === buttonRef.current) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (amountRef.current && !amountRef.current.contains(event.target)) {
|
|
169
|
+
// Check the 2nd moneybuy exists before using it;
|
|
170
|
+
// 'philantrophy' carts have been set up to use a single moneybuy.
|
|
171
|
+
// See ENG-1685 for more details
|
|
172
|
+
const thisAmount = givingData.moneybuys[1]
|
|
173
|
+
? givingData.moneybuys[1].value
|
|
174
|
+
: givingData.moneybuys[0].value;
|
|
175
|
+
|
|
176
|
+
setAmountDonate(thisAmount);
|
|
177
|
+
}
|
|
178
|
+
}, [errorMsg, givingData]);
|
|
179
|
+
|
|
180
|
+
// Listen for click outside custom amount input if there is no value entered.
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
// Bind the event listener
|
|
183
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
184
|
+
return () => {
|
|
185
|
+
// Unbind the event listener on clean up
|
|
186
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
187
|
+
};
|
|
188
|
+
}, [errorMsg, handleClickOutside]);
|
|
189
|
+
|
|
190
|
+
// Create function to conditionally render button text
|
|
191
|
+
const renderButtonText = () => {
|
|
192
|
+
if (errorMsg) {
|
|
193
|
+
return 'Donate';
|
|
194
|
+
}
|
|
195
|
+
if (givingType === 'single') {
|
|
196
|
+
return `Donate £${amountDonate} now`;
|
|
197
|
+
}
|
|
198
|
+
return `Donate £${amountDonate} monthly`;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const defaultChooseAmountText = `${noMoneyBuys ? 'Enter' : 'Choose'} an amount to give`;
|
|
202
|
+
const thisChooseAmountText = givingType === 'monthly' && monthlyChooseAmountText
|
|
203
|
+
? monthlyChooseAmountText
|
|
204
|
+
: (chooseAmountText || defaultChooseAmountText);
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<FormWrapper
|
|
208
|
+
donateOrientation={donateOrientation}
|
|
209
|
+
shouldShowTitleSection={shouldShowTitleSection}
|
|
210
|
+
>
|
|
211
|
+
{ popOpen && <PopUpComponent popUpText={popUpText} setPopOpen={setPopOpen} /> }
|
|
212
|
+
|
|
213
|
+
<Form
|
|
214
|
+
donateOrientation={donateOrientation}
|
|
215
|
+
hasTopImage={hasTopImage}
|
|
216
|
+
shouldShowTitleSection={shouldShowTitleSection}
|
|
217
|
+
onSubmit={e => submitDonation(
|
|
218
|
+
e,
|
|
219
|
+
amountDonate,
|
|
220
|
+
clientID,
|
|
221
|
+
cartID,
|
|
222
|
+
mbshipID,
|
|
223
|
+
donateLink
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
>
|
|
227
|
+
<OuterFieldset>
|
|
228
|
+
<Legend>
|
|
229
|
+
<PrimaryTitleText tag="span" color="black">
|
|
230
|
+
{thisChooseAmountText}
|
|
231
|
+
</PrimaryTitleText>
|
|
232
|
+
</Legend>
|
|
233
|
+
{showGivingSelector && (
|
|
234
|
+
<GivingSelector
|
|
235
|
+
givingType={givingType}
|
|
236
|
+
changeGivingType={data => changeGivingType(data)}
|
|
237
|
+
setPopOpen={setPopOpen}
|
|
238
|
+
mbshipID={mbshipID}
|
|
239
|
+
/>
|
|
240
|
+
)}
|
|
241
|
+
{!noMoneyBuys && givingType && (
|
|
242
|
+
<MoneyBuys>
|
|
243
|
+
{givingData.moneybuys.map(({ value }, index) => (
|
|
244
|
+
<MoneyBuy
|
|
245
|
+
isSelected={amountDonate === value}
|
|
246
|
+
amount={value.toString()}
|
|
247
|
+
description={`£${amountFormatter(value)}`}
|
|
248
|
+
setOtherAmount={() => setAmountDonate(value)}
|
|
249
|
+
key={value}
|
|
250
|
+
name={`${mbshipID}--moneyBuy${index + 1}`}
|
|
251
|
+
id={`${mbshipID}--moneyBuy-box${index + 1}`}
|
|
252
|
+
/>
|
|
253
|
+
))}
|
|
254
|
+
</MoneyBuys>
|
|
255
|
+
)}
|
|
256
|
+
<FormFieldset>
|
|
257
|
+
{!noMoneyBuys && (
|
|
258
|
+
<Label size="s" weight="500" color="black">
|
|
259
|
+
Enter another amount
|
|
260
|
+
</Label>
|
|
261
|
+
)}
|
|
262
|
+
<AmountField
|
|
263
|
+
$noMoneyBuys={noMoneyBuys}
|
|
264
|
+
step="0.01"
|
|
265
|
+
name="membership_amount"
|
|
266
|
+
type="string"
|
|
267
|
+
inputBorderColor={isAmountValid(amountDonate) === false}
|
|
268
|
+
prefix="£"
|
|
269
|
+
label={noMoneyBuys ? 'Donation amount' : 'Other donation amount'}
|
|
270
|
+
errorMsg=""
|
|
271
|
+
id={`${mbshipID}--MoneyBuy-userInput`}
|
|
272
|
+
showLabel={false}
|
|
273
|
+
{...rest}
|
|
274
|
+
max="25000"
|
|
275
|
+
min="1"
|
|
276
|
+
value={amountDonate}
|
|
277
|
+
pattern="^[0-9]+([,.][0-9]{0,2})?$" // this only applies on submit
|
|
278
|
+
placeholder="0.00"
|
|
279
|
+
onChange={e => setAmountDonate(e.target.value.trim())}
|
|
280
|
+
ref={amountRef}
|
|
281
|
+
/>
|
|
282
|
+
</FormFieldset>
|
|
283
|
+
{amountDonate >= 1 && moneyBuyCopy && (
|
|
284
|
+
<Copy>
|
|
285
|
+
<strong>{`£${amountDonate} `}</strong>
|
|
286
|
+
{moneyBuyCopy}
|
|
287
|
+
</Copy>
|
|
288
|
+
)}
|
|
289
|
+
|
|
290
|
+
{errorMsg && (
|
|
291
|
+
<Error className="error--amount" tag="p">
|
|
292
|
+
Please enter an amount between £1 and £25000 and up to 2 decimal
|
|
293
|
+
places
|
|
294
|
+
</Error>
|
|
295
|
+
)}
|
|
296
|
+
|
|
297
|
+
<Button
|
|
298
|
+
type="submit"
|
|
299
|
+
color={submitButtonColor}
|
|
300
|
+
ref={buttonRef}
|
|
301
|
+
// Used by analytics:
|
|
302
|
+
className="Button_DonateWidget"
|
|
303
|
+
>
|
|
304
|
+
{renderButtonText()}
|
|
305
|
+
</Button>
|
|
306
|
+
|
|
307
|
+
</OuterFieldset>
|
|
308
|
+
</Form>
|
|
309
|
+
</FormWrapper>
|
|
310
|
+
);
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
Signup.propTypes = {
|
|
314
|
+
clientID: PropTypes.string.isRequired,
|
|
315
|
+
cartID: PropTypes.string.isRequired,
|
|
316
|
+
donateLink: PropTypes.string.isRequired,
|
|
317
|
+
otherAmountText: PropTypes.string.isRequired,
|
|
318
|
+
mbshipID: PropTypes.string.isRequired,
|
|
319
|
+
donateOrientation: PropTypes.oneOf(['left', 'right']),
|
|
320
|
+
noMoneyBuys: PropTypes.bool,
|
|
321
|
+
data: PropTypes.objectOf(PropTypes.shape),
|
|
322
|
+
popUpText: PropTypes.string.isRequired,
|
|
323
|
+
chooseAmountText: PropTypes.string,
|
|
324
|
+
monthlyChooseAmountText: PropTypes.string,
|
|
325
|
+
submitButtonColor: PropTypes.string,
|
|
326
|
+
changeGivingType: PropTypes.func.isRequired,
|
|
327
|
+
givingType: PropTypes.string,
|
|
328
|
+
hasTopImage: PropTypes.bool,
|
|
329
|
+
shouldShowTitleSection: PropTypes.bool
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
export default Signup;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import styled, { css, keyframes } from 'styled-components';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import Text from '../../../Atoms/Text/Text';
|
|
5
|
+
import CloseCross from '../assets/close.svg';
|
|
6
|
+
|
|
7
|
+
const closeDuration = 0.6;
|
|
8
|
+
|
|
9
|
+
const fadeClose = keyframes`
|
|
10
|
+
0% {
|
|
11
|
+
opacity: 1;
|
|
12
|
+
max-height: 350px;
|
|
13
|
+
}
|
|
14
|
+
100% {
|
|
15
|
+
opacity: 0;
|
|
16
|
+
max-height: 0px;
|
|
17
|
+
display: none;
|
|
18
|
+
margin-top: -16px;
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
const fadeOpen = keyframes`
|
|
23
|
+
0% {
|
|
24
|
+
opacity: 0;
|
|
25
|
+
max-height: 0px;
|
|
26
|
+
display: none;
|
|
27
|
+
margin-top: -16px;
|
|
28
|
+
}
|
|
29
|
+
100% {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
max-height: 350px;
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const StyledPopUp = styled.div`
|
|
36
|
+
display: grid;
|
|
37
|
+
overflow: hidden;
|
|
38
|
+
max-height: 350px;
|
|
39
|
+
opacity: 1;
|
|
40
|
+
animation: 0.4s ${props => props.fadeOpen} ease;
|
|
41
|
+
${props => props.isClosed && css`
|
|
42
|
+
animation: ${closeDuration}s ${props.fadeClose} ease forwards;
|
|
43
|
+
`}
|
|
44
|
+
background-color: ${({ theme }) => theme.color('blue_light')};
|
|
45
|
+
box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.15);
|
|
46
|
+
border-radius: 0.5rem;
|
|
47
|
+
|
|
48
|
+
@media ${({ theme }) => theme.allBreakpoints('M')} {
|
|
49
|
+
width: 450px;
|
|
50
|
+
margin-right: auto;
|
|
51
|
+
margin-left: auto;
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
const TextWrapper = styled.div`
|
|
56
|
+
margin: 0 32px 32px;
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
const Button = styled.button`
|
|
60
|
+
justify-self: end;
|
|
61
|
+
background-color: transparent;
|
|
62
|
+
border: 0;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
width: 30px;
|
|
65
|
+
height: 30px;
|
|
66
|
+
margin: 3px;
|
|
67
|
+
:active,
|
|
68
|
+
:focus,
|
|
69
|
+
:hover {
|
|
70
|
+
outline: none;
|
|
71
|
+
border: 1px solid ${({ theme }) => theme.color('grey')};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
img {
|
|
75
|
+
width: 15px;
|
|
76
|
+
height: 15px;
|
|
77
|
+
vertical-align: middle;
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
const PopUpComponent = ({ popUpText, setPopOpen }) => {
|
|
82
|
+
const [isClosed, setIsClosed] = useState(false);
|
|
83
|
+
|
|
84
|
+
// Only update centralised state - which renders
|
|
85
|
+
// this component - once the closing animation is complete
|
|
86
|
+
const handleCloser = () => {
|
|
87
|
+
setIsClosed(true);
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
setPopOpen(false);
|
|
90
|
+
}, closeDuration * 1000);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<StyledPopUp isClosed={isClosed} fadeOpen={fadeOpen} fadeClose={fadeClose}>
|
|
95
|
+
<Button onClick={() => handleCloser()} aria-label="Close">
|
|
96
|
+
<img src={CloseCross} alt="Close cross icon" />
|
|
97
|
+
</Button>
|
|
98
|
+
<TextWrapper>
|
|
99
|
+
<Text>{ popUpText }</Text>
|
|
100
|
+
</TextWrapper>
|
|
101
|
+
</StyledPopUp>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
PopUpComponent.propTypes = {
|
|
106
|
+
popUpText: PropTypes.string.isRequired,
|
|
107
|
+
setPopOpen: PropTypes.func.isRequired
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export default PopUpComponent;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import {
|
|
5
|
+
Switch, Wrapper, MoneyBox, Label
|
|
6
|
+
} from './GivingSelector.style';
|
|
7
|
+
|
|
8
|
+
const GivingSelector = ({
|
|
9
|
+
givingType = null, changeGivingType, setPopOpen, mbshipID
|
|
10
|
+
}) => {
|
|
11
|
+
// Only updates giving type and popup status when appropriate
|
|
12
|
+
const handleGivingTypeChange = (thisButtonType, currentGivingType) => {
|
|
13
|
+
if (currentGivingType !== thisButtonType) {
|
|
14
|
+
changeGivingType(thisButtonType);
|
|
15
|
+
setPopOpen(thisButtonType === 'single');
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Wrapper>
|
|
21
|
+
<MoneyBox>
|
|
22
|
+
<input
|
|
23
|
+
className="give-once"
|
|
24
|
+
aria-label="Single"
|
|
25
|
+
id={`give-once--${mbshipID}`}
|
|
26
|
+
value="Single"
|
|
27
|
+
type="radio"
|
|
28
|
+
label=""
|
|
29
|
+
checked={givingType === 'single'}
|
|
30
|
+
onChange={() => handleGivingTypeChange('single', givingType)}
|
|
31
|
+
/>
|
|
32
|
+
<Label active={givingType === 'single'} htmlFor={`give-once--${mbshipID}`}>
|
|
33
|
+
Single
|
|
34
|
+
</Label>
|
|
35
|
+
<input
|
|
36
|
+
className="give-monthly"
|
|
37
|
+
aria-label="Monthly"
|
|
38
|
+
id={`give-monthly--${mbshipID}`}
|
|
39
|
+
value="Monthly"
|
|
40
|
+
type="radio"
|
|
41
|
+
label=""
|
|
42
|
+
checked={givingType === 'monthly'}
|
|
43
|
+
onChange={() => handleGivingTypeChange('monthly', givingType)}
|
|
44
|
+
/>
|
|
45
|
+
<Label active={givingType === 'monthly'} htmlFor={`give-monthly--${mbshipID}`}>
|
|
46
|
+
Monthly
|
|
47
|
+
</Label>
|
|
48
|
+
<Switch />
|
|
49
|
+
</MoneyBox>
|
|
50
|
+
</Wrapper>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
GivingSelector.propTypes = {
|
|
55
|
+
givingType: PropTypes.string,
|
|
56
|
+
changeGivingType: PropTypes.func.isRequired,
|
|
57
|
+
setPopOpen: PropTypes.func.isRequired,
|
|
58
|
+
mbshipID: PropTypes.string.isRequired
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default GivingSelector;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
import spacing from '../../../../theme/shared/spacing';
|
|
4
|
+
import zIndex from '../../../../theme/shared/zIndex';
|
|
5
|
+
import hideVisually from '../../../../theme/shared/hideVisually';
|
|
6
|
+
|
|
7
|
+
const Switch = styled.span`
|
|
8
|
+
width: 50%;
|
|
9
|
+
height: 48px;
|
|
10
|
+
${zIndex('low')};
|
|
11
|
+
display: block;
|
|
12
|
+
position: absolute;
|
|
13
|
+
transition: left 0.15s ease-out;
|
|
14
|
+
background-color: ${({ theme }) => theme.color('red')};
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const Wrapper = styled.div`
|
|
18
|
+
display: flex;
|
|
19
|
+
margin: ${spacing('md')} 0;
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
const MoneyBox = styled.div`
|
|
23
|
+
width: 100%;
|
|
24
|
+
position: relative;
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: row;
|
|
27
|
+
margin: ${spacing('sm')} 0;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
border-radius: 0.5rem;
|
|
30
|
+
border: 1px solid ${({ theme }) => theme.color('grey')};
|
|
31
|
+
background: ${({ theme }) => theme.color('white')};
|
|
32
|
+
@media ${({ theme }) => theme.allBreakpoints('M')} {
|
|
33
|
+
margin: 0 auto;
|
|
34
|
+
}
|
|
35
|
+
.give-monthly:checked ~ ${Switch} {
|
|
36
|
+
left: calc(50%);
|
|
37
|
+
}
|
|
38
|
+
input {
|
|
39
|
+
${hideVisually}
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
const Label = styled.label`
|
|
44
|
+
font-size: ${({ theme }) => theme.fontSize('s')};
|
|
45
|
+
font-family: ${({ theme }) => theme.fontFamilies('Montserrat')};
|
|
46
|
+
font-weight: bold;
|
|
47
|
+
min-height: 48px;
|
|
48
|
+
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
display: flex;
|
|
51
|
+
flex-basis: 50%;
|
|
52
|
+
border: none;
|
|
53
|
+
transition: color 0.15s ease-out;
|
|
54
|
+
${zIndex('medium')};
|
|
55
|
+
cursor: ${({ active }) => (active === true ? 'default' : 'pointer')};
|
|
56
|
+
border-radius: 2rem;
|
|
57
|
+
color: ${({ active, theme }) => (active === true ? theme.color('white') : theme.color('black'))};
|
|
58
|
+
|
|
59
|
+
&:active:focus {
|
|
60
|
+
box-shadow: none;
|
|
61
|
+
}
|
|
62
|
+
&:focus {
|
|
63
|
+
border: none;
|
|
64
|
+
outline: none;
|
|
65
|
+
box-shadow: inset 0 0 0 4px ${({ theme }) => theme.color('red')};
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
export {
|
|
70
|
+
Switch, Wrapper, MoneyBox, Label
|
|
71
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import styled, { css } from 'styled-components';
|
|
4
|
+
|
|
5
|
+
import Input from '../../../Atoms/Input/Input';
|
|
6
|
+
|
|
7
|
+
const MoneyBuyButton = styled(Input)`
|
|
8
|
+
display: block;
|
|
9
|
+
input {
|
|
10
|
+
border: none;
|
|
11
|
+
background-color: ${({ theme }) => theme.color('white')};
|
|
12
|
+
color: ${({ theme }) => theme.color('black')};
|
|
13
|
+
font-size: ${({ theme }) => theme.fontSize('l')};
|
|
14
|
+
font-family: ${({ theme }) => theme.fontFamilies('Anton')};
|
|
15
|
+
font-weight: normal;
|
|
16
|
+
border-radius: 0.5rem;
|
|
17
|
+
height: 4rem;
|
|
18
|
+
border: 1px solid ${({ theme }) => theme.color('grey')};
|
|
19
|
+
&:focus {
|
|
20
|
+
border: 1px solid ${({ theme }) => theme.color('red')};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
${({ isSelected }) => isSelected
|
|
24
|
+
&& css`
|
|
25
|
+
background-color: ${({ theme }) => theme.color('red')};
|
|
26
|
+
border: 1px solid ${({ theme }) => theme.color('red')};
|
|
27
|
+
color: ${({ theme }) => theme.color('white')};
|
|
28
|
+
`}
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
const MoneyBuy = ({
|
|
33
|
+
setOtherAmount,
|
|
34
|
+
amount = '10',
|
|
35
|
+
currency = '£',
|
|
36
|
+
description = 'description',
|
|
37
|
+
...rest
|
|
38
|
+
}) => (
|
|
39
|
+
<MoneyBuyButton
|
|
40
|
+
{...rest}
|
|
41
|
+
label={description}
|
|
42
|
+
showLabel={false}
|
|
43
|
+
value={`${currency} ${amount}`}
|
|
44
|
+
type="button"
|
|
45
|
+
errorMsg=""
|
|
46
|
+
onClick={setOtherAmount}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
MoneyBuy.propTypes = {
|
|
51
|
+
amount: PropTypes.string,
|
|
52
|
+
currency: PropTypes.string,
|
|
53
|
+
description: PropTypes.string,
|
|
54
|
+
// Function already set doesn't need to be passed as props
|
|
55
|
+
setOtherAmount: PropTypes.func.isRequired
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default MoneyBuy;
|