108 lines
5.5 KiB
TypeScript
108 lines
5.5 KiB
TypeScript
"use client";
|
|
|
|
import { useRef, useState, type FormEvent } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { KeyRoundIcon } from "lucide-react";
|
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
|
|
import { Input } from "@/components/ui/input";
|
|
import { authClient } from "@/lib/auth/client";
|
|
|
|
export function PasswordForm({ hasPassword: initialHasPassword }: { hasPassword: boolean }) {
|
|
const router = useRouter();
|
|
const formRef = useRef<HTMLFormElement>(null);
|
|
const [hasPassword, setHasPassword] = useState(initialHasPassword);
|
|
const [busy, setBusy] = useState(false);
|
|
const [error, setError] = useState("");
|
|
const [success, setSuccess] = useState("");
|
|
|
|
async function changePassword(event: FormEvent<HTMLFormElement>) {
|
|
event.preventDefault();
|
|
if (busy) return;
|
|
const form = new FormData(event.currentTarget);
|
|
const currentPassword = String(form.get("currentPassword") ?? "");
|
|
const newPassword = String(form.get("newPassword") ?? "");
|
|
const confirmPassword = String(form.get("confirmPassword") ?? "");
|
|
setError("");
|
|
setSuccess("");
|
|
if (newPassword !== confirmPassword) {
|
|
setError(hasPassword ? "รหัสผ่านใหม่ไม่ตรงกัน" : "รหัสผ่านไม่ตรงกัน");
|
|
return;
|
|
}
|
|
setBusy(true);
|
|
try {
|
|
if (hasPassword) {
|
|
const result = await authClient.changePassword({ currentPassword, newPassword });
|
|
if (result.error) {
|
|
setError(result.error.code === "INVALID_PASSWORD"
|
|
? "รหัสผ่านปัจจุบันไม่ถูกต้อง"
|
|
: "เปลี่ยนรหัสผ่านไม่สำเร็จ กรุณาลองอีกครั้ง");
|
|
return;
|
|
}
|
|
} else {
|
|
const response = await fetch("/api/profile/password", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ newPassword }),
|
|
});
|
|
if (!response.ok) {
|
|
setError("เพิ่มรหัสผ่านไม่สำเร็จ กรุณาลองอีกครั้ง");
|
|
return;
|
|
}
|
|
setHasPassword(true);
|
|
router.refresh();
|
|
}
|
|
formRef.current?.reset();
|
|
setSuccess(hasPassword ? "เปลี่ยนรหัสผ่านเรียบร้อยแล้ว" : "เพิ่มรหัสผ่านเรียบร้อยแล้ว");
|
|
} catch {
|
|
setError(hasPassword ? "เปลี่ยนรหัสผ่านไม่สำเร็จ กรุณาลองอีกครั้ง" : "เพิ่มรหัสผ่านไม่สำเร็จ กรุณาลองอีกครั้ง");
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}
|
|
|
|
return <Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<KeyRoundIcon aria-hidden="true" className="size-4 shrink-0" />
|
|
{hasPassword ? "เปลี่ยนรหัสผ่าน" : "เพิ่มรหัสผ่าน"}
|
|
</CardTitle>
|
|
<CardDescription>{hasPassword
|
|
? "กรอกรหัสผ่านปัจจุบันและรหัสผ่านใหม่"
|
|
: "บัญชีนี้ยังไม่มีรหัสผ่าน เพิ่มรหัสผ่านเพื่อเข้าสู่ระบบด้วยอีเมลได้ด้วย"}</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<form id="password-form" ref={formRef} onSubmit={changePassword}>
|
|
<FieldGroup>
|
|
{hasPassword && <Field>
|
|
<FieldLabel htmlFor="current-password">รหัสผ่านปัจจุบัน</FieldLabel>
|
|
<Input id="current-password" name="currentPassword" type="password"
|
|
autoComplete="current-password" required disabled={busy} />
|
|
</Field>}
|
|
<Field>
|
|
<FieldLabel htmlFor="new-password">{hasPassword ? "รหัสผ่านใหม่" : "รหัสผ่าน"}</FieldLabel>
|
|
<Input id="new-password" name="newPassword" type="password"
|
|
autoComplete="new-password" minLength={6} maxLength={128} required disabled={busy} />
|
|
</Field>
|
|
<Field>
|
|
<FieldLabel htmlFor="confirm-password">{hasPassword ? "ยืนยันรหัสผ่านใหม่" : "ยืนยันรหัสผ่าน"}</FieldLabel>
|
|
<Input id="confirm-password" name="confirmPassword" type="password"
|
|
autoComplete="new-password" minLength={6} maxLength={128} required disabled={busy} />
|
|
</Field>
|
|
{error && <Alert variant="destructive"><AlertDescription>{error}</AlertDescription></Alert>}
|
|
{success && <Alert role="status"><AlertDescription>{success}</AlertDescription></Alert>}
|
|
</FieldGroup>
|
|
</form>
|
|
</CardContent>
|
|
<CardFooter>
|
|
<Button type="submit" form="password-form" disabled={busy}>
|
|
{busy
|
|
? hasPassword ? "กำลังเปลี่ยนรหัสผ่าน..." : "กำลังเพิ่มรหัสผ่าน..."
|
|
: hasPassword ? "เปลี่ยนรหัสผ่าน" : "เพิ่มรหัสผ่าน"}
|
|
</Button>
|
|
</CardFooter>
|
|
</Card>;
|
|
}
|