From 229c77eca24c1a8b367fa55cf5e438b0a1a83d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Oliveira?= Date: Tue, 22 Feb 2022 15:17:46 +0000 Subject: [PATCH 1/3] fix: format twilio api response --- lib/customers.js | 21 +++++++++++++++++++ .../src/pages/Customers/CustomerData.js | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/customers.js b/lib/customers.js index ae7d436f..d4668429 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -575,6 +575,7 @@ function getCustomerById (id) { .then(assignCustomerData) .then(getCustomInfoRequestsData) .then(camelizeDeep) + .then(formatSubscriberInfo) } function assignCustomerData (customer) { @@ -582,6 +583,26 @@ function assignCustomerData (customer) { .then(customerEditedData => selectLatestData(customer, customerEditedData)) } +function formatSubscriberInfo(customer) { + const subscriberInfo = customer.subscriberInfo + if(!subscriberInfo) return customer + const result = subscriberInfo.result + if(subscriberInfo.status !== 'successful' || _.isEmpty(result)) return customer + + const name = _.get('belongs_to.name')(result) + const street = _.get('current_addresses[0].street_line_1')(result) + const city = _.get('current_addresses[0].city')(result) + const stateCode = _.get('current_addresses[0].state_code')(result) + const postalCode = _.get('current_addresses[0].postal_code')(result) + + customer.subscriberInfo = { + name, + address: `${street ?? ''} ${city ?? ''}${street || city ? ',' : ''} ${stateCode ?? ''} ${postalCode ?? ''}` + } + + return customer +} + /** * Query the specific customer manually edited data * diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.js b/new-lamassu-admin/src/pages/Customers/CustomerData.js index 247871a5..fa2fb32f 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerData.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerData.js @@ -103,7 +103,7 @@ const CustomerData = ({ ) const phone = R.path(['phone'])(customer) - const smsData = R.path(['subscriberInfo', 'result'])(customer) + const smsData = R.path(['subscriberInfo'])(customer) const isEven = elem => elem % 2 === 0 @@ -373,7 +373,7 @@ const CustomerData = ({ name: it, label: onlyFirstToUpper(it), component: TextInput, - editable: true + editable: false }) }, R.keys(smsData) ?? []) From 8aabd8c056828dc2e51982304f3b001bca561586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Oliveira?= Date: Tue, 22 Feb 2022 15:51:11 +0000 Subject: [PATCH 2/3] fix: disable edit on sms data card --- .../src/pages/Customers/CustomerData.js | 27 +++++++---- .../Customers/components/EditableCard.js | 45 +++++++++++++++---- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.js b/new-lamassu-admin/src/pages/Customers/CustomerData.js index fa2fb32f..837a9f93 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerData.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerData.js @@ -179,7 +179,8 @@ const CustomerData = ({ }), validationSchema: customerDataSchemas.idCardData, initialValues: initialValues.idCardData, - isAvailable: !R.isNil(idData) + isAvailable: !R.isNil(idData), + editable: true }, { fields: smsDataElements, @@ -199,7 +200,8 @@ const CustomerData = ({ retrieveAdditionalData: () => setRetrieve(true), initialValues: initialValues.smsData, isAvailable: !R.isNil(phone), - hasAdditionalData: !R.isNil(smsData) && !R.isEmpty(smsData) + hasAdditionalData: !R.isNil(smsData) && !R.isEmpty(smsData), + editable: false }, { title: 'Name', @@ -207,7 +209,8 @@ const CustomerData = ({ authorize: () => {}, reject: () => {}, save: () => {}, - isAvailable: false + isAvailable: false, + editable: true }, { title: 'Sanctions check', @@ -217,7 +220,8 @@ const CustomerData = ({ updateCustomer({ sanctionsOverride: OVERRIDE_AUTHORIZED }), reject: () => updateCustomer({ sanctionsOverride: OVERRIDE_REJECTED }), children: {sanctionsDisplay}, - isAvailable: !R.isNil(sanctions) + isAvailable: !R.isNil(sanctions), + editable: true }, { fields: customerDataElements.frontCamera, @@ -244,7 +248,8 @@ const CustomerData = ({ hasImage: true, validationSchema: customerDataSchemas.frontCamera, initialValues: initialValues.frontCamera, - isAvailable: !R.isNil(customer.frontCameraPath) + isAvailable: !R.isNil(customer.frontCameraPath), + editable: true }, { fields: customerDataElements.idCardPhoto, @@ -269,7 +274,8 @@ const CustomerData = ({ hasImage: true, validationSchema: customerDataSchemas.idCardPhoto, initialValues: initialValues.idCardPhoto, - isAvailable: !R.isNil(customer.idCardPhotoPath) + isAvailable: !R.isNil(customer.idCardPhotoPath), + editable: true }, { fields: customerDataElements.usSsn, @@ -282,7 +288,8 @@ const CustomerData = ({ deleteEditedData: () => deleteEditedData({ usSsn: null }), validationSchema: customerDataSchemas.usSsn, initialValues: initialValues.usSsn, - isAvailable: !R.isNil(customer.usSsn) + isAvailable: !R.isNil(customer.usSsn), + editable: true } ] @@ -392,7 +399,8 @@ const CustomerData = ({ validationSchema, initialValues, hasImage, - hasAdditionalData + hasAdditionalData, + editable }, idx ) => { @@ -412,7 +420,8 @@ const CustomerData = ({ initialValues={initialValues} save={save} deleteEditedData={deleteEditedData} - retrieveAdditionalData={retrieveAdditionalData}> + retrieveAdditionalData={retrieveAdditionalData} + editable={editable}> ) } diff --git a/new-lamassu-admin/src/pages/Customers/components/EditableCard.js b/new-lamassu-admin/src/pages/Customers/components/EditableCard.js index e83daa23..287fc52a 100644 --- a/new-lamassu-admin/src/pages/Customers/components/EditableCard.js +++ b/new-lamassu-admin/src/pages/Customers/components/EditableCard.js @@ -145,7 +145,8 @@ const EditableCard = ({ initialValues, deleteEditedData, retrieveAdditionalData, - hasAdditionalData = true + hasAdditionalData = true, + editable }) => { const classes = useStyles() @@ -274,13 +275,41 @@ const EditableCard = ({ )} - setEditing(true)}> - Edit - + {editable && ( + setEditing(true)}> + Edit + + )} + {!editable && + authorize && + authorized.label !== 'Accepted' && ( +
+ authorize()}> + Authorize + +
+ )} + {!editable && + authorize && + authorized.label !== 'Rejected' && ( + reject()}> + Reject + + )} )} {editing && ( From 53afd7587d6e5cecfd26421f72790cf05fb73f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Oliveira?= Date: Wed, 23 Feb 2022 00:32:25 +0000 Subject: [PATCH 3/3] refactor: retrieve data modal and error handling --- lib/customers.js | 2 +- .../src/pages/Customers/CustomerData.js | 70 +------------ .../pages/Customers/CustomerData.styles.js | 23 +---- .../src/pages/Customers/CustomerProfile.js | 99 +++++++++++++++++-- .../pages/Customers/CustomerProfile.styles.js | 26 ++++- 5 files changed, 125 insertions(+), 95 deletions(-) diff --git a/lib/customers.js b/lib/customers.js index d4668429..ebbc76b5 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -125,7 +125,7 @@ async function updateCustomer (id, data, userToken) { } 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(res => updateSubscriberData(id, res, userToken)) .catch(logger.error) diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.js b/new-lamassu-admin/src/pages/Customers/CustomerData.js index 837a9f93..4029814a 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerData.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerData.js @@ -1,4 +1,3 @@ -import { DialogActions, DialogContent, Dialog } from '@material-ui/core' import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' import { parse, format } from 'date-fns/fp' @@ -7,9 +6,9 @@ import { useState, React } from 'react' import * as Yup from 'yup' 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 { H3, Info3, H2 } from 'src/components/typography' +import { H3, Info3 } from 'src/components/typography' import { OVERRIDE_AUTHORIZED, OVERRIDE_REJECTED @@ -17,7 +16,6 @@ import { 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 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 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' @@ -74,11 +72,11 @@ const CustomerData = ({ updateCustomRequest, authorizeCustomRequest, updateCustomEntry, - retrieveAdditionalData + retrieveAdditionalDataDialog, + setRetrieve }) => { const classes = useStyles() const [listView, setListView] = useState(false) - const [retrieve, setRetrieve] = useState(false) const idData = R.path(['idCardData'])(customer) const rawExpirationDate = R.path(['expirationDate'])(idData) @@ -500,67 +498,9 @@ const CustomerData = ({ )} - + {retrieveAdditionalDataDialog} ) } -const RetrieveDataDialog = ({ - setRetrieve, - retrieveAdditionalData, - open, - props -}) => { - const classes = useStyles() - - return ( - -
- setRetrieve(false)}> - - -
-

{'Retrieve API data from Twilio'}

- - {`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`} - {` There is a small cost from Twilio for each retrieval. Would you like - to proceed?`} - - - - - -
- ) -} - export default CustomerData diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.styles.js b/new-lamassu-admin/src/pages/Customers/CustomerData.styles.js index 9a4e2871..373e2f0c 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerData.styles.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerData.styles.js @@ -1,4 +1,4 @@ -import { offColor, spacer } from 'src/styling/variables' +import { offColor } from 'src/styling/variables' export default { header: { @@ -45,26 +45,5 @@ export default { left: '100%', 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 } } diff --git a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js index 1d44c02c..4d82ebe2 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js @@ -1,18 +1,27 @@ 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 gql from 'graphql-tag' import * as R from 'ramda' import React, { memo, useState } from 'react' 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 { Label1, Label2 } from 'src/components/typography' +import { Label1, Label2, H2, Info3 } from 'src/components/typography' import { OVERRIDE_AUTHORIZED, OVERRIDE_REJECTED } 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 AuthorizeIcon } from 'src/styling/icons/button/authorize/zodiac.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 history = useHistory() + const [retrieve, setRetrieve] = useState(false) const [showCompliance, setShowCompliance] = useState(false) const [wizard, setWizard] = useState(false) - const [error] = useState(null) + const [error, setError] = useState(null) const [clickedItem, setClickedItem] = useState('overview') const { id: customerId } = useParams() @@ -323,7 +333,11 @@ const CustomerProfile = memo(() => { }) const [setCustomer] = useMutation(SET_CUSTOMER, { - onCompleted: () => getCustomer() + onCompleted: () => { + getCustomer() + setRetrieve(false) + }, + onError: error => setError(error) }) const [authorizeCustomRequest] = useMutation(SET_AUTHORIZED_REQUEST, { @@ -631,7 +645,20 @@ const CustomerProfile = memo(() => { updateCustomRequest={setCustomerCustomInfoRequest} authorizeCustomRequest={authorizeCustomRequest} updateCustomEntry={updateCustomEntry} - retrieveAdditionalData={retrieveAdditionalData}> + setRetrieve={setRetrieve} + retrieveAdditionalDataDialog={ + { + setError(null) + setRetrieve(false) + }} + onConfirmed={() => { + setError(null) + retrieveAdditionalData() + }} + error={error} + open={retrieve}> + }> )} {isNotes && ( @@ -665,4 +692,64 @@ const CustomerProfile = memo(() => { ) }) +const RetrieveDataDialog = ({ + onConfirmed, + onDismissed, + open, + error, + props +}) => { + const classes = useStyles() + + return ( + +
+ onDismissed(false)}> + + +
+

{'Retrieve API data from Twilio'}

+ + {`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`} + {` There is a small cost from Twilio for each retrieval. Would you like + to proceed?`} + + {error && ( + + Failed to save + + )} + + + + +
+ ) +} + export default CustomerProfile diff --git a/new-lamassu-admin/src/pages/Customers/CustomerProfile.styles.js b/new-lamassu-admin/src/pages/Customers/CustomerProfile.styles.js index a486abee..cd16fb0c 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerProfile.styles.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerProfile.styles.js @@ -1,4 +1,4 @@ -import { comet, subheaderColor } from 'src/styling/variables' +import { comet, subheaderColor, spacer } from 'src/styling/variables' export default { labelLink: { @@ -52,5 +52,29 @@ export default { backgroundColor: subheaderColor, borderRadius: 8, 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 } }