import { useEffect } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { updateProfileSchema, type UpdateProfileInput, type Profile, } from '@family-wishlist/shared'; import { toast } from 'sonner'; import { Loader2 } from 'lucide-react'; import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { Label } from '@/components/ui/Label'; import { Textarea } from '@/components/ui/Textarea'; import { api, ApiError } from '@/lib/api'; import { useAuthStore } from '@/features/auth/authStore'; export function ProfileSettingsPage() { const refresh = useAuthStore((s) => s.refresh); const queryClient = useQueryClient(); const { data, isLoading } = useQuery({ queryKey: ['profile'], queryFn: () => api.get('/api/profile'), }); const { register, handleSubmit, reset, formState: { errors, isSubmitting, isDirty }, } = useForm({ resolver: zodResolver(updateProfileSchema), defaultValues: { slug: '', displayName: '', bio: '', avatarUrl: '' }, }); useEffect(() => { if (data) { reset({ slug: data.slug, displayName: data.displayName, bio: data.bio ?? '', avatarUrl: data.avatarUrl ?? '', }); } }, [data, reset]); const update = useMutation({ mutationFn: (values: UpdateProfileInput) => api.patch('/api/profile', values), onSuccess: (p) => { toast.success('Profile saved'); void queryClient.invalidateQueries({ queryKey: ['profile'] }); void refresh(); reset({ slug: p.slug, displayName: p.displayName, bio: p.bio ?? '', avatarUrl: p.avatarUrl ?? '', }); }, onError: (err) => { if (err instanceof ApiError) toast.error(err.message); else toast.error('Save failed'); }, }); const submit = handleSubmit((values) => { const payload: UpdateProfileInput = { ...values, bio: values.bio ? values.bio : null, avatarUrl: values.avatarUrl ? values.avatarUrl : null, }; update.mutate(payload); }); return (

Profile

Your public page lives at /u/{data?.slug ?? '...'}.

{isLoading ? (
Loading...
) : (
{errors.slug && {errors.slug.message}}
{errors.displayName && ( {errors.displayName.message} )}