[#41] Allow users to download the user/planing guide for a payment - frontend #93
5 changed files with 147 additions and 21 deletions
|
@ -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": "",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
77
frontend/src/components/steps/activation/ActivationStep.jsx
Normal file
77
frontend/src/components/steps/activation/ActivationStep.jsx
Normal file
|
@ -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 = (
|
||||
<div className="p-5">
|
||||
<StepInformation
|
||||
title={staticText.steps.key.title}
|
||||
description={<p>{staticText.steps.key.description}</p>}
|
||||
/>
|
||||
<div className="p-4">
|
||||
<TextField
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
placeholder="Enter activation key..."
|
||||
autoComplete="off"
|
||||
error={error.length > 0}
|
||||
helperText={error}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
/>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'row', py: 2, paddingRight: '10pt', paddingLeft: '10pt', minHeight: '68px' }}>
|
||||
<Box sx={{ flex: '1 1 auto' }} />
|
||||
<Button href="/api/key/purchase">Purchase Key</Button>
|
||||
</Box>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Step
|
||||
contentComponent={keyPanel}
|
||||
backgroundImage={keyBackgroundImage}
|
||||
/>
|
||||
<StepperFooter nextDisabled={nextDisabled} onNext={onNext} />
|
||||
</>);
|
||||
};
|
||||
|
||||
export default ActivationStep;
|
|
@ -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 (
|
||||
<Container fluid className="main-container p-0">
|
||||
<Header />
|
||||
<StepperWizard>
|
||||
<AddressStep label="Enter address" tooltip="Enter your address" />
|
||||
<SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" />
|
||||
<HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" />
|
||||
<ZoneStep label="Select zone" tooltip="Specify geographical detail" />
|
||||
<SummaryStep label="Summary" tooltip="Check your inputs" onSubmit={submit} />
|
||||
<CompleteStep label="Complete" tooltip="Complete your application" />
|
||||
</StepperWizard>
|
||||
</Container>);
|
||||
<>
|
||||
<Container fluid className="main-container p-0">
|
||||
<Header />
|
||||
<StepperWizard>
|
||||
<ActivationStep label="Activate" tooltip="Enter your activation key" />
|
||||
<AddressStep label="Enter address" tooltip="Enter your address" />
|
||||
<SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" />
|
||||
<HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" />
|
||||
<ZoneStep label="Select zone" tooltip="Specify geographical detail" />
|
||||
<SummaryStep label="Summary" tooltip="Check your inputs" onSubmit={onSubmit} />
|
||||
<CompleteStep label="Complete" tooltip="Complete your application" />
|
||||
</StepperWizard>
|
||||
</Container>
|
||||
<Modal open={error.length > 0} onClose={() => setError("")}>
|
||||
<Box sx={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: 400,
|
||||
bgcolor: 'background.paper',
|
||||
border: '2px solid #000',
|
||||
boxShadow: 24,
|
||||
color: 'white',
|
||||
p: 4,
|
||||
}}>
|
||||
<Typography variant="h4" component="h2">Error</Typography>
|
||||
<Typography sx={{ mt: 2 }}>{error}</Typography>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<Box sx={{ flex: '1 1 auto' }} />
|
||||
<Button onClick={() => setError("")}>Close</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
</>);
|
||||
};
|
||||
|
||||
export default ApplyPage;
|
||||
|
|
Loading…
Reference in a new issue