diff --git a/src/app/api/plan/trigger/route.ts b/src/app/api/plan/trigger/route.ts index 1e810f08..bf6be78f 100644 --- a/src/app/api/plan/trigger/route.ts +++ b/src/app/api/plan/trigger/route.ts @@ -1,28 +1,36 @@ import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { MeasureKeyEnum } from "@/app/db/schema/recommendations"; +import { PortfolioGoal } from "@/app/db/schema/portfolio"; -const PresignedUrlBodySchema = z.object({ - portfolio_id: z.string(), - housing_type: z.enum(["Social", "Private"]), - goal: z.enum(["Increasing EPC", "Reduce energy consumption"]), - goal_value: z.string(), - trigger_file_path: z.string(), - valuation_file_path: z.string(), - multi_plan: z.boolean().optional(), - budget: z.number().optional().nullable(), - scenario_name: z.string().optional(), - event_type: z.enum(["remote_assessment"]).optional(), - // inclusions is a list of measures, where the values are in measuresList - inclusions: z.array(MeasureKeyEnum).optional(), - exclusions: z.array(MeasureKeyEnum).optional(), - already_installed_file_path: z.string().optional(), - // optional scenario_id to link the plan to an existing scenario - scenario_id: z.string().optional().nullable(), - file_type: z.enum(["csv", "xlsx"]).optional(), // Specify the file type - file_format: z.enum(["domna_asset_list"]).optional().nullable(), // Specify the file format - sheet_name: z.string().optional().nullable(), // Specify the sheet name if applicable -}); +const PresignedUrlBodySchema = z + .object({ + portfolio_id: z.string(), + housing_type: z.enum(["Social", "Private"]), + goal: z.enum(PortfolioGoal), + goal_value: z.string().nullable(), // Nullable to handle cases where goal_value is not applicable + trigger_file_path: z.string(), + valuation_file_path: z.string(), + multi_plan: z.boolean().optional(), + budget: z.number().optional().nullable(), + scenario_name: z.string().optional(), + sheet_count: z.number().optional(), // Number of rows in the selected sheet + event_type: z.enum(["remote_assessment"]).optional(), + ashp_cop: z.number().optional(), + // inclusions is a list of measures, where the values are in measuresList + inclusions: z.array(MeasureKeyEnum).optional(), + exclusions: z.array(MeasureKeyEnum).optional(), + already_installed_file_path: z.string().optional(), + // optional scenario_id to link the plan to an existing scenario + scenario_id: z.string().optional().nullable(), + file_type: z.enum(["csv", "xlsx"]).optional(), // Specify the file type + file_format: z.enum(["domna_asset_list"]).optional().nullable(), // Specify the file format + sheet_name: z.string().optional().nullable(), // Specify the sheet name if applicable + }) + .refine((data) => data.goal !== "Increasing EPC" || !!data.goal_value, { + path: ["goal_value"], + message: "Target EPC Rating is required when goal is Increasing EPC", + }); export async function POST(request: NextRequest) { // For the moment, this api specifically handles uploads of csvs diff --git a/src/app/components/building-passport/Toolbar.tsx b/src/app/components/building-passport/Toolbar.tsx index 0c7807ab..57ad05d7 100644 --- a/src/app/components/building-passport/Toolbar.tsx +++ b/src/app/components/building-passport/Toolbar.tsx @@ -23,7 +23,34 @@ interface ToolbarProps { } const navigationMenuTriggerStyle = cva( - "bg-gray-50 cursor-pointer group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-gray-200 hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-gray-200" + [ + "bg-gray-50", + "cursor-pointer", + "group", + "inline-flex", + "h-10", + "w-max", + "items-center", + "justify-center", + "rounded-md", + "bg-background", + "px-4", + "py-2", + "text-sm", + "font-medium", + "transition-colors", + "hover:bg-gray-200", + "hover:text-accent-foreground", + "focus:bg-accent", + "focus:text-accent-foreground", + "focus:outline-none", + "disabled:pointer-events-none", + "disabled:opacity-50", + "data-[active]:bg-accent/50", + "data-[state=open]:bg-gray-200", + // + "text-gray-900", + ].join(" ") ); export function Toolbar({ propertyId, portfolioId }: ToolbarProps) { diff --git a/src/app/components/portfolio/AddNew.tsx b/src/app/components/portfolio/AddNew.tsx index eb102f2b..c1e5b5e5 100644 --- a/src/app/components/portfolio/AddNew.tsx +++ b/src/app/components/portfolio/AddNew.tsx @@ -65,7 +65,7 @@ export default function AddNewDropDown({ return ( - + Add New diff --git a/src/app/components/portfolio/SummaryBox.tsx b/src/app/components/portfolio/SummaryBox.tsx index 067f840f..c92cebb7 100644 --- a/src/app/components/portfolio/SummaryBox.tsx +++ b/src/app/components/portfolio/SummaryBox.tsx @@ -94,7 +94,7 @@ function SummaryBox({ scenarios, numProperties }: SummaryBoxProps) { return (
-

+

Portfolio Summary

@@ -102,7 +102,7 @@ function SummaryBox({ scenarios, numProperties }: SummaryBoxProps) { id="scenario-select" value={selectedScenarioId} onChange={(e) => handleScenarioChange(e.target.value)} - className="p-2 border rounded w-full" + className="p-2 border rounded w-full text-black" > {scenarios.map((scenario) => (