From c265826a7c390a8b21d09487e2c1413d120bc215 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 26 Aug 2025 18:06:17 +0000 Subject: [PATCH] restructured the category 1 and category 2 hazards --- .../assessment/ConditionReport.tsx | 329 ++++++++++++------ .../[propertyId]/assessment/page.tsx | 10 +- 2 files changed, 223 insertions(+), 116 deletions(-) diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/ConditionReport.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/ConditionReport.tsx index 0641abef..bb18f6ae 100644 --- a/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/ConditionReport.tsx +++ b/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/ConditionReport.tsx @@ -18,6 +18,7 @@ import { } from "@/app/shadcn_components/ui/accordion"; import clsx from "clsx"; import { AlertTriangle } from "lucide-react"; +import { PropertyDetailsEpc } from "@/app/db/schema/property"; function ChecklistItem({ @@ -129,13 +130,17 @@ function getRecommendedOccupants(bedrooms: number): number { export default function ConditionReport({ conditionReport, - totalFloorArea + totalFloorArea, + currentSapPoints, + conditionData, }: { conditionReport: { rooms: Record; [key: string]: any; }, totalFloorArea: number; + currentSapPoints: number; + conditionData: PropertyDetailsEpc }) { // Documentation on decent home standards can be found here: @@ -179,75 +184,108 @@ export default function ConditionReport({ b?.room_info?.overall_condition_of_the_room === "Good" ) - const roomsWithDefects = allRoomData.filter( - ([, room]: any) => room.room_info?.does_the_room_have_any_defects === "Yes" - ); + const roomsWithDefects = allRoomData.filter( + ([, room]: any) => room.room_info?.does_the_room_have_any_defects === "Yes" + ); - const roomsWithDamp = allRoomData.filter( - ([, room]: any) => - room.room_info?.ventilation_info - ?.are_there_any_visible_or_reported_signs_of_damp_mould_or_excessive_condensation_within_the_room - ); + const roomsWithDamp = allRoomData.filter( + ([, room]: any) => + room.room_info?.ventilation_info + ?.are_there_any_visible_or_reported_signs_of_damp_mould_or_excessive_condensation_within_the_room + ); - const roomsWithBadWindows = allRoomData.filter( - ([, room]: any) => { - const wi = room.room_info?.windows_info; - return wi?.does_the_room_have_any_windows && wi.condition_of_the_windows !== "Good condition"; - } - ); - - // Check if the property has adequate space - // We've seen a case where the number of adult occupants + child occupants is greater than the total_number_of_occupants so we - // take the biggest of the two - const totalOccupants = conditionReport.occupant_info?.total_number_of_occupants ?? 0; - const totalAdults = conditionReport.occupant_info?.no_of_adult_occupants ?? 0; - const totalChildren = conditionReport.occupant_info?.no_of_child_occupants ?? 0; - const numberOfBedrooms = Array.isArray(rooms.bedrooms) - ? rooms.bedrooms.length - : 0; - - const occupantsToUse = Math.max(totalAdults + totalChildren, totalOccupants); - - const maxOccupants = getRecommendedOccupants(numberOfBedrooms); - const areaPerPerson = totalFloorArea / occupantsToUse; - const hasSufficientSpace = (occupantsToUse <= maxOccupants) && (areaPerPerson >= 20); - - // Category 1 Hazard structural - const frontElevation = conditionReport.access_and_elevations?.external_elevation_front?.external_elevation; - -const elevationEntries: [string, any][] = [ - ["Front Elevation", frontElevation], - ["Back Elevation", conditionReport.access_and_elevations?.external_elevation_back?.external_elevation], - ["Gable One", conditionReport.access_and_elevations?.external_elevation_gable_one?.external_elevation], - ["Gable Two", conditionReport.access_and_elevations?.external_elevation_gable_two?.external_elevation], -]; - -// If a wall inherits front elevation, use the front's data -const applyFrontDefaults = (label: string, elevationKey: string): [string, any] => { - const section = conditionReport.access_and_elevations?.[elevationKey]; - if (section?.do_all_answers_for_the_front_elevation_apply_to_this_wall) { - return [label, frontElevation]; + const roomsWithBadWindows = allRoomData.filter( + ([, room]: any) => { + const wi = room.room_info?.windows_info; + return wi?.does_the_room_have_any_windows && wi.condition_of_the_windows !== "Good condition"; } - return [label, section?.external_elevation ?? null]; -}; + ); -const allElevations: [string, any][] = [ - ["Front Elevation", frontElevation], - applyFrontDefaults("Back Elevation", "external_elevation_back"), - applyFrontDefaults("Gable One", "external_elevation_gable_one"), - applyFrontDefaults("Gable Two", "external_elevation_gable_two"), -]; + // Check if the property has adequate space + // We've seen a case where the number of adult occupants + child occupants is greater than the total_number_of_occupants so we + // take the biggest of the two + const totalOccupants = conditionReport.occupant_info?.total_number_of_occupants ?? 0; + const totalAdults = conditionReport.occupant_info?.no_of_adult_occupants ?? 0; + const totalChildren = conditionReport.occupant_info?.no_of_child_occupants ?? 0; + const numberOfBedrooms = Array.isArray(rooms.bedrooms) + ? rooms.bedrooms.length + : 0; -const elevationsWithIssues = allElevations.filter(([_, elevation]) => - elevation && - ( - elevation.does_any_structural_defect_need_resolving_before_retrofit === true || - elevation.are_there_any_signs_of_water_penetration_caused_by_failed_rainwater_goods_or_pipework === true || - elevation.are_there_any_visible_signs_of_movement === true || - elevation.are_there_any_visible_signs_of_cracking_to_the_existing_external_finish === true - ) -); + const occupantsToUse = Math.max(totalAdults + totalChildren, totalOccupants); + const maxOccupants = getRecommendedOccupants(numberOfBedrooms); + const areaPerPerson = totalFloorArea / occupantsToUse; + const hasSufficientSpace = (occupantsToUse <= maxOccupants) && (areaPerPerson >= 20); + + // Category 1 Hazard structural + const frontElevation = conditionReport.access_and_elevations?.external_elevation_front?.external_elevation; + + const elevationEntries: [string, any][] = [ + ["Front Elevation", frontElevation], + ["Back Elevation", conditionReport.access_and_elevations?.external_elevation_back?.external_elevation], + ["Gable One", conditionReport.access_and_elevations?.external_elevation_gable_one?.external_elevation], + ["Gable Two", conditionReport.access_and_elevations?.external_elevation_gable_two?.external_elevation], + ]; + + // If a wall inherits front elevation, use the front's data + const applyFrontDefaults = (label: string, elevationKey: string): [string, any] => { + const section = conditionReport.access_and_elevations?.[elevationKey]; + if (section?.do_all_answers_for_the_front_elevation_apply_to_this_wall) { + return [label, frontElevation]; + } + return [label, section?.external_elevation ?? null]; + }; + + const allElevations: [string, any][] = [ + ["Front Elevation", frontElevation], + applyFrontDefaults("Back Elevation", "external_elevation_back"), + applyFrontDefaults("Gable One", "external_elevation_gable_one"), + applyFrontDefaults("Gable Two", "external_elevation_gable_two"), + ]; + + const elevationsWithIssues = allElevations.filter(([_, elevation]) => + elevation && + ( + elevation.does_any_structural_defect_need_resolving_before_retrofit === true || + elevation.are_there_any_signs_of_water_penetration_caused_by_failed_rainwater_goods_or_pipework === true || + elevation.are_there_any_visible_signs_of_movement === true || + elevation.are_there_any_visible_signs_of_cracking_to_the_existing_external_finish === true + ) + ); + + // Thermal comfort + const meetsSapThreshold = currentSapPoints >= 35; + + const heatingType = conditionData.heating?.toLowerCase(); + const hasEfficientHeating = + heatingType?.includes("gas") || + heatingType?.includes("oil") || + heatingType?.includes("storage") || + heatingType?.includes("warm air") || + heatingType?.includes("underfloor") || + heatingType?.includes("lpg") || + heatingType?.includes("solid fuel"); + + const loftInsulationRating = conditionData.roofRating; // assume rating 3+ is ≥50mm + const wallInsulationRating = conditionData.wallsRating; // assume rating 3+ is insulated + + let insulationIsAdequate = false; + + if (heatingType?.includes("gas") || heatingType?.includes("oil")) { + insulationIsAdequate = + (loftInsulationRating != null && loftInsulationRating >= 3) || + (wallInsulationRating != null && wallInsulationRating >= 3); + } else if ( + heatingType?.includes("storage") || + heatingType?.includes("lpg") || + heatingType?.includes("solid fuel") + ) { + insulationIsAdequate = + (loftInsulationRating != null && loftInsulationRating >= 4) && + (wallInsulationRating != null && wallInsulationRating >= 3); + } + + const thermalComfortOk = hasEfficientHeating && insulationIsAdequate; return (
@@ -255,58 +293,119 @@ const elevationsWithIssues = allElevations.filter(([_, elevation]) => Decent Homes Checklist - - 0 - ? "Structural issues identified" - : "No major structural issues identified" - } - passed={elevationsWithIssues.length === 0} - alert={elevationsWithIssues.length > 0} - roomsWithIssues={elevationsWithIssues} - /> - 0} - roomsWithIssues={roomsWithDamp} - /> - - - - - - - + +
+ {/* Category 1 Hazards */} +
+

+ Category 1 Hazards +

+ 0 + ? "Structural issues identified" + : "No major structural issues identified" + } + passed={elevationsWithIssues.length === 0} + alert={elevationsWithIssues.length > 0} + roomsWithIssues={elevationsWithIssues} + /> + + 0 + ? "Signs of damp or mould present" + : "No signs of damp or mould" + } + passed={roomsWithDamp.length === 0} + alert={roomsWithDamp.length > 0} + roomsWithIssues={roomsWithDamp} + /> + + + + + + + +
+ + {/* Category 2 Hazards */} +
+

+ Category 2 Hazards +

+ + + + + + + + + + +
+
+
diff --git a/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/page.tsx b/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/page.tsx index ddce32ae..c6b3afe7 100644 --- a/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/page.tsx +++ b/src/app/portfolio/[slug]/building-passport/[propertyId]/assessment/page.tsx @@ -144,6 +144,7 @@ export default async function PreAssessmentReport( } // console.log("conditionReport", conditionReport.rooms.utility) + console.log("Condition data", propertyMeta) const nonIntrusiveSurvey = await getNonIntrusiveSurvey(propertyMeta.uprn); @@ -167,6 +168,7 @@ export default async function PreAssessmentReport( { - Object.keys(conditionReportMeta).length > 0 && + Object.keys(conditionReportMeta).length > 0 && + } {nonIntrusiveSurvey && (