diff --git a/package-lock.json b/package-lock.json
index a676e9a2..7b5d53fd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,7 @@
"@mui/material": "^5.11.8",
"@next/bundle-analyzer": "^10.1.3",
"@paypal/react-paypal-js": "^7.8.2",
- "@planet-sdk/common": "^0.1.27",
+ "@planet-sdk/common": "^0.1.29",
"@sentry/browser": "^6.2.5",
"@sentry/integrations": "^6.2.5",
"@sentry/node": "^6.2.5",
@@ -1812,9 +1812,9 @@
"dev": true
},
"node_modules/@planet-sdk/common": {
- "version": "0.1.28",
- "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.28.tgz",
- "integrity": "sha512-8SAoDEhX2dsSXuRfcIlNR10ptGntsTb14YHkOuLvXkNCdHrYB4gtZ365EmxsziQqoEk+4QhMVZD1yikbmRgh9w==",
+ "version": "0.1.29",
+ "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.29.tgz",
+ "integrity": "sha512-hNmkxfYcqmUuYGm0BLWSvr+sIbZxOXCy1AEhpClTTcfQjpofyqfHfrgkmgoFzZqK9WXPEq0Tn2uSDfqPPcRpFg==",
"dependencies": {
"@types/geojson": "^7946.0.10"
}
@@ -10416,9 +10416,9 @@
}
},
"@planet-sdk/common": {
- "version": "0.1.28",
- "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.28.tgz",
- "integrity": "sha512-8SAoDEhX2dsSXuRfcIlNR10ptGntsTb14YHkOuLvXkNCdHrYB4gtZ365EmxsziQqoEk+4QhMVZD1yikbmRgh9w==",
+ "version": "0.1.29",
+ "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.29.tgz",
+ "integrity": "sha512-hNmkxfYcqmUuYGm0BLWSvr+sIbZxOXCy1AEhpClTTcfQjpofyqfHfrgkmgoFzZqK9WXPEq0Tn2uSDfqPPcRpFg==",
"requires": {
"@types/geojson": "^7946.0.10"
}
diff --git a/package.json b/package.json
index 306dddd9..bca37a1f 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"@mui/material": "^5.11.8",
"@next/bundle-analyzer": "^10.1.3",
"@paypal/react-paypal-js": "^7.8.2",
- "@planet-sdk/common": "^0.1.27",
+ "@planet-sdk/common": "^0.1.29",
"@sentry/browser": "^6.2.5",
"@sentry/integrations": "^6.2.5",
"@sentry/node": "^6.2.5",
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index 5e202d0a..ffaa9dd6 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -3,6 +3,8 @@
"fortreeCountTrees_other": "for {{treeCount}} Trees",
"forQuantitym2": "for {{quantity}} m²",
"m2": "m²",
+ "tree_one": "tree",
+ "tree_other": "trees",
"recipientName": "Recipient Name",
"recipientNameRequired": "Recipient Name is required",
"email": "Email",
@@ -44,6 +46,10 @@
"orgNamePublishedTax": "Company name is visible on our leaderboard and app. Tax-deduction receipts will be issued for the same name.",
"orgNamePublished": "Company name is visible on our leaderboard and app.",
"paymentDetails": "Payment Details",
+ "perUnit": {
+ "tree": "per tree",
+ "m2": "per m²"
+ },
"perTree": "per tree",
"perm2": "per m²",
"youWillReceiveTaxDeduction": "You will receive a tax deduction receipt for ",
@@ -78,9 +84,10 @@
"contributionMessage": "Maybe you'll visit them some day? In the mean time, maybe hook up your friends with some trees of their own by telling them about yours?",
"fundingDonationSuccess": "Thank you for your contribution! You’ll receive a confirmation for your contribution on your email.",
"fundingContributionMessage": "We will keep you posted about our actions, in the mean time maybe share with your friends about your contribution.",
- "yourTreesPlantedByOnLocation": "Your {{treeCount}} trees will be planted by {{projectName}} in {{location}}.",
+ "restorationDonationUsage": "Your donation will be used to restore {{units}} {{unitType}} by {{projectName}} in {{location}}.",
"m2conservedByOnLocation": "{{quantity}} m² forest will be conserved by {{projectName}} in {{location}}.",
"myTreesPlantedByOnLocation": "My {{treeCount}} trees are being planted in {{location}}.",
+ "restorationDonationShareDetails": "I donated {{amount}} for forest restoration in {{location}}.",
"iDonatedForestOnLocation": "I donated {{amount}} for forest conservation in {{location}}.",
"weDonatedForestOnLocation": "We donated {{amount}} for forest conservation in {{location}}.",
"plantTreesAtURL": "Restore & protect trees at {{url}}",
@@ -172,7 +179,7 @@
"lowBalance": "Balance is low",
"oneTimePay": "Donation with PlanetCash is a one time payment",
"currency": "Currency",
- "treesPurpose": "tree donation",
+ "treesPurpose": "restoration donation",
"fundsPurpose": "donation",
"bouquetPurpose": "donation",
"conservationPurpose": "conservation donation",
@@ -216,4 +223,4 @@
"top_project_standards_fulfilled": "The project inspection revealed that this project fulfilled at least 12 of the 19 Top Project <2>standards.2>",
"standardsLink": "https://www.plant-for-the-planet.org/standards/",
"enterValidEmail": "Please enter a valid email"
-}
\ No newline at end of file
+}
diff --git a/src/Common/Types/index.tsx b/src/Common/Types/index.tsx
index 9248a7d2..bf303391 100644
--- a/src/Common/Types/index.tsx
+++ b/src/Common/Types/index.tsx
@@ -10,6 +10,7 @@ import {
ContactDetails,
BankTransferDetails,
PaymentGateway,
+ CurrencyCode,
} from "@planet-sdk/common";
/** planet-donations only allows direct or invitation gifts */
@@ -145,14 +146,16 @@ export interface PaymentOptions extends FetchedProjectDetails {
frequencies: Frequencies;
gateways: Gateways;
recurrency: Recurrency;
+ /** @deprecated - use unitType instead */
unit: string;
+ unitType: UnitType;
unitCost: number;
currency: string;
destination: string;
- isApproved: boolean;
- isTopProject: boolean;
}
+export type UnitType = "tree" | "m2" | "currency" | CurrencyCode;
+
interface Frequencies {
[key: string]: Frequency;
}
diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx
index c466c684..be22af4c 100644
--- a/src/Donations/Components/DonationsForm.tsx
+++ b/src/Donations/Components/DonationsForm.tsx
@@ -109,6 +109,7 @@ function DonationsForm(): ReactElement {
projectDetails !== null &&
projectDetails.purpose !== "funds" &&
projectDetails.purpose !== "planet-cash" &&
+ paymentSetup?.unitType === "tree" && //Enables planetcash for restoration projects with unitType tree only (TEMP)
profile !== null &&
isSignedUp &&
profile.planetCash !== null &&
@@ -339,7 +340,9 @@ function DonationsForm(): ReactElement {
{/* show PlanetCashSelector only if user is signed up and have a planetCash account */}
{canPayWithPlanetCash && }
{!(onBehalf && onBehalfDonor.firstName === "") &&
- (projectDetails.purpose === "trees" ? (
+ (projectDetails.purpose === "trees" &&
+ (paymentSetup?.unitType !== "m2" ||
+ giftDetails.type === "direct") ? (
diff --git a/src/Donations/LeftPanel/TransactionSummary.tsx b/src/Donations/LeftPanel/TransactionSummary.tsx
index 3b3cf673..57bffc07 100644
--- a/src/Donations/LeftPanel/TransactionSummary.tsx
+++ b/src/Donations/LeftPanel/TransactionSummary.tsx
@@ -2,7 +2,7 @@ import { ReactElement } from "react";
import { useTranslation } from "next-i18next";
import getFormatedCurrency from "src/Utils/getFormattedCurrency";
import { getFormattedNumber } from "src/Utils/getFormattedNumber";
-import { PaymentOptions, ProjectPurpose } from "src/Common/Types";
+import { PaymentOptions, UnitType } from "src/Common/Types";
import styles from "./LeftPanel.module.scss";
interface Props {
@@ -22,26 +22,28 @@ const TransactionSummary = ({
/** Generates unit/frequency info when needed */
const getAdditionalInfo = (
- purpose: ProjectPurpose,
- frequency: string
+ unitType: UnitType,
+ frequency: string,
+ language: string,
+ quantity: number
): string => {
let info = "";
- switch (purpose) {
- case "trees":
+ switch (unitType) {
+ case "tree":
info =
info +
" " +
t("fortreeCountTrees", {
count: Number(quantity),
- treeCount: getFormattedNumber(i18n.language, Number(quantity)),
+ treeCount: getFormattedNumber(language, Number(quantity)),
});
break;
- case "conservation":
+ case "m2":
info =
info +
" " +
t("forQuantitym2", {
- quantity: getFormattedNumber(i18n.language, Number(quantity)),
+ quantity: getFormattedNumber(language, Number(quantity)),
});
break;
default:
@@ -72,7 +74,12 @@ const TransactionSummary = ({
paymentSetup.unitCost * quantity
)}
- {getAdditionalInfo(paymentSetup.purpose, frequency)}
+ {getAdditionalInfo(
+ paymentSetup.unitType,
+ frequency,
+ i18n.language,
+ quantity
+ )}
);
};
diff --git a/src/Donations/Micros/DonationAmount.tsx b/src/Donations/Micros/DonationAmount.tsx
index 3fcd60ec..454837a1 100644
--- a/src/Donations/Micros/DonationAmount.tsx
+++ b/src/Donations/Micros/DonationAmount.tsx
@@ -21,12 +21,12 @@ function DonationAmount(): ReactElement {
paymentSetup.unitCost * quantity
)}
- {paymentSetup.purpose === "trees"
+ {paymentSetup.unitType === "tree"
? t("fortreeCountTrees", {
count: Number(quantity),
treeCount: getFormattedNumber(i18n.language, Number(quantity)),
})
- : paymentSetup.purpose === "conservation"
+ : paymentSetup.unitType === "m2"
? t("forQuantitym2", {
quantity: getFormattedNumber(i18n.language, Number(quantity)),
})
diff --git a/src/Donations/Micros/DonationTypes/BouquetDonations.tsx b/src/Donations/Micros/DonationTypes/BouquetDonations.tsx
index 4bf8a149..3893f92d 100644
--- a/src/Donations/Micros/DonationTypes/BouquetDonations.tsx
+++ b/src/Donations/Micros/DonationTypes/BouquetDonations.tsx
@@ -108,7 +108,7 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {
setCustomInputValue(
getFormattedNumber(
i18n.language,
- paymentSetup.unit !== "currency"
+ paymentSetup.unitType !== "currency"
? newQuantity
: newQuantity * paymentSetup.unitCost
)
@@ -165,7 +165,11 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {
currency,
option.quantity * paymentSetup.unitCost
)}{" "}
- {paymentSetup.purpose === "conservation" ? t("m2") : []}
+ {/* Below condition is redundant currently, but is left here as a reminder while refactoring */}
+ {paymentSetup.purpose === "conservation" &&
+ paymentSetup.unitType === "m2"
+ ? t(paymentSetup.unitType)
+ : []}
@@ -226,8 +230,10 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {
fontWeight: "800",
}}
>
- {paymentSetup.purpose === "conservation"
- ? t(paymentSetup.unit)
+ {/* Below condition is redundant currently, but is left here as a reminder while refactoring */}
+ {paymentSetup.purpose === "conservation" &&
+ paymentSetup.unitType === "m2"
+ ? t(paymentSetup.unitType)
: []}
@@ -238,7 +244,7 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {
>
{" "}
- {paymentSetup.unit === "currency"
+ {paymentSetup.unitType === "currency"
? t("customAmount")
: t("custom")}
@@ -282,7 +288,11 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {
)
: []}{" "}
- {paymentSetup.purpose === "conservation" ? t("perm2") : []}
+ {/* Below condition is redundant currently, but is left here as a reminder while refactoring */}
+ {paymentSetup.purpose === "conservation" &&
+ paymentSetup.unitType === "m2"
+ ? t("perUnit.m2")
+ : []}
) : (
diff --git a/src/Donations/Micros/DonationTypes/TreeDonation.tsx b/src/Donations/Micros/DonationTypes/TreeDonation.tsx
index f09cf700..b959dabe 100644
--- a/src/Donations/Micros/DonationTypes/TreeDonation.tsx
+++ b/src/Donations/Micros/DonationTypes/TreeDonation.tsx
@@ -74,7 +74,7 @@ function TreeDonation({ setopenCurrencyModal }: Props): ReactElement {
}, [quantity]);
const customInputRef = React.useRef
(null);
- return (
+ return paymentSetup !== null ? (
{option.quantity}
-
{t("trees")}
+
+ {t(paymentSetup.unitType, { count: option.quantity })}
+
);
@@ -136,7 +138,11 @@ function TreeDonation({ setopenCurrencyModal }: Props): ReactElement {
}}
ref={customInputRef}
/>
- {t("trees")}
+
+ {t(paymentSetup.unitType, {
+ count: parseInt(customTreeInputValue),
+ })}
+
@@ -165,7 +171,7 @@ function TreeDonation({ setopenCurrencyModal }: Props): ReactElement {
Number(paymentSetup.unitCost)
)}{" "}
- {t("perTree")}
+ {t(`perUnit.${paymentSetup.unitType}`)}
) : (
@@ -173,6 +179,8 @@ function TreeDonation({ setopenCurrencyModal }: Props): ReactElement {
)}
+ ) : (
+ <>>
);
}
diff --git a/src/Donations/Micros/PaymentStatus/ImageComponent.tsx b/src/Donations/Micros/PaymentStatus/ImageComponent.tsx
index 0c43a31c..382ca014 100644
--- a/src/Donations/Micros/PaymentStatus/ImageComponent.tsx
+++ b/src/Donations/Micros/PaymentStatus/ImageComponent.tsx
@@ -60,15 +60,26 @@ const ImageComponent = ({
return (
{projectDetails?.purpose === "trees" &&
- t("common:myTreesPlantedByOnLocation", {
- treeCount: getFormattedNumber(
- i18n.language,
- Number(donation.treeCount)
- ),
- location: t(
- "country:" + donation.destination.country.toLowerCase()
- ),
- })}
+ (donation.unitType === "tree"
+ ? t("common:myTreesPlantedByOnLocation", {
+ treeCount: getFormattedNumber(
+ i18n.language,
+ Number(donation.treeCount)
+ ),
+ location: t(
+ "country:" + donation.destination.country.toLowerCase()
+ ),
+ })
+ : t("common:restorationDonationShareDetails", {
+ amount: getFormattedCurrency(
+ i18n.language,
+ donation.currency,
+ Number(donation.amount)
+ ),
+ location: t(
+ "country:" + donation.destination.country.toLowerCase()
+ ),
+ }))}
{projectDetails?.purpose === "conservation" &&
t(
`common:${
diff --git a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx
index 3af17716..73d036c1 100644
--- a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx
+++ b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx
@@ -48,18 +48,18 @@ function ThankyouMessage({
})
: null;
- // EXAMPLE: Your 50 trees will be planted by AMU EcoVillage Project, Ethiopia in Ethiopia.
- const donationProjectMessage = donation.destination
- ? " " +
- t("common:yourTreesPlantedByOnLocation", {
- treeCount: getFormattedNumber(
- i18n.language,
- Number(donation.treeCount)
- ),
- projectName: donation.destination.name,
- location: t("country:" + donation.destination.country.toLowerCase()),
- })
- : null;
+ // EXAMPLE: Your donation will be used to restore 1,000 trees by Yucatán Restoration in Mexico.
+ // EXAMPLE: Your donation will be used to restore 2,000 m² by Saving Sumatra’s Last Refuge in Indonesia.
+ const donationProjectMessage =
+ donation.destination && donation.units
+ ? " " +
+ t("common:restorationDonationUsage", {
+ units: getFormattedNumber(i18n.language, donation.units),
+ unitType: t(`common:${donation.unitType}`, { count: donation.units }),
+ projectName: donation.destination.name,
+ location: t("country:" + donation.destination.country.toLowerCase()),
+ })
+ : null;
const Message = () => {
return (
diff --git a/src/Donations/PaymentMethods/PaymentFunctions.ts b/src/Donations/PaymentMethods/PaymentFunctions.ts
index dd9d92ec..fbf1d1e3 100644
--- a/src/Donations/PaymentMethods/PaymentFunctions.ts
+++ b/src/Donations/PaymentMethods/PaymentFunctions.ts
@@ -473,6 +473,7 @@ export async function handleStripeSCAPayment({
}
try {
const payDonationData = {
+ // method not sent here as it was already captured in the 1st request.
paymentProviderRequest: {
account: paymentSetup.gateways.stripe.account,
gateway: "stripe" as const,