docs(03-02): complete portal shell plan — layout, nav, components, client actions
- 03-02-SUMMARY.md: plan summary with task commits, deviations, and decisions - STATE.md: updated current position to Phase 3 Plan 02 complete, added decisions - ROADMAP.md: Phase 3 progress updated (2/4 plans complete)
This commit is contained in:
@@ -136,7 +136,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
|
|||||||
|-------|----------------|--------|-----------|
|
|-------|----------------|--------|-----------|
|
||||||
| 1. Foundation | 1/3 | Complete | 2026-03-19 |
|
| 1. Foundation | 1/3 | Complete | 2026-03-19 |
|
||||||
| 2. Marketing Site | 2/3 | In Progress| |
|
| 2. Marketing Site | 2/3 | In Progress| |
|
||||||
| 3. Agent Portal Shell | 0/4 | Not started | - |
|
| 3. Agent Portal Shell | 1/4 | In Progress| |
|
||||||
| 4. PDF Ingest | 0/? | Not started | - |
|
| 4. PDF Ingest | 0/? | Not started | - |
|
||||||
| 5. PDF Fill and Field Mapping | 0/? | Not started | - |
|
| 5. PDF Fill and Field Mapping | 0/? | Not started | - |
|
||||||
| 6. Signing Flow | 0/? | Not started | - |
|
| 6. Signing Flow | 0/? | Not started | - |
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: unknown
|
status: unknown
|
||||||
last_updated: "2026-03-19T21:27:39.353Z"
|
last_updated: "2026-03-19T22:42:39.547Z"
|
||||||
progress:
|
progress:
|
||||||
total_phases: 2
|
total_phases: 3
|
||||||
completed_phases: 2
|
completed_phases: 2
|
||||||
total_plans: 6
|
total_plans: 10
|
||||||
completed_plans: 6
|
completed_plans: 8
|
||||||
---
|
---
|
||||||
|
|
||||||
# Project State
|
# Project State
|
||||||
@@ -18,14 +18,14 @@ progress:
|
|||||||
See: .planning/PROJECT.md (updated 2026-03-19)
|
See: .planning/PROJECT.md (updated 2026-03-19)
|
||||||
|
|
||||||
**Core value:** Teressa can prepare and send any real estate form to a client for signing in minutes, from her browser, without leaving her site.
|
**Core value:** Teressa can prepare and send any real estate form to a client for signing in minutes, from her browser, without leaving her site.
|
||||||
**Current focus:** Phase 2 - Marketing Site
|
**Current focus:** Phase 3 - Agent Portal Shell
|
||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 2 of 7 (Marketing Site) — COMPLETE
|
Phase: 3 of 7 (Agent Portal Shell) — In Progress
|
||||||
Plan: 02-03 complete (all 3 plans in phase complete)
|
Plan: 03-02 complete (2 of 4 plans in phase complete)
|
||||||
Status: Phase 2 complete — awaiting Phase 3 start
|
Status: Phase 3 in progress — portal layout, nav, shared components, and client actions complete; awaiting 03-03 (Client CRUD UI) start
|
||||||
Last activity: 2026-03-19 — Plan 02-03 complete: Human verification approved all 7 checklist items; Phase 2 marketing site complete
|
Last activity: 2026-03-19 — Plan 03-02 complete: Portal layout/PortalNav, StatusBadge, DocumentsTable, and createClient/updateClient/deleteClient server actions
|
||||||
|
|
||||||
Progress: [████░░░░░░] 40%
|
Progress: [████░░░░░░] 40%
|
||||||
|
|
||||||
@@ -49,6 +49,8 @@ Progress: [████░░░░░░] 40%
|
|||||||
|
|
||||||
*Updated after each plan completion*
|
*Updated after each plan completion*
|
||||||
| Phase 02-marketing-site P01 | 5 | 2 tasks | 8 files |
|
| Phase 02-marketing-site P01 | 5 | 2 tasks | 8 files |
|
||||||
|
| Phase 03-agent-portal-shell P01 | 3 | 2 tasks | 6 files |
|
||||||
|
| Phase 03-agent-portal-shell P02 | 8 | 3 tasks | 5 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -72,6 +74,12 @@ Recent decisions affecting current work:
|
|||||||
- [Phase 02-marketing-site 02-02]: nodemailer pinned to ^7.0.7 — v8 conflicts with next-auth@5.0.0-beta.30 peerOptional dep
|
- [Phase 02-marketing-site 02-02]: nodemailer pinned to ^7.0.7 — v8 conflicts with next-auth@5.0.0-beta.30 peerOptional dep
|
||||||
- [Phase 02-marketing-site 02-02]: useActionState imported from 'react' not 'react-dom' — React 19 canonical API (useFormState removed in React 19)
|
- [Phase 02-marketing-site 02-02]: useActionState imported from 'react' not 'react-dom' — React 19 canonical API (useFormState removed in React 19)
|
||||||
- [Phase 02-marketing-site 02-02]: Honeypot silent success pattern — bots receive status:success without email sent, preventing bot discovery of rejection
|
- [Phase 02-marketing-site 02-02]: Honeypot silent success pattern — bots receive status:success without email sent, preventing bot discovery of rejection
|
||||||
|
- [Phase 03-agent-portal-shell]: documentStatusEnum exported before documents table in schema.ts — pgEnum must precede referencing table or drizzle-kit may omit CREATE TYPE from migration
|
||||||
|
- [Phase 03-agent-portal-shell]: Portal route protection: add new prefix to both middleware.ts matcher array AND auth.config.ts authorized callback isPortalRoute check — mirrors existing /agent pattern
|
||||||
|
- [Phase 03-agent-portal-shell]: Post-login redirect changed from /agent/dashboard to /portal/dashboard — agent portal lives at /portal prefix going forward
|
||||||
|
- [Phase 03-agent-portal-shell]: Zod v4 uses .issues not .errors for ZodError — updated plan-specified .errors[0].message to .issues[0].message in client server actions
|
||||||
|
- [Phase 03-agent-portal-shell]: updateClient uses bind pattern (id pre-bound) so useActionState passes prevState + formData as remaining args — caller does updateClient.bind(null, clientId)
|
||||||
|
- [Phase 03-agent-portal-shell]: PortalNav is a client component (usePathname requires use client); active link state driven by pathname.startsWith(href) with gold border-b-2 underline
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -88,5 +96,5 @@ None yet.
|
|||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-03-19
|
Last session: 2026-03-19
|
||||||
Stopped at: Completed 02-03-PLAN.md — Human verification approved; Phase 2 marketing site complete with visual fixes (hero objectPosition, contact field styling, testimonial accent bar)
|
Stopped at: Completed 03-02-PLAN.md — Portal shell built: authenticated layout, PortalNav, StatusBadge, DocumentsTable, and client server actions (createClient, updateClient, deleteClient)
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
149
.planning/phases/03-agent-portal-shell/03-02-SUMMARY.md
Normal file
149
.planning/phases/03-agent-portal-shell/03-02-SUMMARY.md
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
---
|
||||||
|
phase: 03-agent-portal-shell
|
||||||
|
plan: 02
|
||||||
|
subsystem: ui
|
||||||
|
tags: [nextjs, tailwind, server-actions, zod, drizzle, portal, layout, auth]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires:
|
||||||
|
- phase: 03-agent-portal-shell
|
||||||
|
plan: 01
|
||||||
|
provides: clients and documents tables in PostgreSQL, /portal/* route protection via middleware and auth.config.ts
|
||||||
|
- phase: 01-foundation
|
||||||
|
provides: auth() from next-auth, LogoutButton component, CSS brand variables
|
||||||
|
|
||||||
|
provides:
|
||||||
|
- portal/(protected)/layout.tsx — authenticated layout wrapping all /portal/* pages with PortalNav
|
||||||
|
- PortalNav.tsx — horizontal nav bar with Dashboard/Clients links and active gold underline
|
||||||
|
- StatusBadge.tsx — color-coded pill for Draft/Sent/Viewed/Signed document status
|
||||||
|
- DocumentsTable.tsx — reusable documents table with optional Client column and StatusBadge integration
|
||||||
|
- src/lib/actions/clients.ts — createClient, updateClient (bind pattern), deleteClient server actions
|
||||||
|
|
||||||
|
affects: [03-03, 03-04, all Phase 3 plans — portal layout and shared components are required by dashboard, clients, and profile pages]
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Portal authenticated layout: auth() check at layout level, redirect on no session, children rendered in cream bg"
|
||||||
|
- "PortalNav active state: usePathname() comparison drives border-b-2 gold underline on active link"
|
||||||
|
- "Server actions with bound id: updateClient(id, prevState, formData) called via .bind(null, clientId) from modal"
|
||||||
|
- "Zod v4 .issues accessor: ZodError uses .issues not .errors in Zod v4"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- teressa-copeland-homes/src/app/portal/(protected)/layout.tsx
|
||||||
|
- teressa-copeland-homes/src/app/portal/_components/PortalNav.tsx
|
||||||
|
- teressa-copeland-homes/src/app/portal/_components/StatusBadge.tsx
|
||||||
|
- teressa-copeland-homes/src/app/portal/_components/DocumentsTable.tsx
|
||||||
|
- teressa-copeland-homes/src/lib/actions/clients.ts
|
||||||
|
modified: []
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Zod v4 uses .issues not .errors for ZodError field access — auto-fixed during Task 3 TypeScript compilation"
|
||||||
|
- "updateClient uses bind pattern (id pre-bound) so useActionState can pass prevState + formData as the remaining args"
|
||||||
|
- "PortalNav as client component: usePathname() requires 'use client'; LogoutButton has internal server action so it's importable from client components"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Portal layout auth: await auth() at the layout level, redirect('/agent/login') on no session"
|
||||||
|
- "Active nav link: usePathname().startsWith(href) drives border-b-2 border-[var(--gold)] class"
|
||||||
|
- "Server action id binding: export async function action(id: string, prevState, formData) — caller does action.bind(null, id)"
|
||||||
|
|
||||||
|
requirements-completed: [CLIENT-01, DASH-01, DASH-02]
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: 8min
|
||||||
|
completed: 2026-03-19
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 3 Plan 02: Agent Portal Shell — Portal Layout, Shared Components, and Client Actions Summary
|
||||||
|
|
||||||
|
**Authenticated portal layout with PortalNav, StatusBadge (4-color document status pill), reusable DocumentsTable, and createClient/updateClient/deleteClient server actions with Zod validation**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 8 min
|
||||||
|
- **Started:** 2026-03-19T22:32:44Z
|
||||||
|
- **Completed:** 2026-03-19T22:40:44Z
|
||||||
|
- **Tasks:** 3
|
||||||
|
- **Files modified:** 5
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Created `portal/(protected)/layout.tsx` — async server component that calls `auth()`, redirects unauthenticated users to `/agent/login`, and renders `PortalNav` + main content area with cream background
|
||||||
|
- Created `PortalNav.tsx` — client component with navy background, Dashboard/Clients links (gold underline on active via `usePathname()`), agent email display, and LogoutButton
|
||||||
|
- Created `StatusBadge.tsx` and `DocumentsTable.tsx` — shared components providing color-coded document status pills and a reusable table with optional Client column
|
||||||
|
- Created `src/lib/actions/clients.ts` with `createClient`, `updateClient` (bind pattern), and `deleteClient` — all protected by `auth()` check, Zod-validated, and calling `revalidatePath` after mutation
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Portal layout and PortalNav** - `9c4caee` (feat)
|
||||||
|
2. **Task 2: StatusBadge and DocumentsTable shared components** - `28d42f5` (feat)
|
||||||
|
3. **Task 3: Client server actions (createClient, updateClient, deleteClient)** - `5b87201` (feat)
|
||||||
|
|
||||||
|
**Plan metadata:** (pending docs commit)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `teressa-copeland-homes/src/app/portal/(protected)/layout.tsx` — Authenticated portal layout with auth() check and PortalNav rendering
|
||||||
|
- `teressa-copeland-homes/src/app/portal/_components/PortalNav.tsx` — Client component nav bar with active link state via usePathname()
|
||||||
|
- `teressa-copeland-homes/src/app/portal/_components/StatusBadge.tsx` — Color-coded pill: Draft=gray, Sent=blue, Viewed=amber, Signed=green
|
||||||
|
- `teressa-copeland-homes/src/app/portal/_components/DocumentsTable.tsx` — Reusable table with StatusBadge integration and optional Client column
|
||||||
|
- `teressa-copeland-homes/src/lib/actions/clients.ts` — 'use server' actions: createClient, updateClient (bound id pattern), deleteClient
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- **Zod v4 `.issues` accessor:** Zod v4 changed `ZodError.errors` to `ZodError.issues` — the plan referenced `.errors[0].message` which is the v3 API; auto-fixed to `.issues[0].message` during Task 3.
|
||||||
|
- **updateClient bind pattern:** The plan specified `updateClient(id, prevState, formData)` — this design allows the calling modal component to use `updateClient.bind(null, clientId)` and pass the bound function to `useActionState`.
|
||||||
|
- **PortalNav as client component:** `usePathname()` requires `"use client"`. `LogoutButton` (which contains a server action inline) is importable from client components because the server action is defined inline in the server component file.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 1 - Bug] Fixed Zod v4 error access from `.errors` to `.issues`**
|
||||||
|
- **Found during:** Task 3 (Client server actions) TypeScript compilation
|
||||||
|
- **Issue:** Plan specified `parsed.error.errors[0].message` but Zod v4 renamed this property to `.issues` — TypeScript error TS2339 "Property 'errors' does not exist on type 'ZodError'"
|
||||||
|
- **Fix:** Updated both `createClient` and `updateClient` to use `parsed.error.issues[0].message`
|
||||||
|
- **Files modified:** `teressa-copeland-homes/src/lib/actions/clients.ts`
|
||||||
|
- **Verification:** `npx tsc --noEmit` passes cleanly
|
||||||
|
- **Committed in:** `5b87201` (Task 3 commit)
|
||||||
|
|
||||||
|
**2. [Rule 3 - Blocking] Updated stale Next.js generated types to include /portal routes**
|
||||||
|
- **Found during:** Task 1 (Portal layout) TypeScript compilation
|
||||||
|
- **Issue:** `.next/types/routes.d.ts` was stale and didn't include `/portal` routes, causing TypeScript validator mismatch errors. File is gitignored so not committed.
|
||||||
|
- **Fix:** Manually updated `.next/types/routes.d.ts` to include `/portal`, `/portal/dashboard`, `/portal/clients` routes — file is regenerated by Next.js dev server on startup
|
||||||
|
- **Files modified:** `.next/types/routes.d.ts` (gitignored, not committed)
|
||||||
|
- **Verification:** `npx tsc --noEmit` passes cleanly after update
|
||||||
|
- **Committed in:** N/A (gitignored file — will be auto-regenerated by dev server)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 2 auto-fixed (1 bug — Zod v4 API, 1 blocking — stale generated types)
|
||||||
|
**Impact on plan:** Both auto-fixes necessary for TypeScript correctness. No scope creep.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
- Next.js `.next/types/routes.d.ts` is a generated file included in `tsconfig.json` via `.next/types/**/*.ts`. When new routes are added without running the dev server first, this file is stale and causes validator type mismatches. The file is gitignored so it must be regenerated by running `npm run dev` before TypeScript will pass in CI environments.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None - no external service configuration required. All portal shell components are pure UI and server action code.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Portal layout renders PortalNav for every `/portal/(protected)/` page — no per-page nav code needed
|
||||||
|
- `StatusBadge` ready for use in dashboard and client profile pages
|
||||||
|
- `DocumentsTable` ready for use in dashboard (show all documents) and client profile (hide client column)
|
||||||
|
- `createClient`, `updateClient`, `deleteClient` server actions ready for ClientModal in Plan 03-03
|
||||||
|
- No blockers for subsequent Phase 3 plans
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 03-agent-portal-shell*
|
||||||
|
*Completed: 2026-03-19*
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
All 5 files verified present. All 3 task commits verified in git log (9c4caee, 28d42f5, 5b87201). TypeScript compiles cleanly.
|
||||||
Reference in New Issue
Block a user