From e80151ada8e44eee35f7735cbba7846908f0d76a Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:36:57 +0530 Subject: [PATCH 01/26] feat: enhance project details types with classification & purpose variations --- src/Common/Types/index.tsx | 56 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/src/Common/Types/index.tsx b/src/Common/Types/index.tsx index bf303391..704002d7 100644 --- a/src/Common/Types/index.tsx +++ b/src/Common/Types/index.tsx @@ -119,7 +119,7 @@ export interface PlanetCashSignupDetails { purpose: "planet-cash-signup"; } -export interface FetchedProjectDetails { +export interface FetchedBaseProjectDetails { id: string; name: string; description?: string | null; @@ -127,11 +127,32 @@ export interface FetchedProjectDetails { ownerName: string | null; image?: string | null; purpose: ProjectPurpose; + classification: Nullable; taxDeductionCountries?: Array; isApproved: boolean; isTopProject: boolean; } +export interface FetchedTreeProjectDetails extends FetchedBaseProjectDetails { + purpose: "trees"; + classification: TreeProjectClassification; +} + +export interface FetchedFundsProjectDetails extends FetchedBaseProjectDetails { + purpose: "funds"; + classification: FundsProjectClassification; +} + +export interface FetchedOtherProjectDetails extends FetchedBaseProjectDetails { + purpose: "conservation" | "reforestation" | "bouquet" | "planet-cash"; + classification: null; +} + +export type FetchedProjectDetails = + | FetchedTreeProjectDetails + | FetchedFundsProjectDetails + | FetchedOtherProjectDetails; + export type ProjectPurpose = | "trees" | "conservation" @@ -140,7 +161,36 @@ export type ProjectPurpose = | "bouquet" | "planet-cash"; -export interface PaymentOptions extends FetchedProjectDetails { +export type TreeProjectClassification = + | "agroforestry" + | "managed-regeneration" + | "large-scale-planting" + | "mangroves" + | "natural-regeneration" + | "other-planting" + | "urban-planting"; + +export type FundsProjectClassification = + | "academy" + | "endowment" + | "forest-protection" + | "funding" + | "membership" + | "mixed" + | "neutral" + | "neutral-event" + | "penalty" + | "public-funds" + | "research" + | "sponsorship" + | "subscription" + | "subsidy"; + +export type ProjectClassification = + | TreeProjectClassification + | FundsProjectClassification; + +export type PaymentOptions = FetchedProjectDetails & { requestedCountry: string; effectiveCountry: string; frequencies: Frequencies; @@ -152,7 +202,7 @@ export interface PaymentOptions extends FetchedProjectDetails { unitCost: number; currency: string; destination: string; -} +}; export type UnitType = "tree" | "m2" | "currency" | CurrencyCode; From 330aeda863150959ba6ffc80eeae5866a1c8a582 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:44:13 +0530 Subject: [PATCH 02/26] feat: refactor project details handling with createProjectDetails utility - also populates `classification` in projectDetails --- pages/index.tsx | 29 ++++------------------- src/Layout/QueryParamContext.tsx | 14 ++---------- src/Utils/createProjectDetails.ts | 38 +++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 37 deletions(-) create mode 100644 src/Utils/createProjectDetails.ts diff --git a/pages/index.tsx b/pages/index.tsx index 863c5d5b..60abf8df 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -20,6 +20,7 @@ import { ContactDetails, } from "@planet-sdk/common/build/types/donation"; import { GetServerSideProps } from "next/types"; +import { createProjectDetails } from "src/Utils/createProjectDetails"; interface Props { projectDetails?: FetchedProjectDetails; @@ -250,7 +251,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { const queryCountry = context.query.country; const found = countriesData.some( (country) => - country.countryCode?.toUpperCase() === queryCountry.toUpperCase(), + country.countryCode?.toUpperCase() === queryCountry.toUpperCase() ); if (found) { country = queryCountry.toUpperCase(); @@ -276,18 +277,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { const paymentOptionsResponse = await apiRequest(requestParams); const paymentOptionsData: PaymentOptions = paymentOptionsResponse?.data; if (paymentOptionsData) { - projectDetails = { - id: paymentOptionsData.id, - name: paymentOptionsData.name, - description: paymentOptionsData.description, - purpose: paymentOptionsData.purpose, - ownerName: paymentOptionsData.ownerName, - taxDeductionCountries: paymentOptionsData.taxDeductionCountries, - image: paymentOptionsData.image, - ownerAvatar: paymentOptionsData.ownerAvatar, - isApproved: paymentOptionsData.isApproved ? true : false, - isTopProject: paymentOptionsData.isTopProject ? true : false, - }; + projectDetails = createProjectDetails(paymentOptionsData); donationStep = 1; } } catch (err) { @@ -360,18 +350,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { if (paymentSetupData) { currency = paymentSetupData.currency; paymentSetup = paymentSetupData; - projectDetails = { - id: paymentSetupData.id, - name: paymentSetupData.name, - description: paymentSetupData.description, - purpose: paymentSetupData.purpose, - ownerName: paymentSetupData.ownerName, - taxDeductionCountries: paymentSetupData.taxDeductionCountries, - image: paymentSetupData.image, - ownerAvatar: paymentSetupData.ownerAvatar, - isApproved: paymentSetupData.isApproved ? true : false, - isTopProject: paymentSetupData.isTopProject ? true : false, - }; + projectDetails = createProjectDetails(paymentSetupData); donationStep = 3; } } catch (err) { diff --git a/src/Layout/QueryParamContext.tsx b/src/Layout/QueryParamContext.tsx index 0e068f50..04d569ef 100644 --- a/src/Layout/QueryParamContext.tsx +++ b/src/Layout/QueryParamContext.tsx @@ -40,6 +40,7 @@ import { import ErrorPopup from "src/Common/ErrorPopup/ErrorPopup"; import { APIError, handleError, SerializedError } from "@planet-sdk/common"; import { PaymentRequest } from "@stripe/stripe-js/types/stripe-js/payment-request"; +import { createProjectDetails } from "src/Utils/createProjectDetails"; export const QueryParamContext = createContext(null); @@ -509,18 +510,7 @@ const QueryParamProvider: FC = ({ children }) => { setpaymentSetup(paymentSetup); } - setprojectDetails({ - id: paymentSetup.id, - name: paymentSetup.name, - description: paymentSetup.description, - purpose: paymentSetup.purpose, - ownerName: paymentSetup.ownerName, - taxDeductionCountries: paymentSetup.taxDeductionCountries, - image: paymentSetup.image, - ownerAvatar: paymentSetup.ownerAvatar, - isApproved: paymentSetup.isApproved ? true : false, - isTopProject: paymentSetup.isTopProject ? true : false, - }); + setprojectDetails(createProjectDetails(paymentSetup)); } setIsPaymentOptionsLoading(false); } catch (err) { diff --git a/src/Utils/createProjectDetails.ts b/src/Utils/createProjectDetails.ts new file mode 100644 index 00000000..64ad6df2 --- /dev/null +++ b/src/Utils/createProjectDetails.ts @@ -0,0 +1,38 @@ +import { FetchedProjectDetails, PaymentOptions } from "src/Common/Types"; + +export const createProjectDetails = ( + paymentOptions: PaymentOptions +): FetchedProjectDetails => { + const baseDetails = { + id: paymentOptions.id, + name: paymentOptions.name, + description: paymentOptions.description, + ownerName: paymentOptions.ownerName, + taxDeductionCountries: paymentOptions.taxDeductionCountries, + image: paymentOptions.image, + ownerAvatar: paymentOptions.ownerAvatar, + isApproved: !!paymentOptions.isApproved, + isTopProject: !!paymentOptions.isTopProject, + }; + + switch (paymentOptions.purpose) { + case "trees": + return { + ...baseDetails, + purpose: "trees", + classification: paymentOptions.classification, + }; + case "funds": + return { + ...baseDetails, + purpose: "funds", + classification: paymentOptions.classification, + }; + default: + return { + ...baseDetails, + purpose: paymentOptions.purpose, + classification: null, + }; + } +}; From 4827176f7795925c5c97ff7093b9341fa60b5178 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:11:03 +0530 Subject: [PATCH 03/26] feat: update GiftForm display logic - based on project classification and frequency --- src/Donations/Components/DonationsForm.tsx | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index b26266f7..30f5f9a3 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -130,6 +130,13 @@ function DonationsForm(): ReactElement { !(isGift && giftDetails.recipientName === "") && !(onBehalf && onBehalfDonor.firstName === ""); + const canSendInvitationGift = + (projectDetails?.classification !== "membership" && frequency === "once") || + (projectDetails?.classification === "membership" && frequency !== "once"); + + const canSendDirectGift = projectDetails?.classification !== "membership"; + const hasDirectGift = giftDetails.type === "direct"; + //Only used for native pay. Is this still applicable, or should this be removed? const onPaymentFunction = async ( paymentMethod: PaymentMethod, @@ -359,16 +366,13 @@ function DonationsForm(): ReactElement { )} {/* show PlanetCashSelector only if user is signed up and have a planetCash account */} {canPayWithPlanetCash && } - {!(onBehalf && onBehalfDonor.firstName === "") && - (projectDetails.purpose === "trees" && - (paymentSetup?.unitType !== "m2" || - giftDetails.type === "direct") ? ( -
- -
- ) : ( - <> - ))} + {(canSendDirectGift && hasDirectGift) || canSendInvitationGift ? ( +
+ +
+ ) : ( + <> + )} {process.env.RECURRENCY && showFrequencyOptions && paymentSetup && From e508a6f8bea8f402f1ec56e89583d286c2d6481f Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 12 Nov 2024 17:50:33 +0530 Subject: [PATCH 04/26] feat: removes unneeded GiftForm fields for membership projects --- src/Donations/Micros/GiftForm.tsx | 144 +++++++++++++++--------------- 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/src/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index b6006674..05819242 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -25,8 +25,8 @@ const EMPTY_GIFT_DETAILS: Readonly = { export default function GiftForm(): ReactElement { const { t } = useTranslation("common"); - const [showEmail, setshowEmail] = React.useState(false); - const { giftDetails, setGiftDetails, isGift, setisGift } = + const [showEmail, setShowEmail] = React.useState(false); + const { giftDetails, setGiftDetails, isGift, setisGift, projectDetails } = React.useContext(QueryParamContext); const defaultDetails: GiftFormData = { @@ -115,78 +115,82 @@ export default function GiftForm(): ReactElement { )} - {showEmail ? ( -
-
-
-

{t("giftNotification")}

+ {projectDetails?.classification !== "membership" && ( + <> + {showEmail ? ( +
+
+
+

{t("giftNotification")}

+ +
+ + value.length === 0 || isEmailValid(value), + }, + }} + render={({ field: { onChange, value } }) => ( + + )} + /> + {errors.recipientEmail && ( +
+ {errors.recipientEmail.type === "required" + ? t("emailRequired") + : t("enterValidEmail")} +
+ )} +
+
+ ( + + )} + /> +
+
+ ) : ( +
- - value.length === 0 || isEmailValid(value), - }, - }} - render={({ field: { onChange, value } }) => ( - - )} - /> - {errors.recipientEmail && ( -
- {errors.recipientEmail.type === "required" - ? t("emailRequired") - : t("enterValidEmail")} -
- )} -
-
- ( - - )} - /> -
-
- ) : ( -
- -
+ )} + )}
- {projectDetails?.classification !== "membership" && ( + {projectDetails?.category !== "membership" && ( <> {showEmail ? (
diff --git a/src/Utils/createProjectDetails.ts b/src/Utils/createProjectDetails.ts index 64ad6df2..bb491b72 100644 --- a/src/Utils/createProjectDetails.ts +++ b/src/Utils/createProjectDetails.ts @@ -20,19 +20,19 @@ export const createProjectDetails = ( return { ...baseDetails, purpose: "trees", - classification: paymentOptions.classification, + category: paymentOptions.category, }; case "funds": return { ...baseDetails, purpose: "funds", - classification: paymentOptions.classification, + category: paymentOptions.category, }; default: return { ...baseDetails, purpose: paymentOptions.purpose, - classification: null, + category: null, }; } }; From 09ccd937c9a37f88eb4c7acf40ad701d85390f0c Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:42:14 +0530 Subject: [PATCH 08/26] feat: prevent GiftForm display for planet-cash donations --- pages/index.tsx | 7 ++++++- src/Donations/Components/DonationsForm.tsx | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 597d2eec..087c8ba2 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -409,7 +409,12 @@ export const getServerSideProps: GetServerSideProps = async (context) => { utmSource = context.query.utm_source; // Set gift details if there is s (support link) in the query params - if (projectDetails?.category !== "membership" && context.query.s) { + if ( + projectDetails !== null && + projectDetails?.category !== "membership" && + projectDetails.purpose !== "planet-cash" && + context.query.s + ) { try { const requestParams = { url: `/app/profiles/${context.query.s}`, diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index 63798c29..6aa5e9fe 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -130,9 +130,14 @@ function DonationsForm(): ReactElement { !(isGift && giftDetails.recipientName === "") && !(onBehalf && onBehalfDonor.firstName === ""); - const canSendDirectGift = projectDetails?.category !== "membership"; + const canSendDirectGift = + projectDetails !== null && + projectDetails.category !== "membership" && + projectDetails.purpose !== "planet-cash"; const hasDirectGift = giftDetails.type === "direct"; const canSendInvitationGift = + projectDetails !== null && + projectDetails.purpose !== "planet-cash" && !hasDirectGift && ((projectDetails?.category !== "membership" && frequency === "once") || (projectDetails?.category === "membership" && frequency !== "once")); From 10fbef4131e1ea7068b638e80ba02fdd83cfe876 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:42:55 +0530 Subject: [PATCH 09/26] fix: remove unneeded `onBehalf` while creating prepaid donation --- src/Donations/Components/DonationsForm.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index 6aa5e9fe..72c6618d 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -335,7 +335,6 @@ function DonationsForm(): ReactElement { project: projectDetails.id, units: quantity, prePaid: true, - onBehalf: onBehalf, metadata: _metadata, ...(onBehalf && { donor: _onBehalfDonor }), ...(isGift && { gift: _gift }), From fa0c77050d5d6b18838868bce6ccc6c6831e5ea1 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:10:42 +0530 Subject: [PATCH 10/26] feat: prevent gifts to non giftable project purposes - bouquet and planet-cash --- pages/index.tsx | 5 +++-- src/Donations/Components/DonationsForm.tsx | 6 ++++-- src/Utils/projects/constants.ts | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 src/Utils/projects/constants.ts diff --git a/pages/index.tsx b/pages/index.tsx index 087c8ba2..4ef741f4 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -21,6 +21,7 @@ import { } from "@planet-sdk/common/build/types/donation"; import { GetServerSideProps } from "next/types"; import { createProjectDetails } from "src/Utils/createProjectDetails"; +import { NON_GIFTABLE_PROJECT_PURPOSES } from "src/Utils/projects/constants"; interface Props { projectDetails?: FetchedProjectDetails; @@ -411,8 +412,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => { // Set gift details if there is s (support link) in the query params if ( projectDetails !== null && - projectDetails?.category !== "membership" && - projectDetails.purpose !== "planet-cash" && + projectDetails.category !== "membership" && + !NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose) && context.query.s ) { try { diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index 72c6618d..d788adbd 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -34,6 +34,7 @@ import { } from "@planet-sdk/common/build/types/donation"; import { PaymentMethod } from "@stripe/stripe-js/types/api/payment-methods"; import { PaymentRequest } from "@stripe/stripe-js/types/stripe-js/payment-request"; +import { NON_GIFTABLE_PROJECT_PURPOSES } from "src/Utils/projects/constants"; function DonationsForm(): ReactElement { const { @@ -133,11 +134,12 @@ function DonationsForm(): ReactElement { const canSendDirectGift = projectDetails !== null && projectDetails.category !== "membership" && - projectDetails.purpose !== "planet-cash"; + !NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose); + const hasDirectGift = giftDetails.type === "direct"; const canSendInvitationGift = projectDetails !== null && - projectDetails.purpose !== "planet-cash" && + !NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose) && !hasDirectGift && ((projectDetails?.category !== "membership" && frequency === "once") || (projectDetails?.category === "membership" && frequency !== "once")); diff --git a/src/Utils/projects/constants.ts b/src/Utils/projects/constants.ts new file mode 100644 index 00000000..b42d0006 --- /dev/null +++ b/src/Utils/projects/constants.ts @@ -0,0 +1 @@ +export const NON_GIFTABLE_PROJECT_PURPOSES = ["planet-cash", "bouquet"]; From 9ca3909261e71002a58aa3673dcee4f9f40dc3e5 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:11:12 +0530 Subject: [PATCH 11/26] feat: update gift message to clarify dedication to recipient --- public/locales/en/common.json | 4 ++-- src/Donations/Micros/GiftForm.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index c0c67c0c..bd7ccd20 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -118,7 +118,7 @@ "selectLanguage": "Select Language", "trees": "trees", "logout": "Logout", - "directGiftRecipient": "This donation supports {{name}}'s Forest", + "giftDedicatedTo": "This donation is dedicated to {{name}}", "saveGiftDetails": "Save Gift Details", "giftSomeone": "My donation is dedicated to someone", "or": "OR", @@ -223,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.", "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/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index 21cec0e7..29528778 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -204,7 +204,7 @@ export default function GiftForm(): ReactElement { ) : (

resetGiftForm()}> - {t("directGiftRecipient", { + {t("giftDedicatedTo", { name: giftDetails.recipientName, })}

From 92d62ab526d1e7cd3a90e3023bdb53d25c593556 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Wed, 13 Nov 2024 19:07:55 +0530 Subject: [PATCH 12/26] chore: update @planet-sdk/common to version 0.1.42 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 822811d0..1bd5fb0b 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.34", + "@planet-sdk/common": "^0.1.42", "@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.34", - "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.34.tgz", - "integrity": "sha512-oMPD7QvXVkLYVz5Q3OhU+mFypfs407aKqCGprHo0M9ALvDTDoOKT2HsjiETCXkuu4nJcGOYmLdwGyXbWXWyZGQ==", + "version": "0.1.42", + "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.42.tgz", + "integrity": "sha512-C8rV0i3P9YyAUQlldFT91JxVpUX5rQcmKMB9IDqLKKByJ8794GTiL2y+zaJixBB1UnG/4isqyyPXTE2m1zomYg==", "dependencies": { "@types/geojson": "^7946.0.10" } @@ -10431,9 +10431,9 @@ } }, "@planet-sdk/common": { - "version": "0.1.34", - "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.34.tgz", - "integrity": "sha512-oMPD7QvXVkLYVz5Q3OhU+mFypfs407aKqCGprHo0M9ALvDTDoOKT2HsjiETCXkuu4nJcGOYmLdwGyXbWXWyZGQ==", + "version": "0.1.42", + "resolved": "https://registry.npmjs.org/@planet-sdk/common/-/common-0.1.42.tgz", + "integrity": "sha512-C8rV0i3P9YyAUQlldFT91JxVpUX5rQcmKMB9IDqLKKByJ8794GTiL2y+zaJixBB1UnG/4isqyyPXTE2m1zomYg==", "requires": { "@types/geojson": "^7946.0.10" } diff --git a/package.json b/package.json index c9650888..02ab2ac6 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.34", + "@planet-sdk/common": "^0.1.42", "@sentry/browser": "^6.2.5", "@sentry/integrations": "^6.2.5", "@sentry/node": "^6.2.5", From 62b38ac454ae1a1d941bd304a23739cf3b22fea7 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:43:41 +0530 Subject: [PATCH 13/26] feat: remove support link from query params when not applicable --- pages/index.tsx | 67 +++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 4ef741f4..b26a6311 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -409,34 +409,51 @@ export const getServerSideProps: GetServerSideProps = async (context) => { if (typeof context.query.utm_source === "string") utmSource = context.query.utm_source; - // Set gift details if there is s (support link) in the query params - if ( - projectDetails !== null && - projectDetails.category !== "membership" && - !NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose) && - context.query.s - ) { - try { - const requestParams = { - url: `/app/profiles/${context.query.s}`, - setshowErrorCard, - tenant, - locale, + // Handle s (support link) in the query params + if (typeof context.query.s === "string" && context.query.s.length > 0) { + if ( + projectDetails === null || + projectDetails.category === "membership" || + NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose) + ) { + // If project cannot have direct gift, remove 's' parameter by redirecting + const pathname = context.resolvedUrl.split("?")[0]; + const query = { ...context.query }; + delete query.s; + const queryString = new URLSearchParams( + query as Record + ).toString(); + + return { + redirect: { + destination: `${pathname}${queryString ? `?${queryString}` : ""}`, + permanent: true, + }, }; - const newProfile = await apiRequest(requestParams); - if (newProfile.data.type !== "tpo") { - isGift = true; - giftDetails = { - recipientName: newProfile.data.displayName, - recipientEmail: "", - message: "", - type: "direct", - recipient: newProfile.data.id, - recipientTreecounter: newProfile.data.slug, + } else { + // Set gift details if there is s (support link) in the query params for an eligible project + try { + const requestParams = { + url: `/app/profiles/${context.query.s}`, + setshowErrorCard, + tenant, + locale, }; + const newProfile = await apiRequest(requestParams); + if (newProfile.data.type !== "tpo") { + isGift = true; + giftDetails = { + recipientName: newProfile.data.displayName, + recipientEmail: "", + message: "", + type: "direct", + recipient: newProfile.data.id, + recipientTreecounter: newProfile.data.slug, + }; + } + } catch (err) { + console.log("Error", err); } - } catch (err) { - console.log("Error", err); } } From 416b7a456ded8b9065f77b6b77bacc585503ab02 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:19:27 +0530 Subject: [PATCH 14/26] feat: update gift types and usage to resolve TS warnings - giftDetails stored in context is now of type `GiftDetails` - `SentGift` is used purely for the API request data - updates types and type guards through the app --- pages/index.tsx | 10 ++++------ src/Common/Types/QueryParamContextInterface.ts | 6 +++--- src/Common/Types/index.tsx | 12 ++++++++++-- src/Donations/LeftPanel/GiftInfo.tsx | 10 +++++----- src/Donations/LeftPanel/LeftPanelInfo.tsx | 4 ++-- src/Donations/Micros/GiftForm.tsx | 6 ++++-- .../Micros/PaymentStatus/FailedDonation.tsx | 7 +++---- .../Micros/PaymentStatus/ThankyouMessage.tsx | 9 ++++++++- src/Layout/QueryParamContext.tsx | 4 ++-- 9 files changed, 41 insertions(+), 27 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index b26a6311..ad08aa64 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -11,7 +11,7 @@ import countriesData from "./../src/Utils/countriesData.json"; import { setCountryCode } from "src/Utils/setCountryCode"; import { DONATE } from "src/Utils/donationStepConstants"; import { - SentGift, + GiftDetails, FetchedProjectDetails, PaymentOptions, } from "src/Common/Types"; @@ -26,7 +26,7 @@ import { NON_GIFTABLE_PROJECT_PURPOSES } from "src/Utils/projects/constants"; interface Props { projectDetails?: FetchedProjectDetails; donationStep: number | null; - giftDetails: SentGift | null; + giftDetails: GiftDetails | null; isGift: boolean; resolvedUrl?: string; isDirectDonation: boolean; @@ -217,7 +217,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { // Variables that will be affected with Gift details let isGift = false; - let giftDetails: SentGift | null = null; + let giftDetails: GiftDetails | null = null; let frequency = "once"; // Variables that will be affected with context let hideTaxDeduction = false; @@ -444,11 +444,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => { isGift = true; giftDetails = { recipientName: newProfile.data.displayName, - recipientEmail: "", - message: "", type: "direct", recipient: newProfile.data.id, - recipientTreecounter: newProfile.data.slug, + recipientProfile: newProfile.data.slug, }; } } catch (err) { diff --git a/src/Common/Types/QueryParamContextInterface.ts b/src/Common/Types/QueryParamContextInterface.ts index e93aa8bf..f478ddb2 100644 --- a/src/Common/Types/QueryParamContextInterface.ts +++ b/src/Common/Types/QueryParamContextInterface.ts @@ -1,10 +1,10 @@ import { CurrencyList, FetchedProjectDetails, + GiftDetails, OnBehalfDonor, PaymentOptions, PlanetCashSignupDetails, - SentGift, } from "."; import { ProjectMapInfo as Project } from "@planet-sdk/common/build/types/project"; import { User } from "@planet-sdk/common/build/types/user"; @@ -21,8 +21,8 @@ import { Dispatch, SetStateAction } from "react"; export default interface QueryParamContextInterface { isGift: boolean; setisGift: Dispatch>; - giftDetails: SentGift | NoGift; - setGiftDetails: Dispatch>; + giftDetails: GiftDetails | NoGift; + setGiftDetails: Dispatch>; contactDetails: ContactDetails; setContactDetails: Dispatch>; country: string; diff --git a/src/Common/Types/index.tsx b/src/Common/Types/index.tsx index 2007d186..b957c783 100644 --- a/src/Common/Types/index.tsx +++ b/src/Common/Types/index.tsx @@ -14,8 +14,16 @@ import { } from "@planet-sdk/common"; /** planet-donations only allows direct or invitation gifts */ +export type DirectGiftDetails = SentDirectGift & { + recipientName?: string; + recipientProfile?: string; +}; +export type InvitationGiftDetails = SentInvitationGift; + export type SentGift = SentDirectGift | SentInvitationGift; +export type GiftDetails = DirectGiftDetails | InvitationGiftDetails; + export interface PaymentProviderRequest { account?: string; gateway: PaymentGateway; @@ -38,7 +46,7 @@ export interface CreateDonationFunctionProps { paymentSetup: PaymentOptions; currency: string; contactDetails: ContactDetails; - giftDetails: SentGift | NoGift; + giftDetails: GiftDetails | NoGift; isGift: boolean; setIsPaymentProcessing: Dispatch>; setPaymentError: Dispatch>; @@ -101,7 +109,7 @@ export interface CreateDonationDataProps { contactDetails: ContactDetails; taxDeductionCountry: string | null; isGift: boolean; - giftDetails: SentGift | NoGift; + giftDetails: GiftDetails | NoGift; frequency: string; amount?: number | null; callbackUrl: string | undefined; diff --git a/src/Donations/LeftPanel/GiftInfo.tsx b/src/Donations/LeftPanel/GiftInfo.tsx index fc1e2456..3b070b12 100644 --- a/src/Donations/LeftPanel/GiftInfo.tsx +++ b/src/Donations/LeftPanel/GiftInfo.tsx @@ -1,10 +1,10 @@ import { ReactElement } from "react"; import { useTranslation } from "next-i18next"; -import { SentGift } from "src/Common/Types"; +import { GiftDetails } from "src/Common/Types"; import styles from "./LeftPanel.module.scss"; interface Props { - giftDetails: SentGift; + giftDetails: GiftDetails; } const GiftInfo = ({ giftDetails }: Props): ReactElement => { @@ -13,11 +13,11 @@ const GiftInfo = ({ giftDetails }: Props): ReactElement => { return (

{t("dedicatedTo")}

- {giftDetails.type === "direct" && giftDetails.recipientTreecounter ? ( + {giftDetails.type === "direct" && giftDetails.recipientProfile ? ( {giftDetails.recipientName} @@ -26,7 +26,7 @@ const GiftInfo = ({ giftDetails }: Props): ReactElement => {

{giftDetails.recipientName}

)} - {giftDetails.message && ( + {giftDetails.type === "invitation" && giftDetails.message && (

{t("message")}: {giftDetails.message}

diff --git a/src/Donations/LeftPanel/LeftPanelInfo.tsx b/src/Donations/LeftPanel/LeftPanelInfo.tsx index 42e9922f..64dea0d1 100644 --- a/src/Donations/LeftPanel/LeftPanelInfo.tsx +++ b/src/Donations/LeftPanel/LeftPanelInfo.tsx @@ -7,7 +7,7 @@ import { PaymentOptions, PlanetCashSignupDetails, OnBehalfDonor, - SentGift, + GiftDetails, } from "src/Common/Types"; import Avatar from "./Avatar"; import TransactionSummary from "./TransactionSummary"; @@ -28,7 +28,7 @@ interface Props { quantity: number; currency: string; frequency: string; - giftDetails: SentGift | NoGift; + giftDetails: GiftDetails | NoGift; contactDetails: ContactDetails; isPlanetCashActive: boolean; isGift: boolean; diff --git a/src/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index 29528778..93fbfaf2 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -31,8 +31,10 @@ export default function GiftForm(): ReactElement { const defaultDetails: GiftFormData = { recipientName: giftDetails.recipientName || "", - recipientEmail: giftDetails.recipientEmail || "", - message: giftDetails.message || "", + recipientEmail: + (giftDetails.type === "invitation" && giftDetails.recipientEmail) || "", + message: + (giftDetails.type === "invitation" && giftDetails.recipientName) || "", }; const { diff --git a/src/Donations/Micros/PaymentStatus/FailedDonation.tsx b/src/Donations/Micros/PaymentStatus/FailedDonation.tsx index 99316329..ccf7ba29 100644 --- a/src/Donations/Micros/PaymentStatus/FailedDonation.tsx +++ b/src/Donations/Micros/PaymentStatus/FailedDonation.tsx @@ -7,7 +7,7 @@ import { QueryParamContext } from "../../../Layout/QueryParamContext"; import themeProperties from "../../../../styles/themeProperties"; import InfoIcon from "public/assets/icons/InfoIcon"; import RetryIcon from "public/assets/icons/RetryIcon"; -import { FetchedProjectDetails, SentGift } from "src/Common/Types"; +import { FetchedProjectDetails, GiftDetails } from "src/Common/Types"; import { Donation } from "@planet-sdk/common/build/types/donation"; interface FailedDonationProps { @@ -72,7 +72,7 @@ function FailedDonation({ const { giftRequest } = donation; setisGift(giftRequest.recipientName ? true : false); - const _giftDetails: SentGift = { + const _giftDetails: GiftDetails = { ...(giftRequest.type === "invitation" ? { type: giftRequest.type, @@ -83,8 +83,7 @@ function FailedDonation({ : { type: giftRequest.type, recipient: giftRequest.recipient, - recipientName: "", - message: "", + recipientName: giftRequest.recipientName || "", }), }; // TODO - Gift type invitation and direct will have different properties diff --git a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx index 73d036c1..e0d7e2fe 100644 --- a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx +++ b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx @@ -22,7 +22,11 @@ function ThankyouMessage({ let currencyFormat = () => {}; if (donation) { currencyFormat = () => + getFormatedCurrency( + i18n.language, + donation.currency, getFormatedCurrency(i18n.language, donation.currency, donation.amount); + ); } // EXAMPLE: Your ₹21,713.64 donation was successful {with Google Pay} @@ -41,7 +45,10 @@ function ThankyouMessage({ // EXAMPLE: We've sent an email to Sagar Aryal about the gift. // TO DO - if recipientEmail is not present, then show message - You will receive the Gift certificate for {{recipientName}} on your email const donationGiftMessage = - donation && donation.gift && donation.gift.recipientEmail //TODOO - address TS warnings after /donations is updated to send gift data + donation && + donation.gift && + donation.gift.type === "invitation" && + donation.gift.recipientEmail //TODOO - address TS warnings after /donations is updated to send gift data ? " " + t("common:giftSentMessage", { recipientName: donation.gift.recipientName, diff --git a/src/Layout/QueryParamContext.tsx b/src/Layout/QueryParamContext.tsx index 04d569ef..3fc3c745 100644 --- a/src/Layout/QueryParamContext.tsx +++ b/src/Layout/QueryParamContext.tsx @@ -24,7 +24,7 @@ import { PlanetCashSignupDetails, OnBehalfDonor, ConfigResponse, - SentGift, + GiftDetails, } from "src/Common/Types"; import { useAuth0 } from "@auth0/auth0-react"; import { validateToken } from "../Utils/tokenActions"; @@ -89,7 +89,7 @@ const QueryParamProvider: FC = ({ children }) => { const [frequency, setfrequency] = useState("once"); const [isGift, setisGift] = useState(false); - const [giftDetails, setGiftDetails] = useState({ + const [giftDetails, setGiftDetails] = useState({ recipientName: "", recipientEmail: "", message: "", From ed270b3592ed4129eb0082eca1f3d6aa4b0e2eba Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:19:36 +0530 Subject: [PATCH 15/26] feat: ensure donation amounts are treated as numbers for consistency --- pages/index.tsx | 2 +- src/Donations/Micros/PaymentStatus/FailedDonation.tsx | 2 +- src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index ad08aa64..b1478cc2 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -359,7 +359,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { } allowTaxDeductionChange = false; units = donation.units; - amount = donation.amount; + amount = Number(donation.amount); // Setting contact details from donor details if (donorData) { contactDetails = { diff --git a/src/Donations/Micros/PaymentStatus/FailedDonation.tsx b/src/Donations/Micros/PaymentStatus/FailedDonation.tsx index ccf7ba29..8d20cbc0 100644 --- a/src/Donations/Micros/PaymentStatus/FailedDonation.tsx +++ b/src/Donations/Micros/PaymentStatus/FailedDonation.tsx @@ -57,7 +57,7 @@ function FailedDonation({ setPaymentError(""); setquantity(donation?.quantity); if (donation.donor) setContactDetails(donation.donor); - setAmount(donation.amount); + setAmount(Number(donation.amount)); let country: string; if (donation.taxDeductionCountry) { diff --git a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx index e0d7e2fe..08a851d9 100644 --- a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx +++ b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx @@ -25,7 +25,7 @@ function ThankyouMessage({ getFormatedCurrency( i18n.language, donation.currency, - getFormatedCurrency(i18n.language, donation.currency, donation.amount); + Number(donation.amount) ); } From dd2b8e3072da8ec3816202c9345542b1509bbb10 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:20:38 +0530 Subject: [PATCH 16/26] fix: standardize casing for setIsGift --- pages/index.tsx | 4 ++-- src/Common/Types/QueryParamContextInterface.ts | 2 +- src/Donations/Micros/GiftForm.tsx | 4 ++-- src/Donations/Micros/PaymentStatus/FailedDonation.tsx | 4 ++-- src/Layout/QueryParamContext.tsx | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index b1478cc2..662a6e75 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -81,7 +81,7 @@ function index({ setSelectedProjects, loadselectedProjects, setGiftDetails, - setisGift, + setIsGift, setpaymentSetup, setcurrency, setContactDetails, @@ -131,7 +131,7 @@ function index({ // If gift details are present, initialize gift in context if (giftDetails && isGift) { setGiftDetails(giftDetails); - setisGift(true); + setIsGift(true); } }, []); diff --git a/src/Common/Types/QueryParamContextInterface.ts b/src/Common/Types/QueryParamContextInterface.ts index f478ddb2..e82b925e 100644 --- a/src/Common/Types/QueryParamContextInterface.ts +++ b/src/Common/Types/QueryParamContextInterface.ts @@ -20,7 +20,7 @@ import { Dispatch, SetStateAction } from "react"; export default interface QueryParamContextInterface { isGift: boolean; - setisGift: Dispatch>; + setIsGift: Dispatch>; giftDetails: GiftDetails | NoGift; setGiftDetails: Dispatch>; contactDetails: ContactDetails; diff --git a/src/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index 93fbfaf2..c3975eb6 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -26,7 +26,7 @@ const EMPTY_GIFT_DETAILS: Readonly = { export default function GiftForm(): ReactElement { const { t } = useTranslation("common"); const [showEmail, setShowEmail] = React.useState(false); - const { giftDetails, setGiftDetails, isGift, setisGift, projectDetails } = + const { giftDetails, setGiftDetails, isGift, setIsGift, projectDetails } = React.useContext(QueryParamContext); const defaultDetails: GiftFormData = { @@ -80,7 +80,7 @@ export default function GiftForm(): ReactElement { name="show-gift-form-toggle" checked={isGift} onChange={() => { - setisGift((isGift) => !isGift); + setIsGift((isGift) => !isGift); }} id="show-gift-form-toggle" /> diff --git a/src/Donations/Micros/PaymentStatus/FailedDonation.tsx b/src/Donations/Micros/PaymentStatus/FailedDonation.tsx index 8d20cbc0..a0221013 100644 --- a/src/Donations/Micros/PaymentStatus/FailedDonation.tsx +++ b/src/Donations/Micros/PaymentStatus/FailedDonation.tsx @@ -29,7 +29,7 @@ function FailedDonation({ setprojectDetails, setquantity, setContactDetails, - setisGift, + setIsGift, setGiftDetails, setfrequency, setdonationStep, @@ -70,7 +70,7 @@ function FailedDonation({ setcurrency(donation.currency); if (donation.giftRequest) { const { giftRequest } = donation; - setisGift(giftRequest.recipientName ? true : false); + setIsGift(giftRequest.recipientName ? true : false); const _giftDetails: GiftDetails = { ...(giftRequest.type === "invitation" diff --git a/src/Layout/QueryParamContext.tsx b/src/Layout/QueryParamContext.tsx index 3fc3c745..a980387b 100644 --- a/src/Layout/QueryParamContext.tsx +++ b/src/Layout/QueryParamContext.tsx @@ -88,7 +88,7 @@ const QueryParamProvider: FC = ({ children }) => { const [quantity, setquantity] = useState(50); const [frequency, setfrequency] = useState("once"); - const [isGift, setisGift] = useState(false); + const [isGift, setIsGift] = useState(false); const [giftDetails, setGiftDetails] = useState({ recipientName: "", recipientEmail: "", @@ -522,7 +522,7 @@ const QueryParamProvider: FC = ({ children }) => { Date: Mon, 18 Nov 2024 12:26:17 +0530 Subject: [PATCH 17/26] revert: rename projectDetails `category` to `classification` for consistency --- pages/index.tsx | 2 +- src/Common/Types/index.tsx | 8 ++++---- src/Donations/Components/DonationsForm.tsx | 8 +++++--- src/Donations/Micros/GiftForm.tsx | 2 +- src/Utils/createProjectDetails.ts | 6 +++--- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 662a6e75..1824b14b 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -413,7 +413,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { if (typeof context.query.s === "string" && context.query.s.length > 0) { if ( projectDetails === null || - projectDetails.category === "membership" || + projectDetails.classification === "membership" || NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose) ) { // If project cannot have direct gift, remove 's' parameter by redirecting diff --git a/src/Common/Types/index.tsx b/src/Common/Types/index.tsx index b957c783..b5d55992 100644 --- a/src/Common/Types/index.tsx +++ b/src/Common/Types/index.tsx @@ -135,7 +135,7 @@ export interface FetchedBaseProjectDetails { ownerName: string | null; image?: string | null; purpose: ProjectPurpose; - category: Nullable; + classification: Nullable; taxDeductionCountries?: Array; isApproved: boolean; isTopProject: boolean; @@ -143,17 +143,17 @@ export interface FetchedBaseProjectDetails { export interface FetchedTreeProjectDetails extends FetchedBaseProjectDetails { purpose: "trees"; - category: TreeProjectClassification; + classification: TreeProjectClassification; } export interface FetchedFundsProjectDetails extends FetchedBaseProjectDetails { purpose: "funds"; - category: FundsProjectClassification; + classification: FundsProjectClassification; } export interface FetchedOtherProjectDetails extends FetchedBaseProjectDetails { purpose: "conservation" | "reforestation" | "bouquet" | "planet-cash"; - category: null; + classification: null; } export type FetchedProjectDetails = diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index d788adbd..b7054b7c 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -133,7 +133,7 @@ function DonationsForm(): ReactElement { const canSendDirectGift = projectDetails !== null && - projectDetails.category !== "membership" && + projectDetails.classification !== "membership" && !NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose); const hasDirectGift = giftDetails.type === "direct"; @@ -141,8 +141,10 @@ function DonationsForm(): ReactElement { projectDetails !== null && !NON_GIFTABLE_PROJECT_PURPOSES.includes(projectDetails.purpose) && !hasDirectGift && - ((projectDetails?.category !== "membership" && frequency === "once") || - (projectDetails?.category === "membership" && frequency !== "once")); + ((projectDetails?.classification !== "membership" && + frequency === "once") || + (projectDetails?.classification === "membership" && + frequency !== "once")); //Only used for native pay. Is this still applicable, or should this be removed? const onPaymentFunction = async ( diff --git a/src/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index c3975eb6..f74dda99 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -117,7 +117,7 @@ export default function GiftForm(): ReactElement { )}
- {projectDetails?.category !== "membership" && ( + {projectDetails?.classification !== "membership" && ( <> {showEmail ? (
diff --git a/src/Utils/createProjectDetails.ts b/src/Utils/createProjectDetails.ts index bb491b72..64ad6df2 100644 --- a/src/Utils/createProjectDetails.ts +++ b/src/Utils/createProjectDetails.ts @@ -20,19 +20,19 @@ export const createProjectDetails = ( return { ...baseDetails, purpose: "trees", - category: paymentOptions.category, + classification: paymentOptions.classification, }; case "funds": return { ...baseDetails, purpose: "funds", - category: paymentOptions.category, + classification: paymentOptions.classification, }; default: return { ...baseDetails, purpose: paymentOptions.purpose, - category: null, + classification: null, }; } }; From 448c65deef197f5999eb03e4693f2e62a737e1ca Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:23:36 +0530 Subject: [PATCH 18/26] refactor: remove conditional onBehalf donor assignment in DonationsForm --- src/Donations/Components/DonationsForm.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index b7054b7c..e43d4ce9 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -340,7 +340,6 @@ function DonationsForm(): ReactElement { units: quantity, prePaid: true, metadata: _metadata, - ...(onBehalf && { donor: _onBehalfDonor }), ...(isGift && { gift: _gift }), }; From fb98cd94177daa41e217428e752152a57bbe2311 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:22:06 +0530 Subject: [PATCH 19/26] fix: minor code cleanup and fixes --- src/Donations/Micros/GiftForm.tsx | 3 +-- src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index f74dda99..79227df6 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -33,8 +33,7 @@ export default function GiftForm(): ReactElement { recipientName: giftDetails.recipientName || "", recipientEmail: (giftDetails.type === "invitation" && giftDetails.recipientEmail) || "", - message: - (giftDetails.type === "invitation" && giftDetails.recipientName) || "", + message: (giftDetails.type === "invitation" && giftDetails.message) || "", }; const { diff --git a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx index 08a851d9..300ee601 100644 --- a/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx +++ b/src/Donations/Micros/PaymentStatus/ThankyouMessage.tsx @@ -45,10 +45,7 @@ function ThankyouMessage({ // EXAMPLE: We've sent an email to Sagar Aryal about the gift. // TO DO - if recipientEmail is not present, then show message - You will receive the Gift certificate for {{recipientName}} on your email const donationGiftMessage = - donation && - donation.gift && - donation.gift.type === "invitation" && - donation.gift.recipientEmail //TODOO - address TS warnings after /donations is updated to send gift data + donation?.gift?.type === "invitation" && donation.gift.recipientEmail //TODOO - address TS warnings after /donations is updated to send gift data ? " " + t("common:giftSentMessage", { recipientName: donation.gift.recipientName, From bc4af28fff019bdd3a1d64f9583eae4522151607 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Thu, 21 Nov 2024 18:41:25 +0530 Subject: [PATCH 20/26] fix: fixes visible currency selector for non tree donations while displaying gift form --- .../Micros/DonationTypes/BouquetDonations.tsx | 28 +++++++++---------- .../Micros/DonationTypes/FundingDonations.tsx | 14 +++++----- styles/donations.scss | 22 ++++++++++----- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/Donations/Micros/DonationTypes/BouquetDonations.tsx b/src/Donations/Micros/DonationTypes/BouquetDonations.tsx index 3893f92d..ed3ce57e 100644 --- a/src/Donations/Micros/DonationTypes/BouquetDonations.tsx +++ b/src/Donations/Micros/DonationTypes/BouquetDonations.tsx @@ -131,12 +131,12 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement { // return Math.trunc(Math.ceil(cost/5)*5); // } return ( - <> -
+
+
{paymentSetup && paymentSetup.frequencies && paymentSetup.frequencies[`${frequency}`].options.map( @@ -149,14 +149,14 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement { setisCustomDonation(false); setCustomInputValue(""); }} - className={`funding-selection-option ${ + className={`bouquet-selection-option ${ approximatelyEqual(option.quantity, quantity) && !isCustomDonation - ? "funding-selection-option-selected" + ? "bouquet-selection-option-selected" : "" }`} > -
+
{paymentSetup.purpose === "conservation" ? option.quantity @@ -175,8 +175,8 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {
) : (
{ setisCustomDonation(true); @@ -197,7 +197,7 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement { : []}

) => { // replaces any character other than number to blank @@ -239,7 +239,7 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {
) : (

@@ -299,7 +299,7 @@ function BouquetDonations({ setopenCurrencyModal }: Props): ReactElement {

)} - +
); } diff --git a/src/Donations/Micros/DonationTypes/FundingDonations.tsx b/src/Donations/Micros/DonationTypes/FundingDonations.tsx index f0b7eadd..062359da 100644 --- a/src/Donations/Micros/DonationTypes/FundingDonations.tsx +++ b/src/Donations/Micros/DonationTypes/FundingDonations.tsx @@ -103,12 +103,12 @@ function FundingDonations({ setopenCurrencyModal }: Props): ReactElement { const customInputRef = React.useRef(null); return ( - <> -
+
+
{paymentSetup && paymentSetup.frequencies && paymentSetup.frequencies[`${frequency}`] && @@ -280,7 +280,7 @@ function FundingDonations({ setopenCurrencyModal }: Props): ReactElement {
)} - +
); } function getPaymentOptionIcons(logoName: string) { diff --git a/styles/donations.scss b/styles/donations.scss index 3d98fc79..7002d1a5 100644 --- a/styles/donations.scss +++ b/styles/donations.scss @@ -296,13 +296,15 @@ width: 0px; } } -.funding-selection-options-container { +.funding-selection-options-container, +.bouquet-selection-options-container { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: space-between; margin-top: 10px; - .funding-selection-option { + .funding-selection-option, + .bouquet-selection-option { width: 130px; margin: 10px; // height: 80px; @@ -325,12 +327,14 @@ flex: calc(50% - 20px); } &.funding-selection-option-selected, + &.bouquet-selection-option-selected, &:hover, &:focus { cursor: pointer; background-color: $primaryColor; border: 1px solid $primaryColor; - .funding-selection-option-text { + .funding-selection-option-text, + .bouquet-selection-option-text { color: $primaryFontColor; p, span { @@ -349,7 +353,8 @@ &:active { transform: scale(0.98); } - .funding-selection-option-text { + .funding-selection-option-text, + .bouquet-selection-option-text { text-align: left; line-height: 1; // margin-left: 12px; @@ -479,7 +484,8 @@ outline: 0px; font-size: 16px; } -.funding-custom-tree-input { +.funding-custom-tree-input, +.bouquet-custom-tree-input { border: 0px; border-bottom: 2px solid $activeGreenBgTextColor; width: 100%; @@ -751,9 +757,11 @@ width: 100px; padding: 12px; } - .funding-selection-options-container { + .funding-selection-options-container, + .bouquet-selection-options-container { margin-top: 10px; - .funding-selection-option { + .funding-selection-option, + .bouquet-selection-option { width: 160px; &.monthly-option { width: 100px; From 83e15443b39ed25c7b04c792c9438ecc4b7cff90 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:51:01 +0530 Subject: [PATCH 21/26] fix: resolves intermittent layout issue with MaterialTextField --- src/Common/InputTypes/MaterialTextField.tsx | 101 ++++++++++++++------ 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/src/Common/InputTypes/MaterialTextField.tsx b/src/Common/InputTypes/MaterialTextField.tsx index 09e2a7ee..160209f1 100644 --- a/src/Common/InputTypes/MaterialTextField.tsx +++ b/src/Common/InputTypes/MaterialTextField.tsx @@ -5,61 +5,102 @@ import themeProperties from "./../../../styles/themeProperties"; const MaterialTextField = styled(TextField)({ width: "100%", color: "var(--primary-font-color)", - "& .MuiInputBase-input.MuiOutlinedInput-input": { + + // Label styles + "& label": { color: "var(--primary-font-color)", - height: "1.1876em", - lineHeight: "1.1876em", + fontFamily: themeProperties.fontFamily, + fontSize: "14px", + lineHeight: "1", }, - "& .MuiInputAdornment-root": { - color: "var(--primary-font-color)", + + // Base label positioning + "& .MuiInputLabel-root": { + transform: "translate(14px, 16px) scale(1)", // Matches original position + transformOrigin: "left top", + position: "absolute", + left: 0, + top: 0, + display: "block", + padding: 0, + pointerEvents: "none", + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + maxWidth: "calc(100% - 24px)", }, + + // Shrunk/focused label "& label.Mui-focused": { color: "var(--primary-font-color)", fontFamily: themeProperties.fontFamily, }, - "& label": { - color: "var(--primary-font-color)", - fontFamily: themeProperties.fontFamily, - fontSize: "14px", - lineHeight: 1, - }, + "& .MuiInputLabel-outlined.MuiInputLabel-shrink": { transform: "translate(14px, -4px) scale(0.75)", - top: "-3px", - }, - "& .MuiOutlinedInput-notchedOutline": { - border: "0px!important", + top: "-3px", // Critical for matching original position + pointerEvents: "auto", + maxWidth: "calc(133% - 32px)", }, - "& .Mui-disabled.MuiInputLabel-root": { + + // Input styles + "& .MuiInputBase-input.MuiOutlinedInput-input": { color: "var(--primary-font-color)", + height: "20px", + lineHeight: "20px", + padding: "14px", }, - "& .Mui-disabled.MuiOutlinedInput-input ": { - color: "var(--disabled-font-color)", - WebkitTextFillColor: "initial", - }, + + // Input container "& .MuiOutlinedInput-root": { backgroundColor: "var(--background-color-dark)", - border: "0px!important", borderRadius: "10px", fontFamily: themeProperties.fontFamily, + minHeight: "44px", + + "& fieldset": { + border: "none", + }, }, - "& .MuiOutlinedInput-input": { - padding: "14px", + + // Input adornment + "& .MuiInputAdornment-root": { + color: "var(--primary-font-color)", + }, + + // Notched outline + "& .MuiOutlinedInput-notchedOutline": { + border: "0px!important", }, + + // Disabled state + "& .Mui-disabled": { + "&.MuiInputLabel-root": { + color: "var(--primary-font-color)", + }, + "&.MuiOutlinedInput-input": { + color: "var(--disabled-font-color)", + WebkitTextFillColor: "initial", + }, + }, + + // Multiline "& .MuiInputBase-multiline": { padding: "0px", }, + + // Autocomplete '& .MuiAutocomplete-inputRoot[class*="MuiOutlinedInput-root"]': { padding: "14px", - }, - '& .MuiAutocomplete-inputRoot[class*="MuiOutlinedInput-root"] .MuiAutocomplete-input': - { + + "& .MuiAutocomplete-input": { padding: "0px", + + "&:first-of-type": { + paddingLeft: "0px", + }, }, - '& .MuiAutocomplete-inputRoot[class*="MuiOutlinedInput-root"] .MuiAutocomplete-input:first-of-type': - { - paddingLeft: "0px", - }, + }, }); export default MaterialTextField; From c379166132651c608338474646fc074f473e23c2 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:01:39 +0530 Subject: [PATCH 22/26] fix: add validation for recipient name length in GiftForm --- public/locales/en/common.json | 1 + src/Donations/Micros/GiftForm.tsx | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index bd7ccd20..47fe4dd8 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -7,6 +7,7 @@ "tree_other": "trees", "recipientName": "Recipient Name", "recipientNameRequired": "Recipient Name is required", + "recipientNameTooLong": "Recipient Name must be 35 characters or less", "email": "Email", "recipientEmail": "Recipient Email", "emailRequired": "Email is required", diff --git a/src/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index 79227df6..b1c31dc6 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -91,7 +91,16 @@ export default function GiftForm(): ReactElement { ( )} /> - {errors.recipientName && ( + {errors.recipientName !== undefined && (
- {t("recipientNameRequired")} + {errors.recipientName.message}
)}
From 28906618a426883f3b2ba85e2db4044f21554edb Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:24:27 +0530 Subject: [PATCH 23/26] feat: update logic to show PlanetCashSelector - refactors code to extract logic to show `PlanetCashSelector` to `isPlanetCashAllowed` utility function --- src/Donations/Components/DonationsForm.tsx | 22 +++++------- src/Utils/donationOptions.ts | 40 ++++++++++++++++++++++ src/Utils/projects/constants.ts | 18 +++++++++- 3 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 src/Utils/donationOptions.ts diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index e43d4ce9..610b7d5f 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -35,6 +35,7 @@ import { import { PaymentMethod } from "@stripe/stripe-js/types/api/payment-methods"; import { PaymentRequest } from "@stripe/stripe-js/types/stripe-js/payment-request"; import { NON_GIFTABLE_PROJECT_PURPOSES } from "src/Utils/projects/constants"; +import { isPlanetCashAllowed } from "src/Utils/donationOptions"; function DonationsForm(): ReactElement { const { @@ -117,19 +118,13 @@ function DonationsForm(): ReactElement { const [isPaymentProcessing, setIsPaymentProcessing] = React.useState(false); const [paymentError, setPaymentError] = React.useState(""); //TODOO - confirm and remove - const canPayWithPlanetCash = - 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 && - projectDetails.taxDeductionCountries?.includes( - profile.planetCash.country - ) && - !(isGift && giftDetails.recipientName === "") && - !(onBehalf && onBehalfDonor.firstName === ""); + const canPayWithPlanetCash = isPlanetCashAllowed({ + profile, + isSignedUp, + projectDetails, + isGift, + giftDetails, + }); const canSendDirectGift = projectDetails !== null && @@ -385,7 +380,6 @@ function DonationsForm(): ReactElement { {projectDetails.purpose !== "funds" && (

{t("donate")}

)} - {/* show PlanetCashSelector only if user is signed up and have a planetCash account */} {canPayWithPlanetCash && } {(canSendDirectGift && hasDirectGift) || canSendInvitationGift ? (
diff --git a/src/Utils/donationOptions.ts b/src/Utils/donationOptions.ts new file mode 100644 index 00000000..6ac14a04 --- /dev/null +++ b/src/Utils/donationOptions.ts @@ -0,0 +1,40 @@ +import { NoGift, User } from "@planet-sdk/common"; +import { + PLANETCASH_ALLOWED_PROJECT_PURPOSES, + PLANETCASH_DISALLOWED_PROJECT_CLASSIFICATIONS, +} from "./projects/constants"; +import { FetchedProjectDetails, GiftDetails } from "src/Common/Types"; + +interface PlanetCashAllowedParams { + profile: User | null; + isSignedUp: boolean; + projectDetails: FetchedProjectDetails | null; + isGift: boolean; + giftDetails: GiftDetails | NoGift; +} + +/** + * Determines if Planet Cash is allowed for the current donation + */ +export const isPlanetCashAllowed = ({ + profile, + isSignedUp, + projectDetails, + isGift, + giftDetails, +}: PlanetCashAllowedParams): boolean => { + return ( + profile !== null && + isSignedUp && + profile.planetCash !== null && + projectDetails !== null && + PLANETCASH_ALLOWED_PROJECT_PURPOSES.includes(projectDetails.purpose) && + (projectDetails.classification === null || + !PLANETCASH_DISALLOWED_PROJECT_CLASSIFICATIONS.includes( + projectDetails.classification + )) && + projectDetails.taxDeductionCountries !== undefined && + projectDetails.taxDeductionCountries.includes(profile.planetCash.country) && + !(isGift && giftDetails.recipientName === "") + ); +}; diff --git a/src/Utils/projects/constants.ts b/src/Utils/projects/constants.ts index b42d0006..8e8ed20f 100644 --- a/src/Utils/projects/constants.ts +++ b/src/Utils/projects/constants.ts @@ -1 +1,17 @@ -export const NON_GIFTABLE_PROJECT_PURPOSES = ["planet-cash", "bouquet"]; +import { ProjectPurpose, TreeProjectClassification } from "@planet-sdk/common"; +import { FundsProjectClassification } from "src/Common/Types"; + +export const NON_GIFTABLE_PROJECT_PURPOSES: Array = [ + "planet-cash", + "bouquet", +]; + +export const PLANETCASH_ALLOWED_PROJECT_PURPOSES: Array = [ + "trees", + "conservation", + "funds", +]; + +export const PLANETCASH_DISALLOWED_PROJECT_CLASSIFICATIONS: Array< + FundsProjectClassification | TreeProjectClassification +> = ["membership", "endowment"]; From 071785c0a28087e6b6e2c23cd3e432b4b8c67d11 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Thu, 28 Nov 2024 18:19:37 +0530 Subject: [PATCH 24/26] refactor: remove unused _onBehalfDonor assignment in DonationsForm --- src/Donations/Components/DonationsForm.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index 610b7d5f..b8b3cea8 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -293,11 +293,6 @@ function DonationsForm(): ReactElement { const handlePlanetCashDonate = async () => { if (projectDetails) { setShowDisablePlanetCashButton(true); - const _onBehalfDonor = { - firstname: onBehalfDonor.firstName, - lastname: onBehalfDonor.lastName, - email: onBehalfDonor.email, - }; const _metadata = { utm_campaign: utmCampaign, From 2839bc1d51f41f472139c93d868b87deca751950 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:13:21 +0530 Subject: [PATCH 25/26] feat: add check for PlanetCash gateway while permitting planet cash donations --- src/Common/Types/index.tsx | 8 ++++++++ src/Donations/Components/DonationsForm.tsx | 1 + src/Utils/donationOptions.ts | 3 +++ 3 files changed, 12 insertions(+) diff --git a/src/Common/Types/index.tsx b/src/Common/Types/index.tsx index b5d55992..18a9ce45 100644 --- a/src/Common/Types/index.tsx +++ b/src/Common/Types/index.tsx @@ -227,6 +227,7 @@ export interface Gateways { paypal: Paypal; stripe: Stripe; offline?: Offline; + "planet-cash"?: PlanetCashGateway; } export interface Paypal { methods?: string[] | null; @@ -254,6 +255,13 @@ export interface Offline { account: string; } +export interface PlanetCashGateway { + account: string; + balance: number; + creditLimit: number; + available: number; +} + export interface OptionsEntity { id?: string; caption: string | null; diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index b8b3cea8..188ade15 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -124,6 +124,7 @@ function DonationsForm(): ReactElement { projectDetails, isGift, giftDetails, + hasPlanetCashGateway: paymentSetup?.gateways["planet-cash"] !== undefined, }); const canSendDirectGift = diff --git a/src/Utils/donationOptions.ts b/src/Utils/donationOptions.ts index 6ac14a04..3badad02 100644 --- a/src/Utils/donationOptions.ts +++ b/src/Utils/donationOptions.ts @@ -11,6 +11,7 @@ interface PlanetCashAllowedParams { projectDetails: FetchedProjectDetails | null; isGift: boolean; giftDetails: GiftDetails | NoGift; + hasPlanetCashGateway: boolean; } /** @@ -22,11 +23,13 @@ export const isPlanetCashAllowed = ({ projectDetails, isGift, giftDetails, + hasPlanetCashGateway, }: PlanetCashAllowedParams): boolean => { return ( profile !== null && isSignedUp && profile.planetCash !== null && + hasPlanetCashGateway && projectDetails !== null && PLANETCASH_ALLOWED_PROJECT_PURPOSES.includes(projectDetails.purpose) && (projectDetails.classification === null || From 2eced0a8e0c1b1fd920efef7fd5e67c9137a8939 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:53:12 +0530 Subject: [PATCH 26/26] feat: add authentication to loadPaymentSetup - adds authentication to loadPaymentSetup call (as "planet-cash" gateway is only returned in authenticated call) - adds debouncing while loading payment setup for non planet cash projects --- src/Layout/QueryParamContext.tsx | 47 ++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/Layout/QueryParamContext.tsx b/src/Layout/QueryParamContext.tsx index a980387b..f15b3c6d 100644 --- a/src/Layout/QueryParamContext.tsx +++ b/src/Layout/QueryParamContext.tsx @@ -41,6 +41,7 @@ import ErrorPopup from "src/Common/ErrorPopup/ErrorPopup"; import { APIError, handleError, SerializedError } from "@planet-sdk/common"; import { PaymentRequest } from "@stripe/stripe-js/types/stripe-js/payment-request"; import { createProjectDetails } from "src/Utils/createProjectDetails"; +import { useDebouncedEffect } from "src/Utils/useDebouncedEffect"; export const QueryParamContext = createContext(null); @@ -346,23 +347,27 @@ const QueryParamProvider: FC = ({ children }) => { router.query.token, ]); - useEffect(() => { - const regex = /^pcash_/; - if ( - router.query.to && - !regex.test(router.query.to as string) && - country !== undefined && - country !== "" && - router.query.to?.toString().toLowerCase() !== "planetcash" - ) { - const to = String(router.query.to).replace(/\//g, ""); - loadPaymentSetup({ - projectGUID: to, - paymentSetupCountry: country, - shouldSetPaymentDetails: true, - }); - } - }, [router.query.to, country]); + useDebouncedEffect( + () => { + const regex = /^pcash_/; + if ( + router.query.to && + !regex.test(router.query.to as string) && + country !== undefined && + country !== "" && + router.query.to?.toString().toLowerCase() !== "planetcash" + ) { + const to = String(router.query.to).replace(/\//g, ""); + loadPaymentSetup({ + projectGUID: to, + paymentSetupCountry: country, + shouldSetPaymentDetails: true, + }); + } + }, + 1000, + [router.query.to, country, profile?.slug] + ); async function loadConfig() { try { @@ -488,11 +493,19 @@ const QueryParamProvider: FC = ({ children }) => { paymentSetupCountry: string; shouldSetPaymentDetails?: boolean; }) => { + const token = + profile === null + ? null + : queryToken || + (router.query.token as string) || + (await getAccessTokenSilently()); + setIsPaymentOptionsLoading(true); try { const requestParams = { url: `/app/paymentOptions/${projectGUID}?country=${paymentSetupCountry}`, setshowErrorCard, + token, tenant, locale: i18n.language, };