diff --git a/package.json b/package.json index 81c9187b8..479c5cc6b 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "react-test-renderer": "^16.8.6", "react-uid": "^2.2.0", "styled-components": "^4.3.1", + "universal-cookie": "^4.0.3", "youtube-player": "^5.5.2" }, "husky": { diff --git a/src/components/Molecules/Membership/Form/Form.js b/src/components/Molecules/Membership/Form/Form.js index ec85a3b05..b9aed2b31 100644 --- a/src/components/Molecules/Membership/Form/Form.js +++ b/src/components/Molecules/Membership/Form/Form.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import Text from '../../../Atoms/Text/Text'; @@ -8,7 +8,7 @@ import { onKeyPress, isAmountValid, isInputMatchBoxValue -} from '../../../../utils/Membership'; +} from '../../../../utils/membershipHelper'; import { Button, Copy, @@ -23,13 +23,19 @@ import { Legend } from '../Membership.style'; +import { + DataLayerInit, + DataLayerUpdate, + checkCookie +} from '../../../../utils/membershipDataLayer'; + const Signup = ({ data: { regularGiving }, donateLink, otherDescription, clientID, cartID, - mbshipID, + mbshipID: mbshipRowID, ...rest }) => { const [moneyBoxes, setMoneyBoxes] = useState({ @@ -40,25 +46,36 @@ const Signup = ({ const [isSelected, setIsSelected] = useState(true); // Highlight one the money buy box when the page load const [errorMsg, setErrorMsg] = useState(false); - const [amountDonate, setAmountDonate] = useState(''); - const [userInput, setUserInput] = useState(''); + const [currentDonationAmount, setCurrentDonationAmount] = useState(''); + const [userInputValue, setUserInputValue] = useState(''); const [boxBorderColor, setBoxBorderColor] = useState(''); const [inputBorderColor, setInputBorderColor] = useState(false); const [moneyBuyCopy, setMoneyBuyCopy] = useState(true); + const [currentMoneyBuyPosition, setCurrentMoneyBuyPosition] = useState(true); + + const dataLayer = useRef(null); // This function is triggered when one of the money buy box is selected - const selectMoneyBuy = (copy, value) => { + const selectMoneyBuy = (copy, value, event) => { + // Stops outer label clickevent being passed down to the input, triggering twice + if (event && event.type === 'click') { + event.stopPropagation(); + } + + // Make a record of what position our currently-selected amount is + setCurrentMoneyBuyPosition(event.target.getAttribute('data-pos')); + if (isSelected) setIsSelected(false); if (errorMsg) setErrorMsg(false); // Check if input is highlighted and his value matches one of the money buy box - const isUserInputMatch = userInput * 1 === value; // convert string to number string * 1 + const isUserInputMatch = userInputValue * 1 === value; // convert string to number string * 1 if (inputBorderColor && !isUserInputMatch) { setInputBorderColor(false); - setUserInput(''); + setUserInputValue(''); } setBoxBorderColor(value); setMoneyBuyCopy(copy); - setAmountDonate(value); + setCurrentDonationAmount(value); }; // Handle user other amount input @@ -71,39 +88,64 @@ const Signup = ({ setBoxBorderColor(false); if (errorMsg) setErrorMsg(false); setMoneyBuyCopy(description); - setAmountDonate(input); + setCurrentDonationAmount(input); } // Highlight both input and box - isInputMatchBoxValue(moneyBoxes, selectMoneyBuy, setAmountDonate, input); + isInputMatchBoxValue( + moneyBoxes, + selectMoneyBuy, + setCurrentDonationAmount, + input + ); setInputBorderColor(true); - setUserInput(input); + setUserInputValue(input); }; - const hightlightInput = (value, description) => { + const highlightInput = (value, description) => { + // The manual input field always represnts the '0' MoneyBuy position in the DL + setCurrentMoneyBuyPosition('0'); if (isSelected) setIsSelected(false); if (errorMsg) { setMoneyBuyCopy(false); } else if (!value) { - setAmountDonate(0); + setCurrentDonationAmount(0); setBoxBorderColor(false); setMoneyBuyCopy(description); } setInputBorderColor(true); }; + useEffect(() => { + // eslint--next-line no-multi-assign + dataLayer.current = window.dataLayer ? window.dataLayer : []; + }, []); + useEffect(() => { regularGiving.moneybuys.map((moneyBuy, index) => { const box = `box${index + 1}`; // eslint-disable-next-line no-shadow setMoneyBoxes(moneyBoxes => ({ ...moneyBoxes, [box]: moneyBuy })); + return ( isSelected && index === 1 && - (setMoneyBuyCopy(moneyBuy.description), setAmountDonate(moneyBuy.value)) + (setMoneyBuyCopy(moneyBuy.description), + setCurrentDonationAmount(moneyBuy.value)) ); }); }, [isSelected, regularGiving.moneybuys]); + /* Set up default DataLayer obj on pageload */ + useEffect(() => { + DataLayerInit( + mbshipRowID, + clientID, + cartID, + regularGiving.moneybuys, + dataLayer.current + ); + }, [cartID, clientID, mbshipRowID, regularGiving.moneybuys]); + const submitDonation = ( event, amount, @@ -113,7 +155,18 @@ const Signup = ({ donateURL ) => { event.preventDefault(); + if (isAmountValid(amount)) { + // Pass current values to function to fire DL event + DataLayerUpdate( + amount, + 'add', + currentMoneyBuyPosition, + clientId, + cartId, + mbshipRowID, + dataLayer.current + ); handleDonateSubmission(amount, clientId, cartId, mbshipId, donateURL); } else { setErrorMsg(true); @@ -130,24 +183,35 @@ const Signup = ({ isInputMatchBox={value} amount={value} description={`£${value}`} - setOtherAmount={() => selectMoneyBuy(description, value)} + setOtherAmount={e => { + selectMoneyBuy(description, value, e); + }} key={value} - name={`${mbshipID}--moneyBuy${index + 1}`} - id={`${mbshipID}--moneyBuy-box${index + 1}`} + name={`${mbshipRowID}--moneyBuy${index + 1}`} + id={`${mbshipRowID}--moneyBuy-box${index + 1}`} + position={`${index + 1}`} /> ) ); + /* + * Check to see if we've got any previously 'added' values in the last 30min, if so 'remove' + * them from the 'basket' to avoid duplicates in the DL for the same user session + */ + useEffect(() => { + checkCookie(clientID, cartID, dataLayer.current); + }); + return (
submitDonation( e, - amountDonate, + currentDonationAmount, clientID, cartID, - mbshipID, + mbshipRowID, donateLink ) } @@ -168,16 +232,16 @@ const Signup = ({ inputBorderColor={inputBorderColor} label="£" errorMsg="" - id={`${mbshipID}--MoneyBuy-userInput`} + id={`${mbshipRowID}--MoneyBuy-userInput`} showLabel {...rest} max="5000" min="1" - value={userInput} + value={userInputValue} pattern="[^[0-9]+([,.][0-9]+)?$]" placeholder="0.00" onChange={e => handleChange(e.target.value, otherDescription)} - onClick={e => hightlightInput(e.target.value, otherDescription)} + onClick={e => highlightInput(e.target.value, otherDescription)} onKeyPress={e => onKeyPress(e)} aria-label="Input a different amount" /> diff --git a/src/components/Molecules/Membership/Membership.js b/src/components/Molecules/Membership/Membership.js index 23762b659..b309ffaf8 100644 --- a/src/components/Molecules/Membership/Membership.js +++ b/src/components/Molecules/Membership/Membership.js @@ -1,4 +1,5 @@ import React from 'react'; + import PropTypes from 'prop-types'; import Text from '../../Atoms/Text/Text'; diff --git a/src/components/Molecules/Membership/Membership.test.js b/src/components/Molecules/Membership/Membership.test.js index e483d221f..b5f7d83a7 100644 --- a/src/components/Molecules/Membership/Membership.test.js +++ b/src/components/Molecules/Membership/Membership.test.js @@ -450,6 +450,7 @@ it('renders correctly', () => {