Switching to tabs over spaces!

This commit is contained in:
2025-06-09 09:55:49 -05:00
parent cc225fae80
commit c2e816591d
71 changed files with 4353 additions and 4157 deletions

View File

@ -1,5 +1,7 @@
{ {
"singleQuote": true, "singleQuote": true,
"jsxSingleQuote": true, "jsxSingleQuote": true,
"trailingComma": "all" "trailingComma": "all",
"useTabs": true,
"tabWidth": 2
} }

View File

@ -17,7 +17,9 @@ export const GET = async (request: NextRequest) => {
const { error } = await supabase.auth.exchangeCodeForSession(code); const { error } = await supabase.auth.exchangeCodeForSession(code);
if (error) { if (error) {
console.error('OAuth error:', error); console.error('OAuth error:', error);
return redirect(`/sign-in?error=${encodeURIComponent(error.message)}`); return redirect(
`/sign-in?error=${encodeURIComponent(error.message)}`,
);
} }
return redirect(redirectTo); return redirect(redirectTo);
} }

View File

@ -21,7 +21,9 @@ const AuthSuccessPage = () => {
}; };
handleAuthSuccess().catch((error) => { handleAuthSuccess().catch((error) => {
console.error(`Error: ${error instanceof Error ? error.message : error}`); console.error(
`Error: ${error instanceof Error ? error.message : error}`,
);
}); });
}, [refreshUserData, router]); }, [refreshUserData, router]);

View File

