Tidying up layout on portfolio screen

This commit is contained in:
Khalim Conn-Kowlessar 2023-07-12 18:04:13 +01:00
parent 40926b7106
commit 8d2db50d1c
5 changed files with 217 additions and 85 deletions

View file

@ -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

View file

@ -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

View file

@ -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 />
) : (

View file

@ -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,
}
};

View file

@ -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: {