mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
Added kwh and co2 to building passport
This commit is contained in:
parent
3b259d7611
commit
4df0276829
7 changed files with 78 additions and 32 deletions
|
|
@ -30,6 +30,14 @@ export async function GET(
|
|||
updatedAt: true,
|
||||
},
|
||||
where: eq(property.id, BigInt(propertyId)),
|
||||
with: {
|
||||
detailsEpc: {
|
||||
columns: {
|
||||
adjustedEnergyConsumption: true,
|
||||
co2Emissions: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return new NextResponse(JSON.stringify(propertyMeta, serializeBigInt));
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import { getEpcColorClass } from "@/app/utils";
|
||||
|
||||
export default function EpcCard({
|
||||
epcRating,
|
||||
fullMargin = true,
|
||||
expected = false,
|
||||
kwh = null,
|
||||
carbon = null,
|
||||
}: {
|
||||
epcRating: string;
|
||||
fullMargin: boolean;
|
||||
expected?: boolean;
|
||||
kwh?: number | null;
|
||||
carbon?: number | null;
|
||||
}) {
|
||||
let marginClass = "";
|
||||
if (fullMargin) {
|
||||
|
|
@ -13,24 +19,42 @@ export default function EpcCard({
|
|||
}
|
||||
|
||||
let title;
|
||||
let bgStyling;
|
||||
if (expected) {
|
||||
title = "Expected Energy Rating";
|
||||
bgStyling = "bg-green-600";
|
||||
} else {
|
||||
title = "Energy Rating";
|
||||
bgStyling = "bg-brandblue";
|
||||
}
|
||||
|
||||
const bgColour = getEpcColorClass(epcRating);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
"flex flex-col items-center p-4 shadow rounded-md max-w-xl justify-start text-gray-100 " +
|
||||
bgStyling
|
||||
bgColour
|
||||
}
|
||||
>
|
||||
<div className="text-xl font-bold mb-4 text-center">{title}</div>
|
||||
<div className="text-6xl font-bold">{epcRating}</div>
|
||||
<div className="text-6xl font-bold ">{epcRating}</div>
|
||||
|
||||
{(kwh || carbon) && (
|
||||
<table className="mt-6 text-sm">
|
||||
<tbody>
|
||||
{kwh && (
|
||||
<tr>
|
||||
<td className="text-gray-50 pr-2 py-1">Energy:</td>
|
||||
<td className="text-gray-50">{kwh.toFixed(0)} kWh</td>
|
||||
</tr>
|
||||
)}
|
||||
{carbon && (
|
||||
<tr>
|
||||
<td className="text-gray-50 pr-2 py-1">CO2:</td>
|
||||
<td className="text-gray-50">{carbon}t</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ export interface PropertyMeta {
|
|||
currentEpcRating: string;
|
||||
currentSapPoints: number;
|
||||
updatedAt: string;
|
||||
detailsEpc: {
|
||||
adjustedEnergyConsumption: number | null;
|
||||
co2Emissions: number | null;
|
||||
};
|
||||
}
|
||||
|
||||
export type Rating = "Very good" | "Good" | "Poor" | "Very poor" | "N/A";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// This script contains ALL relations for the database, used by drizzle-orm
|
||||
|
||||
import { relations } from "drizzle-orm";
|
||||
import { property, propertyTargets } from "./property";
|
||||
import { property, propertyDetailsEpc, propertyTargets } from "./property";
|
||||
import {
|
||||
plan,
|
||||
planRecommendations,
|
||||
|
|
@ -77,6 +77,10 @@ export const propertyRelations = relations(property, ({ one, many }) => ({
|
|||
references: [propertyTargets.propertyId],
|
||||
}),
|
||||
recommendations: many(recommendation),
|
||||
detailsEpc: one(propertyDetailsEpc, {
|
||||
fields: [property.id],
|
||||
references: [propertyDetailsEpc.propertyId],
|
||||
}),
|
||||
}));
|
||||
|
||||
// We have a many to many relationship between users and portfolios
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import EpcCard from "@/app/components/building-passport/EpcCard";
|
||||
import { PropertyMeta } from "@/app/db/schema/property";
|
||||
import { formatDateTime } from "@/app/utils";
|
||||
import {
|
||||
HomeIcon,
|
||||
|
|
@ -22,10 +21,17 @@ export default async function BuildingPassportHome({
|
|||
// the response is cached so we just gain access to the data
|
||||
const propertyMeta = await getPropertyMeta(params.propertyId);
|
||||
|
||||
console.log(propertyMeta);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center mt-4">
|
||||
<div className="flex justify-center mt-4 space-x-2">
|
||||
<EpcCard epcRating={propertyMeta.currentEpcRating} fullMargin={false} />
|
||||
<EpcCard
|
||||
epcRating={propertyMeta.currentEpcRating}
|
||||
fullMargin={false}
|
||||
kwh={propertyMeta.detailsEpc.adjustedEnergyConsumption}
|
||||
carbon={propertyMeta.detailsEpc.co2Emissions}
|
||||
/>
|
||||
<div className="flex flex-col p-8 bg-white shadow rounded-md max-w-2xl mx-auto justify-start text-gray-700">
|
||||
<div className="text-2xl font-bold mb-4">Your property</div>
|
||||
<div className="flex items-center space-x-2 mb-2">
|
||||
|
|
@ -55,7 +61,7 @@ export default async function BuildingPassportHome({
|
|||
</div>
|
||||
<div className="flex items-center space-x-2 mb-2">
|
||||
<HomeModernIcon className="h-5 w-5 text-gray-400" />
|
||||
<div className="text-gray-500">Number of Rooms:</div>
|
||||
<div className="text-gray-500">Number of Habitable Rooms:</div>
|
||||
<div className="text-gray-700">{propertyMeta.numberOfRooms}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { ArrowUpDown, MoreHorizontal } from "lucide-react";
|
|||
import StatusBadge from "@/app/components/StatusBadge";
|
||||
import { HomeIcon } from "@heroicons/react/20/solid";
|
||||
import { FunnelIcon } from "@heroicons/react/24/outline";
|
||||
import { formatNumber, sapToEpc } from "@/app/utils";
|
||||
import { formatNumber, getEpcColorClass, sapToEpc } from "@/app/utils";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { PortfolioStatus } from "@/app/db/schema/portfolio";
|
||||
import {
|
||||
|
|
@ -29,30 +29,9 @@ interface DataTableColumnHeaderProps<TData, TValue>
|
|||
}
|
||||
|
||||
const EpcLetterBubble = ({ letter }: { letter: string }) => {
|
||||
const getColorClass = (letter: string) => {
|
||||
switch (letter.toUpperCase()) {
|
||||
case "A":
|
||||
return "bg-epc_a";
|
||||
case "B":
|
||||
return "bg-epc_b";
|
||||
case "C":
|
||||
return "bg-epc_c";
|
||||
case "D":
|
||||
return "bg-epc_d";
|
||||
case "E":
|
||||
return "bg-epc_e";
|
||||
case "F":
|
||||
return "bg-epc_f";
|
||||
case "G":
|
||||
return "bg-epc_d";
|
||||
default:
|
||||
return "bg-gray-500";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`inline-flex items-center justify-center w-6 h-6 rounded-full ${getColorClass(
|
||||
className={`inline-flex items-center justify-center w-6 h-6 rounded-full ${getEpcColorClass(
|
||||
letter
|
||||
)} text-white text-m font-bold shadow-outline-black`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,26 @@
|
|||
import { Rating } from "./db/schema/property";
|
||||
|
||||
export const getEpcColorClass = (letter: string) => {
|
||||
switch (letter.toUpperCase()) {
|
||||
case "A":
|
||||
return "bg-epc_a";
|
||||
case "B":
|
||||
return "bg-epc_b";
|
||||
case "C":
|
||||
return "bg-epc_c";
|
||||
case "D":
|
||||
return "bg-epc_d";
|
||||
case "E":
|
||||
return "bg-epc_e";
|
||||
case "F":
|
||||
return "bg-epc_f";
|
||||
case "G":
|
||||
return "bg-epc_d";
|
||||
default:
|
||||
return "bg-gray-500";
|
||||
}
|
||||
};
|
||||
|
||||
export const getRating = (rating: number | null): Rating => {
|
||||
if (rating == null) {
|
||||
return "N/A";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue