Enabled payment for Corporate along with increasing every single one of their students/teachers expiry date as well
This commit is contained in:
@@ -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 (
|
||||
|
||||
@@ -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' 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 />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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!"});
|
||||
|
||||
Reference in New Issue
Block a user