Getting started on Tech Tracker. Added TV Context
This commit is contained in:
@ -17,7 +17,7 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^5.1.0",
|
||||
"@hookform/resolvers": "^5.1.1",
|
||||
"@radix-ui/react-avatar": "^1.1.10",
|
||||
"@radix-ui/react-checkbox": "^1.3.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
||||
|
38
pnpm-lock.yaml
generated
38
pnpm-lock.yaml
generated
@ -9,8 +9,8 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@hookform/resolvers':
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0(react-hook-form@7.57.0(react@19.1.0))
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1(react-hook-form@7.57.0(react@19.1.0))
|
||||
'@radix-ui/react-avatar':
|
||||
specifier: ^1.1.10
|
||||
version: 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
@ -274,8 +274,8 @@ packages:
|
||||
'@floating-ui/utils@0.2.9':
|
||||
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
|
||||
|
||||
'@hookform/resolvers@5.1.0':
|
||||
resolution: {integrity: sha512-A5tY8gxqvvR0lFfropqpy/gUDOxjwT7LZCxJ8lNA9puK7nFNRl/O0egGKxzdF4JSz/pnnT1O8g76P/YMyTBEFw==}
|
||||
'@hookform/resolvers@5.1.1':
|
||||
resolution: {integrity: sha512-J/NVING3LMAEvexJkyTLjruSm7aOFx7QX21pzkiJfMoNG0wl5aFEjLTl7ay7IQb9EWY6AkrBy7tHL2Alijpdcg==}
|
||||
peerDependencies:
|
||||
react-hook-form: ^7.55.0
|
||||
|
||||
@ -1723,8 +1723,8 @@ packages:
|
||||
peerDependencies:
|
||||
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
|
||||
acorn@8.14.1:
|
||||
resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
|
||||
acorn@8.15.0:
|
||||
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
|
||||
@ -3697,7 +3697,7 @@ snapshots:
|
||||
|
||||
'@floating-ui/utils@0.2.9': {}
|
||||
|
||||
'@hookform/resolvers@5.1.0(react-hook-form@7.57.0(react@19.1.0))':
|
||||
'@hookform/resolvers@5.1.1(react-hook-form@7.57.0(react@19.1.0))':
|
||||
dependencies:
|
||||
'@standard-schema/utils': 0.3.0
|
||||
react-hook-form: 7.57.0(react@19.1.0)
|
||||
@ -5157,15 +5157,15 @@ snapshots:
|
||||
|
||||
'@xtuc/long@4.2.2': {}
|
||||
|
||||
acorn-import-attributes@1.9.5(acorn@8.14.1):
|
||||
acorn-import-attributes@1.9.5(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.14.1):
|
||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn@8.14.1: {}
|
||||
acorn@8.15.0: {}
|
||||
|
||||
agent-base@6.0.2:
|
||||
dependencies:
|
||||
@ -5789,8 +5789,8 @@ snapshots:
|
||||
|
||||
espree@10.3.0:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn-jsx: 5.3.2(acorn@8.14.1)
|
||||
acorn: 8.15.0
|
||||
acorn-jsx: 5.3.2(acorn@8.15.0)
|
||||
eslint-visitor-keys: 4.2.0
|
||||
|
||||
esquery@1.6.0:
|
||||
@ -5997,8 +5997,8 @@ snapshots:
|
||||
|
||||
import-in-the-middle@1.14.0:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn-import-attributes: 1.9.5(acorn@8.14.1)
|
||||
acorn: 8.15.0
|
||||
acorn-import-attributes: 1.9.5(acorn@8.15.0)
|
||||
cjs-module-lexer: 1.4.3
|
||||
module-details-from-path: 1.0.4
|
||||
|
||||
@ -6908,7 +6908,7 @@ snapshots:
|
||||
terser@5.41.0:
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.6
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
|
||||
@ -7000,7 +7000,7 @@ snapshots:
|
||||
|
||||
unplugin@1.0.1:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
chokidar: 3.6.0
|
||||
webpack-sources: 3.3.2
|
||||
webpack-virtual-modules: 0.5.0
|
||||
@ -7077,7 +7077,7 @@ snapshots:
|
||||
'@webassemblyjs/ast': 1.14.1
|
||||
'@webassemblyjs/wasm-edit': 1.14.1
|
||||
'@webassemblyjs/wasm-parser': 1.14.1
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
browserslist: 4.25.0
|
||||
chrome-trace-event: 1.0.4
|
||||
enhanced-resolve: 5.18.1
|
||||
|
63
public/icons/tv/enter.svg
Normal file
63
public/icons/tv/enter.svg
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg513"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="Fullscreen.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview515"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8.4359982"
|
||||
inkscape:cx="69.108597"
|
||||
inkscape:cy="37.458519"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="3832"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs510" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 5.8615386,0 H 0 V 5.8615386 H 0.97692256 V 0.97692327 H 5.8615386 Z"
|
||||
id="path396-6"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 0,6.8384619 V 12.7 H 5.8615386 V 11.723076 H 0.97692256 V 6.8384619 Z"
|
||||
id="path396-52"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 6.8384613,12.7 H 12.7 V 6.8384619 H 11.723078 V 11.723076 H 6.8384613 Z"
|
||||
id="path396-4"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 12.7,5.8615386 V 0 H 6.8384613 V 0.97692327 H 11.723078 V 5.8615386 Z"
|
||||
id="path396-0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
63
public/icons/tv/exit.svg
Normal file
63
public/icons/tv/exit.svg
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg513"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="ExitFullscreen.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview515"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8.4359982"
|
||||
inkscape:cx="69.108597"
|
||||
inkscape:cy="37.458519"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="3832"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs510" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 0,5.8620045 H 5.8615381 L 5.8621526,0 H 4.8849607 L 4.8846152,4.8851478 H 0 Z"
|
||||
id="path190"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 6.8384615,8.6556325e-4 V 5.8620045 H 12.7 V 4.8851478 H 7.815384 V 8.6556325e-4 Z"
|
||||
id="path396"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 12.7,6.8388612 H 6.8384615 V 12.7 H 7.815384 V 7.8157173 H 12.7 Z"
|
||||
id="path396-5"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 5.8615381,12.7 V 6.8388612 H 0 V 7.8157173 H 4.8846152 V 12.7 Z"
|
||||
id="path396-1"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
@ -35,7 +35,7 @@ export const GET = async (request: NextRequest) => {
|
||||
if (type === 'invite') return redirect('/sign-up');
|
||||
}
|
||||
return redirect(
|
||||
`/?error=${encodeURIComponent(error?.message || 'Unknown error')}`,
|
||||
`/?error=${encodeURIComponent(error?.message ?? 'Unknown error')}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
|
||||
const AuthSuccessPage = () => {
|
||||
const { refreshUserData, isAuthenticated } = useAuth();
|
||||
const { refreshUserData } = useAuth();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
import Link from 'next/link';
|
||||
import { forgotPassword } from '@/lib/actions';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { StatusMessage, SubmitButton } from '@/components/default';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
'use client';
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
import {
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
import Link from 'next/link';
|
||||
import { signIn } from '@/lib/actions';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { StatusMessage, SubmitButton } from '@/components/default';
|
||||
import { Separator } from '@/components/ui';
|
||||
|
@ -7,7 +7,7 @@ import Link from 'next/link';
|
||||
import { signUp } from '@/lib/actions';
|
||||
import { StatusMessage, SubmitButton } from '@/components/default';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@ -26,7 +26,7 @@ import {
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
SignInWithApple,
|
||||
SignInWithMicrosoft
|
||||
SignInWithMicrosoft,
|
||||
} from '@/components/default/auth';
|
||||
|
||||
const formSchema = z
|
||||
@ -201,8 +201,8 @@ const SignUp = () => {
|
||||
<span className='text-sm text-muted-foreground'>or</span>
|
||||
<Separator className='flex-1 bg-accent py-0.5' />
|
||||
</div>
|
||||
<SignInWithMicrosoft type='signUp' />
|
||||
<SignInWithApple type='signUp' />
|
||||
<SignInWithMicrosoft />
|
||||
<SignInWithApple />
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
import '@/styles/globals.css';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ThemeProvider } from '@/components/context/theme';
|
||||
import { AuthProvider } from '@/components/context/auth';
|
||||
import { AuthProvider, ThemeProvider } from '@/components/context';
|
||||
import Navigation from '@/components/default/navigation';
|
||||
import Footer from '@/components/default/footer';
|
||||
import { Button, Toaster } from '@/components/ui';
|
||||
@ -60,21 +59,6 @@ const GlobalError = ({ error, reset = undefined }: GlobalErrorProps) => {
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
return (
|
||||
<html lang='en'>
|
||||
<body>
|
||||
{/* `NextError` is the default Next.js error page component. Its type
|
||||
definition requires a `statusCode` prop. However, since the App Router
|
||||
does not expose status codes for errors, we simply pass 0 to render a
|
||||
generic error message. */}
|
||||
<NextError statusCode={0} />
|
||||
{reset !== undefined && (
|
||||
<Button onClick={() => reset()}>Try again</Button>
|
||||
)}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
};
|
||||
|
||||
export default GlobalError;
|
||||
|
@ -2,8 +2,11 @@ import type { Metadata } from 'next';
|
||||
import '@/styles/globals.css';
|
||||
import { Geist } from 'next/font/google';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ThemeProvider } from '@/components/context/theme';
|
||||
import { AuthProvider } from '@/components/context/auth';
|
||||
import {
|
||||
AuthProvider,
|
||||
ThemeProvider,
|
||||
TVModeProvider,
|
||||
} from '@/components/context';
|
||||
import Navigation from '@/components/default/navigation';
|
||||
import Footer from '@/components/default/footer';
|
||||
import { Toaster } from '@/components/ui';
|
||||
@ -357,6 +360,7 @@ const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<AuthProvider>
|
||||
<TVModeProvider>
|
||||
<main className='min-h-screen flex flex-col items-center'>
|
||||
<div className='flex-1 w-full flex flex-col gap-20 items-center'>
|
||||
<Navigation />
|
||||
@ -370,6 +374,7 @@ const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
<Footer />
|
||||
</main>
|
||||
<Toaster />
|
||||
</TVModeProvider>
|
||||
</AuthProvider>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
import {
|
||||
SignInSignUp,
|
||||
SignInWithApple,
|
||||
SignInWithMicrosoft
|
||||
SignInWithMicrosoft,
|
||||
} from '@/components/default/auth';
|
||||
|
||||
const HomePage = async () => {
|
||||
|
@ -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') {
|
79
src/components/context/TVMode.tsx
Normal file
79
src/components/context/TVMode.tsx
Normal 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>
|
||||
);
|
||||
};
|
@ -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();
|
3
src/components/context/index.tsx
Normal file
3
src/components/context/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
export { AuthProvider, useAuth } from './Auth';
|
||||
export { ThemeProvider, ThemeToggle } from './Theme';
|
||||
export { TVModeProvider, useTVMode, TVToggle } from './TVMode';
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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';
|
||||
|
@ -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>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useFileUpload } from '@/lib/hooks/useFileUpload';
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
|
@ -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({
|
||||
|
@ -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}
|
||||
|
@ -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 = () => {
|
||||
|
@ -149,7 +149,7 @@ export const getUser = async (): Promise<Result<User>> => {
|
||||
const { data, error } = await supabase.auth.getUser();
|
||||
if (error) throw error;
|
||||
return { success: true, data: data.user };
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Could not get user!' };
|
||||
} catch {
|
||||
return { success: false, error: `Could not get user!` };
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,5 @@
|
||||
export * from './auth';
|
||||
export * from './public';
|
||||
//export * from './resizeImage';
|
||||
export * from './storage';
|
||||
export * from './useFileUpload';
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { useState, useRef } from 'react';
|
||||
import { replaceFile, uploadFile } from '@/lib/hooks';
|
||||
import { toast } from 'sonner';
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
import { resizeImage } from '@/lib/hooks';
|
||||
import type { Result } from '.';
|
||||
|
||||
|
Reference in New Issue
Block a user