From 32dc2d3ee57bbe455fc4bfc392e69ff918a296db Mon Sep 17 00:00:00 2001 From: Chandler Copeland Date: Thu, 19 Mar 2026 13:39:25 -0600 Subject: [PATCH] feat(01-02): build agent portal layout, dashboard stub, and logout mechanism - LogoutButton: client component with server action calling signOut to ?signed_out=1 - AgentLayout: defense-in-depth auth() check, header with email and sign-out button - DashboardPage: belt-and-suspenders auth() check, welcome message with agent email - HomePage: updated to Teressa Copeland Homes placeholder (Phase 2 marketing site) - npm run build and npx tsc --noEmit both pass with zero errors --- .../src/app/agent/dashboard/page.tsx | 17 +++++ .../src/app/agent/layout.tsx | 26 +++++++ teressa-copeland-homes/src/app/page.tsx | 70 +++---------------- .../src/components/ui/LogoutButton.tsx | 19 +++++ 4 files changed, 70 insertions(+), 62 deletions(-) create mode 100644 teressa-copeland-homes/src/app/agent/dashboard/page.tsx create mode 100644 teressa-copeland-homes/src/app/agent/layout.tsx create mode 100644 teressa-copeland-homes/src/components/ui/LogoutButton.tsx diff --git a/teressa-copeland-homes/src/app/agent/dashboard/page.tsx b/teressa-copeland-homes/src/app/agent/dashboard/page.tsx new file mode 100644 index 0000000..c07d97e --- /dev/null +++ b/teressa-copeland-homes/src/app/agent/dashboard/page.tsx @@ -0,0 +1,17 @@ +import { auth } from "@/lib/auth"; +import { redirect } from "next/navigation"; + +export default async function DashboardPage() { + // Defense-in-depth session check (layout also checks, this is belt-and-suspenders) + const session = await auth(); + if (!session) redirect("/agent/login"); + + return ( +
+

Dashboard

+

+ Welcome back, {session.user?.email}. Portal content coming in Phase 3. +

+
+ ); +} diff --git a/teressa-copeland-homes/src/app/agent/layout.tsx b/teressa-copeland-homes/src/app/agent/layout.tsx new file mode 100644 index 0000000..a521b11 --- /dev/null +++ b/teressa-copeland-homes/src/app/agent/layout.tsx @@ -0,0 +1,26 @@ +import { auth } from "@/lib/auth"; +import { redirect } from "next/navigation"; +import { LogoutButton } from "@/components/ui/LogoutButton"; + +export default async function AgentLayout({ + children, +}: { + children: React.ReactNode; +}) { + // Defense-in-depth: middleware handles most cases, this catches edge cases + const session = await auth(); + if (!session) redirect("/agent/login"); + + return ( +
+
+ Agent Portal +
+ {session.user?.email} + +
+
+
{children}
+
+ ); +} diff --git a/teressa-copeland-homes/src/app/page.tsx b/teressa-copeland-homes/src/app/page.tsx index 3f36f7c..098c316 100644 --- a/teressa-copeland-homes/src/app/page.tsx +++ b/teressa-copeland-homes/src/app/page.tsx @@ -1,65 +1,11 @@ -import Image from "next/image"; - -export default function Home() { +export default function HomePage() { 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 - -
-
-
+
+
+

Teressa Copeland Homes

+

Real estate expertise for Utah home buyers and sellers.

+

Marketing site coming in Phase 2.

+
+
); } diff --git a/teressa-copeland-homes/src/components/ui/LogoutButton.tsx b/teressa-copeland-homes/src/components/ui/LogoutButton.tsx new file mode 100644 index 0000000..9e9a1c9 --- /dev/null +++ b/teressa-copeland-homes/src/components/ui/LogoutButton.tsx @@ -0,0 +1,19 @@ +import { signOut } from "@/lib/auth"; + +async function logoutAction() { + "use server"; + await signOut({ redirectTo: "/agent/login?signed_out=1" }); +} + +export function LogoutButton() { + return ( +
+ +
+ ); +}