Created
October 1, 2021 16:33
-
-
Save naydav/b87cd7fa17e7db70a807c6893948283a to your computer and use it in GitHub Desktop.
Custommer App - ActionsForm.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* <license header> | |
*/ | |
import React, { useState } from 'react' | |
import PropTypes from 'prop-types' | |
import ErrorBoundary from 'react-error-boundary' | |
import { | |
Flex, | |
Heading, | |
Form, | |
Picker, | |
TextArea, | |
TextField, | |
Button, | |
ActionButton, | |
StatusLight, | |
ProgressCircle, | |
Item, | |
Text, | |
View | |
} from '@adobe/react-spectrum' | |
import Function from '@spectrum-icons/workflow/Function' | |
import actions from '../config.json' // ADD notice | |
import actionWebInvoke from '../utils' | |
const ActionsForm = (props) => { | |
const [state, setState] = useState({ | |
formValid: null, | |
actionResponse: null, | |
actionResponseError: null, | |
parkingSpaceNumber: '', | |
parkingSpaceNumberValid: null, | |
orderNumber: '', | |
orderNumberValid: null, | |
customerEmail: '', | |
customerEmailValid: null, | |
actionImHereInProgress: false, | |
actionResult: '' | |
}) | |
return ( | |
<View width={{base: 'auto', L: 'size-6000'}} | |
minWidth={'350px'} | |
margin={'0 auto'} | |
> | |
<Heading level={1}>Curbside Pickup Customer App</Heading> | |
{Object.keys(actions).length > 0 && ( | |
<Form necessityIndicator="label"> | |
<TextField | |
label="Parking space #" | |
placeholder='your parking space number' | |
validationState={state.parkingSpaceNumberValid} | |
isRequired | |
value={state.parkingSpaceNumber} | |
onChange={(input) => | |
setNumberInput(input, 'parkingSpaceNumber', 'parkingSpaceNumberValid') | |
} | |
/> | |
<TextField | |
label="Order #" | |
placeholder='your order number' | |
validationState={state.orderNumberValid} | |
isRequired | |
value={state.orderNumber} | |
onChange={(input) => | |
setNumberInput(input, 'orderNumber', 'orderNumberValid') | |
} | |
/> | |
<TextField | |
type="email" | |
label="Email" | |
placeholder='customer email' | |
validationState={state.customerEmailValid} | |
isRequired | |
value={state.customerEmail} | |
onChange={(input) => | |
setEmailInput(input, 'customerEmail', 'customerEmailValid') | |
} | |
/> | |
</Form> | |
)} | |
{state.actionResponseError && ( | |
<View padding={`size-100`} marginTop={`size-100`} marginBottom={`size-100`} borderRadius={`small `}> | |
<StatusLight variant="negative">Failure! See the complete error in your browser console.</StatusLight> | |
</View> | |
)} | |
{!state.actionResponseError && state.actionResponse && ( | |
<View padding={`size-100`} marginTop={`size-100`} marginBottom={`size-100`} borderRadius={`small `}> | |
<StatusLight variant="positive">Success! See the complete response in your browser console.</StatusLight> | |
</View> | |
)} | |
<Flex> | |
<Button | |
variant="primary" | |
type="button" | |
width="100%" | |
isDisabled={!formValid()} | |
onPress={invokeAction.bind(this)} | |
><Text>I'm here</Text></Button> | |
<ProgressCircle | |
aria-label="loading" | |
isIndeterminate | |
isHidden={!state.actionImHereInProgress} | |
marginStart="size-100" | |
/> | |
</Flex> | |
</View> | |
) | |
// Methods | |
// parses a number input and adds it to the state | |
async function setNumberInput (input, stateNumber, stateValid) { | |
let content | |
let validStr = null | |
if (input) { | |
content = parseInt(input) || input | |
validStr = Number.isInteger(content) ? 'valid' : 'invalid' | |
} | |
setState({ ...state, [stateNumber]: content, [stateValid]: validStr }) | |
} | |
// check the email input and adds it to the state | |
async function setEmailInput (input, stateName, stateValid) { | |
let validStr = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(input) ? 'valid' : 'invalid' ; | |
setState({ ...state, [stateName]: input, [stateValid]: validStr }) | |
} | |
// checks if form is valid | |
function formValid () { | |
return !!(state.parkingSpaceNumber && state.parkingSpaceNumberValid | |
&& state.orderNumber && state.orderNumberValid | |
&& state.customerEmail && state.customerEmailValid) | |
} | |
// invokes a the selected backend actions with input headers and params | |
async function invokeAction () { | |
setState({ ...state, actionInvokeInProgress: true, actionResult: 'calling action ... ' }) | |
const actionName = 'i-am-here' | |
const parkingSpaceNumber = state.parkingSpaceNumber || '' | |
const orderNumber = state.orderNumber || '' | |
const customerEmail = state.customerEmail || '' | |
const params = { | |
parkingSpaceNumber: parkingSpaceNumber, | |
orderNumber: orderNumber, | |
customerEmail: customerEmail | |
} | |
const startTime = Date.now() | |
let formattedResult = "" | |
try { | |
// invoke backend action | |
const actionResponse = await actionWebInvoke(actions[actionName], {}, params) | |
formattedResult = `time: ${Date.now() - startTime} ms\n` + JSON.stringify(actionResponse,0,2) | |
// store the response | |
setState({ | |
...state, | |
actionResponse, | |
actionResult:formattedResult, | |
actionResponseError: null, | |
actionInvokeInProgress: false, | |
parkingSpaceNumber: '', | |
parkingSpaceNumberValid: null, | |
orderNumber: '', | |
orderNumberValid: null, | |
customerEmail: '', | |
customerEmailValid: null | |
}) | |
console.log(`Response from ${actionName}:`, actionResponse) | |
} catch (e) { | |
// log and store any error message | |
formattedResult = `time: ${Date.now() - startTime} ms\n` + e.message | |
console.error(e) | |
setState({ | |
...state, | |
actionResponse: null, | |
actionResult:formattedResult, | |
actionResponseError: e.message, | |
actionInvokeInProgress: false | |
}) | |
} | |
} | |
} | |
ActionsForm.propTypes = { | |
runtime: PropTypes.any, | |
ims: PropTypes.any | |
} | |
export default ActionsForm |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment