refactor: retrieve data modal and error handling
This commit is contained in:
parent
8aabd8c056
commit
53afd7587d
5 changed files with 125 additions and 95 deletions
|
|
@ -125,7 +125,7 @@ async function updateCustomer (id, data, userToken) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.subscriberInfo) {
|
if (data.subscriberInfo) {
|
||||||
Promise.all([getCustomerById(id), settingsLoader.loadLatest()])
|
await Promise.all([getCustomerById(id), settingsLoader.loadLatest()])
|
||||||
.then(([customer, config]) => sms.getLookup(config, customer.phone))
|
.then(([customer, config]) => sms.getLookup(config, customer.phone))
|
||||||
.then(res => updateSubscriberData(id, res, userToken))
|
.then(res => updateSubscriberData(id, res, userToken))
|
||||||
.catch(logger.error)
|
.catch(logger.error)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { DialogActions, DialogContent, Dialog } from '@material-ui/core'
|
|
||||||
import Grid from '@material-ui/core/Grid'
|
import Grid from '@material-ui/core/Grid'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import { parse, format } from 'date-fns/fp'
|
import { parse, format } from 'date-fns/fp'
|
||||||
|
|
@ -7,9 +6,9 @@ import { useState, React } from 'react'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
|
|
||||||
import ImagePopper from 'src/components/ImagePopper'
|
import ImagePopper from 'src/components/ImagePopper'
|
||||||
import { FeatureButton, Button, IconButton } from 'src/components/buttons'
|
import { FeatureButton } from 'src/components/buttons'
|
||||||
import { TextInput } from 'src/components/inputs/formik'
|
import { TextInput } from 'src/components/inputs/formik'
|
||||||
import { H3, Info3, H2 } from 'src/components/typography'
|
import { H3, Info3 } from 'src/components/typography'
|
||||||
import {
|
import {
|
||||||
OVERRIDE_AUTHORIZED,
|
OVERRIDE_AUTHORIZED,
|
||||||
OVERRIDE_REJECTED
|
OVERRIDE_REJECTED
|
||||||
|
|
@ -17,7 +16,6 @@ import {
|
||||||
import { ReactComponent as CardIcon } from 'src/styling/icons/ID/card/comet.svg'
|
import { ReactComponent as CardIcon } from 'src/styling/icons/ID/card/comet.svg'
|
||||||
import { ReactComponent as PhoneIcon } from 'src/styling/icons/ID/phone/comet.svg'
|
import { ReactComponent as PhoneIcon } from 'src/styling/icons/ID/phone/comet.svg'
|
||||||
import { ReactComponent as CrossedCameraIcon } from 'src/styling/icons/ID/photo/crossed-camera.svg'
|
import { ReactComponent as CrossedCameraIcon } from 'src/styling/icons/ID/photo/crossed-camera.svg'
|
||||||
import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg'
|
|
||||||
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/comet.svg'
|
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/comet.svg'
|
||||||
import { ReactComponent as CustomerListViewReversedIcon } from 'src/styling/icons/circle buttons/customer-list-view/white.svg'
|
import { ReactComponent as CustomerListViewReversedIcon } from 'src/styling/icons/circle buttons/customer-list-view/white.svg'
|
||||||
import { ReactComponent as CustomerListViewIcon } from 'src/styling/icons/circle buttons/customer-list-view/zodiac.svg'
|
import { ReactComponent as CustomerListViewIcon } from 'src/styling/icons/circle buttons/customer-list-view/zodiac.svg'
|
||||||
|
|
@ -74,11 +72,11 @@ const CustomerData = ({
|
||||||
updateCustomRequest,
|
updateCustomRequest,
|
||||||
authorizeCustomRequest,
|
authorizeCustomRequest,
|
||||||
updateCustomEntry,
|
updateCustomEntry,
|
||||||
retrieveAdditionalData
|
retrieveAdditionalDataDialog,
|
||||||
|
setRetrieve
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const [listView, setListView] = useState(false)
|
const [listView, setListView] = useState(false)
|
||||||
const [retrieve, setRetrieve] = useState(false)
|
|
||||||
|
|
||||||
const idData = R.path(['idCardData'])(customer)
|
const idData = R.path(['idCardData'])(customer)
|
||||||
const rawExpirationDate = R.path(['expirationDate'])(idData)
|
const rawExpirationDate = R.path(['expirationDate'])(idData)
|
||||||
|
|
@ -500,67 +498,9 @@ const CustomerData = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<RetrieveDataDialog
|
{retrieveAdditionalDataDialog}
|
||||||
setRetrieve={setRetrieve}
|
|
||||||
retrieveAdditionalData={retrieveAdditionalData}
|
|
||||||
open={retrieve}></RetrieveDataDialog>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const RetrieveDataDialog = ({
|
|
||||||
setRetrieve,
|
|
||||||
retrieveAdditionalData,
|
|
||||||
open,
|
|
||||||
props
|
|
||||||
}) => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog
|
|
||||||
open={open}
|
|
||||||
aria-labelledby="form-dialog-title"
|
|
||||||
PaperProps={{
|
|
||||||
style: {
|
|
||||||
borderRadius: 8,
|
|
||||||
minWidth: 656,
|
|
||||||
bottom: 125,
|
|
||||||
right: 7
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
{...props}>
|
|
||||||
<div className={classes.closeButton}>
|
|
||||||
<IconButton
|
|
||||||
size={16}
|
|
||||||
aria-label="close"
|
|
||||||
onClick={() => setRetrieve(false)}>
|
|
||||||
<CloseIcon />
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
<H2 className={classes.dialogTitle}>{'Retrieve API data from Twilio'}</H2>
|
|
||||||
<DialogContent className={classes.dialogContent}>
|
|
||||||
<Info3>{`With this action you'll be using Twilio's API to retrieve additional
|
|
||||||
data from this user. This includes name and address, if available.\n`}</Info3>
|
|
||||||
<Info3>{` There is a small cost from Twilio for each retrieval. Would you like
|
|
||||||
to proceed?`}</Info3>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions className={classes.dialogActions}>
|
|
||||||
<Button
|
|
||||||
backgroundColor="grey"
|
|
||||||
className={classes.cancelButton}
|
|
||||||
onClick={() => setRetrieve(false)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
retrieveAdditionalData()
|
|
||||||
setRetrieve(false)
|
|
||||||
}}>
|
|
||||||
Confirm
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CustomerData
|
export default CustomerData
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { offColor, spacer } from 'src/styling/variables'
|
import { offColor } from 'src/styling/variables'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
header: {
|
header: {
|
||||||
|
|
@ -45,26 +45,5 @@ export default {
|
||||||
left: '100%',
|
left: '100%',
|
||||||
marginLeft: 15
|
marginLeft: 15
|
||||||
}
|
}
|
||||||
},
|
|
||||||
closeButton: {
|
|
||||||
display: 'flex',
|
|
||||||
padding: [[spacer * 2, spacer * 2, 0, spacer * 2]],
|
|
||||||
paddingRight: spacer * 1.5,
|
|
||||||
justifyContent: 'end'
|
|
||||||
},
|
|
||||||
dialogTitle: {
|
|
||||||
margin: [[0, spacer * 2, spacer, spacer * 4 + spacer]]
|
|
||||||
},
|
|
||||||
dialogContent: {
|
|
||||||
width: 615,
|
|
||||||
marginLeft: 16
|
|
||||||
},
|
|
||||||
dialogActions: {
|
|
||||||
padding: spacer * 4,
|
|
||||||
paddingTop: spacer * 2
|
|
||||||
},
|
|
||||||
cancelButton: {
|
|
||||||
marginRight: 8,
|
|
||||||
padding: 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,27 @@
|
||||||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||||
import { makeStyles, Breadcrumbs, Box } from '@material-ui/core'
|
import {
|
||||||
|
makeStyles,
|
||||||
|
Breadcrumbs,
|
||||||
|
Box,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
Dialog
|
||||||
|
} from '@material-ui/core'
|
||||||
import NavigateNextIcon from '@material-ui/icons/NavigateNext'
|
import NavigateNextIcon from '@material-ui/icons/NavigateNext'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { memo, useState } from 'react'
|
import React, { memo, useState } from 'react'
|
||||||
import { useHistory, useParams } from 'react-router-dom'
|
import { useHistory, useParams } from 'react-router-dom'
|
||||||
|
|
||||||
import { ActionButton } from 'src/components/buttons'
|
import ErrorMessage from 'src/components/ErrorMessage'
|
||||||
|
import { Button, IconButton, ActionButton } from 'src/components/buttons'
|
||||||
import { Switch } from 'src/components/inputs'
|
import { Switch } from 'src/components/inputs'
|
||||||
import { Label1, Label2 } from 'src/components/typography'
|
import { Label1, Label2, H2, Info3 } from 'src/components/typography'
|
||||||
import {
|
import {
|
||||||
OVERRIDE_AUTHORIZED,
|
OVERRIDE_AUTHORIZED,
|
||||||
OVERRIDE_REJECTED
|
OVERRIDE_REJECTED
|
||||||
} from 'src/pages/Customers/components/propertyCard'
|
} from 'src/pages/Customers/components/propertyCard'
|
||||||
|
import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg'
|
||||||
import { ReactComponent as AuthorizeReversedIcon } from 'src/styling/icons/button/authorize/white.svg'
|
import { ReactComponent as AuthorizeReversedIcon } from 'src/styling/icons/button/authorize/white.svg'
|
||||||
import { ReactComponent as AuthorizeIcon } from 'src/styling/icons/button/authorize/zodiac.svg'
|
import { ReactComponent as AuthorizeIcon } from 'src/styling/icons/button/authorize/zodiac.svg'
|
||||||
import { ReactComponent as BlockReversedIcon } from 'src/styling/icons/button/block/white.svg'
|
import { ReactComponent as BlockReversedIcon } from 'src/styling/icons/button/block/white.svg'
|
||||||
|
|
@ -280,9 +289,10 @@ const GET_ACTIVE_CUSTOM_REQUESTS = gql`
|
||||||
const CustomerProfile = memo(() => {
|
const CustomerProfile = memo(() => {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
|
const [retrieve, setRetrieve] = useState(false)
|
||||||
const [showCompliance, setShowCompliance] = useState(false)
|
const [showCompliance, setShowCompliance] = useState(false)
|
||||||
const [wizard, setWizard] = useState(false)
|
const [wizard, setWizard] = useState(false)
|
||||||
const [error] = useState(null)
|
const [error, setError] = useState(null)
|
||||||
const [clickedItem, setClickedItem] = useState('overview')
|
const [clickedItem, setClickedItem] = useState('overview')
|
||||||
const { id: customerId } = useParams()
|
const { id: customerId } = useParams()
|
||||||
|
|
||||||
|
|
@ -323,7 +333,11 @@ const CustomerProfile = memo(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const [setCustomer] = useMutation(SET_CUSTOMER, {
|
const [setCustomer] = useMutation(SET_CUSTOMER, {
|
||||||
onCompleted: () => getCustomer()
|
onCompleted: () => {
|
||||||
|
getCustomer()
|
||||||
|
setRetrieve(false)
|
||||||
|
},
|
||||||
|
onError: error => setError(error)
|
||||||
})
|
})
|
||||||
|
|
||||||
const [authorizeCustomRequest] = useMutation(SET_AUTHORIZED_REQUEST, {
|
const [authorizeCustomRequest] = useMutation(SET_AUTHORIZED_REQUEST, {
|
||||||
|
|
@ -631,7 +645,20 @@ const CustomerProfile = memo(() => {
|
||||||
updateCustomRequest={setCustomerCustomInfoRequest}
|
updateCustomRequest={setCustomerCustomInfoRequest}
|
||||||
authorizeCustomRequest={authorizeCustomRequest}
|
authorizeCustomRequest={authorizeCustomRequest}
|
||||||
updateCustomEntry={updateCustomEntry}
|
updateCustomEntry={updateCustomEntry}
|
||||||
retrieveAdditionalData={retrieveAdditionalData}></CustomerData>
|
setRetrieve={setRetrieve}
|
||||||
|
retrieveAdditionalDataDialog={
|
||||||
|
<RetrieveDataDialog
|
||||||
|
onDismissed={() => {
|
||||||
|
setError(null)
|
||||||
|
setRetrieve(false)
|
||||||
|
}}
|
||||||
|
onConfirmed={() => {
|
||||||
|
setError(null)
|
||||||
|
retrieveAdditionalData()
|
||||||
|
}}
|
||||||
|
error={error}
|
||||||
|
open={retrieve}></RetrieveDataDialog>
|
||||||
|
}></CustomerData>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isNotes && (
|
{isNotes && (
|
||||||
|
|
@ -665,4 +692,64 @@ const CustomerProfile = memo(() => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const RetrieveDataDialog = ({
|
||||||
|
onConfirmed,
|
||||||
|
onDismissed,
|
||||||
|
open,
|
||||||
|
error,
|
||||||
|
props
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
aria-labelledby="form-dialog-title"
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
borderRadius: 8,
|
||||||
|
minWidth: 656,
|
||||||
|
bottom: 125,
|
||||||
|
right: 7
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
{...props}>
|
||||||
|
<div className={classes.closeButton}>
|
||||||
|
<IconButton
|
||||||
|
size={16}
|
||||||
|
aria-label="close"
|
||||||
|
onClick={() => onDismissed(false)}>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
<H2 className={classes.dialogTitle}>{'Retrieve API data from Twilio'}</H2>
|
||||||
|
<DialogContent className={classes.dialogContent}>
|
||||||
|
<Info3>{`With this action you'll be using Twilio's API to retrieve additional
|
||||||
|
data from this user. This includes name and address, if available.\n`}</Info3>
|
||||||
|
<Info3>{` There is a small cost from Twilio for each retrieval. Would you like
|
||||||
|
to proceed?`}</Info3>
|
||||||
|
</DialogContent>
|
||||||
|
{error && (
|
||||||
|
<ErrorMessage className={classes.errorMessage}>
|
||||||
|
Failed to save
|
||||||
|
</ErrorMessage>
|
||||||
|
)}
|
||||||
|
<DialogActions className={classes.dialogActions}>
|
||||||
|
<Button
|
||||||
|
backgroundColor="grey"
|
||||||
|
className={classes.cancelButton}
|
||||||
|
onClick={() => onDismissed(false)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
onConfirmed()
|
||||||
|
}}>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default CustomerProfile
|
export default CustomerProfile
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { comet, subheaderColor } from 'src/styling/variables'
|
import { comet, subheaderColor, spacer } from 'src/styling/variables'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
labelLink: {
|
labelLink: {
|
||||||
|
|
@ -52,5 +52,29 @@ export default {
|
||||||
backgroundColor: subheaderColor,
|
backgroundColor: subheaderColor,
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
padding: [[0, 5]]
|
padding: [[0, 5]]
|
||||||
|
},
|
||||||
|
closeButton: {
|
||||||
|
display: 'flex',
|
||||||
|
padding: [[spacer * 2, spacer * 2, 0, spacer * 2]],
|
||||||
|
paddingRight: spacer * 1.5,
|
||||||
|
justifyContent: 'end'
|
||||||
|
},
|
||||||
|
dialogTitle: {
|
||||||
|
margin: [[0, spacer * 2, spacer, spacer * 4 + spacer]]
|
||||||
|
},
|
||||||
|
dialogContent: {
|
||||||
|
width: 615,
|
||||||
|
marginLeft: 16
|
||||||
|
},
|
||||||
|
dialogActions: {
|
||||||
|
padding: spacer * 4,
|
||||||
|
paddingTop: spacer * 2
|
||||||
|
},
|
||||||
|
cancelButton: {
|
||||||
|
marginRight: 8,
|
||||||
|
padding: 0
|
||||||
|
},
|
||||||
|
errorMessage: {
|
||||||
|
marginLeft: 38
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue