mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-30 12:55:02 +00:00
Made multiple ui improvements
This commit is contained in:
parent
3bc12fdfdb
commit
083aff0d4a
3 changed files with 191 additions and 109 deletions
109
src/app/components/StatusBadge.tsx
Normal file
109
src/app/components/StatusBadge.tsx
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
"use client";
|
||||
|
||||
import { PortfolioStage } from "@/types/portfolio";
|
||||
import { Badge } from "@/app/shadcn_components/ui/badge";
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from "@/app/shadcn_components/ui/hover-card";
|
||||
|
||||
export default function StatusBadge({
|
||||
status,
|
||||
isProperty = false,
|
||||
}: {
|
||||
status: PortfolioStage;
|
||||
isProperty?: boolean;
|
||||
}) {
|
||||
const statusConfig = statusColor[status];
|
||||
|
||||
return (
|
||||
<div className="flex justify-end w-full pr-4">
|
||||
<HoverCard>
|
||||
<HoverCardTrigger>
|
||||
<Badge className={statusConfig.class}>{statusConfig.text}</Badge>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent>
|
||||
<div className="flex items-center">
|
||||
<div>
|
||||
<div
|
||||
className={"w-6 h-6 rounded-full mr-2 " + statusConfig.class}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{!isProperty
|
||||
? statusConfig.hoverText
|
||||
: statusConfig.propertyHoverText}
|
||||
</p>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const statusColor: {
|
||||
[key in PortfolioStage]: {
|
||||
class: string;
|
||||
text: string;
|
||||
hoverText: string;
|
||||
propertyHoverText: string;
|
||||
};
|
||||
} = {
|
||||
scoping: {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "scoping",
|
||||
hoverText: "This portfolio is currently in scoping",
|
||||
propertyHoverText: "This property is currently in scoping",
|
||||
},
|
||||
assessment: {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "assessment",
|
||||
hoverText: "This portfolio is currently in the assessment stage",
|
||||
propertyHoverText: "This property is currently in the assessment stage",
|
||||
},
|
||||
tendering: {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "tendering",
|
||||
hoverText: "This portfolio is currently in the tendering stage",
|
||||
propertyHoverText: "This property is currently in tender",
|
||||
},
|
||||
"project underway": {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "project underway",
|
||||
hoverText: "This portfolio has begun works",
|
||||
propertyHoverText: "This property has begun works",
|
||||
},
|
||||
"completion; status 'on track'": {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "on track",
|
||||
hoverText: "This portfolio is on track to be completed on time",
|
||||
propertyHoverText: "This property is on track to be completed on time",
|
||||
},
|
||||
"completion; status 'delayed'": {
|
||||
class: "bg-orange-400 hover:bg-orange-400",
|
||||
text: "delayed",
|
||||
hoverText:
|
||||
"This portfolio is delayed and one or more properties require attention",
|
||||
propertyHoverText: "This property is delayed and requires attention",
|
||||
},
|
||||
"completion; status 'at risk'": {
|
||||
class: "bg-red-400 hover:bg-red-400",
|
||||
text: "at risk",
|
||||
hoverText:
|
||||
"This portfolio is at risk. One or more properties require attention",
|
||||
propertyHoverText: "This property is at risk and requires attention",
|
||||
},
|
||||
"completion; status 'completed'": {
|
||||
class: "bg-gray-400 hover:bg-gray-400",
|
||||
text: "completed",
|
||||
hoverText: "This portfolio has been completed",
|
||||
propertyHoverText: "This property has been completed",
|
||||
},
|
||||
"needs review": {
|
||||
class: "bg-emerald-300 hover:bg-emerald-300",
|
||||
text: "needs review",
|
||||
hoverText: "The works in this portfolio has been completed and need review",
|
||||
propertyHoverText: "The works on this property have been completed",
|
||||
},
|
||||
};
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
import { PortfolioStage } from "@/types/portfolio";
|
||||
import Link from "next/link";
|
||||
import React from "react";
|
||||
import { Badge } from "@/app/shadcn_components/ui/badge";
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from "@/app/shadcn_components/ui/hover-card";
|
||||
import React, { use } from "react";
|
||||
import StatusBadge from "@/app/components/StatusBadge";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
const styles = {
|
||||
wrapper:
|
||||
"font-medium leading-none text-base tracking-wider text-gray-400 hover:text-gray-300 bg-white hover:bg-hoverblue shadow-xl hover:shadow-none cursor-pointer w-60 rounded-3xl flex flex-col items-center justify-center",
|
||||
"active:bg-brandmidblue font-medium leading-none text-base tracking-wider text-gray-400 hover:text-gray-300 bg-white hover:bg-hoverblue shadow-xl hover:shadow-none cursor-pointer w-60 rounded-3xl flex flex-col items-center justify-center",
|
||||
header: "relative mt-2 mx-2 border-red",
|
||||
imageWrapper: "h-56 rounded-2xl overflow-hidden flex items-center",
|
||||
wrapperAnime: "transition-all duration-500 ease-in-out",
|
||||
|
|
@ -26,88 +22,19 @@ interface CardProps {
|
|||
status: PortfolioStage;
|
||||
}
|
||||
|
||||
function StatusBadge({ status }: { status: PortfolioStage }) {
|
||||
const statusConfig = statusColor[status];
|
||||
|
||||
return (
|
||||
<div className="flex justify-end w-full mb-1 pr-4">
|
||||
<HoverCard>
|
||||
<HoverCardTrigger>
|
||||
<Badge className={statusConfig.class}>{statusConfig.text}</Badge>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent>
|
||||
<div className="flex items-center">
|
||||
<div>
|
||||
<div
|
||||
className={"w-6 h-6 rounded-full mr-2 " + statusConfig.class}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{statusConfig.hoverText}
|
||||
</p>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const statusColor: {
|
||||
[key in PortfolioStage]: { class: string; text: string; hoverText: string };
|
||||
} = {
|
||||
scoping: {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "scoping",
|
||||
hoverText: "This portfolio is currently in scoping",
|
||||
},
|
||||
assessment: {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "assessment",
|
||||
hoverText: "This portfolio is currently in the assessment stage",
|
||||
},
|
||||
tendering: {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "tendering",
|
||||
hoverText: "This portfolio is currently in the tendering stage",
|
||||
},
|
||||
"project underway": {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "project underway",
|
||||
hoverText: "This portfolio has begun works",
|
||||
},
|
||||
"completion; status 'on track'": {
|
||||
class: "bg-emerald-500 hover:bg-emerald-500",
|
||||
text: "on track",
|
||||
hoverText: "This portfolio is on track to be completed on time",
|
||||
},
|
||||
"completion; status 'delayed'": {
|
||||
class: "bg-orange-400 hover:bg-orange-400",
|
||||
text: "delayed",
|
||||
hoverText:
|
||||
"This portfolio is delayed and one or more properties require attention",
|
||||
},
|
||||
"completion; status 'at risk'": {
|
||||
class: "bg-red-400 hover:bg-red-400",
|
||||
text: "at risk",
|
||||
hoverText:
|
||||
"This portfolio is at risk. One or more properties require attention",
|
||||
},
|
||||
"completion; status 'completed'": {
|
||||
class: "bg-gray-400 hover:bg-gray-400",
|
||||
text: "completed",
|
||||
hoverText: "This portfolio has been completed",
|
||||
},
|
||||
"needs review": {
|
||||
class: "bg-emerald-300 hover:bg-emerald-300",
|
||||
text: "needs review",
|
||||
hoverText: "The works in this portfolio has been completed and need review",
|
||||
},
|
||||
};
|
||||
|
||||
const Card = ({ id, title, image, budget, status }: CardProps) => {
|
||||
const router = useRouter();
|
||||
|
||||
function handleClick() {
|
||||
router.push(`/portfolio/${id}`);
|
||||
}
|
||||
|
||||
return (
|
||||
<Link href={`/portfolio/${id}`}>
|
||||
<div className={[styles.wrapper, styles.wrapperAnime].join(" ")}>
|
||||
<div>
|
||||
<div
|
||||
onClick={handleClick}
|
||||
className={[styles.wrapper, styles.wrapperAnime].join(" ")}
|
||||
>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.imageWrapper}>
|
||||
<img src={image} className={styles.image} alt="" />
|
||||
|
|
@ -117,9 +44,11 @@ const Card = ({ id, title, image, budget, status }: CardProps) => {
|
|||
<h1>{`${title}`}</h1>
|
||||
<div>{budget}</div>
|
||||
</div>
|
||||
<StatusBadge status={status} />
|
||||
<div className="mb-2 flex justify-end w-full">
|
||||
<StatusBadge status={status} />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,16 @@ import AddNew from "../../components/portfolio/AddNew";
|
|||
import { formatNumber } from "@/app/utils";
|
||||
import Link from "next/link";
|
||||
import { SearchData } from "@/types/epc";
|
||||
import { ArrowRightCircleIcon } from "@heroicons/react/20/solid";
|
||||
import { Badge } from "@/app/shadcn_components/ui/badge";
|
||||
import { PortfolioStage } from "@/types/portfolio";
|
||||
import StatusBadge from "@/app/components/StatusBadge";
|
||||
|
||||
function generateProperties(value: number, suffix: string) {
|
||||
function generateProperties(
|
||||
value: number,
|
||||
suffix: string,
|
||||
status: PortfolioStage
|
||||
) {
|
||||
const length = Math.ceil(value / 30000);
|
||||
|
||||
return Array.from({ length }, (_, index) => ({
|
||||
|
|
@ -15,6 +23,7 @@ function generateProperties(value: number, suffix: string) {
|
|||
cost: 30000,
|
||||
co2Reduction: 9 / 5,
|
||||
targetEpcRating: "C",
|
||||
status: status,
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -26,6 +35,7 @@ type Property = {
|
|||
co2Reduction: number;
|
||||
lmkKey: string;
|
||||
targetEpcRating: string;
|
||||
status: PortfolioStage;
|
||||
};
|
||||
|
||||
function EmptyPropertyState() {
|
||||
|
|
@ -54,27 +64,41 @@ function Propertycards({
|
|||
{properties.map((property) => (
|
||||
<li
|
||||
key={property.id}
|
||||
className="border-l-4 border-l-brandmidblue bg-white rounded-lg shadow mb-4 p-4 flex items-center justify-between"
|
||||
className="bg-white rounded-lg shadow mb-4 p-4 flex items-center justify-between"
|
||||
>
|
||||
<div className="flex items-center ">
|
||||
<div>
|
||||
<HomeIcon className="h-10 w-10 mx-auto text-gray-200" />
|
||||
<HomeIcon className="h-8 w-8 mx-auto text-gray-200" />
|
||||
</div>
|
||||
<div className="ml-4 ">
|
||||
<h3 className="text-xl font-medium">{property.address}</h3>
|
||||
<p className="text-gray-600">{property.postcode}</p>
|
||||
<h3 className="text-xl font-medium font-semibold text-brandblue">
|
||||
{property.address}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{property.postcode}
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-10">
|
||||
<Badge className="bg-brandblue">
|
||||
Cost: £{formatNumber(property.cost)}
|
||||
</Badge>
|
||||
</div>
|
||||
<div className="ml-10">Cost: £{formatNumber(property.cost)}</div>
|
||||
<div className="ml-4">
|
||||
Co2 Savings (t): {property.co2Reduction}
|
||||
<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}`}
|
||||
className="bg-brandtan text-white rounded-lg px-4 py-2 hover:bg-hovertan transition-colors duration-200"
|
||||
>
|
||||
Go to Plan
|
||||
<div className="w-10 h-10">
|
||||
<ArrowRightCircleIcon className="text-brandblue" />
|
||||
</div>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
|
|
@ -101,7 +125,7 @@ export default async function Page({
|
|||
id: "d290f1ee-6c54-4b01-90e6-d701748f0851",
|
||||
title: "Portfolio 1",
|
||||
budget: 500000,
|
||||
properties: generateProperties(500000, "1") as Property[],
|
||||
properties: generateProperties(500000, "1", "scoping") as Property[],
|
||||
co2Reduction: 5.4,
|
||||
totalWorksHours: 45,
|
||||
totalValueIncrease: 500000 * 1.2,
|
||||
|
|
@ -116,7 +140,7 @@ export default async function Page({
|
|||
totalWorksHours: 30,
|
||||
totalValueIncrease: 150000 * 1.2,
|
||||
rentalYieldIncrease: 150000 * 0.002,
|
||||
properties: generateProperties(150000, "2") as Property[],
|
||||
properties: generateProperties(150000, "2", "assessment") as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0853",
|
||||
|
|
@ -127,7 +151,7 @@ export default async function Page({
|
|||
totalWorksHours: 100,
|
||||
totalValueIncrease: 1000000 * 1.2,
|
||||
rentalYieldIncrease: 1000000 * 0.002,
|
||||
properties: generateProperties(1000000, "3") as Property[],
|
||||
properties: generateProperties(1000000, "3", "tendering") as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0854",
|
||||
|
|
@ -138,7 +162,7 @@ export default async function Page({
|
|||
totalWorksHours: 150,
|
||||
totalValueIncrease: 2000000 * 1.2,
|
||||
rentalYieldIncrease: 2000000 * 0.002,
|
||||
properties: generateProperties(2000000, "4") as Property[],
|
||||
properties: generateProperties(2000000, "4", "tendering") as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0855",
|
||||
|
|
@ -149,7 +173,11 @@ export default async function Page({
|
|||
totalWorksHours: 15,
|
||||
totalValueIncrease: 250000 * 1.2,
|
||||
rentalYieldIncrease: 250000 * 0.002,
|
||||
properties: generateProperties(250000, "5") as Property[],
|
||||
properties: generateProperties(
|
||||
250000,
|
||||
"5",
|
||||
"project underway"
|
||||
) as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0856",
|
||||
|
|
@ -160,7 +188,11 @@ export default async function Page({
|
|||
totalWorksHours: 10,
|
||||
totalValueIncrease: 410000 * 1.2,
|
||||
rentalYieldIncrease: 410000 * 0.002,
|
||||
properties: generateProperties(410000, "6") as Property[],
|
||||
properties: generateProperties(
|
||||
410000,
|
||||
"6",
|
||||
"completion; status 'on track'"
|
||||
) as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0857",
|
||||
|
|
@ -171,7 +203,11 @@ export default async function Page({
|
|||
totalWorksHours: 25,
|
||||
totalValueIncrease: 233000 * 1.2,
|
||||
rentalYieldIncrease: 233000 * 0.002,
|
||||
properties: generateProperties(233000, "7") as Property[],
|
||||
properties: generateProperties(
|
||||
233000,
|
||||
"7",
|
||||
"completion; status 'delayed'"
|
||||
) as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0858",
|
||||
|
|
@ -182,7 +218,11 @@ export default async function Page({
|
|||
totalWorksHours: 65,
|
||||
totalValueIncrease: 670000 * 1.2,
|
||||
rentalYieldIncrease: 670000 * 0.002,
|
||||
properties: generateProperties(670000, "8") as Property[],
|
||||
properties: generateProperties(
|
||||
670000,
|
||||
"8",
|
||||
"completion; status 'at risk'"
|
||||
) as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0859",
|
||||
|
|
@ -193,7 +233,11 @@ export default async function Page({
|
|||
totalWorksHours: 40,
|
||||
totalValueIncrease: 240000 * 1.2,
|
||||
rentalYieldIncrease: 240000 * 0.002,
|
||||
properties: generateProperties(240000, "9") as Property[],
|
||||
properties: generateProperties(
|
||||
240000,
|
||||
"9",
|
||||
"completion; status 'completed'"
|
||||
) as Property[],
|
||||
},
|
||||
{
|
||||
id: "d290f1ee-6c54-4b01-90e6-d701748f0860",
|
||||
|
|
@ -204,7 +248,7 @@ export default async function Page({
|
|||
totalWorksHours: 18,
|
||||
totalValueIncrease: 93000 * 1.2,
|
||||
rentalYieldIncrease: 93000 * 0.002,
|
||||
properties: generateProperties(93000, "10") as Property[],
|
||||
properties: generateProperties(93000, "10", "needs review") as Property[],
|
||||
},
|
||||
];
|
||||
const demo_id = "f290f1ee-6c54-4b01-90e6-d701748f0851";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue