Seed: saas template (34 files)
This commit is contained in:
@@ -0,0 +1,107 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Layers, ArrowLeft, Mail, CheckCircle2, KeyRound } from "lucide-react";
|
||||||
|
|
||||||
|
export default function ForgotPasswordPage() {
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [sent, setSent] = useState(false);
|
||||||
|
const [code, setCode] = useState("");
|
||||||
|
const [newPassword, setNewPassword] = useState("");
|
||||||
|
const [step, setStep] = useState<"email" | "code" | "done">("email");
|
||||||
|
|
||||||
|
const handleSendCode = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setSent(true);
|
||||||
|
toast.success("Reset code sent to " + email);
|
||||||
|
setStep("code");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleResetPassword = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
toast.success("Password reset successfully!");
|
||||||
|
setStep("done");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-indigo-950 to-slate-900 flex items-center justify-center p-6">
|
||||||
|
<div className="w-full max-w-md">
|
||||||
|
<Link to="/" className="flex items-center justify-center gap-2 mb-8">
|
||||||
|
<div className="h-10 w-10 rounded-xl bg-gradient-to-br from-indigo-500 to-cyan-500 flex items-center justify-center">
|
||||||
|
<Layers className="h-5 w-5 text-white" />
|
||||||
|
</div>
|
||||||
|
<span className="text-2xl font-bold text-white tracking-tight">Nexus</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Card className="border-slate-800 bg-slate-900/50 backdrop-blur-xl shadow-2xl">
|
||||||
|
<CardContent className="p-8">
|
||||||
|
{step === "email" && (
|
||||||
|
<>
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<div className="mx-auto w-12 h-12 rounded-full bg-indigo-500/10 flex items-center justify-center mb-4">
|
||||||
|
<Mail className="h-6 w-6 text-indigo-400" />
|
||||||
|
</div>
|
||||||
|
<h1 className="text-2xl font-bold text-white">Forgot password?</h1>
|
||||||
|
<p className="text-slate-400 mt-1 text-sm">No worries, we'll send you a reset code</p>
|
||||||
|
</div>
|
||||||
|
<form onSubmit={handleSendCode} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="reset-email" className="text-slate-300 text-sm">Email</Label>
|
||||||
|
<Input id="reset-email" type="email" required placeholder="you@company.com" value={email} onChange={(e) => setEmail(e.target.value)} className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500" />
|
||||||
|
</div>
|
||||||
|
<Button type="submit" className="w-full bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-semibold">Send Reset Code</Button>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{step === "code" && (
|
||||||
|
<>
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<div className="mx-auto w-12 h-12 rounded-full bg-emerald-500/10 flex items-center justify-center mb-4">
|
||||||
|
<KeyRound className="h-6 w-6 text-emerald-400" />
|
||||||
|
</div>
|
||||||
|
<h1 className="text-2xl font-bold text-white">Enter reset code</h1>
|
||||||
|
<p className="text-slate-400 mt-1 text-sm">Check your email for a 6-digit code</p>
|
||||||
|
</div>
|
||||||
|
<form onSubmit={handleResetPassword} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="code" className="text-slate-300 text-sm">Reset Code</Label>
|
||||||
|
<Input id="code" type="text" required placeholder="000000" maxLength={6} value={code} onChange={(e) => setCode(e.target.value)} className="mt-1.5 bg-slate-800/50 border-slate-700 text-white text-center text-2xl tracking-[0.5em] placeholder:text-slate-500 placeholder:tracking-[0.5em] focus:border-indigo-500" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="new-password" className="text-slate-300 text-sm">New Password</Label>
|
||||||
|
<Input id="new-password" type="password" required placeholder="Enter new password" minLength={8} value={newPassword} onChange={(e) => setNewPassword(e.target.value)} className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500" />
|
||||||
|
</div>
|
||||||
|
<Button type="submit" className="w-full bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-semibold">Reset Password</Button>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{step === "done" && (
|
||||||
|
<div className="text-center py-4">
|
||||||
|
<div className="mx-auto w-12 h-12 rounded-full bg-emerald-500/10 flex items-center justify-center mb-4">
|
||||||
|
<CheckCircle2 className="h-6 w-6 text-emerald-400" />
|
||||||
|
</div>
|
||||||
|
<h1 className="text-2xl font-bold text-white">Password reset!</h1>
|
||||||
|
<p className="text-slate-400 mt-2 text-sm">Your password has been reset successfully</p>
|
||||||
|
<Link to="/login">
|
||||||
|
<Button className="mt-6 bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-semibold">Back to Sign In</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mt-6 text-center">
|
||||||
|
<Link to="/login" className="text-sm text-slate-400 hover:text-white inline-flex items-center gap-1">
|
||||||
|
<ArrowLeft className="h-3 w-3" /> Back to sign in
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user