Files
tech-tracker-next/src/components/default/profile/AvatarUpload.tsx

88 lines
2.6 KiB
TypeScript

import { useFileUpload } from '@/lib/hooks/useFileUpload';
import { useAuth } from '@/components/context';
import { BasedAvatar, CardContent } from '@/components/ui';
import { Loader2, Pencil, Upload } from 'lucide-react';
type AvatarUploadProps = {
onAvatarUploaded: (path: string) => Promise<void>;
};
export const AvatarUpload = ({ onAvatarUploaded }: AvatarUploadProps) => {
const { profile } = useAuth();
const { isUploading, fileInputRef, uploadToStorage } = useFileUpload();
const handleAvatarClick = () => {
fileInputRef.current?.click();
};
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const result = await uploadToStorage({
file,
bucket: 'avatars',
resize: true,
options: {
maxWidth: 500,
maxHeight: 500,
quality: 0.8,
},
replace: { replace: true, path: profile?.avatar_url ?? file.name },
});
if (result.success && result.data) {
await onAvatarUploaded(result.data);
}
};
return (
<CardContent>
<div className='flex flex-col items-center'>
<div
className='relative group cursor-pointer mb-4'
onClick={handleAvatarClick}
>
<BasedAvatar
src={profile?.avatar_url}
fullName={profile?.full_name}
className='h-32 w-32'
fallbackClassName='text-4xl font-semibold'
userIconSize={100}
/>
<div
className='absolute inset-0 rounded-full bg-black/0 group-hover:bg-black/50
transition-all flex items-center justify-center'
>
<Upload
className='text-white opacity-0 group-hover:opacity-100
transition-opacity'
size={24}
/>
</div>
<div className='absolute inset-1 transition-all flex items-end justify-end'>
<Pencil
className='text-white opacity-100 group-hover:opacity-0
transition-opacity'
size={24}
/>
</div>
</div>
<input
ref={fileInputRef}
type='file'
accept='image/*'
className='hidden'
onChange={handleFileChange}
disabled={isUploading}
/>
{isUploading && (
<div className='flex items-center text-sm text-gray-500 mt-2'>
<Loader2 className='h-4 w-4 mr-2 animate-spin' />
Uploading...
</div>
)}
</div>
</CardContent>
);
};