96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { changePassword } from "./actions";
|
|
|
|
export function ChangePasswordForm() {
|
|
const [success, setSuccess] = useState(false);
|
|
const [error, setError] = useState("");
|
|
const [pending, setPending] = useState(false);
|
|
|
|
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
|
e.preventDefault();
|
|
const form = e.currentTarget;
|
|
const fd = new FormData(form);
|
|
|
|
const newPw = fd.get("newPassword") as string;
|
|
const confirmPw = fd.get("confirmPassword") as string;
|
|
if (newPw !== confirmPw) {
|
|
setError("New passwords do not match");
|
|
return;
|
|
}
|
|
|
|
setPending(true);
|
|
setSuccess(false);
|
|
setError("");
|
|
const result = await changePassword(fd);
|
|
setPending(false);
|
|
|
|
if ("error" in result) {
|
|
setError(result.error);
|
|
} else {
|
|
setSuccess(true);
|
|
form.reset();
|
|
}
|
|
}
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
<div>
|
|
<label className="block text-sm font-medium text-neutral-700 mb-1.5">
|
|
Current password
|
|
</label>
|
|
<input
|
|
type="password"
|
|
name="currentPassword"
|
|
required
|
|
autoComplete="current-password"
|
|
className="w-full rounded-lg border border-neutral-300 px-3 py-2.5 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-neutral-700 mb-1.5">
|
|
New password
|
|
</label>
|
|
<input
|
|
type="password"
|
|
name="newPassword"
|
|
required
|
|
minLength={8}
|
|
autoComplete="new-password"
|
|
className="w-full rounded-lg border border-neutral-300 px-3 py-2.5 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-neutral-700 mb-1.5">
|
|
Confirm new password
|
|
</label>
|
|
<input
|
|
type="password"
|
|
name="confirmPassword"
|
|
required
|
|
minLength={8}
|
|
autoComplete="new-password"
|
|
className="w-full rounded-lg border border-neutral-300 px-3 py-2.5 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"
|
|
/>
|
|
</div>
|
|
|
|
{error && (
|
|
<p className="text-sm text-danger-700 bg-danger-50 rounded-lg px-3 py-2">{error}</p>
|
|
)}
|
|
{success && (
|
|
<p className="text-sm text-success-700 bg-success-50 rounded-lg px-3 py-2">
|
|
Password changed successfully.
|
|
</p>
|
|
)}
|
|
|
|
<button
|
|
type="submit"
|
|
disabled={pending}
|
|
className="rounded-lg bg-primary-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-primary-700 disabled:opacity-60 transition-colors"
|
|
>
|
|
{pending ? "Saving…" : "Change Password"}
|
|
</button>
|
|
</form>
|
|
);
|
|
}
|