got the react hook form with zod to work, FormProvder got rid of the getField errors somehow, all hail Overlord Claude, aesthetic clean up needed as well as linked up to trigger the engine

This commit is contained in:
StefanWout 2024-11-21 16:44:34 +00:00
parent 3520d0858d
commit 710d60b5ed

View file

@ -8,6 +8,10 @@ import { Float } from "@headlessui-float/react";
import { ChevronDownIcon } from "@heroicons/react/20/solid";
import { useMutation } from "@tanstack/react-query";
import { useSession } from "next-auth/react";
import { Form, useForm, FormProvider } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { FormField, FormItem, FormLabel, FormControl, FormMessage } from "@/app/shadcn_components/ui/form";
type Option = {
label: string;
@ -291,6 +295,8 @@ function useCreateRemoteAssessment({
},
});
async function handleSubmit() {
try {
// Mutate presigned URL for asset list file
@ -325,71 +331,58 @@ export default function RemoteAssessmentModal({
setIsOpen: (isOpen: boolean) => void;
portfolioId: string;
}) {
const [scenario, setScenario] = useState<undefined | string>(undefined);
const [housingType, sethousingType] = useState<string>("");
const [selectedGoal, setSelectedGoal] = useState<string>("");
const [goalValue, setGoalValue] = useState<string>("");
const [addressLineOne, setAddressLineOne] = useState<string>("");
const [postcode, setPostcode] = useState<string>("");
const [uprn, setUprn] = useState<number | null>(null);
const [valuation, setValuation] = useState<number | string | null>("");
const [buttonDisabled, setButtonDisabled] = useState(true);
const formSchema = z.object({
scenario: z.string().min(1, "Scenario is required"),
goal: z.string().min(1, "Goal is required"),
goalValue: z.string().min(1, "Goal value is required"),
housingType: z.string().min(1, "Housing type is required"),
addressLineOne: z.string().min(1, "Address is required"),
postcode: z.string().min(1, "Postcode is required"),
uprn: z.number().min(1, "UPRN is required"),
valuation: z.number().min(1, "Valuation is required"),
});
function handleScenarioChange(event: React.ChangeEvent<HTMLInputElement>) {
setScenario(event.target.value);
}
const form = useForm<FormValues>({
resolver: zodResolver(formSchema),
defaultValues: {
scenario: "",
housingType: "",
goal: "",
goalValue: "",
addressLineOne: "",
postcode: "",
uprn: 0,
valuation: 0,
},
});
function handleAddressLineOneChange(
event: React.ChangeEvent<HTMLInputElement>
) {
setAddressLineOne(event.target.value);
}
type FormValues = z.infer<typeof formSchema>;
function handlePostcodeChange(event: React.ChangeEvent<HTMLInputElement>) {
setPostcode(event.target.value);
}
function handleUprnChange(event: React.ChangeEvent<HTMLInputElement>) {
setUprn(Number(event.target.value));
}
function handleValuationChange(event: React.ChangeEvent<HTMLInputElement>) {
setValuation(event.target.value);
}
const onSubmit = async (data: FormValues) => {
try {
// First handle the form submission from react-hook-form
const formData = form.getValues();
// Then trigger the data upload using handleSubmit from useCreateRemoteAssessment
await handleSubmit();
// Close the modal on success
setIsOpen(false);
} catch (error) {
console.error('Error submitting form:', error);
}
};
const { handleSubmit, presignedUrlIsLoading, presignedUrlIsError } =
useCreateRemoteAssessment({
portfolioId,
uprn,
addressLineOne,
postcode,
valuation,
uprn: form.watch("uprn"),
addressLineOne: form.watch("addressLineOne"),
postcode: form.watch("postcode"),
valuation: form.watch("valuation"),
});
useEffect(() => {
function handleButtonDisabled(): boolean {
return !(
scenario &&
selectedGoal &&
housingType &&
addressLineOne &&
postcode &&
uprn &&
valuation
);
}
setButtonDisabled(handleButtonDisabled());
}, [
scenario,
selectedGoal,
housingType,
addressLineOne,
postcode,
uprn,
valuation,
]);
return (
<>
<Transition appear show={isOpen} as={Fragment}>
@ -422,101 +415,169 @@ export default function RemoteAssessmentModal({
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"
>
{scenario}
</Dialog.Title>
<div className="flex justify-center">
Scenario Name
<Input
type="text"
defaultValue={"Remote Assessment"}
onChange={handleScenarioChange}
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-gray-900">
Remote Assessment Details
</Dialog.Title>
<FormProvider {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="scenario"
render={({ field }) => (
<FormItem>
<FormLabel>Scenario Name</FormLabel>
<FormControl>
<Input
placeholder="Enter scenario name"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="flex flex-col mt-6">
<label
htmlFor="portfolio-name"
className="text-sm font-semibold text-gray-600 mb-1 relative leading-relaxed tracking-wider"
>
Housing type
<span className="text-red-500">*</span>
</label>
<SelectDropdown
options={selecthousingTypeOptions}
selectedOption={housingType}
onSelectOption={(option) => sethousingType(option.value)}
<FormField
control={form.control}
name="housingType"
render={({ field }) => (
<FormItem>
<FormLabel>Housing Type</FormLabel>
<FormControl>
<SelectDropdown
options={selecthousingTypeOptions}
selectedOption={field.value}
onSelectOption={(option) => field.onChange(option.value)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="flex flex-col mt-6">
<label
htmlFor="portfolio-name"
className="text-sm font-semibold text-gray-600 mb-1 relative leading-relaxed tracking-wider"
>
Select Goal
<span className="text-red-500">*</span>
</label>
<SelectDropdown
options={selectGoalOptions}
selectedOption={selectedGoal}
onSelectOption={(option) => setSelectedGoal(option.value)}
<FormField
control={form.control}
name="goal"
render={({ field }) => (
<FormItem>
<FormLabel>Goal</FormLabel>
<FormControl>
<SelectDropdown
options={selectGoalOptions}
selectedOption={field.value}
onSelectOption={(option) => field.onChange(option.value)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{selectedGoal === "Increase EPC" && (
<div className="flex flex-col mt-6">
<label
htmlFor="csv-upload-epc"
className="text-sm font-semibold text-gray-600 relative leading-relaxed tracking-wider"
>
Choose a target EPC value
<span className="text-red-500">*</span>
</label>
<SelectDropdown
options={goalValueOptions}
selectedOption={goalValue}
onSelectOption={(option) => {
setGoalValue(option.value);
}}
/>
</div>
<FormField
control={form.control}
name="goalValue"
render={({ field }) => (
<FormItem>
<FormLabel>Goal Value</FormLabel>
<FormControl>
<SelectDropdown
options={goalValueOptions}
selectedOption={field.value}
onSelectOption={(option) => field.onChange(option.value)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="addressLineOne"
render={({ field }) => (
<FormItem>
<FormLabel>Address</FormLabel>
<FormControl>
<Input placeholder="Enter address" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="postcode"
render={({ field }) => (
<FormItem>
<FormLabel>Postcode</FormLabel>
<FormControl>
<Input placeholder="Enter postcode" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="uprn"
render={({ field }) => (
<FormItem>
<FormLabel>UPRN</FormLabel>
<FormControl>
<Input
type="number"
placeholder="Enter UPRN"
{...field}
onChange={(e) => field.onChange(Number(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="valuation"
render={({ field }) => (
<FormItem>
<FormLabel>Valuation</FormLabel>
<FormControl>
<Input
type="number"
placeholder="Enter valuation"
{...field}
onChange={(e) => field.onChange(Number(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex justify-end gap-4 mt-6">
<Button
type="button"
variant="outline"
onClick={() => setIsOpen(false)}
>
Cancel
</Button>
<Button
type="submit"
disabled={presignedUrlIsLoading}
>
{presignedUrlIsLoading ? "Submitting..." : "Submit"}
</Button>
</div>
{presignedUrlIsError && (
<p className="text-red-500 mt-2">Error uploading files</p>
)}
</div>
<div className="flex justify-center mt-6">
Address Line 1
<Input type="text" onChange={handleAddressLineOneChange} />
</div>
<div className="flex justify-center mt-6">
Postcode
<Input type="text" onChange={handlePostcodeChange} />
</div>
<div className="flex justify-center mt-6">
UPRN
<Input type="text" onChange={handleUprnChange} />
</div>
<div className="flex justify-center mt-6">
Valuation
<Input type="text" onChange={handleValuationChange} />
</div>
<div className="flex justify-center mt-6">
<Button
disabled={buttonDisabled}
onClick={() => {
handleSubmit();
setIsOpen(false);
}}
>
Submit
</Button>
</div>
<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>
</Dialog.Panel>
</form>
</FormProvider>
</Dialog.Panel>
</Transition.Child>
</div>
</div>