Cleaning up
This commit is contained in:
parent
5dcf2ed423
commit
40ab2d8450
@ -20,5 +20,5 @@ export async function GET(request: Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// URL to redirect to after sign up process completes
|
// URL to redirect to after sign up process completes
|
||||||
return NextResponse.redirect(`${origin}/protected`);
|
return NextResponse.redirect(origin);
|
||||||
}
|
}
|
||||||
|
@ -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 (
|
return (
|
||||||
<main className='w-full items-center justify-center'>
|
<div className='flex-1 w-full flex flex-col gap-12'>
|
||||||
<div className='flex p-5 items-center justify-center'>
|
<div className='w-full'>
|
||||||
<h1>Make sure you can sign in!</h1>
|
<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>
|
</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;
|
export default HomePage;
|
||||||
|
@ -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;
|
|
@ -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;
|
|
@ -6,7 +6,6 @@ import {
|
|||||||
Avatar,
|
Avatar,
|
||||||
AvatarFallback,
|
AvatarFallback,
|
||||||
AvatarImage,
|
AvatarImage,
|
||||||
Button,
|
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
@ -17,16 +16,12 @@ import {
|
|||||||
import { getSignedUrl, getProfile, signOut } from '@/lib/actions';
|
import { getSignedUrl, getProfile, signOut } from '@/lib/actions';
|
||||||
|
|
||||||
import type { Profile } from '@/utils/supabase';
|
import type { Profile } from '@/utils/supabase';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
const AvatarDropdown = () => {
|
const AvatarDropdown = () => {
|
||||||
const router = useRouter();
|
|
||||||
const [profile, setProfile] = useState<Profile | undefined>(undefined);
|
const [profile, setProfile] = useState<Profile | undefined>(undefined);
|
||||||
const [signedUrl, setSignedUrl] = useState<string | undefined>(undefined);
|
const [signedUrl, setSignedUrl] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
const handleEditProfile = async () => {
|
|
||||||
router.push('/profile');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSignOut = async () => {
|
const handleSignOut = async () => {
|
||||||
await signOut();
|
await signOut();
|
||||||
};
|
};
|
||||||
@ -78,14 +73,15 @@ const AvatarDropdown = () => {
|
|||||||
<DropdownMenuLabel>{profile?.full_name}</DropdownMenuLabel>
|
<DropdownMenuLabel>{profile?.full_name}</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
<Button onClick={handleEditProfile} variant={'secondary'} className='w-full text-left'>
|
<Link href='/profile' className='w-full justify-center'>
|
||||||
Edit profile
|
Edit profile
|
||||||
</Button>
|
</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator className='h-[2px]' />
|
||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
<Button onClick={handleSignOut} variant={'secondary'} className='w-full text-left'>
|
<button onClick={handleSignOut} className='w-full justify-center'>
|
||||||
Sign out
|
Log out
|
||||||
</Button>
|
</button>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
@ -32,7 +32,7 @@ export const signUp = async (formData: FormData) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return redirect('/protected');
|
return redirect('/');
|
||||||
//return encodedRedirect('error', '/sign-up',
|
//return encodedRedirect('error', '/sign-up',
|
||||||
//'Thanks for signing up! Please check your email for a verification link.');
|
//'Thanks for signing up! Please check your email for a verification link.');
|
||||||
} else {
|
} else {
|
||||||
@ -49,8 +49,8 @@ export const signUp = async (formData: FormData) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating profile: ', error);
|
console.error('Error updating profile: ', error);
|
||||||
} finally {
|
} finally {
|
||||||
return redirect('/protected');
|
return redirect('/');
|
||||||
//return encodedRedirect('success', '/protected',
|
//return encodedRedirect('success', '/',
|
||||||
//'Thanks for signing up! Please check your email for a verification link.);
|
//'Thanks for signing up! Please check your email for a verification link.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ export const signIn = async (formData: FormData) => {
|
|||||||
if (error) {
|
if (error) {
|
||||||
return encodedRedirect('error', '/sign-in', error.message);
|
return encodedRedirect('error', '/sign-in', error.message);
|
||||||
}
|
}
|
||||||
return redirect('/protected');
|
return redirect('/');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const forgotPassword = async (formData: FormData) => {
|
export const forgotPassword = async (formData: FormData) => {
|
||||||
@ -83,7 +83,7 @@ export const forgotPassword = async (formData: FormData) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
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) {
|
if (error) {
|
||||||
@ -113,7 +113,7 @@ export const resetPassword = async (formData: FormData) => {
|
|||||||
if (!password || !confirmPassword) {
|
if (!password || !confirmPassword) {
|
||||||
encodedRedirect(
|
encodedRedirect(
|
||||||
'error',
|
'error',
|
||||||
'/protected/reset-password',
|
'/reset-password',
|
||||||
'Password and confirm password are required',
|
'Password and confirm password are required',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ export const resetPassword = async (formData: FormData) => {
|
|||||||
if (password !== confirmPassword) {
|
if (password !== confirmPassword) {
|
||||||
encodedRedirect(
|
encodedRedirect(
|
||||||
'error',
|
'error',
|
||||||
'/protected/reset-password',
|
'/reset-password',
|
||||||
'Passwords do not match',
|
'Passwords do not match',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -133,12 +133,12 @@ export const resetPassword = async (formData: FormData) => {
|
|||||||
if (error) {
|
if (error) {
|
||||||
encodedRedirect(
|
encodedRedirect(
|
||||||
'error',
|
'error',
|
||||||
'/protected/reset-password',
|
'/reset-password',
|
||||||
'Password update failed',
|
'Password update failed',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
encodedRedirect('success', '/protected/reset-password', 'Password updated');
|
encodedRedirect('success', '/reset-password', 'Password updated');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const signOut = async () => {
|
export const signOut = async () => {
|
||||||
|
@ -41,13 +41,13 @@ export const updateSession = async (request: NextRequest) => {
|
|||||||
const user = await supabase.auth.getUser();
|
const user = await supabase.auth.getUser();
|
||||||
|
|
||||||
// protected routes
|
// 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));
|
return NextResponse.redirect(new URL('/sign-in', request.url));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.nextUrl.pathname === '/' && !user.error) {
|
//if (request.nextUrl.pathname === '/' && !user.error) {
|
||||||
return NextResponse.redirect(new URL('/protected', request.url));
|
//return NextResponse.redirect(new URL('/protected', request.url));
|
||||||
}
|
//}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import type { Database } from '@/utils/supabase/types';
|
import type { Database } from '@/utils/supabase/types';
|
||||||
|
export type { User } from '@supabase/supabase-js';
|
||||||
|
|
||||||
// Table row types
|
// Table row types
|
||||||
export type Profile = Database['public']['Tables']['profiles']['Row'];
|
export type Profile = Database['public']['Tables']['profiles']['Row'];
|
||||||
|
@ -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;
|
|
Loading…
x
Reference in New Issue
Block a user