Files
neta/app/(dashboard)/settings/profile/profile-settings-form.tsx
T

133 lines
4.4 KiB
TypeScript

"use client";
import Image from "next/image";
import { useState, useTransition } from "react";
import { Save, User } from "lucide-react";
import { Button, Card, CardContent, Input, Label } from "poyraz-ui/atoms";
import { toast } from "poyraz-ui/molecules";
import { useTranslations } from "@/components/i18n/i18n-provider";
import { updateProfileAction } from "./actions";
export function ProfileSettingsForm({
initial,
}: {
initial: {
avatarUrl: string;
email: string;
firstName: string;
lastName: string;
};
}) {
const t = useTranslations();
const [pending, startTransition] = useTransition();
const [firstName, setFirstName] = useState(initial.firstName);
const [lastName, setLastName] = useState(initial.lastName);
function submit(formData: FormData) {
startTransition(async () => {
const result = await updateProfileAction(formData);
if (result.errorKey) {
toast.error(t(result.errorKey));
return;
}
toast.success(t("settings.profile.messages.saved"));
if (result.avatarChanged) {
window.location.reload();
}
});
}
return (
<Card>
<CardContent className="space-y-8 p-6 sm:p-8">
<div className="space-y-1.5">
<h2 className="text-xl font-semibold text-foreground">
{t("settings.profile.title")}
</h2>
<p className="max-w-2xl text-sm text-muted-foreground">
{t("settings.profile.description")}
</p>
</div>
<form action={submit} className="max-w-2xl space-y-7">
<section className="flex flex-col gap-5 sm:flex-row sm:items-center">
{initial.avatarUrl ? (
<Image
src={initial.avatarUrl}
alt={t("settings.profile.avatarAlt")}
width={80}
height={80}
unoptimized
className="h-20 w-20 rounded-full border border-border object-cover"
/>
) : (
<div className="flex h-20 w-20 shrink-0 items-center justify-center rounded-full border border-border bg-muted/50">
<User className="h-9 w-9 text-muted-foreground" aria-hidden="true" />
</div>
)}
<div className="flex-1 space-y-2">
<Label htmlFor="avatar">{t("settings.profile.fields.avatar")}</Label>
<Input
id="avatar"
name="avatar"
type="file"
accept="image/png,image/jpeg,image/webp,image/gif"
className="cursor-pointer"
/>
<p className="text-xs text-muted-foreground">
{t("settings.profile.help.avatar")}
</p>
</div>
</section>
<section className="grid gap-5 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="firstName">{t("settings.profile.fields.firstName")}</Label>
<Input
id="firstName"
name="firstName"
value={firstName}
onChange={(event) => setFirstName(event.target.value)}
maxLength={80}
required
/>
</div>
<div className="space-y-2">
<Label htmlFor="lastName">{t("settings.profile.fields.lastName")}</Label>
<Input
id="lastName"
name="lastName"
value={lastName}
onChange={(event) => setLastName(event.target.value)}
maxLength={120}
required
/>
</div>
</section>
<div className="space-y-2">
<Label htmlFor="profile-email">{t("settings.profile.fields.email")}</Label>
<Input id="profile-email" value={initial.email} disabled readOnly />
<p className="text-xs text-muted-foreground">
{t("settings.profile.help.email")}
</p>
</div>
<div className="flex justify-end border-t border-border pt-6">
<Button
type="submit"
variant="default"
effect="shine"
loading={pending}
className="gap-2"
>
<Save className="h-4 w-4" aria-hidden="true" />
{t("settings.profile.actions.save")}
</Button>
</div>
</form>
</CardContent>
</Card>
);
}