[#41] Allow users to download the user/planing guide for a payment - frontend #93

Merged
mattn merged 1 commit from matt/41-frontend into main 2023-03-09 17:01:12 +13:00
5 changed files with 147 additions and 21 deletions

View file

@ -1,13 +1,17 @@
{ {
"steps": { "steps": {
"address": { "key": {
"title": "Right Plant Right Place Right Time\nPlant Selector Tool for New Zealand.", "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": { "location": {
"title": "Right Plant Right Place Right Time\nPlant Selector Tool for New Zealand.", "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." "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": { "soil": {
"title": "Soil Variant Selection", "title": "Soil Variant Selection",
"description": "", "description": "",

View file

@ -10,13 +10,15 @@ const FilterProvider = ({children}) => {
const updateFilters = newFilters => setFilters(oldFilters => ({...oldFilters, ...newFilters})); const updateFilters = newFilters => setFilters(oldFilters => ({...oldFilters, ...newFilters}));
const submit = async () => { const submit = () => Repository.post(
return await Repository.post("/questionnaire/", { "/questionnaire/",
{
location: `SRID=4326;POINT (${filters.coordinates.lng} ${filters.coordinates.lat})`, location: `SRID=4326;POINT (${filters.coordinates.lng} ${filters.coordinates.lat})`,
soil_variant: filters.soilVariant, soil_variant: filters.soilVariant,
zone: filters.zone.id, zone: filters.zone.id,
}); key: filters.key,
}; },
);
const value = { const value = {
filters, filters,

View file

@ -44,7 +44,7 @@ const StepperWizard = ({children}) => {
const useStepper = () => useContext(StepContext); 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 { step, isStep, setStepNext, setStepBack, setStep } = useStepper();
const { resetFilters } = useFilter(); const { resetFilters } = useFilter();
const isSubmit = !isStep(step + 2); const isSubmit = !isStep(step + 2);
@ -62,8 +62,13 @@ const StepperFooter = ({nextDisabled, backDisabled, onBack = null, onNext = null
setStepNext(); setStepNext();
}; };
const _onSubmit = () => { const _onSubmit = async () => {
onSubmit(); try {
await onSubmit();
} catch {
return;
}
if (onNext) { if (onNext) {
onNext(); onNext();
} else { } else {

View 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;

View file

@ -1,29 +1,67 @@
import { useState } from 'react';
import { Container } from "reactstrap"; import { Container } from "reactstrap";
import Header from "../components/Header"; import Header from "../components/Header";
import ActivationStep from "../components/steps/activation/ActivationStep";
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 CompleteStep from "../components/steps/complete/CompleteStep";
import { StepperWizard } from "../components/providers/StepperProvider";
import { useFilter } from "../components/providers/FilterProvider"; import { useFilter } from "../components/providers/FilterProvider";
import { Box, Typography, Modal, Button } from '@mui/material';
const ApplyPage = () => { const ApplyPage = () => {
const [error, setError] = useState("");
const { submit } = useFilter(); 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 ( return (
<Container fluid className="main-container p-0"> <>
<Header /> <Container fluid className="main-container p-0">
<StepperWizard> <Header />
<AddressStep label="Enter address" tooltip="Enter your address" /> <StepperWizard>
<SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" /> <ActivationStep label="Activate" tooltip="Enter your activation key" />
<HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" /> <AddressStep label="Enter address" tooltip="Enter your address" />
<ZoneStep label="Select zone" tooltip="Specify geographical detail" /> <SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" />
<SummaryStep label="Summary" tooltip="Check your inputs" onSubmit={submit} /> <HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" />
<CompleteStep label="Complete" tooltip="Complete your application" /> <ZoneStep label="Select zone" tooltip="Specify geographical detail" />
</StepperWizard> <SummaryStep label="Summary" tooltip="Check your inputs" onSubmit={onSubmit} />
</Container>); <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; export default ApplyPage;