testing adding valuation and funding components

This commit is contained in:
Khalim Conn-Kowlessar 2024-10-18 13:53:04 +01:00
parent 45d4a8dccb
commit 30ca58471b
8 changed files with 101 additions and 4 deletions

View file

@ -29,6 +29,7 @@ export async function GET(
currentEpcRating: true,
currentSapPoints: true,
updatedAt: true,
currentValuation: true,
},
where: eq(property.id, BigInt(propertyId)),
with: {

View file

@ -26,19 +26,25 @@ export function BrandButton({
}: {
label: string;
onClick: Dispatch<SetStateAction<any>>;
backgroundColor: "brandblue" | "brandgold"; // Restrict backgroundColor to these two options
backgroundColor:
| "brandblue"
| "brandgold"
| "brandmidblue"
| "brandlightblue"; // Restrict backgroundColor to these two options
}) {
// Dictionary to map background colors to hover colors
const hoverColors = {
brandblue: "hover:bg-hoverblue",
brandgold: "hover:bg-hovergold",
brandmidblue: "hover:bg-hoverblue",
brandlightblue: "hover:bg-brandmidblue",
};
return (
<button
type="button"
className={`inline-flex justify-center rounded-md border border-transparent px-4 py-2 text-sm font-medium text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2
${backgroundColor === "brandblue" ? "bg-brandblue" : "bg-brandgold"}
bg-${backgroundColor}
${hoverColors[backgroundColor]}`}
onClick={onClick}
>

View file

@ -3,9 +3,11 @@
import {
Recommendation,
RecommendationType,
Plan,
} from "@/app/db/schema/recommendations";
import RecommendationCard from "./RecommendationCard";
import WorksPackageCard from "./WorksPackageCard";
import ValuationImpactComponent from "./ValuationImpactComponent";
import { Separator } from "@/app/shadcn_components/ui/separator";
import { PropertyMeta } from "@/app/db/schema/property";
import { sapToEpc } from "@/app/utils";
@ -20,6 +22,7 @@ import {
interface RecommendationContainerProps {
recommendations: Recommendation[];
propertyMeta: PropertyMeta;
planMeta: Plan;
}
const typeToCategoryMap: { [key in RecommendationType]?: RecommendationType } =
@ -50,6 +53,7 @@ const emptyImpactState = {
export default function RecommendationContainer({
recommendations,
propertyMeta,
planMeta,
}: RecommendationContainerProps) {
const categorizedRecommendations = recommendations.reduce((acc, curr) => {
const typeKey = curr.type as RecommendationType;
@ -337,6 +341,12 @@ export default function RecommendationContainer({
totalEnergyCostSavings={totalEnergyCostSavings}
totalKwhSavings={totalKwhSavings}
/>
<ValuationImpactComponent
currentValuation={propertyMeta.currentValuation}
valuationIncreaseLowerBound={planMeta.valuationIncreaseLowerBound}
valuationIncreaseUpperBound={planMeta.valuationIncreaseUpperBound}
/>
</div>
<Separator className="mb-4 bg-brandblue" />

View file

@ -0,0 +1,62 @@
"use client";
import { BrandButton } from "../Buttons";
import { useState } from "react";
export default function ValuationImpactComponent({
currentValuation,
valuationIncreaseLowerBound,
valuationIncreaseUpperBound,
}: {
currentValuation: number | null;
valuationIncreaseLowerBound: number | null;
valuationIncreaseUpperBound: number | null;
}) {
const [fundingModalIsOpen, setFundingModalIsOpen] = useState(false);
// If we have no current valuation, we return no component
if (!currentValuation) {
return <></>;
}
const lowerBoundValuation =
currentValuation + (valuationIncreaseLowerBound ?? 0);
const upperBoundValuation =
currentValuation + (valuationIncreaseUpperBound ?? 0);
function openFundingModal() {
setFundingModalIsOpen(true);
}
return (
<div className="col-span-1 md:col-span-2 lg:col-span-3 w-full p-4 bg-brandblue rounded-lg shadow-md grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="flex flex-col items-center text-center">
<span className="text-gray-100 text-lg">Current Value</span>
<span className="text-3xl font-bold text-brandgold mt-1">
£{currentValuation.toLocaleString()}
</span>
</div>
<div className="flex flex-col items-center text-center">
<span className="text-gray-100 text-lg">After Retrofit Valuation</span>
<div className="text-2xl text-brandgold mt-1">
£{lowerBoundValuation.toLocaleString()} - £
{upperBoundValuation.toLocaleString()}
</div>
<span className="text-sm text-gray-100 mt-1">
Estimated improvement: £
{valuationIncreaseLowerBound?.toLocaleString()} - £
{valuationIncreaseUpperBound?.toLocaleString()}
</span>
</div>
<div className="flex flex-col items-center text-center">
<span className="text-gray-100 text-lg">Funding Options</span>
<BrandButton
label="See More"
onClick={openFundingModal}
backgroundColor="brandlightblue"
/>
</div>
</div>
);
}

View file

@ -32,6 +32,7 @@ export interface PropertyMeta {
currentEpcRating: string;
currentSapPoints: number;
updatedAt: string;
currentValuation: number | null;
detailsEpc: {
currentEnergyDemand: number | null;
co2Emissions: number | null;

View file

@ -1,5 +1,5 @@
import RecommendationContainer from "@/app/components/building-passport/RecommendationContainer";
import { getPropertyMeta, getRecommendations } from "../../utils";
import { getPropertyMeta, getRecommendations, getPlanMeta } from "../../utils";
export default async function Recommendations({
params,
@ -8,6 +8,7 @@ export default async function Recommendations({
}) {
const propertyMeta = await getPropertyMeta(params.propertyId);
const recommendations = await getRecommendations(params.planId);
const planMeta = await getPlanMeta(params.planId);
return (
<div className="leading-loose tracking-wider">
@ -15,6 +16,7 @@ export default async function Recommendations({
<RecommendationContainer
recommendations={recommendations}
propertyMeta={propertyMeta}
planMeta={planMeta}
/>
</div>
);

View file

@ -1,6 +1,8 @@
import {
Recommendation,
planRecommendations,
plan,
Plan,
} from "@/app/db/schema/recommendations";
import { db } from "@/app/db/db";
import {
@ -14,7 +16,6 @@ import {
NonIntrusiveSurveyData,
nonInstrusiveSurvey,
} from "@/app/db/schema/property";
import { plan, Plan } from "@/app/db/schema/recommendations";
import { getRating } from "@/app/utils";
import { eq, desc } from "drizzle-orm";
import {
@ -85,6 +86,18 @@ export async function getRecommendations(
return recommendations;
}
export async function getPlanMeta(planId: string): Promise<Plan> {
const data = await db.query.plan.findFirst({
where: eq(plan.id, BigInt(planId)),
});
if (!data) {
throw new Error("Network response was not ok");
}
return data;
}
type PlanRelation = Plan & {
planRecommendations: {
recommendation: {

View file

@ -104,6 +104,7 @@ module.exports = {
hovergold: "#c79d12",
brandbrown: "#3d1e05",
brandmidblue: "#3943b7",
brandlightblue: "#00a9f4",
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
@ -145,6 +146,7 @@ module.exports = {
hovertan: "#947750",
brandbrown: "#3d1e05",
brandmidblue: "#3943b7",
brandlightblue: "#00a9f4",
},
borderRadius: {
lg: `var(--radius)`,