import { signIn } from "next-auth/react";
import Head from "next/head";
import { useRouter } from "next/router";
import * as React from "react";
import { useEffect, useState, useRef } from "react";
import z from "zod";
import { APP_NAME, WEBAPP_URL } from "@calcom/lib/constants";
import { trpc } from "@calcom/trpc/react";
import { Button, showToast } from "@calcom/ui";
import { Check, MailOpen, AlertTriangle } from "@calcom/ui/components/icon";
import Loader from "@components/Loader";
import PageWrapper from "@components/PageWrapper";
async function sendVerificationLogin(email: string, username: string) {
await signIn("email", {
email: email.toLowerCase(),
username: username.toLowerCase(),
redirect: false,
callbackUrl: WEBAPP_URL || "https://app.cal.com",
})
.then(() => {
showToast("Verification email sent", "success");
})
.catch((err) => {
showToast(err, "error");
});
}
function useSendFirstVerificationLogin({
email,
username,
}: {
email: string | undefined;
username: string | undefined;
}) {
const sent = useRef(false);
useEffect(() => {
if (!email || !username || sent.current) {
return;
}
(async () => {
await sendVerificationLogin(email, username);
sent.current = true;
})();
}, [email, username]);
}
const querySchema = z.object({
stripeCustomerId: z.string().optional(),
sessionId: z.string().optional(),
t: z.string().optional(),
});
export default function Verify() {
const router = useRouter();
const { t, sessionId, stripeCustomerId } = querySchema.parse(router.query);
const [secondsLeft, setSecondsLeft] = useState(30);
const { data } = trpc.viewer.public.stripeCheckoutSession.useQuery({
stripeCustomerId,
checkoutSessionId: sessionId,
});
useSendFirstVerificationLogin({ email: data?.customer?.email, username: data?.customer?.username });
// @note: check for t=timestamp and apply disabled state and secondsLeft accordingly
// to avoid refresh to skip waiting 30 seconds to re-send email
useEffect(() => {
const lastSent = new Date(parseInt(`${t}`));
// @note: This double round() looks ugly but it's the only way I came up to get the time difference in seconds
const difference = Math.round(Math.round(new Date().getTime() - lastSent.getTime()) / 1000);
if (difference < 30) {
// If less than 30 seconds, set the seconds left to 30 - difference
setSecondsLeft(30 - difference);
} else {
// else set the seconds left to 0 and disabled false
setSecondsLeft(0);
}
}, [t]);
// @note: here we make sure each second is decremented if disabled up to 0.
useEffect(() => {
if (secondsLeft > 0) {
const interval = setInterval(() => {
if (secondsLeft > 0) {
setSecondsLeft(secondsLeft - 1);
}
}, 1000);
return () => clearInterval(interval);
}
}, [secondsLeft]);
if (!router.isReady || !data) {
// Loading state
return
Your account has been created, but your premium has not been reserved.
)}We have sent an email to {customer?.email} with a link to activate your account.{" "} {hasPaymentFailed && "Once you activate your account you will be able to try purchase your premium username again or select a different one."}
Don't see an email? Click the button below to send another email.