From b8051ad1e3436c96bd88284f0341b53f98670920 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Thu, 23 Oct 2025 19:48:49 +0000 Subject: [PATCH 1/4] refactor code --- .../BuildingPassportHomeClient.tsx | 120 ++++++++++++++++++ .../building-passport/[propertyId]/page.tsx | 74 ++--------- .../[slug]/components/BookSurveyModal.tsx | 4 +- .../components/propertyTableColumns.tsx | 28 ---- 4 files changed, 134 insertions(+), 92 deletions(-) create mode 100644 src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx new file mode 100644 index 00000000..9ab29b71 --- /dev/null +++ b/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx @@ -0,0 +1,120 @@ +"use client"; + +import { useState } from "react"; +import EpcCard from "@/app/components/building-passport/EpcCard"; +import { Button } from "@/app/shadcn_components/ui/button"; +import { formatDateTime } from "@/app/utils"; +import { + CalendarIcon, + HomeIcon, + BuildingOfficeIcon, + ClockIcon, + UserGroupIcon, + HomeModernIcon, +} from "@heroicons/react/24/solid"; +import BookSurveyModal from "../../components/BookSurveyModal"; +import BookingSuccessToast from "../../components/BookingSuccessToast"; + +interface BuildingPassportHomeClientProps { + propertyMeta: any; + portfolioId: string; // ✅ from URL (slug) +} + +export default function BuildingPassportHomeClient({ + propertyMeta, + portfolioId, +}: BuildingPassportHomeClientProps) { + const [openModal, setOpenModal] = useState(false); + const [showToast, setShowToast] = useState(false); + console.log(portfolioId) + console.log(propertyMeta) + + return ( +
+ {/* EPC Card + Property Info */} +
+ {/* EPC Rating Card */} + + + {/* Property Info Card */} +
+
Your Property
+ +
+ +
Building Passport Created At:
+
{formatDateTime(propertyMeta.createdAt)}
+
+ +
+ +
Property Type:
+
{propertyMeta.propertyType}
+
+ +
+ +
Built Form:
+
{propertyMeta.builtForm}
+
+ +
+ +
Year Built:
+
{propertyMeta.yearBuilt}
+
+ +
+ +
Tenure:
+
{propertyMeta.tenure}
+
+ +
+ +
Number of Habitable Rooms:
+
{propertyMeta.numberOfRooms}
+
+
+
+ + {/* ✅ "Book a Survey" Button */} +
+ +
+ + {/* ✅ Modal for booking a survey */} + {openModal && ( + { + setOpenModal(false); + setShowToast(true); + }} + /> + )} + + {/* ✅ Success Toast */} + setShowToast(false)} + message="Survey Booked Successfully!" + subtext="Your survey request has been sent to Domna. We'll contact you shortly. 🎉" + /> +
+ ); +} diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx index ccb05275..326b6739 100644 --- a/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx +++ b/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx @@ -1,70 +1,20 @@ -import EpcCard from "@/app/components/building-passport/EpcCard"; -import { formatDateTime } from "@/app/utils"; -import { - HomeIcon, - BuildingOfficeIcon, - CalendarIcon, - HomeModernIcon, - ClockIcon, - UserGroupIcon, -} from "@heroicons/react/24/solid"; import { getPropertyMeta } from "./utils"; +import BuildingPassportHomeClient from "./BuildingPassportHomeClient"; export const revalidate = 1; -export default async function BuildingPassportHome( - props: { - params: Promise<{ slug: string; propertyId: string }>; - } -) { - const params = await props.params; - // This is a server component and because we make the exact same request in the layout, - // the response is cached so we just gain access to the data +export default async function BuildingPassportHome({ + params, +}: { + params: { slug: string; propertyId: string }; +}) { const propertyMeta = await getPropertyMeta(params.propertyId); + // ✅ pass both property data and the portfolio slug (from the URL) return ( -
-
- -
-
Your property
-
- -
Building Passport Created At:
-
{formatDateTime(propertyMeta.createdAt)}
-
-
- -
Property Type:
-
{propertyMeta.propertyType}
-
-
- -
Built Form:
-
{propertyMeta.builtForm}
-
-
- -
Year Built:
-
{propertyMeta.yearBuilt}
-
-
- -
Tenure:
-
{propertyMeta.tenure}
-
-
- -
Number of Habitable Rooms:
-
{propertyMeta.numberOfRooms}
-
-
-
-
+ ); -} +} \ No newline at end of file diff --git a/src/app/portfolio/[slug]/components/BookSurveyModal.tsx b/src/app/portfolio/[slug]/components/BookSurveyModal.tsx index bd599ce8..39f6651f 100644 --- a/src/app/portfolio/[slug]/components/BookSurveyModal.tsx +++ b/src/app/portfolio/[slug]/components/BookSurveyModal.tsx @@ -17,7 +17,7 @@ interface BookSurveyModalProps { open: boolean; onOpenChange: (open: boolean) => void; propertyId: bigint; - portfolioId: bigint; + portfolioId: string; address: string; onSuccess?: () => void; // ✅ fix: properly declare optional callback } @@ -41,7 +41,7 @@ export default function BookSurveyModal({ pipelineId: "2400089278", dealStageId: "3288115388", propertyId: propertyId.toString(), - portfolioId: portfolioId.toString(), + portfolioId: portfolioId, }), }); diff --git a/src/app/portfolio/[slug]/components/propertyTableColumns.tsx b/src/app/portfolio/[slug]/components/propertyTableColumns.tsx index 52307c13..c65a7743 100644 --- a/src/app/portfolio/[slug]/components/propertyTableColumns.tsx +++ b/src/app/portfolio/[slug]/components/propertyTableColumns.tsx @@ -21,9 +21,6 @@ import { PropertyToRecommendation, PropertyWithRelations, } from "@/app/db/schema/property"; -import BookSurveyModal from "./BookSurveyModal"; -import BookingSuccessToast from "./BookingSuccessToast"; -import { useState } from "react"; interface DataTableColumnHeaderProps @@ -218,10 +215,7 @@ export const columns: ColumnDef[] = [ { id: "actions", cell: ({ row }) => { - const [openModal, setOpenModal] = useState(false); - const [showToast, setShowToast] = useState(false); const property = row.original; - const address = String(row.getValue("address")); const propertyId = property.id; const portfolioId = property.portfolioId; @@ -246,9 +240,6 @@ export const columns: ColumnDef[] = [ Actions - setOpenModal(true)}> - Book a survey - navigator.clipboard.writeText(payment.id)} className="text-gray-700 cursor-pointer" @@ -268,25 +259,6 @@ export const columns: ColumnDef[] = [ - {/* ✅ Render modal outside dropdown context */} - {openModal && ( - setShowToast(true)} - /> - )} - - {/* 💥 Toast */} - setShowToast(false)} - message="Survey Booked Successfully!" - subtext="Your Survey Request is with Domna and will be in contact with you shortly. 🎉" - /> ); }, From d156ce2b4562353ca43fb83190926af8a6a630d2 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Thu, 23 Oct 2025 20:18:09 +0000 Subject: [PATCH 2/4] new lay out --- .../components/building-passport/Toolbar.tsx | 98 ++++++++++++++----- .../BuildingPassportHomeClient.tsx | 27 ----- .../building-passport/[propertyId]/layout.tsx | 1 + .../building-passport/[propertyId]/page.tsx | 72 +++++++++++--- 4 files changed, 133 insertions(+), 65 deletions(-) diff --git a/src/app/components/building-passport/Toolbar.tsx b/src/app/components/building-passport/Toolbar.tsx index b0759e4e..8d74d524 100644 --- a/src/app/components/building-passport/Toolbar.tsx +++ b/src/app/components/building-passport/Toolbar.tsx @@ -1,5 +1,6 @@ "use client"; +import { useState } from "react"; import { Cog6ToothIcon, NewspaperIcon, @@ -8,6 +9,7 @@ import { SunIcon, CircleStackIcon, HeartIcon, + CalendarDaysIcon, } from "@heroicons/react/24/outline"; import { NavigationMenu, @@ -15,12 +17,17 @@ import { NavigationMenuList, NavigationMenuLink, } from "@/app/shadcn_components/ui/navigation-menu"; +import { Button } from "@/app/shadcn_components/ui/button"; import { cva } from "class-variance-authority"; import { getUploadedFile } from "@/app/db/surveyDB/schema/surveyDB"; +import BookSurveyModal from "@/app/portfolio/[slug]/components/BookSurveyModal"; +import BookingSuccessToast from "@/app/portfolio/[slug]/components/BookingSuccessToast"; +import { PropertyMeta } from "@/app/db/schema/property"; interface ToolbarProps { propertyId: string; portfolioId: string; + propertyMeta: PropertyMeta decentHomes: getUploadedFile; } @@ -50,7 +57,6 @@ const navigationMenuTriggerStyle = cva( "disabled:opacity-50", "data-[active]:bg-accent/50", "data-[state=open]:bg-gray-200", - // "text-gray-900", ].join(" ") ); @@ -58,8 +64,12 @@ const navigationMenuTriggerStyle = cva( export function Toolbar({ propertyId, portfolioId, + propertyMeta, decentHomes, }: ToolbarProps) { + const [openModal, setOpenModal] = useState(false); + const [showToast, setShowToast] = useState(false); + function handleClickSettings() { console.log("Settings were clicked, implement me"); } @@ -115,33 +125,67 @@ export function Toolbar({ ); return ( - - - - Summary - + <> +
+ {/* Left side: navigation */} + + + + Summary + - - {preAssessmentReportButton} - {/* We only show decent homes button if decent homes is not an empty object */} - {Object.keys(decentHomes).length > 0 && - decentHomes.uprn && - decentHomesButton} - {solarAnalysisButton} - {recommendationsButton} - {documentsButton} + + {preAssessmentReportButton} + {Object.keys(decentHomes).length > 0 && + decentHomes.uprn && + decentHomesButton} + {solarAnalysisButton} + {recommendationsButton} + {documentsButton} - - - Settings - - - + + + Settings + + + + + {/* ✅ Right side: Book a Survey button */} +
+ +
+
+ + {/* ✅ Modal */} + {openModal && ( + setShowToast(true)} + /> + )} + + {/* ✅ Toast */} + setShowToast(false)} + message="Survey Booked Successfully!" + subtext="Your Survey Request is with Domna and will be in contact with you shortly. 🎉" + /> + ); } diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx index 9ab29b71..6e4f6a96 100644 --- a/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx +++ b/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx @@ -24,10 +24,6 @@ export default function BuildingPassportHomeClient({ propertyMeta, portfolioId, }: BuildingPassportHomeClientProps) { - const [openModal, setOpenModal] = useState(false); - const [showToast, setShowToast] = useState(false); - console.log(portfolioId) - console.log(propertyMeta) return (
@@ -92,29 +88,6 @@ export default function BuildingPassportHomeClient({ Book a Survey
- - {/* ✅ Modal for booking a survey */} - {openModal && ( - { - setOpenModal(false); - setShowToast(true); - }} - /> - )} - - {/* ✅ Success Toast */} - setShowToast(false)} - message="Survey Booked Successfully!" - subtext="Your survey request has been sent to Domna. We'll contact you shortly. 🎉" - /> ); } diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/layout.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/layout.tsx index 5da4b86b..11358e3b 100644 --- a/src/app/portfolio/[slug]/building-passport/[propertyId]/layout.tsx +++ b/src/app/portfolio/[slug]/building-passport/[propertyId]/layout.tsx @@ -60,6 +60,7 @@ export default async function DashboardLayout(props: { diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx index 326b6739..047090d6 100644 --- a/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx +++ b/src/app/portfolio/[slug]/building-passport/[propertyId]/page.tsx @@ -1,20 +1,70 @@ +import EpcCard from "@/app/components/building-passport/EpcCard"; +import { formatDateTime } from "@/app/utils"; +import { + HomeIcon, + BuildingOfficeIcon, + CalendarIcon, + HomeModernIcon, + ClockIcon, + UserGroupIcon, +} from "@heroicons/react/24/solid"; import { getPropertyMeta } from "./utils"; -import BuildingPassportHomeClient from "./BuildingPassportHomeClient"; export const revalidate = 1; -export default async function BuildingPassportHome({ - params, -}: { - params: { slug: string; propertyId: string }; -}) { +export default async function BuildingPassportHome( + props: { + params: Promise<{ slug: string; propertyId: string }>; + } +) { + const params = await props.params; + // This is a server component and because we make the exact same request in the layout, + // the response is cached so we just gain access to the data const propertyMeta = await getPropertyMeta(params.propertyId); - // ✅ pass both property data and the portfolio slug (from the URL) return ( - +
+
+ +
+
Your property
+
+ +
Building Passport Created At:
+
{formatDateTime(propertyMeta.createdAt)}
+
+
+ +
Property Type:
+
{propertyMeta.propertyType}
+
+
+ +
Built Form:
+
{propertyMeta.builtForm}
+
+
+ +
Year Built:
+
{propertyMeta.yearBuilt}
+
+
+ +
Tenure:
+
{propertyMeta.tenure}
+
+
+ +
Number of Habitable Rooms:
+
{propertyMeta.numberOfRooms}
+
+
+
+
); } \ No newline at end of file From bea9d72861aaa7b5751a52732e7277e641739cd8 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Thu, 23 Oct 2025 20:19:14 +0000 Subject: [PATCH 3/4] add in tool bar instead --- .../BuildingPassportHomeClient.tsx | 93 ------------------- 1 file changed, 93 deletions(-) delete mode 100644 src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx deleted file mode 100644 index 6e4f6a96..00000000 --- a/src/app/portfolio/[slug]/building-passport/[propertyId]/BuildingPassportHomeClient.tsx +++ /dev/null @@ -1,93 +0,0 @@ -"use client"; - -import { useState } from "react"; -import EpcCard from "@/app/components/building-passport/EpcCard"; -import { Button } from "@/app/shadcn_components/ui/button"; -import { formatDateTime } from "@/app/utils"; -import { - CalendarIcon, - HomeIcon, - BuildingOfficeIcon, - ClockIcon, - UserGroupIcon, - HomeModernIcon, -} from "@heroicons/react/24/solid"; -import BookSurveyModal from "../../components/BookSurveyModal"; -import BookingSuccessToast from "../../components/BookingSuccessToast"; - -interface BuildingPassportHomeClientProps { - propertyMeta: any; - portfolioId: string; // ✅ from URL (slug) -} - -export default function BuildingPassportHomeClient({ - propertyMeta, - portfolioId, -}: BuildingPassportHomeClientProps) { - - return ( -
- {/* EPC Card + Property Info */} -
- {/* EPC Rating Card */} - - - {/* Property Info Card */} -
-
Your Property
- -
- -
Building Passport Created At:
-
{formatDateTime(propertyMeta.createdAt)}
-
- -
- -
Property Type:
-
{propertyMeta.propertyType}
-
- -
- -
Built Form:
-
{propertyMeta.builtForm}
-
- -
- -
Year Built:
-
{propertyMeta.yearBuilt}
-
- -
- -
Tenure:
-
{propertyMeta.tenure}
-
- -
- -
Number of Habitable Rooms:
-
{propertyMeta.numberOfRooms}
-
-
-
- - {/* ✅ "Book a Survey" Button */} -
- -
-
- ); -} From 5249fc0984cb6d5b6f32cebfdbccfb09859c6a66 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Thu, 23 Oct 2025 20:21:04 +0000 Subject: [PATCH 4/4] add in tool bar instead --- src/app/components/building-passport/Toolbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/building-passport/Toolbar.tsx b/src/app/components/building-passport/Toolbar.tsx index 8d74d524..9bb4958c 100644 --- a/src/app/components/building-passport/Toolbar.tsx +++ b/src/app/components/building-passport/Toolbar.tsx @@ -184,7 +184,7 @@ export function Toolbar({ show={showToast} onClose={() => setShowToast(false)} message="Survey Booked Successfully!" - subtext="Your Survey Request is with Domna and will be in contact with you shortly. 🎉" + subtext="Your Survey Request is with Domna and we will be in contact. 🎉" /> );