From 8a5e029b03ad7b43088eeb6b852d7b3b28bc4ca8 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 21 Aug 2025 23:06:12 +0000 Subject: [PATCH] fixed build --- src/app/components/portfolio/SummaryBox.tsx | 59 +++++++++++++++---- src/app/db/schema/recommendations.ts | 4 +- src/app/portfolio/[slug]/(portfolio)/page.tsx | 4 ++ src/app/portfolio/[slug]/utils.ts | 7 ++- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/app/components/portfolio/SummaryBox.tsx b/src/app/components/portfolio/SummaryBox.tsx index c92cebb7..5c6b9499 100644 --- a/src/app/components/portfolio/SummaryBox.tsx +++ b/src/app/components/portfolio/SummaryBox.tsx @@ -1,6 +1,7 @@ "use client"; import { useState } from "react"; -import { convertDaysToWorkingWeeks, formatNumber } from "@/app/utils"; +import { formatNumber } from "@/app/utils"; + interface SummaryBoxProps { scenarios: Array<{ @@ -8,6 +9,8 @@ interface SummaryBoxProps { name: string; budget: number | null; totalCost: number | null; + funding: number | null; + contingency: number | null; co2EquivalentSavings: number | null; propertyValuationIncrease: number | null; energySavings: number | null; @@ -33,6 +36,15 @@ function SummaryBox({ scenarios, numProperties }: SummaryBoxProps) { const [totalCostFormatted, setTotalCostFormatted] = useState( formatMoney(defaultScenario.totalCost) ); + const [funding, setFunding] = useState( + formatMoney(defaultScenario.funding) + ); + const [netCost, setNetCost] = useState( + formatMoney((defaultScenario.totalCost || 0) - (defaultScenario.funding || 0)) + ); + const [contingency, setContingency] = useState( + formatMoney(defaultScenario.contingency) + ); const [totalValueIncreaseFormatted, setTotalValueIncreaseFormatted] = useState(formatMoney(defaultScenario.propertyValuationIncrease)); const [energyCostSavingsFormatted, setEnergyCostSavingsFormatted] = useState( @@ -56,6 +68,13 @@ function SummaryBox({ scenarios, numProperties }: SummaryBoxProps) { setBudgetFormatted(formatBudget(selectedScenario.budget)); setTotalCostFormatted(formatMoney(selectedScenario.totalCost)); + setFunding(formatMoney(selectedScenario.funding)); + setNetCost( + formatMoney( + (selectedScenario.totalCost || 0) - (selectedScenario.funding || 0) + ) + ); + setContingency(formatMoney(selectedScenario.contingency)); setTotalValueIncreaseFormatted( formatMoney(selectedScenario.propertyValuationIncrease) ); @@ -119,18 +138,36 @@ function SummaryBox({ scenarios, numProperties }: SummaryBoxProps) { - - + + - - + + + + + + + + + + + + + - +
Total Budget{budgetFormatted}Budget{budgetFormatted}
Total Cost + Cost {totalCostFormatted}
Funding + {funding} +
Cost after funding + {netCost} +
Contingency + {contingency} +
Total properties{numProperties}{numProperties}
@@ -149,13 +186,13 @@ function SummaryBox({ scenarios, numProperties }: SummaryBoxProps) { {" "} Savings - + {co2EquivalentSavingsFormatted} Annual Energy Savings - + {energySavingsFormatted} @@ -164,19 +201,19 @@ function SummaryBox({ scenarios, numProperties }: SummaryBoxProps) {

- Financial Impact + Bills and Property Valuation

- - diff --git a/src/app/db/schema/recommendations.ts b/src/app/db/schema/recommendations.ts index e05f2e55..f27908fe 100644 --- a/src/app/db/schema/recommendations.ts +++ b/src/app/db/schema/recommendations.ts @@ -199,7 +199,7 @@ export type RecommendationType = | "extension_cavity_wall_insulation"; export type UnnestedRecommendation = { - quantity: number; + quantity: number | null; quantityUnit: string | null; estimatedCost: number; materialType: string | null; @@ -209,7 +209,7 @@ export type UnnestedRecommendation = { }; export interface PortfolioPlanRecommendation { - quantity: number; + quantity: number | null; // Allow null for cases where no materials are associated quantityUnit: string | null; estimatedCost: number; materialType: string | null; diff --git a/src/app/portfolio/[slug]/(portfolio)/page.tsx b/src/app/portfolio/[slug]/(portfolio)/page.tsx index 1f12123a..03d0425d 100644 --- a/src/app/portfolio/[slug]/(portfolio)/page.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/page.tsx @@ -44,6 +44,8 @@ export default async function Page( name: performance.name || "Default Scenario", budget: performance.budget, totalCost: performance.cost, + funding: performance.funding, + contingency: performance.contingency, co2EquivalentSavings: performance.co2EquivalentSavings, propertyValuationIncrease: performance.propertyValuationIncrease, energySavings: performance.energySavings, @@ -59,6 +61,8 @@ export default async function Page( name: "Default", budget: portfolio.budget, totalCost: portfolio.cost, + funding: 0, + contingency: 0, co2EquivalentSavings: portfolio.co2EquivalentSavings, propertyValuationIncrease: portfolio.propertyValuationIncrease, energySavings: portfolio.energySavings, diff --git a/src/app/portfolio/[slug]/utils.ts b/src/app/portfolio/[slug]/utils.ts index 40a4e4b9..545f7ac4 100644 --- a/src/app/portfolio/[slug]/utils.ts +++ b/src/app/portfolio/[slug]/utils.ts @@ -460,7 +460,7 @@ export async function getProperties( } interface UnaggregatedPortfolioPlanRecommendation { - quantity: number; + quantity: number | null; // Allow null for cases where no materials are associated quantityUnit: string | null; estimatedCost: number; materialType: string | null; @@ -496,7 +496,8 @@ function aggregateRecommendations( : new Set(), }; } else { - grouped[key].quantity += item.quantity; + // if quantity is null previously, set to 0 + grouped[key].quantity = (grouped[key].quantity ?? 0) + (item.quantity ?? 0); grouped[key].estimatedCost += item.estimatedCost; if (item.propertyId) { @@ -511,7 +512,7 @@ function aggregateRecommendations( // Round the results to 2 decimal places, compute uniquePropertyCount, and count unique measureTypes for (const key in grouped) { - grouped[key].quantity = parseFloat(grouped[key].quantity.toFixed(2)); + grouped[key].quantity = parseFloat(grouped[key].quantity?.toFixed(2) || "0.00"); grouped[key].estimatedCost = parseFloat( grouped[key].estimatedCost.toFixed(2) );
Annual Energy Bill Reduction + {energyCostSavingsFormatted}
Total Value Increase + {totalValueIncreaseFormatted}