Get started on turning this to tech tracker
This commit is contained in:
@ -161,9 +161,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
} catch (error) {
|
||||
console.error('Error updating profile:', error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Failed to update profile',
|
||||
error instanceof Error ? error.message : 'Failed to update profile',
|
||||
);
|
||||
return { success: false, error };
|
||||
}
|
||||
@ -185,9 +183,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
refreshUserData,
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
||||
);
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
'use server';
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { Button, type buttonVariants } from '@/components/ui';
|
||||
@ -13,7 +13,7 @@ type SignInSignUpProps = {
|
||||
signUpVariant?: VariantProps<typeof buttonVariants>['variant'];
|
||||
};
|
||||
|
||||
export const SignInSignUp = async ({
|
||||
export const SignInSignUp = ({
|
||||
className = 'flex gap-2',
|
||||
signInSize = 'default',
|
||||
signUpSize = 'sm',
|
||||
|
@ -71,9 +71,7 @@ export const SignInWithApple = ({
|
||||
<p className='text-[1.0rem]'>Sign In with Apple</p>
|
||||
</div>
|
||||
</SubmitButton>
|
||||
{statusMessage && (
|
||||
<StatusMessage message={{ error: statusMessage }} />
|
||||
)}
|
||||
{statusMessage && <StatusMessage message={{ error: statusMessage }} />}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
@ -64,9 +64,7 @@ export const SignInWithMicrosoft = ({
|
||||
<p className='text-[1.0rem]'>Sign In with Microsoft</p>
|
||||
</div>
|
||||
</SubmitButton>
|
||||
{statusMessage && (
|
||||
<StatusMessage message={{ error: statusMessage }} />
|
||||
)}
|
||||
{statusMessage && <StatusMessage message={{ error: statusMessage }} />}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
@ -1,22 +1,17 @@
|
||||
'use server';
|
||||
'use client';
|
||||
|
||||
import { getProfile } from '@/lib/actions';
|
||||
import AvatarDropdown from './AvatarDropdown';
|
||||
import { SignInSignUp } from '@/components/default/auth';
|
||||
import { useAuth } from '@/components/context';
|
||||
|
||||
const NavigationAuth = async () => {
|
||||
try {
|
||||
const profile = await getProfile();
|
||||
return profile.success ? (
|
||||
<div className='flex items-center gap-4'>
|
||||
<AvatarDropdown />
|
||||
</div>
|
||||
) : (
|
||||
<SignInSignUp />
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`Error getting profile: ${error as string}`);
|
||||
return <SignInSignUp />;
|
||||
}
|
||||
const NavigationAuth = () => {
|
||||
const { isAuthenticated } = useAuth();
|
||||
return isAuthenticated ? (
|
||||
<div className='flex items-center gap-4'>
|
||||
<AvatarDropdown />
|
||||
</div>
|
||||
) : (
|
||||
<SignInSignUp />
|
||||
);
|
||||
};
|
||||
export default NavigationAuth;
|
||||
|
@ -1,12 +1,21 @@
|
||||
'use server';
|
||||
'use client'
|
||||
|
||||
import Link from 'next/link';
|
||||
import { Button } from '@/components/ui';
|
||||
import NavigationAuth from './auth';
|
||||
import { ThemeToggle, TVToggle } from '@/components/context';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import NavigationAuth from './auth';
|
||||
import { ThemeToggle, TVToggle, useTVMode } from '@/components/context';
|
||||
|
||||
const Navigation = () => {
|
||||
const { tvMode } = useTVMode();
|
||||
if (tvMode) {
|
||||
return (
|
||||
<div className='absolute top-4 right-2'>
|
||||
<div className='flex flex-row my-auto items-center pt-2 pr-0 md:pt-4'>
|
||||
<TVToggle />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<nav
|
||||
className='w-full flex justify-center
|
||||
@ -18,23 +27,9 @@ const Navigation = () => {
|
||||
>
|
||||
<div className='flex gap-5 items-center font-semibold'>
|
||||
<Link className='flex flex-row my-auto gap-2' href='/'>
|
||||
<Image
|
||||
src='/favicon.png'
|
||||
alt='T3 Logo'
|
||||
width={50}
|
||||
height={50}
|
||||
/>
|
||||
<h1 className='my-auto text-2xl'>
|
||||
T3 Supabase Template
|
||||
</h1>
|
||||
<Image src='/favicon.png' alt='T3 Logo' width={50} height={50} />
|
||||
<h1 className='my-auto text-2xl'>Tech Tracker</h1>
|
||||
</Link>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Button asChild>
|
||||
<Link href='https://git.gbrown.org/gib/T3-Template'>
|
||||
Go to Git Repo
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<TVToggle />
|
||||
|
@ -55,10 +55,7 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
|
||||
return (
|
||||
<CardContent>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(handleSubmit)}
|
||||
className='space-y-6'
|
||||
>
|
||||
<form onSubmit={form.handleSubmit(handleSubmit)} className='space-y-6'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='full_name'
|
||||
@ -68,9 +65,7 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Your public display name.
|
||||
</FormDescription>
|
||||
<FormDescription>Your public display name.</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
@ -86,8 +81,7 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Your email address associated with your
|
||||
account.
|
||||
Your email address associated with your account.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -95,10 +89,7 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
|
||||
/>
|
||||
|
||||
<div className='flex justify-center'>
|
||||
<SubmitButton
|
||||
disabled={isLoading}
|
||||
pendingText='Saving...'
|
||||
>
|
||||
<SubmitButton disabled={isLoading} pendingText='Saving...'>
|
||||
Save Changes
|
||||
</SubmitButton>
|
||||
</div>
|
||||
|
@ -69,9 +69,7 @@ export const ResetPasswordForm = ({
|
||||
}
|
||||
} catch (error) {
|
||||
setStatusMessage(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Password was not updated!',
|
||||
error instanceof Error ? error.message : 'Password was not updated!',
|
||||
);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
@ -102,8 +100,7 @@ export const ResetPasswordForm = ({
|
||||
<Input type='password' {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Enter your new password. Must be at
|
||||
least 8 characters.
|
||||
Enter your new password. Must be at least 8 characters.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -119,8 +116,7 @@ export const ResetPasswordForm = ({
|
||||
<Input type='password' {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Please re-enter your new password to
|
||||
confirm.
|
||||
Please re-enter your new password to confirm.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -131,13 +127,9 @@ export const ResetPasswordForm = ({
|
||||
statusMessage.includes('error') ||
|
||||
statusMessage.includes('failed') ||
|
||||
statusMessage.includes('invalid') ? (
|
||||
<StatusMessage
|
||||
message={{ error: statusMessage }}
|
||||
/>
|
||||
<StatusMessage message={{ error: statusMessage }} />
|
||||
) : (
|
||||
<StatusMessage
|
||||
message={{ message: statusMessage }}
|
||||
/>
|
||||
<StatusMessage message={{ message: statusMessage }} />
|
||||
))}
|
||||
<div className='flex justify-center'>
|
||||
<SubmitButton
|
||||
|
@ -69,9 +69,7 @@ export const TestSentryCard = () => {
|
||||
fill='currentcolor'
|
||||
/>
|
||||
</svg>
|
||||
<CardTitle className='text-3xl my-auto'>
|
||||
Test Sentry
|
||||
</CardTitle>
|
||||
<CardTitle className='text-3xl my-auto'>Test Sentry</CardTitle>
|
||||
</div>
|
||||
<CardDescription className='text-[1.0rem]'>
|
||||
Click the button below & view the sample error on{' '}
|
||||
@ -81,8 +79,8 @@ export const TestSentryCard = () => {
|
||||
>
|
||||
the Sentry website
|
||||
</Link>
|
||||
. Navigate to the {"'"}Issues{"'"} page & you should see the
|
||||
sample error!
|
||||
. Navigate to the {"'"}Issues{"'"} page & you should see the sample
|
||||
error!
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@ -97,20 +95,14 @@ export const TestSentryCard = () => {
|
||||
{hasSentError ? (
|
||||
<div className='rounded-md bg-green-500/80 dark:bg-green-500/50 py-2 px-4 flex flex-row gap-2 my-auto'>
|
||||
<CheckCircle size={30} className='my-auto' />
|
||||
<p className='text-lg'>
|
||||
Sample error was sent to Sentry!
|
||||
</p>
|
||||
<p className='text-lg'>Sample error was sent to Sentry!</p>
|
||||
</div>
|
||||
) : !isConnected ? (
|
||||
<div className='rounded-md bg-red-600/50 dark:bg-red-500/50 py-2 px-4 flex flex-row gap-2 my-auto'>
|
||||
<MessageCircleWarning
|
||||
size={40}
|
||||
className='my-auto'
|
||||
/>
|
||||
<MessageCircleWarning size={40} className='my-auto' />
|
||||
<p>
|
||||
Wait! The Sentry SDK is not able to reach Sentry
|
||||
right now - this may be due to an adblocker. For
|
||||
more information, see{' '}
|
||||
Wait! The Sentry SDK is not able to reach Sentry right now -
|
||||
this may be due to an adblocker. For more information, see{' '}
|
||||
<Link
|
||||
href='https://docs.sentry.io/platforms/javascript/guides/nextjs/troubleshooting/#the-sdk-is-not-sending-any-data'
|
||||
className='text-accent-foreground underline hover:text-primary'
|
||||
@ -125,8 +117,8 @@ export const TestSentryCard = () => {
|
||||
</div>
|
||||
<Separator className='my-4 bg-accent' />
|
||||
<p className='description'>
|
||||
Warning! Sometimes Adblockers will prevent errors from being
|
||||
sent to Sentry.
|
||||
Warning! Sometimes Adblockers will prevent errors from being sent to
|
||||
Sentry.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
@ -57,9 +57,9 @@ export const FetchDataSteps = () => {
|
||||
>
|
||||
Table Editor
|
||||
</a>{' '}
|
||||
for your Supabase project to create a table and insert some
|
||||
example data. If you're stuck for creativity, you can
|
||||
copy and paste the following into the{' '}
|
||||
for your Supabase project to create a table and insert some example
|
||||
data. If you're stuck for creativity, you can copy and paste the
|
||||
following into the{' '}
|
||||
<a
|
||||
href='https://supabase.com/dashboard/project/_/sql/new'
|
||||
className='font-bold hover:underline text-foreground/80'
|
||||
@ -75,8 +75,8 @@ export const FetchDataSteps = () => {
|
||||
|
||||
<TutorialStep title='Query Supabase data from Next.js'>
|
||||
<p>
|
||||
To create a Supabase client and query data from an Async
|
||||
Server Component, create a new page.tsx file at{' '}
|
||||
To create a Supabase client and query data from an Async Server
|
||||
Component, create a new page.tsx file at{' '}
|
||||
<span className='relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-xs font-medium text-secondary-foreground border'>
|
||||
/app/notes/page.tsx
|
||||
</span>{' '}
|
||||
|
@ -17,7 +17,8 @@ const buttonVariants = cva(
|
||||
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
||||
ghost:
|
||||
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
||||
link: 'text-primary underline-offset-4 hover:underline',
|
||||
},
|
||||
size: {
|
||||
|
@ -16,10 +16,7 @@ function DropdownMenuPortal({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Portal
|
||||
data-slot='dropdown-menu-portal'
|
||||
{...props}
|
||||
/>
|
||||
<DropdownMenuPrimitive.Portal data-slot='dropdown-menu-portal' {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -58,10 +55,7 @@ function DropdownMenuGroup({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Group
|
||||
data-slot='dropdown-menu-group'
|
||||
{...props}
|
||||
/>
|
||||
<DropdownMenuPrimitive.Group data-slot='dropdown-menu-group' {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -201,9 +195,7 @@ function DropdownMenuShortcut({
|
||||
function DropdownMenuSub({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Sub data-slot='dropdown-menu-sub' {...props} />
|
||||
);
|
||||
return <DropdownMenuPrimitive.Sub data-slot='dropdown-menu-sub' {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuSubTrigger({
|
||||
|
Reference in New Issue
Block a user