Updated Nav bar avatar to use hooks

This commit is contained in:
Gabriel Brown 2025-05-20 16:11:41 -05:00
parent 408bb140ba
commit 259aa46ef8
6 changed files with 49 additions and 48 deletions

View File

@ -1,5 +1,5 @@
'use client';
import { useProfile } from '@/lib/hooks/useProfile';
import { useProfile } from '@/lib/hooks';
import { AvatarUpload, ProfileForm } from '@/components/default/profile';
import {
Card,

View File

@ -1,5 +1,6 @@
'use client';
import Link from 'next/link';
import { useState, useEffect } from 'react';
import {
Avatar,
@ -12,60 +13,41 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui';
import { getSignedUrl, getProfile, signOut } from '@/lib/actions';
import type { Profile } from '@/utils/supabase';
import Link from 'next/link';
import { useProfile, useAvatar } from '@/lib/hooks'
import { signOut } from '@/lib/actions';
import { User } from 'lucide-react';
const AvatarDropdown = () => {
const [profile, setProfile] = useState<Profile | undefined>(undefined);
const [signedUrl, setSignedUrl] = useState<string | undefined>(undefined);
const { profile } = useProfile();
const { avatarUrl, isLoading } = useAvatar(profile);
const handleSignOut = async () => {
await signOut();
};
useEffect(() => {
const handleGetProfile = async () => {
try {
const profileResponse = await getProfile();
if (!profileResponse.success)
throw new Error('Profile response unsuccessful');
setProfile(profileResponse.data);
} catch (error) {
console.error('Error getting profile:', error);
}
};
handleGetProfile().catch((error) => {
console.error('Error getting profile:', error);
})
}, []);
useEffect(() => {
const handleGetSignedUrl = async () => {
try {
const response = await getSignedUrl({
bucket: 'avatars',
url: profile?.avatar_url ?? '',
});
if (response.success) {
setSignedUrl(response.data);
}
} catch (error) {
console.error('Error getting signed URL:', error);
}
};
handleGetSignedUrl().catch((error) => {
console.error('Error getting signed URL:', error);
});
}, [profile]);
if (isLoading) {
return (
<Avatar>
<AvatarFallback className='animate-pulse'>
<User size={32} />
</AvatarFallback>
</Avatar>
);
}
return (
<DropdownMenu>
<DropdownMenuTrigger>
<Avatar>
<AvatarImage src={signedUrl ?? '/favicon.ico'} />
<AvatarFallback>AN</AvatarFallback>
<Avatar className='cursor-pointer'>
{avatarUrl ? (
<AvatarImage src={avatarUrl} />
) : (
<AvatarFallback className="text-2xl">
{profile?.full_name
? profile.full_name.split(' ').map(n => n[0]).join('').toUpperCase()
: <User size={32} />}
</AvatarFallback>
)}
</Avatar>
</DropdownMenuTrigger>
<DropdownMenuContent>

View File

@ -10,7 +10,7 @@ type AvatarUploadProps = {
};
export const AvatarUpload = ({ profile, onAvatarUploaded }: AvatarUploadProps) => {
const { avatarUrl } = useAvatar(profile);
const { avatarUrl, isLoading } = useAvatar(profile);
const { isUploading, fileInputRef, uploadToStorage } = useFileUpload();
const handleAvatarClick = () => {
@ -27,6 +27,22 @@ export const AvatarUpload = ({ profile, onAvatarUploaded }: AvatarUploadProps) =
}
};
if (isLoading) {
return (
<div className="flex flex-col items-center">
<div className="relative group cursor-pointer mb-4">
<Avatar>
<AvatarFallback className="text-2xl">
{profile?.full_name
? profile.full_name.split(' ').map(n => n[0]).join('').toUpperCase()
: <User size={32} />}
</AvatarFallback>
</Avatar>
</div>
</div>
);
}
return (
<div className="flex flex-col items-center">
<div className="relative group cursor-pointer mb-4" onClick={handleAvatarClick}>

View File

@ -92,7 +92,7 @@ export function ProfileForm({ profile, isLoading, onSubmit }: ProfileFormProps)
)}
/>
<div className="flex justify-end">
<div className="flex justify-center">
<Button type='submit' disabled={isLoading}>
{isLoading ? (
<>

3
src/lib/hooks/index.ts Normal file
View File

@ -0,0 +1,3 @@
export * from './useAvatar';
export * from './useFileUpload';
export * from './useProfile';

View File

@ -3,7 +3,7 @@ import { getProfile, updateProfile } from '@/lib/actions';
import type { Profile } from '@/utils/supabase';
import { toast } from 'sonner';
export function useProfile() {
export const useProfile = () => {
const [profile, setProfile] = useState<Profile | undefined>(undefined);
const [isLoading, setIsLoading] = useState(true);
@ -15,7 +15,7 @@ export function useProfile() {
if (!profileResponse.success)
throw new Error('Profile response unsuccessful');
setProfile(profileResponse.data);
} catch (error) {
} catch {
setProfile(undefined);
} finally {
setIsLoading(false);