mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-30 12:55:02 +00:00
Added budget updates
This commit is contained in:
parent
380f9bfe9b
commit
94e1cc5973
4 changed files with 131 additions and 5 deletions
94
src/app/components/plan/BudgetModal.tsx
Normal file
94
src/app/components/plan/BudgetModal.tsx
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { Dispatch, Fragment, SetStateAction, useState } from "react";
|
||||
import { TanButton } from "../Buttons";
|
||||
|
||||
export default function BudgetModal({
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
budget,
|
||||
setBudget,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
||||
budget: number | "Not set";
|
||||
setBudget: Dispatch<SetStateAction<number | "Not set">>;
|
||||
}) {
|
||||
const [budgetInput, setBudgetInput] = useState<number | null>(null);
|
||||
|
||||
function handleSubmit() {
|
||||
if (budgetInput !== null) {
|
||||
setBudget(budgetInput);
|
||||
}
|
||||
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"
|
||||
>
|
||||
{"Set a Budget"}
|
||||
</Dialog.Title>
|
||||
<div className="flex justify-center">
|
||||
<input
|
||||
id="search"
|
||||
className="w-full appearance-none rounded border-2 border-gray-200 bg-gray-200 px-8 py-2 leading-tight text-gray-700 focus:border-brandmidblue focus:bg-white focus:outline-none"
|
||||
type="number"
|
||||
placeholder="Set your budget "
|
||||
onChange={(e) => setBudgetInput(Number(e.target.value))}
|
||||
onKeyDown={(e) =>
|
||||
(e.key === "e" || e.key === "E") && e.preventDefault()
|
||||
}
|
||||
/>
|
||||
</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={handleSubmit} />
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -19,7 +19,8 @@ export default function PartModal({
|
|||
setSelectedOption: Dispatch<SetStateAction<string>>;
|
||||
}) {
|
||||
function handleModalSubmit() {
|
||||
// setTargetEpcRating(modalEpcTarget);
|
||||
// Right now the dropdown is setting the state on the selected option so we might not need
|
||||
// to do anything here
|
||||
setIsOpen(false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import { PencilSquareIcon } from "@heroicons/react/24/outline";
|
|||
import PlanPart from "@/app/components/plan/PlanPart";
|
||||
import EditEpctargetModal from "@/app/components/property/EditEpcTargetModal";
|
||||
import Link from "next/link";
|
||||
import BudgetModal from "@/app/components/plan/BudgetModal";
|
||||
import { formatNumber } from "@/app/utils";
|
||||
|
||||
export default function Plan({
|
||||
params,
|
||||
|
|
@ -62,10 +64,11 @@ export default function Plan({
|
|||
|
||||
const partsTotalCost = partsConfig.reduce((sum, part) => sum + part.cost, 0);
|
||||
|
||||
const [budget, setBudget] = useState("Not set");
|
||||
const [budget, setBudget] = useState<number | "Not set">("Not set");
|
||||
const [totalCost, setTotalCost] = useState(partsTotalCost);
|
||||
const [installTime, setInstallTime] = useState(totalWorkHours);
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
const [isBudgetModalOpen, setIsBudgetModalOpen] = useState(false);
|
||||
const [targetEpcRating, setTargetEpcRating] = useState<EpcRating | "">(
|
||||
(searchParams.targetEpcRating as EpcRating) ?? "C"
|
||||
);
|
||||
|
|
@ -122,10 +125,12 @@ export default function Plan({
|
|||
<PencilSquareIcon className="h-6 w-6 ml-2" />
|
||||
</li>
|
||||
<li
|
||||
onClick={() => console.log("clicked")}
|
||||
onClick={() => setIsBudgetModalOpen(true)}
|
||||
className="px-2 mb-2 flex items-center cursor-pointer hover:bg-brandblue hover:rounded-md transition-colors duration-200"
|
||||
>
|
||||
Budget: {budget}
|
||||
{budget !== "Not set"
|
||||
? "Budget: £" + formatNumber(budget)
|
||||
: "Budget: " + budget}
|
||||
<PencilSquareIcon className="h-6 w-6 ml-2" />
|
||||
</li>
|
||||
<Link
|
||||
|
|
@ -137,7 +142,6 @@ export default function Plan({
|
|||
</li>
|
||||
</Link>
|
||||
<li className="px-2 mb-2">Total cost: £{totalCost}</li>
|
||||
|
||||
<li className="px-2 mb-2">
|
||||
Installation Time: {installTime} hours
|
||||
</li>
|
||||
|
|
@ -153,6 +157,12 @@ export default function Plan({
|
|||
targetEpcRating={targetEpcRating}
|
||||
currentEpcRating={propertyData["current-energy-rating"]}
|
||||
/>
|
||||
<BudgetModal
|
||||
isOpen={isBudgetModalOpen}
|
||||
setIsOpen={setIsBudgetModalOpen}
|
||||
budget={budget}
|
||||
setBudget={setBudget}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
21
src/app/utils.ts
Normal file
21
src/app/utils.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
export function formatNumber(number: number): string {
|
||||
const suffixes: string[] = ["", "k", "m", "b", "t"];
|
||||
const suffixIndex: number = Math.floor(Math.log10(Math.abs(number)) / 3);
|
||||
|
||||
// Check if the suffix index is within the available suffixes
|
||||
if (suffixIndex >= suffixes.length) {
|
||||
return number.toString(); // Return the number as is
|
||||
}
|
||||
|
||||
// Check if the number is smaller and round to 2 decimal places
|
||||
const roundedNumber: number =
|
||||
Math.abs(number) < 1000
|
||||
? Number(number.toFixed(2))
|
||||
: Number(number.toPrecision(4));
|
||||
|
||||
const formattedNumber: string = (
|
||||
roundedNumber / Math.pow(1000, suffixIndex)
|
||||
).toString();
|
||||
|
||||
return formattedNumber + suffixes[suffixIndex];
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue