Component Details

Auth Component 03

Auth Component 03

ForgotPasswordPage.tsx

Next.jsTailwind CSS
1// app/auth/forgot-password/page.tsx
2"use client";
3
4import type React from "react";
5import { useState } from "react";
6import Link from "next/link";
7import { Button } from "@/components/ui/button";
8import { Input } from "@/components/ui/input";
9import {
10  Card,
11  CardContent,
12  CardHeader,
13  CardTitle,
14  CardDescription,
15  CardFooter,
16} from "@/components/ui/card";
17import { Alert, AlertDescription } from "@/components/ui/alert";
18import { Label } from "@/components/ui/label";
19import { AlertCircle, Loader2, Mail, CheckCircle } from "lucide-react";
20
21export default function ForgotPasswordPage() {
22  const [email, setEmail] = useState("");
23  const [error, setError] = useState("");
24  const [success, setSuccess] = useState("");
25  const [isLoading, setIsLoading] = useState(false);
26  const [isEmailSent, setIsEmailSent] = useState(false);
27
28  const handleRequestReset = async (e: React.FormEvent) => {
29    e.preventDefault();
30    setError("");
31    setSuccess("");
32    setIsLoading(true);
33
34    // Validate email
35    if (!email.trim()) {
36      setError("Please enter your email address");
37      setIsLoading(false);
38      return;
39    }
40
41    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
42    if (!emailRegex.test(email)) {
43      setError("Please enter a valid email address");
44      setIsLoading(false);
45      return;
46    }
47
48    // Simulate API call to send reset email
49    await new Promise((resolve) => setTimeout(resolve, 1500));
50
51    // In a real app with Supabase, you would:
52    // 1. Call Supabase auth.resetPasswordForEmail(email)
53    // 2. This sends a reset email with a token
54    // 3. User clicks link which redirects to /auth/reset-password
55
56    // For demo purposes, simulate success
57    setSuccess(`Password reset email sent to ${email}`);
58    setIsEmailSent(true);
59
60    // Store email in localStorage to simulate token passing
61    localStorage.setItem("passwordResetEmail", email);
62
63    setIsLoading(false);
64  };
65
66  return (
67    <div className="flex flex-col">
68      <main className="flex-1 flex items-center justify-center px-4 py-12">
69        <div className="w-full max-w-md">
70          <div className="text-center mb-8">
71            <h1 className="text-3xl font-bold mb-2">
72              {isEmailSent ? "Check your email" : "Reset your password"}
73            </h1>
74            <p className="text-muted-foreground">
75              {isEmailSent
76                ? "We sent you a password reset link"
77                : "Enter your email to receive reset instructions"}
78            </p>
79          </div>
80
81          <Card className="border shadow-sm">
82            <CardHeader className="space-y-1">
83              <CardTitle className="text-2xl">
84                {isEmailSent ? "Email sent" : "Forgot Password"}
85              </CardTitle>
86              <CardDescription>
87                {isEmailSent
88                  ? "Click the link in your email to reset your password"
89                  : "We'll send you a link to reset your password"}
90              </CardDescription>
91            </CardHeader>
92
93            <CardContent>
94              {!isEmailSent ? (
95                <form onSubmit={handleRequestReset} className="space-y-4">
96                  <div className="space-y-2">
97                    <Label htmlFor="email">Email address</Label>
98                    <div className="relative">
99                      <Mail className="absolute left-3 top-3 h-4 w-4 text-muted-foreground" />
100                      <Input
101                        id="email"
102                        type="email"
103                        placeholder="name@example.com"
104                        className="pl-10"
105                        value={email}
106                        onChange={(e) => setEmail(e.target.value)}
107                        disabled={isLoading}
108                        autoComplete="email"
109                      />
110                    </div>
111                  </div>
112
113                  {error && (
114                    <Alert variant="destructive">
115                      <AlertCircle className="h-4 w-4" />
116                      <AlertDescription>{error}</AlertDescription>
117                    </Alert>
118                  )}
119
120                  {success && (
121                    <Alert
122                      variant="default"
123                      className="bg-blue-50 border-blue-200"
124                    >
125                      <CheckCircle className="h-4 w-4 text-blue-600" />
126                      <AlertDescription className="text-blue-800">
127                        {success}
128                      </AlertDescription>
129                    </Alert>
130                  )}
131
132                  <Button type="submit" className="w-full" disabled={isLoading}>
133                    {isLoading ? (
134                      <>
135                        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
136                        Sending reset link...
137                      </>
138                    ) : (
139                      "Send Reset Link"
140                    )}
141                  </Button>
142                </form>
143              ) : (
144                <div className="space-y-6">
145                  <div className="text-center p-6 border rounded-lg bg-muted/30">
146                    <Mail className="h-12 w-12 mx-auto mb-4 text-primary" />
147                    <h3 className="font-semibold mb-2">Check your inbox</h3>
148                    <p className="text-sm text-muted-foreground mb-4">
149                      We've sent a password reset link to{" "}
150                      <strong>{email}</strong>. Click the link in the email to
151                      set a new password.
152                    </p>
153                  </div>
154
155                  <div className="space-y-3">
156                    <div className="text-sm text-muted-foreground">
157                      <p className="font-medium mb-1">
158                        Didn't receive the email?
159                      </p>
160                      <ul className="space-y-1">
161                        <li className="flex items-start gap-2">
162                          <div className="w-1 h-1 mt-2 rounded-full bg-muted-foreground" />
163                          Check your spam or junk folder
164                        </li>
165                        <li className="flex items-start gap-2">
166                          <div className="w-1 h-1 mt-2 rounded-full bg-muted-foreground" />
167                          Make sure you entered the correct email
168                        </li>
169                        <li className="flex items-start gap-2">
170                          <div className="w-1 h-1 mt-2 rounded-full bg-muted-foreground" />
171                          <Button
172                            type="button"
173                            variant="link"
174                            className="p-0 h-auto text-primary"
175                            onClick={handleRequestReset}
176                            disabled={isLoading}
177                          >
178                            Click here to resend
179                          </Button>
180                        </li>
181                      </ul>
182                    </div>
183                  </div>
184                </div>
185              )}
186            </CardContent>
187
188            <CardFooter className="flex flex-col space-y-3">
189              {!isEmailSent && (
190                <div className="text-center text-sm text-muted-foreground w-full">
191                  <div className="space-y-3">
192                    <div className="relative">
193                      <div className="absolute inset-0 flex items-center">
194                        <div className="w-full border-t"></div>
195                      </div>
196                      <div className="relative flex justify-center text-xs">
197                        <span className="bg-background px-2 text-muted-foreground">
198                          Remember your password?
199                        </span>
200                      </div>
201                    </div>
202
203                    <Link href="/signin">
204                      <Button
205                        type="button"
206                        variant="outline"
207                        className="w-full"
208                      >
209                        Back to Sign in
210                      </Button>
211                    </Link>
212                  </div>
213                </div>
214              )}
215            </CardFooter>
216          </Card>
217        </div>
218      </main>
219    </div>
220  );
221}