Skip to content

Commit

Permalink
Merge pull request #460 from Plant-for-the-Planet-org/feature/planetc…
Browse files Browse the repository at this point in the history
…ash-auto-enable-bug

Fixes bugs with Planetcash selector
  • Loading branch information
mariahosfeld authored Jan 18, 2024
2 parents 260f44c + a2d8163 commit d720673
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 45 deletions.
5 changes: 4 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ const scheme =
: "https";

let APPUrl;
if (process.env.NEXT_PUBLIC_VERCEL_ENV === "preview") {
if (
process.env.NEXT_PUBLIC_VERCEL_ENV === "preview" &&
process.env.DISABLE_VERCEL_REDIRECT !== "true"
) {
APPUrl = `${scheme}://${process.env.VERCEL_URL}`;
} else {
APPUrl = process.env.APP_URL;
Expand Down
1 change: 1 addition & 0 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
"billingAddress": "Contact Details",
"treesInCountry": "{{treeCount}} trees, Plant-for-the-Planet",
"fundingPaymentLabel": "Donate {{amount}}, Plant-for-the-Planet",
"pcashPaymentLabel": "Load {{amount}} PlanetCash, Plant-for-the-Planet",
"bouquetPaymentLabel": "Donate {{amount}}, Plant-for-the-Planet",
"errorOccurred": "Something went wrong. Please feel free to take a screenshot and email us at [email protected].",
"dedicatedTo": "Dedicated to",
Expand Down
4 changes: 2 additions & 2 deletions src/Common/Types/QueryParamContextInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ export default interface QueryParamContextInterface {
paymentSetupCountry: string;
shouldSetPaymentDetails?: boolean;
}) => Promise<void>;
isPlanetCashActive: boolean;
setIsPlanetCashActive: Dispatch<SetStateAction<boolean>>;
isPlanetCashActive: boolean | null;
setIsPlanetCashActive: Dispatch<SetStateAction<boolean | null>>;
onBehalf: boolean;
setOnBehalf: Dispatch<SetStateAction<boolean>>;
onBehalfDonor: OnBehalfDonor;
Expand Down
20 changes: 20 additions & 0 deletions src/Donations/Components/DonationsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function DonationsForm(): ReactElement {
utmMedium,
utmSource,
isPackageWanted,
setPaymentRequest,
} = React.useContext(QueryParamContext);
const { t, i18n } = useTranslation(["common", "country", "donate"]);

Expand All @@ -78,6 +79,16 @@ function DonationsForm(): ReactElement {
React.useState(false);
const router = useRouter();

React.useEffect(() => {
setPaymentRequest(null);
}, []);

React.useEffect(() => {
if (isPlanetCashActive) {
setPaymentRequest(null);
}
}, [isPlanetCashActive]);

React.useEffect(() => {
setMinAmt(getMinimumAmountForCurrency(currency));
}, [currency]);
Expand Down Expand Up @@ -241,6 +252,15 @@ function DonationsForm(): ReactElement {
),
});
break;
case "planet-cash":
paymentLabel = t("pcashPaymentLabel", {
amount: getFormatedCurrency(
i18n.language,
currency,
paymentSetup.unitCost * quantity
),
});
break;
case "bouquet":
case "conservation":
paymentLabel = t("bouquetPaymentLabel", {
Expand Down
10 changes: 6 additions & 4 deletions src/Donations/Components/PaymentsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ function PaymentsForm(): ReactElement {
utmMedium,
utmSource,
isPackageWanted,
setPaymentRequest,
} = React.useContext(QueryParamContext);

const [stripePromise, setStripePromise] =
Expand All @@ -100,6 +101,7 @@ function PaymentsForm(): ReactElement {

React.useEffect(() => {
setPaymentType("CARD");
setPaymentRequest(null);
}, []);

const sofortCountries = ["AT", "BE", "DE", "IT", "NL", "ES"];
Expand All @@ -111,7 +113,7 @@ function PaymentsForm(): ReactElement {
| string
| PaymentMethod
| PaypalApproveData
| PaypalErrorData,
| PaypalErrorData
) => {
if (!paymentSetup || !donationID) {
console.log("Missing payment options"); //TODOO - better error handling
Expand Down Expand Up @@ -144,7 +146,7 @@ function PaymentsForm(): ReactElement {
// Seems to work only for native pay. Should this be removed?
const onPaymentFunction = async (
paymentMethod: PaymentMethod,
paymentRequest: PaymentRequest,
paymentRequest: PaymentRequest
) => {
setPaymentType(paymentRequest._activeBackingLibraryName); //TODOO --_activeBackingLibraryName is a private variable?
const gateway = "stripe";
Expand Down Expand Up @@ -289,7 +291,7 @@ function PaymentsForm(): ReactElement {
query: { ...router.query, step: CONTACT },
},
undefined,
{ shallow: true },
{ shallow: true }
);
}}
className="d-flex"
Expand Down Expand Up @@ -420,7 +422,7 @@ function PaymentsForm(): ReactElement {
totalCost={getFormatedCurrency(
i18n.language,
currency,
paymentSetup?.unitCost * quantity,
paymentSetup?.unitCost * quantity
)}
onPaymentFunction={(providerObject: PaymentMethod) =>
onSubmitPayment("stripe", "card", providerObject)
Expand Down
43 changes: 26 additions & 17 deletions src/Donations/Micros/PlanetCashSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const PlanetCashSelector: FC = () => {
country,
setcountry,
frequency,
paymentRequest,
} = useContext(QueryParamContext);
const router = useRouter();

Expand All @@ -37,20 +36,28 @@ const PlanetCashSelector: FC = () => {
}, [paymentSetup?.unitCost, quantity, setIsPlanetCashActive]);

useEffect(() => {
// On Load If selected country is planetCash Country and balance is sufficient activate planetCash.

if (
country === profile?.planetCash?.country &&
paymentSetup &&
paymentSetup.unitCost * quantity <=
profile.planetCash.balance / 100 + profile.planetCash.creditLimit / 100
) {
setIsPlanetCashActive(true);
}
if (frequency !== "once") {
if (frequency !== "once" && isPlanetCashActive !== null) {
setIsPlanetCashActive(false);
} else {
if (
isPlanetCashActive === null &&
country === profile?.planetCash?.country &&
paymentSetup &&
paymentSetup.unitCost * quantity <=
(profile.planetCash.balance + profile.planetCash.creditLimit) / 100
) {
setIsPlanetCashActive(true);
}
}
}, [paymentRequest, frequency]);
}, [
country,
profile,
paymentSetup,
quantity,
frequency,
isPlanetCashActive,
frequency,
]);

useEffect(() => {
// This is done to lock the transaction with PlanetCash in a single currency.
Expand Down Expand Up @@ -208,11 +215,13 @@ const PlanetCashSelector: FC = () => {
</div>
<div title={disabledReason() ? disabledReason() : ""}>
<ToggleSwitch
checked={isPlanetCashActive}
checked={isPlanetCashActive === true}
disabled={shouldPlanetCashDisable()}
onChange={() =>
setIsPlanetCashActive((isPlanetCashActive) => !isPlanetCashActive)
}
onChange={() => {
setIsPlanetCashActive(
(isPlanetCashActive) => !isPlanetCashActive
);
}}
/>
</div>
</div>
Expand Down
9 changes: 9 additions & 0 deletions src/Donations/PaymentMethods/PaymentMethodTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ export default function PaymentMethodTabs({
),
});
break;
case "planet-cash":
paymentLabel = t("pcashPaymentLabel", {
amount: getFormatedCurrency(
i18n.language,
currency,
paymentSetup.unitCost * quantity
),
});
break;
case "bouquet":
case "conservation":
paymentLabel = t("bouquetPaymentLabel", {
Expand Down
42 changes: 30 additions & 12 deletions src/Donations/PaymentMethods/PaymentRequestCustomButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from "@stripe/stripe-js/types/stripe-js/payment-request";
import { PaymentMethod } from "@stripe/stripe-js/types/api/payment-methods";
import { Stripe } from "@stripe/stripe-js/types/stripe-js/stripe";
import Skeleton from "@mui/material/Skeleton";

interface PaymentButtonProps {
country: string;
Expand Down Expand Up @@ -50,10 +51,8 @@ export const PaymentRequestCustomButton = ({
const stripe = useStripe();
const [canMakePayment, setCanMakePayment] = useState(false);
const [paymentLoading, setPaymentLoading] = useState(false);

useEffect(() => {
setPaymentRequest(null);
}, []);
// Tracks if native pay buttons were shown at least once to prevent layout jerks
const [wasNativePayInit, setWasNativePayInit] = useState(false);

useEffect(() => {
if (
Expand All @@ -75,17 +74,16 @@ export const PaymentRequestCustomButton = ({
pr.canMakePayment().then((result) => {
if (result) {
setPaymentRequest(pr);
setWasNativePayInit(true);
}
});
}
}, [stripe, paymentRequest, country, currency, amount]);

useEffect(() => {
if (stripe && paymentRequest) {
setPaymentRequest(null);
setCanMakePayment(false);
setPaymentLoading(false);
}
setPaymentRequest(null);
setCanMakePayment(false);
setPaymentLoading(false);
}, [country, currency, amount]);

useEffect(() => {
Expand Down Expand Up @@ -121,7 +119,10 @@ export const PaymentRequestCustomButton = ({
);
}
return () => {
if (paymentRequest && !paymentLoading) {
if (
paymentRequest &&
paymentRequest.hasRegisteredListener("paymentmethod")
) {
paymentRequest.off("paymentmethod", () => {
setPaymentLoading(false);
});
Expand Down Expand Up @@ -194,8 +195,25 @@ export const PaymentRequestCustomButton = ({
<div className="separator-text mb-10">{t("or")}</div>
)}
</div>
) : null
) : null}
) : (
<></>
)
) : wasNativePayInit ? (
//Loader shown if native pay was initiated at least once to avoid a jerky effect when payment details change
<div className="w-100">
<Skeleton
className="mb-10"
variant="rectangular"
width={"100%"}
height={40}
/>
{!isPaymentPage && (
<div className="separator-text mb-10">{t("or")}</div>
)}
</div>
) : (
<></>
)}

{!isPaymentPage && (
<button
Expand Down
22 changes: 13 additions & 9 deletions src/Layout/QueryParamContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ const QueryParamProvider: FC = ({ children }) => {
const [transferDetails, setTransferDetails] =
useState<BankTransferDetails | null>(null);

const [isPlanetCashActive, setIsPlanetCashActive] = useState(false);
const [isPlanetCashActive, setIsPlanetCashActive] = useState<boolean | null>(
null
);

// Only used when planetCash is active
const [onBehalf, setOnBehalf] = useState(false);
Expand All @@ -151,7 +153,7 @@ const QueryParamProvider: FC = ({ children }) => {

const [donation, setDonation] = useState<Donation | null>(null);
const [paymentRequest, setPaymentRequest] = useState<PaymentRequest | null>(
null,
null
);

const [errors, setErrors] = React.useState<SerializedError[] | null>(null);
Expand All @@ -163,8 +165,9 @@ const QueryParamProvider: FC = ({ children }) => {
setshowErrorCard,
shouldQueryParamAdd: false,
};
const response: { data: Record<string, string> } =
await apiRequest(requestParams);
const response: { data: Record<string, string> } = await apiRequest(
requestParams
);
setEnabledCurrencies(response.data);
} catch (err) {
console.log(err);
Expand Down Expand Up @@ -198,7 +201,7 @@ const QueryParamProvider: FC = ({ children }) => {

function testURL(url: string) {
const pattern = new RegExp(
/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g,
/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g
);
// regex source https://tutorial.eyehunts.com/js/url-regex-validation-javascript-example-code/
return !!pattern.test(url);
Expand Down Expand Up @@ -242,7 +245,7 @@ const QueryParamProvider: FC = ({ children }) => {
const projects = response.data as Project[];
if (projects) {
const allowedDonationsProjects = projects.filter(
(project) => project.properties.allowDonations === true,
(project) => project.properties.allowDonations === true
);
setAllProjects(allowedDonationsProjects);
if (allowedDonationsProjects?.length < 6) {
Expand Down Expand Up @@ -373,7 +376,7 @@ const QueryParamProvider: FC = ({ children }) => {
const found = countriesData.some(
(arrayCountry) =>
arrayCountry.countryCode?.toUpperCase() ===
config.data.country?.toUpperCase(),
config.data.country?.toUpperCase()
);
if (found) {
// This is to make sure donations which are already created with some country do not get affected by country from user config
Expand Down Expand Up @@ -492,8 +495,9 @@ const QueryParamProvider: FC = ({ children }) => {
tenant,
locale: i18n.language,
};
const paymentSetupData: { data: PaymentOptions } =
await apiRequest(requestParams);
const paymentSetupData: { data: PaymentOptions } = await apiRequest(
requestParams
);
if (paymentSetupData.data) {
const paymentSetup = paymentSetupData.data;
if (shouldSetPaymentDetails) {
Expand Down

0 comments on commit d720673

Please sign in to comment.