Portfolio Dashboard
Portfolio Dashboard
The Portfolio dashboard gives landlords and property managers a unified view of all tenancies and compliance documents across their portfolio, with tiered urgency alerts and direct drill-down navigation to tenancy detail pages.
Dashboard Tabs
The dashboard is divided into five tabs:
| Tab | Description |
|---|---|
| Active Tenancies | All tenancies with a confirmed move-in date |
| Expiring Tenancies | Tenancies ending within the next 90 days, with 7-day high-urgency alerts |
| Expired Tenancies | Tenancies that have lapsed without renewal |
| Expiring Compliance | Compliance documents expiring within the next 30 days |
| Expired Compliance | Compliance documents that have already expired (tab only appears when count > 0) |
Drill-Down Navigation
Every row in every tab is clickable and navigates to the relevant tenancy detail page.
- Tenancy rows (Active, Expiring, Expired): link directly to
/dashboard/tenancies/{id}. - Compliance rows (Expiring Compliance, Expired Compliance): link to
/dashboard/tenancies/{tenancyId}when a linked active tenancy exists for the property. If no tenancy can be resolved, the row links to the tenancies list (/dashboard/tenancies).
A chevron icon (›) on the right side of each row indicates it is navigable.
Compliance Document Types
Compliance document types are displayed as human-readable labels. The following types are supported out of the box:
| Type | Displayed As |
|---|---|
gas_safety | Gas Safety Certificate |
epc | Energy Performance Certificate (EPC) |
eicr | Electrical Installation (EICR) |
hmo_licence | HMO Licence |
insurance | Property Insurance |
fire_safety | Fire Safety Certificate |
legionella | Legionella Risk Assessment |
asbestos | Asbestos Survey |
pat_testing | PAT Testing |
Any unrecognised type slug is automatically converted to title case (e.g. custom_doc → Custom Doc).
Urgency Badges
Tenancy and compliance rows display colour-coded badges based on days remaining or days overdue:
- Expiring Tenancies: tiered alerts at 90-day and 7-day thresholds.
- Expiring Compliance: alerts for documents expiring within 30 days.
- Expired rows: display an overdue badge with the number of days past expiry.
Pagination
Each tab loads up to 20 rows at a time. A Load more button appears at the bottom of a tab when additional rows are available. Clicking it fetches the next page and appends results below the existing rows.
Note (v0.1.20): A bug where paginated rows could appear duplicated on React Query refetches has been fixed. The dashboard now renders
data.itemsdirectly instead of accumulating rows in local state.
Backend: tenancyId Resolution
The expiringCompliance and expiredCompliance tRPC endpoints enrich each compliance row with a tenancyId field. This is resolved via a subquery that finds the most recently created active tenancy for the property associated with each compliance document. The front-end uses this field to construct the drill-down link.
Endpoint signatures (tRPC)
// Expiring compliance documents (within 30 days)
trpc.portfolio.expiringCompliance.useQuery({ limit: number, cursor?: string })
// Returns: { items: ComplianceRow[], nextCursor?: string }
// Expired compliance documents
trpc.portfolio.expiredCompliance.useQuery({ limit: number, cursor?: string })
// Returns: { items: ComplianceRow[], nextCursor?: string }
Where ComplianceRow includes:
interface ComplianceRow {
id: string;
documentType: string; // e.g. "gas_safety"
propertyId?: string | null;
propertyAddress?: string | null;
expiryDate?: Date | string | null;
daysRemaining?: number | null;
daysOverdue?: number | null;
urgency?: string;
tenancyId?: string | null; // Added in v0.1.20
}