RCA: the dueDate >= cutoff filter was incorrectly excluding open tasks more than 7 days overdue. The cutoff now only applies to terminal tasks (COMPLETED/CANCELLED/NA) to suppress ancient clutter. Open tasks of any age are always returned. Fixes tasks/page.tsx and clients/[id]/page.tsx.
5.4 KiB
5.4 KiB
Horizon — Architecture
Overview
Next.js 15 App Router application. All pages are server or client components under src/app/(dashboard)/. Data access goes exclusively through Next.js API route handlers (src/app/api/), which use Prisma to talk to Postgres.
Directory map
src/
├── app/
│ ├── (dashboard)/ # Authenticated layout + all pages
│ │ ├── layout.tsx # Shell: sidebar, nav, session guard
│ │ ├── dashboard/ # Home/summary page
│ │ ├── clients/ # Client list + detail ([id]/)
│ │ ├── policies/ # Policy list + detail ([id]/)
│ │ ├── tasks/ # Task list (page-client.tsx) + detail ([id]/)
│ │ ├── admin/ # Admin-only pages (users, roles, designations, sync)
│ │ └── manager/ # Manager pages (templates, metrics)
│ ├── api/ # API route handlers
│ │ ├── auth/ # NextAuth endpoints
│ │ ├── clients/ # CRUD + notes, contacts, members
│ │ ├── tasks/ # CRUD + notes, assignments
│ │ ├── policies/ # CRUD + policy groups
│ │ ├── policy-groups/ # Renewal group management
│ │ ├── sync/ # Shape import sync
│ │ ├── users/ # User management
│ │ ├── roles/ # Role management
│ │ ├── templates/ # Task templates
│ │ ├── designations/ # Client designations
│ │ ├── metrics/ # Dashboard metrics
│ │ ├── cron/ # Scheduled jobs (notifications, etc.)
│ │ └── dashboard/ # Dashboard summary data
│ ├── auth/ # Sign-in / error pages (unauthenticated)
│ └── layout.tsx # Root layout (providers, theme)
├── components/
│ ├── ui/ # shadcn/ui primitives (Button, Dialog, Input, etc.)
│ ├── clients/ # Client-specific components
│ ├── tasks/ # Task card, task edit modal
│ ├── policies/ # Policy components
│ ├── renewal-groups/ # Policy group components
│ ├── notifications/ # Notification bell + panel
│ ├── admin/ # Admin UI components
│ ├── manager/ # Manager UI components
│ ├── layout/ # Sidebar, header, nav
│ └── providers/ # SessionProvider, ThemeProvider
├── lib/
│ ├── auth.ts # NextAuth config (Entra ID + local credentials)
│ ├── db.ts # Prisma client singleton
│ ├── entra.ts # Microsoft Graph API helpers
│ ├── utils.ts # Shared utilities (cn(), formatters)
│ ├── hooks/ # Custom React hooks
│ ├── sync/ # Shape import sync logic
│ ├── shape-import/ # Shape file parsing
│ └── tasks/ # Task business logic helpers
├── middleware.ts # Auth middleware (protects all dashboard routes)
└── types/ # Shared TypeScript types
Data models (key entities)
| Model | Description |
|---|---|
User |
Staff accounts; synced from Entra ID |
Role / UserRole |
RBAC roles (Admin, Manager, AE, Claims, etc.) |
Client |
Insurance clients; synced from AMS via Shape import |
ClientContact |
Contacts per client |
ClientMember |
Which staff are assigned to a client |
Designation |
Client classification labels (color-coded) |
Policy |
Insurance policies linked to clients |
PolicyGroup |
Renewal groups grouping policies |
Task |
Work items linked to client/policy/policy group |
TaskAssignment |
Which users are assigned to a task |
TaskNote |
Notes on tasks with status snapshots |
TaskTemplate |
Reusable task templates for automation |
SyncLog |
History of Shape import runs |
AuditLog |
Field-level change tracking |
Notification |
In-app notifications per user |
ShapeImportRun |
Shape file import run tracking |
Auth flow
middleware.tschecks NextAuth session on every request under/(dashboard).- Unauthenticated users are redirected to
/auth/signin. - Production: Microsoft Entra ID OAuth. Entra group memberships map to Horizon roles via
EntraGroupRoleMapping. - Dev: local credentials provider (see
src/lib/auth.ts).
Task completion flow
- UI:
src/app/(dashboard)/tasks/page-client.tsx(task detail page) andsrc/components/tasks/task-card.tsx(list card) - Dialog collects: completion date, ImageRight filing confirmation, optional reminder date
PATCH /api/tasks/[id]setscompletedAt,completedBy,imageRightFiled,reminderDate
Sync / data import
- Client and policy data synced from Zywave/Applied AMS via Shape file import
- Shape import logic:
src/lib/shape-import/andsrc/lib/sync/ - Triggered manually from Admin UI or via scheduled cron (
src/app/api/cron/) - Sync history tracked in
SyncLogandAuditLog
Deployment
- Production: Docker Compose at
/opt/stacks/horizon - Image built from this directory's
Dockerfile(Next.js standalone output) - DB: Postgres 17 in
horizon-dbcontainer - Reverse proxy: Pangolin → https://horizon.seubert.cloud