feat(live): add planning fields as toggleable property columns

Surface the four planning columns from hubspot_deal_data — Planning
Authority, Designated Area, Article 4 PD Rights, Listed Building — as
optional columns in the Live Reporting properties table.

The DB columns already exist (migration 0267); this wires them through
the read path only: query mapping, HubspotDeal type, column defs, the
column-visibility toggle (hidden by default), and CSV export. Rendered
as plain text since they are text columns in HubSpot.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-13 23:10:25 +00:00
parent f801025ce3
commit 8d8d4b7fa1
9 changed files with 87 additions and 1 deletions

View file

@ -67,7 +67,11 @@ const COLUMN_LABELS: Record<string, string> = {
coordinationComments: "Coordination Comments",
dampAndMouldGrowth: "Damp and Mould Growth",
dampMouldAndRepairComments: "Damp, Mould and Repair Comments",
domnaSurveyRequested: "Domna Survey Requested"
domnaSurveyRequested: "Domna Survey Requested",
planningAuthority: "Planning Authority",
designatedArea: "Designated Area",
article4PdRights: "Article 4 PD Rights",
listedBuilding: "Listed Building",
};
type DocFilter = "all" | "has_docs" | "incomplete" | "none";
@ -114,6 +118,10 @@ export default function PropertyTable({ data, onOpenDrawer, portfolioId = "", sh
dampAndMouldGrowth: false,
dampMouldAndRepairComments: false,
domnaSurveyRequested: false,
planningAuthority: false,
designatedArea: false,
article4PdRights: false,
listedBuilding: false,
});
// Pre-filter by stage, doc status, and removal status before TanStack gets it

View file

@ -439,6 +439,54 @@ export function createPropertyTableColumns(
},
},
// ── Planning authority ───────────────────────────────────────────────
{
accessorKey: "planningAuthority",
id: "planningAuthority",
header: ({ column }) => <SortableHeader label="Planning Authority" column={column as any} />,
cell: ({ row }) => (
<span className="text-xs text-gray-600 max-w-[180px] line-clamp-2 leading-snug">
{row.original.planningAuthority ?? <span className="text-gray-300"></span>}
</span>
),
},
// ── Designated area ──────────────────────────────────────────────────
{
accessorKey: "designatedArea",
id: "designatedArea",
header: ({ column }) => <SortableHeader label="Designated Area" column={column as any} />,
cell: ({ row }) => (
<span className="text-xs text-gray-600 max-w-[180px] line-clamp-2 leading-snug">
{row.original.designatedArea ?? <span className="text-gray-300"></span>}
</span>
),
},
// ── Article 4 PD rights ──────────────────────────────────────────────
{
accessorKey: "article4PdRights",
id: "article4PdRights",
header: ({ column }) => <SortableHeader label="Article 4 PD Rights" column={column as any} />,
cell: ({ row }) => (
<span className="text-xs text-gray-600 max-w-[180px] line-clamp-2 leading-snug">
{row.original.article4PdRights ?? <span className="text-gray-300"></span>}
</span>
),
},
// ── Listed building ──────────────────────────────────────────────────
{
accessorKey: "listedBuilding",
id: "listedBuilding",
header: ({ column }) => <SortableHeader label="Listed Building" column={column as any} />,
cell: ({ row }) => (
<span className="text-xs text-gray-600 max-w-[180px] line-clamp-2 leading-snug">
{row.original.listedBuilding ?? <span className="text-gray-300"></span>}
</span>
),
},
];
if (showDocuments) {

View file

@ -73,6 +73,10 @@ export function mapDbRowToHubspotDeal(row: DealRow): HubspotDeal {
domnaSurveyDate: d.domnaSurveyDate,
batch: d.batch,
batchDescription: d.batchDescription,
planningAuthority: d.planningAuthority,
designatedArea: d.designatedArea,
article4PdRights: d.article4PdRights,
listedBuilding: d.listedBuilding,
createdAt: d.createdAt,
updatedAt: d.updatedAt,
};

View file

@ -60,6 +60,10 @@ function makeDeal(overrides: Partial<HubspotDeal> = {}): HubspotDeal {
domnaSurveyDate: null,
batch: null,
batchDescription: null,
planningAuthority: null,
designatedArea: null,
article4PdRights: null,
listedBuilding: null,
coordinationComments: null,
domnasurveyRequired: null,
createdAt: new Date(),

View file

@ -59,6 +59,10 @@ function makeDeal(overrides: Partial<ClassifiedDeal> = {}): ClassifiedDeal {
domnaSurveyDate: null,
batch: null,
batchDescription: null,
planningAuthority: null,
designatedArea: null,
article4PdRights: null,
listedBuilding: null,
coordinationComments: null,
domnasurveyRequired: null,
createdAt: new Date(),

View file

@ -59,6 +59,10 @@ function makeDeal(overrides: Partial<HubspotDeal> = {}): HubspotDeal {
domnaSurveyDate: null,
batch: null,
batchDescription: null,
planningAuthority: null,
designatedArea: null,
article4PdRights: null,
listedBuilding: null,
coordinationComments: null,
domnasurveyRequired: null,
createdAt: new Date(),

View file

@ -30,6 +30,10 @@ export const PROPERTY_CSV_FIELDS: PropertyCsvField[] = [
{ key: "dampMouldFlag", label: "Damp and Mould Growth" },
{ key: "dampMouldAndRepairComments", label: "Damp Mould and Repair Comments" },
{ key: "domnasurveyRequired", label: "Domna Survey Required" },
{ key: "planningAuthority", label: "Planning Authority" },
{ key: "designatedArea", label: "Designated Area" },
{ key: "article4PdRights", label: "Article 4 PD Rights" },
{ key: "listedBuilding", label: "Listed Building" },
];
export function escapeCsvCell(value: unknown): string {

View file

@ -66,6 +66,10 @@ function makeDeal(overrides: Partial<HubspotDeal> = {}): HubspotDeal {
domnaSurveyDate: null,
batch: null,
batchDescription: null,
planningAuthority: null,
designatedArea: null,
article4PdRights: null,
listedBuilding: null,
coordinationComments: null,
domnasurveyRequired: null,
createdAt: new Date(),

View file

@ -71,6 +71,12 @@ export type HubspotDeal = {
batch: string | null;
batchDescription: string | null;
// ── Planning fields (issue: extra PM columns) ─────────────────────────
planningAuthority: string | null;
designatedArea: string | null;
article4PdRights: string | null;
listedBuilding: string | null;
createdAt: Date;
updatedAt: Date;
};