Extracted the PayPalScriptProvider

This commit is contained in:
Tiago Ribeiro
2024-02-03 23:40:31 +00:00
parent 00c171b161
commit 5dcab23fdb
2 changed files with 206 additions and 256 deletions

View File

@@ -11,11 +11,12 @@ interface Props {
price: number; price: number;
duration: number; duration: number;
duration_unit: DurationUnit; duration_unit: DurationUnit;
loadScript?: boolean;
setIsLoading: (isLoading: boolean) => void; setIsLoading: (isLoading: boolean) => void;
onSuccess: (duration: number, duration_unit: DurationUnit) => void; onSuccess: (duration: number, duration_unit: DurationUnit) => void;
} }
export default function PayPalPayment({clientID, price, currency, duration, duration_unit, setIsLoading, onSuccess}: Props) { export default function PayPalPayment({clientID, price, currency, duration, duration_unit, loadScript, setIsLoading, onSuccess}: Props) {
const createOrder = async (data: CreateOrderData, actions: CreateOrderActions): Promise<string> => { const createOrder = async (data: CreateOrderData, actions: CreateOrderActions): Promise<string> => {
setIsLoading(true); setIsLoading(true);
@@ -45,7 +46,7 @@ export default function PayPalPayment({clientID, price, currency, duration, dura
setIsLoading(false); setIsLoading(false);
}; };
return ( return loadScript ? (
<PayPalScriptProvider <PayPalScriptProvider
options={{ options={{
clientId: clientID, clientId: clientID,
@@ -60,7 +61,17 @@ export default function PayPalPayment({clientID, price, currency, duration, dura
createOrder={createOrder} createOrder={createOrder}
onApprove={onApprove} onApprove={onApprove}
onCancel={onCancel} onCancel={onCancel}
onError={onError}></PayPalButtons> onError={onError}
/>
</PayPalScriptProvider> </PayPalScriptProvider>
) : (
<PayPalButtons
className="w-full"
style={{layout: "vertical"}}
createOrder={createOrder}
onApprove={onApprove}
onCancel={onCancel}
onError={onError}
/>
); );
} }

View File

@@ -4,15 +4,16 @@ import PayPalPayment from "@/components/PayPalPayment";
import useGroups from "@/hooks/useGroups"; import useGroups from "@/hooks/useGroups";
import usePackages from "@/hooks/usePackages"; import usePackages from "@/hooks/usePackages";
import useUsers from "@/hooks/useUsers"; import useUsers from "@/hooks/useUsers";
import { User } from "@/interfaces/user"; import {User} from "@/interfaces/user";
import clsx from "clsx"; import clsx from "clsx";
import { capitalize } from "lodash"; import {capitalize} from "lodash";
import { useState } from "react"; import {useState} from "react";
import getSymbolFromCurrency from "currency-symbol-map"; import getSymbolFromCurrency from "currency-symbol-map";
import useInvites from "@/hooks/useInvites"; import useInvites from "@/hooks/useInvites";
import { BsArrowRepeat } from "react-icons/bs"; import {BsArrowRepeat} from "react-icons/bs";
import InviteCard from "@/components/Medium/InviteCard"; import InviteCard from "@/components/Medium/InviteCard";
import { useRouter } from "next/router"; import {useRouter} from "next/router";
import {PayPalScriptProvider} from "@paypal/react-paypal-js";
interface Props { interface Props {
user: User; user: User;
@@ -21,24 +22,15 @@ interface Props {
reload: () => void; reload: () => void;
} }
export default function PaymentDue({ export default function PaymentDue({user, hasExpired = false, clientID, reload}: Props) {
user,
hasExpired = false,
clientID,
reload,
}: Props) {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const router = useRouter(); const router = useRouter();
const { packages } = usePackages(); const {packages} = usePackages();
const { users } = useUsers(); const {users} = useUsers();
const { groups } = useGroups(); const {groups} = useGroups();
const { const {invites, isLoading: isInvitesLoading, reload: reloadInvites} = useInvites({to: user?.id});
invites,
isLoading: isInvitesLoading,
reload: reloadInvites,
} = useInvites({ to: user?.id });
const isIndividual = () => { const isIndividual = () => {
if (user?.type === "developer") return true; if (user?.type === "developer") return true;
@@ -47,9 +39,7 @@ export default function PaymentDue({
if (userGroups.length === 0) return true; if (userGroups.length === 0) return true;
const userGroupsAdminTypes = userGroups const userGroupsAdminTypes = userGroups.map((g) => users?.find((u) => u.id === g.admin)?.type).filter((t) => !!t);
.map((g) => users?.find((u) => u.id === g.admin)?.type)
.filter((t) => !!t);
return userGroupsAdminTypes.every((t) => t !== "corporate"); return userGroupsAdminTypes.every((t) => t !== "corporate");
}; };
@@ -59,9 +49,7 @@ export default function PaymentDue({
<div className="absolute left-0 top-0 z-[999] h-screen w-screen overflow-hidden bg-black/60"> <div className="absolute left-0 top-0 z-[999] h-screen w-screen overflow-hidden bg-black/60">
<div className="absolute left-1/2 top-1/2 flex h-fit w-fit -translate-x-1/2 -translate-y-1/2 animate-pulse flex-col items-center gap-8 text-white"> <div className="absolute left-1/2 top-1/2 flex h-fit w-fit -translate-x-1/2 -translate-y-1/2 animate-pulse flex-col items-center gap-8 text-white">
<span className={clsx("loading loading-infinity w-48")} /> <span className={clsx("loading loading-infinity w-48")} />
<span className={clsx("text-2xl font-bold")}> <span className={clsx("text-2xl font-bold")}>Completing your payment...</span>
Completing your payment...
</span>
</div> </div>
</div> </div>
)} )}
@@ -72,17 +60,9 @@ export default function PaymentDue({
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div <div
onClick={reloadInvites} onClick={reloadInvites}
className="text-mti-purple-light hover:text-mti-purple-dark flex cursor-pointer items-center gap-2 transition duration-300 ease-in-out" className="text-mti-purple-light hover:text-mti-purple-dark flex cursor-pointer items-center gap-2 transition duration-300 ease-in-out">
> <span className="text-mti-black text-lg font-bold">Invites</span>
<span className="text-mti-black text-lg font-bold"> <BsArrowRepeat className={clsx("text-xl", isInvitesLoading && "animate-spin")} />
Invites
</span>
<BsArrowRepeat
className={clsx(
"text-xl",
isInvitesLoading && "animate-spin",
)}
/>
</div> </div>
</div> </div>
<span className="text-mti-gray-taupe scrollbar-hide flex gap-8 overflow-x-scroll"> <span className="text-mti-gray-taupe scrollbar-hide flex gap-8 overflow-x-scroll">
@@ -102,40 +82,29 @@ export default function PaymentDue({
)} )}
<div className="flex w-full flex-col items-center justify-center gap-4 text-center"> <div className="flex w-full flex-col items-center justify-center gap-4 text-center">
{hasExpired && ( {hasExpired && <span className="text-lg font-bold">You do not have time credits for your account type!</span>}
<span className="text-lg font-bold">
You do not have time credits for your account type!
</span>
)}
{isIndividual() && ( {isIndividual() && (
<div className="scrollbar-hide flex w-full flex-col items-center gap-12 overflow-x-scroll"> <div className="scrollbar-hide flex w-full flex-col items-center gap-12 overflow-x-scroll">
<span className="max-w-lg"> <span className="max-w-lg">
To add to your use of EnCoach, please purchase one of the time To add to your use of EnCoach, please purchase one of the time packages available below:
packages available below:
</span> </span>
<div className="flex w-full flex-wrap justify-center gap-8"> <div className="flex w-full flex-wrap justify-center gap-8">
<PayPalScriptProvider
options={{
clientId: clientID,
currency: "USD",
intent: "capture",
commit: true,
vault: true,
}}>
{packages.map((p) => ( {packages.map((p) => (
<div <div key={p.id} className={clsx("flex flex-col items-start gap-6 rounded-xl bg-white p-4")}>
key={p.id}
className={clsx(
"flex flex-col items-start gap-6 rounded-xl bg-white p-4",
)}
>
<div className="mb-2 flex flex-col items-start"> <div className="mb-2 flex flex-col items-start">
<img <img src="/logo_title.png" alt="EnCoach's Logo" className="w-32" />
src="/logo_title.png"
alt="EnCoach's Logo"
className="w-32"
/>
<span className="text-xl font-semibold"> <span className="text-xl font-semibold">
EnCoach - {p.duration}{" "} EnCoach - {p.duration}{" "}
{capitalize( {capitalize(
p.duration === 1 p.duration === 1 ? p.duration_unit.slice(0, p.duration_unit.length - 1) : p.duration_unit,
? p.duration_unit.slice(
0,
p.duration_unit.length - 1,
)
: p.duration_unit,
)} )}
</span> </span>
</div> </div>
@@ -158,49 +127,30 @@ export default function PaymentDue({
<span>This includes:</span> <span>This includes:</span>
<ul className="flex flex-col items-start text-sm"> <ul className="flex flex-col items-start text-sm">
<li>- Train your abilities for the IELTS exam</li> <li>- Train your abilities for the IELTS exam</li>
<li> <li>- Gain insights into your weaknesses and strengths</li>
- Gain insights into your weaknesses and strengths <li>- Allow yourself to correctly prepare for the exam</li>
</li>
<li>
- Allow yourself to correctly prepare for the exam
</li>
</ul> </ul>
</div> </div>
</div> </div>
))} ))}
</PayPalScriptProvider>
</div> </div>
</div> </div>
)} )}
{!isIndividual() && {!isIndividual() && user.type === "corporate" && user?.corporateInformation.payment && (
user.type === "corporate" &&
user?.corporateInformation.payment && (
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<span className="max-w-lg"> <span className="max-w-lg">
To add to your use of EnCoach and that of your students and To add to your use of EnCoach and that of your students and teachers, please pay your designated package below:
teachers, please pay your designated package below:
</span> </span>
<div <div className={clsx("flex flex-col items-start gap-6 rounded-xl bg-white p-4")}>
className={clsx(
"flex flex-col items-start gap-6 rounded-xl bg-white p-4",
)}
>
<div className="mb-2 flex flex-col items-start"> <div className="mb-2 flex flex-col items-start">
<img <img src="/logo_title.png" alt="EnCoach's Logo" className="w-32" />
src="/logo_title.png" <span className="text-xl font-semibold">EnCoach - {user.corporateInformation?.monthlyDuration} Months</span>
alt="EnCoach's Logo"
className="w-32"
/>
<span className="text-xl font-semibold">
EnCoach - {user.corporateInformation?.monthlyDuration}{" "}
Months
</span>
</div> </div>
<div className="flex w-full flex-col items-start gap-2"> <div className="flex w-full flex-col items-start gap-2">
<span className="text-2xl"> <span className="text-2xl">
{user.corporateInformation.payment.value} {user.corporateInformation.payment.value}
{getSymbolFromCurrency( {getSymbolFromCurrency(user.corporateInformation.payment.currency)}
user.corporateInformation.payment.currency,
)}
</span> </span>
<PayPalPayment <PayPalPayment
key={clientID} key={clientID}
@@ -214,24 +164,18 @@ export default function PaymentDue({
setIsLoading(false); setIsLoading(false);
setTimeout(reload, 500); setTimeout(reload, 500);
}} }}
loadScript
/> />
</div> </div>
<div className="flex flex-col items-start gap-1"> <div className="flex flex-col items-start gap-1">
<span>This includes:</span> <span>This includes:</span>
<ul className="flex flex-col items-start text-sm"> <ul className="flex flex-col items-start text-sm">
<li> <li>
- Allow a total of{" "} - Allow a total of {user.corporateInformation.companyInformation.userAmount} students and teachers to
{ use EnCoach
user.corporateInformation.companyInformation
.userAmount
}{" "}
students and teachers to use EnCoach
</li> </li>
<li>- Train their abilities for the IELTS exam</li> <li>- Train their abilities for the IELTS exam</li>
<li> <li>- Gain insights into your students&apos; weaknesses and strengths</li>
- Gain insights into your students&apos; weaknesses
and strengths
</li>
<li>- Allow them to correctly prepare for the exam</li> <li>- Allow them to correctly prepare for the exam</li>
</ul> </ul>
</div> </div>
@@ -241,27 +185,22 @@ export default function PaymentDue({
{!isIndividual() && user.type !== "corporate" && ( {!isIndividual() && user.type !== "corporate" && (
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<span className="max-w-lg"> <span className="max-w-lg">
You are not the person in charge of your time credits, please You are not the person in charge of your time credits, please contact your administrator about this situation.
contact your administrator about this situation.
</span> </span>
<span className="max-w-lg"> <span className="max-w-lg">
If you believe this to be a mistake, please contact the If you believe this to be a mistake, please contact the platform&apos;s administration, thank you for your
platform&apos;s administration, thank you for your patience. patience.
</span> </span>
</div> </div>
)} )}
{!isIndividual() && {!isIndividual() && user.type === "corporate" && !user.corporateInformation.payment && (
user.type === "corporate" &&
!user.corporateInformation.payment && (
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<span className="max-w-lg"> <span className="max-w-lg">
An admin nor your agent have yet set the price intended to An admin nor your agent have yet set the price intended to your requirements in terms of the amount of users you
your requirements in terms of the amount of users you desire desire and your expected monthly duration.
and your expected monthly duration.
</span> </span>
<span className="max-w-lg"> <span className="max-w-lg">
Please try again later or contact your agent or an admin, Please try again later or contact your agent or an admin, thank you for your patience.
thank you for your patience.
</span> </span>
</div> </div>
)} )}