diff --git a/frontend/src/assets/data/staticText.json b/frontend/src/assets/data/staticText.json index e4fcf7b..0ea6551 100644 --- a/frontend/src/assets/data/staticText.json +++ b/frontend/src/assets/data/staticText.json @@ -1,13 +1,17 @@ { "steps": { - "address": { + "key": { "title": "Right Plant Right Place Right Time\nPlant Selector Tool for New Zealand.", - "description": "Your native plant selection starts here! Register by entering your address. On the following pages you will provide more details on your project until the system has enough information to create your plant species list and planting plan. To start, click on the map and pan and zoom to the site location. Once the location is selected, click on the “next step” button to complete the process. Repeat this process for sites at different locations." + "description": "Your native plant selection starts here! An activation key is required to proceed to the next step. You can choose to supply your own or purchase a key from our online payment portal." }, "location": { "title": "Right Plant Right Place Right Time\nPlant Selector Tool for New Zealand.", "description": "Your native plant selection starts here! Use the map to select a planting site location within New Zealand. On the following pages you will provide more details on your project until the system has enough information to create your plant species list and planting plan. To start, click on the map and pan and zoom to the site location. Once the location is selected, click on the “next step” button to complete the process. Repeat this process for sites at different locations." }, + "address": { + "title": "Address", + "description": "Thank you for purchasing an activation key. Please start entering your address and select an option from the suggestions provided. On the following pages, you will provide more details on your project until the system has enough information to create your plant species list and planting plan. Once the location is selected, click on the “next step” button to complete the process." + }, "soil": { "title": "Soil Variant Selection", "description": "", diff --git a/frontend/src/components/providers/FilterProvider.jsx b/frontend/src/components/providers/FilterProvider.jsx index 755b0d6..1fe2604 100644 --- a/frontend/src/components/providers/FilterProvider.jsx +++ b/frontend/src/components/providers/FilterProvider.jsx @@ -10,13 +10,15 @@ const FilterProvider = ({children}) => { const updateFilters = newFilters => setFilters(oldFilters => ({...oldFilters, ...newFilters})); - const submit = async () => { - return await Repository.post("/questionnaire/", { + const submit = () => Repository.post( + "/questionnaire/", + { location: `SRID=4326;POINT (${filters.coordinates.lng} ${filters.coordinates.lat})`, soil_variant: filters.soilVariant, zone: filters.zone.id, - }); - }; + key: filters.key, + }, + ); const value = { filters, diff --git a/frontend/src/components/providers/StepperProvider.jsx b/frontend/src/components/providers/StepperProvider.jsx index 8cb4e35..b99e92a 100644 --- a/frontend/src/components/providers/StepperProvider.jsx +++ b/frontend/src/components/providers/StepperProvider.jsx @@ -44,7 +44,7 @@ const StepperWizard = ({children}) => { const useStepper = () => useContext(StepContext); -const StepperFooter = ({nextDisabled, backDisabled, onBack = null, onNext = null, onSubmit = () => {}}) => { +const StepperFooter = ({nextDisabled, backDisabled, onBack = null, onNext = null, onSubmit = async () => {}}) => { const { step, isStep, setStepNext, setStepBack, setStep } = useStepper(); const { resetFilters } = useFilter(); const isSubmit = !isStep(step + 2); @@ -62,8 +62,13 @@ const StepperFooter = ({nextDisabled, backDisabled, onBack = null, onNext = null setStepNext(); }; - const _onSubmit = () => { - onSubmit(); + const _onSubmit = async () => { + try { + await onSubmit(); + } catch { + return; + } + if (onNext) { onNext(); } else { diff --git a/frontend/src/components/steps/activation/ActivationStep.jsx b/frontend/src/components/steps/activation/ActivationStep.jsx new file mode 100644 index 0000000..1bbee8d --- /dev/null +++ b/frontend/src/components/steps/activation/ActivationStep.jsx @@ -0,0 +1,77 @@ +import { useState } from 'react'; +import Step from '../Step'; +import StepInformation from '../StepInformation'; +import staticText from '../../../assets/data/staticText.json' +import keyBackgroundImage from '../../../assets/img/stepBackgrounds/step6.jpg'; +import { StepperFooter, useStepper } from '../../providers/StepperProvider'; +import { useFilter } from '../../providers/FilterProvider'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import Repository from '../../../repository/Repository'; + +const ActivationStep = () => { + const MAX_LENGTH = 20; + const [value, setValue] = useState(new URLSearchParams(window.location.search).get("key") || ""); + const [nextDisabled, setNextDisabled] = useState(value.length < MAX_LENGTH); + const [error, setError] = useState(""); + const { updateFilters } = useFilter(); + const { setStepNext } = useStepper(); + + const onChange = e => { + const newValue = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, MAX_LENGTH); + setNextDisabled(newValue.length !== MAX_LENGTH); + setValue(newValue); + setError(""); + }; + + const onNext = () => { + const data = { key: value }; + Repository.post("/key/validate/", data).then(resp => { + updateFilters(data); + setStepNext(); + }).catch(e => { + setError( + e.response.status === 404 + ? "Invalid or expired activation key. Please try again." + : "Something went wrong. Please try again." + ); + }); + }; + + const keyPanel = ( +
+ {staticText.steps.key.description}

} + /> +
+ 0} + helperText={error} + onChange={onChange} + value={value} + /> + + + + +
+
+ ); + + return ( + <> + + + ); +}; + +export default ActivationStep; diff --git a/frontend/src/pages/ApplyPage.jsx b/frontend/src/pages/ApplyPage.jsx index 7c956b6..c41020e 100644 --- a/frontend/src/pages/ApplyPage.jsx +++ b/frontend/src/pages/ApplyPage.jsx @@ -1,29 +1,67 @@ +import { useState } from 'react'; import { Container } from "reactstrap"; import Header from "../components/Header"; +import ActivationStep from "../components/steps/activation/ActivationStep"; 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 { StepperWizard } from "../components/providers/StepperProvider"; import { useFilter } from "../components/providers/FilterProvider"; +import { Box, Typography, Modal, Button } from '@mui/material'; + const ApplyPage = () => { + const [error, setError] = useState(""); const { submit } = useFilter(); + const onSubmit = async () => { + try { + await submit(); + } catch (e) { + setError("There was a problem sending data to the API. Please try again."); + throw e; + } + } + return ( - -
- - - - - - - - - ); + <> + +
+ + + + + + + + + + + 0} onClose={() => setError("")}> + + Error + {error} + + + + + + + ); }; export default ApplyPage;