import { useRef, useState } from 'react'; import { toast } from 'sonner'; import { Camera } from 'lucide-react'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; import { useForm } from 'hooks/useForm'; import { useAuth } from 'hooks/useAuth'; type ProfileFormState = { name?: string; }; const MAX_AVATAR_SIZE = 384_000; // ~384KB to stay under 512KB varchar after base64 overhead const readFileAsBase64 = (file: File): Promise => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result as string); reader.onerror = reject; reader.readAsDataURL(file); }); }; export const UserData = () => { const { user, updateUser } = useAuth(); const [isUpdating, setIsUpdating] = useState(false); const [avatarPreview, setAvatarPreview] = useState(null); const fileInputRef = useRef(null); const profileForm = useForm({ name: user?.name ?? '' }); const handleAvatarChange = async (ev: React.ChangeEvent) => { const file = ev.target.files?.[0]; if (!file) return; if (!file.type.startsWith('image/')) { toast.error('Please select an image file'); return; } if (file.size > MAX_AVATAR_SIZE) { toast.error('Image must be smaller than 384KB'); return; } const base64 = await readFileAsBase64(file); setAvatarPreview(base64); }; const handleSubmit = async (ev: React.FormEvent) => { ev.preventDefault(); if (isUpdating) return; setIsUpdating(true); try { await updateUser({ name: profileForm.state.name ?? '', avatar: avatarPreview ?? user?.avatar ?? '', }); toast.success('Profile updated'); setAvatarPreview(null); } catch (ex) { const error = ex as { message?: string }; toast.error(error.message || 'Failed to update profile'); } finally { setIsUpdating(false); } }; const displayAvatar = avatarPreview ?? user?.avatar ?? undefined; return (
); };