mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-30 12:55:02 +00:00
Formatting portfolio page and pulled through default recommendation cost
This commit is contained in:
parent
7f1a09f96a
commit
138153f876
5 changed files with 48 additions and 12 deletions
|
|
@ -11,6 +11,7 @@ import {
|
|||
bigint,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { portfolio, PortfolioStatus } from "./portfolio";
|
||||
import { recommendation } from "./recommendations";
|
||||
import { InferModel, relations } from "drizzle-orm";
|
||||
|
||||
// This is a placeholder for the property schema
|
||||
|
|
@ -184,13 +185,25 @@ export const propertyTargets = pgTable("property_targets", {
|
|||
});
|
||||
|
||||
// one to one relationship between property and propertyTargets
|
||||
export const propertyTargetRelations = relations(property, ({ one }) => ({
|
||||
export const propertyRelations = relations(property, ({ one, many }) => ({
|
||||
target: one(propertyTargets, {
|
||||
fields: [property.id],
|
||||
references: [propertyTargets.propertyId],
|
||||
}),
|
||||
recommendations: many(recommendation),
|
||||
}));
|
||||
|
||||
// Define the other side of the one to many relation between a property and its recomendations
|
||||
export const recommendationsRelations = relations(
|
||||
recommendation,
|
||||
({ one }) => ({
|
||||
author: one(property, {
|
||||
fields: [recommendation.propertyId],
|
||||
references: [property.id],
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: We'll need a property details buildings materials for verisk data?
|
||||
|
||||
export type Property = InferModel<typeof property, "select">;
|
||||
|
|
@ -199,7 +212,11 @@ export type PropertyDetailsEpc = InferModel<
|
|||
"select"
|
||||
>;
|
||||
// This type is used for the getProperties function in src/app/portfolio/[slug]/utils.ts
|
||||
export interface PropertyWithTarget {
|
||||
export interface PropertyToRecommendation {
|
||||
estimatedCost?: number | null;
|
||||
}
|
||||
|
||||
export interface PropertyWithRelations {
|
||||
status: string | null;
|
||||
id: bigint;
|
||||
portfolioId: bigint;
|
||||
|
|
@ -207,5 +224,6 @@ export interface PropertyWithTarget {
|
|||
address: string | null;
|
||||
postcode: string | null;
|
||||
target: { epc?: string | null; heatDemand?: number | null };
|
||||
recommendations: PropertyToRecommendation[];
|
||||
cost?: number | null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { HomeIcon } from "@heroicons/react/24/outline";
|
||||
import { getPortfolio, getProperties } from "../utils";
|
||||
import { Toolbar } from "@/app/components/portfolio/Toolbar";
|
||||
import DataTable from "@/app/portfolio/[slug]/components/propertyTable";
|
||||
import { columns } from "@/app/portfolio/[slug]/components/propertyTableColumns";
|
||||
import { PropertyWithTarget } from "@/app/db/schema/property";
|
||||
import { PropertyWithRelations } from "@/app/db/schema/property";
|
||||
|
||||
// We enfore caching of data for 60 seconds
|
||||
export const revalidate = 60;
|
||||
|
|
@ -206,7 +205,7 @@ export default async function Page({
|
|||
} = await getPortfolio(portfolioId);
|
||||
|
||||
// Default limit to 1000 and offset to 0 for now - will handle pagination later
|
||||
const properties: PropertyWithTarget[] = await getProperties(
|
||||
const properties: PropertyWithRelations[] = await getProperties(
|
||||
portfolioId,
|
||||
1000,
|
||||
0
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ import { FunnelIcon } from "@heroicons/react/24/outline";
|
|||
import { formatNumber } from "@/app/utils";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { PortfolioStatus } from "@/app/db/schema/portfolio";
|
||||
import { PropertyWithTarget } from "@/app/db/schema/property";
|
||||
import {
|
||||
PropertyToRecommendation,
|
||||
PropertyWithRelations,
|
||||
} from "@/app/db/schema/property";
|
||||
|
||||
interface DataTableColumnHeaderProps<TData, TValue>
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
|
|
@ -64,7 +67,7 @@ export function DataTableFilterHeader<TData, TValue>({
|
|||
);
|
||||
}
|
||||
|
||||
export const columns: ColumnDef<PropertyWithTarget>[] = [
|
||||
export const columns: ColumnDef<PropertyWithRelations>[] = [
|
||||
{
|
||||
accessorKey: "address",
|
||||
header: ({ column }) => {
|
||||
|
|
@ -124,7 +127,17 @@ export const columns: ColumnDef<PropertyWithTarget>[] = [
|
|||
accessorKey: "cost",
|
||||
header: () => <div className="flex justify-center">Cost</div>,
|
||||
cell: ({ row }) => {
|
||||
const cost = parseFloat(row.getValue("cost"));
|
||||
const recommendations = row.original.recommendations;
|
||||
|
||||
const cost = recommendations.reduce(
|
||||
(acc: number, rec: PropertyToRecommendation) => {
|
||||
if (rec.estimatedCost === null || rec.estimatedCost === undefined) {
|
||||
return acc;
|
||||
}
|
||||
return acc + rec.estimatedCost;
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
const creationStatus = row.original.creationStatus;
|
||||
if (creationStatus === "LOADING") {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { db } from "@/app/db/db";
|
|||
import { portfolio } from "@/app/db/schema/portfolio";
|
||||
import { property } from "@/app/db/schema/property";
|
||||
import type { Portfolio } from "@/app/db/schema/portfolio";
|
||||
import type { PropertyWithTarget } from "@/app/db/schema/property";
|
||||
import type { PropertyWithRelations } from "@/app/db/schema/property";
|
||||
import { plan, planRecommendations } from "@/app/db/schema/recommendations";
|
||||
|
||||
export async function getPortfolio(portfolioId: string): Promise<Portfolio> {
|
||||
|
|
@ -32,8 +32,8 @@ export async function getProperties(
|
|||
portfolioId: string,
|
||||
limit: number = 1000,
|
||||
offset: number = 0
|
||||
): Promise<PropertyWithTarget[]> {
|
||||
const data: PropertyWithTarget[] = await db.query.property.findMany({
|
||||
): Promise<PropertyWithRelations[]> {
|
||||
const data: PropertyWithRelations[] = await db.query.property.findMany({
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
columns: {
|
||||
|
|
@ -51,6 +51,12 @@ export async function getProperties(
|
|||
epc: true,
|
||||
},
|
||||
},
|
||||
recommendations: {
|
||||
columns: {
|
||||
estimatedCost: true,
|
||||
},
|
||||
where: eq(recommendation.default, true),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export function formatNumber(number: number): string {
|
|||
|
||||
const formattedNumber: string = (
|
||||
roundedNumber / Math.pow(1000, suffixIndex)
|
||||
).toString();
|
||||
).toFixed(2);
|
||||
|
||||
return formattedNumber + suffixes[suffixIndex];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue