From cc6cdc5d89574dfd166f261d70b82135f234a1fc Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 31 Jul 2023 17:53:17 +0100 Subject: [PATCH] Added getproperties api --- .../building-passport/RecommendationModal.tsx | 1 - src/app/db/db.ts | 12 +++++-- src/app/db/schema/property.ts | 23 +++++++++++++- .../[slug]/components/propertyTable.tsx | 14 ++++----- .../components/propertyTableColumns.tsx | 24 +++++--------- src/app/portfolio/[slug]/page.tsx | 31 +++---------------- src/app/portfolio/[slug]/utils.ts | 27 ++++++++++++++++ 7 files changed, 77 insertions(+), 55 deletions(-) diff --git a/src/app/components/building-passport/RecommendationModal.tsx b/src/app/components/building-passport/RecommendationModal.tsx index 8105cbf..5081c15 100644 --- a/src/app/components/building-passport/RecommendationModal.tsx +++ b/src/app/components/building-passport/RecommendationModal.tsx @@ -77,7 +77,6 @@ export default function RecommendationModal({ // update the cost sum setTotalEstimatedCost(sumRecommendationMetricMap(newCostMap)); - console.log("title", title); // Update the sap map const newSapMap = { ...sapMap, diff --git a/src/app/db/db.ts b/src/app/db/db.ts index 81e181f..74d0060 100644 --- a/src/app/db/db.ts +++ b/src/app/db/db.ts @@ -1,7 +1,8 @@ // db.ts import { drizzle } from "drizzle-orm/node-postgres"; import { Pool } from "pg"; -import * as schema from "@/app/db/schema/portfolio"; +import * as portfolioSchema from "@/app/db/schema/portfolio"; +import * as propertySchema from "@/app/db/schema/property"; export const pool = new Pool({ host: process.env.DB_HOST, @@ -11,4 +12,11 @@ export const pool = new Pool({ database: process.env.DB_NAME, }); -export const db = drizzle(pool, { schema }); +const schema = { + ...portfolioSchema, + ...propertySchema, +}; + +export const db = drizzle(pool, { + schema: schema, +}); diff --git a/src/app/db/schema/property.ts b/src/app/db/schema/property.ts index 5a15079..71fb574 100644 --- a/src/app/db/schema/property.ts +++ b/src/app/db/schema/property.ts @@ -9,7 +9,7 @@ import { boolean, } from "drizzle-orm/pg-core"; import { portfolio, PortfolioStatus } from "./portfolio"; -import { InferModel } from "drizzle-orm"; +import { InferModel, relations } from "drizzle-orm"; // This is a placeholder for the property schema export interface PropertyMeta { @@ -176,4 +176,25 @@ export const propertyTargets = pgTable("property_targets", { heatDemand: text("heat_demand"), }); +// one to one relationship between property and propertyTargets +export const propertyTargetRelations = relations(property, ({ one }) => ({ + target: one(propertyTargets, { + fields: [property.id], + references: [propertyTargets.propertyId], + }), +})); + // TODO: We'll need a property details buildings materials for verisk data? + +export type Property = InferModel; +// This type is used for the getProperties function in src/app/portfolio/[slug]/utils.ts +export interface PropertyWithTarget { + status: string | null; + id: number; + portfolioId: number; + creationStatus: string; + address: string | null; + postcode: string | null; + target: { epc?: string | null; heatDemand?: number | null }; + cost?: number | null; +} diff --git a/src/app/portfolio/[slug]/components/propertyTable.tsx b/src/app/portfolio/[slug]/components/propertyTable.tsx index 403fd22..3095a7b 100644 --- a/src/app/portfolio/[slug]/components/propertyTable.tsx +++ b/src/app/portfolio/[slug]/components/propertyTable.tsx @@ -22,27 +22,27 @@ import { } from "@/app/shadcn_components/ui/table"; import { useState } from "react"; import { DataTablePagination } from "./propertyTablePagination"; -import { Property } from "./propertyTableColumns"; import React from "react"; import { Input } from "@/app/shadcn_components/ui/input"; +import { PropertyWithTarget } from "@/app/db/schema/property"; interface DataTableProps { - columns: ColumnDef[]; - data: Property[]; + columns: ColumnDef[]; + data: PropertyWithTarget[]; } function fetchData(offset: number) { // Because this is a client component, this will be handled with react query - let properties: Property[] = []; + let properties: PropertyWithTarget[] = []; for (let i = offset; i <= offset + 20; i++) { properties.push({ id: i, portfolioId: 1, address: `${i}23 Fake Street`, postcode: `AB${i} 2CD`, - loadingStatus: Math.random() < 0.5 ? "complete" : "loading", + creationStatus: Math.random() < 0.5 ? "complete" : "loading", status: "assessment", - targetEpc: "C", + target: { epc: "C" }, cost: 1000, }); } @@ -55,7 +55,7 @@ export default function DataTable({ columns, }: DataTableProps) { const [sorting, setSorting] = useState([]); - const [tableData, setTableData] = useState(data); + const [tableData, setTableData] = useState(data); const [offset, setOffset] = useState(0); const [currentPageIndex, setCurrentPageIndex] = useState(0); const [columnFilters, setColumnFilters] = React.useState( diff --git a/src/app/portfolio/[slug]/components/propertyTableColumns.tsx b/src/app/portfolio/[slug]/components/propertyTableColumns.tsx index f8e9601..c2ad90a 100644 --- a/src/app/portfolio/[slug]/components/propertyTableColumns.tsx +++ b/src/app/portfolio/[slug]/components/propertyTableColumns.tsx @@ -17,17 +17,7 @@ import { FunnelIcon } from "@heroicons/react/24/outline"; import { formatNumber } from "@/app/utils"; import { cn } from "@/lib/utils"; import { PortfolioStatus } from "@/app/db/schema/portfolio"; - -export type Property = { - id: number; - portfolioId: number; - address: string; - postcode: string; - loadingStatus: string; - status: string; - targetEpc: string; - cost: number; -}; +import { PropertyWithTarget } from "@/app/db/schema/property"; interface DataTableColumnHeaderProps extends React.HTMLAttributes { @@ -74,7 +64,7 @@ export function DataTableFilterHeader({ ); } -export const columns: ColumnDef[] = [ +export const columns: ColumnDef[] = [ { accessorKey: "address", header: ({ column }) => { @@ -136,8 +126,8 @@ export const columns: ColumnDef[] = [ cell: ({ row }) => { const cost = parseFloat(row.getValue("cost")); - const loadingStatus = row.original.loadingStatus; - if (loadingStatus === "loading") { + const creationStatus = row.original.creationStatus; + if (creationStatus === "LOADING") { return
; } @@ -156,7 +146,7 @@ export const columns: ColumnDef[] = [ cell: ({ row }) => { return (
- {row.original.targetEpc} + {row.original.target?.epc || ""}
); }, @@ -168,8 +158,8 @@ export const columns: ColumnDef[] = [ const propertyId = property.id; const portfolioId = property.portfolioId; - const loadingStatus = property.loadingStatus; - if (loadingStatus === "loading") { + const creationStatus = property.creationStatus; + if (creationStatus === "LOADING") { return (
Loading... diff --git a/src/app/portfolio/[slug]/page.tsx b/src/app/portfolio/[slug]/page.tsx index 1d3e545..414e518 100644 --- a/src/app/portfolio/[slug]/page.tsx +++ b/src/app/portfolio/[slug]/page.tsx @@ -1,11 +1,9 @@ import { HomeIcon } from "@heroicons/react/24/outline"; -import { getPortfolio } from "./utils"; +import { getPortfolio, getProperties } from "./utils"; import { Toolbar } from "@/app/components/portfolio/Toolbar"; import DataTable from "@/app/portfolio/[slug]/components/propertyTable"; -import { - columns, - Property, -} from "@/app/portfolio/[slug]/components/propertyTableColumns"; +import { columns } from "@/app/portfolio/[slug]/components/propertyTableColumns"; +import { PropertyWithTarget } from "@/app/db/schema/property"; // We enfore caching of data for 60 seconds export const revalidate = 60; @@ -194,7 +192,6 @@ export default async function Page({ // We explcitly cast the slug to a number since it will be a string const portfolioId = Number(params.slug); - const pageStatus = searchParams.status || undefined; const { name: portfolioName, budget, @@ -207,23 +204,7 @@ export default async function Page({ energyCostSavings, } = await getPortfolio(portfolioId); - // TODO: TEMP - // let properties: Property[]; - let properties: Property[] = []; - if (pageStatus === "loading") { - for (let i = 1; i <= 20; i++) { - properties.push({ - id: i, - portfolioId: 1, - address: `${i}23 Fake Street`, - postcode: `AB${i} 2CD`, - loadingStatus: Math.random() < 0.5 ? "complete" : "loading", - status: "assessment", - targetEpc: "C", - cost: 1000, - }); - } - } + const properties: PropertyWithTarget[] = await getProperties(portfolioId); return ( <> @@ -258,10 +239,6 @@ export default async function Page({ {properties.length === 0 ? ( ) : ( - // )}
diff --git a/src/app/portfolio/[slug]/utils.ts b/src/app/portfolio/[slug]/utils.ts index a078000..d3b86c9 100644 --- a/src/app/portfolio/[slug]/utils.ts +++ b/src/app/portfolio/[slug]/utils.ts @@ -1,7 +1,9 @@ import { eq } from "drizzle-orm"; 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"; export async function getPortfolio(portfolioId: number): Promise { const data = await db @@ -19,3 +21,28 @@ export async function getPortfolio(portfolioId: number): Promise { return data[0]; } + +export async function getProperties( + portfolioId: number +): Promise { + const data: PropertyWithTarget[] = await db.query.property.findMany({ + columns: { + id: true, + portfolioId: true, + address: true, + postcode: true, + status: true, + creationStatus: true, + }, + where: eq(property.portfolioId, portfolioId), + with: { + target: { + columns: { + epc: true, + }, + }, + }, + }); + + return data; +}