fix: inverted name and phone positions on the customers list

fix: use the correct variables for getting the customers status

fix: customer name was showing as 'undefined undefined' when not present

fix: use the phone number as a fallback for the customer name when it's
not present

fix: removed phone number compliance card

fix: set a fixed size for the popup photos
This commit is contained in:
Liordino Neto 2020-10-23 12:51:35 -03:00 committed by Josh Harvey
parent f53a934092
commit 15618df4ef
10 changed files with 117 additions and 100 deletions

View file

@ -437,13 +437,15 @@ function batch () {
* @returns {array} Array of customers with it's transactions aggregations
*/
function getCustomersList () {
const sql = `select id, name, authorized_override, front_camera_path, front_camera_override,
const sql = `select id, authorized_override, days_suspended, front_camera_path, front_camera_override,
phone, sms_override, id_card_data, id_card_data_override, id_card_data_expiration,
id_card_photo_path, id_card_photo_override, us_ssn, us_ssn_override, sanctions, sanctions_at,
sanctions_override, total_txs, total_spent, created as last_active, fiat as last_tx_fiat,
fiat_code as last_tx_fiat_code, tx_class as last_tx_class
from (
select c.id, c.name, c.authorized_override, c.front_camera_path, c.front_camera_override,
select c.id, c.authorized_override,
greatest(0, date_part('day', c.suspended_until - now())) as days_suspended,
c.front_camera_path, c.front_camera_override,
c.phone, c.sms_override, c.id_card_data, c.id_card_data_override, c.id_card_data_expiration,
c.id_card_photo_path, c.id_card_photo_override, c.us_ssn, c.us_ssn_override, c.sanctions,
c.sanctions_at, c.sanctions_override, t.tx_class, t.fiat, t.fiat_code, t.created,
@ -473,13 +475,15 @@ function getCustomersList () {
* @returns {array} Array of customers with it's transactions aggregations
*/
function getCustomerById (id) {
const sql = `select id, name, authorized_override, front_camera_path, front_camera_override,
const sql = `select id, authorized_override, days_suspended, front_camera_path, front_camera_override,
phone, sms_override, id_card_data, id_card_data_override, id_card_data_expiration,
id_card_photo_path, id_card_photo_override, us_ssn, us_ssn_override, sanctions, sanctions_at,
sanctions_override, total_txs, total_spent, created as last_active, fiat as last_tx_fiat,
fiat_code as last_tx_fiat_code, tx_class as last_tx_class
from (
select c.id, c.name, c.authorized_override, c.front_camera_path, c.front_camera_override,
select c.id, c.authorized_override,
greatest(0, date_part('day', c.suspended_until - now())) as days_suspended,
c.front_camera_path, c.front_camera_override,
c.phone, c.sms_override, c.id_card_data, c.id_card_data_override, c.id_card_data_expiration,
c.id_card_photo_path, c.id_card_photo_override, c.us_ssn, c.us_ssn_override, c.sanctions,
c.sanctions_at, c.sanctions_override, t.tx_class, t.fiat, t.fiat_code, t.created,

View file

@ -65,8 +65,8 @@ const typeDefs = gql`
type Customer {
id: ID!
name: String
authorizedOverride: String
daysSuspended: Int
frontCameraPath: String
frontCameraOverride: String
phone: String
@ -91,7 +91,6 @@ const typeDefs = gql`
}
input CustomerInput {
name: String
authorizedOverride: String
frontCameraPath: String
frontCameraOverride: String

View file

@ -11,42 +11,49 @@ import imagePopperStyles from './ImagePopper.styles'
const useStyles = makeStyles(imagePopperStyles)
const ImagePopper = memo(({ className, width, height, src }) => {
const classes = useStyles({ width, height })
const [popperAnchorEl, setPopperAnchorEl] = useState(null)
const ImagePopper = memo(
({ className, width, height, popupWidth, popupHeight, src }) => {
const classes = useStyles({
width,
height,
popupWidth,
popupHeight
})
const [popperAnchorEl, setPopperAnchorEl] = useState(null)
const handleOpenPopper = event => {
setPopperAnchorEl(popperAnchorEl ? null : event.currentTarget)
const handleOpenPopper = event => {
setPopperAnchorEl(popperAnchorEl ? null : event.currentTarget)
}
const handleClosePopper = () => {
setPopperAnchorEl(null)
}
const popperOpen = Boolean(popperAnchorEl)
const Image = ({ className }) => (
<img className={classnames(className)} src={src} alt="" />
)
return (
<ClickAwayListener onClickAway={handleClosePopper}>
<div className={classnames(classes.row, className)}>
<Image className={classes.image} />
<FeatureButton
Icon={ZoomIcon}
InverseIcon={ZoomIconInverse}
className={classes.button}
onClick={handleOpenPopper}
/>
<Popper open={popperOpen} anchorEl={popperAnchorEl} placement="top">
<div className={classes.popoverContent}>
<Image className={classes.popupImage} />
</div>
</Popper>
</div>
</ClickAwayListener>
)
}
const handleClosePopper = () => {
setPopperAnchorEl(null)
}
const popperOpen = Boolean(popperAnchorEl)
const Image = ({ className }) => (
<img className={classnames(className)} src={src} alt="" />
)
return (
<ClickAwayListener onClickAway={handleClosePopper}>
<div className={classnames(classes.row, className)}>
<Image className={classes.unzoomedImg} />
<FeatureButton
Icon={ZoomIcon}
InverseIcon={ZoomIconInverse}
className={classes.button}
onClick={handleOpenPopper}
/>
<Popper open={popperOpen} anchorEl={popperAnchorEl} placement="top">
<div className={classes.popoverContent}>
<Image />
</div>
</Popper>
</div>
</ClickAwayListener>
)
})
)
export default ImagePopper

View file

@ -3,12 +3,17 @@ export default {
display: 'flex',
flexDirection: 'row'
},
unzoomedImg: ({ width, height }) => ({
image: ({ width, height }) => ({
objectFit: 'cover',
borderRadius: '8px 0px 0px 8px',
width,
height
}),
popupImage: ({ popupWidth, popupHeight }) => ({
objectFit: 'cover',
width: popupWidth,
height: popupHeight
}),
button: ({ height }) => ({
borderRadius: '0px 8px 8px 0px',
height

View file

@ -24,6 +24,7 @@ import {
TransactionsList,
ComplianceDetails
} from './components'
import { getFormattedPhone, getName } from './helper'
const useStyles = makeStyles(styles)
@ -32,7 +33,6 @@ const GET_CUSTOMER = gql`
config
customer(customerId: $customerId) {
id
name
authorizedOverride
frontCameraPath
frontCameraOverride
@ -131,7 +131,7 @@ const CustomerProfile = memo(() => {
const sortedTransactions = R.sort(R.descend(R.prop('cryptoAtoms')))(
rawTransactions
)
const name = getName(customerData)
const blocked =
R.path(['authorizedOverride'])(customerData) === OVERRIDE_REJECTED
@ -148,7 +148,12 @@ const CustomerProfile = memo(() => {
Customers
</Label1>
<Label2 noMargin className={classes.labelLink}>
{R.path(['name'])(customerData) ?? R.path(['phone'])(customerData)}
{name.length
? name
: getFormattedPhone(
R.path(['phone'])(customerData),
locale.country
)}
</Label2>
</Breadcrumbs>
<div>

View file

@ -13,7 +13,7 @@ const GET_CUSTOMERS = gql`
config
customers {
id
name
idCardData
phone
totalTxs
totalSpent
@ -22,6 +22,7 @@ const GET_CUSTOMERS = gql`
lastTxFiatCode
lastTxClass
authorizedOverride
daysSuspended
}
}
`

View file

@ -1,5 +1,4 @@
import { makeStyles } from '@material-ui/core/styles'
import { parsePhoneNumberFromString } from 'libphonenumber-js'
import moment from 'moment'
import * as R from 'ramda'
import React from 'react'
@ -12,38 +11,23 @@ import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-ou
import { ifNotNull } from 'src/utils/nullCheck'
import styles from './CustomersList.styles'
import { getAuthorizedStatus, getFormattedPhone, getName } from './helper'
const useStyles = makeStyles(styles)
const CUSTOMER_VERIFIED = 'verified'
const CUSTOMER_BLOCKED = 'blocked'
const CustomersList = ({ data, locale, onClick, loading }) => {
const classes = useStyles()
const getAuthorizedStatus = authorizedOverride =>
authorizedOverride === CUSTOMER_VERIFIED
? { label: 'Authorized', type: 'success' }
: authorizedOverride === CUSTOMER_BLOCKED
? { label: 'Blocked', type: 'error' }
: { label: 'Suspended', type: 'warning' }
const elements = [
{
header: 'Name',
width: 241,
view: R.path(['name'])
},
{
header: 'Phone',
width: 172,
view: it =>
it.phone && locale.country
? parsePhoneNumberFromString(
it.phone,
locale.country
).formatInternational()
: ''
view: it => getFormattedPhone(it.phone, locale.country)
},
{
header: 'Name',
width: 241,
view: getName
},
{
header: 'Total TXs',
@ -84,9 +68,7 @@ const CustomersList = ({ data, locale, onClick, loading }) => {
{
header: 'Status',
width: 188,
view: it => (
<MainStatus statuses={[getAuthorizedStatus(it.authorizedOverride)]} />
)
view: it => <MainStatus statuses={[getAuthorizedStatus(it)]} />
}
]

View file

@ -1,6 +1,5 @@
import { Box } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import { parsePhoneNumberFromString } from 'libphonenumber-js'
import * as R from 'ramda'
import React from 'react'
@ -23,6 +22,8 @@ const useStyles = makeStyles(complianceDetailsStyles)
const imageWidth = 165
const imageHeight = 45
const popupImageWidth = 360
const popupImageHeight = 240
const Photo = ({ show, src }) => {
const classes = useStyles({ width: imageWidth })
@ -30,7 +31,13 @@ const Photo = ({ show, src }) => {
return (
<>
{show ? (
<ImagePopper src={src} width={imageWidth} height={imageHeight} />
<ImagePopper
src={src}
width={imageWidth}
height={imageHeight}
popupWidth={popupImageWidth}
popupHeight={popupImageHeight}
/>
) : (
<div className={classes.photoWrapper}>
<CrossedCameraIcon />
@ -43,14 +50,6 @@ const Photo = ({ show, src }) => {
const ComplianceDetails = ({ customer, locale, updateCustomer }) => {
const classes = useStyles({ width: imageWidth })
const phone =
customer.phone && locale.country
? parsePhoneNumberFromString(
customer.phone,
locale.country
).formatInternational()
: ''
const sanctions = R.path(['sanctions'])(customer)
const sanctionsAt = R.path(['sanctionsAt'])(customer)
const sanctionsDisplay = !sanctionsAt
@ -66,15 +65,6 @@ const ComplianceDetails = ({ customer, locale, updateCustomer }) => {
<IdDataCard customerData={customer} updateCustomer={updateCustomer} />
<Box className={classes.complianceDetailsGrid}>
<Box className={classes.firstColumn}>
<PropertyCard
title={'Phone nº'}
state={R.path(['smsOverride'])(customer)}
authorize={() =>
updateCustomer({ smsOverride: OVERRIDE_AUTHORIZED })
}
reject={() => updateCustomer({ smsOverride: OVERRIDE_REJECTED })}>
<Field label={'Phone'} display={phone} />
</PropertyCard>
<PropertyCard
title={'ID photo'}
state={R.path(['idCardPhotoOverride'])(customer)}

View file

@ -1,5 +1,4 @@
import { makeStyles, Box } from '@material-ui/core'
import { parsePhoneNumberFromString } from 'libphonenumber-js'
import * as R from 'ramda'
import React, { memo } from 'react'
@ -10,6 +9,7 @@ import { ReactComponent as LawIconInverse } from 'src/styling/icons/circle butto
import { ReactComponent as LawIcon } from 'src/styling/icons/circle buttons/law/zodiac.svg'
import mainStyles from '../CustomersList.styles'
import { getFormattedPhone, getName } from '../helper'
import FrontCameraPhoto from './FrontCameraPhoto'
@ -22,13 +22,7 @@ const CustomerDetails = memo(({ customer, locale, setShowCompliance }) => {
{
header: 'Phone number',
size: 172,
value:
customer.phone && locale.country
? parsePhoneNumberFromString(
customer.phone,
locale.country
).formatInternational()
: ''
value: getFormattedPhone(customer.phone, locale.country)
},
{
header: 'ID number',
@ -42,6 +36,8 @@ const CustomerDetails = memo(({ customer, locale, setShowCompliance }) => {
}
]
const name = getName(customer)
return (
<Box display="flex">
<FrontCameraPhoto
@ -51,7 +47,9 @@ const CustomerDetails = memo(({ customer, locale, setShowCompliance }) => {
<div className={classes.name}>
<IdIcon className={classes.idIcon} />
<H2 noMargin>
{R.path(['name'])(customer) ?? R.path(['phone'])(customer)}
{name.length
? name
: getFormattedPhone(R.path(['phone'])(customer), locale.country)}
</H2>
<SubpageButton
className={classes.subpageButton}

View file

@ -0,0 +1,26 @@
import { parsePhoneNumberFromString } from 'libphonenumber-js'
import * as R from 'ramda'
const CUSTOMER_BLOCKED = 'blocked'
const getAuthorizedStatus = it =>
it.authorizedOverride === CUSTOMER_BLOCKED
? { label: 'Blocked', type: 'error' }
: it.daysSuspended > 0
? { label: `${it.daysSuspended} day suspension`, type: 'warning' }
: { label: 'Authorized', type: 'success' }
const getFormattedPhone = (phone, country) =>
phone && country
? parsePhoneNumberFromString(phone, country).formatInternational()
: ''
const getName = it => {
const idData = R.path(['idCardData'])(it)
return `${R.path(['firstName'])(idData) ?? ''} ${R.path(['lastName'])(
idData
) ?? ''}`.trim()
}
export { getAuthorizedStatus, getFormattedPhone, getName }