Updated Nav bar avatar to use hooks
This commit is contained in:
parent
408bb140ba
commit
259aa46ef8
@ -1,5 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { useProfile } from '@/lib/hooks/useProfile';
|
import { useProfile } from '@/lib/hooks';
|
||||||
import { AvatarUpload, ProfileForm } from '@/components/default/profile';
|
import { AvatarUpload, ProfileForm } from '@/components/default/profile';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
@ -12,60 +13,41 @@ import {
|
|||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui';
|
} from '@/components/ui';
|
||||||
import { getSignedUrl, getProfile, signOut } from '@/lib/actions';
|
import { useProfile, useAvatar } from '@/lib/hooks'
|
||||||
|
import { signOut } from '@/lib/actions';
|
||||||
import type { Profile } from '@/utils/supabase';
|
import { User } from 'lucide-react';
|
||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
const AvatarDropdown = () => {
|
const AvatarDropdown = () => {
|
||||||
const [profile, setProfile] = useState<Profile | undefined>(undefined);
|
const { profile } = useProfile();
|
||||||
const [signedUrl, setSignedUrl] = useState<string | undefined>(undefined);
|
const { avatarUrl, isLoading } = useAvatar(profile);
|
||||||
|
|
||||||
const handleSignOut = async () => {
|
const handleSignOut = async () => {
|
||||||
await signOut();
|
await signOut();
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
if (isLoading) {
|
||||||
const handleGetProfile = async () => {
|
return (
|
||||||
try {
|
<Avatar>
|
||||||
const profileResponse = await getProfile();
|
<AvatarFallback className='animate-pulse'>
|
||||||
if (!profileResponse.success)
|
<User size={32} />
|
||||||
throw new Error('Profile response unsuccessful');
|
</AvatarFallback>
|
||||||
setProfile(profileResponse.data);
|
</Avatar>
|
||||||
} 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]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger>
|
<DropdownMenuTrigger>
|
||||||
<Avatar>
|
<Avatar className='cursor-pointer'>
|
||||||
<AvatarImage src={signedUrl ?? '/favicon.ico'} />
|
{avatarUrl ? (
|
||||||
<AvatarFallback>AN</AvatarFallback>
|
<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>
|
</Avatar>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
|
@ -10,7 +10,7 @@ type AvatarUploadProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const AvatarUpload = ({ profile, onAvatarUploaded }: AvatarUploadProps) => {
|
export const AvatarUpload = ({ profile, onAvatarUploaded }: AvatarUploadProps) => {
|
||||||
const { avatarUrl } = useAvatar(profile);
|
const { avatarUrl, isLoading } = useAvatar(profile);
|
||||||
const { isUploading, fileInputRef, uploadToStorage } = useFileUpload();
|
const { isUploading, fileInputRef, uploadToStorage } = useFileUpload();
|
||||||
|
|
||||||
const handleAvatarClick = () => {
|
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 (
|
return (
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<div className="relative group cursor-pointer mb-4" onClick={handleAvatarClick}>
|
<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}>
|
<Button type='submit' disabled={isLoading}>
|
||||||
{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 type { Profile } from '@/utils/supabase';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
export function useProfile() {
|
export const useProfile = () => {
|
||||||
const [profile, setProfile] = useState<Profile | undefined>(undefined);
|
const [profile, setProfile] = useState<Profile | undefined>(undefined);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ export function useProfile() {
|
|||||||
if (!profileResponse.success)
|
if (!profileResponse.success)
|
||||||
throw new Error('Profile response unsuccessful');
|
throw new Error('Profile response unsuccessful');
|
||||||
setProfile(profileResponse.data);
|
setProfile(profileResponse.data);
|
||||||
} catch (error) {
|
} catch {
|
||||||
setProfile(undefined);
|
setProfile(undefined);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user