Added core layout for the plan table

This commit is contained in:
Khalim Conn-Kowlessar 2023-05-31 09:15:29 +01:00
parent 4d6a38d163
commit bb1eff91d0
4 changed files with 256 additions and 46 deletions

View file

@ -0,0 +1,58 @@
import { Fragment } from "react";
import { Menu, Transition } from "@headlessui/react";
import { ChevronDownIcon } from "@heroicons/react/20/solid";
type Option = {
label: string;
value: string;
};
type DropdownProps = {
options: Option[];
onSelectOption: (option: Option) => void;
selectedOption: string;
};
export default function PartDropdown({
options,
onSelectOption,
selectedOption,
}: DropdownProps) {
return (
<Menu as="div" className="relative inline-block text-left w-full">
<Menu.Button className="inline-flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-brandblue rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
Selected option: {selectedOption ?? ""}{" "}
<ChevronDownIcon
className="ml-2 -mr-1 h-5 w-5 text-violet-200 hover:text-violet-100"
aria-hidden="true"
/>
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Menu.Items className="origin-bottom left-0 w-full rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
{options.map((option) => (
<Menu.Item key={option.value}>
{({ active }) => (
<button
className={`${
active ? "bg-brandmidblue text-white" : "text-gray-900"
} group flex items-center w-full px-4 py-2 text-sm`}
onClick={() => onSelectOption(option)}
>
{option.label}
</button>
)}
</Menu.Item>
))}
</Menu.Items>
</Transition>
</Menu>
);
}

View file

@ -0,0 +1,96 @@
import { Dialog, Transition } from "@headlessui/react";
import { Dispatch, Fragment, SetStateAction, useState } from "react";
import { TanButton } from "../Button";
import PartDropdown from "./PartDropdown";
export default function PartModal({
title,
isOpen,
setIsOpen,
options,
selectedOption,
setSelectedOption,
}: {
title: string;
isOpen: boolean;
setIsOpen: Dispatch<SetStateAction<boolean>>;
options: { label: string; value: string }[];
selectedOption: string;
setSelectedOption: Dispatch<SetStateAction<string>>;
}) {
function handleModalSubmit() {
// setTargetEpcRating(modalEpcTarget);
setIsOpen(false);
}
return (
<>
<Transition appear show={isOpen} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={() => setIsOpen(false)}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="w-1/2 max-w-screen-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 text-brandblue mb-3"
>
{title}
</Dialog.Title>
<div className="flex justify-center">
<div>
You can select different options for this part - this is
example functionality for demo
</div>
<PartDropdown
options={options}
onSelectOption={(option) =>
setSelectedOption(option.value)
}
selectedOption={selectedOption}
/>
</div>
<div className="mt-4 flex justify-end gap-2">
<button
type="button"
className="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={() => setIsOpen(false)}
>
Cancel
</button>
<TanButton label={"Save"} onClick={handleModalSubmit} />
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
</>
);
}

View file

@ -0,0 +1,58 @@
import { useState } from "react";
import PartModal from "./PartModal";
type PlanPartProps = {
title: string;
cost: number;
co2Emissions: number;
workHours: number;
};
export default function PlanPart({
title,
cost,
co2Emissions,
workHours,
}: PlanPartProps) {
const [isOpen, setIsOpen] = useState(false);
// These are temporary options for the demo
const options = [
{ label: "option 1", value: "option 1" },
{ label: "option 2", value: "option 2" },
{ label: "option 3", value: "option 3" },
{ label: "option 4", value: "option 4" },
{ label: "option 5", value: "option 5" },
];
const [selectedOption, setSelectedOption] = useState(options[0].value);
return (
<div
onClick={() => {
setIsOpen(true);
}}
className="active:bg-blue-700 focus:outline-none transition-colors duration-200 flex bg-white p-4 rounded-lg shadow mb-4 items-center border-l-4 border-l-brandmidblue hover:bg-brandmidblue hover:text-white hover:border-l-brandtan cursor-pointer"
>
<h2 className="flex-1 text-lg font-bold mb-2 text-left">{title}</h2>
<div>{selectedOption}</div>
<div className="flex-1 text-center">
<p>Cost: {cost}</p>
</div>
<div className="flex-1 text-center">
<p>CO2 Emissions: {co2Emissions}</p>
</div>
<div className="flex-1 text-center">
<p>Work Hours: {workHours}</p>
</div>
<PartModal
title={title}
isOpen={isOpen}
setIsOpen={setIsOpen}
options={options}
selectedOption={selectedOption}
setSelectedOption={setSelectedOption}
/>
</div>
);
}

