From 74554dafade09cce769b94283fbc2123e014a2d4 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 21 Apr 2026 15:46:47 +0000 Subject: [PATCH 1/3] improving UI for scolldown when adding extra columns on property table --- .../your-projects/live/PropertyTable.tsx | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx index d91ff6d..a746fe6 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx @@ -317,21 +317,26 @@ export default function PropertyTable({ data, onOpenDrawer, onOpenDetail, showDo Columns - - + + Toggle columns - {toggleableColumns.map((col) => ( - col.toggleVisibility(val)} - className="text-sm" - > - {COLUMN_LABELS[col.id] ?? col.id} - - ))} +
+
+ {toggleableColumns.map((col) => ( + col.toggleVisibility(val)} + className="text-sm" + > + {COLUMN_LABELS[col.id] ?? col.id} + + ))} +
+
+
From 4bbd973b6ba494899650e1776b1cc20fa63db469 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 21 Apr 2026 17:47:21 +0000 Subject: [PATCH 2/3] added filtering to filter on lodged rating rather than modelled --- .../scenario/[scenarioId]/metrics/route.ts | 27 +++++++- .../reporting/ReportingClientArea.tsx | 13 +++- .../ReportingFunctionalityButtons.tsx | 69 +++++++++++++++++-- 3 files changed, 98 insertions(+), 11 deletions(-) diff --git a/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts b/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts index ce373b6..5760a33 100644 --- a/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts +++ b/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts @@ -69,6 +69,8 @@ export async function GET( const sid = BigInt(scenarioId); const hideNonCompliant = request.nextUrl.searchParams.get("hideNonCompliant") === "true"; + const useOriginalBaseline = + request.nextUrl.searchParams.get("useOriginalBaseline") === "true"; /* ---------------------------------------------------------- Query 0 — scenario definition @@ -129,7 +131,12 @@ export async function GET( END )::float AS total_sap_uplift FROM latest_plans lp - JOIN property p ON p.id = lp.property_id; + JOIN property p ON p.id = lp.property_id + WHERE ( + ${useOriginalBaseline} = false + OR ${minSap}::float IS NULL + OR p.original_sap_points < ${minSap}::float + ); `); const scenarioAgg = scenarioMetricsResult.rows[0] as ScenarioAggregates; @@ -162,8 +169,14 @@ export async function GET( COALESCE(fp.total_uplift, 0) )::float AS total_funding FROM latest_plans lp + JOIN property p ON p.id = lp.property_id LEFT JOIN funding_package fp ON fp.plan_id = lp.id - WHERE lp.cost_of_works > 0; + WHERE lp.cost_of_works > 0 + AND ( + ${useOriginalBaseline} = false + OR ${minSap}::float IS NULL + OR p.original_sap_points < ${minSap}::float + ); `); const upgraded = upgradedResult.rows[0] as UpgradedAggregates; @@ -223,6 +236,11 @@ export async function GET( AND plan.post_sap_points >= ${minSap}::float ) ) + AND ( + ${useOriginalBaseline} = false + OR ${minSap}::float IS NULL + OR p.original_sap_points < ${minSap}::float + ) ORDER BY created_at DESC LIMIT 1 ) lp ON true @@ -256,6 +274,11 @@ export async function GET( AND plan.post_sap_points >= ${minSap}::float ) ) + AND ( + ${useOriginalBaseline} = false + OR ${minSap}::float IS NULL + OR p.original_sap_points < ${minSap}::float + ) ORDER BY created_at DESC LIMIT 1 ) lp ON true diff --git a/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx b/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx index 47dfeaf..8d89323 100644 --- a/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx @@ -39,13 +39,16 @@ async function fetchScenarioReport({ portfolioId, scenarioId, hideNonCompliant, + useOriginalBaseline, }: { portfolioId: number; scenarioId: number | "default"; hideNonCompliant: boolean; + useOriginalBaseline: boolean; }) { const params = new URLSearchParams({ hideNonCompliant: String(hideNonCompliant), + useOriginalBaseline: String(useOriginalBaseline), }); const path = `/api/portfolio/${portfolioId}/scenario/${scenarioId}/metrics`; @@ -89,6 +92,8 @@ export function ReportingClientArea({ const [measuresOpen, setMeasuresOpen] = useState(false); const [appliedHideNonCompliant, setAppliedHideNonCompliant] = useState(false); + const [appliedUseOriginalBaseline, setAppliedUseOriginalBaseline] = + useState(false); const [showToast, setShowToast] = useState(false); const drawerOpen = Boolean(selectedScenarioId); @@ -107,12 +112,14 @@ export function ReportingClientArea({ portfolioId, selectedScenarioId, appliedHideNonCompliant, + appliedUseOriginalBaseline, ], queryFn: () => fetchScenarioReport({ portfolioId, scenarioId: selectedScenarioId!, hideNonCompliant: appliedHideNonCompliant, + useOriginalBaseline: appliedUseOriginalBaseline, }), enabled: selectedScenarioId !== null, // only run when scenario selected or default selected keepPreviousData: true, // keep showing old data while loading new scenario or applying filter @@ -238,12 +245,14 @@ export function ReportingClientArea({ { - setAppliedHideNonCompliant(value); + onApply={async ({ hideNonCompliant, useOriginalBaseline }) => { + setAppliedHideNonCompliant(hideNonCompliant); + setAppliedUseOriginalBaseline(useOriginalBaseline); }} /> diff --git a/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingFunctionalityButtons.tsx b/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingFunctionalityButtons.tsx index 40ad968..9a70414 100644 --- a/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingFunctionalityButtons.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingFunctionalityButtons.tsx @@ -13,33 +13,45 @@ export interface ReportingFunctionalityButtonsProps { /** Currently applied value */ hideNonCompliant: boolean; + /** Currently applied value */ + useOriginalBaseline: boolean; + /** * Explicit user action. * Parent decides what "apply" means (refetch, mutate, etc). */ - onApply: (value: boolean) => Promise | void; + onApply: (options: { + hideNonCompliant: boolean; + useOriginalBaseline: boolean; + }) => Promise | void; disabled?: boolean; - /* Whether hideNonCompliant filter is available */ + /* Whether filters are available (only for specific non-default scenarios) */ canFilterNonCompliant?: boolean; } export function ReportingFunctionalityButtons({ hideNonCompliant, + useOriginalBaseline, onApply, disabled = false, canFilterNonCompliant = true, }: ReportingFunctionalityButtonsProps) { const [draftHideNonCompliant, setDraftHideNonCompliant] = useState(hideNonCompliant); + const [draftUseOriginalBaseline, setDraftUseOriginalBaseline] = + useState(useOriginalBaseline); const [isApplying, setIsApplying] = useState(false); async function handleApply() { try { setIsApplying(true); - await onApply(draftHideNonCompliant); + await onApply({ + hideNonCompliant: draftHideNonCompliant, + useOriginalBaseline: draftUseOriginalBaseline, + }); } finally { setIsApplying(false); } @@ -50,7 +62,8 @@ export function ReportingFunctionalityButtons({ // reset the filter and trigger the fetch setIsApplying(true); setDraftHideNonCompliant(false); - await onApply(false); + setDraftUseOriginalBaseline(false); + await onApply({ hideNonCompliant: false, useOriginalBaseline: false }); } finally { setIsApplying(false); } @@ -61,6 +74,7 @@ export function ReportingFunctionalityButtons({ onOpenChange={(open) => { if (open) { setDraftHideNonCompliant(hideNonCompliant); + setDraftUseOriginalBaseline(useOriginalBaseline); } }} > @@ -72,7 +86,7 @@ export function ReportingFunctionalityButtons({ className={` relative flex items-center gap-2 ${ - hideNonCompliant + hideNonCompliant || useOriginalBaseline ? "border-brandmidblue/40 bg-brandlightblue/40" : "" } @@ -81,7 +95,7 @@ export function ReportingFunctionalityButtons({ {/* Filter icon */} Filter options - {hideNonCompliant && ( + {(hideNonCompliant || useOriginalBaseline) && ( )} @@ -140,6 +154,47 @@ export function ReportingFunctionalityButtons({ + {/* Use original SAP points */} +
+ + setDraftUseOriginalBaseline(Boolean(checked)) + } + className="mt-1" + /> + + +
+ {/* Actions */}