[#41] Allow users to download the user/plang guide for a payment
- frontend changes to support physical and digital checkouts
This commit is contained in:
parent
a7d7581c1b
commit
d39e7da6f1
18 changed files with 381 additions and 327 deletions
|
@ -6,11 +6,7 @@
|
||||||
},
|
},
|
||||||
"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 or enter an address 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",
|
||||||
|
@ -39,10 +35,6 @@
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
68
frontend/src/components/providers/ActivationProvider.jsx
Normal file
68
frontend/src/components/providers/ActivationProvider.jsx
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { createContext, useState, useContext } from 'react';
|
||||||
|
import Repository from '../../repository/Repository';
|
||||||
|
import { useError } from './ErrorProvider';
|
||||||
|
|
||||||
|
const ActivationContext = createContext(null);
|
||||||
|
|
||||||
|
const ActivationProvider = ({children}) => {
|
||||||
|
const [key, setKey] = useState("");
|
||||||
|
const [isPhysicalKey, setIsPhysicalKey] = useState(false);
|
||||||
|
const { setError, resetError } = useError();
|
||||||
|
|
||||||
|
const validateKey = (value) => new Promise(resolve => {
|
||||||
|
|
||||||
|
const data = {key: value};
|
||||||
|
|
||||||
|
setKey(value);
|
||||||
|
|
||||||
|
Repository.post("/key/validate/", data).then(resp => {
|
||||||
|
if (resp.data) {
|
||||||
|
setIsPhysicalKey(resp.data?.type === "Stripe - physical");
|
||||||
|
resetError();
|
||||||
|
try {
|
||||||
|
const coordinates = resp.data.location.match(/(-?\d+\.\d+)\s(-?\d+\.\d+)/);
|
||||||
|
resolve({
|
||||||
|
coordinates: {
|
||||||
|
lng: parseFloat(coordinates[1]),
|
||||||
|
lat: parseFloat(coordinates[2]),
|
||||||
|
},
|
||||||
|
soilVariant: resp.data.soil_variant[0],
|
||||||
|
zone: {id: resp.data.zone},
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
resolve({...data, ...resp.data});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
switch (e.response.status) {
|
||||||
|
case 400:
|
||||||
|
case 404:
|
||||||
|
setError("Invalid or expired activation key. Please try again.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setError("Something went wrong. Please try again.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
key,
|
||||||
|
isDigitalKey: !isPhysicalKey,
|
||||||
|
isPhysicalKey,
|
||||||
|
validateKey,
|
||||||
|
};
|
||||||
|
|
||||||
|
return <ActivationContext.Provider value={value}>{children}</ActivationContext.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useActivator = () => useContext(ActivationContext);
|
||||||
|
|
||||||
|
export {
|
||||||
|
ActivationProvider,
|
||||||
|
useActivator,
|
||||||
|
};
|
24
frontend/src/components/providers/ErrorProvider.jsx
Normal file
24
frontend/src/components/providers/ErrorProvider.jsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { createContext, useState, useContext } from 'react';
|
||||||
|
|
||||||
|
const ErrorContext = createContext(null);
|
||||||
|
|
||||||
|
const ErrorProvider = ({children}) => {
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
const resetError = () => setError("");
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
error,
|
||||||
|
setError,
|
||||||
|
resetError,
|
||||||
|
};
|
||||||
|
|
||||||
|
return <ErrorContext.Provider value={value}>{children}</ErrorContext.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useError = () => useContext(ErrorContext);
|
||||||
|
|
||||||
|
export {
|
||||||
|
ErrorProvider,
|
||||||
|
useError,
|
||||||
|
};
|
|
@ -15,12 +15,14 @@ const StepperWizard = ({children}) => {
|
||||||
const isStep = n => (0 <= n && n < children.length);
|
const isStep = n => (0 <= n && n < children.length);
|
||||||
const setStepNext = () => setStep(n => isStep(n + 1) ? n + 1 : n);
|
const setStepNext = () => setStep(n => isStep(n + 1) ? n + 1 : n);
|
||||||
const setStepBack = () => setStep(n => isStep(n - 1) ? n - 1 : n);
|
const setStepBack = () => setStep(n => isStep(n - 1) ? n - 1 : n);
|
||||||
|
const setStepLast = () => setStep(children.length - 1);
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
step,
|
step,
|
||||||
setStep,
|
setStep,
|
||||||
setStepNext,
|
setStepNext,
|
||||||
setStepBack,
|
setStepBack,
|
||||||
|
setStepLast,
|
||||||
isStep,
|
isStep,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,39 +4,36 @@ import StepInformation from '../StepInformation';
|
||||||
import staticText from '../../../assets/data/staticText.json'
|
import staticText from '../../../assets/data/staticText.json'
|
||||||
import keyBackgroundImage from '../../../assets/img/stepBackgrounds/step6.jpg';
|
import keyBackgroundImage from '../../../assets/img/stepBackgrounds/step6.jpg';
|
||||||
import { StepperFooter, useStepper } from '../../providers/StepperProvider';
|
import { StepperFooter, useStepper } from '../../providers/StepperProvider';
|
||||||
|
import { useActivator } from '../../providers/ActivationProvider';
|
||||||
import { useFilter } from '../../providers/FilterProvider';
|
import { useFilter } from '../../providers/FilterProvider';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import TextField from '@mui/material/TextField';
|
import TextField from '@mui/material/TextField';
|
||||||
import Repository from '../../../repository/Repository';
|
import PurchaseButton from './PurchaseButton';
|
||||||
|
|
||||||
const ActivationStep = () => {
|
const ActivationStep = () => {
|
||||||
const MAX_LENGTH = 20;
|
const MAX_LENGTH = 20;
|
||||||
const [value, setValue] = useState(new URLSearchParams(window.location.search).get("key") || "");
|
const [value, setValue] = useState(new URLSearchParams(window.location.search).get("key") || "");
|
||||||
const [nextDisabled, setNextDisabled] = useState(value.length < MAX_LENGTH);
|
const [nextDisabled, setNextDisabled] = useState(value.length < MAX_LENGTH);
|
||||||
const [error, setError] = useState("");
|
const { setFilters, updateFilters } = useFilter();
|
||||||
const { updateFilters } = useFilter();
|
const { setStepNext, setStepLast } = useStepper();
|
||||||
const { setStepNext } = useStepper();
|
const { validateKey } = useActivator();
|
||||||
|
|
||||||
const onChange = e => {
|
const onChange = e => {
|
||||||
const newValue = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, MAX_LENGTH);
|
const newValue = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, MAX_LENGTH);
|
||||||
setNextDisabled(newValue.length !== MAX_LENGTH);
|
setNextDisabled(newValue.length !== MAX_LENGTH);
|
||||||
setValue(newValue);
|
setValue(newValue);
|
||||||
setError("");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onNext = () => {
|
const onNext = async () => {
|
||||||
const data = { key: value };
|
const data = await validateKey(value);
|
||||||
Repository.post("/key/validate/", data).then(resp => {
|
|
||||||
|
if (data?.coordinates) {
|
||||||
|
setFilters(data);
|
||||||
|
setStepLast();
|
||||||
|
} else if (data) {
|
||||||
updateFilters(data);
|
updateFilters(data);
|
||||||
setStepNext();
|
setStepNext();
|
||||||
}).catch(e => {
|
}
|
||||||
setError(
|
|
||||||
e.response.status === 404
|
|
||||||
? "Invalid or expired activation key. Please try again."
|
|
||||||
: "Something went wrong. Please try again."
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const keyPanel = (
|
const keyPanel = (
|
||||||
|
@ -51,14 +48,12 @@ const ActivationStep = () => {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="Enter activation key..."
|
placeholder="Enter activation key..."
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
error={error.length > 0}
|
|
||||||
helperText={error}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'row', py: 2, paddingRight: '10pt', paddingLeft: '10pt', minHeight: '68px' }}>
|
<Box sx={{ display: 'flex', flexDirection: 'row', py: 2, paddingRight: '10pt', paddingLeft: '10pt', minHeight: '68px' }}>
|
||||||
<Box sx={{ flex: '1 1 auto' }} />
|
<Box sx={{ flex: '1 1 auto' }} />
|
||||||
<Button href="/api/key/purchase">Purchase Key</Button>
|
<PurchaseButton />
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
44
frontend/src/components/steps/activation/PurchaseButton.jsx
Normal file
44
frontend/src/components/steps/activation/PurchaseButton.jsx
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
|
import Menu from '@mui/material/Menu';
|
||||||
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
|
|
||||||
|
const PurchaseButton = () => {
|
||||||
|
const [anchor, setAnchor] = useState(null);
|
||||||
|
const isOpen = Boolean(anchor);
|
||||||
|
|
||||||
|
const toggleMenu = (e) => {
|
||||||
|
setAnchor(isOpen ? null : e.currentTarget);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelect = (href) => {
|
||||||
|
setAnchor(null);
|
||||||
|
window.location = href;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
id="purchase-button"
|
||||||
|
aria-controls={isOpen ? "basic-menu" : undefined}
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded={isOpen ? "true" : undefined}
|
||||||
|
onClick={toggleMenu}
|
||||||
|
>
|
||||||
|
Purchase Key
|
||||||
|
</Button>
|
||||||
|
<Menu
|
||||||
|
id="purchase-menu"
|
||||||
|
anchorEl={anchor}
|
||||||
|
open={isOpen}
|
||||||
|
onClose={() => toggleMenu(null)}
|
||||||
|
MenuListProps={{"aria-labelledby": "purchase-button"}}
|
||||||
|
>
|
||||||
|
<MenuItem onClick={() => onSelect("/api/key/purchase")}>Purchase digital copy</MenuItem>
|
||||||
|
<MenuItem onClick={() => onSelect("/api/key/purchase?physical=true")}>Purchase physical copy</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PurchaseButton;
|
|
@ -1,49 +0,0 @@
|
||||||
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 = () => {
|
|
||||||
const [nextDisabled, setNextDisabled] = useState(true);
|
|
||||||
const { updateFilters } = useFilter();
|
|
||||||
|
|
||||||
const addressPanel = (
|
|
||||||
<div className="p-5">
|
|
||||||
<StepInformation
|
|
||||||
title={staticText.steps.address.title}
|
|
||||||
description={<p>{staticText.steps.address.description}</p>}
|
|
||||||
/>
|
|
||||||
<div className="p-4">
|
|
||||||
<AddressSearch onSelect={address => {
|
|
||||||
if (address) {
|
|
||||||
setNextDisabled(false);
|
|
||||||
updateFilters({
|
|
||||||
coordinates: {
|
|
||||||
lat: address.coordinates[1],
|
|
||||||
lng: address.coordinates[0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setNextDisabled(true);
|
|
||||||
}
|
|
||||||
}}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Step
|
|
||||||
contentComponent={addressPanel}
|
|
||||||
backgroundImage={addressBackgroundImage}
|
|
||||||
/>
|
|
||||||
<StepperFooter nextDisabled={nextDisabled} />
|
|
||||||
</>);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddressStep;
|
|
|
@ -1,24 +0,0 @@
|
||||||
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 />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -25,7 +25,7 @@ const AddressSearchSuggestions = ({results, onClick}) => (
|
||||||
</Box>
|
</Box>
|
||||||
: null);
|
: null);
|
||||||
|
|
||||||
const AddressSearch = ({onSelect, classNames}) => {
|
const AddressSearch = ({onSelect}) => {
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
const [enable, setEnable] = useState(true);
|
const [enable, setEnable] = useState(true);
|
||||||
const [selected, setSelected] = useState(null);
|
const [selected, setSelected] = useState(null);
|
||||||
|
@ -53,7 +53,7 @@ const AddressSearch = ({onSelect, classNames}) => {
|
||||||
}, [selected, onSelect]);
|
}, [selected, onSelect]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div classNames={classNames}>
|
<Box sx={{width: '100%', height: '20%'}}>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
@ -74,6 +74,7 @@ const AddressSearch = ({onSelect, classNames}) => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
value={value}
|
value={value}
|
||||||
|
sx={{top: 0}}
|
||||||
/>
|
/>
|
||||||
<AddressSearchSuggestions
|
<AddressSearchSuggestions
|
||||||
results={results}
|
results={results}
|
||||||
|
@ -83,7 +84,7 @@ const AddressSearch = ({onSelect, classNames}) => {
|
||||||
setSelected(r);
|
setSelected(r);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>);
|
</Box>);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AddressSearch;
|
export default AddressSearch;
|
|
@ -1,31 +1,57 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
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';
|
import { StepperFooter } from '../../providers/StepperProvider';
|
||||||
|
import AddressSearch from "./AddressSearch";
|
||||||
|
import { useFilter } from '../../providers/FilterProvider';
|
||||||
|
|
||||||
export default function LocationStep(props) {
|
export default function LocationStep({defaultIsSearch = false}) {
|
||||||
const [nextDisabled, setNextDisabled] = useState(true);
|
const [nextDisabled, setNextDisabled] = useState(true);
|
||||||
|
const [showSearch, setShowSearch] = useState(defaultIsSearch);
|
||||||
|
const { updateFilters } = useFilter();
|
||||||
|
|
||||||
const locationInfoPanel = (
|
const locationInfoPanel = (
|
||||||
|
<div>
|
||||||
<StepInformation
|
<StepInformation
|
||||||
title={staticText.steps.location.title}
|
title={staticText.steps.location.title}
|
||||||
description={<p>{staticText.steps.location.description}</p>}
|
description={<p>{staticText.steps.location.description}</p>}
|
||||||
/>
|
/>
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'row', py: 2, paddingRight: '10pt', paddingLeft: '10pt', minHeight: '68px' }}>
|
||||||
|
<Box sx={{ flex: '1 1 auto' }} />
|
||||||
|
<Button onClick={() => setShowSearch(s => !s)}>Switch to {showSearch ? "map" : "search"}</Button>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const locationSelectionPanel = <LocationSelectorMap setNextDisabled={setNextDisabled} />;
|
const selectionComponent = showSearch
|
||||||
|
? <AddressSearch onSelect={address => {
|
||||||
|
if (address) {
|
||||||
|
setNextDisabled(false);
|
||||||
|
updateFilters({
|
||||||
|
coordinates: {
|
||||||
|
lat: address.coordinates[1],
|
||||||
|
lng: address.coordinates[0],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setNextDisabled(true);
|
||||||
|
}
|
||||||
|
}}/>
|
||||||
|
: <LocationSelectorMap setNextDisabled={setNextDisabled} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Step
|
<Step
|
||||||
informationComponent={locationInfoPanel}
|
informationComponent={locationInfoPanel}
|
||||||
selectionComponent={locationSelectionPanel}
|
selectionComponent={selectionComponent}
|
||||||
backgroundImage={locationBackgroundImage}
|
backgroundImage={locationBackgroundImage}
|
||||||
/>
|
/>
|
||||||
<StepperFooter nextDisabled={nextDisabled} />
|
<StepperFooter nextDisabled={nextDisabled} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
|
@ -23,9 +23,8 @@ import staticText from "../../../assets/data/staticText.json";
|
||||||
import forestGraphic from "../../../assets/img/habitats/1a_Forest_Section.png";
|
import forestGraphic from "../../../assets/img/habitats/1a_Forest_Section.png";
|
||||||
import { CircularProgress } from "@mui/material";
|
import { CircularProgress } from "@mui/material";
|
||||||
|
|
||||||
function TablePaginationActions(props) {
|
function TablePaginationActions({ count, page, rowsPerPage, onPageChange }) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { count, page, rowsPerPage, onPageChange } = props;
|
|
||||||
|
|
||||||
const handleFirstPageButtonClick = (event) => {
|
const handleFirstPageButtonClick = (event) => {
|
||||||
onPageChange(event, 0);
|
onPageChange(event, 0);
|
||||||
|
@ -95,18 +94,21 @@ TablePaginationActions.propTypes = {
|
||||||
export default function PlantResultsTable(props) {
|
export default function PlantResultsTable(props) {
|
||||||
const [page, setPage] = React.useState(0);
|
const [page, setPage] = React.useState(0);
|
||||||
const [rowsPerPage, setRowsPerPage] = React.useState(25);
|
const [rowsPerPage, setRowsPerPage] = React.useState(25);
|
||||||
|
const isLoading = props?.rows === null;
|
||||||
|
|
||||||
let rows = [];
|
let rows = [];
|
||||||
if (props.rows) {
|
if (!isLoading) {
|
||||||
rows =
|
rows =
|
||||||
rowsPerPage > 0
|
rowsPerPage > 0
|
||||||
? props.rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
? props.rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||||
: props.rows;
|
: props.rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const totalRows = props?.rows?.length ?? 0;
|
||||||
|
|
||||||
// Avoid a layout jump when reaching the last page with empty rows.
|
// Avoid a layout jump when reaching the last page with empty rows.
|
||||||
const emptyRows =
|
const emptyRows =
|
||||||
page > 0 ? Math.max(0, (1 + page) * rowsPerPage - props.rows.length) : 0;
|
page > 0 ? Math.max(0, (1 + page) * rowsPerPage - totalRows) : 0;
|
||||||
|
|
||||||
const handleChangePage = (event, newPage) => {
|
const handleChangePage = (event, newPage) => {
|
||||||
setPage(newPage);
|
setPage(newPage);
|
||||||
|
@ -157,17 +159,15 @@ export default function PlantResultsTable(props) {
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{rows.length === 0 && (
|
{isLoading
|
||||||
<TableRow style={{ height: 150 }}>
|
? <TableRow style={{ height: 150 }}>
|
||||||
<TableCell colSpan={7}>
|
<TableCell colSpan={7}>
|
||||||
<Stack alignItems="center">
|
<Stack alignItems="center">
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
</Stack>
|
</Stack>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)}
|
: rows.map((row) => (
|
||||||
{rows.length > 0 &&
|
|
||||||
rows.map((row) => (
|
|
||||||
<TableRow key={row.name}>
|
<TableRow key={row.name}>
|
||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
{row.name}
|
{row.name}
|
||||||
|
@ -179,8 +179,8 @@ export default function PlantResultsTable(props) {
|
||||||
<TableCell align="right">{row.carbonSequestration}</TableCell>
|
<TableCell align="right">{row.carbonSequestration}</TableCell>
|
||||||
<TableCell align="right">{row.plantingStage}</TableCell>
|
<TableCell align="right">{row.plantingStage}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))
|
||||||
|
}
|
||||||
{emptyRows > 0 && (
|
{emptyRows > 0 && (
|
||||||
<TableRow style={{ height: 53 * emptyRows }}>
|
<TableRow style={{ height: 53 * emptyRows }}>
|
||||||
<TableCell colSpan={7} />
|
<TableCell colSpan={7} />
|
||||||
|
@ -193,7 +193,7 @@ export default function PlantResultsTable(props) {
|
||||||
className="plant-list-pagination"
|
className="plant-list-pagination"
|
||||||
rowsPerPageOptions={[5, 10, 25, { label: "All", value: -1 }]}
|
rowsPerPageOptions={[5, 10, 25, { label: "All", value: -1 }]}
|
||||||
colSpan={7}
|
colSpan={7}
|
||||||
count={props.rows.length}
|
count={totalRows}
|
||||||
rowsPerPage={rowsPerPage}
|
rowsPerPage={rowsPerPage}
|
||||||
page={page}
|
page={page}
|
||||||
SelectProps={{
|
SelectProps={{
|
||||||
|
|
|
@ -5,10 +5,10 @@ import PlantList from "./PlantList";
|
||||||
import Stack from "@mui/material/Stack";
|
import Stack from "@mui/material/Stack";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import PlantRepository from "../../../repository/PlantRepository";
|
import PlantRepository from "../../../repository/PlantRepository";
|
||||||
import { Typography, Box } from "@mui/material";
|
import { Typography, Box, Modal } 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 { useActivator } from "../../providers/ActivationProvider";
|
||||||
import { StepperFooter } from "../../providers/StepperProvider";
|
import { StepperFooter } from "../../providers/StepperProvider";
|
||||||
|
|
||||||
const RESULTS_DESCRIPTION = (
|
const RESULTS_DESCRIPTION = (
|
||||||
|
@ -30,56 +30,32 @@ const RESULTS_DESCRIPTION = (
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function ResultsStep(props) {
|
export default function ResultsStep(props) {
|
||||||
const [plants, setPlants] = useState([]);
|
const [plants, setPlants] = useState(null);
|
||||||
const { filters } = useFilter();
|
const [showModal, setShowModal] = useState(true);
|
||||||
|
const { key } = useActivator();
|
||||||
|
|
||||||
|
const closeModal = () => setShowModal(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const updatePlants = () => {
|
PlantRepository.getFilteredPlants(key)
|
||||||
PlantRepository.getFilteredPlants(filters)
|
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status === 200) {
|
setPlants(response.status === 200 ? response.data : []);
|
||||||
setPlants(response.data);
|
}).catch(e => {
|
||||||
}
|
setPlants([]);
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
this.setState({ plants: ["No plants found."] });
|
|
||||||
});
|
});
|
||||||
};
|
}, [key]);
|
||||||
updatePlants();
|
|
||||||
}, [filters]);
|
|
||||||
|
|
||||||
function createData(
|
|
||||||
name,
|
|
||||||
growthForm,
|
|
||||||
moisturePreferences,
|
|
||||||
plantTolerances,
|
|
||||||
ecosystemServices,
|
|
||||||
carbonSequestration,
|
|
||||||
plantingStage
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
growthForm,
|
|
||||||
moisturePreferences,
|
|
||||||
plantTolerances,
|
|
||||||
ecosystemServices,
|
|
||||||
carbonSequestration,
|
|
||||||
plantingStage,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const getTableRows = () => {
|
const getTableRows = () => {
|
||||||
return plants.map((plant) => {
|
// null if unloaded, empty if loaded but no results
|
||||||
return createData(
|
return plants?.map((plant) => ({
|
||||||
plant.display_name,
|
name: plant.display_name,
|
||||||
plant.display_growth_form,
|
growthForm: plant.display_growth_form,
|
||||||
plant.moisture_preferences,
|
moisturePreferences: plant.moisture_preferences,
|
||||||
plant.plant_tolerances,
|
plantTolerances: plant.plant_tolerances,
|
||||||
plant.ecosystem_services,
|
ecosystemServices: plant.ecosystem_services,
|
||||||
plant.carbon_sequestration,
|
carbonSequestration: plant.carbon_sequestration,
|
||||||
plant.stage
|
stage: plant.stage,
|
||||||
);
|
})) ?? null;
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const download = (response, fileType, fileName) => {
|
const download = (response, fileType, fileName) => {
|
||||||
|
@ -94,13 +70,13 @@ export default function ResultsStep(props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadCSV = () => {
|
const downloadCSV = () => {
|
||||||
PlantRepository.getPlantsCSV(filters).then((response) => {
|
PlantRepository.getPlantsCSV(key).then((response) => {
|
||||||
download(response, "text/csv", "plants.csv");
|
download(response, "text/csv", "plants.csv");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadPDF = () => {
|
const downloadPDF = () => {
|
||||||
PlantRepository.getPlantsPDF(filters).then((response) => {
|
PlantRepository.getPlantsPDF(key).then((response) => {
|
||||||
download(response, "application/pdf", "planting_guide.pdf");
|
download(response, "application/pdf", "planting_guide.pdf");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -142,6 +118,28 @@ export default function ResultsStep(props) {
|
||||||
backgroundImage={resultsBackgroundImage}
|
backgroundImage={resultsBackgroundImage}
|
||||||
/>
|
/>
|
||||||
<StepperFooter />
|
<StepperFooter />
|
||||||
|
<Modal open={showModal} onClose={closeModal}>
|
||||||
|
<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="h5" component="h2">Questionnaire Complete</Typography>
|
||||||
|
<Typography sx={{ mt: 2 }}>You have completed the questionnaire for your chosen habitat. If you have purchased a physical copy of the planting guide, it should arrive at your chosen delivery address in a number of business days.</Typography>
|
||||||
|
<Typography sx={{ mt: 2 }}>You may now dismiss this popup to view a table of results. You are able to access this page at any time in future by supplying the activation key used at the start of this questionnaire.</Typography>
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Box sx={{ flex: '1 1 auto' }} />
|
||||||
|
<Button onClick={closeModal}>Close</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,45 +29,53 @@ export default function SummaryContent() {
|
||||||
!Object.keys(locationDetails).length && getLocationDetails();
|
!Object.keys(locationDetails).length && getLocationDetails();
|
||||||
});
|
});
|
||||||
|
|
||||||
function createData(name, value) {
|
|
||||||
return { name, value };
|
|
||||||
}
|
|
||||||
|
|
||||||
const locationData = [
|
const locationData = [
|
||||||
createData(
|
{
|
||||||
"Geographical Coordinates (latitude, longitude)",
|
name: "Geographical Coordinates (latitude, longitude)",
|
||||||
`(${filters.coordinates.lat}, ${filters.coordinates.lng})`
|
value: `(${filters.coordinates.lat}, ${filters.coordinates.lng})`,
|
||||||
),
|
},
|
||||||
createData("Ecological Region", locationDetails.ecological_region || ""),
|
{
|
||||||
createData(
|
name: "Ecological Region",
|
||||||
"Ecological District",
|
value: locationDetails.ecological_region || "",
|
||||||
locationDetails.ecological_district || ""
|
},
|
||||||
),
|
{
|
||||||
createData("Property Name", locationDetails.full_address || ""),
|
name: "Ecological District",
|
||||||
|
value: locationDetails.ecological_district || "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Property Name",
|
||||||
|
value: locationDetails.full_address || "",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const soilData = [
|
const soilData = [
|
||||||
createData(
|
{
|
||||||
"Soil Order",
|
name: "Soil Order",
|
||||||
`${locationDetails.soil_name} (${locationDetails.soil_code})` || ""
|
value: `${locationDetails.soil_name} (${locationDetails.soil_code})` || "",
|
||||||
),
|
},
|
||||||
createData("Soil Variant", filters.soilVariant),
|
{
|
||||||
|
name: "Soil Variant",
|
||||||
|
value: filters.soilVariant,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const siteData = [
|
const siteData = [
|
||||||
createData("Habitat", filters.habitat.name ?? ""),
|
{
|
||||||
createData(
|
name: "Habitat",
|
||||||
"Zone Name",
|
value: filters.habitat.name ?? "",
|
||||||
(filters.zone && filters.zone.name) ?? ""
|
},
|
||||||
),
|
{
|
||||||
createData(
|
name: "Zone Name",
|
||||||
"Zone Variant",
|
value: (filters.zone && filters.zone.name) ?? "",
|
||||||
(filters.zone && filters.zone.variant) ?? ""
|
},
|
||||||
),
|
{
|
||||||
createData(
|
name: "Zone Variant",
|
||||||
"Zone Refined Variant",
|
value: (filters.zone && filters.zone.variant) ?? "",
|
||||||
(filters.zone && filters.zone.refined_variant) ?? ""
|
},
|
||||||
),
|
{
|
||||||
|
name: "Zone Refined Variant",
|
||||||
|
value: (filters.zone && filters.zone.refined_variant) ?? "",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const regionInformation = () => {
|
const regionInformation = () => {
|
||||||
|
|
|
@ -9,17 +9,14 @@ import { FilterProvider } from "./components/providers/FilterProvider";
|
||||||
// Styles
|
// Styles
|
||||||
import "./assets/styles/main.scss";
|
import "./assets/styles/main.scss";
|
||||||
import "bootstrap/dist/css/bootstrap.min.css";
|
import "bootstrap/dist/css/bootstrap.min.css";
|
||||||
import ApplyPage from "./pages/ApplyPage";
|
import { ActivationProvider } from "./components/providers/ActivationProvider";
|
||||||
|
import { ErrorProvider } from "./components/providers/ErrorProvider";
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
element: <MainPage />,
|
element: <MainPage />,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/apply",
|
|
||||||
element: <ApplyPage />,
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const darkTheme = createTheme({
|
const darkTheme = createTheme({
|
||||||
|
@ -34,11 +31,15 @@ const darkTheme = createTheme({
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<div className="App">
|
<div className="App">
|
||||||
|
<ErrorProvider>
|
||||||
<FilterProvider>
|
<FilterProvider>
|
||||||
|
<ActivationProvider>
|
||||||
<ThemeProvider theme={darkTheme}>
|
<ThemeProvider theme={darkTheme}>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
</ActivationProvider>
|
||||||
</FilterProvider>
|
</FilterProvider>
|
||||||
|
</ErrorProvider>
|
||||||
</div>
|
</div>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
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 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>
|
|
||||||
<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;
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
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 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";
|
||||||
import HabitatStep from "../components/steps/habitat/HabitatStep";
|
import HabitatStep from "../components/steps/habitat/HabitatStep";
|
||||||
|
@ -7,20 +9,52 @@ 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";
|
import { StepperWizard } from "../components/providers/StepperProvider";
|
||||||
|
import { useFilter } from "../components/providers/FilterProvider";
|
||||||
|
import { Box, Typography, Modal, Button } from '@mui/material';
|
||||||
|
import { useActivator } from '../components/providers/ActivationProvider';
|
||||||
|
import { useError } from '../components/providers/ErrorProvider';
|
||||||
|
|
||||||
const MainPage = () => {
|
const MainPage = () => {
|
||||||
|
const { isPhysicalKey } = useActivator();
|
||||||
|
const { submit } = useFilter();
|
||||||
|
const { error, resetError } = useError();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Container fluid className="main-container p-0">
|
<Container fluid className="main-container p-0">
|
||||||
<Header />
|
<Header />
|
||||||
<StepperWizard>
|
<StepperWizard>
|
||||||
<LocationStep label="Select location" tooltip="Click on a location on the map" />
|
<ActivationStep label="Activate" tooltip="Enter your activation key" />
|
||||||
|
<LocationStep label="Select location" tooltip="Click on a location on the map" defaultIsSearch={isPhysicalKey} />
|
||||||
<SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" />
|
<SoilStep label="Choose soil" tooltip="Describe the moisture content of your soil" />
|
||||||
<HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" />
|
<HabitatStep label="Choose habitat" tooltip="Specify type of landscape to be planted" />
|
||||||
<ZoneStep label="Select zone" tooltip="Specify geographical detail" />
|
<ZoneStep label="Select zone" tooltip="Specify geographical detail" />
|
||||||
<SummaryStep label="Summary" tooltip="Check your inputs" />
|
<SummaryStep label="Summary" tooltip="Check your inputs" onSubmit={submit} />
|
||||||
<ResultsStep label="Results" tooltip="List of plant species and user guide" />
|
<ResultsStep label="Results" tooltip="List of plant species and user guide" />
|
||||||
</StepperWizard>
|
</StepperWizard>
|
||||||
</Container>);
|
</Container>
|
||||||
|
<Modal open={error.length > 0} onClose={resetError}>
|
||||||
|
<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={resetError}>Close</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
</>);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MainPage;
|
export default MainPage;
|
||||||
|
|
|
@ -1,33 +1,34 @@
|
||||||
import API from "./Repository";
|
import API from "./Repository";
|
||||||
|
|
||||||
const LocationRepsostory = {
|
const LocationRepsostory = {
|
||||||
getSoilDetails(filters) {
|
getSoilDetails(params) {
|
||||||
return API.get(`/soil/`, { params: filters });
|
return API.get(`/soil/`, {params});
|
||||||
},
|
},
|
||||||
|
|
||||||
getEcologicalDistrictDetails(filters) {
|
getEcologicalDistrictDetails(params) {
|
||||||
return API.get(`/ecologicaldistrict/`, { params: filters });
|
return API.get(`/ecologicaldistrict/`, {params});
|
||||||
},
|
},
|
||||||
|
|
||||||
getRegionDetails(filters) {
|
getRegionDetails(params) {
|
||||||
return API.get(`/region/`, { params: filters });
|
return API.get(`/region/`, {params});
|
||||||
},
|
},
|
||||||
|
|
||||||
getPropertyDetails(filters) {
|
getPropertyDetails(params) {
|
||||||
return API.get(`/address/`, { params: filters });
|
return API.get(`/address/`, {params});
|
||||||
},
|
},
|
||||||
|
|
||||||
async getLocationData(filters) {
|
async getLocationData(filters) {
|
||||||
|
const params = { lat: filters.coordinates.lat, lng: filters.coordinates.lng };
|
||||||
const [
|
const [
|
||||||
soilDetails,
|
soilDetails,
|
||||||
ecologicalDistrictDetails,
|
ecologicalDistrictDetails,
|
||||||
propertyDetails,
|
propertyDetails,
|
||||||
regionDetails,
|
regionDetails,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
this.getSoilDetails(filters),
|
this.getSoilDetails(params),
|
||||||
this.getEcologicalDistrictDetails(filters),
|
this.getEcologicalDistrictDetails(params),
|
||||||
this.getPropertyDetails(filters),
|
this.getPropertyDetails(params),
|
||||||
this.getRegionDetails(filters),
|
this.getRegionDetails(params),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let locationData = {};
|
let locationData = {};
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import Repository from "./Repository";
|
import Repository from "./Repository";
|
||||||
|
|
||||||
const PlantRepository = {
|
const PlantRepository = {
|
||||||
getFilteredPlants(filters) {
|
getFilteredPlants(key) {
|
||||||
return Repository.get(`/plants/`, { params: filters });
|
return Repository.get(`/plants/`, { params: {key} });
|
||||||
},
|
},
|
||||||
|
|
||||||
getPlantsCSV(filters) {
|
getPlantsCSV(key) {
|
||||||
return Repository.get("/download/csv/", { params: filters });
|
return Repository.get("/download/csv/", { params: {key} });
|
||||||
},
|
},
|
||||||
|
|
||||||
getPlantsPDF(filters) {
|
getPlantsPDF(key) {
|
||||||
return Repository.get("/download/pdf/", {
|
return Repository.get("/download/pdf/", {
|
||||||
params: filters,
|
params: {key},
|
||||||
responseType: "arraybuffer",
|
responseType: "arraybuffer",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue