From 9ac545a6d435aa0e2d4a33b24d939ac7382c5de0 Mon Sep 17 00:00:00 2001
From: Matthew Northcott
Date: Tue, 21 Feb 2023 16:58:20 +1300
Subject: [PATCH] [#40] Bulk PDF export - frontend changes
---
frontend/src/assets/data/staticText.json | 4 +
frontend/src/components/Stepper.jsx | 81 --------------
.../components/providers/FilterProvider.jsx | 37 +++++++
.../components/providers/StepperProvider.jsx | 100 ++++++++++++++++++
.../steps/address/AddressSearch.jsx | 21 ++--
.../components/steps/address/AddressStep.jsx | 32 ++++--
.../steps/complete/CompleteStep.jsx | 24 +++++
.../steps/habitat/HabitatSelector.jsx | 28 ++---
.../components/steps/habitat/HabitatStep.jsx | 19 ++--
.../steps/location/LocationStep.jsx | 19 ++--
.../src/components/steps/location/Map.jsx | 22 ++--
.../components/steps/results/ResultsStep.jsx | 22 ++--
.../steps/soilvariant/SoilSelector.jsx | 17 +--
.../components/steps/soilvariant/SoilStep.jsx | 20 ++--
.../specifics/ProjectSpecificsSelector.jsx | 9 --
.../steps/specifics/ProjectSpecificsStep.jsx | 24 -----
.../steps/summary/SummaryContent.jsx | 19 ++--
.../components/steps/summary/SummaryStep.jsx | 19 ++--
.../components/steps/zone/ZoneSelector.jsx | 20 ++--
.../src/components/steps/zone/ZoneStep.jsx | 32 ++++--
frontend/src/index.js | 9 +-
frontend/src/pages/ApplyPage.jsx | 54 ++++------
frontend/src/pages/MainPage.jsx | 55 +++-------
frontend/src/repository/Repository.js | 7 +-
24 files changed, 393 insertions(+), 301 deletions(-)
delete mode 100644 frontend/src/components/Stepper.jsx
create mode 100644 frontend/src/components/providers/FilterProvider.jsx
create mode 100644 frontend/src/components/providers/StepperProvider.jsx
create mode 100644 frontend/src/components/steps/complete/CompleteStep.jsx
delete mode 100644 frontend/src/components/steps/specifics/ProjectSpecificsSelector.jsx
delete mode 100644 frontend/src/components/steps/specifics/ProjectSpecificsStep.jsx
diff --git a/frontend/src/assets/data/staticText.json b/frontend/src/assets/data/staticText.json
index 56a12e9..e4fcf7b 100644
--- a/frontend/src/assets/data/staticText.json
+++ b/frontend/src/assets/data/staticText.json
@@ -35,6 +35,10 @@
"results": {
"title": "Plant List Results",
"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."
}
}
}
diff --git a/frontend/src/components/Stepper.jsx b/frontend/src/components/Stepper.jsx
deleted file mode 100644
index 2bc1041..0000000
--- a/frontend/src/components/Stepper.jsx
+++ /dev/null
@@ -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 (
-
-
- {steps.map((step) => {
- return (
-
-
- {step.label}
-
-
- );
- })}
-
- setFilters({})}
- setNextDisabled={setNextDisabled}
- setRedirectBack={setRedirectBack}
- />
-
-
-
- {activeStep === steps.length - 1 ?
- : }
-
-
- );
-}
diff --git a/frontend/src/components/providers/FilterProvider.jsx b/frontend/src/components/providers/FilterProvider.jsx
new file mode 100644
index 0000000..755b0d6
--- /dev/null
+++ b/frontend/src/components/providers/FilterProvider.jsx
@@ -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 {children};
+};
+
+const useFilter = () => useContext(FilterContext);
+
+export {
+ FilterProvider,
+ useFilter,
+};
diff --git a/frontend/src/components/providers/StepperProvider.jsx b/frontend/src/components/providers/StepperProvider.jsx
new file mode 100644
index 0000000..8cb4e35
--- /dev/null
+++ b/frontend/src/components/providers/StepperProvider.jsx
@@ -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 (
+
+
+
+ {children.map(child => (
+
+
+ {child.props.label}
+
+ )
+ )}
+
+ {children[step]}
+
+
+ );
+};
+
+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 (
+
+ {isStep(step - 1) &&
+
+ }
+
+ {isStep(step + 1) &&
+
+ }
+ );
+};
+
+export {
+ StepperWizard,
+ StepperFooter,
+ useStepper,
+};
diff --git a/frontend/src/components/steps/address/AddressSearch.jsx b/frontend/src/components/steps/address/AddressSearch.jsx
index 8ebc18b..688b5dd 100644
--- a/frontend/src/components/steps/address/AddressSearch.jsx
+++ b/frontend/src/components/steps/address/AddressSearch.jsx
@@ -25,9 +25,10 @@ const AddressSearchSuggestions = ({results, onClick}) => (
: null);
-const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDisabled, setRedirectBack, classNames}) => {
+const AddressSearch = ({onSelect, classNames}) => {
const [value, setValue] = useState("");
const [enable, setEnable] = useState(true);
+ const [selected, setSelected] = useState(null);
const [results, setResults] = useState([]);
const [isLoading, setIsLoading] = useState(false);
@@ -35,7 +36,6 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
setResults([]);
if (enable && value && value.length > 5) {
- setNextDisabled(true);
const timer = setTimeout(() => {
setIsLoading(true);
LocationRepsostory.getPropertyDetails({search: value}).then(resp => {
@@ -46,7 +46,11 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
return () => clearTimeout(timer);
}
- }, [value, enable, setNextDisabled]);
+ }, [value, enable]);
+
+ useEffect(() => {
+ onSelect(selected);
+ }, [selected, onSelect]);
return (
@@ -65,6 +69,9 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
onChange={(e) => {
setEnable(true);
setValue(e.target.value);
+ if (selected && e.target.value !== selected.address) {
+ setSelected(null);
+ }
}}
value={value}
/>
@@ -72,14 +79,8 @@ const AddressSearch = ({filters, updateFilterState, resetFilterState, setNextDis
results={results}
onClick={(r) => {
setValue(r.address);
- updateFilterState({
- coordinates: {
- lng: r.coordinates[0],
- lat: r.coordinates[1],
- },
- });
- setNextDisabled(false);
setEnable(false);
+ setSelected(r);
}}
/>
);
diff --git a/frontend/src/components/steps/address/AddressStep.jsx b/frontend/src/components/steps/address/AddressStep.jsx
index de705df..47abb6b 100644
--- a/frontend/src/components/steps/address/AddressStep.jsx
+++ b/frontend/src/components/steps/address/AddressStep.jsx
@@ -1,11 +1,16 @@
+import { useState } from 'react';
import Step from '../Step';
import StepInformation from '../StepInformation';
import staticText from '../../../assets/data/staticText.json'
import addressBackgroundImage from '../../../assets/img/stepBackgrounds/step1.jpg';
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 = (
@@ -14,16 +19,31 @@ const AddressStep = (props) => {
description={
{staticText.steps.address.description}
}
/>
-
+
{
+ if (address) {
+ setNextDisabled(false);
+ updateFilters({
+ coordinates: {
+ lat: address.coordinates[1],
+ lng: address.coordinates[0],
+ },
+ });
+ } else {
+ setNextDisabled(true);
+ }
+ }}/>
);
return (
- );
+ <>
+
+
+ >);
};
export default AddressStep;
diff --git a/frontend/src/components/steps/complete/CompleteStep.jsx b/frontend/src/components/steps/complete/CompleteStep.jsx
new file mode 100644
index 0000000..59ac5eb
--- /dev/null
+++ b/frontend/src/components/steps/complete/CompleteStep.jsx
@@ -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 = (
+ {staticText.steps.complete.description}
}
+ />
+ );
+
+ return (
+ <>
+
+
+ >
+ );
+};
diff --git a/frontend/src/components/steps/habitat/HabitatSelector.jsx b/frontend/src/components/steps/habitat/HabitatSelector.jsx
index 33df9b8..1096b27 100644
--- a/frontend/src/components/steps/habitat/HabitatSelector.jsx
+++ b/frontend/src/components/steps/habitat/HabitatSelector.jsx
@@ -8,16 +8,18 @@ import FormLabel from "@mui/material/FormLabel";
import FormControl from "@mui/material/FormControl";
import staticText from "../../../assets/data/staticText.json";
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 [habitatsMap, setHabitatsMap] = useState({});
const [value, setValue] = React.useState(
- props.filters.habitat && props.filters.habitat.id
+ filters.habitat && filters.habitat.id
);
const [selectedHabitat, setSelectedHabitat] = React.useState({});
const [imageValue, setImageValue] = React.useState(
- props.filters.habitatImage
+ filters.habitatImage
);
const getHabitats = () => {
@@ -39,22 +41,22 @@ export default function HabitatSelector(props) {
habitats.length === 0 && getHabitats();
// Sets the selected habitat if its already set in filters
- if (props.filters.habitat && props.filters.habitat.id) {
- setSelectedHabitat(habitatsMap[props.filters.habitat.id]);
+ if (filters.habitat && filters.habitat.id) {
+ setSelectedHabitat(habitatsMap[filters.habitat.id]);
}
// If both the habitat and the image is selected, then enable the next step
- if (props.filters.habitat && props.filters.habitatImage) {
- props.setNextDisabled(false);
+ if (filters.habitat && filters.habitatImage) {
+ setNextDisabled(false);
}
- }, [habitats.length, props, habitatsMap]);
+ }, [habitats.length, setNextDisabled, habitatsMap, filters]);
const setHabitatImage = (imageId) => {
// Sets the selected image radio, updates filter state for image and enable the next button
setImageValue(imageId);
- props.updateFilterState({ habitatImage: imageId });
- props.updateFilterState({ zone: null });
- props.setNextDisabled(false);
+ updateFilters({ habitatImage: imageId });
+ updateFilters({ zone: null });
+ setNextDisabled(false);
};
const handleRadioChange = (event) => {
@@ -69,11 +71,11 @@ export default function HabitatSelector(props) {
if (habitatObject.images.length === 1) {
setHabitatImage(habitatObject.images[0].id);
} else {
- props.setNextDisabled(true);
+ setNextDisabled(true);
}
// Update the filters for the selected habitat
- props.updateFilterState({
+ updateFilters({
habitat: { id: habitatObject.id, name: habitatObject.name },
});
};
diff --git a/frontend/src/components/steps/habitat/HabitatStep.jsx b/frontend/src/components/steps/habitat/HabitatStep.jsx
index 165fe36..a12e0ac 100644
--- a/frontend/src/components/steps/habitat/HabitatStep.jsx
+++ b/frontend/src/components/steps/habitat/HabitatStep.jsx
@@ -1,10 +1,14 @@
+import { useState } from 'react';
import Step from "../Step";
import HabitatSelector from "./HabitatSelector";
import StepInformation from "../StepInformation";
import staticText from "../../../assets/data/staticText.json";
import habitatBackgroundImage from "../../../assets/img/stepBackgrounds/step3.jpg";
+import { StepperFooter } from '../../providers/StepperProvider';
export default function HabitatStep(props) {
+ const [nextDisabled, setNextDisabled] = useState(true);
+
const habitatInfoPanel = (
);
- const habitatSelectionPanel = ;
+ const habitatSelectionPanel = ;
return (
-
+ <>
+
+
+ >
);
}
diff --git a/frontend/src/components/steps/location/LocationStep.jsx b/frontend/src/components/steps/location/LocationStep.jsx
index 4e4c0b4..b5dcd13 100644
--- a/frontend/src/components/steps/location/LocationStep.jsx
+++ b/frontend/src/components/steps/location/LocationStep.jsx
@@ -1,10 +1,14 @@
+import { useState } from "react";
import Step from "../Step";
import LocationSelectorMap from "./Map";
import StepInformation from "../StepInformation";
import staticText from "../../../assets/data/staticText.json";
import locationBackgroundImage from "../../../assets/img/stepBackgrounds/step1.jpg";
+import { StepperFooter } from '../../providers/StepperProvider';
export default function LocationStep(props) {
+ const [nextDisabled, setNextDisabled] = useState(true);
+
const locationInfoPanel = (
);
- const locationSelectionPanel = ;
+ const locationSelectionPanel = ;
return (
-
+ <>
+
+
+ >
);
}
diff --git a/frontend/src/components/steps/location/Map.jsx b/frontend/src/components/steps/location/Map.jsx
index a2a5690..1f66697 100644
--- a/frontend/src/components/steps/location/Map.jsx
+++ b/frontend/src/components/steps/location/Map.jsx
@@ -1,28 +1,31 @@
import { useState, useEffect } from "react";
import { MapContainer, TileLayer, Marker, useMapEvents } from "react-leaflet";
import LocationRepository from "../../../repository/LocationRepository";
+import { useFilter } from "../../providers/FilterProvider";
const NZ_BOUNDS = [
[-47.204642, 165.344238],
[-34.307144, 179.824219],
];
-function LocationMarker(props) {
+function LocationMarker({setNextDisabled}) {
const [position, setPosition] = useState(null);
+ const { filters, updateFilters } = useFilter();
+
const map = useMapEvents({
click(e) {
const newPosition = e.latlng;
setPosition(newPosition);
- props.updateFilterState({ coordinates: newPosition });
- props.setNextDisabled(false);
+ updateFilters({ coordinates: newPosition });
+ setNextDisabled(false);
},
});
map.whenReady(() => {
- const savedCoordinates = props.filters["coordinates"];
+ const savedCoordinates = filters.coordinates;
if (!position && savedCoordinates) {
setPosition(savedCoordinates);
- props.setNextDisabled(false);
+ setNextDisabled(false);
map.flyTo(savedCoordinates, 9);
}
});
@@ -36,16 +39,17 @@ const fitNZBounds = (map) => {
function LocationDetailsDisplay(props) {
const [locationDetails, setLocationDetails] = useState({});
+ const { filters } = useFilter();
useEffect(() => {
- if (props.filters["coordinates"]) {
- LocationRepository.getLocationData(props.filters).then((result) => {
+ if (filters.coordinates) {
+ LocationRepository.getLocationData(filters).then((result) => {
setLocationDetails(result);
});
}
- }, [props.filters, props.filters.coordinates]);
+ }, [filters]);
- const savedCoordinates = props.filters["coordinates"];
+ const savedCoordinates = filters.coordinates;
if (savedCoordinates) {
const soilString = `${locationDetails.soil_name} (${locationDetails.soil_code})`;
diff --git a/frontend/src/components/steps/results/ResultsStep.jsx b/frontend/src/components/steps/results/ResultsStep.jsx
index 07a3ce8..578b416 100644
--- a/frontend/src/components/steps/results/ResultsStep.jsx
+++ b/frontend/src/components/steps/results/ResultsStep.jsx
@@ -8,6 +8,8 @@ import PlantRepository from "../../../repository/PlantRepository";
import { Typography, Box } from "@mui/material";
import resultsBackgroundImage from "../../../assets/img/stepBackgrounds/step6.jpg";
import staticText from "../../../assets/data/staticText.json";
+import { useFilter } from "../../providers/FilterProvider";
+import { StepperFooter } from "../../providers/StepperProvider";
const RESULTS_DESCRIPTION = (
@@ -29,10 +31,11 @@ const RESULTS_DESCRIPTION = (
export default function ResultsStep(props) {
const [plants, setPlants] = useState([]);
+ const { filters } = useFilter();
useEffect(() => {
const updatePlants = () => {
- PlantRepository.getFilteredPlants(props.filters)
+ PlantRepository.getFilteredPlants(filters)
.then((response) => {
if (response.status === 200) {
setPlants(response.data);
@@ -43,7 +46,7 @@ export default function ResultsStep(props) {
});
};
updatePlants();
- }, [props.filters]);
+ }, [filters]);
function createData(
name,
@@ -91,13 +94,13 @@ export default function ResultsStep(props) {
};
const downloadCSV = () => {
- PlantRepository.getPlantsCSV(props.filters).then((response) => {
+ PlantRepository.getPlantsCSV(filters).then((response) => {
download(response, "text/csv", "plants.csv");
});
};
const downloadPDF = () => {
- PlantRepository.getPlantsPDF(props.filters).then((response) => {
+ PlantRepository.getPlantsPDF(filters).then((response) => {
download(response, "application/pdf", "planting_guide.pdf");
});
};
@@ -133,9 +136,12 @@ export default function ResultsStep(props) {
);
return (
-
+ <>
+
+
+ >
);
}
diff --git a/frontend/src/components/steps/soilvariant/SoilSelector.jsx b/frontend/src/components/steps/soilvariant/SoilSelector.jsx
index a0a0fac..980a6f3 100644
--- a/frontend/src/components/steps/soilvariant/SoilSelector.jsx
+++ b/frontend/src/components/steps/soilvariant/SoilSelector.jsx
@@ -7,6 +7,7 @@ import FormControl from "@mui/material/FormControl";
import FormHelperText from "@mui/material/FormHelperText";
import Tooltip from "@mui/material/Tooltip";
import staticText from "../../../assets/data/staticText.json";
+import { useFilter } from "../../providers/FilterProvider";
const WET_SOIL_DESCRIPTION = (
@@ -53,24 +54,26 @@ const MESIC_SOIL_DESCRIPTION = (
);
-export default function SoilSelector(props) {
- const [value, setValue] = React.useState(props.filters.soilVariant);
+export default function SoilSelector({setNextDisabled}) {
+ const { filters, updateFilters } = useFilter();
+
+ const [value, setValue] = React.useState(filters.soilVariant);
const [helperText, setHelperText] = React.useState(
staticText.steps.soil.optionsHelperText
);
React.useEffect(() => {
- if (props.filters.soilVariant) {
- props.setNextDisabled(false);
+ if (filters.soilVariant) {
+ setNextDisabled(false);
}
- });
+ }, [filters, setNextDisabled]);
const handleRadioChange = (event) => {
const soilVariantSelection = event.target.value;
setValue(soilVariantSelection);
setHelperText(" ");
- props.updateFilterState({ soilVariant: soilVariantSelection });
- props.setNextDisabled(false);
+ updateFilters({ soilVariant: soilVariantSelection });
+ setNextDisabled(false);
};
return (
diff --git a/frontend/src/components/steps/soilvariant/SoilStep.jsx b/frontend/src/components/steps/soilvariant/SoilStep.jsx
index bd087c5..78959e2 100644
--- a/frontend/src/components/steps/soilvariant/SoilStep.jsx
+++ b/frontend/src/components/steps/soilvariant/SoilStep.jsx
@@ -1,10 +1,15 @@
+import { useState } from 'react';
import Step from "../Step";
import SoilSelector from "./SoilSelector";
import StepInformation from "../StepInformation";
import staticText from "../../../assets/data/staticText.json";
import soilBackgroundImage from "../../../assets/img/stepBackgrounds/step2.jpg";
+import { StepperFooter } from '../../providers/StepperProvider';
+
export default function SoilVariantStep(props) {
+ const [nextDisabled, setNextDisabled] = useState(true);
+
const SOIL_DESCRIPTION = (
From your site location, we use{" "}
@@ -36,15 +41,18 @@ export default function SoilVariantStep(props) {
const soilVarientSelectionPanel = (
-
+
);
return (
-
+ <>
+
+
+ >
);
}
diff --git a/frontend/src/components/steps/specifics/ProjectSpecificsSelector.jsx b/frontend/src/components/steps/specifics/ProjectSpecificsSelector.jsx
deleted file mode 100644
index 0b16c56..0000000
--- a/frontend/src/components/steps/specifics/ProjectSpecificsSelector.jsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { useEffect } from "react";
-
-export default function ProjectSpecificsSelector(props) {
- useEffect(() => {
- props.setNextDisabled(false);
- });
-
- return Project Specifics Selector
;
-}
diff --git a/frontend/src/components/steps/specifics/ProjectSpecificsStep.jsx b/frontend/src/components/steps/specifics/ProjectSpecificsStep.jsx
deleted file mode 100644
index 22e0da9..0000000
--- a/frontend/src/components/steps/specifics/ProjectSpecificsStep.jsx
+++ /dev/null
@@ -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 = (
- {staticText.steps.projectSpecifics.description}}
- />
- );
-
- const projectSpecificsSelectionPanel = (
-
- );
-
- return (
-
- );
-}
diff --git a/frontend/src/components/steps/summary/SummaryContent.jsx b/frontend/src/components/steps/summary/SummaryContent.jsx
index a50d1a8..0ebf0f2 100644
--- a/frontend/src/components/steps/summary/SummaryContent.jsx
+++ b/frontend/src/components/steps/summary/SummaryContent.jsx
@@ -8,13 +8,15 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import SummaryTable from "./SummaryTable";
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 [locationDetails, setLocationDetails] = React.useState({});
+ const { filters } = useFilter();
const getLocationDetails = () => {
- LocationRepository.getLocationData(props.filters).then((result) => {
+ LocationRepository.getLocationData(filters).then((result) => {
setLocationDetails(result);
});
};
@@ -24,7 +26,6 @@ export default function SummaryContent(props) {
};
React.useEffect(() => {
- props.setNextDisabled(false);
!Object.keys(locationDetails).length && getLocationDetails();
});
@@ -35,7 +36,7 @@ export default function SummaryContent(props) {
const locationData = [
createData(
"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(
@@ -50,22 +51,22 @@ export default function SummaryContent(props) {
"Soil Order",
`${locationDetails.soil_name} (${locationDetails.soil_code})` || ""
),
- createData("Soil Variant", props.filters.soilVariant),
+ createData("Soil Variant", filters.soilVariant),
];
const siteData = [
- createData("Habitat", props.filters.habitat.name ?? ""),
+ createData("Habitat", filters.habitat.name ?? ""),
createData(
"Zone Name",
- (props.filters.zone && props.filters.zone.name) ?? ""
+ (filters.zone && filters.zone.name) ?? ""
),
createData(
"Zone Variant",
- (props.filters.zone && props.filters.zone.variant) ?? ""
+ (filters.zone && filters.zone.variant) ?? ""
),
createData(
"Zone Refined Variant",
- (props.filters.zone && props.filters.zone.refined_variant) ?? ""
+ (filters.zone && filters.zone.refined_variant) ?? ""
),
];
diff --git a/frontend/src/components/steps/summary/SummaryStep.jsx b/frontend/src/components/steps/summary/SummaryStep.jsx
index ef7aa02..835bbc8 100644
--- a/frontend/src/components/steps/summary/SummaryStep.jsx
+++ b/frontend/src/components/steps/summary/SummaryStep.jsx
@@ -3,8 +3,10 @@ import SummaryContent from "./SummaryContent";
import StepInformation from "../StepInformation";
import staticText from "../../../assets/data/staticText.json";
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 summaryContent = ;
+ const summaryContent = ;
return (
-
+ <>
+
+
+ >
);
}
diff --git a/frontend/src/components/steps/zone/ZoneSelector.jsx b/frontend/src/components/steps/zone/ZoneSelector.jsx
index b2463f0..171a762 100644
--- a/frontend/src/components/steps/zone/ZoneSelector.jsx
+++ b/frontend/src/components/steps/zone/ZoneSelector.jsx
@@ -1,11 +1,13 @@
import { useEffect, useState } from "react";
import SiteRepository from "../../../repository/SiteRepository";
+import { useFilter } from "../../providers/FilterProvider";
import { HabitatSVG } from "../HabitatSVG";
-export default function ZoneSelector(props) {
+export default function ZoneSelector({setNextDisabled}) {
const [habitatImageObject, setHabitatImageObject] = useState({});
const [segmentMapping, setSegmentMapping] = useState({});
const [selectedZoneSegment, setZoneSegment] = useState(null);
+ const { filters, updateFilters } = useFilter();
const setZoneOrRedirect = (zone) => {
const redirectHabitat = zone && zone.redirect_habitat;
@@ -15,15 +17,13 @@ export default function ZoneSelector(props) {
? { habitat: { id: redirectHabitat.id, name: redirectHabitat.name } }
: { zone: zone };
- props.updateFilterState(newFilterState);
- props.setRedirectBack(Boolean(redirectHabitat));
-
- props.setNextDisabled(false);
+ updateFilters(newFilterState);
+ setNextDisabled(false);
};
useEffect(() => {
const getHabitatImage = () => {
- SiteRepository.getHabitatImage(props.filters.habitatImage).then(
+ SiteRepository.getHabitatImage(filters.habitatImage).then(
(response) => {
if (response.status === 200) {
const imageData = response.data;
@@ -34,8 +34,8 @@ export default function ZoneSelector(props) {
};
const setInitialZone = () => {
- if (props.filters.zone) {
- const zone = props.filters.zone;
+ if (filters.zone) {
+ const zone = filters.zone;
const zoneSegment = document.querySelectorAll(
`.zone-selector-svg svg path[inkscapelabel="${zone.related_svg_segment}"]`
)[0];
@@ -45,7 +45,7 @@ export default function ZoneSelector(props) {
setZoneSegment(zoneSegment);
zoneSegment.style.fill = "#eeeeee";
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
Object.keys(segmentMapping).length === 0 && getZones();
- }, [habitatImageObject, segmentMapping, props, props.filters.zone]);
+ }, [habitatImageObject, segmentMapping, setNextDisabled, filters]);
const selectZone = (element) => {
if (
diff --git a/frontend/src/components/steps/zone/ZoneStep.jsx b/frontend/src/components/steps/zone/ZoneStep.jsx
index e4ebf3b..c870293 100644
--- a/frontend/src/components/steps/zone/ZoneStep.jsx
+++ b/frontend/src/components/steps/zone/ZoneStep.jsx
@@ -1,10 +1,20 @@
+import { useState } from 'react';
+import Button from '@mui/material/Button';
import Step from "../Step";
import ZoneSelector from "./ZoneSelector";
import StepInformation from "../StepInformation";
import staticText from "../../../assets/data/staticText.json";
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 = (
-
+
);
return (
-
+ <>
+
+
+ >
);
-}
+};
diff --git a/frontend/src/index.js b/frontend/src/index.js
index f7fe04d..ffff73c 100644
--- a/frontend/src/index.js
+++ b/frontend/src/index.js
@@ -4,6 +4,7 @@ import { createTheme, ThemeProvider } from "@mui/material/styles";
import reportWebVitals from "./reportWebVitals";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import MainPage from "./pages/MainPage";
+import { FilterProvider } from "./components/providers/FilterProvider";
// Styles
import "./assets/styles/main.scss";
@@ -33,9 +34,11 @@ const darkTheme = createTheme({
ReactDOM.render(
-
-
-
+
+
+
+
+
,
document.getElementById("root")
diff --git a/frontend/src/pages/ApplyPage.jsx b/frontend/src/pages/ApplyPage.jsx
index a4f1879..7c956b6 100644
--- a/frontend/src/pages/ApplyPage.jsx
+++ b/frontend/src/pages/ApplyPage.jsx
@@ -1,45 +1,29 @@
import { Container } from "reactstrap";
-import Stepper from "../components/Stepper";
import Header from "../components/Header";
import AddressStep from "../components/steps/address/AddressStep";
import SoilStep from "../components/steps/soilvariant/SoilStep";
import HabitatStep from "../components/steps/habitat/HabitatStep";
import ZoneStep from "../components/steps/zone/ZoneStep";
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 (
+
+
+
+
+
+
+
+
+
+
+ );
+};
export default ApplyPage;
diff --git a/frontend/src/pages/MainPage.jsx b/frontend/src/pages/MainPage.jsx
index 7828472..f56f66e 100644
--- a/frontend/src/pages/MainPage.jsx
+++ b/frontend/src/pages/MainPage.jsx
@@ -1,5 +1,4 @@
import { Container } from "reactstrap";
-import Stepper from "../components/Stepper";
import Header from "../components/Header";
import LocationStep from "../components/steps/location/LocationStep";
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 SummaryStep from "../components/steps/summary/SummaryStep";
import ResultsStep from "../components/steps/results/ResultsStep";
+import { StepperWizard } from "../components/providers/StepperProvider";
-const MainPage = () => (
-
-
-
-
-);
+const MainPage = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
export default MainPage;
diff --git a/frontend/src/repository/Repository.js b/frontend/src/repository/Repository.js
index 0bc49af..6626035 100644
--- a/frontend/src/repository/Repository.js
+++ b/frontend/src/repository/Repository.js
@@ -2,10 +2,9 @@ import axios from "axios";
// Create the axios object
const repo = axios.create({
- baseURL:
- window.location.hostname === "localhost"
- ? "http://localhost:9000/api"
- : "/api",
+ baseURL: "/api",
+ xsrfHeaderName: "X-CSRFToken",
+ xsrfCookieName: "csrftoken",
});
repo.defaults.headers.post["access-control-allow-origin"] = "*";