diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx new file mode 100644 index 0000000..146fdf3 --- /dev/null +++ b/app/(auth)/login/page.tsx @@ -0,0 +1,12 @@ +// app/(auth)/login/page.tsx +import { LoginForm } from '@/components/auth/login-form' + +export default function LoginPage() { + return ( +
+
+ +
+
+ ) +} diff --git a/app/api/auth/callback/route.ts b/app/api/auth/callback/route.ts new file mode 100644 index 0000000..8f16e19 --- /dev/null +++ b/app/api/auth/callback/route.ts @@ -0,0 +1,19 @@ +// app/api/auth/callback/route.ts +import { createClient } from '@/lib/supabase/server' +import { NextResponse } from 'next/server' + +export async function GET(request: Request) { + const { searchParams, origin } = new URL(request.url) + const code = searchParams.get('code') + const next = searchParams.get('next') ?? '/' + + if (code) { + const supabase = await createClient() + const { error } = await supabase.auth.exchangeCodeForSession(code) + if (!error) { + return NextResponse.redirect(`${origin}${next}`) + } + } + + return NextResponse.redirect(`${origin}/login?error=auth_callback_failed`) +} diff --git a/app/page.tsx b/app/page.tsx index 3f36f7c..f688d36 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,65 +1,25 @@ -import Image from "next/image"; +// app/page.tsx +import { redirect } from 'next/navigation' +import { createClient } from '@/lib/supabase/server' +import { getRoleHome, isValidRole, type UserRole } from '@/lib/auth/roles' -export default function Home() { - return ( -
-
- Next.js logo -
-

- To get started, edit the page.tsx file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
-
- - Vercel logomark - Deploy Now - - - Documentation - -
-
-
- ); +export default async function RootPage() { + const supabase = await createClient() + const { + data: { user }, + } = await supabase.auth.getUser() + + if (!user) redirect('/login') + + const { data: profile } = await supabase + .from('users') + .select('role') + .eq('id', user.id) + .single() + + if (profile?.role && isValidRole(profile.role)) { + redirect(getRoleHome(profile.role as UserRole)) + } + + redirect('/login') } diff --git a/components/auth/login-form.tsx b/components/auth/login-form.tsx new file mode 100644 index 0000000..cadd1af --- /dev/null +++ b/components/auth/login-form.tsx @@ -0,0 +1,72 @@ +// components/auth/login-form.tsx +'use client' + +import { useState } from 'react' +import { useRouter } from 'next/navigation' +import { createClient } from '@/lib/supabase/client' + +export function LoginForm() { + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [error, setError] = useState(null) + const [loading, setLoading] = useState(false) + const router = useRouter() + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault() + setLoading(true) + setError(null) + + const supabase = createClient() + const { error } = await supabase.auth.signInWithPassword({ email, password }) + + if (error) { + setError(error.message) + setLoading(false) + return + } + + router.refresh() + } + + return ( +
+
+

IMS

+

HSE Incident Management

+
+ + {error && ( +

+ {error} +

+ )} + + setEmail(e.target.value)} + required + autoComplete="email" + className="border rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + setPassword(e.target.value)} + required + autoComplete="current-password" + className="border rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+ ) +}