diff --git a/app/auth/reset-password/page.tsx b/app/auth/reset-password/page.tsx new file mode 100644 index 0000000..558e68a --- /dev/null +++ b/app/auth/reset-password/page.tsx @@ -0,0 +1,157 @@ +"use client"; +import { useState, useEffect } from "react"; +import { useRouter, useSearchParams } from "next/navigation"; +import { fetchClient } from "@/lib/api-client"; +import { toast } from "sonner"; + +interface Vendor { + id: string; + username: string; +} + +export default function ResetPasswordPage() { + const router = useRouter(); + const searchParams = useSearchParams(); + const token = searchParams.get('token'); + + const [vendor, setVendor] = useState(null); + const [loading, setLoading] = useState(true); + const [submitting, setSubmitting] = useState(false); + const [password, setPassword] = useState(""); + const [confirmPassword, setConfirmPassword] = useState(""); + + useEffect(() => { + if (!token) { + toast.error("No reset token provided"); + router.push("/auth/login"); + return; + } + + validateToken(); + }, [token]); + + async function validateToken() { + try { + const data = await fetchClient<{ valid: boolean; vendor?: Vendor; message?: string }>(`/auth/validate-reset-token/${token}`); + + if (data.valid && data.vendor) { + setVendor(data.vendor); + } else { + toast.error(data.message || "Invalid or expired token"); + router.push("/auth/login"); + } + } catch (error: any) { + toast.error("Failed to validate token"); + router.push("/auth/login"); + } finally { + setLoading(false); + } + } + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + + if (password !== confirmPassword) { + toast.error("Passwords do not match"); + return; + } + + if (password.length < 6) { + toast.error("Password must be at least 6 characters"); + return; + } + + setSubmitting(true); + + try { + await fetchClient("/auth/reset-password", { + method: "POST", + body: { token, newPassword: password } + }); + + toast.success("Password reset successfully"); + router.push("/auth/login"); + } catch (error: any) { + toast.error(error?.message || "Failed to reset password"); + } finally { + setSubmitting(false); + } + } + + if (loading) { + return ( +
+
+
+

Validating token...

+
+
+ ); + } + + if (!vendor) { + return null; // Will redirect + } + + return ( +
+
+
+

Reset Password

+

+ Reset password for {vendor.username} +

+
+ +
+
+ + setPassword(e.target.value)} + className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm" + placeholder="Enter new password" + /> +
+ +
+ + setConfirmPassword(e.target.value)} + className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm" + placeholder="Confirm new password" + /> +
+ + +
+ +
+ + Back to Login + +
+
+
+ ); +} diff --git a/components/admin/VendorsCard.tsx b/components/admin/VendorsCard.tsx index dba015a..6160dc0 100644 --- a/components/admin/VendorsCard.tsx +++ b/components/admin/VendorsCard.tsx @@ -5,7 +5,6 @@ import { fetchClient } from "@/lib/api-client"; interface Vendor { _id: string; username: string; - email?: string; isAdmin: boolean; createdAt: string; lastLogin?: string; @@ -63,7 +62,6 @@ export default function VendorsCard() {
{vendor.username}
- {vendor.email && `${vendor.email} · `} Created: {new Date(vendor.createdAt).toLocaleDateString()} {vendor.lastLogin && ` · Last login: ${new Date(vendor.lastLogin).toLocaleDateString()}`}