View file

@ -5,40 +5,8 @@ import { useQuery } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { fetchData } from "../utils";
import { useState } from "react";
import React from "react";
import { PencilSquareIcon } from "@heroicons/react/24/outline";
type PlanPartProps = {
title: string;
cost: number;
co2Emissions: number;
workHours: number;
};
const PlanPart: React.FC<PlanPartProps> = ({
title,
cost,
co2Emissions,
workHours,
}) => {
return (
<div className="flex bg-white p-4 rounded-lg shadow mb-4 items-center border-l-4 border-l-brandmidblue hover:bg-brandmidblue hover:text-white hover:border-l-brandtan cursor-pointer">
<div className="flex-1">
<h2 className="text-lg font-bold mb-2">{title}</h2>
</div>
<div className="flex-1 text-center">
<p>Cost: {cost}</p>
</div>
<div className="flex-1 text-center">
<p>CO2 Emissions: {co2Emissions}</p>
</div>
<div className="flex-1 text-center">
<p>Work Hours: {workHours}</p>
</div>
</div>
);
};
import PlanPart from "@/app/components/plan/PlanPart";
export default function Plan({
params,
@ -58,6 +26,37 @@ export default function Plan({
const [totalCost, setTotalCost] = useState("Not set");
const [installTime, setInstallTime] = useState("Not set");
const partsConfig = [
{ part: "Roof", cost: 1000, co2Emissions: 50, workHours: 20 },
{ part: "Walls", cost: 1000, co2Emissions: 50, workHours: 20 },
{ part: "Floors", cost: 1000, co2Emissions: 50, workHours: 20 },
{ part: "Window Glazing", cost: 1000, co2Emissions: 50, workHours: 20 },
{
part: "Window Draughproofing",
cost: 1000,
co2Emissions: 50,
workHours: 20,
},
{ part: "Door Insulation", cost: 1000, co2Emissions: 50, workHours: 20 },
{
part: "Door Draughproofing",
cost: 1000,
co2Emissions: 50,
workHours: 20,
},
{ part: "Heating", cost: 1000, co2Emissions: 50, workHours: 20 },
{ part: "Hot Water", cost: 1000, co2Emissions: 50, workHours: 20 },
{ part: "Solar Panels", cost: 1000, co2Emissions: 50, workHours: 20 },
{ part: "Solar Hot Water", cost: 1000, co2Emissions: 50, workHours: 20 },
{ part: "Lighting", cost: 1000, co2Emissions: 50, workHours: 20 },
{
part: "Chimneys/ Open Fire Places",
cost: 1000,
co2Emissions: 50,
workHours: 20,
},
];
if (postcode === undefined) {
router.push(`/portfolio/${portfolioId}/error`);
}
@ -79,25 +78,24 @@ export default function Plan({
const propertyData = data.rows.filter((row) => row["lmk-key"] === lmkKey)[0];
return (
<section>
<div className="max-w-5xl mx-auto p-6 flex flex-col items-center">
<div className="max-w-6xl mx-auto p-6 flex flex-col items-center">
<div className="text-center mb-4">
<h1 className="text-2xl font-bold">Your Retrofit Plan</h1>
<p>{propertyData.address}</p>
</div>
<div className="flex w-full">
<div className="w-3/4 pr-4">
{/* Clickable Cards */}
{/* Replace this with your actual clickable cards */}
<PlanPart
title="Plan Part 1"
cost={1000}
co2Emissions={50}
workHours={20}
/>
<div className="bg-white p-4 rounded-lg shadow mb-4">
Clickable Card 2
</div>
{/* Add more clickable cards as needed */}
{partsConfig.map((part, index) => {
return (
<PlanPart
key={index}
title={part.part}
cost={part.cost}
co2Emissions={part.co2Emissions}
workHours={part.workHours}
/>
);
})}
</div>
<div className="w-1/4 ">
<div className="bg-brandmidblue p-4 rounded-lg shadow text-white ">