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
| Annual Energy Bill Reduction |
-
+ |
{energyCostSavingsFormatted}
|
| Total Value Increase |
-
+ |
{totalValueIncreaseFormatted}
|
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)
);