mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
Tidying up layout on portfolio screen
This commit is contained in:
parent
40926b7106
commit
8d2db50d1c
5 changed files with 217 additions and 85 deletions
|
|
@ -29,9 +29,9 @@ const ListItem = React.forwardRef<
|
|||
{...props}
|
||||
>
|
||||
<div className="text-sm font-medium leading-none">{title}</div>
|
||||
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
||||
<div className="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
||||
{children}
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</NavigationMenuLink>
|
||||
</li>
|
||||
|
|
@ -49,7 +49,7 @@ export default function AddNewDropDown({
|
|||
}
|
||||
|
||||
function handleClickUploadCSV() {
|
||||
console.log("Uplaod csv");
|
||||
console.log("Upload csv");
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -58,13 +58,13 @@ export default function AddNewDropDown({
|
|||
<NavigationMenuContent>
|
||||
<ul className="p-6 md:w-[200px] lg:w-[350px] lg:grid-cols-[.75fr_1fr]">
|
||||
<ListItem onClick={handleCickAddUnit}>
|
||||
<div className="font-medium items-center flex text-sm text-gray-900 justify-start">
|
||||
<div className="font-medium items-center flex text-sm text-gray-900 justify-start hover:cursor-pointer">
|
||||
<PlusIcon className="h-4 w-4 mr-2" /> Add Unit
|
||||
</div>
|
||||
</ListItem>
|
||||
|
||||
<ListItem onClick={handleClickUploadCSV}>
|
||||
<div className="font-medium items-center flex text-sm text-gray-900 justify-start">
|
||||
<div className="font-medium items-center flex text-sm text-gray-900 justify-start cursor-pointer">
|
||||
<TableCellsIcon className="h-4 w-4 mr-2" /> Upload CSV
|
||||
</div>
|
||||
Upload a csv of multiple units
|
||||
|
|
|
|||
|
|
@ -9,22 +9,6 @@ import {
|
|||
} from "@/app/shadcn_components/ui/navigation-menu";
|
||||
import AddNewDropDown from "./AddNew";
|
||||
|
||||
function PortfolioSettings({ portfolioId }: { portfolioId: number }) {
|
||||
const onClick = () => {
|
||||
console.log("Go to settings");
|
||||
};
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-md border border-transparent bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
|
||||
onClick={onClick}
|
||||
>
|
||||
<Cog6ToothIcon className="h-4 w-4 mr-2" />
|
||||
{"Settings"}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
interface ToolbarProps {
|
||||
portfolioId: number;
|
||||
}
|
||||
|
|
@ -37,7 +21,7 @@ export function Toolbar({ portfolioId }: ToolbarProps) {
|
|||
<NavigationMenu>
|
||||
<NavigationMenuList>
|
||||
<NavigationMenuItem
|
||||
className={navigationMenuTriggerStyle()}
|
||||
className={navigationMenuTriggerStyle() + " ml-3 mr-2"}
|
||||
onClick={handleClickSettings}
|
||||
>
|
||||
Settings
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ type Property = {
|
|||
function EmptyPropertyState() {
|
||||
return (
|
||||
<div className="flex justify-center h-1/2">
|
||||
<div className="bg-gray-50 rounded-lg shadow w-full">
|
||||
<p className="text-center text-gray-400 pt-3">
|
||||
<div className="bg-white rounded-lg w-full">
|
||||
<p className="text-center text-gray-400 pt-6">
|
||||
Click on Add new to start adding properties to your Portfolio
|
||||
<HomeIcon className="h-20 w-20 mx-auto mt-4 text-gray-200" />
|
||||
</p>
|
||||
|
|
@ -91,6 +91,170 @@ function Propertycards({
|
|||
);
|
||||
}
|
||||
|
||||
interface SummaryBoxProps {
|
||||
budget: number | null;
|
||||
totalCost: number | null;
|
||||
properties: Property[];
|
||||
co2EquivalentSavings: number | null;
|
||||
totalWorkHours: number | null;
|
||||
propertyValuationIncrease: number | null;
|
||||
rentalYieldIncrease: number | null;
|
||||
energySavings: number | null;
|
||||
energyCostSavings: number | null;
|
||||
}
|
||||
|
||||
function SummaryBox({
|
||||
budget,
|
||||
totalCost,
|
||||
properties,
|
||||
co2EquivalentSavings,
|
||||
totalWorkHours,
|
||||
propertyValuationIncrease,
|
||||
rentalYieldIncrease,
|
||||
energySavings,
|
||||
energyCostSavings,
|
||||
}: SummaryBoxProps) {
|
||||
function formatMoney(amount: number | null) {
|
||||
if (amount === null) {
|
||||
return "£0";
|
||||
} else {
|
||||
return "£" + amount.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, "$&,");
|
||||
}
|
||||
}
|
||||
|
||||
function formatHours(hours: number | null) {
|
||||
if (hours === null) {
|
||||
return "0 hours";
|
||||
} else {
|
||||
return hours + " hours";
|
||||
}
|
||||
}
|
||||
|
||||
function formatCo2(co2: number | null) {
|
||||
if (co2 === null) {
|
||||
return "0 tonnes";
|
||||
} else {
|
||||
return co2 + " tonnes";
|
||||
}
|
||||
}
|
||||
|
||||
function formatKwh(energy: number | null) {
|
||||
if (energy === null) {
|
||||
return "0 Kwh";
|
||||
} else {
|
||||
return energy + " Kwh";
|
||||
}
|
||||
}
|
||||
|
||||
const budgetFormatted = formatMoney(budget);
|
||||
const totalCostFormatted = formatMoney(totalCost);
|
||||
const totalValueIncreaseFormatted = formatMoney(propertyValuationIncrease);
|
||||
const totalWorkHoursFormatted = formatHours(totalWorkHours);
|
||||
const rentalYieldIncreaseFormatted = formatMoney(rentalYieldIncrease);
|
||||
const energyCostSavingsFormatted = formatMoney(energyCostSavings);
|
||||
const co2EquivalentSavingsFormatted = formatCo2(co2EquivalentSavings);
|
||||
const energySavingsFormatted = formatKwh(energySavings);
|
||||
|
||||
return (
|
||||
<div className="p-6 bg-white rounded-lg shadow ">
|
||||
<h2 className="text-2xl font-bold mb-4 text-gray-700 text-center">
|
||||
Portfolio Summary
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-1 gap-6">
|
||||
<div className="p-4 bg-gray-50 rounded-lg">
|
||||
<h3 className="text-lg font-semibold text-gray-700 mb-2">
|
||||
Financials
|
||||
</h3>
|
||||
<table className="w-full">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">Budget</td>
|
||||
<td className="text-gray-600 text-end">{budgetFormatted}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">Total Cost</td>
|
||||
<td className="text-gray-600 text-end">{totalCostFormatted}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">
|
||||
Total Value Increase
|
||||
</td>
|
||||
<td className="text-gray-600 text-end">
|
||||
{totalValueIncreaseFormatted}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">
|
||||
Annual rental yield Increase
|
||||
</td>
|
||||
<td className="text-gray-600 text-end">
|
||||
{rentalYieldIncreaseFormatted}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">
|
||||
Annual Energy Bill Savings
|
||||
</td>
|
||||
<td className="text-gray-600 text-end">
|
||||
{energyCostSavingsFormatted}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="p-4 bg-gray-50 rounded-lg">
|
||||
<h3 className="text-lg font-semibold text-gray-700 mb-2">
|
||||
Property Data
|
||||
</h3>
|
||||
<table className="w-full">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">
|
||||
Number of properties
|
||||
</td>
|
||||
<td className="text-gray-600 text-end">{properties.length}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">
|
||||
Total Works Time
|
||||
</td>
|
||||
<td className="text-gray-600 text-end">
|
||||
{totalWorkHoursFormatted}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="p-4 bg-gray-50 rounded-lg">
|
||||
<h3 className="text-lg font-semibold text-gray-700 mb-2">
|
||||
Environmental Impact
|
||||
</h3>
|
||||
<table className="w-full">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">
|
||||
Annual Co2 Savings
|
||||
</td>
|
||||
<td className="text-gray-600 text-end">
|
||||
{co2EquivalentSavingsFormatted}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-gray-700 font-semibold">
|
||||
Annual Energy Savings
|
||||
</td>
|
||||
<td className="text-gray-600 text-end">
|
||||
{energySavingsFormatted}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
searchParams,
|
||||
|
|
@ -112,6 +276,8 @@ export default async function Page({
|
|||
totalWorkHours,
|
||||
propertyValuationIncrease,
|
||||
rentalYieldIncrease,
|
||||
energySavings,
|
||||
energyCostSavings,
|
||||
} = await getPortfolio(portfolioId);
|
||||
|
||||
const properties: Property[] = [];
|
||||
|
|
@ -119,54 +285,33 @@ export default async function Page({
|
|||
return (
|
||||
<>
|
||||
<div className="flex justify-center">
|
||||
<h1 className="text-3xl text-brandblue font-bold mt-3 mb-4">
|
||||
Portfolio: {portfolioName}
|
||||
<h1 className="text-3xl text-gray-700 font-bold mt-3 mb-4">
|
||||
{portfolioName}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<div className="grid grid-cols-8 gap-4 w-full max-w-7xl">
|
||||
<div className="col-span-12 justify-center mb-4">
|
||||
<div className="grid grid-cols-8 w-full max-w-8xl">
|
||||
<div className="col-span-12 justify-center bg-gray-50 py-2">
|
||||
<Toolbar portfolioId={portfolioId} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<div className="grid grid-cols-8 gap-4 w-full max-w-7xl h-screen">
|
||||
<div className="col-span-2 flex-col">
|
||||
<div
|
||||
className="mb-4 max-h-96 bg-white p-4 rounded-lg border shadow-sm
|
||||
text-black h-1/2"
|
||||
>
|
||||
<h2 className="text-center text-xl font-bold mb-4 text-brandblue">
|
||||
Portfolio Summary
|
||||
</h2>
|
||||
<ul>
|
||||
<li className="text-gray-700 px-2 mb-2 flex items-center cursor-pointer hover:text-gray-200 hover:bg-brandblue hover:rounded-md transition-colors duration-200">
|
||||
Budget: {budget || "Not Set"}
|
||||
<PencilSquareIcon className="h-6 w-6 ml-2" />
|
||||
</li>
|
||||
<li className="text-gray-700 px-2 mb-2">
|
||||
Total Cost: £{totalCost}
|
||||
</li>
|
||||
<li className="text-gray-700 px-2 mb-2">
|
||||
Number of properties: {properties.length}
|
||||
</li>
|
||||
<li className="text-gray-700 px-2 mb-2">
|
||||
Annual Co2 Savings: {co2EquivalentSavings} tonnes
|
||||
</li>
|
||||
<li className="text-gray-700 px-2 mb-2">
|
||||
Total Works Time: {totalWorkHours} hours
|
||||
</li>
|
||||
<li className="text-gray-700 px-2 mb-2">
|
||||
Total Value Increase: £{propertyValuationIncrease}
|
||||
</li>
|
||||
<li className="text-gray-700 px-2 mb-2">
|
||||
Annual rental yield Increase: £{rentalYieldIncrease}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="grid grid-cols-11 w-full max-w-8xl h-screen">
|
||||
<div className="col-span-3 flex-col">
|
||||
<SummaryBox
|
||||
budget={budget}
|
||||
totalCost={totalCost}
|
||||
properties={properties}
|
||||
co2EquivalentSavings={co2EquivalentSavings}
|
||||
totalWorkHours={totalWorkHours}
|
||||
propertyValuationIncrease={propertyValuationIncrease}
|
||||
rentalYieldIncrease={rentalYieldIncrease}
|
||||
energySavings={energySavings}
|
||||
energyCostSavings={energyCostSavings}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-6 bg-white">
|
||||
<div className="col-span-8 bg-white">
|
||||
{properties.length === 0 ? (
|
||||
<EmptyPropertyState />
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import * as React from "react"
|
||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
|
||||
import { cva } from "class-variance-authority"
|
||||
import { ChevronDown } from "lucide-react"
|
||||
import * as React from "react";
|
||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
|
||||
import { cva } from "class-variance-authority";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const NavigationMenu = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
|
||||
|
|
@ -20,8 +20,8 @@ const NavigationMenu = React.forwardRef<
|
|||
{children}
|
||||
<NavigationMenuViewport />
|
||||
</NavigationMenuPrimitive.Root>
|
||||
))
|
||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
|
||||
));
|
||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
|
||||
|
||||
const NavigationMenuList = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.List>,
|
||||
|
|
@ -35,14 +35,14 @@ const NavigationMenuList = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
|
||||
));
|
||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
|
||||
|
||||
const NavigationMenuItem = NavigationMenuPrimitive.Item
|
||||
const NavigationMenuItem = NavigationMenuPrimitive.Item;
|
||||
|
||||
const navigationMenuTriggerStyle = cva(
|
||||
"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50"
|
||||
)
|
||||
"bg-gray-50 cursor-pointer group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-gray-200 hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50"
|
||||
);
|
||||
|
||||
const NavigationMenuTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
|
||||
|
|
@ -59,8 +59,8 @@ const NavigationMenuTrigger = React.forwardRef<
|
|||
aria-hidden="true"
|
||||
/>
|
||||
</NavigationMenuPrimitive.Trigger>
|
||||
))
|
||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
|
||||
));
|
||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
|
||||
|
||||
const NavigationMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
|
||||
|
|
@ -74,10 +74,10 @@ const NavigationMenuContent = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
|
||||
));
|
||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
|
||||
|
||||
const NavigationMenuLink = NavigationMenuPrimitive.Link
|
||||
const NavigationMenuLink = NavigationMenuPrimitive.Link;
|
||||
|
||||
const NavigationMenuViewport = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
|
||||
|
|
@ -93,9 +93,9 @@ const NavigationMenuViewport = React.forwardRef<
|
|||
{...props}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
));
|
||||
NavigationMenuViewport.displayName =
|
||||
NavigationMenuPrimitive.Viewport.displayName
|
||||
NavigationMenuPrimitive.Viewport.displayName;
|
||||
|
||||
const NavigationMenuIndicator = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
|
||||
|
|
@ -111,9 +111,9 @@ const NavigationMenuIndicator = React.forwardRef<
|
|||
>
|
||||
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
||||
</NavigationMenuPrimitive.Indicator>
|
||||
))
|
||||
));
|
||||
NavigationMenuIndicator.displayName =
|
||||
NavigationMenuPrimitive.Indicator.displayName
|
||||
NavigationMenuPrimitive.Indicator.displayName;
|
||||
|
||||
export {
|
||||
navigationMenuTriggerStyle,
|
||||
|
|
@ -125,4 +125,4 @@ export {
|
|||
NavigationMenuLink,
|
||||
NavigationMenuIndicator,
|
||||
NavigationMenuViewport,
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ module.exports = {
|
|||
"accordion-down": "accordion-down 0.2s ease-out",
|
||||
"accordion-up": "accordion-up 0.2s ease-out",
|
||||
},
|
||||
maxWidth: {
|
||||
"8xl": "90rem",
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue