diff --git a/open-giving/package.json b/open-giving/package.json index ce18138..f3ca707 100644 --- a/open-giving/package.json +++ b/open-giving/package.json @@ -20,7 +20,7 @@ "@opentelemetry/api": "^1.6.0", "chimoney-payment-widget": "^0.0.28", "next": "^12.2.5", - "non-profit-donations": "latest", + "non-profit-donations": "^0.0.9", "qrcode.react": "^4.0.1", "react": "^18", "react-dom": "^18", diff --git a/open-giving/src/components/DonationForm.js b/open-giving/src/components/DonationForm.js index 507e136..393a121 100644 --- a/open-giving/src/components/DonationForm.js +++ b/open-giving/src/components/DonationForm.js @@ -15,188 +15,221 @@ import { TextField, Typography, } from '@mui/material'; -import React from 'react'; +import React, { useCallback } from 'react'; import useDonation from '../hooks/useDonation'; import { formatPaymentMethodName } from '../utils/paymentMethods'; -const DonationForm = ({ - method, - index, - setSnackbarMessage, - setSnackbarOpen, - useTestPaymentID, -}) => { - const { - donationAmount, - setDonationAmount, - payerEmail, - setPayerEmail, - isLoading, - paymentLink, - paymentAmount, - paymentCurrency, - handleDonateClick, - openPaymentWidget, - resetPayment, - } = useDonation(method, setSnackbarMessage, setSnackbarOpen); +const DonationForm = React.memo( + ({ method, index, setSnackbarMessage, setSnackbarOpen }) => { + const { + donationAmount, + setDonationAmount, + payerEmail, + setPayerEmail, + isLoading, + paymentLink, + paymentAmount, + paymentCurrency, + handleDonateClick, + openPaymentWidget, + resetPayment, + } = useDonation(method, setSnackbarMessage, setSnackbarOpen); - const getIcon = (methodType) => { - switch (methodType) { - case 'interledger': - case 'paypal': - case 'stripe': - case 'venmo': - case 'cashapp': - case 'airtime': - case 'mobile-money': - case 'stablecoin': - return ; - case 'chimoney': - return ; - case 'donation-link': - return ; - default: - return ; - } - }; + const getIcon = (methodType) => { + switch (methodType) { + case 'interledger': + case 'paypal': + case 'stripe': + case 'venmo': + case 'cashapp': + case 'airtime': + case 'mobile-money': + case 'stablecoin': + return ; + case 'chimoney': + return ; + case 'donation-link': + return ; + default: + return ; + } + }; - const formattedMethodName = formatPaymentMethodName(method.type); - const formattedPaymentID = - method.paymentID && typeof method.paymentID !== 'undefined' - ? useTestPaymentID - ? method.paymentID.test - : method.paymentID.production - : method.paymentID; + const formattedMethodName = formatPaymentMethodName(method.type); - if (method.type === 'donation-link') { - return ( - - + if (method.type === 'donation-link') { + return ( + + + + {index + 1}. {formattedMethodName}{' '} + + {getIcon(method.type)} + + + + } + secondary={ + + {method.paymentID} + + } + /> + + ); + } + + if (method.type === 'chimoney') { + return ( + + + {index + 1}. {formattedMethodName} {getIcon(method.type)} - } - secondary={ - - {formattedPaymentID} - - } - /> - - ); - } - - if (method.type === 'chimoney') { - return ( - - - - + + { + e.preventDefault(); + handleDonateClick(); }} > - {index + 1}. {formattedMethodName} - - {getIcon(method.type)} - - - - { - e.preventDefault(); - handleDonateClick(); - }} - > - - Will be deposited to {formattedPaymentID}. - - setDonationAmount(e.target.value)} - fullWidth - margin="normal" - required - /> - setPayerEmail(e.target.value)} - fullWidth - margin="normal" - required - /> - {paymentLink && parseFloat(donationAmount) === paymentAmount ? ( - + setDonationAmount(e.target.value)} + fullWidth + margin="normal" + required + /> + setPayerEmail(e.target.value)} + fullWidth + margin="normal" + required + /> + {paymentLink && parseFloat(donationAmount) === paymentAmount ? ( + + + + + ) : ( - - - ) : ( - - )} - - - - ); - } + + {index + 1}. {formattedMethodName} + + {getIcon(method.type)} + + } + secondary={ + + {method.paymentID} + + } + /> + + ); + } - if (method.type !== 'chimoney' && method.type !== 'donation-link') { return ( handleDonateClick(formattedPaymentID)} + onClick={() => handleDonateClick(method.paymentID)} > - {formattedPaymentID} + {method.paymentID} } /> ); } - - return ( - - handleDonateClick(formattedPaymentID)} - > - - {index + 1}. {formattedMethodName} - - {getIcon(method.type)} - - } - secondary={ - - {formattedPaymentID} - - } - /> - - ); -}; +); +DonationForm.displayName = 'DonationForm'; export default DonationForm; diff --git a/open-giving/src/components/Layout.js b/open-giving/src/components/Layout.js index 9ab61a6..cda5a13 100644 --- a/open-giving/src/components/Layout.js +++ b/open-giving/src/components/Layout.js @@ -4,6 +4,8 @@ import { Box, Button, Container, IconButton } from '@mui/material'; import { useTheme } from '@mui/material/styles'; import React from 'react'; +import TestModeSwitcher from './TestModeSwitcher'; + const Layout = ({ children, plain = false }) => { const theme = useTheme(); @@ -45,13 +47,14 @@ const Layout = ({ children, plain = false }) => { startIcon={} style={{ color: theme.palette.common.black, - margin: 'auto', + margin: '0', position: 'fixed', left: 0, bottom: 0, width: '100%', background: theme.palette.background.paper, zIndex: '1000000', + borderRadius: '0', }} fullWidth > @@ -59,6 +62,7 @@ const Layout = ({ children, plain = false }) => { )} + ); }; diff --git a/open-giving/src/components/NonProfitDialog.js b/open-giving/src/components/NonProfitDialog.js index 4056f2e..96c63eb 100644 --- a/open-giving/src/components/NonProfitDialog.js +++ b/open-giving/src/components/NonProfitDialog.js @@ -117,7 +117,9 @@ const NonProfitDialog = ({ Donation Methods {nonProfit.paymentMethods - .filter((method) => getPaymentID(method)) + .filter( + (method) => method.paymentID && getPaymentID(method) + ) .map((method, index) => ( { + const router = useRouter(); + const isTestMode = router.query.useTestPaymentID === '1'; + + const handleToggle = () => { + const query = { ...router.query }; + if (isTestMode) { + delete query.useTestPaymentID; + } else { + query.useTestPaymentID = '1'; + } + router.push({ pathname: router.pathname, query }, undefined, { + shallow: true, + }); + }; + + return ( + + + } + label="Test Mode" + style={{ color: isTestMode ? 'inherit' : 'grey' }} + /> + + ); +}; + +export default TestModeSwitcher; diff --git a/open-giving/src/hooks/useDonation.js b/open-giving/src/hooks/useDonation.js index 142629d..c58ebcb 100644 --- a/open-giving/src/hooks/useDonation.js +++ b/open-giving/src/hooks/useDonation.js @@ -4,7 +4,6 @@ import { useRouter } from 'next/router'; import { handlers } from 'non-profit-donations'; import { useState } from 'react'; - const useDonation = (method, setSnackbarMessage, setSnackbarOpen) => { const router = useRouter(); const [donationAmount, setDonationAmount] = useState(''); @@ -17,6 +16,18 @@ const useDonation = (method, setSnackbarMessage, setSnackbarOpen) => { const useTestPaymentID = router.query.useTestPaymentID; const handleDonateClick = async (paymentID) => { + paymentID = + typeof paymentID === 'string' && paymentID.length > 0 + ? paymentID + : method?.paymentID; + console.log('paymentID', paymentID); + const walletID = + paymentID && paymentID.test + ? useTestPaymentID + ? paymentID.test + : paymentID.production + : paymentID; + if (method.type !== 'chimoney') { try { await navigator.clipboard.writeText(paymentID); @@ -60,12 +71,7 @@ const useDonation = (method, setSnackbarMessage, setSnackbarOpen) => { payerEmail, redirect_url: `${window.location.origin}/donation-success`, useTestPaymentID, - walletID: - paymentID && paymentID.test - ? useTestPaymentID - ? paymentID.test - : paymentID.production - : paymentID, + walletID, }), }); diff --git a/open-giving/src/pages/api/chimoney-donate.js b/open-giving/src/pages/api/chimoney-donate.js index b43ebd3..c25e952 100644 --- a/open-giving/src/pages/api/chimoney-donate.js +++ b/open-giving/src/pages/api/chimoney-donate.js @@ -7,7 +7,7 @@ export default async function handler(req, res) { amount, currency = 'USD', payerEmail, - walletID, + walletID: walletIDFromBody, redirect_url, useTestPaymentID, } = req.body; @@ -15,6 +15,13 @@ export default async function handler(req, res) { const apiKEYTest = process.env.CHIMONEY_API_SECRET_TEST; try { + const walletID = + useTestPaymentID && typeof walletIDFromBody?.test !== 'undefined' + ? walletIDFromBody?.test + : typeof walletIDFromBody?.production !== 'undefined' + ? walletIDFromBody?.production + : walletIDFromBody; + if (!walletID) { res.status(400).json({ error: `Wallet ID is not set for this Organization in ${ diff --git a/open-giving/yarn.lock b/open-giving/yarn.lock index 83617ec..b3330c1 100644 --- a/open-giving/yarn.lock +++ b/open-giving/yarn.lock @@ -2778,10 +2778,10 @@ next@^12.2.5: "@next/swc-win32-ia32-msvc" "12.3.4" "@next/swc-win32-x64-msvc" "12.3.4" -non-profit-donations@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/non-profit-donations/-/non-profit-donations-0.0.7.tgz#ffe9f9e00909a6da4d44af98a30c544bd53b8db0" - integrity sha512-ToTclTjBCUkCyvOOg49uz5qUJmsdk9McbxkI/CauV5IEDGHEMFXlteSxDlfMWKNa8jT9D6AcVt9gMw9hBa29JQ== +non-profit-donations@^0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/non-profit-donations/-/non-profit-donations-0.0.9.tgz#2a2d3f937c5e186cf2699fd252877ad3febcd6b4" + integrity sha512-SZjCcOjWgji4FfY9AzlHxALDD8GU+TnlpTBdsd7kwwNJHRT5FHlqLPDkZgUYts80s26niplAY2WuZioaOIDtLQ== dependencies: "@bitauth/libauth" "^1.17.1" commitizen "^4.2.4"