mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
Added getproperties api
This commit is contained in:
parent
34b140cf27
commit
cc6cdc5d89
7 changed files with 77 additions and 55 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<typeof property, "select">;
|
||||
// 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TData, TValue> {
|
||||
columns: ColumnDef<Property>[];
|
||||
data: Property[];
|
||||
columns: ColumnDef<PropertyWithTarget>[];
|
||||
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<TData, TValue>({
|
|||
columns,
|
||||
}: DataTableProps<TData, TValue>) {
|
||||
const [sorting, setSorting] = useState<SortingState>([]);
|
||||
const [tableData, setTableData] = useState<Property[]>(data);
|
||||
const [tableData, setTableData] = useState<PropertyWithTarget[]>(data);
|
||||
const [offset, setOffset] = useState(0);
|
||||
const [currentPageIndex, setCurrentPageIndex] = useState(0);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
|
|
|
|||
|
|
@ -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<TData, TValue>
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
|
|
@ -74,7 +64,7 @@ export function DataTableFilterHeader<TData, TValue>({
|
|||
);
|
||||
}
|
||||
|
||||
export const columns: ColumnDef<Property>[] = [
|
||||
export const columns: ColumnDef<PropertyWithTarget>[] = [
|
||||
{
|
||||
accessorKey: "address",
|
||||
header: ({ column }) => {
|
||||
|
|
@ -136,8 +126,8 @@ export const columns: ColumnDef<Property>[] = [
|
|||
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 <div className="font-medium flex justify-center"></div>;
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +146,7 @@ export const columns: ColumnDef<Property>[] = [
|
|||
cell: ({ row }) => {
|
||||
return (
|
||||
<div className="text-gray-700 font-medium flex justify-center">
|
||||
{row.original.targetEpc}
|
||||
{row.original.target?.epc || ""}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
@ -168,8 +158,8 @@ export const columns: ColumnDef<Property>[] = [
|
|||
const propertyId = property.id;
|
||||
const portfolioId = property.portfolioId;
|
||||
|
||||
const loadingStatus = property.loadingStatus;
|
||||
if (loadingStatus === "loading") {
|
||||
const creationStatus = property.creationStatus;
|
||||
if (creationStatus === "LOADING") {
|
||||
return (
|
||||
<div className="font-mediutext-gray-800m text-gray-700 flex justify-center">
|
||||
Loading...
|
||||
|
|
|
|||
|
|
@ -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 ? (
|
||||
<EmptyPropertyState />
|
||||
) : (
|
||||
// <Propertycards
|
||||
// properties={properties}
|
||||
// portfolioId={portfolioId}
|
||||
// />
|
||||
<DataTable data={properties} columns={columns} />
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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<Portfolio> {
|
||||
const data = await db
|
||||
|
|
@ -19,3 +21,28 @@ export async function getPortfolio(portfolioId: number): Promise<Portfolio> {
|
|||
|
||||
return data[0];
|
||||
}
|
||||
|
||||
export async function getProperties(
|
||||
portfolioId: number
|
||||
): Promise<PropertyWithTarget[]> {
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue