Updated Nav bar avatar to use hooks
This commit is contained in:
parent
408bb140ba
commit
259aa46ef8
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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}>
|
||||
|
@ -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
3
src/lib/hooks/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './useAvatar';
|
||||
export * from './useFileUpload';
|
||||
export * from './useProfile';
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user