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,272 +4,211 @@ 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;
hasExpired?: boolean; hasExpired?: boolean;
clientID: string; clientID: string;
reload: () => void; reload: () => void;
} }
export default function PaymentDue({ export default function PaymentDue({user, hasExpired = false, clientID, reload}: Props) {
user, const [isLoading, setIsLoading] = useState(false);
hasExpired = false,
clientID,
reload,
}: Props) {
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;
if (user?.type !== "student") return false; if (user?.type !== "student") return false;
const userGroups = groups.filter((g) => g.participants.includes(user?.id)); const userGroups = groups.filter((g) => g.participants.includes(user?.id));
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) return userGroupsAdminTypes.every((t) => t !== "corporate");
.filter((t) => !!t); };
return userGroupsAdminTypes.every((t) => t !== "corporate");
};
return ( return (
<> <>
{isLoading && ( {isLoading && (
<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... </div>
</span> </div>
</div> )}
</div> {user ? (
)} <Layout user={user} navDisabled={hasExpired}>
{user ? ( {invites.length > 0 && (
<Layout user={user} navDisabled={hasExpired}> <section className="flex flex-col gap-1 md:gap-3">
{invites.length > 0 && ( <div className="flex items-center gap-4">
<section className="flex flex-col gap-1 md:gap-3"> <div
<div className="flex items-center gap-4"> onClick={reloadInvites}
<div className="text-mti-purple-light hover:text-mti-purple-dark flex cursor-pointer items-center gap-2 transition duration-300 ease-in-out">
onClick={reloadInvites} <span className="text-mti-black text-lg font-bold">Invites</span>
className="text-mti-purple-light hover:text-mti-purple-dark flex cursor-pointer items-center gap-2 transition duration-300 ease-in-out" <BsArrowRepeat className={clsx("text-xl", isInvitesLoading && "animate-spin")} />
> </div>
<span className="text-mti-black text-lg font-bold"> </div>
Invites <span className="text-mti-gray-taupe scrollbar-hide flex gap-8 overflow-x-scroll">
</span> {invites.map((invite) => (
<BsArrowRepeat <InviteCard
className={clsx( key={invite.id}
"text-xl", invite={invite}
isInvitesLoading && "animate-spin", users={users}
)} reload={() => {
/> reloadInvites();
</div> router.reload();
</div> }}
<span className="text-mti-gray-taupe scrollbar-hide flex gap-8 overflow-x-scroll"> />
{invites.map((invite) => ( ))}
<InviteCard </span>
key={invite.id} </section>
invite={invite} )}
users={users}
reload={() => {
reloadInvites();
router.reload();
}}
/>
))}
</span>
</section>
)}
<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"> {isIndividual() && (
You do not have time credits for your account type! <div className="scrollbar-hide flex w-full flex-col items-center gap-12 overflow-x-scroll">
</span> <span className="max-w-lg">
)} To add to your use of EnCoach, please purchase one of the time packages available below:
{isIndividual() && ( </span>
<div className="scrollbar-hide flex w-full flex-col items-center gap-12 overflow-x-scroll"> <div className="flex w-full flex-wrap justify-center gap-8">
<span className="max-w-lg"> <PayPalScriptProvider
To add to your use of EnCoach, please purchase one of the time options={{
packages available below: clientId: clientID,
</span> currency: "USD",
<div className="flex w-full flex-wrap justify-center gap-8"> intent: "capture",
{packages.map((p) => ( commit: true,
<div vault: true,
key={p.id} }}>
className={clsx( {packages.map((p) => (
"flex flex-col items-start gap-6 rounded-xl bg-white p-4", <div 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">
> <img src="/logo_title.png" alt="EnCoach's Logo" className="w-32" />
<div className="mb-2 flex flex-col items-start"> <span className="text-xl font-semibold">
<img EnCoach - {p.duration}{" "}
src="/logo_title.png" {capitalize(
alt="EnCoach's Logo" p.duration === 1 ? p.duration_unit.slice(0, p.duration_unit.length - 1) : p.duration_unit,
className="w-32" )}
/> </span>
<span className="text-xl font-semibold"> </div>
EnCoach - {p.duration}{" "} <div className="flex w-full flex-col items-start gap-2">
{capitalize( <span className="text-2xl">
p.duration === 1 {p.price}
? p.duration_unit.slice( {getSymbolFromCurrency(p.currency)}
0, </span>
p.duration_unit.length - 1, <PayPalPayment
) key={clientID}
: p.duration_unit, {...p}
)} clientID={clientID}
</span> setIsLoading={setIsLoading}
</div> onSuccess={() => {
<div className="flex w-full flex-col items-start gap-2"> setTimeout(reload, 500);
<span className="text-2xl"> }}
{p.price} />
{getSymbolFromCurrency(p.currency)} </div>
</span> <div className="flex flex-col items-start gap-1">
<PayPalPayment <span>This includes:</span>
key={clientID} <ul className="flex flex-col items-start text-sm">
{...p} <li>- Train your abilities for the IELTS exam</li>
clientID={clientID} <li>- Gain insights into your weaknesses and strengths</li>
setIsLoading={setIsLoading} <li>- Allow yourself to correctly prepare for the exam</li>
onSuccess={() => { </ul>
setTimeout(reload, 500); </div>
}} </div>
/> ))}
</div> </PayPalScriptProvider>
<div className="flex flex-col items-start gap-1"> </div>
<span>This includes:</span> </div>
<ul className="flex flex-col items-start text-sm"> )}
<li>- Train your abilities for the IELTS exam</li> {!isIndividual() && user.type === "corporate" && user?.corporateInformation.payment && (
<li> <div className="flex flex-col items-center">
- Gain insights into your weaknesses and strengths <span className="max-w-lg">
</li> To add to your use of EnCoach and that of your students and teachers, please pay your designated package below:
<li> </span>
- Allow yourself to correctly prepare for the exam <div className={clsx("flex flex-col items-start gap-6 rounded-xl bg-white p-4")}>
</li> <div className="mb-2 flex flex-col items-start">
</ul> <img src="/logo_title.png" alt="EnCoach's Logo" className="w-32" />
</div> <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> <span className="text-2xl">
</div> {user.corporateInformation.payment.value}
)} {getSymbolFromCurrency(user.corporateInformation.payment.currency)}
{!isIndividual() && </span>
user.type === "corporate" && <PayPalPayment
user?.corporateInformation.payment && ( key={clientID}
<div className="flex flex-col items-center"> clientID={clientID}
<span className="max-w-lg"> setIsLoading={setIsLoading}
To add to your use of EnCoach and that of your students and currency={user.corporateInformation.payment.currency}
teachers, please pay your designated package below: price={user.corporateInformation.payment.value}
</span> duration={user.corporateInformation.monthlyDuration}
<div duration_unit="months"
className={clsx( onSuccess={() => {
"flex flex-col items-start gap-6 rounded-xl bg-white p-4", setIsLoading(false);
)} setTimeout(reload, 500);
> }}
<div className="mb-2 flex flex-col items-start"> loadScript
<img />
src="/logo_title.png" </div>
alt="EnCoach's Logo" <div className="flex flex-col items-start gap-1">
className="w-32" <span>This includes:</span>
/> <ul className="flex flex-col items-start text-sm">
<span className="text-xl font-semibold"> <li>
EnCoach - {user.corporateInformation?.monthlyDuration}{" "} - Allow a total of {user.corporateInformation.companyInformation.userAmount} students and teachers to
Months use EnCoach
</span> </li>
</div> <li>- Train their abilities for the IELTS exam</li>
<div className="flex w-full flex-col items-start gap-2"> <li>- Gain insights into your students&apos; weaknesses and strengths</li>
<span className="text-2xl"> <li>- Allow them to correctly prepare for the exam</li>
{user.corporateInformation.payment.value} </ul>
{getSymbolFromCurrency( </div>
user.corporateInformation.payment.currency, </div>
)} </div>
</span> )}
<PayPalPayment {!isIndividual() && user.type !== "corporate" && (
key={clientID} <div className="flex flex-col items-center">
clientID={clientID} <span className="max-w-lg">
setIsLoading={setIsLoading} You are not the person in charge of your time credits, please contact your administrator about this situation.
currency={user.corporateInformation.payment.currency} </span>
price={user.corporateInformation.payment.value} <span className="max-w-lg">
duration={user.corporateInformation.monthlyDuration} If you believe this to be a mistake, please contact the platform&apos;s administration, thank you for your
duration_unit="months" patience.
onSuccess={() => { </span>
setIsLoading(false); </div>
setTimeout(reload, 500); )}
}} {!isIndividual() && user.type === "corporate" && !user.corporateInformation.payment && (
/> <div className="flex flex-col items-center">
</div> <span className="max-w-lg">
<div className="flex flex-col items-start gap-1"> An admin nor your agent have yet set the price intended to your requirements in terms of the amount of users you
<span>This includes:</span> desire and your expected monthly duration.
<ul className="flex flex-col items-start text-sm"> </span>
<li> <span className="max-w-lg">
- Allow a total of{" "} Please try again later or contact your agent or an admin, thank you for your patience.
{ </span>
user.corporateInformation.companyInformation </div>
.userAmount )}
}{" "} </div>
students and teachers to use EnCoach </Layout>
</li> ) : (
<li>- Train their abilities for the IELTS exam</li> <div />
<li> )}
- Gain insights into your students&apos; weaknesses </>
and strengths );
</li>
<li>- Allow them to correctly prepare for the exam</li>
</ul>
</div>
</div>
</div>
)}
{!isIndividual() && user.type !== "corporate" && (
<div className="flex flex-col items-center">
<span className="max-w-lg">
You are not the person in charge of your time credits, please
contact your administrator about this situation.
</span>
<span className="max-w-lg">
If you believe this to be a mistake, please contact the
platform&apos;s administration, thank you for your patience.
</span>
</div>
)}
{!isIndividual() &&
user.type === "corporate" &&
!user.corporateInformation.payment && (
<div className="flex flex-col items-center">
<span className="max-w-lg">
An admin nor your agent have yet set the price intended to
your requirements in terms of the amount of users you desire
and your expected monthly duration.
</span>
<span className="max-w-lg">
Please try again later or contact your agent or an admin,
thank you for your patience.
</span>
</div>
)}
</div>
</Layout>
) : (
<div />
)}
</>
);
} }