Cleaning up

This commit is contained in:
Gabriel Brown 2025-05-15 16:53:21 -05:00
parent 5dcf2ed423
commit 40ab2d8450
10 changed files with 61 additions and 286 deletions

View File

@ -20,5 +20,5 @@ export async function GET(request: Request) {
}
// URL to redirect to after sign up process completes
return NextResponse.redirect(`${origin}/protected`);
return NextResponse.redirect(origin);
}

View File

@ -1,10 +1,44 @@
const HomePage = () => {
'use server';
import { FetchDataSteps } from '@/components/tutorial';
import { InfoIcon } from 'lucide-react';
import { getUser } from '@/lib/actions';
import type { User } from '@/utils/supabase';
const HomePage = async () => {
const response = await getUser();
if (!response.success || !response.data) {
return (
<main className='w-full items-center justify-center'>
<div className='flex p-5 items-center justify-center'>
<h1>Make sure you can sign in!</h1>
</div>
</main>
);
}
const user: User = response.data;
return (
<main className='w-full items-center justify-center'>
<div className='flex p-5 items-center justify-center'>
<h1>Make sure you can sign in!</h1>
<div className='flex-1 w-full flex flex-col gap-12'>
<div className='w-full'>
<div className='bg-accent text-sm p-3 px-5
rounded-md text-foreground flex gap-3 items-center'>
<InfoIcon size='16' strokeWidth={2} />
This is a protected component that you can only see as an authenticated
user
</div>
</div>
</main>
<div className='flex flex-col gap-2 items-start'>
<h2 className='font-bold text-2xl mb-4'>Your user details</h2>
<pre className='text-xs font-mono p-3 rounded
border max-h-32 overflow-auto'>
{JSON.stringify(user, null, 2)}
</pre>
</div>
<div>
<h2 className='font-bold text-2xl mb-4'>Next steps</h2>
<FetchDataSteps />
</div>
</div>
);
};
export default HomePage;

View File

@ -1,40 +0,0 @@
'use server';
import { FetchDataSteps } from '@/components/tutorial';
import { createServerClient } from '@/utils/supabase';
import { InfoIcon } from 'lucide-react';
import { redirect } from 'next/navigation';
const ProtectedPage = async () => {
const supabase = await createServerClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) {
return redirect('sign-in');
}
return (
<div className='flex-1 w-full flex flex-col gap-12'>
<div className='w-full'>
<div className='bg-accent text-sm p-3 px-5 rounded-md text-foreground flex gap-3 items-center'>
<InfoIcon size='16' strokeWidth={2} />
This is a protected page that you can only see as an authenticated
user
</div>
</div>
<div className='flex flex-col gap-2 items-start'>
<h2 className='font-bold text-2xl mb-4'>Your user details</h2>
<pre className='text-xs font-mono p-3 rounded border max-h-32 overflow-auto'>
{JSON.stringify(user, null, 2)}
</pre>
</div>
<div>
<h2 className='font-bold text-2xl mb-4'>Next steps</h2>
<FetchDataSteps />
</div>
</div>
);
};
export default ProtectedPage;

View File

@ -1,28 +0,0 @@
'use server';
import { getSignedUrl, getProfile } from '@/lib/actions';
import Image from 'next/image';
const Page = async () => {
const user = await getProfile();
if (!user.success) throw new Error(user.error);
const imageUrl = await getSignedUrl({
bucket: 'avatars',
url: user.data.avatar_url ?? '',
});
if (!imageUrl.success) throw new Error(imageUrl.error);
return (
<div className='flex justify-center items-center p-8'>
<Image
src={imageUrl.data ?? '/favicon.ico'}
alt='User avatar'
width={150}
height={150}
className='rounded-full'
priority
/>
</div>
);
};
export default Page;

View File

