poop
This commit is contained in:
@ -13,12 +13,14 @@ import {
|
||||
import { createClient } from '@/utils/supabase/client';
|
||||
import type { Session } from '@supabase/supabase-js';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { redirect } from 'next/navigation';
|
||||
import type { User } from '@/lib/types';
|
||||
|
||||
const AvatarDropdown = () => {
|
||||
const supabase = createClient();
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [pfp, setPfp] = useState<string>('/images/default_user_pfp.png');
|
||||
|
||||
useEffect(() => {
|
||||
// Function to fetch the session
|
||||
@ -28,6 +30,24 @@ const AvatarDropdown = () => {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
setSession(session);
|
||||
|
||||
if (session?.user?.id) {
|
||||
const { data: userData, error } = await supabase
|
||||
.from('profiles')
|
||||
.select('*')
|
||||
.eq('id', session?.user.id)
|
||||
.single();
|
||||
if (error) {
|
||||
console.error('Error fetching user data:', error);
|
||||
return;
|
||||
}
|
||||
if (userData) {
|
||||
const user = userData as User;
|
||||
console.log(user);
|
||||
setUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching session:', error);
|
||||
} finally {
|
||||
@ -53,10 +73,36 @@ const AvatarDropdown = () => {
|
||||
};
|
||||
}, [supabase]);
|
||||
|
||||
useEffect(() => {
|
||||
if (user?.avatar_url) {
|
||||
console.log('Avatar Url:', user.avatar_url);
|
||||
if (user.avatar_url.startsWith('http')) {
|
||||
setPfp(user.avatar_url);
|
||||
return;
|
||||
}
|
||||
// Get public URL - this is synchronous
|
||||
const { data } = supabase
|
||||
.storage
|
||||
.from('avatars')
|
||||
.getPublicUrl(user.avatar_url);
|
||||
|
||||
console.log('Avatar URL:', data.publicUrl);
|
||||
setPfp(data.publicUrl);
|
||||
}
|
||||
}, [user, supabase]);
|
||||
|
||||
const getInitials = (fullName: string | undefined): string => {
|
||||
if (!fullName || fullName.trim() === '' || fullName === 'undefined') return 'NA';
|
||||
const nameParts = fullName.trim().split(' ');
|
||||
const firstInitial = nameParts[0]?.charAt(0).toUpperCase() ?? 'N';
|
||||
if (nameParts.length === 1) return 'NA';
|
||||
const lastIntitial = nameParts[nameParts.length -1]?.charAt(0).toUpperCase() ?? 'A';
|
||||
return firstInitial + lastIntitial;
|
||||
};
|
||||
|
||||
// Handle sign out
|
||||
const handleSignOut = async () => {
|
||||
await supabase.auth.signOut();
|
||||
redirect('/');
|
||||
};
|
||||
|
||||
// Show nothing while loading
|
||||
@ -69,18 +115,6 @@ const AvatarDropdown = () => {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
// Get user details
|
||||
const pfp =
|
||||
(session.user?.user_metadata?.avatar_url as string) ??
|
||||
(session.user?.user_metadata?.picture as string) ??
|
||||
'/images/default_user_pfp.png';
|
||||
|
||||
const name: string =
|
||||
(session.user?.user_metadata?.full_name as string) ??
|
||||
(session.user?.user_metadata?.name as string) ??
|
||||
(session.user?.email as string) ??
|
||||
('Profile' as string);
|
||||
|
||||
// If no session, return empty div
|
||||
if (!session) return <div />;
|
||||
return (
|
||||
@ -89,7 +123,7 @@ const AvatarDropdown = () => {
|
||||
<DropdownMenuTrigger>
|
||||
<Image
|
||||
src={pfp}
|
||||
alt='User profile'
|
||||
alt={getInitials(user?.full_name) ?? 'NA'}
|
||||
width={35}
|
||||
height={35}
|
||||
className='rounded-full border-2 border-white m-auto mr-1 md:mr-2
|
||||
@ -97,7 +131,7 @@ const AvatarDropdown = () => {
|
||||
/>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuLabel>{name}</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>{user?.full_name}</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem asChild>
|
||||
<Button onClick={handleSignOut} className='w-full text-left'>
|
||||
|
@ -1,9 +1,7 @@
|
||||
'use client';
|
||||
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||
import React, { createContext, useContext, useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { Session } from '@supabase/supabase-js';
|
||||
import { createClient } from '@/utils/supabase/client';
|
||||
|
||||
interface TVModeContextProps {
|
||||
tvMode: boolean;
|
||||
@ -34,62 +32,31 @@ export const useTVMode = () => {
|
||||
return context;
|
||||
};
|
||||
|
||||
export const TVToggle = () => {
|
||||
type TVToggleProps = {
|
||||
width?: number;
|
||||
height?: number;
|
||||
};
|
||||
|
||||
export const TVToggle = ({
|
||||
width = 25,
|
||||
height = 25,
|
||||
}: TVToggleProps) => {
|
||||
const { tvMode, toggleTVMode } = useTVMode();
|
||||
const supabase = createClient();
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
// Function to fetch the session
|
||||
async function fetchSession() {
|
||||
try {
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
setSession(session);
|
||||
} catch (error) {
|
||||
console.error('Error fetching session:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Call the function
|
||||
fetchSession().catch((error) => {
|
||||
console.error('Error fetching session:', error);
|
||||
});
|
||||
|
||||
// Set up auth state change listener
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabase.auth.onAuthStateChange((_event, session) => {
|
||||
setSession(session);
|
||||
});
|
||||
|
||||
// Clean up the subscription when component unmounts
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [supabase]);
|
||||
|
||||
if (loading || !session) return <div />;
|
||||
|
||||
return (
|
||||
<button onClick={toggleTVMode} className='mr-4 mt-1'>
|
||||
{tvMode ? (
|
||||
<Image
|
||||
src='/images/exit_fullscreen.svg'
|
||||
alt='Exit TV Mode'
|
||||
width={25}
|
||||
height={25}
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
src='/images/fullscreen.svg'
|
||||
alt='Enter TV Mode'
|
||||
width={25}
|
||||
height={25}
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
|
@ -1,20 +1,69 @@
|
||||
'use client';
|
||||
import { useState, useEffect } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { TVToggle, useTVMode } from '@/components/context/TVMode';
|
||||
import { ThemeToggle } from '@/components/context/Theme';
|
||||
import AvatarDropdown from '@/components/auth/AvatarDropdown';
|
||||
import { createClient } from '@/utils/supabase/client';
|
||||
import type { Session } from '@supabase/supabase-js';
|
||||
|
||||
const Header = () => {
|
||||
const { tvMode } = useTVMode();
|
||||
|
||||
const supabase = createClient();
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
// Function to fetch the session
|
||||
async function fetchSession() {
|
||||
try {
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
setSession(session);
|
||||
} catch (error) {
|
||||
console.error('Error fetching session:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Call the function
|
||||
fetchSession().catch((error) => {
|
||||
console.error('Error fetching session:', error);
|
||||
});
|
||||
|
||||
// Set up auth state change listener
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabase.auth.onAuthStateChange((_event, session) => {
|
||||
setSession(session);
|
||||
});
|
||||
|
||||
// Clean up the subscription when component unmounts
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [supabase]);
|
||||
|
||||
if (tvMode) {
|
||||
return (
|
||||
<div className='w-full flex flex-row items-end justify-end'>
|
||||
<div className='flex flex-row my-auto items-center pt-2 pr-0 sm:pr-8 sm:pt-4'>
|
||||
<AvatarDropdown />
|
||||
<div className='mb-0.5 ml-2'>
|
||||
<TVToggle />
|
||||
</div>
|
||||
<div className='flex flex-row my-auto items-center
|
||||
justify-center pt-2 pr-0 sm:pt-4 sm:pr-8'
|
||||
>
|
||||
<ThemeToggle />
|
||||
{session && !loading && (
|
||||
<div className='flex flex-row my-auto items-center
|
||||
justify-center'
|
||||
>
|
||||
<div className='mb-0.5 ml-4'>
|
||||
<TVToggle width={22} height={22} />
|
||||
</div>
|
||||
<AvatarDropdown />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -22,15 +71,20 @@ const Header = () => {
|
||||
return (
|
||||
<header className='w-full min-h-[10vh]'>
|
||||
<div className='w-full flex flex-row items-end justify-end'>
|
||||
<div
|
||||
className='flex flex-row my-auto items-center
|
||||
pt-2 pr-0 sm:pt-4 sm:pr-8'
|
||||
<div className='flex flex-row my-auto items-center
|
||||
justify-center pt-2 pr-0 sm:pt-4 sm:pr-8'
|
||||
>
|
||||
<AvatarDropdown />
|
||||
<div className='mb-0.5 ml-2'>
|
||||
<TVToggle />
|
||||
</div>
|
||||
<ThemeToggle />
|
||||
{session && !loading && (
|
||||
<div className='flex flex-row my-auto items-center
|
||||
justify-center'
|
||||
>
|
||||
<div className='mb-0.5 ml-4'>
|
||||
<TVToggle width={22} height={22} />
|
||||
</div>
|
||||
<AvatarDropdown />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
Reference in New Issue
Block a user