Enabled payment for Corporate along with increasing every single one of their students/teachers expiry date as well

This commit is contained in:
Tiago Ribeiro
2023-11-26 11:01:27 +00:00
parent 7e91a989b3
commit fa544bf4e8
3 changed files with 127 additions and 84 deletions

View File

@@ -10,10 +10,11 @@ interface Props {
price: number;
duration: number;
duration_unit: DurationUnit;
setIsLoading: (isLoading: boolean) => void;
onSuccess: (duration: number, duration_unit: DurationUnit) => void;
}
export default function PayPalPayment({price, currency, duration, duration_unit, onSuccess}: Props) {
export default function PayPalPayment({price, currency, duration, duration_unit, setIsLoading, onSuccess}: Props) {
const [{options}, dispatch] = usePayPalScriptReducer();
useEffect(() => {
@@ -28,7 +29,7 @@ export default function PayPalPayment({price, currency, duration, duration_unit,
}, [currency]);
const createOrder = async (data: CreateOrderData, actions: CreateOrderActions): Promise<string> => {
console.log(data, actions);
setIsLoading(true);
return axios
.post<OrderResponseBody>("/api/paypal", {currencyCode: currency, price})
@@ -49,13 +50,11 @@ export default function PayPalPayment({price, currency, duration, duration_unit,
};
const onError = async (data: Record<string, unknown>) => {
console.log(data);
toast.error("ERROR!");
setIsLoading(false);
};
const onCancel = async (data: Record<string, unknown>, actions: OnCancelledActions) => {
console.log(data, actions);
toast.error("CANCEL!");
setIsLoading(false);
};
return (

View File

@@ -20,10 +20,9 @@ import Input from "@/components/Low/Input";
import Button from "@/components/Low/Button";
export default function PaymentDue({user, reload}: {user: User; reload: () => void}) {
const [selectedPackage, setPackage] = useState<string>();
const [code, setCode] = useState<string>();
const [isLoading, setIsLoading] = useState(false);
const {packages, isLoading} = usePackages();
const {packages} = usePackages();
const {users} = useUsers();
const {groups} = useGroups();
@@ -38,13 +37,25 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
return userGroupsAdminTypes.every((t) => t !== "admin");
};
return user ? (
return (
<>
{isLoading && (
<div className="w-screen h-screen absolute top-0 left-0 overflow-hidden z-[999] bg-black/60">
<div className="w-fit h-fit absolute top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2 animate-pulse flex flex-col gap-8 items-center text-white">
<span className={clsx("loading loading-infinity w-48")} />
<span className={clsx("font-bold text-2xl")}>Completing your payment...</span>
</div>
</div>
)}
{user ? (
<Layout user={user} navDisabled>
<div className="flex flex-col items-center justify-center text-center w-full gap-4">
<span className="font-bold text-lg">You do not have time credits for your account type!</span>
{isIndividual() && (
<div className="flex flex-col items-center w-full overflow-x-scroll scrollbar-hide gap-12">
<span className="max-w-lg">To add to your use of EnCoach, please purchase one of the time packages available below:</span>
<span className="max-w-lg">
To add to your use of EnCoach, please purchase one of the time packages available below:
</span>
<div className="w-full flex flex-wrap justify-center gap-8">
{packages.map((p) => (
<div key={p.id} className={clsx("p-4 bg-white rounded-xl flex flex-col gap-6 items-start")}>
@@ -52,7 +63,9 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
<img src="/logo_title.png" alt="EnCoach's Logo" className="w-32" />
<span className="font-semibold text-xl">
EnCoach - {p.duration}{" "}
{capitalize(p.duration === 1 ? p.duration_unit.slice(0, p.duration_unit.length - 1) : p.duration_unit)}
{capitalize(
p.duration === 1 ? p.duration_unit.slice(0, p.duration_unit.length - 1) : p.duration_unit,
)}
</span>
</div>
<div className="flex flex-col gap-2 items-start w-full">
@@ -62,6 +75,7 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
</span>
<PayPalPayment
{...p}
setIsLoading={setIsLoading}
onSuccess={(duration, duration_unit) => {
setTimeout(reload, 500);
}}
@@ -88,7 +102,7 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
<div className={clsx("p-4 bg-white rounded-xl flex flex-col gap-6 items-start")}>
<div className="flex flex-col items-start mb-2">
<img src="/logo_title.png" alt="EnCoach's Logo" className="w-32" />
<span className="font-semibold text-xl">EnCoach - {user.corporateInformation?.monthlyDuration} Month(s)</span>
<span className="font-semibold text-xl">EnCoach - {user.corporateInformation?.monthlyDuration} Months</span>
</div>
<div className="flex flex-col gap-2 items-start w-full">
<span className="text-2xl">
@@ -96,11 +110,13 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
{getSymbolFromCurrency(user.corporateInformation.payment.currency)}
</span>
<PayPalPayment
setIsLoading={setIsLoading}
currency={user.corporateInformation.payment.currency}
price={user.corporateInformation.payment.value}
duration={user.corporateInformation.monthlyDuration}
duration_unit="months"
onSuccess={(duration, duration_unit) => {
setIsLoading(false);
setTimeout(reload, 500);
}}
/>
@@ -109,8 +125,8 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
<span>This includes:</span>
<ul className="flex flex-col items-start text-sm">
<li>
- Allow a total of {user.corporateInformation.companyInformation.userAmount} students and teachers to use
EnCoach
- Allow a total of {user.corporateInformation.companyInformation.userAmount} students and teachers to
use EnCoach
</li>
<li>- Train their abilities for the IELTS exam</li>
<li>- Gain insights into your students&apos; weaknesses and strengths</li>
@@ -123,15 +139,19 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
{!isIndividual() && (!user?.corporateInformation || !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.
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 again later or contact your agent or an admin, thank you for your patience.
</span>
<span className="max-w-lg">Please try again again later or contact your agent or an admin, thank you for your patience.</span>
</div>
)}
</div>
</Layout>
) : (
<div />
)}
</>
);
}

View File

@@ -11,6 +11,7 @@ import {v4} from "uuid";
import {OrderResponseBody} from "@paypal/paypal-js";
import {getAccessToken} from "@/utils/paypal";
import moment from "moment";
import {Group} from "@/interfaces/user";
const db = getFirestore(app);
@@ -36,6 +37,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
);
if (request.data.status === "COMPLETED") {
const user = req.session.user;
const subscriptionExpirationDate = req.session.user.subscriptionExpirationDate;
const today = moment(new Date());
const dateToBeAddedTo = !subscriptionExpirationDate
@@ -51,8 +53,30 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
{merge: true},
);
res.status(200).json({ok: true});
return;
if (user.type === "corporate") {
const snapshot = await getDocs(collection(db, "groups"));
const groups: Group[] = (
snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
})) as Group[]
).filter((x) => x.admin === user.id);
await Promise.all(
groups
.flatMap((x) => x.participants)
.map(
async (x) =>
await setDoc(
doc(db, "users", x),
{subscriptionExpirationDate: updatedExpirationDate.toISOString(), status: "active"},
{merge: true},
),
),
);
}
return res.status(200).json({ok: true});
}
res.status(404).json({ok: false, reason: "Order ID not found or purchase was not approved!"});