properties table wip

This commit is contained in:
Khalim Conn-Kowlessar 2023-07-24 12:40:48 +01:00
parent 68414c73ea
commit a1e9c075a0
3 changed files with 173 additions and 69 deletions

133
package-lock.json generated
View file

@ -12,12 +12,14 @@
"@headlessui/react": "^1.7.14",
"@heroicons/react": "^2.0.18",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-hover-card": "^1.0.6",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.3",
"@radix-ui/react-select": "^1.2.2",
"@radix-ui/react-slot": "^1.0.2",
"@tanstack/react-query": "^4.29.12",
"@tanstack/react-table": "^8.9.3",
"@types/node": "20.2.3",
"@types/react": "18.2.7",
"@types/react-dom": "18.2.4",
@ -1671,6 +1673,35 @@
}
}
},
"node_modules/@radix-ui/react-dropdown-menu": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.5.tgz",
"integrity": "sha512-xdOrZzOTocqqkCkYo8yRPCib5OkTkqN7lqNCdxwPOdE466DOaNl4N8PkUIlsXthQvW5Wwkd+aEmWpfWlBoDPEw==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/primitive": "1.0.1",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-id": "1.0.1",
"@radix-ui/react-menu": "2.0.5",
"@radix-ui/react-primitive": "1.0.3",
"@radix-ui/react-use-controllable-state": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-focus-guards": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz",
@ -1785,6 +1816,46 @@
}
}
},
"node_modules/@radix-ui/react-menu": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.5.tgz",
"integrity": "sha512-Gw4f9pwdH+w5w+49k0gLjN0PfRDHvxmAgG16AbyJZ7zhwZ6PBHKtWohvnSwfusfnK3L68dpBREHpVkj8wEM7ZA==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/primitive": "1.0.1",
"@radix-ui/react-collection": "1.0.3",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-direction": "1.0.1",
"@radix-ui/react-dismissable-layer": "1.0.4",
"@radix-ui/react-focus-guards": "1.0.1",
"@radix-ui/react-focus-scope": "1.0.3",
"@radix-ui/react-id": "1.0.1",
"@radix-ui/react-popper": "1.1.2",
"@radix-ui/react-portal": "1.0.3",
"@radix-ui/react-presence": "1.0.1",
"@radix-ui/react-primitive": "1.0.3",
"@radix-ui/react-roving-focus": "1.0.4",
"@radix-ui/react-slot": "1.0.2",
"@radix-ui/react-use-callback-ref": "1.0.1",
"aria-hidden": "^1.1.1",
"react-remove-scroll": "2.5.5"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-navigation-menu": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.1.3.tgz",
@ -1923,6 +1994,37 @@
}
}
},
"node_modules/@radix-ui/react-roving-focus": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz",
"integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/primitive": "1.0.1",
"@radix-ui/react-collection": "1.0.3",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-direction": "1.0.1",
"@radix-ui/react-id": "1.0.1",
"@radix-ui/react-primitive": "1.0.3",
"@radix-ui/react-use-callback-ref": "1.0.1",
"@radix-ui/react-use-controllable-state": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-select": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.2.tgz",
@ -2207,6 +2309,37 @@
}
}
},
"node_modules/@tanstack/react-table": {
"version": "8.9.3",
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.9.3.tgz",
"integrity": "sha512-Ng9rdm3JPoSCi6cVZvANsYnF+UoGVRxflMb270tVj0+LjeT/ZtZ9ckxF6oLPLcKesza6VKBqtdF9mQ+vaz24Aw==",
"dependencies": {
"@tanstack/table-core": "8.9.3"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": ">=16",
"react-dom": ">=16"
}
},
"node_modules/@tanstack/table-core": {
"version": "8.9.3",
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.9.3.tgz",
"integrity": "sha512-NpHZBoHTfqyJk0m/s/+CSuAiwtebhYK90mDuf5eylTvgViNOujiaOaxNDxJkQQAsVvHWZftUGAx1EfO1rkKtLg==",
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@testing-library/cypress": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-9.0.0.tgz",

View file

@ -18,12 +18,14 @@
"@headlessui/react": "^1.7.14",
"@heroicons/react": "^2.0.18",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-hover-card": "^1.0.6",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-navigation-menu": "^1.1.3",
"@radix-ui/react-select": "^1.2.2",
"@radix-ui/react-slot": "^1.0.2",
"@tanstack/react-query": "^4.29.12",
"@tanstack/react-table": "^8.9.3",
"@types/node": "20.2.3",
"@types/react": "18.2.7",
"@types/react-dom": "18.2.4",

View file

@ -7,6 +7,11 @@ import type { PortfolioStatus } from "@/app/db/schema/portfolio";
import StatusBadge from "@/app/components/StatusBadge";
import { getPortfolio } from "./utils";
import { Toolbar } from "@/app/components/portfolio/Toolbar";
import DataTable from "@/app/portfolio/[slug]/components/propertyTable";
import {
columns,
Payment,
} from "@/app/portfolio/[slug]/components/propertyTableColumns";
// We enfore caching of data for 60 seconds
export const revalidate = 60;
@ -15,10 +20,7 @@ type Property = {
id: string;
address: string;
postcode: string;
cost: number;
co2Reduction: number;
lmkKey: string;
targetEpcRating: string;
loadingStatus: string;
status: (typeof PortfolioStatus)[number];
};
@ -36,66 +38,10 @@ function EmptyPropertyState() {
);
}
function Propertycards({
properties,
portfolioId,
}: {
properties: Property[];
portfolioId: number;
}) {
return (
<div className="flex justify-center">
<ul className="w-full">
{properties.map((property) => (
<li
key={property.id}
className="bg-white rounded-lg shadow mb-4 p-4 flex items-center justify-between"
>
<div className="flex items-center ">
<div>
<HomeIcon className="h-8 w-8 mx-auto text-gray-200" />
</div>
<div className="ml-4 ">
<h3 className="text-xl font-medium font-semibold text-brandblue">
{property.address}
</h3>
<div className="text-sm text-muted-foreground">
{property.postcode}
</div>
</div>
<div className="ml-10">
<Badge className="bg-brandblue">
Cost: £{formatNumber(property.cost)}
</Badge>
</div>
<div className="ml-4">
<Badge className="bg-brandtan">
Co2 Savings (t): {property.co2Reduction}
</Badge>
</div>
<div className="ml-4">
<StatusBadge status={property.status} isProperty={true} />
</div>
</div>
<Link
href={`/portfolio/${portfolioId}/property/${property.lmkKey}/plan?postcode=${property.postcode}&targetEpcRating=${property.targetEpcRating}`}
>
<div className="w-10 h-10">
<ArrowRightCircleIcon className="text-brandblue" />
</div>
</Link>
</li>
))}
</ul>
</div>
);
}
interface SummaryBoxProps {
budget: number | null;
totalCost: number | null;
properties: Property[];
numProperties: number;
co2EquivalentSavings: number | null;
totalWorkHours: number | null;
propertyValuationIncrease: number | null;
@ -107,7 +53,7 @@ interface SummaryBoxProps {
function SummaryBox({
budget,
totalCost,
properties,
numProperties,
co2EquivalentSavings,
totalWorkHours,
propertyValuationIncrease,
@ -205,7 +151,7 @@ function SummaryBox({
<tbody>
<tr>
<td className="text-gray-700">Total properties</td>
<td className="text-gray-600 text-end">{properties.length}</td>
<td className="text-gray-600 text-end">{numProperties}</td>
</tr>
<tr>
<td className="text-gray-700">Total Works Time</td>
@ -262,6 +208,7 @@ 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,
@ -274,7 +221,28 @@ export default async function Page({
energyCostSavings,
} = await getPortfolio(portfolioId);
const properties: Property[] = [];
// TODO: TEMP
// let properties: Property[];
let properties: {}[];
if (pageStatus === "loading") {
properties = [
{
id: 1,
address: "123 Fake Street",
postcode: "AB1 2CD",
loadingStatus: "loading",
},
{
id: 2,
address: "223 Fake Street",
postcode: "AB1 2CD",
loadingStatus: "complete",
cost: 1000,
},
];
} else {
properties = [];
}
return (
<>
@ -296,7 +264,7 @@ export default async function Page({
<SummaryBox
budget={budget}
totalCost={totalCost}
properties={properties}
numProperties={properties.length}
co2EquivalentSavings={co2EquivalentSavings}
totalWorkHours={totalWorkHours}
propertyValuationIncrease={propertyValuationIncrease}
@ -309,10 +277,11 @@ export default async function Page({
{properties.length === 0 ? (
<EmptyPropertyState />
) : (
<Propertycards
properties={properties}
portfolioId={portfolioId}
/>
// <Propertycards
// properties={properties}
// portfolioId={portfolioId}
// />
<DataTable data={properties} columns={columns} />
)}
</div>
</div>