feat: add dynamic position to editable cards, reject/authorize buttons
This commit is contained in:
parent
5cc63d05a6
commit
550bc2b7a4
9 changed files with 403 additions and 319 deletions
|
|
@ -1,21 +1,28 @@
|
|||
import { CardContent, Card } from '@material-ui/core'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import _ from 'lodash/fp'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import { useState, React } from 'react'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { Tooltip } from 'src/components/Tooltip'
|
||||
import ImagePopper from 'src/components/ImagePopper'
|
||||
import { FeatureButton } from 'src/components/buttons'
|
||||
import { TextInput } from 'src/components/inputs/formik'
|
||||
import { H3 } from 'src/components/typography'
|
||||
import { H3, Info3 } from 'src/components/typography'
|
||||
import {
|
||||
OVERRIDE_AUTHORIZED,
|
||||
OVERRIDE_REJECTED
|
||||
} from 'src/pages/Customers/components/propertyCard'
|
||||
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 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'
|
||||
import { ReactComponent as OverviewReversedIcon } from 'src/styling/icons/circle buttons/overview/white.svg'
|
||||
import { ReactComponent as OverviewIcon } from 'src/styling/icons/circle buttons/overview/zodiac.svg'
|
||||
import { URI } from 'src/utils/apollo'
|
||||
import { ifNotNull } from 'src/utils/nullCheck'
|
||||
|
||||
import styles from './CustomerData.styles.js'
|
||||
|
|
@ -24,38 +31,91 @@ import { getName } from './helper.js'
|
|||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const imageWidth = 165
|
||||
const imageHeight = 45
|
||||
const popupImageWidth = 360
|
||||
const popupImageHeight = 240
|
||||
|
||||
const Photo = ({ show, src }) => {
|
||||
const classes = useStyles({ width: imageWidth })
|
||||
|
||||
return (
|
||||
<>
|
||||
{show ? (
|
||||
<ImagePopper
|
||||
src={src}
|
||||
width={imageWidth}
|
||||
height={imageHeight}
|
||||
popupWidth={popupImageWidth}
|
||||
popupHeight={popupImageHeight}
|
||||
/>
|
||||
) : (
|
||||
<div className={classes.photoWrapper}>
|
||||
<CrossedCameraIcon />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const CustomerData = ({ customer, updateCustomer }) => {
|
||||
const classes = useStyles()
|
||||
const [listView, setListView] = useState(false)
|
||||
|
||||
const idData = R.path(['idCardData'])(customer)
|
||||
const rawExpirationDate = R.path(['expirationDate'])(idData)
|
||||
const country = R.path(['country'])(idData)
|
||||
const rawDob = R.path(['dateOfBirth'])(idData)
|
||||
|
||||
const nameElements = [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
value: `${getName(customer)}` ?? '',
|
||||
component: TextInput,
|
||||
size: 190
|
||||
const sanctions = R.path(['sanctions'])(customer)
|
||||
const sanctionsAt = R.path(['sanctionsAt'])(customer)
|
||||
const sanctionsDisplay = !sanctionsAt
|
||||
? 'Not checked yet'
|
||||
: sanctions
|
||||
? 'Passed'
|
||||
: 'Failed'
|
||||
|
||||
const isEven = elem => elem % 2 === 0
|
||||
|
||||
const getVisibleCards = _.filter(
|
||||
elem => !_.isEmpty(elem.data) || !_.isNil(elem.children)
|
||||
)
|
||||
|
||||
const getAvailableFields = _.filter(({ value }) => value !== '')
|
||||
|
||||
const schemas = {
|
||||
idScan: Yup.object().shape({
|
||||
name: Yup.string(),
|
||||
idNumber: Yup.string(),
|
||||
birthDate: Yup.string(),
|
||||
age: Yup.string(),
|
||||
gender: Yup.string(),
|
||||
state: Yup.string(),
|
||||
expirationDate: Yup.string()
|
||||
}),
|
||||
usSsn: Yup.object().shape({
|
||||
usSsn: Yup.string()
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
const idScanElements = [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
value: `${getName(customer)}`,
|
||||
component: TextInput,
|
||||
size: 190
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
name: 'ID number',
|
||||
name: 'idNumber',
|
||||
label: 'ID number',
|
||||
value: R.path(['documentNumber'])(idData),
|
||||
component: TextInput,
|
||||
size: 160
|
||||
value: R.path(['documentNumber'])(idData) ?? '',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
name: 'birthDate',
|
||||
label: 'Birth Date',
|
||||
value: ifNotNull(rawDob, moment.utc(rawDob).format('YYYY-MM-DD')),
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
name: 'age',
|
||||
|
|
@ -64,36 +124,166 @@ const CustomerData = ({ customer, updateCustomer }) => {
|
|||
rawDob,
|
||||
moment.utc().diff(moment.utc(rawDob).format('YYYY-MM-DD'), 'years')
|
||||
),
|
||||
component: TextInput,
|
||||
size: 50
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
name: 'gender',
|
||||
label: 'Gender',
|
||||
value: R.path(['gender'])(idData),
|
||||
component: TextInput,
|
||||
size: 80
|
||||
value: R.path(['gender'])(idData) ?? '',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
name: country === 'Canada' ? 'province' : 'state',
|
||||
name: 'state',
|
||||
label: country === 'Canada' ? 'Province' : 'State',
|
||||
value: R.path(['state'])(idData),
|
||||
component: TextInput,
|
||||
size: 120
|
||||
value: R.path(['state'])(idData) ?? '',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
name: 'expiration date',
|
||||
name: 'expirationDate',
|
||||
label: 'Expiration Date',
|
||||
value: ifNotNull(
|
||||
rawExpirationDate,
|
||||
moment.utc(rawExpirationDate).format('YYYY-MM-DD')
|
||||
),
|
||||
component: TextInput,
|
||||
size: 120
|
||||
component: TextInput
|
||||
}
|
||||
]
|
||||
|
||||
const [listView, setListView] = useState(false)
|
||||
const usSsnElements = [
|
||||
{
|
||||
name: 'us ssn',
|
||||
label: 'US SSN',
|
||||
value: `${customer.usSsn ?? ''}`,
|
||||
component: TextInput,
|
||||
size: 190
|
||||
}
|
||||
]
|
||||
|
||||
const initialValues = {
|
||||
idScan: {
|
||||
name: '',
|
||||
idNumber: '',
|
||||
birthDate: '',
|
||||
age: '',
|
||||
gender: '',
|
||||
state: '',
|
||||
expirationDate: ''
|
||||
},
|
||||
usSsn: {
|
||||
usSsn: ''
|
||||
}
|
||||
}
|
||||
|
||||
const cards = [
|
||||
{
|
||||
data: getAvailableFields(idScanElements),
|
||||
title: 'ID Scan',
|
||||
titleIcon: <PhoneIcon className={classes.cardIcon} />,
|
||||
state: R.path(['idCardDataOverride'])(customer),
|
||||
authorize: () =>
|
||||
updateCustomer({ idCardDataOverride: OVERRIDE_AUTHORIZED }),
|
||||
reject: () => updateCustomer({ idCardDataOverride: OVERRIDE_REJECTED }),
|
||||
save: values => console.log(values),
|
||||
validationSchema: schemas.idScan,
|
||||
initialValues: initialValues.idScan
|
||||
},
|
||||
{
|
||||
title: 'SMS Confirmation',
|
||||
titleIcon: <CardIcon className={classes.cardIcon} />,
|
||||
authorize: () => {},
|
||||
reject: () => {},
|
||||
save: () => {}
|
||||
},
|
||||
{
|
||||
title: 'Name',
|
||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
||||
authorize: () => {},
|
||||
reject: () => {},
|
||||
save: () => {}
|
||||
},
|
||||
{
|
||||
title: 'Sanctions check',
|
||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
||||
state: R.path(['sanctionsOverride'])(customer),
|
||||
authorize: () =>
|
||||
updateCustomer({ sanctionsOverride: OVERRIDE_AUTHORIZED }),
|
||||
reject: () => updateCustomer({ sanctionsOverride: OVERRIDE_REJECTED }),
|
||||
save: () => {},
|
||||
children: <Info3>{sanctionsDisplay}</Info3>
|
||||
},
|
||||
{
|
||||
title: 'Front facing camera',
|
||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
||||
state: R.path(['frontCameraOverride'])(customer),
|
||||
authorize: () =>
|
||||
updateCustomer({ frontCameraOverride: OVERRIDE_AUTHORIZED }),
|
||||
reject: () => updateCustomer({ frontCameraOverride: OVERRIDE_REJECTED }),
|
||||
save: () => {},
|
||||
children: customer.frontCameraPath ? (
|
||||
<Photo
|
||||
show={customer.frontCameraPath}
|
||||
src={`${URI}/front-camera-photo/${R.path(['frontCameraPath'])(
|
||||
customer
|
||||
)}`}
|
||||
/>
|
||||
) : null
|
||||
},
|
||||
{
|
||||
title: 'ID card image',
|
||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
||||
state: R.path(['idCardPhotoOverride'])(customer),
|
||||
authorize: () =>
|
||||
updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED }),
|
||||
reject: () => updateCustomer({ idCardPhotoOverride: OVERRIDE_REJECTED }),
|
||||
save: () => {},
|
||||
children: customer.idCardPhotoPath ? (
|
||||
<Photo
|
||||
show={customer.idCardPhotoPath}
|
||||
src={`${URI}/id-card-photo/${R.path(['idCardPhotoPath'])(customer)}`}
|
||||
/>
|
||||
) : null
|
||||
},
|
||||
{
|
||||
data: getAvailableFields(usSsnElements),
|
||||
title: 'US SSN',
|
||||
titleIcon: <CardIcon className={classes.cardIcon} />,
|
||||
state: R.path(['usSsnOverride'])(customer),
|
||||
authorize: () => updateCustomer({ usSsnOverride: OVERRIDE_AUTHORIZED }),
|
||||
reject: () => updateCustomer({ usSsnOverride: OVERRIDE_REJECTED }),
|
||||
save: () => {},
|
||||
validationSchema: schemas.usSsn,
|
||||
initialValues: initialValues.usSsn
|
||||
}
|
||||
]
|
||||
|
||||
const editableCard = ({
|
||||
title,
|
||||
authorize,
|
||||
reject,
|
||||
state,
|
||||
titleIcon,
|
||||
data,
|
||||
save,
|
||||
children,
|
||||
validationSchema,
|
||||
initialValues
|
||||
}) => {
|
||||
return (
|
||||
<EditableCard
|
||||
title={title}
|
||||
authorize={authorize}
|
||||
reject={reject}
|
||||
state={state}
|
||||
titleIcon={titleIcon}
|
||||
data={data}
|
||||
children={children}
|
||||
validationSchema={validationSchema}
|
||||
initialValues={initialValues}
|
||||
save={save}></EditableCard>
|
||||
)
|
||||
}
|
||||
|
||||
const visibleCards = getVisibleCards(cards)
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
@ -105,7 +295,6 @@ const CustomerData = ({ customer, updateCustomer }) => {
|
|||
Icon={OverviewIcon}
|
||||
InverseIcon={OverviewReversedIcon}
|
||||
onClick={() => setListView(false)}
|
||||
variant="contained"
|
||||
/>
|
||||
<FeatureButton
|
||||
active={listView}
|
||||
|
|
@ -115,45 +304,17 @@ const CustomerData = ({ customer, updateCustomer }) => {
|
|||
onClick={() => setListView(true)}></FeatureButton>
|
||||
</div>
|
||||
<div>
|
||||
{listView && <H3>{''}</H3>}
|
||||
{!listView && (
|
||||
<Grid container>
|
||||
<Grid container direction="column" item xs={6}>
|
||||
<Card className={classes.leftSideCard}>
|
||||
<CardContent>
|
||||
<div className={classes.cardHeader}>
|
||||
<EditIcon className={classes.editIcon} />
|
||||
<H3 className={classes.cardTitle}>{'Name'}</H3>
|
||||
<Tooltip width={304}></Tooltip>
|
||||
</div>
|
||||
<EditableCard
|
||||
data={nameElements}
|
||||
save={() => {}}></EditableCard>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className={classes.leftSideCard}>
|
||||
<CardContent>
|
||||
<div className={classes.cardHeader}>
|
||||
<PhoneIcon className={classes.cardIcon} />
|
||||
<H3 className={classes.cardTitle}>{'ID Scan'}</H3>
|
||||
<Tooltip width={304}></Tooltip>
|
||||
</div>
|
||||
<EditableCard
|
||||
data={idScanElements}
|
||||
save={() => {}}></EditableCard>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{visibleCards.map((elem, idx) => {
|
||||
return isEven(idx) ? editableCard(elem) : null
|
||||
})}
|
||||
</Grid>
|
||||
<Grid container direction="column" item xs={6}>
|
||||
<Card className={classes.rightSideCard}>
|
||||
<CardContent>
|
||||
<div className={classes.cardHeader}>
|
||||
<CardIcon className={classes.cardIcon} />
|
||||
<H3 className={classes.cardTitle}>{'SMS Confirmation'}</H3>
|
||||
<Tooltip width={304}></Tooltip>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{visibleCards.map((elem, idx) => {
|
||||
return !isEven(idx) ? editableCard(elem) : null
|
||||
})}
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -8,29 +8,12 @@ export default {
|
|||
marginTop: 7,
|
||||
marginRight: 24
|
||||
},
|
||||
leftSideCard: {
|
||||
borderRadius: 10,
|
||||
marginRight: 10,
|
||||
marginBottom: 15
|
||||
},
|
||||
rightSideCard: {
|
||||
borderRadius: 10,
|
||||
marginLeft: 10
|
||||
},
|
||||
cardHeader: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
marginBottom: 15
|
||||
},
|
||||
editIcon: {
|
||||
marginTop: 5
|
||||
},
|
||||
cardIcon: {
|
||||
marginTop: 7
|
||||
},
|
||||
cardTitle: {
|
||||
margin: [[8, 15, 15, 15]]
|
||||
},
|
||||
viewIcons: {
|
||||
marginRight: 12
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import styles from './CustomerProfile.styles'
|
|||
import {
|
||||
CustomerDetails,
|
||||
TransactionsList,
|
||||
ComplianceDetails,
|
||||
CustomerSidebar
|
||||
} from './components'
|
||||
import { getFormattedPhone, getName } from './helper'
|
||||
|
|
@ -260,7 +259,6 @@ const CustomerProfile = memo(() => {
|
|||
setShowCompliance={() => setShowCompliance(!showCompliance)}
|
||||
/>
|
||||
</Box>
|
||||
{!showCompliance && (
|
||||
<div>
|
||||
<TransactionsList
|
||||
customer={customerData}
|
||||
|
|
@ -269,13 +267,6 @@ const CustomerProfile = memo(() => {
|
|||
loading={loading}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{showCompliance && (
|
||||
<ComplianceDetails
|
||||
customer={customerData}
|
||||
updateCustomer={updateCustomer}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{isCustomerData && (
|
||||
|
|
|
|||
|
|
@ -1,131 +0,0 @@
|
|||
import { Box } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
|
||||
import ImagePopper from 'src/components/ImagePopper'
|
||||
import { H3, Info3 } from 'src/components/typography'
|
||||
import {
|
||||
PropertyCard,
|
||||
OVERRIDE_AUTHORIZED,
|
||||
OVERRIDE_REJECTED
|
||||
} from 'src/pages/Customers/components/propertyCard'
|
||||
import { ReactComponent as CrossedCameraIcon } from 'src/styling/icons/ID/photo/crossed-camera.svg'
|
||||
import { URI } from 'src/utils/apollo'
|
||||
|
||||
import { complianceDetailsStyles } from './ComplianceDetails.styles'
|
||||
import Field from './Field'
|
||||
|
||||
import { IdDataCard } from './'
|
||||
|
||||
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 })
|
||||
|
||||
return (
|
||||
<>
|
||||
{show ? (
|
||||
<ImagePopper
|
||||
src={src}
|
||||
width={imageWidth}
|
||||
height={imageHeight}
|
||||
popupWidth={popupImageWidth}
|
||||
popupHeight={popupImageHeight}
|
||||
/>
|
||||
) : (
|
||||
<div className={classes.photoWrapper}>
|
||||
<CrossedCameraIcon />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const ComplianceDetails = ({ customer, updateCustomer }) => {
|
||||
const classes = useStyles({ width: imageWidth })
|
||||
|
||||
const sanctions = R.path(['sanctions'])(customer)
|
||||
const sanctionsAt = R.path(['sanctionsAt'])(customer)
|
||||
const sanctionsDisplay = !sanctionsAt
|
||||
? 'Not checked yet'
|
||||
: sanctions
|
||||
? 'Passed'
|
||||
: 'Failed'
|
||||
|
||||
return (
|
||||
<div>
|
||||
<H3>Compliance details</H3>
|
||||
<div>
|
||||
<IdDataCard customerData={customer} updateCustomer={updateCustomer} />
|
||||
<Box className={classes.complianceDetailsGrid}>
|
||||
<Box className={classes.firstColumn}>
|
||||
<PropertyCard
|
||||
title={'ID card image'}
|
||||
state={R.path(['idCardPhotoOverride'])(customer)}
|
||||
authorize={() =>
|
||||
updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED })
|
||||
}
|
||||
reject={() =>
|
||||
updateCustomer({ idCardPhotoOverride: OVERRIDE_REJECTED })
|
||||
}>
|
||||
<Photo
|
||||
show={customer.idCardPhotoPath}
|
||||
src={`${URI}/id-card-photo/${R.path(['idCardPhotoPath'])(
|
||||
customer
|
||||
)}`}
|
||||
/>
|
||||
</PropertyCard>
|
||||
<PropertyCard
|
||||
title={'Front facing camera'}
|
||||
state={R.path(['frontCameraOverride'])(customer)}
|
||||
authorize={() =>
|
||||
updateCustomer({ frontCameraOverride: OVERRIDE_AUTHORIZED })
|
||||
}
|
||||
reject={() =>
|
||||
updateCustomer({ frontCameraOverride: OVERRIDE_REJECTED })
|
||||
}>
|
||||
<Photo
|
||||
show={customer.frontCameraPath}
|
||||
src={`${URI}/front-camera-photo/${R.path(['frontCameraPath'])(
|
||||
customer
|
||||
)}`}
|
||||
/>
|
||||
</PropertyCard>
|
||||
</Box>
|
||||
<Box className={classes.lastColumn}>
|
||||
<PropertyCard
|
||||
title={'US SSN'}
|
||||
state={R.path(['usSsnOverride'])(customer)}
|
||||
authorize={() =>
|
||||
updateCustomer({ usSsnOverride: OVERRIDE_AUTHORIZED })
|
||||
}
|
||||
reject={() =>
|
||||
updateCustomer({ usSsnOverride: OVERRIDE_REJECTED })
|
||||
}>
|
||||
<Field label={'US SSN'} display={customer.usSsn} />
|
||||
</PropertyCard>
|
||||
<PropertyCard
|
||||
title={'Sanctions check'}
|
||||
state={R.path(['sanctionsOverride'])(customer)}
|
||||
authorize={() =>
|
||||
updateCustomer({ sanctionsOverride: OVERRIDE_AUTHORIZED })
|
||||
}
|
||||
reject={() =>
|
||||
updateCustomer({ sanctionsOverride: OVERRIDE_REJECTED })
|
||||
}>
|
||||
<Info3>{sanctionsDisplay}</Info3>
|
||||
</PropertyCard>
|
||||
</Box>
|
||||
</Box>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ComplianceDetails
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
const complianceDetailsStyles = {
|
||||
complianceDetailsGrid: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
firstColumn: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
marginRight: 10
|
||||
},
|
||||
lastColumn: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
marginLeft: 10
|
||||
},
|
||||
photoWrapper: ({ width }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
width
|
||||
})
|
||||
}
|
||||
|
||||
export { complianceDetailsStyles }
|
||||
|
|
@ -2,11 +2,8 @@ import { makeStyles, Box } from '@material-ui/core'
|
|||
import * as R from 'ramda'
|
||||
import React, { memo } from 'react'
|
||||
|
||||
import { SubpageButton } from 'src/components/buttons'
|
||||
import { H2, Label1, P } from 'src/components/typography'
|
||||
import { ReactComponent as IdIcon } from 'src/styling/icons/ID/card/zodiac.svg'
|
||||
import { ReactComponent as LawIconInverse } from 'src/styling/icons/circle buttons/law/white.svg'
|
||||
import { ReactComponent as LawIcon } from 'src/styling/icons/circle buttons/law/zodiac.svg'
|
||||
|
||||
import mainStyles from '../CustomersList.styles'
|
||||
import { getFormattedPhone, getName } from '../helper'
|
||||
|
|
@ -70,13 +67,6 @@ const CustomerDetails = memo(
|
|||
locale.country
|
||||
)}
|
||||
</H2>
|
||||
<SubpageButton
|
||||
className={classes.subpageButton}
|
||||
Icon={LawIcon}
|
||||
InverseIcon={LawIconInverse}
|
||||
toggle={setShowCompliance}>
|
||||
Compliance details
|
||||
</SubpageButton>
|
||||
</div>
|
||||
<Box display="flex" mt="auto">
|
||||
{elements.map(({ size, header }, idx) => (
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { CardContent, Card, Grid } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import classnames from 'classnames'
|
||||
import { Form, Formik, Field as FormikField } from 'formik'
|
||||
|
|
@ -5,14 +6,23 @@ import { useState, React } from 'react'
|
|||
|
||||
import ErrorMessage from 'src/components/ErrorMessage'
|
||||
import PromptWhenDirty from 'src/components/PromptWhenDirty'
|
||||
import { MainStatus } from 'src/components/Status'
|
||||
import { Tooltip } from 'src/components/Tooltip'
|
||||
import { ActionButton } from 'src/components/buttons'
|
||||
import { Label1, Info3 } from 'src/components/typography'
|
||||
import { Label1, Info3, H3 } from 'src/components/typography'
|
||||
import {
|
||||
OVERRIDE_AUTHORIZED,
|
||||
OVERRIDE_REJECTED,
|
||||
OVERRIDE_PENDING
|
||||
} from 'src/pages/Customers/components/propertyCard'
|
||||
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
|
||||
import { ReactComponent as EditReversedIcon } from 'src/styling/icons/action/edit/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 CancelReversedIcon } from 'src/styling/icons/button/cancel/white.svg'
|
||||
import { ReactComponent as CancelIcon } from 'src/styling/icons/button/cancel/zodiac.svg'
|
||||
import { ReactComponent as SaveReversedIcon } from 'src/styling/icons/circle buttons/save/white.svg'
|
||||
import { ReactComponent as SaveIcon } from 'src/styling/icons/circle buttons/save/zodiac.svg'
|
||||
import { comet } from 'src/styling/variables'
|
||||
|
||||
import styles from './EditableCard.styles.js'
|
||||
|
|
@ -92,14 +102,52 @@ const EditableField = ({ editing, field, size, ...props }) => {
|
|||
)
|
||||
}
|
||||
|
||||
const EditableCard = ({ data, save }) => {
|
||||
const EditableCard = ({
|
||||
data,
|
||||
save,
|
||||
authorize,
|
||||
reject,
|
||||
state,
|
||||
title,
|
||||
titleIcon,
|
||||
children
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const [editing, setEditing] = useState(false)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const label1ClassNames = {
|
||||
[classes.label1]: true,
|
||||
[classes.label1Pending]: state === OVERRIDE_PENDING,
|
||||
[classes.label1Rejected]: state === OVERRIDE_REJECTED,
|
||||
[classes.label1Accepted]: state === OVERRIDE_AUTHORIZED
|
||||
}
|
||||
const isNotAuthorized =
|
||||
state === OVERRIDE_REJECTED || state === OVERRIDE_PENDING
|
||||
const authorized =
|
||||
state === OVERRIDE_PENDING
|
||||
? { label: 'Pending', type: 'neutral' }
|
||||
: state === OVERRIDE_REJECTED
|
||||
? { label: 'Rejected', type: 'error' }
|
||||
: { label: 'Accepted', type: 'success' }
|
||||
|
||||
const editableField = field => {
|
||||
return <EditableField field={field} editing={editing} size={180} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<div className={classes.cardHeader}>
|
||||
{titleIcon}
|
||||
<H3 className={classes.cardTitle}>{title}</H3>
|
||||
<Tooltip width={304}></Tooltip>
|
||||
<div className={classnames(label1ClassNames)}>
|
||||
<MainStatus statuses={[authorized]} />
|
||||
</div>
|
||||
</div>
|
||||
<Formik
|
||||
validateOnBlur={false}
|
||||
validateOnChange={false}
|
||||
|
|
@ -112,10 +160,20 @@ const EditableCard = ({ data, save }) => {
|
|||
<Form>
|
||||
<PromptWhenDirty />
|
||||
<div className={classes.row}>
|
||||
{data.map((field, idx) => (
|
||||
<EditableField key={idx} field={field} editing={editing} />
|
||||
))}
|
||||
<Grid container>
|
||||
<Grid container direction="column" item xs={6}>
|
||||
{data?.map((field, idx) => {
|
||||
return idx >= 0 && idx < 4 ? editableField(field) : null
|
||||
})}
|
||||
</Grid>
|
||||
<Grid container direction="column" item xs={6}>
|
||||
{data?.map((field, idx) => {
|
||||
return idx >= 4 ? editableField(field) : null
|
||||
})}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
{children}
|
||||
<div className={classes.edit}>
|
||||
{!editing && (
|
||||
<div className={classes.editButton}>
|
||||
|
|
@ -130,15 +188,18 @@ const EditableCard = ({ data, save }) => {
|
|||
)}
|
||||
{editing && (
|
||||
<div className={classes.editingButtons}>
|
||||
<div className={classes.saveButton}>
|
||||
{data && (
|
||||
<div className={classes.button}>
|
||||
<ActionButton
|
||||
color="secondary"
|
||||
Icon={AuthorizeIcon}
|
||||
InverseIcon={AuthorizeReversedIcon}
|
||||
Icon={SaveIcon}
|
||||
InverseIcon={SaveReversedIcon}
|
||||
type="submit">
|
||||
Save
|
||||
</ActionButton>
|
||||
</div>
|
||||
)}
|
||||
<div className={classes.button}>
|
||||
<ActionButton
|
||||
color="secondary"
|
||||
Icon={CancelIcon}
|
||||
|
|
@ -146,12 +207,31 @@ const EditableCard = ({ data, save }) => {
|
|||
type="reset">
|
||||
Cancel
|
||||
</ActionButton>
|
||||
{error && <ErrorMessage>Failed to save changes</ErrorMessage>}
|
||||
</div>
|
||||
<ActionButton
|
||||
color="secondary"
|
||||
Icon={isNotAuthorized ? AuthorizeIcon : CancelIcon}
|
||||
InverseIcon={
|
||||
isNotAuthorized
|
||||
? AuthorizeReversedIcon
|
||||
: CancelReversedIcon
|
||||
}
|
||||
type="submit"
|
||||
onClick={
|
||||
isNotAuthorized ? () => authorize() : () => reject()
|
||||
}>
|
||||
{isNotAuthorized ? 'Authorize' : 'Reject'}
|
||||
</ActionButton>
|
||||
{error && (
|
||||
<ErrorMessage>Failed to save changes</ErrorMessage>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
</Formik>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,50 @@
|
|||
import { tomato, spring4, comet } from 'src/styling/variables'
|
||||
|
||||
export default {
|
||||
label1: {
|
||||
display: 'flex',
|
||||
width: 85,
|
||||
justifyContent: 'right'
|
||||
},
|
||||
label1Pending: {
|
||||
color: comet
|
||||
},
|
||||
label1Rejected: {
|
||||
color: tomato
|
||||
},
|
||||
label1Accepted: {
|
||||
color: spring4
|
||||
},
|
||||
editButton: {
|
||||
marginTop: 30,
|
||||
display: 'flex',
|
||||
justifyContent: 'right'
|
||||
},
|
||||
saveButton: {
|
||||
marginRight: 12
|
||||
button: {
|
||||
marginRight: 8
|
||||
},
|
||||
editingButtons: {
|
||||
marginTop: 30,
|
||||
display: 'flex',
|
||||
justifyContent: 'right'
|
||||
},
|
||||
card: {
|
||||
borderRadius: 10,
|
||||
marginRight: 15,
|
||||
marginBottom: 15
|
||||
},
|
||||
cardHeader: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
marginBottom: 15
|
||||
},
|
||||
editIcon: {
|
||||
marginTop: 5
|
||||
},
|
||||
cardIcon: {
|
||||
marginTop: 7
|
||||
},
|
||||
cardTitle: {
|
||||
margin: [[8, 15, 15, 15]]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import ComplianceDetails from './ComplianceDetails'
|
||||
import CustomerDetails from './CustomerDetails'
|
||||
import CustomerSidebar from './CustomerSidebar'
|
||||
import EditableCard from './EditableCard'
|
||||
|
|
@ -10,7 +9,6 @@ export {
|
|||
CustomerDetails,
|
||||
IdDataCard,
|
||||
TransactionsList,
|
||||
ComplianceDetails,
|
||||
CustomerSidebar,
|
||||
Field,
|
||||
EditableCard
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue