Files
HKSingleParty/99_references/supabase-examples/user-management/nextjs-user-management/app/account/avatar.tsx
2025-05-28 09:55:51 +08:00

97 lines
2.4 KiB
TypeScript

'use client'
import React, { useEffect, useState } from 'react'
import { createClient } from '@/utils/supabase/client'
import Image from 'next/image'
export default function Avatar({
uid,
url,
size,
onUpload,
}: {
uid: string | null
url: string | null
size: number
onUpload: (url: string) => void
}) {
const supabase = createClient()
const [avatarUrl, setAvatarUrl] = useState<string | null>(url)
const [uploading, setUploading] = useState(false)
useEffect(() => {
async function downloadImage(path: string) {
try {
const { data, error } = await supabase.storage.from('avatars').download(path)
if (error) {
throw error
}
const url = URL.createObjectURL(data)
setAvatarUrl(url)
} catch (error) {
console.log('Error downloading image: ', error)
}
}
if (url) downloadImage(url)
}, [url, supabase])
const uploadAvatar: React.ChangeEventHandler<HTMLInputElement> = async (event) => {
try {
setUploading(true)
if (!event.target.files || event.target.files.length === 0) {
throw new Error('You must select an image to upload.')
}
const file = event.target.files[0]
const fileExt = file.name.split('.').pop()
const filePath = `${uid}-${Math.random()}.${fileExt}`
const { error: uploadError } = await supabase.storage.from('avatars').upload(filePath, file)
if (uploadError) {
throw uploadError
}
onUpload(filePath)
} catch (error) {
alert('Error uploading avatar!')
} finally {
setUploading(false)
}
}
return (
<div>
{avatarUrl ? (
<Image
width={size}
height={size}
src={avatarUrl}
alt="Avatar"
className="avatar image"
style={{ height: size, width: size }}
/>
) : (
<div className="avatar no-image" style={{ height: size, width: size }} />
)}
<div style={{ width: size }}>
<label className="button primary block" htmlFor="single">
{uploading ? 'Uploading ...' : 'Upload'}
</label>
<input
style={{
visibility: 'hidden',
position: 'absolute',
}}
type="file"
id="single"
accept="image/*"
onChange={uploadAvatar}
disabled={uploading}
/>
</div>
</div>
)
}