@ -57,7 +57,8 @@ const ForgotPassword = () => {
if (result?.success) { if (result?.success) {
await refreshUserData(); await refreshUserData();
setStatusMessage( setStatusMessage(
result?.data ?? 'Check your email for a link to reset your password.', result?.data ??
'Check your email for a link to reset your password.',
); );
form.reset(); form.reset();
router.push(''); router.push('');
@ -74,7 +75,9 @@ const ForgotPassword = () => {
return ( return (
<Card className='min-w-xs md:min-w-sm'> <Card className='min-w-xs md:min-w-sm'>
<CardHeader> <CardHeader>
<CardTitle className='text-2xl font-medium'>Reset Password</CardTitle> <CardTitle className='text-2xl font-medium'>
Reset Password
</CardTitle>
<CardDescription className='text-sm text-foreground'> <CardDescription className='text-sm text-foreground'>
Don&apos;t have an account?{' '} Don&apos;t have an account?{' '}
<Link className='font-medium underline' href='/sign-up'> <Link className='font-medium underline' href='/sign-up'>
@ -116,9 +119,13 @@ const ForgotPassword = () => {
statusMessage.includes('error') || statusMessage.includes('error') ||
statusMessage.includes('failed') || statusMessage.includes('failed') ||
statusMessage.includes('invalid') ? ( statusMessage.includes('invalid') ? (
<StatusMessage message={{ error: statusMessage }} /> <StatusMessage
message={{ error: statusMessage }}
/>
) : ( ) : (
<StatusMessage message={{ success: statusMessage }} /> <StatusMessage
message={{ success: statusMessage }}
/>
))} ))}
</form> </form>
</Form> </Form>

View File

@ -97,7 +97,8 @@ const ProfilePage = () => {
<CardHeader className='pb-2'> <CardHeader className='pb-2'>
<CardTitle className='text-2xl'>Your Profile</CardTitle> <CardTitle className='text-2xl'>Your Profile</CardTitle>
<CardDescription> <CardDescription>
Manage your personal information and how it appears to others Manage your personal information and how it appears to
others
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
{isLoading && !profile ? ( {isLoading && !profile ? (
@ -110,7 +111,9 @@ const ProfilePage = () => {
<Separator /> <Separator />
<ProfileForm onSubmit={handleProfileSubmit} /> <ProfileForm onSubmit={handleProfileSubmit} />
<Separator /> <Separator />
<ResetPasswordForm onSubmit={handleResetPasswordSubmit} /> <ResetPasswordForm
onSubmit={handleResetPasswordSubmit}
/>
<Separator /> <Separator />
<SignOut /> <SignOut />
</div> </div>

View File

@ -99,7 +99,9 @@ const Login = () => {
name='email' name='email'
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel className='text-lg'>Email</FormLabel> <FormLabel className='text-lg'>
Email
</FormLabel>
<FormControl> <FormControl>
<Input <Input
type='email' type='email'
@ -118,7 +120,9 @@ const Login = () => {
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<div className='flex justify-between'> <div className='flex justify-between'>
<FormLabel className='text-lg'>Password</FormLabel> <FormLabel className='text-lg'>
Password
</FormLabel>
<Link <Link
className='text-xs text-foreground underline text-right' className='text-xs text-foreground underline text-right'
href='/forgot-password' href='/forgot-password'
@ -142,9 +146,13 @@ const Login = () => {
statusMessage.includes('error') || statusMessage.includes('error') ||
statusMessage.includes('failed') || statusMessage.includes('failed') ||
statusMessage.includes('invalid') ? ( statusMessage.includes('invalid') ? (
<StatusMessage message={{ error: statusMessage }} /> <StatusMessage
message={{ error: statusMessage }}
/>
) : ( ) : (
<StatusMessage message={{ message: statusMessage }} /> <StatusMessage
message={{ message: statusMessage }}
/>
))} ))}
<SubmitButton <SubmitButton
disabled={isLoading} disabled={isLoading}

View File

@ -104,7 +104,10 @@ const SignUp = () => {
<CardTitle className='text-3xl font-medium'>Sign Up</CardTitle> <CardTitle className='text-3xl font-medium'>Sign Up</CardTitle>
<CardDescription className='text-foreground'> <CardDescription className='text-foreground'>
Already have an account?{' '} Already have an account?{' '}
<Link className='text-primary font-medium underline' href='/sign-in'> <Link
className='text-primary font-medium underline'
href='/sign-in'
>
Sign in Sign in
</Link> </Link>
</CardDescription> </CardDescription>
@ -120,9 +123,15 @@ const SignUp = () => {
name='name' name='name'
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel className='text-lg'>Name</FormLabel> <FormLabel className='text-lg'>
Name
</FormLabel>
<FormControl> <FormControl>
<Input type='text' placeholder='Full Name' {...field} /> <Input
type='text'
placeholder='Full Name'
{...field}
/>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}
@ -132,7 +141,9 @@ const SignUp = () => {
name='email' name='email'
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel className='text-lg'>Email</FormLabel> <FormLabel className='text-lg'>
Email
</FormLabel>
<FormControl> <FormControl>
<Input <Input
type='email' type='email'
@ -149,7 +160,9 @@ const SignUp = () => {
name='password' name='password'
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel className='text-lg'>Password</FormLabel> <FormLabel className='text-lg'>
Password
</FormLabel>
<FormControl> <FormControl>
<Input <Input
type='password' type='password'
@ -166,7 +179,9 @@ const SignUp = () => {
name='confirmPassword' name='confirmPassword'
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel className='text-lg'>Confirm Password</FormLabel> <FormLabel className='text-lg'>
Confirm Password
</FormLabel>
<FormControl> <FormControl>
<Input <Input
type='password' type='password'
@ -183,9 +198,13 @@ const SignUp = () => {
statusMessage.includes('error') || statusMessage.includes('error') ||
statusMessage.includes('failed') || statusMessage.includes('failed') ||
statusMessage.includes('invalid') ? ( statusMessage.includes('invalid') ? (
<StatusMessage message={{ error: statusMessage }} /> <StatusMessage
message={{ error: statusMessage }}
/>
) : ( ) : (
<StatusMessage message={{ success: statusMessage }} /> <StatusMessage
message={{ success: statusMessage }}
/>
))} ))}
<SubmitButton <SubmitButton
className='text-[1.0rem] cursor-pointer' className='text-[1.0rem] cursor-pointer'

View File

@ -27,9 +27,15 @@ const GlobalError = ({ error, reset = undefined }: GlobalErrorProps) => {
}, [error]); }, [error]);
return ( return (
<html lang='en' className={`${geist.variable}`} suppressHydrationWarning> <html
lang='en'
className={`${geist.variable}`}
suppressHydrationWarning
>
<body <body
className={cn('bg-background text-foreground font-sans antialiased')} className={cn(
'bg-background text-foreground font-sans antialiased',
)}
> >
<ThemeProvider <ThemeProvider
attribute='class' attribute='class'
@ -47,7 +53,9 @@ const GlobalError = ({ error, reset = undefined }: GlobalErrorProps) => {
> >
<NextError statusCode={0} /> <NextError statusCode={0} />
{reset !== undefined && ( {reset !== undefined && (
<Button onClick={() => reset()}>Try again</Button> <Button onClick={() => reset()}>
Try again
</Button>
)} )}
</div> </div>
</div> </div>

View File

@ -46,8 +46,16 @@ export const generateMetadata = (): Metadata => {
icons: { icons: {
icon: [ icon: [
{ url: '/favicon.ico', type: 'image/x-icon', sizes: 'any' }, { url: '/favicon.ico', type: 'image/x-icon', sizes: 'any' },
{ url: '/favicon-16x16.png', type: 'image/png', sizes: '16x16' }, {
{ url: '/favicon-32x32.png', type: 'image/png', sizes: '32x32' }, url: '/favicon-16x16.png',
type: 'image/png',
sizes: '16x16',
},
{
url: '/favicon-32x32.png',
type: 'image/png',
sizes: '32x32',
},
{ url: '/favicon.png', type: 'image/png', sizes: '96x96' }, { url: '/favicon.png', type: 'image/png', sizes: '96x96' },
{ {
url: '/favicon.ico', url: '/favicon.ico',
@ -74,16 +82,36 @@ export const generateMetadata = (): Metadata => {
media: '(prefers-color-scheme: dark)', media: '(prefers-color-scheme: dark)',
}, },
{ url: '/appicon/icon-36x36.png', type: 'image/png', sizes: '36x36' }, {
{ url: '/appicon/icon-48x48.png', type: 'image/png', sizes: '48x48' }, url: '/appicon/icon-36x36.png',
{ url: '/appicon/icon-72x72.png', type: 'image/png', sizes: '72x72' }, type: 'image/png',
{ url: '/appicon/icon-96x96.png', type: 'image/png', sizes: '96x96' }, sizes: '36x36',
},
{
url: '/appicon/icon-48x48.png',
type: 'image/png',
sizes: '48x48',
},
{
url: '/appicon/icon-72x72.png',
type: 'image/png',
sizes: '72x72',
},
{
url: '/appicon/icon-96x96.png',
type: 'image/png',
sizes: '96x96',
},
{ {
url: '/appicon/icon-144x144.png', url: '/appicon/icon-144x144.png',
type: 'image/png', type: 'image/png',
sizes: '144x144', sizes: '144x144',
}, },
{ url: '/appicon/icon.png', type: 'image/png', sizes: '192x192' }, {
url: '/appicon/icon.png',
type: 'image/png',
sizes: '192x192',
},
{ {
url: '/appicon/icon-36x36.png', url: '/appicon/icon-36x36.png',
type: 'image/png', type: 'image/png',
@ -122,16 +150,36 @@ export const generateMetadata = (): Metadata => {
}, },
], ],
shortcut: [ shortcut: [
{ url: '/appicon/icon-36x36.png', type: 'image/png', sizes: '36x36' }, {
{ url: '/appicon/icon-48x48.png', type: 'image/png', sizes: '48x48' }, url: '/appicon/icon-36x36.png',
{ url: '/appicon/icon-72x72.png', type: 'image/png', sizes: '72x72' }, type: 'image/png',
{ url: '/appicon/icon-96x96.png', type: 'image/png', sizes: '96x96' }, sizes: '36x36',
},
{
url: '/appicon/icon-48x48.png',
type: 'image/png',
sizes: '48x48',
},
{
url: '/appicon/icon-72x72.png',
type: 'image/png',
sizes: '72x72',
},
{
url: '/appicon/icon-96x96.png',
type: 'image/png',
sizes: '96x96',
},
{ {
url: '/appicon/icon-144x144.png', url: '/appicon/icon-144x144.png',
type: 'image/png', type: 'image/png',
sizes: '144x144', sizes: '144x144',
}, },
{ url: '/appicon/icon.png', type: 'image/png', sizes: '192x192' }, {
url: '/appicon/icon.png',
type: 'image/png',
sizes: '192x192',
},
{ {
url: '/appicon/icon-36x36.png', url: '/appicon/icon-36x36.png',
type: 'image/png', type: 'image/png',
@ -170,10 +218,26 @@ export const generateMetadata = (): Metadata => {
}, },
], ],
apple: [ apple: [
{ url: 'appicon/icon-57x57.png', type: 'image/png', sizes: '57x57' }, {
{ url: 'appicon/icon-60x60.png', type: 'image/png', sizes: '60x60' }, url: 'appicon/icon-57x57.png',
{ url: 'appicon/icon-72x72.png', type: 'image/png', sizes: '72x72' }, type: 'image/png',
{ url: 'appicon/icon-76x76.png', type: 'image/png', sizes: '76x76' }, sizes: '57x57',
},
{
url: 'appicon/icon-60x60.png',
type: 'image/png',
sizes: '60x60',
},
{
url: 'appicon/icon-72x72.png',
type: 'image/png',
sizes: '72x72',
},
{
url: 'appicon/icon-76x76.png',
type: 'image/png',
sizes: '76x76',
},
{ {
url: 'appicon/icon-114x114.png', url: 'appicon/icon-114x114.png',
type: 'image/png', type: 'image/png',
@ -199,7 +263,11 @@ export const generateMetadata = (): Metadata => {
type: 'image/png', type: 'image/png',
sizes: '180x180', sizes: '180x180',
}, },
{ url: 'appicon/icon.png', type: 'image/png', sizes: '192x192' }, {
url: 'appicon/icon.png',
type: 'image/png',
sizes: '192x192',
},
{ {
url: 'appicon/icon-57x57.png', url: 'appicon/icon-57x57.png',
type: 'image/png', type: 'image/png',
@ -349,9 +417,15 @@ const geist = Geist({
const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => { const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
return ( return (
<html lang='en' className={`${geist.variable}`} suppressHydrationWarning> <html
lang='en'
className={`${geist.variable}`}
suppressHydrationWarning
>
<body <body
className={cn('bg-background text-foreground font-sans antialiased')} className={cn(
'bg-background text-foreground font-sans antialiased',
)}
> >
<ThemeProvider <ThemeProvider
attribute='class' attribute='class'

View File

@ -31,9 +31,9 @@ const HomePage = async () => {
Welcome to the T3 Supabase Template! Welcome to the T3 Supabase Template!
</CardTitle> </CardTitle>
<CardDescription className='text-[1.0rem] mb-2'> <CardDescription className='text-[1.0rem] mb-2'>
A great place to start is by creating a new user account & A great place to start is by creating a new user
ensuring you can sign up! If you already have an account, go account & ensuring you can sign up! If you
ahead and sign in! already have an account, go ahead and sign in!
</CardDescription> </CardDescription>
<SignInSignUp <SignInSignUp
className='flex gap-4 w-full justify-center' className='flex gap-4 w-full justify-center'
@ -42,7 +42,9 @@ const HomePage = async () => {
/> />
<div className='flex items-center w-full gap-4'> <div className='flex items-center w-full gap-4'>
<Separator className='flex-1 bg-accent py-0.5' /> <Separator className='flex-1 bg-accent py-0.5' />
<span className='text-sm text-muted-foreground'>or</span> <span className='text-sm text-muted-foreground'>
or
</span>
<Separator className='flex-1 bg-accent py-0.5' /> <Separator className='flex-1 bg-accent py-0.5' />
</div> </div>
<div className='flex gap-4'> <div className='flex gap-4'>
@ -53,8 +55,8 @@ const HomePage = async () => {
<Separator className='bg-accent' /> <Separator className='bg-accent' />
<CardContent className='flex flex-col px-5 py-2 items-center justify-center'> <CardContent className='flex flex-col px-5 py-2 items-center justify-center'>
<CardTitle className='text-lg mb-6 w-2/3 text-center'> <CardTitle className='text-lg mb-6 w-2/3 text-center'>
You can also test out your connection to Sentry if you want to You can also test out your connection to Sentry
start there! if you want to start there!
</CardTitle> </CardTitle>
<TestSentryCard /> <TestSentryCard />
</CardContent> </CardContent>

View File

@ -161,7 +161,9 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
} catch (error) { } catch (error) {
console.error('Error updating profile:', error); console.error('Error updating profile:', error);
toast.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 }; return { success: false, error };
} }
@ -183,7 +185,9 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
refreshUserData, refreshUserData,
}; };
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; return (
<AuthContext.Provider value={value}>{children}</AuthContext.Provider>
);
}; };
export const useAuth = () => { export const useAuth = () => {

View File

@ -71,7 +71,9 @@ export const SignInWithApple = ({
<p className='text-[1.0rem]'>Sign In with Apple</p> <p className='text-[1.0rem]'>Sign In with Apple</p>
</div> </div>
</SubmitButton> </SubmitButton>
{statusMessage && <StatusMessage message={{ error: statusMessage }} />} {statusMessage && (
<StatusMessage message={{ error: statusMessage }} />
)}
</form> </form>
); );
}; };

View File

@ -64,7 +64,9 @@ export const SignInWithMicrosoft = ({
<p className='text-[1.0rem]'>Sign In with Microsoft</p> <p className='text-[1.0rem]'>Sign In with Microsoft</p>
</div> </div>
</SubmitButton> </SubmitButton>
{statusMessage && <StatusMessage message={{ error: statusMessage }} />} {statusMessage && (
<StatusMessage message={{ error: statusMessage }} />
)}
</form> </form>
); );
}; };

View File

@ -18,8 +18,15 @@ const Navigation = () => {
> >
<div className='flex gap-5 items-center font-semibold'> <div className='flex gap-5 items-center font-semibold'>
<Link className='flex flex-row my-auto gap-2' href='/'> <Link className='flex flex-row my-auto gap-2' href='/'>
<Image src='/favicon.png' alt='T3 Logo' width={50} height={50} /> <Image
<h1 className='my-auto text-2xl'>T3 Supabase Template</h1> src='/favicon.png'
alt='T3 Logo'
width={50}
height={50}
/>
<h1 className='my-auto text-2xl'>
T3 Supabase Template
</h1>
</Link> </Link>
<div className='flex items-center gap-2'> <div className='flex items-center gap-2'>
<Button asChild> <Button asChild>

View File

@ -55,7 +55,10 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
return ( return (
<CardContent> <CardContent>
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className='space-y-6'> <form
onSubmit={form.handleSubmit(handleSubmit)}
className='space-y-6'
>
<FormField <FormField
control={form.control} control={form.control}
name='full_name' name='full_name'
@ -65,7 +68,9 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
<FormControl> <FormControl>
<Input {...field} /> <Input {...field} />
</FormControl> </FormControl>
<FormDescription>Your public display name.</FormDescription> <FormDescription>
Your public display name.
</FormDescription>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}
@ -81,7 +86,8 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
<Input {...field} /> <Input {...field} />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
Your email address associated with your account. Your email address associated with your
account.
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
@ -89,7 +95,10 @@ export const ProfileForm = ({ onSubmit }: ProfileFormProps) => {
/> />
<div className='flex justify-center'> <div className='flex justify-center'>
<SubmitButton disabled={isLoading} pendingText='Saving...'> <SubmitButton
disabled={isLoading}
pendingText='Saving...'
>
Save Changes Save Changes
</SubmitButton> </SubmitButton>
</div> </div>

View File

@ -69,7 +69,9 @@ export const ResetPasswordForm = ({
} }
} catch (error) { } catch (error) {
setStatusMessage( setStatusMessage(
error instanceof Error ? error.message : 'Password was not updated!', error instanceof Error
? error.message
: 'Password was not updated!',
); );
} finally { } finally {
setIsLoading(false); setIsLoading(false);
@ -100,7 +102,8 @@ export const ResetPasswordForm = ({
<Input type='password' {...field} /> <Input type='password' {...field} />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
Enter your new password. Must be at least 8 characters. Enter your new password. Must be at
least 8 characters.
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
@ -116,7 +119,8 @@ export const ResetPasswordForm = ({
<Input type='password' {...field} /> <Input type='password' {...field} />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
Please re-enter your new password to confirm. Please re-enter your new password to
confirm.
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
@ -127,9 +131,13 @@ export const ResetPasswordForm = ({
statusMessage.includes('error') || statusMessage.includes('error') ||
statusMessage.includes('failed') || statusMessage.includes('failed') ||
statusMessage.includes('invalid') ? ( statusMessage.includes('invalid') ? (
<StatusMessage message={{ error: statusMessage }} /> <StatusMessage
message={{ error: statusMessage }}
/>
) : ( ) : (
<StatusMessage message={{ message: statusMessage }} /> <StatusMessage
message={{ message: statusMessage }}
/>
))} ))}
<div className='flex justify-center'> <div className='flex justify-center'>
<SubmitButton <SubmitButton

View File

@ -69,7 +69,9 @@ export const TestSentryCard = () => {
fill='currentcolor' fill='currentcolor'
/> />
</svg> </svg>
<CardTitle className='text-3xl my-auto'>Test Sentry</CardTitle> <CardTitle className='text-3xl my-auto'>
Test Sentry
</CardTitle>
</div> </div>
<CardDescription className='text-[1.0rem]'> <CardDescription className='text-[1.0rem]'>
Click the button below & view the sample error on{' '} Click the button below & view the sample error on{' '}
@ -79,8 +81,8 @@ export const TestSentryCard = () => {
> >
the Sentry website the Sentry website
</Link> </Link>
. Navigate to the {"'"}Issues{"'"} page & you should see the sample . Navigate to the {"'"}Issues{"'"} page & you should see the
error! sample error!
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
@ -95,14 +97,20 @@ export const TestSentryCard = () => {
{hasSentError ? ( {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'> <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' /> <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> </div>
) : !isConnected ? ( ) : !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'> <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> <p>
Wait! The Sentry SDK is not able to reach Sentry right now - Wait! The Sentry SDK is not able to reach Sentry
this may be due to an adblocker. For more information, see{' '} right now - this may be due to an adblocker. For
more information, see{' '}
<Link <Link
href='https://docs.sentry.io/platforms/javascript/guides/nextjs/troubleshooting/#the-sdk-is-not-sending-any-data' 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' className='text-accent-foreground underline hover:text-primary'
@ -117,8 +125,8 @@ export const TestSentryCard = () => {
</div> </div>
<Separator className='my-4 bg-accent' /> <Separator className='my-4 bg-accent' />
<p className='description'> <p className='description'>
Warning! Sometimes Adblockers will prevent errors from being sent to Warning! Sometimes Adblockers will prevent errors from being
Sentry. sent to Sentry.
</p> </p>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -57,9 +57,9 @@ export const FetchDataSteps = () => {
> >
Table Editor Table Editor
</a>{' '} </a>{' '}
for your Supabase project to create a table and insert some example for your Supabase project to create a table and insert some
data. If you&apos;re stuck for creativity, you can copy and paste the example data. If you&apos;re stuck for creativity, you can
following into the{' '} copy and paste the following into the{' '}
<a <a
href='https://supabase.com/dashboard/project/_/sql/new' href='https://supabase.com/dashboard/project/_/sql/new'
className='font-bold hover:underline text-foreground/80' className='font-bold hover:underline text-foreground/80'
@ -75,8 +75,8 @@ export const FetchDataSteps = () => {
<TutorialStep title='Query Supabase data from Next.js'> <TutorialStep title='Query Supabase data from Next.js'>
<p> <p>
To create a Supabase client and query data from an Async Server To create a Supabase client and query data from an Async
Component, create a new page.tsx file at{' '} 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'> <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 /app/notes/page.tsx
</span>{' '} </span>{' '}

View File

@ -17,8 +17,7 @@ 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', '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: secondary:
'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80', 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
ghost: ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
link: 'text-primary underline-offset-4 hover:underline', link: 'text-primary underline-offset-4 hover:underline',
}, },
size: { size: {

View File

@ -16,7 +16,10 @@ function DropdownMenuPortal({
...props ...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) { }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
return ( return (
<DropdownMenuPrimitive.Portal data-slot='dropdown-menu-portal' {...props} /> <DropdownMenuPrimitive.Portal
data-slot='dropdown-menu-portal'
{...props}
/>
); );
} }
@ -55,7 +58,10 @@ function DropdownMenuGroup({
...props ...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) { }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
return ( return (
<DropdownMenuPrimitive.Group data-slot='dropdown-menu-group' {...props} /> <DropdownMenuPrimitive.Group
data-slot='dropdown-menu-group'
{...props}
/>
); );
} }
@ -195,7 +201,9 @@ function DropdownMenuShortcut({
function DropdownMenuSub({ function DropdownMenuSub({
...props ...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) { }: 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({ function DropdownMenuSubTrigger({

View File

@ -40,7 +40,8 @@ export const env = createEnv({
CI: process.env.CI, CI: process.env.CI,
NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,
NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_SUPABASE_ANON_KEY:
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL, NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN, NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
NEXT_PUBLIC_SENTRY_URL: process.env.NEXT_PUBLIC_SENTRY_URL, NEXT_PUBLIC_SENTRY_URL: process.env.NEXT_PUBLIC_SENTRY_URL,

View File

@ -124,7 +124,9 @@ export const uploadFile = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error uploading file', error instanceof Error
? error.message
: 'Unknown error uploading file',
}; };
} }
}; };
@ -147,7 +149,9 @@ export const replaceFile = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error replacing file', error instanceof Error
? error.message
: 'Unknown error replacing file',
}; };
} }
}; };
@ -171,7 +175,9 @@ export const deleteFile = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error deleting file', error instanceof Error
? error.message
: 'Unknown error deleting file',
}; };
} }
}; };
@ -205,7 +211,9 @@ export const listFiles = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error listing files', error instanceof Error
? error.message
: 'Unknown error listing files',
}; };
} }
}; };

View File

@ -124,7 +124,9 @@ export const uploadFile = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error uploading file', error instanceof Error
? error.message
: 'Unknown error uploading file',
}; };
} }
}; };
@ -150,7 +152,9 @@ export const replaceFile = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error replacing file', error instanceof Error
? error.message
: 'Unknown error replacing file',
}; };
} }
}; };
@ -174,7 +178,9 @@ export const deleteFile = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error deleting file', error instanceof Error
? error.message
: 'Unknown error deleting file',
}; };
} }
}; };
@ -208,7 +214,9 @@ export const listFiles = async ({
return { return {
success: false, success: false,
error: error:
error instanceof Error ? error.message : 'Unknown error listing files', error instanceof Error
? error.message
: 'Unknown error listing files',
}; };
} }
}; };

View File

@ -72,7 +72,9 @@ export const useFileUpload = () => {
}); });
if (!uploadResult.success) { if (!uploadResult.success) {
throw new Error(uploadResult.error || `Failed to upload to ${bucket}`); throw new Error(
uploadResult.error || `Failed to upload to ${bucket}`,
);
} }
return { success: true, data: uploadResult.data }; return { success: true, data: uploadResult.data };

View File

@ -41,7 +41,10 @@ export const updateSession = async (
const user = await supabase.auth.getUser(); const user = await supabase.auth.getUser();
// protected routes // protected routes
if (request.nextUrl.pathname.startsWith('/reset-password') && user.error) { if (
request.nextUrl.pathname.startsWith('/reset-password') &&
user.error
) {
return NextResponse.redirect(new URL('/sign-in', request.url)); return NextResponse.redirect(new URL('/sign-in', request.url));
} }