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 ? (
+
+
+
+
+ ) : (
-
-
- ) : (
-
+
+ );
+ }
+
+ if (method.type !== 'chimoney' && method.type !== 'donation-link') {
+ return (
+
+ handleDonateClick(method.paymentID)}
>
- {isLoading ? (
-
- ) : (
- `Donate via ${formattedMethodName}`
- )}
-
- )}
-
-
-
- );
- }
+
+ {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"