parent
3f9f816a7e
commit
9ac545a6d4
24 changed files with 393 additions and 301 deletions
|
@ -35,6 +35,10 @@
|
||||||
"results": {
|
"results": {
|
||||||
"title": "Plant List Results",
|
"title": "Plant List Results",
|
||||||
"forestDiagramDescription": "Forest Position Information Diagram"
|
"forestDiagramDescription": "Forest Position Information Diagram"
|
||||||
|
},
|
||||||
|
"complete": {
|
||||||
|
"title": "Application Complete",
|
||||||
|
"description": "You have completed your application and submitted your results. You may now return to the homepage or fill out another application for a different habitat or zone."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
import { useState } from 'react';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Stepper from '@mui/material/Stepper';
|
|
||||||
import Step from '@mui/material/Step';
|
|
||||||
import StepLabel from '@mui/material/StepLabel';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
|
||||||
|
|
||||||
export default function StepperWizard({ steps }) {
|
|
||||||
const [filters, setFilters] = useState({});
|
|
||||||
const [activeStep, setActiveStep] = useState(0);
|
|
||||||
const [nextDisabled, setNextDisabled] = useState(true);
|
|
||||||
const [redirectBack, setRedirectBack] = useState(false);
|
|
||||||
|
|
||||||
const resetStepState = () => {
|
|
||||||
setNextDisabled(true);
|
|
||||||
setRedirectBack(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleNext = () => {
|
|
||||||
if (redirectBack) {
|
|
||||||
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
|
||||||
} else {
|
|
||||||
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
|
||||||
}
|
|
||||||
resetStepState();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBack = () => {
|
|
||||||
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
|
||||||
resetStepState();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setActiveStep(0);
|
|
||||||
resetStepState();
|
|
||||||
setFilters({});
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateFilterState = (newFilters) => {
|
|
||||||
setFilters(f => ({...f, ...newFilters}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let CurrentStep = activeStep >= steps.length ? steps[steps.length - 1].component : steps[activeStep].component;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box sx={{ width: '100%', height: '100%', display: "flex", flexDirection: "column", overflow: "hidden" }}>
|
|
||||||
<Stepper activeStep={activeStep} sx={{ paddingRight: '3vw', paddingLeft: '3vw', marginBottom: '2vw' }}>
|
|
||||||
{steps.map((step) => {
|
|
||||||
return (
|
|
||||||
<Tooltip title={step.tooltip}>
|
|
||||||
<Step key={step.label}>
|
|
||||||
<StepLabel>{step.label}</StepLabel>
|
|
||||||
</Step>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Stepper>
|
|
||||||
<CurrentStep
|
|
||||||
filters={filters}
|
|
||||||
updateFilterState={updateFilterState}
|
|
||||||
resetFilterState={() => setFilters({})}
|
|
||||||
setNextDisabled={setNextDisabled}
|
|
||||||
setRedirectBack={setRedirectBack}
|
|
||||||
/>
|
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'row', pt: 2, pb: 2, paddingRight: '3vw', paddingLeft: '3vw' }}>
|
|
||||||
<Button
|
|
||||||
color="inherit"
|
|
||||||
disabled={activeStep === 0}
|
|
||||||
onClick={handleBack}
|
|
||||||
sx={{ mr: 1 }}
|
|
||||||
>
|
|
||||||
Back
|
|
||||||
</Button>
|
|
||||||
<Box sx={{ flex: '1 1 auto' }} />
|
|
||||||
{activeStep === steps.length - 1 ?
|
|
||||||
<Button onClick={handleReset}>Reset</Button> : <Button onClick={handleNext} disabled={nextDisabled}>Next</Button>}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
37
frontend/src/components/providers/FilterProvider.jsx
Normal file
37
frontend/src/components/providers/FilterProvider.jsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { createContext, useState, useContext } from 'react';
|
||||||
|
import Repository from '../../repository/Repository';
|
||||||
|
|
||||||
|
const FilterContext = createContext(null);
|
||||||
|
|
||||||
|
const FilterProvider = ({children}) => {
|
||||||
|
const [filters, setFilters] = useState({});
|
||||||
|
|
||||||
|
const resetFilters = () => setFilters({});
|
||||||
|
|
||||||
|
const updateFilters = newFilters => setFilters(oldFilters => ({...oldFilters, ...newFilters}));
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
return await Repository.post("/questionnaire/", {
|
||||||
|
location: `SRID=4326;POINT (${filters.coordinates.lng} ${filters.coordinates.lat})`,
|
||||||
|
soil_variant: filters.soilVariant,
|
||||||
|
zone: filters.zone.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
filters,
|
||||||
|
setFilters,
|
||||||
|
resetFilters,
|
||||||
|
updateFilters,
|
||||||
|
submit,
|
||||||
|
};
|
||||||
|
|
||||||
|
return <FilterContext.Provider value={value}>{children}</FilterContext.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useFilter = () => useContext(FilterContext);
|
||||||
|
|
||||||
|
export {
|
||||||
|
FilterProvider,
|
||||||
|
useFilter,
|
||||||
|
};
|
100
frontend/src/components/providers/StepperProvider.jsx
Normal file
100
frontend/src/components/providers/StepperProvider.jsx
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import { createContext, useState, useContext } from 'react';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Stepper from '@mui/material/Stepper';
|
||||||
|
import Step from '@mui/material/Step';
|
||||||
|
import StepLabel from '@mui/material/StepLabel';
|
||||||
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
|
import { useFilter } from './FilterProvider';
|
||||||
|
|
||||||
|
const StepContext = createContext(null);
|
||||||
|
|
||||||
|
const StepperWizard = ({children}) => {
|
||||||
|
const [step, setStep] = useState(0);
|
||||||
|
|
||||||
|
const isStep = n => (0 <= n && n < children.length);
|
||||||
|
const setStepNext = () => setStep(n => isStep(n + 1) ? n + 1 : n);
|
||||||
|
const setStepBack = () => setStep(n => isStep(n - 1) ? n - 1 : n);
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
step,
|
||||||
|
setStep,
|
||||||
|
setStepNext,
|
||||||
|
setStepBack,
|
||||||
|
isStep,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StepContext.Provider value={value}>
|
||||||
|
<Box sx={{ width: '100%', height: '100%', display: "flex", flexDirection: "column", overflow: "hidden" }}>
|
||||||
|
<Stepper activeStep={step} sx={{ paddingRight: '3vw', paddingLeft: '3vw', marginBottom: '2vw' }}>
|
||||||
|
{children.map(child => (
|
||||||
|
<Tooltip title={child.props.tooltip}>
|
||||||
|
<Step key={child.props.label}>
|
||||||
|
<StepLabel>{child.props.label}</StepLabel>
|
||||||
|
</Step>
|
||||||
|
</Tooltip>)
|
||||||
|
)}
|
||||||
|
</Stepper>
|
||||||
|
{children[step]}
|
||||||
|
</Box>
|
||||||
|
</StepContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const useStepper = () => useContext(StepContext);
|
||||||
|
|
||||||
|
const StepperFooter = ({nextDisabled, backDisabled, onBack = null, onNext = null, onSubmit = () => {}}) => {
|
||||||
|
const { step, isStep, setStepNext, setStepBack, setStep } = useStepper();
|
||||||
|
const { resetFilters } = useFilter();
|
||||||
|
const isSubmit = !isStep(step + 2);
|
||||||
|
|
||||||
|
const _onBack = () => {
|
||||||
|
if (isStep(step + 1)) {
|
||||||
|
setStepBack();
|
||||||
|
} else {
|
||||||
|
resetFilters();
|
||||||
|
setStep(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onNext = () => {
|
||||||
|
setStepNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onSubmit = () => {
|
||||||
|
onSubmit();
|
||||||
|
if (onNext) {
|
||||||
|
onNext();
|
||||||
|
} else {
|
||||||
|
_onNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'row', pt: 2, pb: 2, paddingRight: '3vw', paddingLeft: '3vw', minHeight: '68px' }}>
|
||||||
|
{isStep(step - 1) &&
|
||||||
|
<Button
|
||||||
|
onClick={onBack ?? _onBack}
|
||||||
|
disabled={backDisabled}
|
||||||
|
>
|
||||||
|
{isStep(step + 1) ? "Back" : "Reset"}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
<Box sx={{ flex: '1 1 auto' }} />
|
||||||
|
{isStep(step + 1) &&
|
||||||
|
<Button
|
||||||
|
onClick={isSubmit ? _onSubmit : (onNext ?? _onNext)}
|
||||||
|
disabled={nextDisabled}
|
||||||
|
>
|
||||||
|
{isSubmit ? "Submit" : "Next"}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
</Box>);
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
StepperWizard,
|
||||||
|
StepperFooter,
|
||||||
|
useStepper,
|
||||||
|
};
|
|
@ -25,9 +25,10 @@ const AddressSearchSuggestions = ({results, onClick}) => (
|
||||||
</Box>
|
</Box>
|
||||||
: null);
|
: null);
|
||||||
|
|
||||||
const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDisabled, setRedirectBack, classNames}) => {
|
const AddressSearch = ({onSelect, classNames}) => {
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
const [enable, setEnable] = useState(true);
|
const [enable, setEnable] = useState(true);
|
||||||
|
const [selected, setSelected] = useState(null);
|
||||||
const [results, setResults] = useState([]);
|
const [results, setResults] = useState([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
@ -35,7 +36,6 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
|
||||||
setResults([]);
|
setResults([]);
|
||||||
|
|
||||||
if (enable && value && value.length > 5) {
|
if (enable && value && value.length > 5) {
|
||||||
setNextDisabled(true);
|
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
LocationRepsostory.getPropertyDetails({search: value}).then(resp => {
|
LocationRepsostory.getPropertyDetails({search: value}).then(resp => {
|
||||||
|
@ -46,7 +46,11 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}
|
}
|
||||||
}, [value, enable, setNextDisabled]);
|
}, [value, enable]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onSelect(selected);
|
||||||
|
}, [selected, onSelect]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div classNames={classNames}>
|
<div classNames={classNames}>
|
||||||
|
@ -65,6 +69,9 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setEnable(true);
|
setEnable(true);
|
||||||
setValue(e.target.value);
|
setValue(e.target.value);
|
||||||
|
if (selected && e.target.value !== selected.address) {
|
||||||
|
setSelected(null);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
|
@ -72,14 +79,8 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
|
||||||
results={results}
|
results={results}
|
||||||
onClick={(r) => {
|
onClick={(r) => {
|
||||||
setValue(r.address);
|
setValue(r.address);
|
||||||
updateFilterState({
|
|
||||||
coordinates: {
|
|
||||||
lng: r.coordinates[0],
|
|
||||||
lat: r.coordinates[1],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
setNextDisabled(false);
|
|
||||||
setEnable(false);
|
setEnable(false);
|
||||||
|
setSelected(r);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>);
|
</div>);
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
|
import { useState } from 'react';
|
||||||
import Step from '../Step';
|
import Step from '../Step';
|
||||||
import StepInformation from '../StepInformation';
|
import StepInformation from '../StepInformation';
|
||||||
import staticText from '../../../assets/data/staticText.json'
|
import staticText from '../../../assets/data/staticText.json'
|
||||||
import addressBackgroundImage from '../../../assets/img/stepBackgrounds/step1.jpg';
|
import addressBackgroundImage from '../../../assets/img/stepBackgrounds/step1.jpg';
|
||||||
import AddressSearch from './AddressSearch';
|
import AddressSearch from './AddressSearch';
|
||||||
|
import { StepperFooter } from '../../providers/StepperProvider';
|
||||||
|
import { useFilter } from '../../providers/FilterProvider';
|
||||||
|
|
||||||
|
|
||||||
const AddressStep = (props) => {
|
const AddressStep = () => {
|
||||||
|
const [nextDisabled, setNextDisabled] = useState(true);
|
||||||
|
const { updateFilters } = useFilter();
|
||||||
|
|
||||||
const addressPanel = (
|
const addressPanel = (
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
|
@ -14,16 +19,31 @@ const AddressStep = (props) => {
|
||||||
description={<p>{staticText.steps.address.description}</p>}
|
description={<p>{staticText.steps.address.description}</p>}
|
||||||
/>
|
/>
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<AddressSearch {...props} />
|
<AddressSearch onSelect={address => {
|
||||||
|
if (address) {
|
||||||
|
setNextDisabled(false);
|
||||||
|
updateFilters({
|
||||||
|
coordinates: {
|
||||||
|
lat: address.coordinates[1],
|
||||||
|
lng: address.coordinates[0],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setNextDisabled(true);
|
||||||
|
}
|
||||||
|
}}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Step
|
<Step
|
||||||
contentComponent={addressPanel}
|
contentComponent={addressPanel}
|
||||||
backgroundImage={addressBackgroundImage}
|
backgroundImage={addressBackgroundImage}
|
||||||
/>);
|
/>
|
||||||
|
<StepperFooter nextDisabled={nextDisabled} />
|
||||||
|
</>);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AddressStep;
|
export default AddressStep;
|
||||||
|
|
24
frontend/src/components/steps/complete/CompleteStep.jsx
Normal file
24
frontend/src/components/steps/complete/CompleteStep.jsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import Step from "../Step";
|
||||||
|
import StepInformation from "../StepInformation";
|
||||||
|
import completeBackgroundImage from "../../../assets/img/stepBackgrounds/step6.jpg";
|
||||||
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
|
import { StepperFooter } from "../../providers/StepperProvider";
|
||||||
|
|
||||||
|
export default function CompleteStep() {
|
||||||
|
const completeInfoPanel = (
|
||||||
|
<StepInformation
|
||||||
|
title={staticText.steps.complete.title}
|
||||||
|
description={<p>{staticText.steps.complete.description}</p>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Step
|
||||||
|
informationComponent={completeInfoPanel}
|
||||||
|
backgroundImage={completeBackgroundImage}
|
||||||
|
/>
|
||||||
|
<StepperFooter />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -8,16 +8,18 @@ import FormLabel from "@mui/material/FormLabel";
|
||||||
import FormControl from "@mui/material/FormControl";
|
import FormControl from "@mui/material/FormControl";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
import { HabitatSVG } from "../HabitatSVG";
|
import { HabitatSVG } from "../HabitatSVG";
|
||||||
|
import { useFilter } from '../../providers/FilterProvider';
|
||||||
|
|
||||||
export default function HabitatSelector(props) {
|
export default function HabitatSelector({setNextDisabled}) {
|
||||||
|
const { filters, updateFilters } = useFilter();
|
||||||
const [habitats, setHabitats] = useState([]);
|
const [habitats, setHabitats] = useState([]);
|
||||||
const [habitatsMap, setHabitatsMap] = useState({});
|
const [habitatsMap, setHabitatsMap] = useState({});
|
||||||
const [value, setValue] = React.useState(
|
const [value, setValue] = React.useState(
|
||||||
props.filters.habitat && props.filters.habitat.id
|
filters.habitat && filters.habitat.id
|
||||||
);
|
);
|
||||||
const [selectedHabitat, setSelectedHabitat] = React.useState({});
|
const [selectedHabitat, setSelectedHabitat] = React.useState({});
|
||||||
const [imageValue, setImageValue] = React.useState(
|
const [imageValue, setImageValue] = React.useState(
|
||||||
props.filters.habitatImage
|
filters.habitatImage
|
||||||
);
|
);
|
||||||
|
|
||||||
const getHabitats = () => {
|
const getHabitats = () => {
|
||||||
|
@ -39,22 +41,22 @@ export default function HabitatSelector(props) {
|
||||||
habitats.length === 0 && getHabitats();
|
habitats.length === 0 && getHabitats();
|
||||||
|
|
||||||
// Sets the selected habitat if its already set in filters
|
// Sets the selected habitat if its already set in filters
|
||||||
if (props.filters.habitat && props.filters.habitat.id) {
|
if (filters.habitat && filters.habitat.id) {
|
||||||
setSelectedHabitat(habitatsMap[props.filters.habitat.id]);
|
setSelectedHabitat(habitatsMap[filters.habitat.id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If both the habitat and the image is selected, then enable the next step
|
// If both the habitat and the image is selected, then enable the next step
|
||||||
if (props.filters.habitat && props.filters.habitatImage) {
|
if (filters.habitat && filters.habitatImage) {
|
||||||
props.setNextDisabled(false);
|
setNextDisabled(false);
|
||||||
}
|
}
|
||||||
}, [habitats.length, props, habitatsMap]);
|
}, [habitats.length, setNextDisabled, habitatsMap, filters]);
|
||||||
|
|
||||||
const setHabitatImage = (imageId) => {
|
const setHabitatImage = (imageId) => {
|
||||||
// Sets the selected image radio, updates filter state for image and enable the next button
|
// Sets the selected image radio, updates filter state for image and enable the next button
|
||||||
setImageValue(imageId);
|
setImageValue(imageId);
|
||||||
props.updateFilterState({ habitatImage: imageId });
|
updateFilters({ habitatImage: imageId });
|
||||||
props.updateFilterState({ zone: null });
|
updateFilters({ zone: null });
|
||||||
props.setNextDisabled(false);
|
setNextDisabled(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRadioChange = (event) => {
|
const handleRadioChange = (event) => {
|
||||||
|
@ -69,11 +71,11 @@ export default function HabitatSelector(props) {
|
||||||
if (habitatObject.images.length === 1) {
|
if (habitatObject.images.length === 1) {
|
||||||
setHabitatImage(habitatObject.images[0].id);
|
setHabitatImage(habitatObject.images[0].id);
|
||||||
} else {
|
} else {
|
||||||
props.setNextDisabled(true);
|
setNextDisabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the filters for the selected habitat
|
// Update the filters for the selected habitat
|
||||||
props.updateFilterState({
|
updateFilters({
|
||||||
habitat: { id: habitatObject.id, name: habitatObject.name },
|
habitat: { id: habitatObject.id, name: habitatObject.name },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
import { useState } from 'react';
|
||||||
import Step from "../Step";
|
import Step from "../Step";
|
||||||
import HabitatSelector from "./HabitatSelector";
|
import HabitatSelector from "./HabitatSelector";
|
||||||
import StepInformation from "../StepInformation";
|
import StepInformation from "../StepInformation";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
import habitatBackgroundImage from "../../../assets/img/stepBackgrounds/step3.jpg";
|
import habitatBackgroundImage from "../../../assets/img/stepBackgrounds/step3.jpg";
|
||||||
|
import { StepperFooter } from '../../providers/StepperProvider';
|
||||||
|
|
||||||
export default function HabitatStep(props) {
|
export default function HabitatStep(props) {
|
||||||
|
const [nextDisabled, setNextDisabled] = useState(true);
|
||||||
|
|
||||||
const habitatInfoPanel = (
|
const habitatInfoPanel = (
|
||||||
<StepInformation
|
<StepInformation
|
||||||
title={staticText.steps.habitat.title}
|
title={staticText.steps.habitat.title}
|
||||||
|
@ -12,13 +16,16 @@ export default function HabitatStep(props) {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const habitatSelectionPanel = <HabitatSelector {...props} />;
|
const habitatSelectionPanel = <HabitatSelector setNextDisabled={setNextDisabled} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Step
|
<Step
|
||||||
informationComponent={habitatInfoPanel}
|
informationComponent={habitatInfoPanel}
|
||||||
selectionComponent={habitatSelectionPanel}
|
selectionComponent={habitatSelectionPanel}
|
||||||
backgroundImage={habitatBackgroundImage}
|
backgroundImage={habitatBackgroundImage}
|
||||||
/>
|
/>
|
||||||
|
<StepperFooter nextDisabled={nextDisabled} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
import { useState } from "react";
|
||||||
import Step from "../Step";
|
import Step from "../Step";
|
||||||
import LocationSelectorMap from "./Map";
|
import LocationSelectorMap from "./Map";
|
||||||
import StepInformation from "../StepInformation";
|
import StepInformation from "../StepInformation";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
import locationBackgroundImage from "../../../assets/img/stepBackgrounds/step1.jpg";
|
import locationBackgroundImage from "../../../assets/img/stepBackgrounds/step1.jpg";
|
||||||
|
import { StepperFooter } from '../../providers/StepperProvider';
|
||||||
|
|
||||||
export default function LocationStep(props) {
|
export default function LocationStep(props) {
|
||||||
|
const [nextDisabled, setNextDisabled] = useState(true);
|
||||||
|
|
||||||
const locationInfoPanel = (
|
const locationInfoPanel = (
|
||||||
<StepInformation
|
<StepInformation
|
||||||
title={staticText.steps.location.title}
|
title={staticText.steps.location.title}
|
||||||
|
@ -12,13 +16,16 @@ export default function LocationStep(props) {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const locationSelectionPanel = <LocationSelectorMap {...props} />;
|
const locationSelectionPanel = <LocationSelectorMap setNextDisabled={setNextDisabled} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Step
|
<Step
|
||||||
informationComponent={locationInfoPanel}
|
informationComponent={locationInfoPanel}
|
||||||
selectionComponent={locationSelectionPanel}
|
selectionComponent={locationSelectionPanel}
|
||||||
backgroundImage={locationBackgroundImage}
|
backgroundImage={locationBackgroundImage}
|
||||||
/>
|
/>
|
||||||
|
<StepperFooter nextDisabled={nextDisabled} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,31 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { MapContainer, TileLayer, Marker, useMapEvents } from "react-leaflet";
|
import { MapContainer, TileLayer, Marker, useMapEvents } from "react-leaflet";
|
||||||
import LocationRepository from "../../../repository/LocationRepository";
|
import LocationRepository from "../../../repository/LocationRepository";
|
||||||
|
import { useFilter } from "../../providers/FilterProvider";
|
||||||
|
|
||||||
const NZ_BOUNDS = [
|
const NZ_BOUNDS = [
|
||||||
[-47.204642, 165.344238],
|
[-47.204642, 165.344238],
|
||||||
[-34.307144, 179.824219],
|
[-34.307144, 179.824219],
|
||||||
];
|
];
|
||||||
|
|
||||||
function LocationMarker(props) {
|
function LocationMarker({setNextDisabled}) {
|
||||||
const [position, setPosition] = useState(null);
|
const [position, setPosition] = useState(null);
|
||||||
|
const { filters, updateFilters } = useFilter();
|
||||||
|
|
||||||
const map = useMapEvents({
|
const map = useMapEvents({
|
||||||
click(e) {
|
click(e) {
|
||||||
const newPosition = e.latlng;
|
const newPosition = e.latlng;
|
||||||
setPosition(newPosition);
|
setPosition(newPosition);
|
||||||
props.updateFilterState({ coordinates: newPosition });
|
updateFilters({ coordinates: newPosition });
|
||||||
props.setNextDisabled(false);
|
setNextDisabled(false);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
map.whenReady(() => {
|
map.whenReady(() => {
|
||||||
const savedCoordinates = props.filters["coordinates"];
|
const savedCoordinates = filters.coordinates;
|
||||||
if (!position && savedCoordinates) {
|
if (!position && savedCoordinates) {
|
||||||
setPosition(savedCoordinates);
|
setPosition(savedCoordinates);
|
||||||
props.setNextDisabled(false);
|
setNextDisabled(false);
|
||||||
map.flyTo(savedCoordinates, 9);
|
map.flyTo(savedCoordinates, 9);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -36,16 +39,17 @@ const fitNZBounds = (map) => {
|
||||||
|
|
||||||
function LocationDetailsDisplay(props) {
|
function LocationDetailsDisplay(props) {
|
||||||
const [locationDetails, setLocationDetails] = useState({});
|
const [locationDetails, setLocationDetails] = useState({});
|
||||||
|
const { filters } = useFilter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.filters["coordinates"]) {
|
if (filters.coordinates) {
|
||||||
LocationRepository.getLocationData(props.filters).then((result) => {
|
LocationRepository.getLocationData(filters).then((result) => {
|
||||||
setLocationDetails(result);
|
setLocationDetails(result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [props.filters, props.filters.coordinates]);
|
}, [filters]);
|
||||||
|
|
||||||
const savedCoordinates = props.filters["coordinates"];
|
const savedCoordinates = filters.coordinates;
|
||||||
|
|
||||||
if (savedCoordinates) {
|
if (savedCoordinates) {
|
||||||
const soilString = `${locationDetails.soil_name} (${locationDetails.soil_code})`;
|
const soilString = `${locationDetails.soil_name} (${locationDetails.soil_code})`;
|
||||||
|
|
|
@ -8,6 +8,8 @@ import PlantRepository from "../../../repository/PlantRepository";
|
||||||
import { Typography, Box } from "@mui/material";
|
import { Typography, Box } from "@mui/material";
|
||||||
import resultsBackgroundImage from "../../../assets/img/stepBackgrounds/step6.jpg";
|
import resultsBackgroundImage from "../../../assets/img/stepBackgrounds/step6.jpg";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
|
import { useFilter } from "../../providers/FilterProvider";
|
||||||
|
import { StepperFooter } from "../../providers/StepperProvider";
|
||||||
|
|
||||||
const RESULTS_DESCRIPTION = (
|
const RESULTS_DESCRIPTION = (
|
||||||
<Typography>
|
<Typography>
|
||||||
|
@ -29,10 +31,11 @@ const RESULTS_DESCRIPTION = (
|
||||||
|
|
||||||
export default function ResultsStep(props) {
|
export default function ResultsStep(props) {
|
||||||
const [plants, setPlants] = useState([]);
|
const [plants, setPlants] = useState([]);
|
||||||
|
const { filters } = useFilter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const updatePlants = () => {
|
const updatePlants = () => {
|
||||||
PlantRepository.getFilteredPlants(props.filters)
|
PlantRepository.getFilteredPlants(filters)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setPlants(response.data);
|
setPlants(response.data);
|
||||||
|
@ -43,7 +46,7 @@ export default function ResultsStep(props) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
updatePlants();
|
updatePlants();
|
||||||
}, [props.filters]);
|
}, [filters]);
|
||||||
|
|
||||||
function createData(
|
function createData(
|
||||||
name,
|
name,
|
||||||
|
@ -91,13 +94,13 @@ export default function ResultsStep(props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadCSV = () => {
|
const downloadCSV = () => {
|
||||||
PlantRepository.getPlantsCSV(props.filters).then((response) => {
|
PlantRepository.getPlantsCSV(filters).then((response) => {
|
||||||
download(response, "text/csv", "plants.csv");
|
download(response, "text/csv", "plants.csv");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadPDF = () => {
|
const downloadPDF = () => {
|
||||||
PlantRepository.getPlantsPDF(props.filters).then((response) => {
|
PlantRepository.getPlantsPDF(filters).then((response) => {
|
||||||
download(response, "application/pdf", "planting_guide.pdf");
|
download(response, "application/pdf", "planting_guide.pdf");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -133,9 +136,12 @@ export default function ResultsStep(props) {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Step
|
<Step
|
||||||
contentComponent={stepContent}
|
contentComponent={stepContent}
|
||||||
backgroundImage={resultsBackgroundImage}
|
backgroundImage={resultsBackgroundImage}
|
||||||
/>
|
/>
|
||||||
|
<StepperFooter />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import FormControl from "@mui/material/FormControl";
|
||||||
import FormHelperText from "@mui/material/FormHelperText";
|
import FormHelperText from "@mui/material/FormHelperText";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
|
import { useFilter } from "../../providers/FilterProvider";
|
||||||
|
|
||||||
const WET_SOIL_DESCRIPTION = (
|
const WET_SOIL_DESCRIPTION = (
|
||||||
<p>
|
<p>
|
||||||
|
@ -53,24 +54,26 @@ const MESIC_SOIL_DESCRIPTION = (
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function SoilSelector(props) {
|
export default function SoilSelector({setNextDisabled}) {
|
||||||
const [value, setValue] = React.useState(props.filters.soilVariant);
|
const { filters, updateFilters } = useFilter();
|
||||||
|
|
||||||
|
const [value, setValue] = React.useState(filters.soilVariant);
|
||||||
const [helperText, setHelperText] = React.useState(
|
const [helperText, setHelperText] = React.useState(
|
||||||
staticText.steps.soil.optionsHelperText
|
staticText.steps.soil.optionsHelperText
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (props.filters.soilVariant) {
|
if (filters.soilVariant) {
|
||||||
props.setNextDisabled(false);
|
setNextDisabled(false);
|
||||||
}
|
}
|
||||||
});
|
}, [filters, setNextDisabled]);
|
||||||
|
|
||||||
const handleRadioChange = (event) => {
|
const handleRadioChange = (event) => {
|
||||||
const soilVariantSelection = event.target.value;
|
const soilVariantSelection = event.target.value;
|
||||||
setValue(soilVariantSelection);
|
setValue(soilVariantSelection);
|
||||||
setHelperText(" ");
|
setHelperText(" ");
|
||||||
props.updateFilterState({ soilVariant: soilVariantSelection });
|
updateFilters({ soilVariant: soilVariantSelection });
|
||||||
props.setNextDisabled(false);
|
setNextDisabled(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
|
import { useState } from 'react';
|
||||||
import Step from "../Step";
|
import Step from "../Step";
|
||||||
import SoilSelector from "./SoilSelector";
|
import SoilSelector from "./SoilSelector";
|
||||||
import StepInformation from "../StepInformation";
|
import StepInformation from "../StepInformation";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
import soilBackgroundImage from "../../../assets/img/stepBackgrounds/step2.jpg";
|
import soilBackgroundImage from "../../../assets/img/stepBackgrounds/step2.jpg";
|
||||||
|
import { StepperFooter } from '../../providers/StepperProvider';
|
||||||
|
|
||||||
|
|
||||||
export default function SoilVariantStep(props) {
|
export default function SoilVariantStep(props) {
|
||||||
|
const [nextDisabled, setNextDisabled] = useState(true);
|
||||||
|
|
||||||
const SOIL_DESCRIPTION = (
|
const SOIL_DESCRIPTION = (
|
||||||
<p>
|
<p>
|
||||||
From your site location, we use{" "}
|
From your site location, we use{" "}
|
||||||
|
@ -36,15 +41,18 @@ export default function SoilVariantStep(props) {
|
||||||
|
|
||||||
const soilVarientSelectionPanel = (
|
const soilVarientSelectionPanel = (
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
<SoilSelector {...props} />
|
<SoilSelector setNextDisabled={setNextDisabled} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Step
|
<Step
|
||||||
informationComponent={soilVarientInfoPanel}
|
informationComponent={soilVarientInfoPanel}
|
||||||
selectionComponent={soilVarientSelectionPanel}
|
selectionComponent={soilVarientSelectionPanel}
|
||||||
backgroundImage={soilBackgroundImage}
|
backgroundImage={soilBackgroundImage}
|
||||||
/>
|
/>
|
||||||
|
<StepperFooter nextDisabled={nextDisabled} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
export default function ProjectSpecificsSelector(props) {
|
|
||||||
useEffect(() => {
|
|
||||||
props.setNextDisabled(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
return <h2>Project Specifics Selector</h2>;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import Step from "../Step";
|
|
||||||
import ProjectSpecificsSelector from "./ProjectSpecificsSelector";
|
|
||||||
import StepInformation from "../StepInformation";
|
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
|
||||||
|
|
||||||
export default function ProjectSpecificsStep(props) {
|
|
||||||
const projectSpecificsInfoPanel = (
|
|
||||||
<StepInformation
|
|
||||||
title={staticText.steps.projectSpecifics.title}
|
|
||||||
description={<p>{staticText.steps.projectSpecifics.description}</p>}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const projectSpecificsSelectionPanel = (
|
|
||||||
<ProjectSpecificsSelector {...props} />
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Step
|
|
||||||
informationComponent={projectSpecificsInfoPanel}
|
|
||||||
selectionComponent={projectSpecificsSelectionPanel}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -8,13 +8,15 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
|
||||||
import SummaryTable from "./SummaryTable";
|
import SummaryTable from "./SummaryTable";
|
||||||
import LocationRepository from "../../../repository/LocationRepository";
|
import LocationRepository from "../../../repository/LocationRepository";
|
||||||
|
import { useFilter } from "../../providers/FilterProvider";
|
||||||
|
|
||||||
export default function SummaryContent(props) {
|
export default function SummaryContent() {
|
||||||
const [expanded, setExpanded] = React.useState(null);
|
const [expanded, setExpanded] = React.useState(null);
|
||||||
const [locationDetails, setLocationDetails] = React.useState({});
|
const [locationDetails, setLocationDetails] = React.useState({});
|
||||||
|
const { filters } = useFilter();
|
||||||
|
|
||||||
const getLocationDetails = () => {
|
const getLocationDetails = () => {
|
||||||
LocationRepository.getLocationData(props.filters).then((result) => {
|
LocationRepository.getLocationData(filters).then((result) => {
|
||||||
setLocationDetails(result);
|
setLocationDetails(result);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -24,7 +26,6 @@ export default function SummaryContent(props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
props.setNextDisabled(false);
|
|
||||||
!Object.keys(locationDetails).length && getLocationDetails();
|
!Object.keys(locationDetails).length && getLocationDetails();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ export default function SummaryContent(props) {
|
||||||
const locationData = [
|
const locationData = [
|
||||||
createData(
|
createData(
|
||||||
"Geographical Coordinates (latitude, longitude)",
|
"Geographical Coordinates (latitude, longitude)",
|
||||||
`(${props.filters.coordinates.lat}, ${props.filters.coordinates.lng})`
|
`(${filters.coordinates.lat}, ${filters.coordinates.lng})`
|
||||||
),
|
),
|
||||||
createData("Ecological Region", locationDetails.ecological_region || ""),
|
createData("Ecological Region", locationDetails.ecological_region || ""),
|
||||||
createData(
|
createData(
|
||||||
|
@ -50,22 +51,22 @@ export default function SummaryContent(props) {
|
||||||
"Soil Order",
|
"Soil Order",
|
||||||
`${locationDetails.soil_name} (${locationDetails.soil_code})` || ""
|
`${locationDetails.soil_name} (${locationDetails.soil_code})` || ""
|
||||||
),
|
),
|
||||||
createData("Soil Variant", props.filters.soilVariant),
|
createData("Soil Variant", filters.soilVariant),
|
||||||
];
|
];
|
||||||
|
|
||||||
const siteData = [
|
const siteData = [
|
||||||
createData("Habitat", props.filters.habitat.name ?? ""),
|
createData("Habitat", filters.habitat.name ?? ""),
|
||||||
createData(
|
createData(
|
||||||
"Zone Name",
|
"Zone Name",
|
||||||
(props.filters.zone && props.filters.zone.name) ?? ""
|
(filters.zone && filters.zone.name) ?? ""
|
||||||
),
|
),
|
||||||
createData(
|
createData(
|
||||||
"Zone Variant",
|
"Zone Variant",
|
||||||
(props.filters.zone && props.filters.zone.variant) ?? ""
|
(filters.zone && filters.zone.variant) ?? ""
|
||||||
),
|
),
|
||||||
createData(
|
createData(
|
||||||
"Zone Refined Variant",
|
"Zone Refined Variant",
|
||||||
(props.filters.zone && props.filters.zone.refined_variant) ?? ""
|
(filters.zone && filters.zone.refined_variant) ?? ""
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,10 @@ import SummaryContent from "./SummaryContent";
|
||||||
import StepInformation from "../StepInformation";
|
import StepInformation from "../StepInformation";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
import summaryBackgroundImage from "../../../assets/img/stepBackgrounds/step5.jpg";
|
import summaryBackgroundImage from "../../../assets/img/stepBackgrounds/step5.jpg";
|
||||||
|
import { StepperFooter } from '../../providers/StepperProvider';
|
||||||
|
|
||||||
export default function SummaryStep(props) {
|
|
||||||
|
export default function SummaryStep({ onSubmit }) {
|
||||||
const summaryInfoPanel = (
|
const summaryInfoPanel = (
|
||||||
<StepInformation
|
<StepInformation
|
||||||
title={staticText.steps.summary.title}
|
title={staticText.steps.summary.title}
|
||||||
|
@ -12,13 +14,16 @@ export default function SummaryStep(props) {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const summaryContent = <SummaryContent {...props} />;
|
const summaryContent = <SummaryContent />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Step
|
<Step
|
||||||
informationComponent={summaryInfoPanel}
|
informationComponent={summaryInfoPanel}
|
||||||
selectionComponent={summaryContent}
|
selectionComponent={summaryContent}
|
||||||
backgroundImage={summaryBackgroundImage}
|
backgroundImage={summaryBackgroundImage}
|
||||||
/>
|
/>
|
||||||
|
<StepperFooter onSubmit={onSubmit} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import SiteRepository from "../../../repository/SiteRepository";
|
import SiteRepository from "../../../repository/SiteRepository";
|
||||||
|
import { useFilter } from "../../providers/FilterProvider";
|
||||||
import { HabitatSVG } from "../HabitatSVG";
|
import { HabitatSVG } from "../HabitatSVG";
|
||||||
|
|
||||||
export default function ZoneSelector(props) {
|
export default function ZoneSelector({setNextDisabled}) {
|
||||||
const [habitatImageObject, setHabitatImageObject] = useState({});
|
const [habitatImageObject, setHabitatImageObject] = useState({});
|
||||||
const [segmentMapping, setSegmentMapping] = useState({});
|
const [segmentMapping, setSegmentMapping] = useState({});
|
||||||
const [selectedZoneSegment, setZoneSegment] = useState(null);
|
const [selectedZoneSegment, setZoneSegment] = useState(null);
|
||||||
|
const { filters, updateFilters } = useFilter();
|
||||||
|
|
||||||
const setZoneOrRedirect = (zone) => {
|
const setZoneOrRedirect = (zone) => {
|
||||||
const redirectHabitat = zone && zone.redirect_habitat;
|
const redirectHabitat = zone && zone.redirect_habitat;
|
||||||
|
@ -15,15 +17,13 @@ export default function ZoneSelector(props) {
|
||||||
? { habitat: { id: redirectHabitat.id, name: redirectHabitat.name } }
|
? { habitat: { id: redirectHabitat.id, name: redirectHabitat.name } }
|
||||||
: { zone: zone };
|
: { zone: zone };
|
||||||
|
|
||||||
props.updateFilterState(newFilterState);
|
updateFilters(newFilterState);
|
||||||
props.setRedirectBack(Boolean(redirectHabitat));
|
setNextDisabled(false);
|
||||||
|
|
||||||
props.setNextDisabled(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getHabitatImage = () => {
|
const getHabitatImage = () => {
|
||||||
SiteRepository.getHabitatImage(props.filters.habitatImage).then(
|
SiteRepository.getHabitatImage(filters.habitatImage).then(
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
const imageData = response.data;
|
const imageData = response.data;
|
||||||
|
@ -34,8 +34,8 @@ export default function ZoneSelector(props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const setInitialZone = () => {
|
const setInitialZone = () => {
|
||||||
if (props.filters.zone) {
|
if (filters.zone) {
|
||||||
const zone = props.filters.zone;
|
const zone = filters.zone;
|
||||||
const zoneSegment = document.querySelectorAll(
|
const zoneSegment = document.querySelectorAll(
|
||||||
`.zone-selector-svg svg path[inkscapelabel="${zone.related_svg_segment}"]`
|
`.zone-selector-svg svg path[inkscapelabel="${zone.related_svg_segment}"]`
|
||||||
)[0];
|
)[0];
|
||||||
|
@ -45,7 +45,7 @@ export default function ZoneSelector(props) {
|
||||||
setZoneSegment(zoneSegment);
|
setZoneSegment(zoneSegment);
|
||||||
zoneSegment.style.fill = "#eeeeee";
|
zoneSegment.style.fill = "#eeeeee";
|
||||||
zoneSegment.style["fill-opacity"] = 0.5;
|
zoneSegment.style["fill-opacity"] = 0.5;
|
||||||
props.setNextDisabled(false);
|
setNextDisabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -69,7 +69,7 @@ export default function ZoneSelector(props) {
|
||||||
|
|
||||||
// Retrieves the habitat image from the api if it's not loaded already
|
// Retrieves the habitat image from the api if it's not loaded already
|
||||||
Object.keys(segmentMapping).length === 0 && getZones();
|
Object.keys(segmentMapping).length === 0 && getZones();
|
||||||
}, [habitatImageObject, segmentMapping, props, props.filters.zone]);
|
}, [habitatImageObject, segmentMapping, setNextDisabled, filters]);
|
||||||
|
|
||||||
const selectZone = (element) => {
|
const selectZone = (element) => {
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -1,10 +1,20 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
import Step from "../Step";
|
import Step from "../Step";
|
||||||
import ZoneSelector from "./ZoneSelector";
|
import ZoneSelector from "./ZoneSelector";
|
||||||
import StepInformation from "../StepInformation";
|
import StepInformation from "../StepInformation";
|
||||||
import staticText from "../../../assets/data/staticText.json";
|
import staticText from "../../../assets/data/staticText.json";
|
||||||
import zoneBackgroundImage from "../../../assets/img/stepBackgrounds/step4.jpg";
|
import zoneBackgroundImage from "../../../assets/img/stepBackgrounds/step4.jpg";
|
||||||
|
import { StepperFooter, useStepper } from '../../providers/StepperProvider';
|
||||||
|
import { useFilter } from '../../providers/FilterProvider';
|
||||||
|
|
||||||
|
export default function ZoneStep({repeatable}) {
|
||||||
|
const [nextDisabled, setNextDisabled] = useState(true);
|
||||||
|
const { setStepBack, setStepNext } = useStepper();
|
||||||
|
const { filters } = useFilter();
|
||||||
|
|
||||||
|
const redirect = !nextDisabled && !filters.zone;
|
||||||
|
|
||||||
export default function ZoneStep(props) {
|
|
||||||
const zoneInfoPanel = (
|
const zoneInfoPanel = (
|
||||||
<StepInformation
|
<StepInformation
|
||||||
title={staticText.steps.zone.title}
|
title={staticText.steps.zone.title}
|
||||||
|
@ -23,15 +33,21 @@ export default function ZoneStep(props) {
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ZoneSelector {...props} />
|
<ZoneSelector setNextDisabled={setNextDisabled} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Step
|
<Step
|
||||||
informationComponent={zoneInfoPanel}
|
informationComponent={zoneInfoPanel}
|
||||||
selectionComponent={zoneSelectionPanel}
|
selectionComponent={zoneSelectionPanel}
|
||||||
backgroundImage={zoneBackgroundImage}
|
backgroundImage={zoneBackgroundImage}
|
||||||
/>
|
/>
|
||||||
|
<StepperFooter
|
||||||
|
nextDisabled={nextDisabled}
|
||||||
|
onNext={redirect ? setStepBack : setStepNext}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { createTheme, ThemeProvider } from "@mui/material/styles";
|
||||||
import reportWebVitals from "./reportWebVitals";
|
import reportWebVitals from "./reportWebVitals";
|
||||||
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import MainPage from "./pages/MainPage";
|
import MainPage from "./pages/MainPage";
|
||||||
|
import { FilterProvider } from "./components/providers/FilterProvider";
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
import "./assets/styles/main.scss";
|
import "./assets/styles/main.scss";
|
||||||
|
@ -33,9 +34,11 @@ const darkTheme = createTheme({
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<div className="App">
|
<div className="App">
|
||||||
|
<FilterProvider>
|
||||||
<ThemeProvider theme={darkTheme}>
|
<ThemeProvider theme={darkTheme}>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
</FilterProvider>
|
||||||
</div>
|
</div>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
|
|
|
@ -1,45 +1,29 @@
|
||||||
import { Container } from "reactstrap";
|
import { Container } from "reactstrap";
|
||||||
import Stepper from "../components/Stepper";
|
|
||||||
import Header from "../components/Header";
|
import Header from "../components/Header";
|
||||||
import AddressStep from "../components/steps/address/AddressStep";
|
import AddressStep from "../components/steps/address/AddressStep";
|
||||||
import SoilStep from "../components/steps/soilvariant/SoilStep";
|
import SoilStep from "../components/steps/soilvariant/SoilStep";
|
||||||
import HabitatStep from "../components/steps/habitat/HabitatStep";
|
import HabitatStep from "../components/steps/habitat/HabitatStep";
|
||||||
import ZoneStep from "../components/steps/zone/ZoneStep";
|
import ZoneStep from "../components/steps/zone/ZoneStep";
|
||||||
import SummaryStep from "../components/steps/summary/SummaryStep";
|
import SummaryStep from "../components/steps/summary/SummaryStep";
|
||||||
|
import { StepperWizard } from "../components/providers/StepperProvider";
|
||||||
|
import CompleteStep from "../components/steps/complete/CompleteStep";
|
||||||
|
import { useFilter } from "../components/providers/FilterProvider";
|
||||||
|
|
||||||
const ApplyPage = () => (
|
const ApplyPage = () => {
|
||||||
|
const { submit } = useFilter();
|
||||||
|
|
||||||
|
return (
|
||||||
<Container fluid className="main-container p-0">
|
<Container fluid className="main-container p-0">
|
||||||
<Header />
|
<Header />
|
||||||
<Stepper
|
<StepperWizard>
|
||||||
steps={[
|
<AddressStep label="Enter address" tooltip="Enter your address" />
|
||||||
{
|
<SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" />
|
||||||
label: "Enter address",
|
<HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" />
|
||||||
component: AddressStep,
|
<ZoneStep label="Select zone" tooltip="Specify geographical detail" />
|
||||||
tooltip: "Enter your address",
|
<SummaryStep label="Summary" tooltip="Check your inputs" onSubmit={submit} />
|
||||||
},
|
<CompleteStep label="Complete" tooltip="Complete your application" />
|
||||||
{
|
</StepperWizard>
|
||||||
label: "Choose soil",
|
</Container>);
|
||||||
component: SoilStep,
|
};
|
||||||
tooltip: "Describe the moisture content of your soil",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Choose habitat",
|
|
||||||
component: HabitatStep,
|
|
||||||
tooltip: "Specify type of landscape to be planted",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Select zone",
|
|
||||||
component: ZoneStep,
|
|
||||||
tooltip: "Specify geographical detail",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Submit",
|
|
||||||
component: SummaryStep,
|
|
||||||
tooltip: "Submit your application",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ApplyPage;
|
export default ApplyPage;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Container } from "reactstrap";
|
import { Container } from "reactstrap";
|
||||||
import Stepper from "../components/Stepper";
|
|
||||||
import Header from "../components/Header";
|
import Header from "../components/Header";
|
||||||
import LocationStep from "../components/steps/location/LocationStep";
|
import LocationStep from "../components/steps/location/LocationStep";
|
||||||
import SoilStep from "../components/steps/soilvariant/SoilStep";
|
import SoilStep from "../components/steps/soilvariant/SoilStep";
|
||||||
|
@ -7,45 +6,21 @@ import HabitatStep from "../components/steps/habitat/HabitatStep";
|
||||||
import ZoneStep from "../components/steps/zone/ZoneStep";
|
import ZoneStep from "../components/steps/zone/ZoneStep";
|
||||||
import SummaryStep from "../components/steps/summary/SummaryStep";
|
import SummaryStep from "../components/steps/summary/SummaryStep";
|
||||||
import ResultsStep from "../components/steps/results/ResultsStep";
|
import ResultsStep from "../components/steps/results/ResultsStep";
|
||||||
|
import { StepperWizard } from "../components/providers/StepperProvider";
|
||||||
|
|
||||||
const MainPage = () => (
|
const MainPage = () => {
|
||||||
|
return (
|
||||||
<Container fluid className="main-container p-0">
|
<Container fluid className="main-container p-0">
|
||||||
<Header />
|
<Header />
|
||||||
<Stepper
|
<StepperWizard>
|
||||||
steps={[
|
<LocationStep label="Select location" tooltip="Click on a location on the map" />
|
||||||
{
|
<SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" />
|
||||||
label: "Select location",
|
<HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" />
|
||||||
component: LocationStep,
|
<ZoneStep label="Select zone" tooltip="Specify geographical detail" />
|
||||||
tooltip: "Click on a location on the map",
|
<SummaryStep label="Summary" tooltip="Check your inputs" />
|
||||||
},
|
<ResultsStep label="Results" tooltip="List of plant species and user guide" />
|
||||||
{
|
</StepperWizard>
|
||||||
label: "Choose soil",
|
</Container>);
|
||||||
component: SoilStep,
|
};
|
||||||
tooltip: "Describe the moisture content of your soil",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Choose habitat",
|
|
||||||
component: HabitatStep,
|
|
||||||
tooltip: "Specify type of landscape to be planted",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Select zone",
|
|
||||||
component: ZoneStep,
|
|
||||||
tooltip: "Specify geographical detail",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Summary",
|
|
||||||
component: SummaryStep,
|
|
||||||
tooltip: "Check your inputs",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Results",
|
|
||||||
component: ResultsStep,
|
|
||||||
tooltip: "List of plant species and user guide",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default MainPage;
|
export default MainPage;
|
||||||
|
|
|
@ -2,10 +2,9 @@ import axios from "axios";
|
||||||
|
|
||||||
// Create the axios object
|
// Create the axios object
|
||||||
const repo = axios.create({
|
const repo = axios.create({
|
||||||
baseURL:
|
baseURL: "/api",
|
||||||
window.location.hostname === "localhost"
|
xsrfHeaderName: "X-CSRFToken",
|
||||||
? "http://localhost:9000/api"
|
xsrfCookieName: "csrftoken",
|
||||||
: "/api",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
repo.defaults.headers.post["access-control-allow-origin"] = "*";
|
repo.defaults.headers.post["access-control-allow-origin"] = "*";
|
||||||
|
|
Loading…
Reference in a new issue