Getting started on Tech Tracker. Added TV Context

This commit is contained in:
2025-06-09 06:59:38 -05:00
parent 5f2d25f9dd
commit cc225fae80
28 changed files with 284 additions and 91 deletions

View File

@ -110,7 +110,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
const {
data: { subscription },
} = supabase.auth.onAuthStateChange(async (event, session) => {
} = supabase.auth.onAuthStateChange(async (event, _session) => {
console.log('Auth state change:', event); // Debug log
if (event === 'SIGNED_IN') {

View File

@ -0,0 +1,79 @@
'use client';
import Image from 'next/image';
import React, { createContext, useContext, useState } from 'react';
import type { ReactNode } from 'react';
import { useAuth } from '@/components/context';
import { Button, type buttonVariants } from '@/components/ui';
import { type ComponentProps } from 'react';
import { type VariantProps } from 'class-variance-authority';
type TVModeContextProps = {
tvMode: boolean;
toggleTVMode: () => void;
};
type TVToggleProps = {
className?: ComponentProps<'button'>['className'];
buttonSize?: VariantProps<typeof buttonVariants>['size'];
buttonVariant?: VariantProps<typeof buttonVariants>['variant'];
imageWidth?: number;
imageHeight?: number;
};
const TVModeContext = createContext<TVModeContextProps | undefined>(undefined);
export const TVModeProvider = ({ children }: { children: ReactNode }) => {
const [tvMode, setTVMode] = useState(false);
const toggleTVMode = () => {
setTVMode((prev) => !prev);
};
return (
<TVModeContext.Provider value={{ tvMode, toggleTVMode }}>
{children}
</TVModeContext.Provider>
);
};
export const useTVMode = () => {
const context = useContext(TVModeContext);
if (!context) {
throw new Error('useTVMode must be used within a TVModeProvider');
}
return context;
};
export const TVToggle = ({
className = 'my-auto cursor-pointer',
buttonSize = 'default',
buttonVariant = 'link',
imageWidth = 25,
imageHeight = 25,
}: TVToggleProps) => {
const { tvMode, toggleTVMode } = useTVMode();
const { isAuthenticated } = useAuth();
if (!isAuthenticated) return <div />;
return (
<Button
onClick={toggleTVMode}
className={className}
size={buttonSize}
variant={buttonVariant}
>
{tvMode ? (
<Image
src='/icons/tv/exit.svg'
alt='Exit TV Mode'
width={imageWidth}
height={imageHeight}
/>
) : (
<Image
src='/icons/tv/enter.svg'
alt='Exit TV Mode'
width={imageWidth}
height={imageHeight}
/>
)}
</Button>
);
};

View File

@ -20,10 +20,9 @@ export const ThemeProvider = ({
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
};
export interface ThemeToggleProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
type ThemeToggleProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
size?: number;
}
};
export const ThemeToggle = ({ size = 1, ...props }: ThemeToggleProps) => {
const { setTheme, resolvedTheme } = useTheme();

View File

@ -0,0 +1,3 @@
export { AuthProvider, useAuth } from './Auth';
export { ThemeProvider, ThemeToggle } from './Theme';
export { TVModeProvider, useTVMode, TVToggle } from './TVMode';

View File

@ -1,7 +1,7 @@
'use client';
import { signInWithApple } from '@/lib/actions';
import { StatusMessage, SubmitButton } from '@/components/default';
import { useAuth } from '@/components/context/auth';
import { useAuth } from '@/components/context';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import Image from 'next/image';
@ -37,7 +37,7 @@ export const SignInWithApple = ({
// Redirect to Apple OAuth page
window.location.href = result.data;
} else {
setStatusMessage(`Error: ${result.error}`);
setStatusMessage(`Error signing in with Apple!`);
}
} catch (error) {
setStatusMessage(

View File

@ -1,7 +1,7 @@
'use client';
import { signInWithMicrosoft } from '@/lib/actions';
import { StatusMessage, SubmitButton } from '@/components/default';
import { useAuth } from '@/components/context/auth';
import { useAuth } from '@/components/context';
import { useState } from 'react';
import Image from 'next/image';
import { type buttonVariants } from '@/components/ui';
@ -35,7 +35,7 @@ export const SignInWithMicrosoft = ({
// Redirect to Microsoft OAuth page
window.location.href = result.data;
} else {
setStatusMessage(`Error: ${result.error}`);
setStatusMessage(`Error: Could not sign in with Microsoft!`);
}
} catch (error) {
setStatusMessage(

View File

@ -12,7 +12,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui';
import { useAuth } from '@/components/context/auth';
import { useAuth } from '@/components/context';
import { useRouter } from 'next/navigation';
import { signOut } from '@/lib/actions';
import { User } from 'lucide-react';

View File

@ -3,7 +3,7 @@
import Link from 'next/link';
import { Button } from '@/components/ui';
import NavigationAuth from './auth';
import { ThemeToggle } from '@/components/context/theme';
import { ThemeToggle, TVToggle } from '@/components/context';
import Image from 'next/image';
const Navigation = () => {
@ -30,6 +30,7 @@ const Navigation = () => {
</div>
</div>
<div className='flex items-center gap-2'>
<TVToggle />
<ThemeToggle />
<NavigationAuth />
</div>

View File

@ -1,5 +1,5 @@
import { useFileUpload } from '@/lib/hooks/useFileUpload';
import { useAuth } from '@/components/context/auth';
import { useAuth } from '@/components/context';
import {
Avatar,
AvatarFallback,

View File

@ -13,7 +13,7 @@ import {
Input,
} from '@/components/ui';
import { useEffect } from 'react';
import { useAuth } from '@/components/context/auth';
import { useAuth } from '@/components/context';
import { SubmitButton } from '@/components/default';
const formSchema = z.object({

View File

@ -122,18 +122,15 @@ export const ResetPasswordForm = ({
</FormItem>
)}
/>
{statusMessage && (
<div
className={`text-sm text-center ${
statusMessage.includes('Error') ||
statusMessage.includes('failed')
? 'text-destructive'
: 'text-green-600'
}`}
>
{statusMessage}
</div>
)}
{statusMessage &&
(statusMessage.includes('Error') ||
statusMessage.includes('error') ||
statusMessage.includes('failed') ||
statusMessage.includes('invalid') ? (
<StatusMessage message={{ error: statusMessage }} />
) : (
<StatusMessage message={{ message: statusMessage }} />
))}
<div className='flex justify-center'>
<SubmitButton
disabled={isLoading}

View File

@ -3,7 +3,7 @@
import { CardHeader } from '@/components/ui';
import { SubmitButton } from '@/components/default';
import { useRouter } from 'next/navigation';
import { useAuth } from '@/components/context/auth';
import { useAuth } from '@/components/context';
import { signOut } from '@/lib/actions';
export const SignOut = () => {