}
\ No newline at end of file
diff --git a/app/dashboard/invoices/[id]/edit/page.tsx b/app/dashboard/invoices/[id]/edit/page.tsx
index 842545e..a544fa3 100644
--- a/app/dashboard/invoices/[id]/edit/page.tsx
+++ b/app/dashboard/invoices/[id]/edit/page.tsx
@@ -3,6 +3,12 @@ import Breadcrumbs from '@/app/ui/invoices/breadcrumbs';
import { fetchInvoiceById, fetchCustomers } from '@/app/lib/data';
import { notFound } from 'next/navigation';
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Edit Invoice',
+};
+
export default async function Page({ params }: { params: { id: string } }) {
const id = params.id;
const [invoice, customers] = await Promise.all([
diff --git a/app/dashboard/invoices/create/page.tsx b/app/dashboard/invoices/create/page.tsx
index 0568f27..dd62b41 100644
--- a/app/dashboard/invoices/create/page.tsx
+++ b/app/dashboard/invoices/create/page.tsx
@@ -1,6 +1,11 @@
import Form from '@/app/ui/invoices/create-form';
import Breadcrumbs from '@/app/ui/invoices/breadcrumbs';
import { fetchCustomers } from '@/app/lib/data';
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Create Invoice',
+};
export default async function Page() {
const customers = await fetchCustomers();
diff --git a/app/dashboard/invoices/page.tsx b/app/dashboard/invoices/page.tsx
index 984404d..36a5073 100644
--- a/app/dashboard/invoices/page.tsx
+++ b/app/dashboard/invoices/page.tsx
@@ -6,6 +6,11 @@ import { lusitana } from '@/app/ui/fonts';
import { InvoicesTableSkeleton } from '@/app/ui/skeletons';
import { Suspense } from 'react';
import { fetchInvoicesPages } from '@/app/lib/data';
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Invoices',
+};
export default async function Page({
searchParams,
diff --git a/public/favicon.ico b/app/favicon.ico
similarity index 100%
rename from public/favicon.ico
rename to app/favicon.ico
diff --git a/app/layout.tsx b/app/layout.tsx
index bc3a4c8..1570232 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,5 +1,15 @@
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: {
+ template: '%s | Acme Dashboard',
+ default: 'Acme Dashboard',
+ },
+ description: 'The official Next.js Course Dashboard, built with App Router',
+ metadataBase: new URL('https://next-learn-dashboard.vercel.sh'),
+};
export default function RootLayout({
children,
diff --git a/app/lib/actions.ts b/app/lib/actions.ts
index 09d84de..05daa7b 100644
--- a/app/lib/actions.ts
+++ b/app/lib/actions.ts
@@ -4,6 +4,8 @@ import { z } from 'zod';
import { sql } from '@vercel/postgres';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
+import { signIn } from '@/auth';
+import { AuthError } from 'next-auth';
const FormSchema = z.object({
id: z.string(),
@@ -113,4 +115,23 @@ export async function deleteInvoice(id: string) {
} catch (error) {
return {message: 'Database Error: Failed to Delete Invoice.'};
}
+}
+
+export async function authenticate(
+ prevState: 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;
+ }
}
\ No newline at end of file
diff --git a/app/login/page.tsx b/app/login/page.tsx
new file mode 100644
index 0000000..a4337b6
--- /dev/null
+++ b/app/login/page.tsx
@@ -0,0 +1,22 @@
+import AcmeLogo from "@/app/ui/acme-logo";
+import LoginForm from "@/app/ui/login-form";
+import { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: 'Login | Acme Dashboard',
+};
+
+export default function LoginPage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/public/opengraph-image.png b/app/opengraph-image.png
similarity index 100%
rename from public/opengraph-image.png
rename to app/opengraph-image.png
diff --git a/app/ui/dashboard/sidenav.tsx b/app/ui/dashboard/sidenav.tsx
index 3d55b46..a04d0cc 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,11 @@ export default function SideNav() {