@ -6,7 +6,6 @@ import {
Avatar,
AvatarFallback,
AvatarImage,
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
@ -17,16 +16,12 @@ import {
import { getSignedUrl, getProfile, signOut } from '@/lib/actions';
import type { Profile } from '@/utils/supabase';
import Link from 'next/link';
const AvatarDropdown = () => {
const router = useRouter();
const [profile, setProfile] = useState<Profile | undefined>(undefined);
const [signedUrl, setSignedUrl] = useState<string | undefined>(undefined);
const handleEditProfile = async () => {
router.push('/profile');
};
const handleSignOut = async () => {
await signOut();
};
@ -78,14 +73,15 @@ const AvatarDropdown = () => {
<DropdownMenuLabel>{profile?.full_name}</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Button onClick={handleEditProfile} variant={'secondary'} className='w-full text-left'>
<Link href='/profile' className='w-full justify-center'>
Edit profile
</Button>
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator className='h-[2px]' />
<DropdownMenuItem asChild>
<Button onClick={handleSignOut} variant={'secondary'} className='w-full text-left'>
Sign out
</Button>
<button onClick={handleSignOut} className='w-full justify-center'>
Log out
</button>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

View File

@ -32,7 +32,7 @@ export const signUp = async (formData: FormData) => {
});
if (error) {
return redirect('/protected');
return redirect('/');
//return encodedRedirect('error', '/sign-up',
//'Thanks for signing up! Please check your email for a verification link.');
} else {
@ -49,8 +49,8 @@ export const signUp = async (formData: FormData) => {
} catch (error) {
console.error('Error updating profile: ', error);
} finally {
return redirect('/protected');
//return encodedRedirect('success', '/protected',
return redirect('/');
//return encodedRedirect('success', '/',
//'Thanks for signing up! Please check your email for a verification link.);
}
}
@ -69,7 +69,7 @@ export const signIn = async (formData: FormData) => {
if (error) {
return encodedRedirect('error', '/sign-in', error.message);
}
return redirect('/protected');
return redirect('/');
};
export const forgotPassword = async (formData: FormData) => {
@ -83,7 +83,7 @@ export const forgotPassword = async (formData: FormData) => {
}
const { error } = await supabase.auth.resetPasswordForEmail(email, {
redirectTo: `${origin}/auth/callback?redirect_to=/protected/reset-password`,
redirectTo: `${origin}/auth/callback?redirect_to=/reset-password`,
});
if (error) {
@ -113,7 +113,7 @@ export const resetPassword = async (formData: FormData) => {
if (!password || !confirmPassword) {
encodedRedirect(
'error',
'/protected/reset-password',
'/reset-password',
'Password and confirm password are required',
);
}
@ -121,7 +121,7 @@ export const resetPassword = async (formData: FormData) => {
if (password !== confirmPassword) {
encodedRedirect(
'error',
'/protected/reset-password',
'/reset-password',
'Passwords do not match',
);
}
@ -133,12 +133,12 @@ export const resetPassword = async (formData: FormData) => {
if (error) {
encodedRedirect(
'error',
'/protected/reset-password',
'/reset-password',
'Password update failed',
);
}
encodedRedirect('success', '/protected/reset-password', 'Password updated');
encodedRedirect('success', '/reset-password', 'Password updated');
};
export const signOut = async () => {

View File

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

View File

@ -1,4 +1,5 @@
import type { Database } from '@/utils/supabase/types';
export type { User } from '@supabase/supabase-js';
// Table row types
export type Profile = Database['public']['Tables']['profiles']['Row'];

View File

@ -1,188 +0,0 @@
export type Json =
| string
| number
| boolean
| null
| { [key: string]: Json | undefined }
| Json[];
export type Database = {
public: {
Tables: {
profiles: {
Row: {
avatar_url: string | null;
email: string | null;
full_name: string | null;
id: string;
provider: string | null;
updated_at: string | null;
};
Insert: {
avatar_url?: string | null;
email?: string | null;
full_name?: string | null;
id: string;
provider?: string | null;
updated_at?: string | null;
};
Update: {
avatar_url?: string | null;
email?: string | null;
full_name?: string | null;
id?: string;
provider?: string | null;
updated_at?: string | null;
};
Relationships: [];
};
statuses: {
Row: {
created_at: string;
id: string;
status: string;
updated_by_id: string | null;
user_id: string;
};
Insert: {
created_at?: string;
id?: string;
status: string;
updated_by_id?: string | null;
user_id: string;
};
Update: {
created_at?: string;
id?: string;
status?: string;
updated_by_id?: string | null;
user_id?: string;
};
Relationships: [];
};
};
Views: {
[_ in never]: never;
};
Functions: {
[_ in never]: never;
};
Enums: {
[_ in never]: never;
};
CompositeTypes: {
[_ in never]: never;
};
};
};
type DefaultSchema = Database[Extract<keyof Database, 'public'>];
export type Tables<
DefaultSchemaTableNameOrOptions extends
| keyof (DefaultSchema['Tables'] & DefaultSchema['Views'])
| { schema: keyof Database },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof Database;
}
? keyof (Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'] &
Database[DefaultSchemaTableNameOrOptions['schema']]['Views'])
: never = never,
> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database }
? (Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'] &
Database[DefaultSchemaTableNameOrOptions['schema']]['Views'])[TableName] extends {
Row: infer R;
}
? R
: never
: DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema['Tables'] &
DefaultSchema['Views'])
? (DefaultSchema['Tables'] &
DefaultSchema['Views'])[DefaultSchemaTableNameOrOptions] extends {
Row: infer R;
}
? R
: never
: never;
export type TablesInsert<
DefaultSchemaTableNameOrOptions extends
| keyof DefaultSchema['Tables']
| { schema: keyof Database },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[DefaultSchemaTableNameOrOptions['schema']]['Tables']
: never = never,
> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database }
? Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'][TableName] extends {
Insert: infer I;
}
? I
: never
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables']
? DefaultSchema['Tables'][DefaultSchemaTableNameOrOptions] extends {
Insert: infer I;
}
? I
: never
: never;
export type TablesUpdate<
DefaultSchemaTableNameOrOptions extends
| keyof DefaultSchema['Tables']
| { schema: keyof Database },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[DefaultSchemaTableNameOrOptions['schema']]['Tables']
: never = never,
> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database }
? Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'][TableName] extends {
Update: infer U;
}
? U
: never
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables']
? DefaultSchema['Tables'][DefaultSchemaTableNameOrOptions] extends {
Update: infer U;
}
? U
: never
: never;
export type Enums<
DefaultSchemaEnumNameOrOptions extends
| keyof DefaultSchema['Enums']
| { schema: keyof Database },
EnumName extends DefaultSchemaEnumNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[DefaultSchemaEnumNameOrOptions['schema']]['Enums']
: never = never,
> = DefaultSchemaEnumNameOrOptions extends { schema: keyof Database }
? Database[DefaultSchemaEnumNameOrOptions['schema']]['Enums'][EnumName]
: DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema['Enums']
? DefaultSchema['Enums'][DefaultSchemaEnumNameOrOptions]
: never;
export type CompositeTypes<
PublicCompositeTypeNameOrOptions extends
| keyof DefaultSchema['CompositeTypes']
| { schema: keyof Database },
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes']
: never = never,
> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database }
? Database[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes'][CompositeTypeName]
: PublicCompositeTypeNameOrOptions extends keyof DefaultSchema['CompositeTypes']
? DefaultSchema['CompositeTypes'][PublicCompositeTypeNameOrOptions]
: never;
export const Constants = {
public: {
Enums: {},
},
} as const;