mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-30 12:55:02 +00:00
deplying new remote assessment model
This commit is contained in:
parent
1f0d4f0dcb
commit
1e61b8c04a
3 changed files with 94 additions and 45 deletions
|
|
@ -17,6 +17,8 @@ const PresignedUrlBodySchema = z.object({
|
|||
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(),
|
||||
});
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ export function SelectScenarioDropdown({
|
|||
<Menu.Item key={opt.value}>
|
||||
{({ active }) => (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onSelect(opt)}
|
||||
className={
|
||||
`group w-full text-left px-4 py-3 text-sm transition-colors flex flex-col space-y-1 ` +
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ interface EngineTriggerBody {
|
|||
budget: null;
|
||||
event_type: string;
|
||||
inclusions: (typeof measuresList)[number][];
|
||||
scenario_id?: string | null;
|
||||
}
|
||||
|
||||
const formSchema = z.object({
|
||||
|
|
@ -169,9 +170,9 @@ const formSchema = z.object({
|
|||
postcode: z.string().min(1),
|
||||
uprn: z.number().min(1),
|
||||
valuation: z.number().min(1),
|
||||
propertyType: z.string().optional().nullable(),
|
||||
builtForm: z.string().optional().nullable(),
|
||||
measures: z.array(MeasureKeyEnum),
|
||||
propertyType: z.string().nullable(),
|
||||
builtForm: z.string().nullable(),
|
||||
measures: z.array(MeasureKeyEnum).min(1, "Select at least one measure."),
|
||||
});
|
||||
|
||||
type FormValues = z.infer<typeof formSchema>;
|
||||
|
|
@ -276,6 +277,7 @@ function useCreateRemoteAssessment({
|
|||
propertyType,
|
||||
builtForm,
|
||||
measures,
|
||||
scenarioId,
|
||||
}: {
|
||||
portfolioId: string;
|
||||
uprn: number | null;
|
||||
|
|
@ -285,6 +287,7 @@ function useCreateRemoteAssessment({
|
|||
measures: (typeof measuresList)[number][];
|
||||
propertyType?: string | null;
|
||||
builtForm?: string | null;
|
||||
scenarioId?: string | null;
|
||||
}) {
|
||||
// 1) We want to upload the asset data. To do this, we format the asset data, generate a presigned URL, and upload the data to S3.
|
||||
// 2) We then want to upload valuation data. To do this, we format the valuation data, generate a presigned URL, and upload the data to S3.
|
||||
|
|
@ -367,6 +370,7 @@ function useCreateRemoteAssessment({
|
|||
async function triggerEngine(data: FormValues) {
|
||||
try {
|
||||
const triggerBody: EngineTriggerBody = {
|
||||
scenario_id: scenarioId || null,
|
||||
portfolio_id: portfolioId,
|
||||
housing_type: data.housingType,
|
||||
goal: data.goal,
|
||||
|
|
@ -454,7 +458,7 @@ export default function RemoteAssessmentModal({
|
|||
() => [
|
||||
...scenarios.map((s) => ({
|
||||
label: s.name || "",
|
||||
value: s.name || "",
|
||||
value: String(s.id) || "",
|
||||
disabled: false,
|
||||
})),
|
||||
],
|
||||
|
|
@ -465,6 +469,7 @@ export default function RemoteAssessmentModal({
|
|||
|
||||
const form = useForm({
|
||||
resolver: zodResolver(formSchema),
|
||||
mode: "onChange",
|
||||
defaultValues: {
|
||||
scenario: "",
|
||||
housingType: "",
|
||||
|
|
@ -474,12 +479,15 @@ export default function RemoteAssessmentModal({
|
|||
postcode: "",
|
||||
uprn: 0,
|
||||
valuation: 0,
|
||||
propertyType: null,
|
||||
builtForm: null,
|
||||
propertyType: null as string | null,
|
||||
builtForm: null as string | null,
|
||||
measures: measuresList,
|
||||
},
|
||||
});
|
||||
const { reset, setValue } = form;
|
||||
const { reset, setValue, formState } = form;
|
||||
const { isValid, isSubmitting } = formState;
|
||||
|
||||
const measures = form.watch("measures");
|
||||
|
||||
const {
|
||||
handleSubmit: triggerAssessment,
|
||||
|
|
@ -493,7 +501,8 @@ export default function RemoteAssessmentModal({
|
|||
valuation: form.watch("valuation"),
|
||||
propertyType: form.watch("propertyType"),
|
||||
builtForm: form.watch("builtForm"),
|
||||
measures: form.watch("measures"),
|
||||
measures: measures,
|
||||
scenarioId: selectedScenario,
|
||||
});
|
||||
|
||||
const onSelectScenario = (opt: Option) => {
|
||||
|
|
@ -507,7 +516,8 @@ export default function RemoteAssessmentModal({
|
|||
goalValue: "",
|
||||
});
|
||||
} else {
|
||||
const picked = scenarios.find((s) => s.name === opt.value);
|
||||
const picked = scenarios.find((s) => String(s.id) === opt.value);
|
||||
|
||||
if (!picked) return;
|
||||
setValue("scenario", picked.name || "");
|
||||
setValue("housingType", picked.housingType);
|
||||
|
|
@ -840,7 +850,7 @@ export default function RemoteAssessmentModal({
|
|||
<span>Measures</span>
|
||||
<span>{showMeasures ? "−" : "+"}</span>
|
||||
</button>
|
||||
{showMeasures && <MeasuresCheckboxes />}
|
||||
{showMeasures && <MeasuresCheckboxes form={form} />}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-4">
|
||||
|
|
@ -851,8 +861,15 @@ export default function RemoteAssessmentModal({
|
|||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button type="submit" disabled={presignedUrlIsLoading}>
|
||||
{presignedUrlIsLoading ? "Submitting…" : "Submit"}
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={
|
||||
!isValid || presignedUrlIsLoading || isSubmitting
|
||||
}
|
||||
>
|
||||
{isSubmitting || presignedUrlIsLoading
|
||||
? "Submitting…"
|
||||
: "Submit"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
|
@ -872,40 +889,69 @@ function setIsOpen(arg0: boolean) {
|
|||
throw new Error("Function not implemented.");
|
||||
}
|
||||
|
||||
function MeasuresCheckboxes() {
|
||||
const { control } = useFormContext();
|
||||
function MeasuresCheckboxes({
|
||||
form,
|
||||
}: {
|
||||
form: ReturnType<typeof useForm<FormValues>>;
|
||||
}) {
|
||||
const { control } = form;
|
||||
const allMeasures = measuresList;
|
||||
return (
|
||||
<div className="grid grid-cols-2 gap-4 mt-4">
|
||||
{measuresList.map((measure) => (
|
||||
<FormField
|
||||
key={measure}
|
||||
control={control}
|
||||
name="measures"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex items-center space-x-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
value={measure}
|
||||
checked={field.value?.includes(measure) ?? true}
|
||||
onChange={(e) => {
|
||||
const checked = e.target.checked;
|
||||
const current = new Set(field.value ?? []);
|
||||
if (checked) {
|
||||
current.add(measure);
|
||||
} else {
|
||||
current.delete(measure);
|
||||
}
|
||||
field.onChange(Array.from(current));
|
||||
}}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
<FormLabel className="text-sm">
|
||||
{measuresDisplayLabels[measure]}
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
<div className="flex flex-col gap-4 mt-4 ">
|
||||
<div className="flex justify-start gap-4">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
form.setValue("measures", allMeasures, { shouldValidate: true })
|
||||
}
|
||||
className="text-sm text-brandbrown underline"
|
||||
>
|
||||
Select All
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
form.setValue("measures", [], { shouldValidate: true })
|
||||
}
|
||||
className="text-sm text-brandbrown underline"
|
||||
>
|
||||
Untick All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Measures grid */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{measuresList.map((measure) => (
|
||||
<FormField
|
||||
key={measure}
|
||||
control={control}
|
||||
name="measures"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex items-center space-x-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
value={measure}
|
||||
checked={field.value?.includes(measure) ?? true}
|
||||
onChange={(e) => {
|
||||
const checked = e.target.checked;
|
||||
const current = new Set(field.value ?? []);
|
||||
if (checked) {
|
||||
current.add(measure);
|
||||
} else {
|
||||
current.delete(measure);
|
||||
}
|
||||
field.onChange(Array.from(current));
|
||||
}}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
<FormLabel className="text-sm">
|
||||
{measuresDisplayLabels[measure]}
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue