Skip to content

Commit

Permalink
Update Create Project Form (#73)
Browse files Browse the repository at this point in the history
* fix: issue while logged in from the dashboard

* style: change the style of custom components RadioButton and UploadArea

* feat: add no fly zone option while project creation

* feat: add package.json to the gitignore

* feat: add a MapTools component in map section of create project form

* fix: change the order of the step form

* feat: add nofly zone upload area in the form

* feat: specift required fields

* fix: change stepswitcher width for compotibility

* feat: remove unused slice

* fix: make errors field not required in types

* feat: add keyparameters to the form

* feat: add no fly zones in define aoi section

* feat: add types to formProps

* feat: finalize payload for project creation

* feat: add dimension while generating task

* feat: add react-datepicker package

* feat: create a custom date picker component

* feat: make watch field not required in useFormPropTypes

* refactor: remove code clutter in the project creation from section
  • Loading branch information
Prajwalism authored Jul 16, 2024
1 parent 903deb1 commit 295109b
Show file tree
Hide file tree
Showing 20 changed files with 574 additions and 175 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ temp_webmaps/Naivasha
# node & pnpm
**/**/node_modules
**/**/package-lock.json
**/**/package.json
**/**/yarn.lock
**/**/.pnpm-store

Expand Down
2 changes: 1 addition & 1 deletion src/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"maplibre-gl": "^3.2.0",
"papaparse": "^5.4.1",
"react": "^18.2.0",
"react-day-picker": "^8.8.1",
"react-datepicker": "^7.3.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.4",
"react-hook-form": "^7.52.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { useTypedSelector, useTypedDispatch } from '@Store/hooks';
import { FlexRow } from '@Components/common/Layouts';
import {
StepComponentMap,
stepDescriptionComponents,
} from '@Constants/createProject';
import { Button } from '@Components/RadixComponents/Button';
import { setCreateProjectState } from '@Store/actions/createproject';
import { useMutation } from '@tanstack/react-query';
import { FieldValues, useForm } from 'react-hook-form';
import {
BasicInformationForm,
DefineAOIForm,
KeyParametersForm,
ContributionsForm,
GenerateTaskForm,
} from '@Components/CreateProject/FormContents';
import { UseFormPropsType } from '@Components/common/FormUI/types';
import { FlexRow } from '@Components/common/Layouts';
import { Button } from '@Components/RadixComponents/Button';
import { setCreateProjectState } from '@Store/actions/createproject';
import { postCreateProject, postTaskBoundary } from '@Services/createproject';
import { useMutation } from '@tanstack/react-query';
import { toast } from 'react-toastify';
import {
StepComponentMap,
stepDescriptionComponents,
} from '@Constants/createProject';
import { convertGeojsonToFile } from '@Utils/convertLayerUtils';
import prepareFormData from '@Utils/prepareFormData';

Expand All @@ -38,7 +39,7 @@ const getActiveStepDescription = (
return Component ? <Component /> : <></>;
};

const getActiveStepForm = (activeStep: number, formProps: any) => {
const getActiveStepForm = (activeStep: number, formProps: UseFormPropsType) => {
switch (activeStep) {
case 1:
return <BasicInformationForm formProps={formProps} />;
Expand All @@ -47,9 +48,9 @@ const getActiveStepForm = (activeStep: number, formProps: any) => {
case 3:
return <KeyParametersForm formProps={formProps} />;
case 4:
return <ContributionsForm formProps={formProps} />;
case 5:
return <GenerateTaskForm formProps={formProps} />;
case 5:
return <ContributionsForm formProps={formProps} />;
default:
return <></>;
}
Expand All @@ -58,23 +59,61 @@ const getActiveStepForm = (activeStep: number, formProps: any) => {
export default function CreateprojectLayout() {
const dispatch = useTypedDispatch();
const navigate = useNavigate();

const activeStep = useTypedSelector(state => state.createproject.activeStep);
const splitGeojson = useTypedSelector(
state => state.createproject.splitGeojson,
);
const isTerrainFollow = useTypedSelector(
state => state.createproject.isTerrainFollow,
);

const initialState = {
const initialState: FieldValues = {
name: '',
short_description: '',
description: '',
organisation_id: 1,
outline_geojson: {},
outline_geojson: null,
outline_no_fly_zones: null,
gsd_cm_px: null,
dimension: null,
is_terrain_follow: null,
task_split_type: 1,
per_task_instructions: '',
deadline_at: '',
visibility: 0,
};

const { mutate: uploadTaskBoundary } = useMutation<any, any, any, unknown>({
const {
register,
setValue,
handleSubmit,
reset,
formState: { errors },
control,
getValues,
watch,
} = useForm({
defaultValues: initialState,
});

const { mutate: uploadTaskBoundary, isLoading } = useMutation<
any,
any,
any,
unknown
>({
mutationFn: postTaskBoundary,
onSuccess: () => {
toast.success('Project Boundary Uploaded');
reset();
dispatch(
setCreateProjectState({
activeStep: 1,
splitGeojson: null,
uploadedProjectArea: null,
uploadedNoFlyZone: null,
}),
);
navigate('/projects');
},
onError: err => {
Expand All @@ -86,40 +125,42 @@ export default function CreateprojectLayout() {
mutationFn: postCreateProject,
onSuccess: (res: any) => {
toast.success('Project Created Successfully');
dispatch(setCreateProjectState({ projectId: res.data.id }));
dispatch(setCreateProjectState({ projectId: res.data.project_id }));
if (!splitGeojson) return;
const geojson = convertGeojsonToFile(splitGeojson);
const formData = prepareFormData({ task_geojson: geojson });
uploadTaskBoundary({ id: res.data.id, data: formData });
uploadTaskBoundary({ id: res.data.project_id, data: formData });
},
onError: err => {
toast.error(err.message);
},
});

const onSubmit = (data: any) => {
if (activeStep < 5) return;
createProject(data);
reset();
};

const { register, setValue, handleSubmit, reset } = useForm({
defaultValues: initialState,
});

const formProps = {
register,
setValue,
reset,
errors,
control,
getValues,
watch,
};

const onPrevBtnClick = () => {
dispatch(setCreateProjectState({ activeStep: activeStep - 1 }));
};

const onNextBtnClick = () => {
handleSubmit(onSubmit)();
if (activeStep === 5) return;
dispatch(setCreateProjectState({ activeStep: activeStep + 1 }));
const onSubmit = (data: any) => {
if (activeStep === 4 && !splitGeojson) return;
if (activeStep !== 5) {
dispatch(setCreateProjectState({ activeStep: activeStep + 1 }));
return;
}
const payload = {
...data,
is_terrain_follow: isTerrainFollow === 'hilly',
};
createProject(payload);
};

return (
Expand All @@ -146,10 +187,15 @@ export default function CreateprojectLayout() {
<div />
)}
<Button
onClick={onNextBtnClick}
onClick={e => {
e.preventDefault();
handleSubmit(onSubmit)();
}}
type="submit"
className="!naxatw-bg-red !naxatw-text-white"
rightIcon="chevron_right"
withLoader
isLoading={isLoading}
>
{activeStep === 5 ? 'Save' : 'Next'}
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
import { FormControl, Label, Input } from '@Components/common/FormUI';
import ErrorMessage from '@Components/common/FormUI/ErrorMessage';
import { UseFormPropsType } from '@Components/common/FormUI/types';

export default function BasicInformation({
formProps,
}: {
formProps: UseFormPropsType;
}) {
const { register, errors } = formProps;

export default function BasicInformation({ formProps }: { formProps: any }) {
const { register } = formProps;
return (
<div className="naxatw-px-10 naxatw-py-5">
<FormControl className="naxatw-gap-1">
<Label required>Name</Label>
<Input
placeholder="Enter Name of the Project"
{...register('name', {
required: 'Required',
required: 'Name of the project is required',
})}
/>
<ErrorMessage message={errors?.name?.message as string} />
</FormControl>
<FormControl className="naxatw-mt-5 naxatw-gap-1">
<Label required>Description of the project</Label>
<Input
type="text-area"
placeholder="Description of the Project"
{...register('description', {
required: 'Required',
required: 'Description is Required',
})}
/>
<ErrorMessage message={errors?.description?.message as string} />
</FormControl>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,62 @@
/* eslint-disable no-unused-vars */
import { useTypedDispatch, useTypedSelector } from '@Store/hooks';
import { FlexColumn } from '@Components/common/Layouts';
import { FormControl, Label, Input } from '@Components/common/FormUI';
import { setCreateProjectState } from '@Store/actions/createproject';
import RadioButton from '@Components/common/RadioButton';
import ErrorMessage from '@Components/common/ErrorMessage';
import { UseFormPropsType } from '@Components/common/FormUI/types';
import { setCreateProjectState } from '@Store/actions/createproject';
import { contributionsOptions } from '@Constants/createProject';

export default function Conditions({ formProps }: { formProps: any }) {
export default function Conditions({
formProps,
}: {
formProps: UseFormPropsType;
}) {
const dispatch = useTypedDispatch();

const { register, errors } = formProps;

const contributionsOption = useTypedSelector(
state => state.createproject.contributionsOption,
);

return (
<div className="naxatw-px-10 naxatw-py-5">
<FlexColumn gap={5} className="naxatw-px-10 naxatw-py-5">
<FormControl>
<Label>Instructions for Drone Operators</Label>
<Input
placeholder="Enter Instructions for Drone Operators"
{...register('per_task_instructions', {
required: 'Instructions are required',
})}
/>
<ErrorMessage
message={errors?.per_task_instructions?.message as string}
/>
</FormControl>
<RadioButton
topic="Publish"
options={contributionsOptions}
direction="row"
direction="column"
onChangeData={val => {
dispatch(setCreateProjectState({ contributionsOption: val }));
}}
value={contributionsOption}
/>
<FormControl className="naxatw-mt-4 naxatw-gap-1">
<Label>Deadline for Submission</Label>
<Input placeholder="Enter GSD in meter" />
<FormControl className="naxatw-gap-1">
<div className="naxatw-w-full">
<Label>Deadline for Submission</Label>
<Input
placeholder="Deadline for Submission"
type="date"
className="naxatw-mt-1"
{...register('deadline_at', {
required: 'Deadline forRequired',
})}
/>
</div>
<ErrorMessage message={errors?.deadline_at?.message as string} />
</FormControl>
</div>
</FlexColumn>
);
}
Loading

0 comments on commit 295109b

Please sign in to comment.