Compare commits
2 Commits
e8301c22cb
...
eecffff110
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eecffff110 | ||
|
|
62017ea236 |
75
app/(auth)/forgot-password/page.tsx
Normal file
75
app/(auth)/forgot-password/page.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import ComponentsAuthForgotForm from '@/components/auth/components-auth-forgot-form';
|
||||
import IconFacebookCircle from '@/components/icon/icon-facebook-circle';
|
||||
import IconGoogle from '@/components/icon/icon-google';
|
||||
import IconInstagram from '@/components/icon/icon-instagram';
|
||||
import IconTwitter from '@/components/icon/icon-twitter';
|
||||
import { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import React from 'react';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Forgot Password',
|
||||
};
|
||||
|
||||
export default function CoverForgotPassword() {
|
||||
return (
|
||||
<div>
|
||||
<div className="absolute inset-0">
|
||||
<img src="/assets/images/auth/bg-gradient.png" alt="image" className="h-full w-full object-cover" />
|
||||
</div>
|
||||
<div className="relative flex min-h-screen items-center justify-center bg-[url(/assets/images/auth/bg.webp)] bg-cover bg-center bg-no-repeat px-6 py-10 dark:bg-[#060818] sm:px-16">
|
||||
<img src="/assets/images/auth/left.webp" alt="image" className="absolute left-0 top-1/2 h-full max-h-[893px] -translate-y-1/2" />
|
||||
<img src="/assets/images/auth/top.webp" alt="image" className="absolute left-24 top-0 h-40 md:left-[30%]" />
|
||||
<img src="/assets/images/auth/top-right.webp" alt="image" className="absolute right-0 top-0 h-[300px]" />
|
||||
<img src="/assets/images/auth/bottom.webp" alt="image" className="absolute bottom-0 end-[28%]" />
|
||||
<div className="relative flex w-full max-w-[1502px] flex-col justify-between overflow-hidden rounded-md bg-white/60 backdrop-blur-lg dark:bg-black/50 lg:min-h-[758px] lg:flex-row lg:gap-10 xl:gap-0">
|
||||
<div className="relative hidden w-full items-center justify-center bg-[linear-gradient(225deg,#333333_35%,#325aa9_100%)] p-5 lg:inline-flex lg:max-w-[835px] xl:-ms-28 ltr:xl:skew-x-[14deg] rtl:xl:skew-x-[-14deg]">
|
||||
<div className="absolute inset-y-0 w-8 from-primary/10 via-transparent to-transparent ltr:-right-10 ltr:bg-gradient-to-r rtl:-left-10 rtl:bg-gradient-to-l xl:w-16 ltr:xl:-right-20 rtl:xl:-left-20"></div>
|
||||
<div className="ltr:xl:-skew-x-[14deg] rtl:xl:skew-x-[14deg]">
|
||||
<Link href="/" className="ms-10 block w-48 lg:w-72">
|
||||
<img src="/assets/images/white-logo.png" alt="Logo" className="w-full" />
|
||||
</Link>
|
||||
<div className="mt-24 hidden w-full max-w-[430px] lg:block">
|
||||
<img src="/assets/images/auth/register.svg" alt="Cover Image" className="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right side form */}
|
||||
<div className="relative flex w-full flex-col items-center justify-center gap-6 px-4 pb-16 pt-6 sm:px-6 lg:max-w-[667px]">
|
||||
<div className="flex w-full max-w-[440px] items-center gap-2 lg:absolute lg:end-6 lg:top-6 lg:max-w-full">
|
||||
<Link href="/" className="block w-8 lg:hidden">
|
||||
<img src="/assets/images/logo.svg" alt="Logo" className="mx-auto w-10" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="w-full max-w-[440px] lg:mt-16">
|
||||
<div className="mb-10">
|
||||
<h1 className="text-3xl font-extrabold uppercase !leading-snug text-primary md:text-4xl">
|
||||
Forgot Password
|
||||
</h1>
|
||||
<p className="text-base font-bold leading-normal text-white-dark">
|
||||
Enter your email to receive the reset link
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* forgot form */}
|
||||
<ComponentsAuthForgotForm />
|
||||
|
||||
<div className="text-center mt-8 dark:text-white">
|
||||
Remember your password?
|
||||
<Link href="/login" className="uppercase text-primary underline transition hover:text-black dark:hover:text-white">
|
||||
SIGN IN
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="absolute bottom-6 w-full text-center dark:text-white">
|
||||
© {new Date().getFullYear()}. Metatroncube All Rights Reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
76
app/(auth)/reset-password/page.tsx
Normal file
76
app/(auth)/reset-password/page.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import ComponentsAuthForgotForm from '@/components/auth/components-auth-forgot-form';
|
||||
import ResetPasswordForm from '@/components/auth/components-auth-reset-form';
|
||||
import IconFacebookCircle from '@/components/icon/icon-facebook-circle';
|
||||
import IconGoogle from '@/components/icon/icon-google';
|
||||
import IconInstagram from '@/components/icon/icon-instagram';
|
||||
import IconTwitter from '@/components/icon/icon-twitter';
|
||||
import { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import React from 'react';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Reset Password',
|
||||
};
|
||||
|
||||
export default function CoverForgotPassword() {
|
||||
return (
|
||||
<div>
|
||||
<div className="absolute inset-0">
|
||||
<img src="/assets/images/auth/bg-gradient.png" alt="image" className="h-full w-full object-cover" />
|
||||
</div>
|
||||
<div className="relative flex min-h-screen items-center justify-center bg-[url(/assets/images/auth/bg.webp)] bg-cover bg-center bg-no-repeat px-6 py-10 dark:bg-[#060818] sm:px-16">
|
||||
<img src="/assets/images/auth/left.webp" alt="image" className="absolute left-0 top-1/2 h-full max-h-[893px] -translate-y-1/2" />
|
||||
<img src="/assets/images/auth/top.webp" alt="image" className="absolute left-24 top-0 h-40 md:left-[30%]" />
|
||||
<img src="/assets/images/auth/top-right.webp" alt="image" className="absolute right-0 top-0 h-[300px]" />
|
||||
<img src="/assets/images/auth/bottom.webp" alt="image" className="absolute bottom-0 end-[28%]" />
|
||||
<div className="relative flex w-full max-w-[1502px] flex-col justify-between overflow-hidden rounded-md bg-white/60 backdrop-blur-lg dark:bg-black/50 lg:min-h-[758px] lg:flex-row lg:gap-10 xl:gap-0">
|
||||
<div className="relative hidden w-full items-center justify-center bg-[linear-gradient(225deg,#333333_35%,#325aa9_100%)] p-5 lg:inline-flex lg:max-w-[835px] xl:-ms-28 ltr:xl:skew-x-[14deg] rtl:xl:skew-x-[-14deg]">
|
||||
<div className="absolute inset-y-0 w-8 from-primary/10 via-transparent to-transparent ltr:-right-10 ltr:bg-gradient-to-r rtl:-left-10 rtl:bg-gradient-to-l xl:w-16 ltr:xl:-right-20 rtl:xl:-left-20"></div>
|
||||
<div className="ltr:xl:-skew-x-[14deg] rtl:xl:skew-x-[14deg]">
|
||||
<Link href="/" className="ms-10 block w-48 lg:w-72">
|
||||
<img src="/assets/images/white-logo.png" alt="Logo" className="w-full" />
|
||||
</Link>
|
||||
<div className="mt-24 hidden w-full max-w-[430px] lg:block">
|
||||
<img src="/assets/images/auth/register.svg" alt="Cover Image" className="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right side form */}
|
||||
<div className="relative flex w-full flex-col items-center justify-center gap-6 px-4 pb-16 pt-6 sm:px-6 lg:max-w-[667px]">
|
||||
<div className="flex w-full max-w-[440px] items-center gap-2 lg:absolute lg:end-6 lg:top-6 lg:max-w-full">
|
||||
<Link href="/" className="block w-8 lg:hidden">
|
||||
<img src="/assets/images/logo.svg" alt="Logo" className="mx-auto w-10" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="w-full max-w-[440px] lg:mt-16">
|
||||
<div className="mb-10">
|
||||
<h1 className="text-3xl font-extrabold uppercase !leading-snug text-primary md:text-4xl">
|
||||
Reset Password
|
||||
</h1>
|
||||
<p className="text-base font-bold leading-normal text-white-dark">
|
||||
Enter the verification code you received and set your new password
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* forgot form */}
|
||||
<ResetPasswordForm />
|
||||
|
||||
<div className="text-center mt-8 dark:text-white">
|
||||
Remember your password?
|
||||
<Link href="/login" className="uppercase text-primary underline transition hover:text-black dark:hover:text-white">
|
||||
SIGN IN
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="absolute bottom-6 w-full text-center dark:text-white">
|
||||
© {new Date().getFullYear()}. Metatroncube All Rights Reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
51
components/auth/components-auth-forgot-form.tsx
Normal file
51
components/auth/components-auth-forgot-form.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import axios from "axios";
|
||||
|
||||
export default function ForgotPasswordForm() {
|
||||
const [email, setEmail] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [message, setMessage] = useState("");
|
||||
|
||||
const handleForgot = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
setMessage("");
|
||||
try {
|
||||
const res = await axios.post("http://localhost:3020/api/auth/forgot-password", { email });
|
||||
setMessage("✅ We’ve emailed you a reset code / link. Enter it below.");
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
setMessage("Something went wrong. Try again.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleForgot} className="space-y-5">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-white-dark mb-1">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="form-input w-full rounded-md border-white-light bg-transparent text-black dark:text-white"
|
||||
placeholder="you@example.com"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="btn btn-primary w-full uppercase font-bold"
|
||||
>
|
||||
{loading ? "Sending..." : "Send Reset Link"}
|
||||
</button>
|
||||
{message && <p className="mt-2 text-center text-sm font-semibold text-primary">{message}</p>}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
68
components/auth/components-auth-reset-form.tsx
Normal file
68
components/auth/components-auth-reset-form.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import axios from "axios";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
export default function ResetPasswordForm() {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
// ✅ token and email are read from the URL: /reset-password?email=...&token=...
|
||||
const email = searchParams.get("email") || "";
|
||||
const token = searchParams.get("token") || "";
|
||||
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [message, setMessage] = useState("");
|
||||
|
||||
const handleReset = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
setMessage("");
|
||||
try {
|
||||
await axios.post("http://localhost:3020/api/auth/reset-password", {
|
||||
email,
|
||||
token, // ✅ use token from URL
|
||||
newPassword,
|
||||
});
|
||||
setMessage("✅ Your password has been successfully reset.");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setMessage("❌ Reset failed. Check the link or try again.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleReset} className="space-y-5">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-white-dark mb-1">
|
||||
New Password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
required
|
||||
value={newPassword}
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
className="form-input w-full rounded-md border-white-light bg-transparent text-black dark:text-white"
|
||||
placeholder="********"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="btn btn-primary w-full uppercase font-bold"
|
||||
>
|
||||
{loading ? "Resetting..." : "Reset Password"}
|
||||
</button>
|
||||
|
||||
{message && (
|
||||
<p className="mt-2 text-center text-sm font-semibold text-primary">
|
||||
{message}
|
||||
</p>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 38 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 6.0 KiB |
Loading…
x
Reference in New Issue
Block a user