mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
Added reactivity for total cost
This commit is contained in:
parent
2b3e8c7211
commit
bc8e9f1ebe
3 changed files with 38 additions and 84 deletions
|
|
@ -6,6 +6,8 @@ import { Dialog, Transition } from "@headlessui/react";
|
|||
import RecommendationTable from "@/app/components/building-passport/RecommendationTable";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { Checkbox } from "@/app/shadcn_components/ui/checkbox";
|
||||
import { CostMap } from "@/types/recommendations";
|
||||
import { sumCostMap } from "@/app/portfolio/[slug]/building-passport/[propertyId]/recommendations/utils";
|
||||
|
||||
export const uvalueColumns: ColumnDef<ComponentRecommendation>[] = [
|
||||
{
|
||||
|
|
@ -49,12 +51,20 @@ export function RecommendationModal({
|
|||
setIsOpen,
|
||||
recommendationData,
|
||||
setCardComponent,
|
||||
setCostMap,
|
||||
costMap,
|
||||
totalEstimatedCost,
|
||||
setTotalEstimatedCost,
|
||||
}: {
|
||||
title: string;
|
||||
isOpen: boolean;
|
||||
setIsOpen: (isOpen: boolean) => void;
|
||||
recommendationData: ComponentRecommendation[];
|
||||
setCardComponent: Dispatch<SetStateAction<ComponentRecommendation>>;
|
||||
setCostMap: Dispatch<SetStateAction<CostMap>>;
|
||||
costMap: CostMap;
|
||||
totalEstimatedCost: number;
|
||||
setTotalEstimatedCost: Dispatch<SetStateAction<number>>;
|
||||
}) {
|
||||
const [saveButtonDisabled, setSaveButtonDisabled] = useState(true);
|
||||
|
||||
|
|
@ -85,6 +95,14 @@ export function RecommendationModal({
|
|||
setCardComponent(recommendationData[newIndex]);
|
||||
// Set the default index
|
||||
setDefaultRowIndex(newIndex);
|
||||
// Update the cost map
|
||||
const newCostMap = {
|
||||
...costMap,
|
||||
[title]: recommendationData[newIndex].estimatedCost,
|
||||
};
|
||||
setCostMap(newCostMap);
|
||||
// update the cost sum
|
||||
setTotalEstimatedCost(sumCostMap(newCostMap));
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -174,9 +192,17 @@ const noSelectionStyling =
|
|||
export default function RecommendationCard({
|
||||
componentType,
|
||||
recommendationData,
|
||||
setCostMap,
|
||||
costMap,
|
||||
totalEstimatedCost,
|
||||
setTotalEstimatedCost,
|
||||
}: {
|
||||
componentType: string;
|
||||
recommendationData: ComponentRecommendation[];
|
||||
setCostMap: Dispatch<SetStateAction<CostMap>>;
|
||||
costMap: CostMap;
|
||||
totalEstimatedCost: number;
|
||||
setTotalEstimatedCost: Dispatch<SetStateAction<number>>;
|
||||
}) {
|
||||
const defaultComponent = recommendationData.find(
|
||||
(rec: ComponentRecommendation) => rec.default
|
||||
|
|
@ -240,6 +266,10 @@ export default function RecommendationCard({
|
|||
setIsOpen={setModalIsOpen}
|
||||
recommendationData={recommendationData}
|
||||
setCardComponent={setCardComponent}
|
||||
setCostMap={setCostMap}
|
||||
costMap={costMap}
|
||||
totalEstimatedCost={totalEstimatedCost}
|
||||
setTotalEstimatedCost={setTotalEstimatedCost}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,22 +9,19 @@ export default function RecommendationCostSummaryCard({
|
|||
totalEstimatedCost: number;
|
||||
totalSapPoints: number;
|
||||
}) {
|
||||
const [totalCost, setTotalcost] = useState(totalEstimatedCost);
|
||||
const [totalSap, setTotalSap] = useState(totalSapPoints);
|
||||
|
||||
return (
|
||||
<table className="text-left bg-green-700 rounded-md text-gray-100">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="font-medium pl-4 py-2">Total Cost:</td>
|
||||
<td className="pr-2">{"£" + formatNumber(totalCost)}</td>
|
||||
<td className="pr-2">{"£" + formatNumber(totalEstimatedCost)}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="font-medium pl-4 py-2">
|
||||
Total SAP Points Improvement:
|
||||
</td>
|
||||
<td className="pr-2">{totalSap}</td>
|
||||
<td className="pr-2">{totalSapPoints}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
import {
|
||||
ComponentRecommendation,
|
||||
Recommendation,
|
||||
} from "@/app/db/schema/recommendations";
|
||||
import RecommendationCard from "@/app/components/building-passport/RecommendationCard";
|
||||
import { formatNumber, sapToEpc } from "@/app/utils";
|
||||
import { Recommendation } from "@/app/db/schema/recommendations";
|
||||
import { PropertyMeta } from "@/app/db/schema/property";
|
||||
import RecommendationCostSummaryCard from "@/app/components/building-passport/RecommendationCostSummaryCard";
|
||||
import { Separator } from "@/app/shadcn_components/ui/separator";
|
||||
import RecommendationContainer from "@/app/components/building-passport/RecommendationContainer";
|
||||
|
||||
export default async function Recommendations() {
|
||||
const propertyMeta: PropertyMeta = {
|
||||
|
|
@ -90,80 +84,13 @@ export default async function Recommendations() {
|
|||
],
|
||||
};
|
||||
|
||||
const defaultWallsRecommendations = recommendations.Walls?.find(
|
||||
(rec: ComponentRecommendation) => rec.default
|
||||
) || { estimatedCost: 0, sapPoints: 0 };
|
||||
|
||||
const defaultFloorRecommendations = recommendations.Floor?.find(
|
||||
(rec: ComponentRecommendation) => rec.default
|
||||
) || { estimatedCost: 0, sapPoints: 0 };
|
||||
|
||||
const defaultVentiliationRecommendations = recommendations.Ventilation?.find(
|
||||
(rec: ComponentRecommendation) => rec.default
|
||||
) || { estimatedCost: 0, sapPoints: 0 };
|
||||
|
||||
const totalEstimatedCost =
|
||||
(defaultWallsRecommendations.estimatedCost || 0) +
|
||||
(defaultFloorRecommendations.estimatedCost || 0) +
|
||||
(defaultVentiliationRecommendations.estimatedCost || 0);
|
||||
|
||||
const costMap = {
|
||||
Walls: defaultWallsRecommendations.estimatedCost,
|
||||
Floor: defaultFloorRecommendations.estimatedCost,
|
||||
Ventilation: defaultVentiliationRecommendations.estimatedCost,
|
||||
};
|
||||
|
||||
const totalSapPoints =
|
||||
(defaultWallsRecommendations.sapPoints || 0) +
|
||||
(defaultFloorRecommendations.sapPoints || 0) +
|
||||
(defaultVentiliationRecommendations.sapPoints || 0);
|
||||
|
||||
const currentEpcRating = propertyMeta.currentEpcRating;
|
||||
const currentSapPoints = propertyMeta.currentSapPoints;
|
||||
|
||||
const expectedSapPoints = currentSapPoints + totalSapPoints;
|
||||
const expectedEpcRating = sapToEpc(expectedSapPoints);
|
||||
|
||||
return (
|
||||
<div className="leading-loose tracking-wider">
|
||||
<div className="flex py-8 text-lg">Recommendations</div>
|
||||
|
||||
<div className="mb-4 flex flex-col grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 items-stretch">
|
||||
<RecommendationCostSummaryCard
|
||||
totalEstimatedCost={totalEstimatedCost}
|
||||
totalSapPoints={totalSapPoints}
|
||||
/>
|
||||
|
||||
<table className="text-left bg-green-700 rounded-md text-gray-100">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="font-medium pl-4 py-2">Current EPC Rating:</td>
|
||||
<td className="font-bold pr-2">{currentEpcRating}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="font-medium pl-4 py-2">Expected EPC Rating:</td>
|
||||
<td className="font-bold pr-2">{expectedEpcRating}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<Separator className="mb-4" />
|
||||
|
||||
<div className="flex flex-col grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 items-stretch">
|
||||
{Object.entries(recommendations).map(
|
||||
([componentType, recommendationData], idx) => {
|
||||
return (
|
||||
<RecommendationCard
|
||||
key={idx}
|
||||
componentType={componentType}
|
||||
recommendationData={recommendationData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
<RecommendationContainer
|
||||
recommendations={recommendations}
|
||||
propertyMeta={propertyMeta}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue