98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import { useState } from "react";
|
||
|
|
import { useRouter } from "next/navigation";
|
||
|
|
import { Loader2 } from "lucide-react";
|
||
|
|
import { toast } from "sonner";
|
||
|
|
import { Button } from "@/components/ui/button";
|
||
|
|
import { Input } from "@/components/ui/input";
|
||
|
|
import { Label } from "@/components/ui/label";
|
||
|
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||
|
|
import { authClient } from "@/lib/auth/auth-client";
|
||
|
|
|
||
|
|
export function SettingsClient({ name, email }: { name: string; email: string }) {
|
||
|
|
const router = useRouter();
|
||
|
|
const [displayName, setDisplayName] = useState(name);
|
||
|
|
const [savingProfile, setSavingProfile] = useState(false);
|
||
|
|
const [savingPw, setSavingPw] = useState(false);
|
||
|
|
|
||
|
|
async function saveProfile(e: React.FormEvent) {
|
||
|
|
e.preventDefault();
|
||
|
|
setSavingProfile(true);
|
||
|
|
const { error } = await authClient.updateUser({ name: displayName });
|
||
|
|
setSavingProfile(false);
|
||
|
|
if (error) toast.error(error.message ?? "Could not update");
|
||
|
|
else {
|
||
|
|
toast.success("Profile updated");
|
||
|
|
router.refresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function changePassword(e: React.FormEvent<HTMLFormElement>) {
|
||
|
|
e.preventDefault();
|
||
|
|
const form = new FormData(e.currentTarget);
|
||
|
|
setSavingPw(true);
|
||
|
|
const { error } = await authClient.changePassword({
|
||
|
|
currentPassword: String(form.get("current")),
|
||
|
|
newPassword: String(form.get("new")),
|
||
|
|
revokeOtherSessions: true,
|
||
|
|
});
|
||
|
|
setSavingPw(false);
|
||
|
|
if (error) toast.error(error.message ?? "Could not change password");
|
||
|
|
else {
|
||
|
|
toast.success("Password changed");
|
||
|
|
e.currentTarget.reset();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="max-w-xl space-y-6">
|
||
|
|
<Card>
|
||
|
|
<CardHeader>
|
||
|
|
<CardTitle>Profile</CardTitle>
|
||
|
|
<CardDescription>Update your name and see your email.</CardDescription>
|
||
|
|
</CardHeader>
|
||
|
|
<CardContent>
|
||
|
|
<form onSubmit={saveProfile} className="space-y-4">
|
||
|
|
<div className="space-y-2">
|
||
|
|
<Label htmlFor="name">Name</Label>
|
||
|
|
<Input id="name" value={displayName} onChange={(e) => setDisplayName(e.target.value)} />
|
||
|
|
</div>
|
||
|
|
<div className="space-y-2">
|
||
|
|
<Label>Email</Label>
|
||
|
|
<Input value={email} disabled />
|
||
|
|
</div>
|
||
|
|
<Button type="submit" disabled={savingProfile}>
|
||
|
|
{savingProfile && <Loader2 className="h-4 w-4 animate-spin" />}
|
||
|
|
Save profile
|
||
|
|
</Button>
|
||
|
|
</form>
|
||
|
|
</CardContent>
|
||
|
|
</Card>
|
||
|
|
|
||
|
|
<Card>
|
||
|
|
<CardHeader>
|
||
|
|
<CardTitle>Password</CardTitle>
|
||
|
|
<CardDescription>Change your account password.</CardDescription>
|
||
|
|
</CardHeader>
|
||
|
|
<CardContent>
|
||
|
|
<form onSubmit={changePassword} className="space-y-4">
|
||
|
|
<div className="space-y-2">
|
||
|
|
<Label htmlFor="current">Current password</Label>
|
||
|
|
<Input id="current" name="current" type="password" required />
|
||
|
|
</div>
|
||
|
|
<div className="space-y-2">
|
||
|
|
<Label htmlFor="new">New password</Label>
|
||
|
|
<Input id="new" name="new" type="password" minLength={8} required />
|
||
|
|
</div>
|
||
|
|
<Button type="submit" disabled={savingPw}>
|
||
|
|
{savingPw && <Loader2 className="h-4 w-4 animate-spin" />}
|
||
|
|
Change password
|
||
|
|
</Button>
|
||
|
|
</form>
|
||
|
|
</CardContent>
|
||
|
|
</Card>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|