gbclient/app/settings/profile-form.tsx

117 lines
3.7 KiB
TypeScript
Raw Normal View History

"use client";
import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
const profileFormSchema = z.object({
username: z
.string()
.min(2, {
message: "Username must be at least 2 characters.",
})
.max(30, {
message: "Username must not be longer than 30 characters.",
}),
email: z
.string({
required_error: "Please select an email to display.",
})
.email(),
bio: z.string().max(160).min(4),
});
type ProfileFormValues = z.infer<typeof profileFormSchema>;
const defaultValues: Partial<ProfileFormValues> = {
bio: "I own a computer.",
};
export function ProfileForm() {
const { control, handleSubmit } = useForm<ProfileFormValues>({
resolver: zodResolver(profileFormSchema),
defaultValues,
});
const onSubmit = (data: ProfileFormValues) => {
console.log(JSON.stringify(data, null, 2));
};
return (
<div className="space-y-4">
<Controller
control={control}
name="username"
render={({ field: { onChange, onBlur, value }, fieldState: { error } }) => (
<div className="mb-4">
<label className="block text-sm font-medium mb-1">Username</label>
<input
className={`w-full p-2 border rounded ${error ? 'border-red-500' : 'border-gray-300'}`}
onBlur={onBlur}
onChange={(e) => onChange(e.target.value)}
value={value}
placeholder="Enter username"
/>
{error && <p className="text-red-500 text-xs mt-1">{error.message}</p>}
<p className="text-sm text-gray-500 mt-1">
This is your public display name. It can be your real name or a pseudonym. You can only change this once every 30 days.
</p>
</div>
)}
/>
<Controller
control={control}
name="email"
render={({ field: { onChange, onBlur, value }, fieldState: { error } }) => (
<div className="mb-4">
<label className="block text-sm font-medium mb-1">Email</label>
<input
className={`w-full p-2 border rounded ${error ? 'border-red-500' : 'border-gray-300'}`}
onBlur={onBlur}
onChange={(e) => onChange(e.target.value)}
value={value}
placeholder="Enter email"
type="email"
/>
{error && <p className="text-red-500 text-xs mt-1">{error.message}</p>}
<p className="text-sm text-gray-500 mt-1">
You can manage verified email addresses in your email settings.
</p>
</div>
)}
/>
<Controller
control={control}
name="bio"
render={({ field: { onChange, onBlur, value }, fieldState: { error } }) => (
<div className="mb-4">
<label className="block text-sm font-medium mb-1">Bio</label>
<textarea
className={`w-full p-2 border rounded ${error ? 'border-red-500' : 'border-gray-300'}`}
onBlur={onBlur}
onChange={(e) => onChange(e.target.value)}
value={value}
placeholder="Tell us a little bit about yourself"
rows={4}
/>
{error && <p className="text-red-500 text-xs mt-1">{error.message}</p>}
<p className="text-sm text-gray-500 mt-1">
You can @mention other users and organizations to link to them.
</p>
</div>
)}
/>
<button
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
onClick={handleSubmit(onSubmit)}
>
Update profile
</button>
</div>
);
}