diff --git a/app/lib/actions.ts b/app/lib/actions.ts
index a571cf0..a99a225 100644
--- a/app/lib/actions.ts
+++ b/app/lib/actions.ts
@@ -1,6 +1,8 @@
'use server';
+import { signIn } from '@/auth';
import { sql } from '@vercel/postgres';
+import { AuthError } from 'next-auth';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { z } from 'zod';
@@ -75,17 +77,17 @@ export async function updateInvoice(
amount: formData.get('amount'),
status: formData.get('status'),
});
-
+
if (!validatedFields.success) {
return {
errors: validatedFields.error.flatten().fieldErrors,
message: 'Missing Fields. Failed to Update Invoice.',
};
}
-
+
const { customerId, amount, status } = validatedFields.data;
const amountInCents = amount * 100;
-
+
try {
await sql`
UPDATE invoices
@@ -95,7 +97,7 @@ export async function updateInvoice(
} catch (error) {
return { message: 'Database Error: Failed to Update Invoice.' };
}
-
+
revalidatePath('/dashboard/invoices');
redirect('/dashboard/invoices');
}
@@ -112,3 +114,21 @@ export async function deleteInvoice(id: string) {
}
}
+export async function authenticate(
+ prevSate: string | undefined,
+ formData: FormData
+) {
+ try {
+ await signIn('credentials', formData);
+ } catch (error) {
+ if (error instanceof AuthError) {
+ switch (error.type) {
+ case 'CredentialsSignin':
+ return 'Invalid credentials';
+ default:
+ return 'Something went wrong.';
+ }
+ }
+ throw error;
+ }
+}
diff --git a/app/login/page.tsx b/app/login/page.tsx
new file mode 100644
index 0000000..805055c
--- /dev/null
+++ b/app/login/page.tsx
@@ -0,0 +1,17 @@
+import AcmeLogo from '@/app/ui/acme-logo';
+import LoginForm from '@/app/ui/login-form';
+
+export default function LoginPage() {
+ return (
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/ui/dashboard/sidenav.tsx b/app/ui/dashboard/sidenav.tsx
index 3d55b46..0ce9302 100644
--- a/app/ui/dashboard/sidenav.tsx
+++ b/app/ui/dashboard/sidenav.tsx
@@ -2,6 +2,7 @@ import Link from 'next/link';
import NavLinks from '@/app/ui/dashboard/nav-links';
import AcmeLogo from '@/app/ui/acme-logo';
import { PowerIcon } from '@heroicons/react/24/outline';
+import { signOut } from '@/auth';
export default function SideNav() {
return (
@@ -17,7 +18,12 @@ export default function SideNav() {
-
- {/* Add form errors here */}
+
+ {errorMessage && (
+ <>
+
+
{errorMessage}
+ >
+ )}
@@ -65,8 +79,9 @@ export default function LoginForm() {
}
function LoginButton() {
+ const { pending } = useFormStatus();
return (
-