Better verify

This commit is contained in:
2025-10-17 11:08:58 +02:00
parent 4876b57389
commit 56e8857c7c
2 changed files with 143 additions and 103 deletions
+74
View File
@@ -0,0 +1,74 @@
"use client";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import Cookies from "js-cookie";
import axios from "axios";
export default function Verify() {
const [email, setEmail] = useState<string>();
const router = useRouter();
const [verified, setVerified] = useState(false);
useEffect(() => {
const email = Cookies.get("verify_temp_email");
setEmail(email);
const password = Cookies.get("verify_temp_password");
const i = setInterval(async () => {
const { data } = await axios.get("/api/verify", {
params: { email, password },
});
const response = data as {
verified: boolean;
user_id: string;
access_token?: string;
refresh_token?: string;
};
if (response.verified) {
clearInterval(i);
if (response.access_token) {
setVerified(true);
toast.info("Email verified, redirecting...");
Cookies.set("token", response.access_token);
Cookies.remove("verify_temp_email");
Cookies.remove("verify_temp_password");
setTimeout(() => router.push("/chat"), 500);
} else {
console.log(response);
}
}
}, 8000);
}, []);
return (
<div className="h-screen flex items-center">
<Card className="w-md m-auto">
<CardHeader>
<CardTitle className="text-3xl mx-auto">Verify Email</CardTitle>
<CardDescription>
{verified ? (
"Successfully verified"
) : (
<>
We sent you a verification email at {email}. Please verify to
continue.
</>
)}
</CardDescription>
</CardHeader>
<CardContent className="gap-3 flex flex-col">
Current status: {verified ? "Verified" : "Unverified"}
</CardContent>
</Card>
</div>
);
}
+69 -103
View File
@@ -3,13 +3,13 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import axios from "axios"; import axios from "axios";
import { useEffect, useState } from "react"; import { useState } from "react";
import Cookies from "js-cookie";
import { useRouter } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
import { CardContent, CardHeader, CardTitle } from "../ui/card"; import { CardContent, CardHeader, CardTitle } from "../ui/card";
import { Label } from "../ui/label"; import { Label } from "../ui/label";
import { toast } from "sonner"; import { toast } from "sonner";
import { useRouter } from "next/navigation";
import Cookies from "js-cookie";
export default function CreateAccount() { export default function CreateAccount() {
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
@@ -21,40 +21,8 @@ export default function CreateAccount() {
const [feedback, setFeedback] = useState< const [feedback, setFeedback] = useState<
undefined | { kind: "error" | "info"; message: string } undefined | { kind: "error" | "info"; message: string }
>(); >();
const [verify, setVerify] = useState<string | undefined>();
const router = useRouter(); const router = useRouter();
// Verify interval
useEffect(() => {
if (verify) {
const i = setInterval(async () => {
const { data } = await axios.get("/api/verify", {
params: { email, password },
});
const response = data as {
verified: boolean;
user_id: string;
access_token?: string;
refresh_token?: string;
};
if (response.verified) {
clearInterval(i);
setFeedback({
message: "Email verified, redirecting...",
kind: "info",
});
if (response.access_token) {
Cookies.set("token", response.access_token);
setTimeout(() => router.push("/chat"), 500);
} else {
console.log(response);
}
}
}, 8000);
}
}, [verify]);
const validateInput = (): const validateInput = ():
| { kind: "error" | "info"; message: string } | { kind: "error" | "info"; message: string }
| undefined => { | undefined => {
@@ -113,8 +81,14 @@ export default function CreateAccount() {
toast.info( toast.info(
"We sent you a verification email. Please verify to continue." "We sent you a verification email. Please verify to continue."
); );
setFeedback(undefined); setFeedback({
setVerify(response.user_id); message:
"We sent you a verification email. Please verify to continue.",
kind: "info",
});
Cookies.set("verify_temp_email", email);
Cookies.set("verify_temp_password", password);
router.push(`/verify`);
} else { } else {
setFeedback({ message: response.message, kind: "error" }); setFeedback({ message: response.message, kind: "error" });
} }
@@ -133,77 +107,69 @@ export default function CreateAccount() {
return ( return (
<> <>
<CardHeader> <CardHeader>
<CardTitle className="text-3xl mx-auto"> <CardTitle className="text-3xl mx-auto">Create an Account</CardTitle>
{verify ? "Verify" : "Create an Account"}
</CardTitle>
</CardHeader> </CardHeader>
<CardContent className="gap-3 flex flex-col"> <CardContent className="gap-3 flex flex-col">
{verify ? ( <span>
`We sent you a verification email at (${email}). Please verify to continue.` Email
) : ( <Input
<> onChange={(e) => setEmail(e.target.value)}
<span> placeholder="[email protected]"
Email type="email"
<Input />
onChange={(e) => setEmail(e.target.value)} </span>
placeholder="[email protected]" <span>
type="email" Username
/> <Input
</span> onChange={(e) => setUsername(e.target.value)}
<span> placeholder="john_doe"
Username />
<Input </span>
onChange={(e) => setUsername(e.target.value)} <span>
placeholder="john_doe" Password
/> <Input
</span> onChange={(e) => setPassword(e.target.value)}
<span> type="password"
Password />
<Input </span>
onChange={(e) => setPassword(e.target.value)} <span>
type="password" Confirm Password
/> <Input
</span> onChange={(e) => setConfirmPassword(e.target.value)}
<span> onKeyDown={(e) => {
Confirm Password if (e.key === "Enter") signup();
<Input }}
onChange={(e) => setConfirmPassword(e.target.value)} type="password"
onKeyDown={(e) => { />
if (e.key === "Enter") signup(); </span>
}}
type="password"
/>
</span>
<Label className="flex items-center gap-2 text-sm"> <Label className="flex items-center gap-2 text-sm">
<input <input
type="checkbox" type="checkbox"
checked={acceptTerms} checked={acceptTerms}
onChange={(e) => setAcceptTerms(e.target.checked)} onChange={(e) => setAcceptTerms(e.target.checked)}
/> />
I agree to the{" "} I agree to the{" "}
<Link className="underline" href="/terms"> <Link className="underline" href="/terms">
terms & conditions terms & conditions
</Link> </Link>
</Label> </Label>
{feedback && ( {feedback && (
<div <div
className={`text-sm rounded-md p-2 ${ className={`text-sm rounded-md p-2 ${
feedback.kind === "error" feedback.kind === "error"
? "bg-red-500/20 text-red-400" ? "bg-red-500/20 text-red-400"
: "bg-green-500/20 text-green-400" : "bg-green-500/20 text-green-400"
}`} }`}
> >
{feedback.message} {feedback.message}
</div> </div>
)}
<Button onClick={signup} disabled={loading}>
{loading ? "Signing Up..." : "Sign Up"}
</Button>
</>
)} )}
<Button onClick={signup} disabled={loading}>
{loading ? "Signing Up..." : "Sign Up"}
</Button>
</CardContent> </CardContent>
</> </>
); );