partial: customer page css migration
This commit is contained in:
parent
926b7e6933
commit
d7b2e12f94
48 changed files with 524 additions and 2183 deletions
|
|
@ -7,14 +7,15 @@ import styles from './ActionButton.styles'
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const ActionButton = memo(
|
const ActionButton = memo(
|
||||||
({ className, Icon, InverseIcon, color, children, ...props }) => {
|
({ className, Icon, InverseIcon, color, center, children, ...props }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const classNames = {
|
const classNames = {
|
||||||
[classes.actionButton]: true,
|
[classes.actionButton]: true,
|
||||||
[classes.primary]: color === 'primary',
|
[classes.primary]: color === 'primary',
|
||||||
[classes.secondary]: color === 'secondary',
|
[classes.secondary]: color === 'secondary',
|
||||||
[classes.spring]: color === 'spring',
|
[classes.spring]: color === 'spring',
|
||||||
[classes.tomato]: color === 'tomato'
|
[classes.tomato]: color === 'tomato',
|
||||||
|
[classes.center]: center
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -119,5 +119,9 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
center: {
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
actionButtonIconActive: {}
|
actionButtonIconActive: {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ const TextInput = memo(
|
||||||
suffix,
|
suffix,
|
||||||
textAlign,
|
textAlign,
|
||||||
width,
|
width,
|
||||||
|
inputClasses,
|
||||||
// lg or sm
|
// lg or sm
|
||||||
size,
|
size,
|
||||||
bold,
|
bold,
|
||||||
|
|
@ -29,7 +30,7 @@ const TextInput = memo(
|
||||||
const classes = useStyles({ textAlign, width, size })
|
const classes = useStyles({ textAlign, width, size })
|
||||||
const isTextFilled = !error && !R.isNil(value) && !R.isEmpty(value)
|
const isTextFilled = !error && !R.isNil(value) && !R.isEmpty(value)
|
||||||
const filled = isPasswordFilled || isTextFilled
|
const filled = isPasswordFilled || isTextFilled
|
||||||
const inputClasses = {
|
const divClass = {
|
||||||
[classes.bold]: bold
|
[classes.bold]: bold
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,15 +45,17 @@ const TextInput = memo(
|
||||||
classes={{ root: classes.root }}
|
classes={{ root: classes.root }}
|
||||||
className={className}
|
className={className}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
className: classnames(inputClasses),
|
className: classnames(divClass),
|
||||||
classes: {
|
classes: {
|
||||||
root: classes.size,
|
root: classes.size,
|
||||||
underline: filled ? classes.underline : null
|
underline: filled ? classes.underline : null,
|
||||||
|
input: inputClasses
|
||||||
},
|
},
|
||||||
...InputProps
|
...InputProps
|
||||||
}}
|
}}
|
||||||
{...props} />
|
{...props}
|
||||||
);
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,19 @@
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import { useState, React } from 'react'
|
import { useState, React } from 'react'
|
||||||
import ImagePopper from 'src/components/ImagePopper'
|
import ImagePopper from 'src/components/ImagePopper'
|
||||||
import { H3, Info3 } from 'src/components/typography'
|
import { H3, Info3 } from 'src/components/typography'
|
||||||
import CardIcon from 'src/styling/icons/ID/card/comet.svg?react'
|
import CardIcon from 'src/styling/icons/ID/card/comet.svg?react'
|
||||||
import PhoneIcon from 'src/styling/icons/ID/phone/comet.svg?react'
|
import PhoneIcon from 'src/styling/icons/ID/phone/comet.svg?react'
|
||||||
import CrossedCameraIcon from 'src/styling/icons/ID/photo/crossed-camera.svg?react'
|
|
||||||
import EditIcon from 'src/styling/icons/action/edit/comet.svg?react'
|
import EditIcon from 'src/styling/icons/action/edit/comet.svg?react'
|
||||||
import CustomerListViewReversedIcon from 'src/styling/icons/circle buttons/customer-list-view/white.svg?react'
|
|
||||||
import CustomerListViewIcon from 'src/styling/icons/circle buttons/customer-list-view/zodiac.svg?react'
|
|
||||||
import OverviewReversedIcon from 'src/styling/icons/circle buttons/overview/white.svg?react'
|
|
||||||
import OverviewIcon from 'src/styling/icons/circle buttons/overview/zodiac.svg?react'
|
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
|
|
||||||
import { FeatureButton } from 'src/components/buttons'
|
|
||||||
import { TextInput } from 'src/components/inputs/formik'
|
import { TextInput } from 'src/components/inputs/formik'
|
||||||
import {
|
import {
|
||||||
OVERRIDE_AUTHORIZED,
|
OVERRIDE_AUTHORIZED,
|
||||||
OVERRIDE_REJECTED
|
OVERRIDE_REJECTED
|
||||||
} from 'src/pages/Customers/components/propertyCard'
|
} from 'src/pages/Customers/components/consts'
|
||||||
import { onlyFirstToUpper } from 'src/utils/string'
|
import { onlyFirstToUpper } from 'src/utils/string'
|
||||||
|
|
||||||
import styles from './CustomerData.styles'
|
|
||||||
import { EditableCard } from './components'
|
import { EditableCard } from './components'
|
||||||
import {
|
import {
|
||||||
customerDataElements,
|
customerDataElements,
|
||||||
|
|
@ -32,32 +23,20 @@ import {
|
||||||
getFormattedPhone
|
getFormattedPhone
|
||||||
} from './helper'
|
} from './helper'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const IMAGE_WIDTH = 165
|
const IMAGE_WIDTH = 165
|
||||||
const IMAGE_HEIGHT = 32
|
const IMAGE_HEIGHT = 32
|
||||||
const POPUP_IMAGE_WIDTH = 360
|
const POPUP_IMAGE_WIDTH = 360
|
||||||
const POPUP_IMAGE_HEIGHT = 240
|
const POPUP_IMAGE_HEIGHT = 240
|
||||||
|
|
||||||
const Photo = ({ show, src }) => {
|
const Photo = ({ src }) => {
|
||||||
const classes = useStyles({ width: IMAGE_WIDTH })
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ImagePopper
|
||||||
{show ? (
|
src={src}
|
||||||
<ImagePopper
|
width={IMAGE_WIDTH}
|
||||||
src={src}
|
height={IMAGE_HEIGHT}
|
||||||
width={IMAGE_WIDTH}
|
popupWidth={POPUP_IMAGE_WIDTH}
|
||||||
height={IMAGE_HEIGHT}
|
popupHeight={POPUP_IMAGE_HEIGHT}
|
||||||
popupWidth={POPUP_IMAGE_WIDTH}
|
/>
|
||||||
popupHeight={POPUP_IMAGE_HEIGHT}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className={classes.photoWrapper}>
|
|
||||||
<CrossedCameraIcon />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,8 +54,6 @@ const CustomerData = ({
|
||||||
setRetrieve,
|
setRetrieve,
|
||||||
checkAgainstSanctions
|
checkAgainstSanctions
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
const [listView, setListView] = useState(false)
|
|
||||||
const [previewPhoto, setPreviewPhoto] = useState(null)
|
const [previewPhoto, setPreviewPhoto] = useState(null)
|
||||||
const [previewCard, setPreviewCard] = useState(null)
|
const [previewCard, setPreviewCard] = useState(null)
|
||||||
|
|
||||||
|
|
@ -163,7 +140,7 @@ const CustomerData = ({
|
||||||
{
|
{
|
||||||
fields: customerDataElements.idCardData,
|
fields: customerDataElements.idCardData,
|
||||||
title: 'ID Scan',
|
title: 'ID Scan',
|
||||||
titleIcon: <CardIcon className={classes.cardIcon} />,
|
titleIcon: <CardIcon />,
|
||||||
state: R.path(['idCardDataOverride'])(customer),
|
state: R.path(['idCardDataOverride'])(customer),
|
||||||
authorize: () =>
|
authorize: () =>
|
||||||
updateCustomer({ idCardDataOverride: OVERRIDE_AUTHORIZED }),
|
updateCustomer({ idCardDataOverride: OVERRIDE_AUTHORIZED }),
|
||||||
|
|
@ -187,7 +164,7 @@ const CustomerData = ({
|
||||||
{
|
{
|
||||||
fields: smsDataElements,
|
fields: smsDataElements,
|
||||||
title: 'SMS data',
|
title: 'SMS data',
|
||||||
titleIcon: <PhoneIcon className={classes.cardIcon} />,
|
titleIcon: <PhoneIcon />,
|
||||||
state: R.path(['phoneOverride'])(customer),
|
state: R.path(['phoneOverride'])(customer),
|
||||||
authorize: () => updateCustomer({ phoneOverride: OVERRIDE_AUTHORIZED }),
|
authorize: () => updateCustomer({ phoneOverride: OVERRIDE_AUTHORIZED }),
|
||||||
reject: () => updateCustomer({ phoneOverride: OVERRIDE_REJECTED }),
|
reject: () => updateCustomer({ phoneOverride: OVERRIDE_REJECTED }),
|
||||||
|
|
@ -208,7 +185,7 @@ const CustomerData = ({
|
||||||
{
|
{
|
||||||
title: 'Email',
|
title: 'Email',
|
||||||
fields: customerDataElements.email,
|
fields: customerDataElements.email,
|
||||||
titleIcon: <CardIcon className={classes.cardIcon} />,
|
titleIcon: <CardIcon />,
|
||||||
// state: R.path(['emailOverride'])(customer),
|
// state: R.path(['emailOverride'])(customer),
|
||||||
// authorize: () => updateCustomer({ emailOverride: OVERRIDE_AUTHORIZED }),
|
// authorize: () => updateCustomer({ emailOverride: OVERRIDE_AUTHORIZED }),
|
||||||
// reject: () => updateCustomer({ emailOverride: OVERRIDE_REJECTED }),
|
// reject: () => updateCustomer({ emailOverride: OVERRIDE_REJECTED }),
|
||||||
|
|
@ -220,13 +197,13 @@ const CustomerData = ({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
titleIcon: <EditIcon />,
|
||||||
isAvailable: false,
|
isAvailable: false,
|
||||||
editable: true
|
editable: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Sanctions check',
|
title: 'Sanctions check',
|
||||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
titleIcon: <EditIcon />,
|
||||||
state: R.path(['sanctionsOverride'])(customer),
|
state: R.path(['sanctionsOverride'])(customer),
|
||||||
authorize: () =>
|
authorize: () =>
|
||||||
updateCustomer({ sanctionsOverride: OVERRIDE_AUTHORIZED }),
|
updateCustomer({ sanctionsOverride: OVERRIDE_AUTHORIZED }),
|
||||||
|
|
@ -238,7 +215,7 @@ const CustomerData = ({
|
||||||
{
|
{
|
||||||
fields: customerDataElements.frontCamera,
|
fields: customerDataElements.frontCamera,
|
||||||
title: 'Front facing camera',
|
title: 'Front facing camera',
|
||||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
titleIcon: <EditIcon />,
|
||||||
state: R.path(['frontCameraOverride'])(customer),
|
state: R.path(['frontCameraOverride'])(customer),
|
||||||
authorize: () =>
|
authorize: () =>
|
||||||
updateCustomer({ frontCameraOverride: OVERRIDE_AUTHORIZED }),
|
updateCustomer({ frontCameraOverride: OVERRIDE_AUTHORIZED }),
|
||||||
|
|
@ -259,7 +236,6 @@ const CustomerData = ({
|
||||||
|
|
||||||
return customer.frontCameraPath ? (
|
return customer.frontCameraPath ? (
|
||||||
<Photo
|
<Photo
|
||||||
show={customer.frontCameraPath}
|
|
||||||
src={
|
src={
|
||||||
!R.isNil(previewPhoto)
|
!R.isNil(previewPhoto)
|
||||||
? URL.createObjectURL(previewPhoto)
|
? URL.createObjectURL(previewPhoto)
|
||||||
|
|
@ -277,7 +253,7 @@ const CustomerData = ({
|
||||||
{
|
{
|
||||||
fields: customerDataElements.idCardPhoto,
|
fields: customerDataElements.idCardPhoto,
|
||||||
title: 'ID card image',
|
title: 'ID card image',
|
||||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
titleIcon: <EditIcon />,
|
||||||
state: R.path(['idCardPhotoOverride'])(customer),
|
state: R.path(['idCardPhotoOverride'])(customer),
|
||||||
authorize: () =>
|
authorize: () =>
|
||||||
updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED }),
|
updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED }),
|
||||||
|
|
@ -298,7 +274,6 @@ const CustomerData = ({
|
||||||
|
|
||||||
return customer.idCardPhotoPath ? (
|
return customer.idCardPhotoPath ? (
|
||||||
<Photo
|
<Photo
|
||||||
show={customer.idCardPhotoPath}
|
|
||||||
src={
|
src={
|
||||||
!R.isNil(previewCard)
|
!R.isNil(previewCard)
|
||||||
? URL.createObjectURL(previewCard)
|
? URL.createObjectURL(previewCard)
|
||||||
|
|
@ -316,7 +291,7 @@ const CustomerData = ({
|
||||||
{
|
{
|
||||||
fields: customerDataElements.usSsn,
|
fields: customerDataElements.usSsn,
|
||||||
title: 'US SSN',
|
title: 'US SSN',
|
||||||
titleIcon: <CardIcon className={classes.cardIcon} />,
|
titleIcon: <CardIcon />,
|
||||||
state: R.path(['usSsnOverride'])(customer),
|
state: R.path(['usSsnOverride'])(customer),
|
||||||
authorize: () => updateCustomer({ usSsnOverride: OVERRIDE_AUTHORIZED }),
|
authorize: () => updateCustomer({ usSsnOverride: OVERRIDE_AUTHORIZED }),
|
||||||
reject: () => updateCustomer({ usSsnOverride: OVERRIDE_REJECTED }),
|
reject: () => updateCustomer({ usSsnOverride: OVERRIDE_REJECTED }),
|
||||||
|
|
@ -342,7 +317,7 @@ const CustomerData = ({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
title: it.customInfoRequest.customRequest.name,
|
title: it.customInfoRequest.customRequest.name,
|
||||||
titleIcon: <CardIcon className={classes.cardIcon} />,
|
titleIcon: <CardIcon />,
|
||||||
state: R.path(['override'])(it),
|
state: R.path(['override'])(it),
|
||||||
authorize: () =>
|
authorize: () =>
|
||||||
authorizeCustomRequest({
|
authorizeCustomRequest({
|
||||||
|
|
@ -395,7 +370,7 @@ const CustomerData = ({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
title: it.label,
|
title: it.label,
|
||||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
titleIcon: <EditIcon />,
|
||||||
save: values => {
|
save: values => {
|
||||||
updateCustomEntry({
|
updateCustomEntry({
|
||||||
fieldId: it.id,
|
fieldId: it.id,
|
||||||
|
|
@ -445,7 +420,7 @@ const CustomerData = ({
|
||||||
editable: false
|
editable: false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
titleIcon: <CardIcon className={classes.cardIcon} />,
|
titleIcon: <CardIcon />,
|
||||||
title: `External Info [${it.service}]`,
|
title: `External Info [${it.service}]`,
|
||||||
initialValues: it ?? {
|
initialValues: it ?? {
|
||||||
externalId: '',
|
externalId: '',
|
||||||
|
|
@ -477,26 +452,28 @@ const CustomerData = ({
|
||||||
idx
|
idx
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<EditableCard
|
<div className="mb-4">
|
||||||
title={title}
|
<EditableCard
|
||||||
key={idx}
|
title={title}
|
||||||
authorize={authorize}
|
key={idx}
|
||||||
reject={reject}
|
authorize={authorize}
|
||||||
state={state}
|
reject={reject}
|
||||||
titleIcon={titleIcon}
|
state={state}
|
||||||
hasImage={hasImage}
|
titleIcon={titleIcon}
|
||||||
hasAdditionalData={hasAdditionalData}
|
hasImage={hasImage}
|
||||||
fields={fields}
|
hasAdditionalData={hasAdditionalData}
|
||||||
validationSchema={validationSchema}
|
fields={fields}
|
||||||
initialValues={initialValues}
|
validationSchema={validationSchema}
|
||||||
save={save}
|
initialValues={initialValues}
|
||||||
cancel={cancel}
|
save={save}
|
||||||
deleteEditedData={deleteEditedData}
|
cancel={cancel}
|
||||||
retrieveAdditionalData={retrieveAdditionalData}
|
deleteEditedData={deleteEditedData}
|
||||||
checkAgainstSanctions={checkAgainstSanctions}
|
retrieveAdditionalData={retrieveAdditionalData}
|
||||||
editable={editable}>
|
checkAgainstSanctions={checkAgainstSanctions}
|
||||||
{children}
|
editable={editable}>
|
||||||
</EditableCard>
|
{children}
|
||||||
|
</EditableCard>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -505,113 +482,67 @@ const CustomerData = ({
|
||||||
idx
|
idx
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<EditableCard
|
<div className="mb-4">
|
||||||
title={title}
|
<EditableCard
|
||||||
key={idx}
|
title={title}
|
||||||
state={state}
|
key={idx}
|
||||||
initialValues={initialValues}
|
state={state}
|
||||||
titleIcon={titleIcon}
|
initialValues={initialValues}
|
||||||
editable={false}
|
titleIcon={titleIcon}
|
||||||
hasImage={hasImage}
|
editable={false}
|
||||||
fields={fields}>
|
hasImage={hasImage}
|
||||||
{children}
|
fields={fields}>
|
||||||
</EditableCard>
|
{children}
|
||||||
|
</EditableCard>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const visibleCards = getVisibleCards(cards)
|
const visibleCards = getVisibleCards(cards)
|
||||||
|
|
||||||
|
const Separator = ({ title }) => (
|
||||||
|
<div className="w-full my-4 col-span-all">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="h-px bg-comet grow-1"></div>
|
||||||
|
<span className="mx-4 text-comet font-medium">{title}</span>
|
||||||
|
<div className="h-px bg-comet grow-5"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.header}>
|
<H3 className="mt-1 mb-7">{'Customer data'}</H3>
|
||||||
<H3 className={classes.title}>{'Customer data'}</H3>
|
|
||||||
{
|
|
||||||
// TODO: Remove false condition for next release
|
|
||||||
// false && (
|
|
||||||
// <>
|
|
||||||
// <FeatureButton
|
|
||||||
// active={!listView}
|
|
||||||
// className={classes.viewIcons}
|
|
||||||
// Icon={OverviewIcon}
|
|
||||||
// InverseIcon={OverviewReversedIcon}
|
|
||||||
// onClick={() => setListView(false)}
|
|
||||||
// />
|
|
||||||
// <FeatureButton
|
|
||||||
// active={listView}
|
|
||||||
// className={classes.viewIcons}
|
|
||||||
// Icon={CustomerListViewIcon}
|
|
||||||
// InverseIcon={CustomerListViewReversedIcon}
|
|
||||||
// onClick={() => setListView(true)}></FeatureButton>
|
|
||||||
// </>
|
|
||||||
// )
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
{!listView && customer && (
|
{customer && (
|
||||||
<Grid container>
|
<div className="columns-2 gap-4">
|
||||||
<Grid container direction="column" item xs={6}>
|
{visibleCards.map((elem, idx) => {
|
||||||
{visibleCards.map((elem, idx) => {
|
return editableCard(elem, idx)
|
||||||
return isEven(idx) ? editableCard(elem, idx) : null
|
})}
|
||||||
})}
|
{!R.isEmpty(customFields) && (
|
||||||
</Grid>
|
<>
|
||||||
<Grid container direction="column" item xs={6}>
|
<Separator title="Custom data entry" />
|
||||||
{visibleCards.map((elem, idx) => {
|
|
||||||
return !isEven(idx) ? editableCard(elem, idx) : null
|
|
||||||
})}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
{!R.isEmpty(customFields) && (
|
|
||||||
<div className={classes.wrapper}>
|
|
||||||
<span className={classes.separator}>Custom data entry</span>
|
|
||||||
<Grid container>
|
|
||||||
<Grid container direction="column" item xs={6}>
|
|
||||||
{customFields.map((elem, idx) => {
|
{customFields.map((elem, idx) => {
|
||||||
return isEven(idx) ? editableCard(elem, idx) : null
|
return editableCard(elem, idx)
|
||||||
})}
|
})}
|
||||||
</Grid>
|
</>
|
||||||
<Grid container direction="column" item xs={6}>
|
)}
|
||||||
{customFields.map((elem, idx) => {
|
{!R.isEmpty(customRequirements) && (
|
||||||
return !isEven(idx) ? editableCard(elem, idx) : null
|
<>
|
||||||
})}
|
<Separator title="Custom requirements" />
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!R.isEmpty(customRequirements) && (
|
|
||||||
<div className={classes.wrapper}>
|
|
||||||
<span className={classes.separator}>Custom requirements</span>
|
|
||||||
<Grid container>
|
|
||||||
<Grid container direction="column" item xs={6}>
|
|
||||||
{customRequirements.map((elem, idx) => {
|
{customRequirements.map((elem, idx) => {
|
||||||
return isEven(idx) ? editableCard(elem, idx) : null
|
return editableCard(elem, idx)
|
||||||
})}
|
})}
|
||||||
</Grid>
|
</>
|
||||||
<Grid container direction="column" item xs={6}>
|
)}
|
||||||
{customRequirements.map((elem, idx) => {
|
{!R.isEmpty(externalCompliance) && (
|
||||||
return !isEven(idx) ? editableCard(elem, idx) : null
|
<>
|
||||||
})}
|
<Separator title="External compliance information" />
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!R.isEmpty(externalCompliance) && (
|
|
||||||
<div className={classes.wrapper}>
|
|
||||||
<span className={classes.separator}>
|
|
||||||
External compliance information
|
|
||||||
</span>
|
|
||||||
<Grid container>
|
|
||||||
<Grid container direction="column" item xs={6}>
|
|
||||||
{externalCompliance.map((elem, idx) => {
|
{externalCompliance.map((elem, idx) => {
|
||||||
return isEven(idx) ? nonEditableCard(elem, idx) : null
|
return nonEditableCard(elem, idx)
|
||||||
})}
|
})}
|
||||||
</Grid>
|
</>
|
||||||
<Grid container direction="column" item xs={6}>
|
)}
|
||||||
{externalCompliance.map((elem, idx) => {
|
|
||||||
return !isEven(idx) ? nonEditableCard(elem, idx) : null
|
|
||||||
})}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
import { offColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
header: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
marginBottom: 15
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
marginTop: 7,
|
|
||||||
marginRight: 24
|
|
||||||
},
|
|
||||||
editIcon: {
|
|
||||||
marginTop: 5
|
|
||||||
},
|
|
||||||
cardIcon: {
|
|
||||||
marginTop: 7
|
|
||||||
},
|
|
||||||
viewIcons: {
|
|
||||||
marginRight: 12
|
|
||||||
},
|
|
||||||
wrapper: {
|
|
||||||
display: 'block',
|
|
||||||
overflow: 'hidden',
|
|
||||||
whiteSpace: 'nowrap'
|
|
||||||
},
|
|
||||||
separator: {
|
|
||||||
color: offColor,
|
|
||||||
margin: [[8, 0, 8, 150]],
|
|
||||||
position: 'relative',
|
|
||||||
display: 'inline-block',
|
|
||||||
'&:before, &:after': {
|
|
||||||
content: '""',
|
|
||||||
position: 'absolute',
|
|
||||||
background: offColor,
|
|
||||||
top: '50%',
|
|
||||||
width: 1000,
|
|
||||||
height: 1
|
|
||||||
},
|
|
||||||
'&:before': {
|
|
||||||
right: '100%',
|
|
||||||
marginRight: 15
|
|
||||||
},
|
|
||||||
'&:after': {
|
|
||||||
left: '100%',
|
|
||||||
marginLeft: 15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import { React, useState } from 'react'
|
import { React, useState } from 'react'
|
||||||
import { H3 } from 'src/components/typography'
|
import { H3 } from 'src/components/typography'
|
||||||
|
|
||||||
import styles from './CustomerNotes.styles'
|
|
||||||
import NewNoteCard from './components/notes/NewNoteCard'
|
import NewNoteCard from './components/notes/NewNoteCard'
|
||||||
import NewNoteModal from './components/notes/NewNoteModal'
|
import NewNoteModal from './components/notes/NewNoteModal'
|
||||||
import NoteCard from './components/notes/NoteCard'
|
import NoteCard from './components/notes/NoteCard'
|
||||||
import NoteEdit from './components/notes/NoteEdit'
|
import NoteEdit from './components/notes/NoteEdit'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const CustomerNotes = ({
|
const CustomerNotes = ({
|
||||||
customer,
|
customer,
|
||||||
createNote,
|
createNote,
|
||||||
|
|
@ -18,7 +14,6 @@ const CustomerNotes = ({
|
||||||
editNote,
|
editNote,
|
||||||
timezone
|
timezone
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
const [openModal, setOpenModal] = useState(false)
|
const [openModal, setOpenModal] = useState(false)
|
||||||
const [editing, setEditing] = useState(null)
|
const [editing, setEditing] = useState(null)
|
||||||
|
|
||||||
|
|
@ -52,11 +47,9 @@ const CustomerNotes = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.header}>
|
<H3 className="mt-1 mb-7">{'Notes'}</H3>
|
||||||
<H3 className={classes.title}>{'Notes'}</H3>
|
|
||||||
</div>
|
|
||||||
{R.isNil(editing) && (
|
{R.isNil(editing) && (
|
||||||
<div className={classes.notesChipList}>
|
<div className="grid grid-cols-[repeat(4,_200px)] gap-5 auto-rows-[200px]">
|
||||||
<NewNoteCard setOpenModal={setOpenModal} />
|
<NewNoteCard setOpenModal={setOpenModal} />
|
||||||
{customerNotes.map((it, idx) => (
|
{customerNotes.map((it, idx) => (
|
||||||
<NoteCard
|
<NoteCard
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
const styles = {
|
|
||||||
header: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
marginTop: 7,
|
|
||||||
marginRight: 24
|
|
||||||
},
|
|
||||||
notesChipList: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'wrap'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import Paper from '@mui/material/Paper'
|
import Paper from '@mui/material/Paper'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { format } from 'date-fns/fp'
|
import { format } from 'date-fns/fp'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import { React, useState } from 'react'
|
import { React, useState } from 'react'
|
||||||
|
|
@ -7,14 +6,9 @@ import { InformativeDialog } from 'src/components/InformativeDialog'
|
||||||
import { Label2, H3 } from 'src/components/typography'
|
import { Label2, H3 } from 'src/components/typography'
|
||||||
import CameraIcon from 'src/styling/icons/ID/photo/comet.svg?react'
|
import CameraIcon from 'src/styling/icons/ID/photo/comet.svg?react'
|
||||||
|
|
||||||
import styles from './CustomerPhotos.styles'
|
|
||||||
import PhotosCarousel from './components/PhotosCarousel'
|
import PhotosCarousel from './components/PhotosCarousel'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const CustomerPhotos = ({ photosData, timezone }) => {
|
const CustomerPhotos = ({ photosData, timezone }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const [photosDialog, setPhotosDialog] = useState(false)
|
const [photosDialog, setPhotosDialog] = useState(false)
|
||||||
const [photoClickedIndex, setPhotoClickIndex] = useState(null)
|
const [photoClickedIndex, setPhotoClickIndex] = useState(null)
|
||||||
const orderedPhotosData = !R.isNil(photoClickedIndex)
|
const orderedPhotosData = !R.isNil(photoClickedIndex)
|
||||||
|
|
@ -23,10 +17,8 @@ const CustomerPhotos = ({ photosData, timezone }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.header}>
|
<H3 className="mt-1 mb-7">{'Photos & files'}</H3>
|
||||||
<H3 className={classes.title}>{'Photos & files'}</H3>
|
<div className="flex flex-wrap gap-4">
|
||||||
</div>
|
|
||||||
<div className={classes.photosChipList}>
|
|
||||||
{photosData.map((elem, idx) => (
|
{photosData.map((elem, idx) => (
|
||||||
<PhotoCard
|
<PhotoCard
|
||||||
key={idx}
|
key={idx}
|
||||||
|
|
@ -59,21 +51,21 @@ export const PhotoCard = ({
|
||||||
setPhotosDialog,
|
setPhotosDialog,
|
||||||
setPhotoClickIndex
|
setPhotoClickIndex
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
className={classes.photoCardChip}
|
className="cursor-pointer overflow-hidden"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPhotoClickIndex(idx)
|
setPhotoClickIndex(idx)
|
||||||
setPhotosDialog(true)
|
setPhotosDialog(true)
|
||||||
}}>
|
}}>
|
||||||
<img className={classes.image} src={src} alt="" />
|
<img
|
||||||
<div className={classes.footer}>
|
className="w-56 h-50 object-cover object-center block"
|
||||||
|
src={src}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div className="flex p-3 gap-3">
|
||||||
<CameraIcon />
|
<CameraIcon />
|
||||||
<Label2 className={classes.date}>
|
<Label2 noMargin>{format('yyyy-MM-dd', new Date(date))}</Label2>
|
||||||
{format('yyyy-MM-dd', new Date(date))}
|
|
||||||
</Label2>
|
|
||||||
</div>
|
</div>
|
||||||
</Paper>
|
</Paper>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
const styles = {
|
|
||||||
header: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
marginTop: 7,
|
|
||||||
marginRight: 24,
|
|
||||||
marginBottom: 32
|
|
||||||
},
|
|
||||||
photosChipList: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: 14
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
objectFit: 'cover',
|
|
||||||
objectPosition: 'center',
|
|
||||||
width: 224,
|
|
||||||
height: 200,
|
|
||||||
borderTopLeftRadius: 4,
|
|
||||||
borderTopRightRadius: 4
|
|
||||||
},
|
|
||||||
photoCardChip: {
|
|
||||||
cursor: 'pointer'
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
margin: [[8, 0, 0, 8]]
|
|
||||||
},
|
|
||||||
date: {
|
|
||||||
margin: [[0, 0, 8, 12]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -4,7 +4,6 @@ import DialogActions from '@mui/material/DialogActions'
|
||||||
import DialogContent from '@mui/material/DialogContent'
|
import DialogContent from '@mui/material/DialogContent'
|
||||||
import Dialog from '@mui/material/Dialog'
|
import Dialog from '@mui/material/Dialog'
|
||||||
import Switch from '@mui/material/Switch'
|
import Switch from '@mui/material/Switch'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import NavigateNextIcon from '@mui/icons-material/NavigateNext'
|
import NavigateNextIcon from '@mui/icons-material/NavigateNext'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { memo, useState } from 'react'
|
import React, { memo, useState } from 'react'
|
||||||
|
|
@ -23,7 +22,7 @@ import { Button, IconButton, ActionButton } from 'src/components/buttons'
|
||||||
import {
|
import {
|
||||||
OVERRIDE_AUTHORIZED,
|
OVERRIDE_AUTHORIZED,
|
||||||
OVERRIDE_REJECTED
|
OVERRIDE_REJECTED
|
||||||
} from 'src/pages/Customers/components/propertyCard'
|
} from 'src/pages/Customers/components/consts'
|
||||||
// TODO: Enable for next release
|
// TODO: Enable for next release
|
||||||
// import DiscountReversedIcon from 'src/styling/icons/button/discount/white.svg?react'
|
// import DiscountReversedIcon from 'src/styling/icons/button/discount/white.svg?react'
|
||||||
// import Discount from 'src/styling/icons/button/discount/zodiac.svg?react'
|
// import Discount from 'src/styling/icons/button/discount/zodiac.svg?react'
|
||||||
|
|
@ -32,7 +31,6 @@ import { fromNamespace, namespaces } from 'src/utils/config'
|
||||||
import CustomerData from './CustomerData'
|
import CustomerData from './CustomerData'
|
||||||
import CustomerNotes from './CustomerNotes'
|
import CustomerNotes from './CustomerNotes'
|
||||||
import CustomerPhotos from './CustomerPhotos'
|
import CustomerPhotos from './CustomerPhotos'
|
||||||
import styles from './CustomerProfile.styles'
|
|
||||||
import {
|
import {
|
||||||
CustomerDetails,
|
CustomerDetails,
|
||||||
TransactionsList,
|
TransactionsList,
|
||||||
|
|
@ -41,8 +39,6 @@ import {
|
||||||
} from './components'
|
} from './components'
|
||||||
import { getFormattedPhone, getName, formatPhotosData } from './helper'
|
import { getFormattedPhone, getName, formatPhotosData } from './helper'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const GET_CUSTOMER = gql`
|
const GET_CUSTOMER = gql`
|
||||||
query customer($customerId: ID!) {
|
query customer($customerId: ID!) {
|
||||||
config
|
config
|
||||||
|
|
@ -528,23 +524,22 @@ const CustomerProfile = memo(() => {
|
||||||
display: it.customRequest.name
|
display: it.customRequest.name
|
||||||
})) ?? []
|
})) ?? []
|
||||||
|
|
||||||
const classes = useStyles()
|
|
||||||
const email = R.path(['email'])(customerData)
|
const email = R.path(['email'])(customerData)
|
||||||
const phone = R.path(['phone'])(customerData)
|
const phone = R.path(['phone'])(customerData)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
classes={{ root: classes.breadcrumbs }}
|
className="my-5"
|
||||||
separator={<NavigateNextIcon fontSize="small" />}
|
separator={<NavigateNextIcon fontSize="small" />}
|
||||||
aria-label="breadcrumb">
|
aria-label="breadcrumb">
|
||||||
<Label1
|
<Label1
|
||||||
noMargin
|
noMargin
|
||||||
className={classes.labelLink}
|
className="cursor-pointer text-comet"
|
||||||
onClick={() => history.push('/compliance/customers')}>
|
onClick={() => history.push('/compliance/customers')}>
|
||||||
Customers
|
Customers
|
||||||
</Label1>
|
</Label1>
|
||||||
<Label2 noMargin className={classes.labelLink}>
|
<Label2 noMargin className="cursor-pointer text-comet">
|
||||||
{name.length
|
{name.length
|
||||||
? name
|
? name
|
||||||
: email?.length
|
: email?.length
|
||||||
|
|
@ -552,8 +547,8 @@ const CustomerProfile = memo(() => {
|
||||||
: getFormattedPhone(phone, locale.country)}
|
: getFormattedPhone(phone, locale.country)}
|
||||||
</Label2>
|
</Label2>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
<div className={classes.panels}>
|
<div className="flex gap-20">
|
||||||
<div className={classes.leftSidePanel}>
|
<div className="w-55 flex flex-col gap-6">
|
||||||
{!loading && !customerData.isAnonymous && (
|
{!loading && !customerData.isAnonymous && (
|
||||||
<>
|
<>
|
||||||
<CustomerSidebar
|
<CustomerSidebar
|
||||||
|
|
@ -561,10 +556,12 @@ const CustomerProfile = memo(() => {
|
||||||
onClick={onClickSidebarItem}
|
onClick={onClickSidebarItem}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<Label1 className={classes.actionLabel}>Actions</Label1>
|
<Label1 noMargin className="text-comet my-1">
|
||||||
<div className={classes.actionBar}>
|
Actions
|
||||||
|
</Label1>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
className={classes.actionButton}
|
center
|
||||||
color="primary"
|
color="primary"
|
||||||
Icon={DataIcon}
|
Icon={DataIcon}
|
||||||
InverseIcon={DataReversedIcon}
|
InverseIcon={DataReversedIcon}
|
||||||
|
|
@ -572,7 +569,6 @@ const CustomerProfile = memo(() => {
|
||||||
{`Manual data entry`}
|
{`Manual data entry`}
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
{/* <ActionButton
|
{/* <ActionButton
|
||||||
className={classes.actionButton}
|
|
||||||
color="primary"
|
color="primary"
|
||||||
Icon={Discount}
|
Icon={Discount}
|
||||||
InverseIcon={DiscountReversedIcon}
|
InverseIcon={DiscountReversedIcon}
|
||||||
|
|
@ -581,7 +577,7 @@ const CustomerProfile = memo(() => {
|
||||||
</ActionButton> */}
|
</ActionButton> */}
|
||||||
{isSuspended && (
|
{isSuspended && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
className={classes.actionButton}
|
center
|
||||||
color="primary"
|
color="primary"
|
||||||
Icon={AuthorizeIcon}
|
Icon={AuthorizeIcon}
|
||||||
InverseIcon={AuthorizeReversedIcon}
|
InverseIcon={AuthorizeReversedIcon}
|
||||||
|
|
@ -595,7 +591,7 @@ const CustomerProfile = memo(() => {
|
||||||
)}
|
)}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.actionButton}
|
center
|
||||||
Icon={blocked ? AuthorizeIcon : BlockIcon}
|
Icon={blocked ? AuthorizeIcon : BlockIcon}
|
||||||
InverseIcon={
|
InverseIcon={
|
||||||
blocked ? AuthorizeReversedIcon : BlockReversedIcon
|
blocked ? AuthorizeReversedIcon : BlockReversedIcon
|
||||||
|
|
@ -612,11 +608,11 @@ const CustomerProfile = memo(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label1 className={classes.actionLabel}>
|
<Label1 className="text-comet my-1">
|
||||||
{`Special user status`}
|
{`Special user status`}
|
||||||
</Label1>
|
</Label1>
|
||||||
<div className={classes.actionBar}>
|
<div className="flex flex-col">
|
||||||
<div className={classes.userStatusAction}>
|
<div className="flex items-center bg-zircon px-1 rounded-lg">
|
||||||
<Switch
|
<Switch
|
||||||
checked={!!R.path(['isTestCustomer'])(customerData)}
|
checked={!!R.path(['isTestCustomer'])(customerData)}
|
||||||
value={!!R.path(['isTestCustomer'])(customerData)}
|
value={!!R.path(['isTestCustomer'])(customerData)}
|
||||||
|
|
@ -626,14 +622,14 @@ const CustomerProfile = memo(() => {
|
||||||
: enableTestCustomer()
|
: enableTestCustomer()
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{`Test user`}
|
<Label1 noMargin>Test user</Label1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.rightSidePanel}>
|
<div className="flex-1">
|
||||||
{isOverview && (
|
{isOverview && (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between mb-5">
|
<div className="flex justify-between mb-5">
|
||||||
|
|
@ -724,8 +720,6 @@ const RetrieveDataDialog = ({
|
||||||
error,
|
error,
|
||||||
props
|
props
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
|
|
@ -739,31 +733,28 @@ const RetrieveDataDialog = ({
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
{...props}>
|
{...props}>
|
||||||
<div className={classes.closeButton}>
|
<div className="pt-4 pr-4 flex justify-end">
|
||||||
<IconButton
|
<IconButton
|
||||||
size={16}
|
size={32}
|
||||||
aria-label="close"
|
aria-label="close"
|
||||||
onClick={() => onDismissed(false)}>
|
onClick={() => onDismissed(false)}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
<H2 className={classes.dialogTitle}>{'Retrieve API data from Twilio'}</H2>
|
<H2 className="mb-2 ml-10">{'Retrieve API data from Twilio'}</H2>
|
||||||
<DialogContent className={classes.dialogContent}>
|
<DialogContent className="w-153 ml-4">
|
||||||
<Info3>{`With this action you'll be using Twilio's API to retrieve additional
|
<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>
|
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
|
<Info3>{` There is a small cost from Twilio for each retrieval. Would you like
|
||||||
to proceed?`}</Info3>
|
to proceed?`}</Info3>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
{error && (
|
{error && (
|
||||||
<ErrorMessage className={classes.errorMessage}>
|
<ErrorMessage className="ml-10">
|
||||||
Failed to fetch additional data
|
Failed to fetch additional data
|
||||||
</ErrorMessage>
|
</ErrorMessage>
|
||||||
)}
|
)}
|
||||||
<DialogActions className={classes.dialogActions}>
|
<DialogActions className="p-8 pt-4 gap-2">
|
||||||
<Button
|
<Button backgroundColor="grey" onClick={() => onDismissed(false)}>
|
||||||
backgroundColor="grey"
|
|
||||||
className={classes.cancelButton}
|
|
||||||
onClick={() => onDismissed(false)}>
|
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
import { comet, subheaderColor, spacer } from 'src/styling/variables'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
labelLink: {
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: comet
|
|
||||||
},
|
|
||||||
breadcrumbs: {
|
|
||||||
margin: [[20, 0]]
|
|
||||||
},
|
|
||||||
actionLabel: {
|
|
||||||
color: comet,
|
|
||||||
margin: [[4, 0]]
|
|
||||||
},
|
|
||||||
customerDetails: {
|
|
||||||
marginBottom: 18
|
|
||||||
},
|
|
||||||
actionButton: {
|
|
||||||
margin: [[0, 0, 4, 0]],
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'center'
|
|
||||||
},
|
|
||||||
actionBar: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
width: 219
|
|
||||||
},
|
|
||||||
panels: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
rightSidePanel: {
|
|
||||||
display: 'block',
|
|
||||||
width: 1100,
|
|
||||||
marginBottom: 25
|
|
||||||
},
|
|
||||||
leftSidePanel: {
|
|
||||||
width: 300,
|
|
||||||
'& > *': {
|
|
||||||
marginBottom: 25
|
|
||||||
},
|
|
||||||
'& > *:last-child': {
|
|
||||||
marginBottom: 0
|
|
||||||
},
|
|
||||||
'& > *:first-child': {
|
|
||||||
marginBottom: 50
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userStatusAction: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useQuery, useMutation, gql } from '@apollo/client'
|
import { useQuery, useMutation, gql } from '@apollo/client'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
|
|
@ -10,7 +9,6 @@ import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
|
||||||
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
||||||
|
|
||||||
import { Link } from 'src/components/buttons'
|
import { Link } from 'src/components/buttons'
|
||||||
import baseStyles from 'src/pages/Logs.styles'
|
|
||||||
import { fromNamespace, namespaces } from 'src/utils/config'
|
import { fromNamespace, namespaces } from 'src/utils/config'
|
||||||
|
|
||||||
import CustomersList from './CustomersList'
|
import CustomersList from './CustomersList'
|
||||||
|
|
@ -93,13 +91,10 @@ const CREATE_CUSTOMER = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const useBaseStyles = makeStyles(baseStyles)
|
|
||||||
|
|
||||||
const getFiltersObj = filters =>
|
const getFiltersObj = filters =>
|
||||||
R.reduce((s, f) => ({ ...s, [f.type]: f.value }), {}, filters)
|
R.reduce((s, f) => ({ ...s, [f.type]: f.value }), {}, filters)
|
||||||
|
|
||||||
const Customers = () => {
|
const Customers = () => {
|
||||||
const baseStyles = useBaseStyles()
|
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
const handleCustomerClicked = customer =>
|
const handleCustomerClicked = customer =>
|
||||||
|
|
@ -210,7 +205,7 @@ const Customers = () => {
|
||||||
<TitleSection
|
<TitleSection
|
||||||
title="Customers"
|
title="Customers"
|
||||||
appendix={
|
appendix={
|
||||||
<div className={baseStyles.buttonsWrapper}>
|
<div className="flex ml-4">
|
||||||
<SearchBox
|
<SearchBox
|
||||||
loading={loadingFilters}
|
loading={loadingFilters}
|
||||||
filters={filters}
|
filters={filters}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { format } from 'date-fns/fp'
|
import { format } from 'date-fns/fp'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
@ -7,11 +6,8 @@ import DataTable from 'src/components/tables/DataTable'
|
||||||
import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
|
import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
|
||||||
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
||||||
|
|
||||||
import styles from './CustomersList.styles'
|
|
||||||
import { getFormattedPhone, getName } from './helper'
|
import { getFormattedPhone, getName } from './helper'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const CustomersList = ({
|
const CustomersList = ({
|
||||||
data,
|
data,
|
||||||
locale,
|
locale,
|
||||||
|
|
@ -20,8 +16,6 @@ const CustomersList = ({
|
||||||
triggers,
|
triggers,
|
||||||
customRequests
|
customRequests
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const elements = [
|
const elements = [
|
||||||
{
|
{
|
||||||
header: 'Phone/email',
|
header: 'Phone/email',
|
||||||
|
|
@ -60,7 +54,7 @@ const CustomersList = ({
|
||||||
view: it => {
|
view: it => {
|
||||||
const hasLastTx = !R.isNil(it.lastTxFiatCode)
|
const hasLastTx = !R.isNil(it.lastTxFiatCode)
|
||||||
const LastTxIcon = it.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon
|
const LastTxIcon = it.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon
|
||||||
const lastIcon = <LastTxIcon className={classes.txClassIconRight} />
|
const lastIcon = <LastTxIcon className="ml-3" />
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hasLastTx &&
|
{hasLastTx &&
|
||||||
|
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import baseStyles from 'src/pages/Logs.styles'
|
|
||||||
import { zircon, comet, primaryColor, fontSize4 } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { label1 } = typographyStyles
|
|
||||||
const { titleWrapper, titleAndButtonsContainer } = baseStyles
|
|
||||||
|
|
||||||
export default {
|
|
||||||
titleWrapper,
|
|
||||||
titleAndButtonsContainer,
|
|
||||||
row: {
|
|
||||||
display: 'flex',
|
|
||||||
flexFlow: 'row nowrap'
|
|
||||||
},
|
|
||||||
rowSpaceBetween: {
|
|
||||||
display: 'flex',
|
|
||||||
flexFlow: 'row nowrap',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
display: 'flex',
|
|
||||||
flexFlow: 'column nowrap',
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
textInput: {
|
|
||||||
width: 144
|
|
||||||
},
|
|
||||||
p: {
|
|
||||||
fontFamily: 'MuseoSans',
|
|
||||||
fontSize: fontSize4,
|
|
||||||
fontWeight: 500,
|
|
||||||
fontStretch: 'normal',
|
|
||||||
fontStyle: 'normal',
|
|
||||||
lineHeight: 1.14,
|
|
||||||
letterSpacing: 'normal',
|
|
||||||
color: primaryColor
|
|
||||||
},
|
|
||||||
txId: {
|
|
||||||
fontFamily: 'MuseoSans',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis'
|
|
||||||
},
|
|
||||||
txClassIconLeft: {
|
|
||||||
marginRight: 11
|
|
||||||
},
|
|
||||||
txClassIconRight: {
|
|
||||||
marginLeft: 11
|
|
||||||
},
|
|
||||||
headerLabels: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
'& div': {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
'& > div:first-child': {
|
|
||||||
marginRight: 24
|
|
||||||
},
|
|
||||||
'& span': {
|
|
||||||
extend: label1,
|
|
||||||
marginLeft: 6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
photo: {
|
|
||||||
width: 92,
|
|
||||||
height: 92,
|
|
||||||
borderRadius: 8,
|
|
||||||
backgroundColor: zircon,
|
|
||||||
margin: [[0, 28, 0, 0]],
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
img: {
|
|
||||||
width: 80
|
|
||||||
},
|
|
||||||
customerName: {
|
|
||||||
marginBottom: 32
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
marginRight: 11
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
height: 16
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
marginBottom: 4,
|
|
||||||
color: comet
|
|
||||||
},
|
|
||||||
txSummaryValue: {
|
|
||||||
height: 16,
|
|
||||||
marginRight: 25
|
|
||||||
},
|
|
||||||
txSummaryLabel: {
|
|
||||||
marginBottom: 4,
|
|
||||||
color: comet,
|
|
||||||
marginRight: 25
|
|
||||||
},
|
|
||||||
idIcon: {
|
|
||||||
marginRight: 10
|
|
||||||
},
|
|
||||||
subpageButton: {
|
|
||||||
marginLeft: 16
|
|
||||||
},
|
|
||||||
txTableSpacing: {
|
|
||||||
marginTop: 40
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { Form, Formik } from 'formik'
|
import { Form, Formik } from 'formik'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState, Fragment } from 'react'
|
import React, { useState, Fragment } from 'react'
|
||||||
|
|
@ -7,7 +6,6 @@ import Modal from 'src/components/Modal'
|
||||||
import Stepper from 'src/components/Stepper'
|
import Stepper from 'src/components/Stepper'
|
||||||
|
|
||||||
import { Button } from 'src/components/buttons'
|
import { Button } from 'src/components/buttons'
|
||||||
import { comet } from 'src/styling/variables'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
entryType,
|
entryType,
|
||||||
|
|
@ -20,43 +18,6 @@ import {
|
||||||
|
|
||||||
const LAST_STEP = 2
|
const LAST_STEP = 2
|
||||||
|
|
||||||
const styles = {
|
|
||||||
stepper: {
|
|
||||||
margin: [[16, 0, 14, 0]]
|
|
||||||
},
|
|
||||||
submit: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
margin: [['auto', 0, 24]]
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
marginLeft: 'auto'
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column'
|
|
||||||
},
|
|
||||||
infoTitle: {
|
|
||||||
margin: [[18, 0, 20, 0]]
|
|
||||||
},
|
|
||||||
infoCurrentText: {
|
|
||||||
color: comet
|
|
||||||
},
|
|
||||||
blankSpace: {
|
|
||||||
padding: [[0, 30]],
|
|
||||||
margin: [[0, 4, 0, 2]],
|
|
||||||
borderBottom: `1px solid ${comet}`,
|
|
||||||
display: 'inline-block'
|
|
||||||
},
|
|
||||||
dropdownField: {
|
|
||||||
marginTop: 16,
|
|
||||||
minWidth: 155
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const getStep = (step, selectedValues) => {
|
const getStep = (step, selectedValues) => {
|
||||||
const elements =
|
const elements =
|
||||||
selectedValues?.entryType === REQUIREMENT &&
|
selectedValues?.entryType === REQUIREMENT &&
|
||||||
|
|
@ -82,8 +43,6 @@ const Wizard = ({
|
||||||
addCustomerData,
|
addCustomerData,
|
||||||
addPhoto
|
addPhoto
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const [selectedValues, setSelectedValues] = useState(null)
|
const [selectedValues, setSelectedValues] = useState(null)
|
||||||
|
|
||||||
const [{ step, config }, setState] = useState({
|
const [{ step, config }, setState] = useState({
|
||||||
|
|
@ -98,7 +57,7 @@ const Wizard = ({
|
||||||
const stepOptions = getStep(step, selectedValues)
|
const stepOptions = getStep(step, selectedValues)
|
||||||
|
|
||||||
const onContinue = async it => {
|
const onContinue = async it => {
|
||||||
const newConfig = R.merge(config, stepOptions.schema.cast(it))
|
const newConfig = R.mergeRight(config, stepOptions.schema.cast(it))
|
||||||
setSelectedValues(newConfig)
|
setSelectedValues(newConfig)
|
||||||
|
|
||||||
if (isLastStep) {
|
if (isLastStep) {
|
||||||
|
|
@ -135,11 +94,7 @@ const Wizard = ({
|
||||||
width={520}
|
width={520}
|
||||||
height={520}
|
height={520}
|
||||||
open={true}>
|
open={true}>
|
||||||
<Stepper
|
<Stepper steps={LAST_STEP} currentStep={step} className="my-4" />
|
||||||
className={classes.stepper}
|
|
||||||
steps={LAST_STEP}
|
|
||||||
currentStep={step}
|
|
||||||
/>
|
|
||||||
<Formik
|
<Formik
|
||||||
validateOnBlur={false}
|
validateOnBlur={false}
|
||||||
validateOnChange={false}
|
validateOnChange={false}
|
||||||
|
|
@ -148,19 +103,19 @@ const Wizard = ({
|
||||||
initialValues={stepOptions.initialValues}
|
initialValues={stepOptions.initialValues}
|
||||||
validationSchema={stepOptions.schema}>
|
validationSchema={stepOptions.schema}>
|
||||||
{({ errors }) => (
|
{({ errors }) => (
|
||||||
<Form className={classes.form}>
|
<Form className="h-full flex flex-col">
|
||||||
<stepOptions.Component
|
<stepOptions.Component
|
||||||
selectedValues={selectedValues}
|
selectedValues={selectedValues}
|
||||||
customInfoRequirementOptions={customInfoRequirementOptions}
|
customInfoRequirementOptions={customInfoRequirementOptions}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
{...stepOptions.props}
|
{...stepOptions.props}
|
||||||
/>
|
/>
|
||||||
<div className={classes.submit}>
|
<div className="flex mt-auto mb-6">
|
||||||
{error && <ErrorMessage>Failed to save</ErrorMessage>}
|
{error && <ErrorMessage>Failed to save</ErrorMessage>}
|
||||||
{Object.keys(errors).length > 0 && (
|
{Object.keys(errors).length > 0 && (
|
||||||
<ErrorMessage>{Object.values(errors)[0]}</ErrorMessage>
|
<ErrorMessage>{Object.values(errors)[0]}</ErrorMessage>
|
||||||
)}
|
)}
|
||||||
<Button className={classes.button} type="submit">
|
<Button className="ml-auto" type="submit">
|
||||||
{isLastStep ? 'Add Data' : 'Next'}
|
{isLastStep ? 'Add Data' : 'Next'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { Field, Form, Formik } from 'formik'
|
import { Field, Form, Formik } from 'formik'
|
||||||
import { parsePhoneNumberWithError } from 'libphonenumber-js'
|
import { parsePhoneNumberWithError } from 'libphonenumber-js'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
|
|
@ -10,28 +9,6 @@ import * as Yup from 'yup'
|
||||||
|
|
||||||
import { Button } from 'src/components/buttons'
|
import { Button } from 'src/components/buttons'
|
||||||
import { TextInput } from 'src/components/inputs/formik'
|
import { TextInput } from 'src/components/inputs/formik'
|
||||||
import { spacer, primaryColor, fontPrimary } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
modalTitle: {
|
|
||||||
marginTop: -5,
|
|
||||||
color: primaryColor,
|
|
||||||
fontFamily: fontPrimary
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
margin: [['auto', 0, spacer * 3, 0]]
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
height: '100%'
|
|
||||||
},
|
|
||||||
submit: {
|
|
||||||
margin: [['auto', 0, 0, 'auto']]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getValidationSchema = countryCodes =>
|
const getValidationSchema = countryCodes =>
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
|
|
@ -39,7 +16,9 @@ const getValidationSchema = countryCodes =>
|
||||||
.required('A phone number is required')
|
.required('A phone number is required')
|
||||||
.test('is-valid-number', 'That is not a valid phone number', value => {
|
.test('is-valid-number', 'That is not a valid phone number', value => {
|
||||||
try {
|
try {
|
||||||
return countryCodes.some(countryCode => parsePhoneNumberWithError(value, countryCode).isValid())
|
return countryCodes.some(countryCode =>
|
||||||
|
parsePhoneNumberWithError(value, countryCode).isValid()
|
||||||
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -60,8 +39,6 @@ const initialValues = {
|
||||||
phoneNumber: ''
|
phoneNumber: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const getErrorMsg = (formikErrors, formikTouched) => {
|
const getErrorMsg = (formikErrors, formikTouched) => {
|
||||||
if (!formikErrors || !formikTouched) return null
|
if (!formikErrors || !formikTouched) return null
|
||||||
if (formikErrors.phoneNumber && formikTouched.phoneNumber)
|
if (formikErrors.phoneNumber && formikTouched.phoneNumber)
|
||||||
|
|
@ -70,8 +47,6 @@ const getErrorMsg = (formikErrors, formikTouched) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateCustomerModal = ({ showModal, handleClose, onSubmit, locale }) => {
|
const CreateCustomerModal = ({ showModal, handleClose, onSubmit, locale }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const possibleCountries = R.append(
|
const possibleCountries = R.append(
|
||||||
locale?.country,
|
locale?.country,
|
||||||
R.map(it => it.country, locale?.overrides ?? [])
|
R.map(it => it.country, locale?.overrides ?? [])
|
||||||
|
|
@ -99,8 +74,10 @@ const CreateCustomerModal = ({ showModal, handleClose, onSubmit, locale }) => {
|
||||||
})
|
})
|
||||||
}}>
|
}}>
|
||||||
{({ errors, touched }) => (
|
{({ errors, touched }) => (
|
||||||
<Form id="customer-registration-form" className={classes.form}>
|
<Form
|
||||||
<H1 className={classes.modalTitle}>Create new customer</H1>
|
id="customer-registration-form"
|
||||||
|
className="flex flex-col h-full">
|
||||||
|
<H1 className="-mt-2">Create new customer</H1>
|
||||||
<Field
|
<Field
|
||||||
component={TextInput}
|
component={TextInput}
|
||||||
name="phoneNumber"
|
name="phoneNumber"
|
||||||
|
|
@ -108,14 +85,14 @@ const CreateCustomerModal = ({ showModal, handleClose, onSubmit, locale }) => {
|
||||||
autoFocus
|
autoFocus
|
||||||
label="Phone number"
|
label="Phone number"
|
||||||
/>
|
/>
|
||||||
<div className={classes.footer}>
|
<div className="flex flex-row mt-auto mb-6">
|
||||||
{getErrorMsg(errors, touched) && (
|
{getErrorMsg(errors, touched) && (
|
||||||
<ErrorMessage>{getErrorMsg(errors, touched)}</ErrorMessage>
|
<ErrorMessage>{getErrorMsg(errors, touched)}</ErrorMessage>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
form="customer-registration-form"
|
form="customer-registration-form"
|
||||||
className={classes.submit}>
|
className="ml-auto">
|
||||||
Finish
|
Finish
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
import { useMutation, gql } from "@apollo/client";
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
|
||||||
import React, { useState } from 'react'
|
|
||||||
import Modal from 'src/components/Modal'
|
|
||||||
import { MainStatus } from 'src/components/Status'
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
THead,
|
|
||||||
Th,
|
|
||||||
Tr,
|
|
||||||
Td,
|
|
||||||
TBody
|
|
||||||
} from 'src/components/fake-table/Table'
|
|
||||||
import { H3, Label1 } from 'src/components/typography'
|
|
||||||
import AuthorizeReversedIcon from 'src/styling/icons/button/authorize/white.svg?react'
|
|
||||||
import AuthorizeIcon from 'src/styling/icons/button/authorize/zodiac.svg?react'
|
|
||||||
import RejectReversedIcon from 'src/styling/icons/button/cancel/white.svg?react'
|
|
||||||
import RejectIcon from 'src/styling/icons/button/cancel/zodiac.svg?react'
|
|
||||||
import LinkIcon from 'src/styling/icons/month arrows/right.svg?react'
|
|
||||||
|
|
||||||
import { ActionButton } from 'src/components/buttons'
|
|
||||||
import { white, disabledColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
import DetailsCard from '../../Triggers/CustomInfoRequests/DetailsCard'
|
|
||||||
const styles = {
|
|
||||||
white: {
|
|
||||||
color: white
|
|
||||||
},
|
|
||||||
actionButton: {
|
|
||||||
display: 'flex',
|
|
||||||
height: 28,
|
|
||||||
marginRight: 'auto'
|
|
||||||
},
|
|
||||||
flex: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
disabledBtn: {
|
|
||||||
backgroundColor: disabledColor,
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: disabledColor
|
|
||||||
}
|
|
||||||
},
|
|
||||||
linkIcon: {
|
|
||||||
marginTop: 12,
|
|
||||||
marginLeft: 4,
|
|
||||||
cursor: 'pointer'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SET_AUTHORIZED_REQUEST = gql`
|
|
||||||
mutation setAuthorizedCustomRequest(
|
|
||||||
$customerId: ID!
|
|
||||||
$infoRequestId: ID!
|
|
||||||
$override: String!
|
|
||||||
) {
|
|
||||||
setAuthorizedCustomRequest(
|
|
||||||
customerId: $customerId
|
|
||||||
infoRequestId: $infoRequestId
|
|
||||||
override: $override
|
|
||||||
)
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
const CustomInfoRequestsData = ({ data }) => {
|
|
||||||
const classes = useStyles()
|
|
||||||
const [toView, setToView] = useState(null)
|
|
||||||
const [setAuthorized] = useMutation(SET_AUTHORIZED_REQUEST, {
|
|
||||||
onError: () => console.error('Error while clearing notification'),
|
|
||||||
refetchQueries: () => ['customer']
|
|
||||||
})
|
|
||||||
|
|
||||||
const authorize = it =>
|
|
||||||
setAuthorized({
|
|
||||||
variables: {
|
|
||||||
customerId: it.customerId,
|
|
||||||
infoRequestId: it.customInfoRequest.id,
|
|
||||||
isAuthorized: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const reject = it =>
|
|
||||||
setAuthorized({
|
|
||||||
variables: {
|
|
||||||
customerId: it.customerId,
|
|
||||||
infoRequestId: it.customInfoRequest.id,
|
|
||||||
isAuthorized: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const getBtnClasses = (it, isAuthorize) => {
|
|
||||||
return {
|
|
||||||
[classes.actionButton]: true,
|
|
||||||
[classes.disabledBtn]:
|
|
||||||
(isAuthorize && it.approved === true) ||
|
|
||||||
(!isAuthorize && it.approved === false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuthorizeButton = it => (
|
|
||||||
<ActionButton
|
|
||||||
className={classnames(getBtnClasses(it, true))}
|
|
||||||
color="secondary"
|
|
||||||
Icon={AuthorizeIcon}
|
|
||||||
InverseIcon={AuthorizeReversedIcon}
|
|
||||||
onClick={() => authorize(it)}>
|
|
||||||
Authorize
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
|
|
||||||
const RejectButton = it => (
|
|
||||||
<ActionButton
|
|
||||||
className={classnames(getBtnClasses(it, false))}
|
|
||||||
color="secondary"
|
|
||||||
Icon={RejectIcon}
|
|
||||||
InverseIcon={RejectReversedIcon}
|
|
||||||
onClick={() => reject(it)}>
|
|
||||||
Reject
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
|
|
||||||
const getActionButtons = it => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{AuthorizeButton(it)}
|
|
||||||
{RejectButton(it)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAuthorizedStatus = it =>
|
|
||||||
it.approved === null
|
|
||||||
? { label: 'Pending', type: 'neutral' }
|
|
||||||
: it.approved === false
|
|
||||||
? { label: 'Rejected', type: 'error' }
|
|
||||||
: { label: 'Accepted', type: 'success' }
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<H3>Custom Info Requests Data</H3>
|
|
||||||
<div>
|
|
||||||
<Table>
|
|
||||||
<THead>
|
|
||||||
<Th width={250}>Custom Request Name</Th>
|
|
||||||
<Th width={500}>Custom Request Data</Th>
|
|
||||||
<Th width={200}>Status</Th>
|
|
||||||
<Th width={250} textAlign="center">
|
|
||||||
Actions
|
|
||||||
</Th>
|
|
||||||
</THead>
|
|
||||||
<TBody>
|
|
||||||
{data.map((it, idx) => (
|
|
||||||
<React.Fragment key={idx}>
|
|
||||||
<Tr>
|
|
||||||
<Td size="sm" width={250}>
|
|
||||||
<div className={classes.flex}>
|
|
||||||
<Label1>{it.customInfoRequest.customRequest.name}</Label1>
|
|
||||||
<div onClick={() => setToView(it)}>
|
|
||||||
<LinkIcon className={classes.linkIcon} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Td>
|
|
||||||
<Td size="sm" width={500}>
|
|
||||||
<div>{JSON.stringify(it.customerData.data, null, 2)}</div>
|
|
||||||
</Td>
|
|
||||||
<Td size="sm" width={200}>
|
|
||||||
<MainStatus statuses={[getAuthorizedStatus(it)]} />
|
|
||||||
</Td>
|
|
||||||
<Td size="sm" width={250}>
|
|
||||||
<div className={classes.flex}>{getActionButtons(it)}</div>
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
</TBody>
|
|
||||||
</Table>
|
|
||||||
{toView && (
|
|
||||||
<Modal
|
|
||||||
width={900}
|
|
||||||
height={400}
|
|
||||||
open={true}
|
|
||||||
handleClose={() => setToView(null)}>
|
|
||||||
<H3>Custom Information Request Details</H3>
|
|
||||||
<DetailsCard it={{ ...toView.customInfoRequest }} />
|
|
||||||
</Modal>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CustomInfoRequestsData
|
|
||||||
|
|
@ -1,19 +1,13 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
import { H2, Label1, P } from 'src/components/typography'
|
import { H2, Label1, P } from 'src/components/typography'
|
||||||
import IdIcon from 'src/styling/icons/ID/card/zodiac.svg?react'
|
import IdIcon from 'src/styling/icons/ID/card/zodiac.svg?react'
|
||||||
|
|
||||||
import mainStyles from '../CustomersList.styles'
|
|
||||||
import { getFormattedPhone, getName } from '../helper'
|
import { getFormattedPhone, getName } from '../helper'
|
||||||
|
|
||||||
import PhotosCard from './PhotosCard'
|
import PhotosCard from './PhotosCard'
|
||||||
|
|
||||||
const useStyles = makeStyles(mainStyles)
|
|
||||||
|
|
||||||
const CustomerDetails = memo(({ customer, photosData, locale, timezone }) => {
|
const CustomerDetails = memo(({ customer, photosData, locale, timezone }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const idNumber = R.path(['idCardData', 'documentNumber'])(customer)
|
const idNumber = R.path(['idCardData', 'documentNumber'])(customer)
|
||||||
const usSsn = R.path(['usSsn'])(customer)
|
const usSsn = R.path(['usSsn'])(customer)
|
||||||
const name = getName(customer)
|
const name = getName(customer)
|
||||||
|
|
@ -50,11 +44,11 @@ const CustomerDetails = memo(({ customer, photosData, locale, timezone }) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex">
|
<div className="flex gap-7">
|
||||||
<PhotosCard photosData={photosData} timezone={timezone} />
|
<PhotosCard photosData={photosData} timezone={timezone} />
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className={classes.name}>
|
<div className="flex items-center gap-2">
|
||||||
<IdIcon className={classes.idIcon} />
|
<IdIcon />
|
||||||
<H2 noMargin>
|
<H2 noMargin>
|
||||||
{name.length
|
{name.length
|
||||||
? name
|
? name
|
||||||
|
|
@ -68,7 +62,7 @@ const CustomerDetails = memo(({ customer, photosData, locale, timezone }) => {
|
||||||
<Label1
|
<Label1
|
||||||
noMargin
|
noMargin
|
||||||
key={idx}
|
key={idx}
|
||||||
className={classes.label}
|
className="mb-1 text-comet"
|
||||||
style={{ width: size }}>
|
style={{ width: size }}>
|
||||||
{header}
|
{header}
|
||||||
</Label1>
|
</Label1>
|
||||||
|
|
@ -76,11 +70,7 @@ const CustomerDetails = memo(({ customer, photosData, locale, timezone }) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{elements.map(({ size, value }, idx) => (
|
{elements.map(({ size, value }, idx) => (
|
||||||
<P
|
<P noMargin key={idx} style={{ width: size }}>
|
||||||
noMargin
|
|
||||||
key={idx}
|
|
||||||
className={classes.value}
|
|
||||||
style={{ width: size }}>
|
|
||||||
{value}
|
{value}
|
||||||
</P>
|
</P>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import CustomerDataReversedIcon from 'src/styling/icons/customer-nav/data/comet.svg?react'
|
import CustomerDataReversedIcon from 'src/styling/icons/customer-nav/data/comet.svg?react'
|
||||||
|
|
@ -10,12 +9,9 @@ import OverviewIcon from 'src/styling/icons/customer-nav/overview/white.svg?reac
|
||||||
import PhotosReversedIcon from 'src/styling/icons/customer-nav/photos/comet.svg?react'
|
import PhotosReversedIcon from 'src/styling/icons/customer-nav/photos/comet.svg?react'
|
||||||
import Photos from 'src/styling/icons/customer-nav/photos/white.svg?react'
|
import Photos from 'src/styling/icons/customer-nav/photos/white.svg?react'
|
||||||
|
|
||||||
import styles from './CustomerSidebar.styles'
|
import { P } from '/src/components/typography/index.jsx'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const CustomerSidebar = ({ isSelected, onClick }) => {
|
const CustomerSidebar = ({ isSelected, onClick }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const sideBarOptions = [
|
const sideBarOptions = [
|
||||||
{
|
{
|
||||||
code: 'overview',
|
code: 'overview',
|
||||||
|
|
@ -44,19 +40,24 @@ const CustomerSidebar = ({ isSelected, onClick }) => {
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.sidebar}>
|
<div className="flex flex-col rounded-sm w-55 bg-zircon overflow-hidden">
|
||||||
{sideBarOptions?.map(({ Icon, InverseIcon, display, code }, idx) => (
|
{sideBarOptions?.map(({ Icon, InverseIcon, display, code }, idx) => (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className={classnames({
|
className={classnames({
|
||||||
[classes.activeLink]: isSelected(code),
|
'gap-4 p-4 cursor-pointer flex items-center': true,
|
||||||
[classes.link]: true
|
'bg-comet2': isSelected(code)
|
||||||
})}
|
})}
|
||||||
onClick={() => onClick(code)}>
|
onClick={() => onClick(code)}>
|
||||||
<div className={classes.icon}>
|
{isSelected(code) ? <Icon /> : <InverseIcon />}
|
||||||
{isSelected(code) ? <Icon /> : <InverseIcon />}
|
<P
|
||||||
</div>
|
noMargin
|
||||||
{display}
|
className={classnames({
|
||||||
|
'text-comet2': true,
|
||||||
|
'text-white font-bold': isSelected(code)
|
||||||
|
})}>
|
||||||
|
{display}
|
||||||
|
</P>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import { zircon, offDarkColor, white } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { tl2, p } = typographyStyles
|
|
||||||
|
|
||||||
const sidebarColor = zircon
|
|
||||||
|
|
||||||
export default {
|
|
||||||
sidebar: {
|
|
||||||
display: 'flex',
|
|
||||||
backgroundColor: sidebarColor,
|
|
||||||
width: 219,
|
|
||||||
flexDirection: 'column',
|
|
||||||
borderRadius: 5
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
alignItems: 'center',
|
|
||||||
display: 'flex',
|
|
||||||
extend: p,
|
|
||||||
position: 'relative',
|
|
||||||
color: offDarkColor,
|
|
||||||
padding: 15,
|
|
||||||
cursor: 'pointer'
|
|
||||||
},
|
|
||||||
activeLink: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
extend: tl2,
|
|
||||||
color: white,
|
|
||||||
backgroundColor: offDarkColor,
|
|
||||||
'&:first-child': {
|
|
||||||
borderRadius: [[5, 5, 0, 0]]
|
|
||||||
},
|
|
||||||
'&:last-child': {
|
|
||||||
borderRadius: [[0, 0, 5, 5]]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
marginRight: 15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
import CardContent from '@mui/material/CardContent'
|
import CardContent from '@mui/material/CardContent'
|
||||||
import Card from '@mui/material/Card'
|
import Card from '@mui/material/Card'
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { Form, Formik, Field as FormikField } from 'formik'
|
import { Form, Formik, Field as FormikField } from 'formik'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import { useState, React, useRef } from 'react'
|
import { useState, React, useRef } from 'react'
|
||||||
// import { HelpTooltip } from 'src/components/Tooltip'
|
|
||||||
import ErrorMessage from 'src/components/ErrorMessage'
|
import ErrorMessage from 'src/components/ErrorMessage'
|
||||||
import PromptWhenDirty from 'src/components/PromptWhenDirty'
|
import PromptWhenDirty from 'src/components/PromptWhenDirty'
|
||||||
import { MainStatus } from 'src/components/Status'
|
import { MainStatus } from 'src/components/Status'
|
||||||
import { Label1, P, H3 } from 'src/components/typography'
|
import { Label1, P, H3 } from 'src/components/typography'
|
||||||
import DeleteIcon from 'src/styling/icons/action/delete/enabled.svg?react'
|
|
||||||
import DeleteReversedIcon from 'src/styling/icons/action/delete/white.svg?react'
|
|
||||||
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
|
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
|
||||||
import EditReversedIcon from 'src/styling/icons/action/edit/white.svg?react'
|
import EditReversedIcon from 'src/styling/icons/action/edit/white.svg?react'
|
||||||
import AuthorizeIcon from 'src/styling/icons/button/authorize/white.svg?react'
|
import AuthorizeIcon from 'src/styling/icons/button/authorize/white.svg?react'
|
||||||
|
|
@ -25,84 +20,34 @@ import SaveReversedIcon from 'src/styling/icons/circle buttons/save/white.svg?re
|
||||||
|
|
||||||
import { ActionButton } from 'src/components/buttons'
|
import { ActionButton } from 'src/components/buttons'
|
||||||
import {
|
import {
|
||||||
OVERRIDE_AUTHORIZED,
|
|
||||||
OVERRIDE_REJECTED,
|
OVERRIDE_REJECTED,
|
||||||
OVERRIDE_PENDING
|
OVERRIDE_PENDING
|
||||||
} from 'src/pages/Customers/components/propertyCard'
|
} from 'src/pages/Customers/components/consts'
|
||||||
import { comet } from 'src/styling/variables'
|
|
||||||
|
|
||||||
import styles from './EditableCard.styles'
|
const ReadOnlyField = ({ field, value }) => {
|
||||||
|
return (
|
||||||
const useStyles = makeStyles(styles)
|
<div className="h-12">
|
||||||
|
<Label1 noMargin className="text-comet">
|
||||||
const fieldStyles = {
|
{field.label}
|
||||||
field: {
|
</Label1>
|
||||||
position: 'relative',
|
<P noMargin className="overflow-hidden whitespace-nowrap text-ellipsis">
|
||||||
width: 280,
|
{value}
|
||||||
height: 48,
|
</P>
|
||||||
padding: [[0, 4, 4, 0]],
|
</div>
|
||||||
marginTop: 2
|
)
|
||||||
},
|
|
||||||
label: {
|
|
||||||
color: comet,
|
|
||||||
margin: [[0, 0, 0, 0]]
|
|
||||||
},
|
|
||||||
notEditing: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
'& > p:first-child': {
|
|
||||||
height: 16,
|
|
||||||
lineHeight: '16px',
|
|
||||||
transformOrigin: 'left',
|
|
||||||
paddingLeft: 0,
|
|
||||||
margin: [[3, 0, 3, 0]]
|
|
||||||
},
|
|
||||||
'& > p:last-child': {
|
|
||||||
overflow: 'hidden',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
margin: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
editing: {
|
|
||||||
'& > div': {
|
|
||||||
'& > input': {
|
|
||||||
padding: 0,
|
|
||||||
fontSize: 14
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
readOnlyLabel: {
|
|
||||||
color: comet,
|
|
||||||
margin: [[3, 0, 3, 0]]
|
|
||||||
},
|
|
||||||
readOnlyValue: {
|
|
||||||
margin: 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldUseStyles = makeStyles(fieldStyles)
|
|
||||||
|
|
||||||
const EditableField = ({ editing, field, value, size, ...props }) => {
|
const EditableField = ({ editing, field, value, size, ...props }) => {
|
||||||
const classes = fieldUseStyles()
|
if (!editing) return <ReadOnlyField field={field} value={value} />
|
||||||
const classNames = {
|
|
||||||
[classes.field]: true,
|
|
||||||
[classes.notEditing]: !editing
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames(classNames)}>
|
<div className="h-12">
|
||||||
{!editing && (
|
|
||||||
<>
|
|
||||||
<Label1 className={classes.label}>{field.label}</Label1>
|
|
||||||
<P>{value}</P>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{editing && (
|
{editing && (
|
||||||
<>
|
<>
|
||||||
<Label1 className={classes.label}>{field.label}</Label1>
|
<Label1 noMargin className="text-comet">
|
||||||
|
{field.label}
|
||||||
|
</Label1>
|
||||||
<FormikField
|
<FormikField
|
||||||
className={classes.editing}
|
inputClasses="p-0 text-sm -mt-1"
|
||||||
id={field.name}
|
id={field.name}
|
||||||
name={field.name}
|
name={field.name}
|
||||||
component={field.component}
|
component={field.component}
|
||||||
|
|
@ -116,23 +61,6 @@ const EditableField = ({ editing, field, value, size, ...props }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReadOnlyField = ({ field, value, ...props }) => {
|
|
||||||
const classes = fieldUseStyles()
|
|
||||||
const classNames = {
|
|
||||||
[classes.field]: true,
|
|
||||||
[classes.notEditing]: true
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className={classnames(classNames)}>
|
|
||||||
<Label1 className={classes.readOnlyLabel}>{field.label}</Label1>
|
|
||||||
<P className={classes.readOnlyValue}>{value}</P>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const EditableCard = ({
|
const EditableCard = ({
|
||||||
fields,
|
fields,
|
||||||
save = () => {},
|
save = () => {},
|
||||||
|
|
@ -152,8 +80,6 @@ const EditableCard = ({
|
||||||
editable,
|
editable,
|
||||||
checkAgainstSanctions
|
checkAgainstSanctions
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const formRef = useRef()
|
const formRef = useRef()
|
||||||
|
|
||||||
const [editing, setEditing] = useState(false)
|
const [editing, setEditing] = useState(false)
|
||||||
|
|
@ -162,12 +88,6 @@ const EditableCard = ({
|
||||||
|
|
||||||
const triggerInput = () => input.click()
|
const triggerInput = () => input.click()
|
||||||
|
|
||||||
const label1ClassNames = {
|
|
||||||
[classes.label1]: true,
|
|
||||||
[classes.label1Pending]: state === OVERRIDE_PENDING,
|
|
||||||
[classes.label1Rejected]: state === OVERRIDE_REJECTED,
|
|
||||||
[classes.label1Accepted]: state === OVERRIDE_AUTHORIZED
|
|
||||||
}
|
|
||||||
const authorized =
|
const authorized =
|
||||||
state === OVERRIDE_PENDING
|
state === OVERRIDE_PENDING
|
||||||
? { label: 'Pending', type: 'neutral' }
|
? { label: 'Pending', type: 'neutral' }
|
||||||
|
|
@ -176,247 +96,211 @@ const EditableCard = ({
|
||||||
: { label: 'Accepted', type: 'success' }
|
: { label: 'Accepted', type: 'success' }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Card className="rounded-xl">
|
||||||
<Card className={classes.card}>
|
<CardContent>
|
||||||
<CardContent>
|
<div className="flex justify-between h-10">
|
||||||
<div className={classes.headerWrapper}>
|
<div className="flex mb-4 gap-4">
|
||||||
<div className={classes.cardHeader}>
|
{titleIcon}
|
||||||
{titleIcon}
|
<H3 noMargin>{title}</H3>
|
||||||
<H3 className={classes.cardTitle}>{title}</H3>
|
|
||||||
{
|
|
||||||
// TODO: Enable for next release
|
|
||||||
/* <HelpTooltip width={304}></HelpTooltip> */
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{state && authorize && (
|
|
||||||
<div className={classnames(label1ClassNames)}>
|
|
||||||
<MainStatus statuses={[authorized]} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{children(formRef.current?.values ?? {})}
|
{state && authorize && <MainStatus statuses={[authorized]} />}
|
||||||
<Formik
|
</div>
|
||||||
innerRef={formRef}
|
{children(formRef.current?.values ?? {})}
|
||||||
validateOnBlur={false}
|
<Formik
|
||||||
validateOnChange={false}
|
innerRef={formRef}
|
||||||
enableReinitialize
|
validateOnBlur={false}
|
||||||
validationSchema={validationSchema}
|
validateOnChange={false}
|
||||||
initialValues={initialValues}
|
enableReinitialize
|
||||||
onSubmit={values => {
|
validationSchema={validationSchema}
|
||||||
save(values)
|
initialValues={initialValues}
|
||||||
setEditing(false)
|
onSubmit={values => {
|
||||||
}}
|
save(values)
|
||||||
onReset={() => {
|
setEditing(false)
|
||||||
setEditing(false)
|
}}
|
||||||
setError(false)
|
onReset={() => {
|
||||||
}}>
|
setEditing(false)
|
||||||
{({ setFieldValue }) => (
|
setError(false)
|
||||||
<Form>
|
}}>
|
||||||
<PromptWhenDirty />
|
{({ setFieldValue }) => (
|
||||||
<div className={classes.row}>
|
<Form>
|
||||||
<Grid container>
|
<PromptWhenDirty />
|
||||||
<Grid container direction="column" item xs={6}>
|
<div className="flex">
|
||||||
{!hasImage &&
|
<div className="flex flex-col w-1/2">
|
||||||
fields?.map((field, idx) => {
|
{!hasImage &&
|
||||||
return idx >= 0 && idx < 4 ? (
|
fields?.map((field, idx) => {
|
||||||
!field.editable ? (
|
return idx >= 0 && idx < 4 ? (
|
||||||
<ReadOnlyField
|
!field.editable ? (
|
||||||
field={field}
|
<ReadOnlyField
|
||||||
value={initialValues[field.name]}
|
field={field}
|
||||||
/>
|
value={initialValues[field.name]}
|
||||||
) : (
|
/>
|
||||||
<EditableField
|
) : (
|
||||||
field={field}
|
<EditableField
|
||||||
value={initialValues[field.name]}
|
field={field}
|
||||||
editing={editing}
|
value={initialValues[field.name]}
|
||||||
size={180}
|
editing={editing}
|
||||||
/>
|
size={180}
|
||||||
)
|
/>
|
||||||
) : null
|
)
|
||||||
})}
|
) : null
|
||||||
</Grid>
|
})}
|
||||||
<Grid container direction="column" item xs={6}>
|
|
||||||
{!hasImage &&
|
|
||||||
fields?.map((field, idx) => {
|
|
||||||
return idx >= 4 ? (
|
|
||||||
!field.editable ? (
|
|
||||||
<ReadOnlyField
|
|
||||||
field={field}
|
|
||||||
value={initialValues[field.name]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<EditableField
|
|
||||||
field={field}
|
|
||||||
value={initialValues[field.name]}
|
|
||||||
editing={editing}
|
|
||||||
size={180}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
) : null
|
|
||||||
})}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.edit}>
|
<div className="flex flex-col w-1/2">
|
||||||
{!editing && (
|
{!hasImage &&
|
||||||
<div className={classes.editButton}>
|
fields?.map((field, idx) => {
|
||||||
<div className={classes.deleteButton}>
|
return idx >= 4 ? (
|
||||||
{/*{false && (*/}
|
!field.editable ? (
|
||||||
{/* <ActionButton*/}
|
<ReadOnlyField
|
||||||
{/* color="primary"*/}
|
field={field}
|
||||||
{/* type="button"*/}
|
value={initialValues[field.name]}
|
||||||
{/* Icon={DeleteIcon}*/}
|
/>
|
||||||
{/* InverseIcon={DeleteReversedIcon}*/}
|
) : (
|
||||||
{/* onClick={() => deleteEditedData()}>*/}
|
<EditableField
|
||||||
{/* Delete*/}
|
field={field}
|
||||||
{/* </ActionButton>*/}
|
value={initialValues[field.name]}
|
||||||
{/*)}*/}
|
editing={editing}
|
||||||
{!hasAdditionalData && (
|
size={180}
|
||||||
<ActionButton
|
/>
|
||||||
color="primary"
|
)
|
||||||
type="button"
|
) : null
|
||||||
Icon={DataIcon}
|
})}
|
||||||
InverseIcon={DataReversedIcon}
|
</div>
|
||||||
onClick={() => retrieveAdditionalData()}>
|
</div>
|
||||||
Retrieve API data
|
<div className="flex justify-end mt-5 gap-2">
|
||||||
</ActionButton>
|
{!editing && (
|
||||||
)}
|
<>
|
||||||
{checkAgainstSanctions && (
|
{!hasAdditionalData && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
type="button"
|
type="button"
|
||||||
Icon={DataIcon}
|
Icon={DataIcon}
|
||||||
InverseIcon={DataReversedIcon}
|
InverseIcon={DataReversedIcon}
|
||||||
onClick={() => checkAgainstSanctions()}>
|
onClick={() => retrieveAdditionalData()}>
|
||||||
Check against OFAC sanction list
|
Retrieve API data
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
{checkAgainstSanctions && (
|
||||||
{editable && (
|
<ActionButton
|
||||||
|
color="primary"
|
||||||
|
type="button"
|
||||||
|
Icon={DataIcon}
|
||||||
|
InverseIcon={DataReversedIcon}
|
||||||
|
onClick={() => checkAgainstSanctions()}>
|
||||||
|
Check against OFAC sanction list
|
||||||
|
</ActionButton>
|
||||||
|
)}
|
||||||
|
{editable && (
|
||||||
|
<ActionButton
|
||||||
|
color="primary"
|
||||||
|
Icon={EditIcon}
|
||||||
|
InverseIcon={EditReversedIcon}
|
||||||
|
onClick={() => setEditing(true)}>
|
||||||
|
Edit
|
||||||
|
</ActionButton>
|
||||||
|
)}
|
||||||
|
{!editable &&
|
||||||
|
authorize &&
|
||||||
|
authorized.label !== 'Accepted' && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="spring"
|
||||||
Icon={EditIcon}
|
type="button"
|
||||||
InverseIcon={EditReversedIcon}
|
Icon={AuthorizeIcon}
|
||||||
onClick={() => setEditing(true)}>
|
InverseIcon={AuthorizeIcon}
|
||||||
Edit
|
onClick={() => authorize()}>
|
||||||
|
Authorize
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
)}
|
)}
|
||||||
{!editable &&
|
{!editable &&
|
||||||
authorize &&
|
authorize &&
|
||||||
authorized.label !== 'Accepted' && (
|
authorized.label !== 'Rejected' && (
|
||||||
<div className={classes.button}>
|
<ActionButton
|
||||||
<ActionButton
|
color="tomato"
|
||||||
color="spring"
|
type="button"
|
||||||
type="button"
|
Icon={BlockIcon}
|
||||||
Icon={AuthorizeIcon}
|
InverseIcon={BlockIcon}
|
||||||
InverseIcon={AuthorizeIcon}
|
onClick={() => reject()}>
|
||||||
onClick={() => authorize()}>
|
Reject
|
||||||
Authorize
|
</ActionButton>
|
||||||
</ActionButton>
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{editing && (
|
||||||
|
<>
|
||||||
|
{hasImage && state !== OVERRIDE_PENDING && (
|
||||||
|
<ActionButton
|
||||||
|
color="secondary"
|
||||||
|
type="button"
|
||||||
|
Icon={ReplaceReversedIcon}
|
||||||
|
InverseIcon={ReplaceReversedIcon}
|
||||||
|
onClick={() => triggerInput()}>
|
||||||
|
{
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
alt=""
|
||||||
|
accept="image/*"
|
||||||
|
className="hidden"
|
||||||
|
ref={fileInput => setInput(fileInput)}
|
||||||
|
onChange={event => {
|
||||||
|
// need to store it locally if we want to display it even after saving to db
|
||||||
|
const file = R.head(event.target.files)
|
||||||
|
if (!file) return
|
||||||
|
setFieldValue(R.head(fields).name, file)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Replace
|
||||||
</div>
|
</div>
|
||||||
)}
|
}
|
||||||
{!editable &&
|
</ActionButton>
|
||||||
authorize &&
|
)}
|
||||||
authorized.label !== 'Rejected' && (
|
{fields && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="tomato"
|
color="secondary"
|
||||||
type="button"
|
Icon={SaveReversedIcon}
|
||||||
Icon={BlockIcon}
|
InverseIcon={SaveReversedIcon}
|
||||||
InverseIcon={BlockIcon}
|
type="submit">
|
||||||
onClick={() => reject()}>
|
Save
|
||||||
Reject
|
</ActionButton>
|
||||||
</ActionButton>
|
)}
|
||||||
)}
|
<ActionButton
|
||||||
</div>
|
color="secondary"
|
||||||
)}
|
Icon={CancelReversedIcon}
|
||||||
{editing && (
|
InverseIcon={CancelReversedIcon}
|
||||||
<div className={classes.editingWrapper}>
|
onClick={() => cancel()}
|
||||||
<div className={classes.replace}>
|
type="reset">
|
||||||
{hasImage && state !== OVERRIDE_PENDING && (
|
Cancel
|
||||||
<ActionButton
|
</ActionButton>
|
||||||
color="secondary"
|
{authorize && authorized.label !== 'Accepted' && (
|
||||||
type="button"
|
<ActionButton
|
||||||
Icon={ReplaceReversedIcon}
|
color="spring"
|
||||||
InverseIcon={ReplaceReversedIcon}
|
type="button"
|
||||||
onClick={() => triggerInput()}>
|
Icon={AuthorizeIcon}
|
||||||
{
|
InverseIcon={AuthorizeIcon}
|
||||||
<div>
|
onClick={() => authorize()}>
|
||||||
<input
|
Authorize
|
||||||
type="file"
|
</ActionButton>
|
||||||
alt=""
|
)}
|
||||||
accept="image/*"
|
{authorize && authorized.label !== 'Rejected' && (
|
||||||
className={classes.input}
|
<ActionButton
|
||||||
ref={fileInput => setInput(fileInput)}
|
color="tomato"
|
||||||
onChange={event => {
|
type="button"
|
||||||
// need to store it locally if we want to display it even after saving to db
|
Icon={BlockIcon}
|
||||||
const file = R.head(event.target.files)
|
InverseIcon={BlockIcon}
|
||||||
if (!file) return
|
onClick={() => reject()}>
|
||||||
setFieldValue(R.head(fields).name, file)
|
Reject
|
||||||
}}
|
</ActionButton>
|
||||||
/>
|
)}
|
||||||
Replace
|
{error && (
|
||||||
</div>
|
<ErrorMessage>Failed to save changes</ErrorMessage>
|
||||||
}
|
)}
|
||||||
</ActionButton>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.editingButtons}>
|
</Form>
|
||||||
{fields && (
|
)}
|
||||||
<div className={classes.button}>
|
</Formik>
|
||||||
<ActionButton
|
</CardContent>
|
||||||
color="secondary"
|
</Card>
|
||||||
Icon={SaveReversedIcon}
|
|
||||||
InverseIcon={SaveReversedIcon}
|
|
||||||
type="submit">
|
|
||||||
Save
|
|
||||||
</ActionButton>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className={classes.button}>
|
|
||||||
<ActionButton
|
|
||||||
color="secondary"
|
|
||||||
Icon={CancelReversedIcon}
|
|
||||||
InverseIcon={CancelReversedIcon}
|
|
||||||
onClick={() => cancel()}
|
|
||||||
type="reset">
|
|
||||||
Cancel
|
|
||||||
</ActionButton>
|
|
||||||
</div>
|
|
||||||
{authorize && authorized.label !== 'Accepted' && (
|
|
||||||
<div className={classes.button}>
|
|
||||||
<ActionButton
|
|
||||||
color="spring"
|
|
||||||
type="button"
|
|
||||||
Icon={AuthorizeIcon}
|
|
||||||
InverseIcon={AuthorizeIcon}
|
|
||||||
onClick={() => authorize()}>
|
|
||||||
Authorize
|
|
||||||
</ActionButton>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{authorize && authorized.label !== 'Rejected' && (
|
|
||||||
<ActionButton
|
|
||||||
color="tomato"
|
|
||||||
type="button"
|
|
||||||
Icon={BlockIcon}
|
|
||||||
InverseIcon={BlockIcon}
|
|
||||||
onClick={() => reject()}>
|
|
||||||
Reject
|
|
||||||
</ActionButton>
|
|
||||||
)}
|
|
||||||
{error && (
|
|
||||||
<ErrorMessage>Failed to save changes</ErrorMessage>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
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: 20,
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'right'
|
|
||||||
},
|
|
||||||
deleteButton: {
|
|
||||||
marginRight: 8
|
|
||||||
},
|
|
||||||
headerWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
height: 40
|
|
||||||
},
|
|
||||||
editingWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
marginTop: 20
|
|
||||||
},
|
|
||||||
replace: {
|
|
||||||
marginRight: 5
|
|
||||||
},
|
|
||||||
input: {
|
|
||||||
display: 'none'
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
marginRight: 5
|
|
||||||
},
|
|
||||||
editingButtons: {
|
|
||||||
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,38 +0,0 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
|
||||||
import React, { memo } from 'react'
|
|
||||||
import { Info3, Label1 } from 'src/components/typography'
|
|
||||||
|
|
||||||
import { comet } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
field: {
|
|
||||||
height: 46
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
color: comet,
|
|
||||||
margin: [[0, 3]]
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
margin: 0,
|
|
||||||
paddingLeft: 4
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const Field = memo(({ label, display, size, className }) => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classnames(classes.field, className)}
|
|
||||||
style={{ width: size }}>
|
|
||||||
<Label1 className={classes.label}>{label}</Label1>
|
|
||||||
<Info3 className={classes.value}>{display}</Info3>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default Field
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
import Paper from '@mui/material/Paper'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import React, { memo } from 'react'
|
|
||||||
import CrossedCameraIcon from 'src/styling/icons/ID/photo/crossed-camera.svg?react'
|
|
||||||
|
|
||||||
import mainStyles from '../CustomersList.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(mainStyles)
|
|
||||||
|
|
||||||
const FrontCameraPhoto = memo(({ frontCameraPath }) => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper className={classes.photo} elevation={0}>
|
|
||||||
{frontCameraPath ? (
|
|
||||||
<img
|
|
||||||
className={classes.img}
|
|
||||||
src={`/front-camera-photo/${frontCameraPath}`}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<CrossedCameraIcon />
|
|
||||||
)}
|
|
||||||
</Paper>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default FrontCameraPhoto
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
|
||||||
import React, { memo } from 'react'
|
|
||||||
import CrossedCameraIcon from 'src/styling/icons/ID/photo/crossed-camera.svg?react'
|
|
||||||
|
|
||||||
import {
|
|
||||||
PropertyCard,
|
|
||||||
OVERRIDE_AUTHORIZED,
|
|
||||||
OVERRIDE_REJECTED
|
|
||||||
} from 'src/pages/Customers/components/propertyCard'
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
idCardPhotoCard: {
|
|
||||||
width: 325,
|
|
||||||
height: 240,
|
|
||||||
margin: [[32, 0, 0, 0]]
|
|
||||||
},
|
|
||||||
idCardPhoto: {
|
|
||||||
maxHeight: 130
|
|
||||||
},
|
|
||||||
field: {
|
|
||||||
marginLeft: 14
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const IdCardPhotoCard = memo(({ customerData, updateCustomer }) => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PropertyCard
|
|
||||||
title={'ID card image'}
|
|
||||||
state={R.path(['idCardPhotoOverride'])(customerData)}
|
|
||||||
authorize={() =>
|
|
||||||
updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED })
|
|
||||||
}
|
|
||||||
reject={() => updateCustomer({ idCardPhotoOverride: OVERRIDE_REJECTED })}>
|
|
||||||
<div className="flex flex-1 justify-center items-center">
|
|
||||||
{customerData.idCardPhotoPath ? (
|
|
||||||
<img
|
|
||||||
className={classes.idCardPhoto}
|
|
||||||
src={`/id-card-photo/${R.path(['idCardPhotoPath'])(customerData)}`}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<CrossedCameraIcon />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</PropertyCard>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default IdCardPhotoCard
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
import { differenceInYears, format, parse } from 'date-fns/fp'
|
|
||||||
import * as R from 'ramda'
|
|
||||||
import React, { memo } from 'react'
|
|
||||||
|
|
||||||
import {
|
|
||||||
PropertyCard,
|
|
||||||
OVERRIDE_AUTHORIZED,
|
|
||||||
OVERRIDE_REJECTED
|
|
||||||
} from 'src/pages/Customers/components/propertyCard'
|
|
||||||
import { ifNotNull } from 'src/utils/nullCheck'
|
|
||||||
|
|
||||||
import { getName } from '../helper'
|
|
||||||
|
|
||||||
import Field from './Field'
|
|
||||||
|
|
||||||
const IdDataCard = memo(({ customerData, updateCustomer }) => {
|
|
||||||
const idData = R.path(['idCardData'])(customerData)
|
|
||||||
const rawExpirationDate = R.path(['expirationDate'])(idData)
|
|
||||||
const country = R.path(['country'])(idData)
|
|
||||||
const rawDob = R.path(['dateOfBirth'])(idData)
|
|
||||||
|
|
||||||
const elements = [
|
|
||||||
{
|
|
||||||
header: 'Name',
|
|
||||||
display: `${getName(customerData)}`,
|
|
||||||
size: 190
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'ID number',
|
|
||||||
display: R.path(['documentNumber'])(idData),
|
|
||||||
size: 160
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Birth date',
|
|
||||||
display:
|
|
||||||
(rawDob &&
|
|
||||||
format('yyyy-MM-dd')(parse(new Date(), 'yyyyMMdd', rawDob))) ??
|
|
||||||
'',
|
|
||||||
size: 110
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Age',
|
|
||||||
display:
|
|
||||||
(rawDob &&
|
|
||||||
differenceInYears(
|
|
||||||
parse(new Date(), 'yyyyMMdd', rawDob),
|
|
||||||
new Date()
|
|
||||||
)) ??
|
|
||||||
'',
|
|
||||||
size: 50
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Gender',
|
|
||||||
display: R.path(['gender'])(idData) ?? R.path(['sex'])(idData),
|
|
||||||
size: 80
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: country === 'Canada' ? 'Province' : 'State',
|
|
||||||
display: R.path(['state'])(idData),
|
|
||||||
size: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Expiration date',
|
|
||||||
display: ifNotNull(
|
|
||||||
rawExpirationDate,
|
|
||||||
format('yyyy-MM-dd', rawExpirationDate)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PropertyCard
|
|
||||||
title={'ID data'}
|
|
||||||
state={R.path(['idCardDataOverride'])(customerData)}
|
|
||||||
authorize={() =>
|
|
||||||
updateCustomer({ idCardDataOverride: OVERRIDE_AUTHORIZED })
|
|
||||||
}
|
|
||||||
reject={() => updateCustomer({ idCardDataOverride: OVERRIDE_REJECTED })}>
|
|
||||||
<div className="flex items-center">
|
|
||||||
{elements.map(({ header, display, size }, idx) => (
|
|
||||||
<Field key={idx} label={header} display={display} size={size} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</PropertyCard>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default IdDataCard
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
import { parsePhoneNumberFromString } from 'libphonenumber-js'
|
|
||||||
import * as R from 'ramda'
|
|
||||||
import React, { memo } from 'react'
|
|
||||||
|
|
||||||
import {
|
|
||||||
PropertyCard,
|
|
||||||
OVERRIDE_AUTHORIZED,
|
|
||||||
OVERRIDE_REJECTED
|
|
||||||
} from 'src/pages/Customers/components/propertyCard'
|
|
||||||
|
|
||||||
import Field from './Field'
|
|
||||||
|
|
||||||
const PhoneCard = memo(
|
|
||||||
({ className, customerData, updateCustomer, locale }) => (
|
|
||||||
<PropertyCard
|
|
||||||
className={className}
|
|
||||||
title={'Phone nº'}
|
|
||||||
state={R.path(['smsOverride'])(customerData)}
|
|
||||||
authorize={() => updateCustomer({ smsOverride: OVERRIDE_AUTHORIZED })}
|
|
||||||
reject={() => updateCustomer({ smsOverride: OVERRIDE_REJECTED })}>
|
|
||||||
<Field
|
|
||||||
label={'Phone'}
|
|
||||||
display={
|
|
||||||
customerData.phone && locale.country
|
|
||||||
? parsePhoneNumberFromString(
|
|
||||||
customerData.phone,
|
|
||||||
locale.country
|
|
||||||
).formatInternational()
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</PropertyCard>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
export default PhoneCard
|
|
||||||
|
|
@ -1,20 +1,14 @@
|
||||||
import ButtonBase from '@mui/material/ButtonBase'
|
import ButtonBase from '@mui/material/ButtonBase'
|
||||||
import Paper from '@mui/material/Card'
|
import Paper from '@mui/material/Card'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { memo, useState } from 'react'
|
import React, { memo, useState } from 'react'
|
||||||
import { InformativeDialog } from 'src/components/InformativeDialog'
|
import { InformativeDialog } from 'src/components/InformativeDialog'
|
||||||
import { Info2 } from 'src/components/typography'
|
import { Info2 } from 'src/components/typography'
|
||||||
import CrossedCameraIcon from 'src/styling/icons/ID/photo/crossed-camera.svg?react'
|
import CrossedCameraIcon from 'src/styling/icons/ID/photo/crossed-camera.svg?react'
|
||||||
|
|
||||||
import styles from './PhotosCard.styles'
|
|
||||||
import PhotosCarousel from './PhotosCarousel'
|
import PhotosCarousel from './PhotosCarousel'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const PhotosCard = memo(({ photosData, timezone }) => {
|
const PhotosCard = memo(({ photosData, timezone }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const [photosDialog, setPhotosDialog] = useState(false)
|
const [photosDialog, setPhotosDialog] = useState(false)
|
||||||
|
|
||||||
const sortedPhotosData = R.sortWith(
|
const sortedPhotosData = R.sortWith(
|
||||||
|
|
@ -26,24 +20,24 @@ const PhotosCard = memo(({ photosData, timezone }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Paper className={classes.photo} elevation={0}>
|
<Paper
|
||||||
|
className="flex justify-center items-center bg-zircon rounded-lg h-34 w-34"
|
||||||
|
elevation={0}>
|
||||||
<ButtonBase
|
<ButtonBase
|
||||||
disabled={!singlePhoto}
|
disabled={!singlePhoto}
|
||||||
className={classes.button}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPhotosDialog(true)
|
setPhotosDialog(true)
|
||||||
}}>
|
}}>
|
||||||
{singlePhoto ? (
|
{singlePhoto ? (
|
||||||
<div className={classes.container}>
|
<div>
|
||||||
<img
|
<img
|
||||||
className={classes.img}
|
className="w-34 h-34 object-center object-cover block"
|
||||||
src={`/${singlePhoto.photoDir}/${singlePhoto.path}`}
|
src={`/${singlePhoto.photoDir}/${singlePhoto.path}`}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<circle className={classes.circle}>
|
<div className=""></div>
|
||||||
<div>
|
<circle className="absolute top-0 right-0 mr-1 mt-1 bg-ghost rounded-full w-6 h-6 flex items-center justify-center">
|
||||||
<Info2>{sortedPhotosData.length}</Info2>
|
<Info2>{sortedPhotosData.length}</Info2>
|
||||||
</div>
|
|
||||||
</circle>
|
</circle>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
import { zircon, backgroundColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
photo: {
|
|
||||||
width: 135,
|
|
||||||
height: 135,
|
|
||||||
borderRadius: 8,
|
|
||||||
backgroundColor: zircon,
|
|
||||||
margin: [[0, 28, 0, 0]],
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
img: {
|
|
||||||
objectFit: 'cover',
|
|
||||||
objectPosition: 'center',
|
|
||||||
width: 135,
|
|
||||||
height: 135
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
position: 'relative',
|
|
||||||
'& > img': {
|
|
||||||
display: 'block'
|
|
||||||
},
|
|
||||||
'& > circle': {
|
|
||||||
position: 'absolute',
|
|
||||||
top: '0',
|
|
||||||
right: '0',
|
|
||||||
marginRight: 5,
|
|
||||||
marginTop: 5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
circle: {
|
|
||||||
background: backgroundColor,
|
|
||||||
borderRadius: '50%',
|
|
||||||
width: 25,
|
|
||||||
height: 25,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
display: 'flex'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { memo, useState } from 'react'
|
import React, { memo, useState } from 'react'
|
||||||
import { Carousel } from 'src/components/Carousel'
|
import { Carousel } from 'src/components/Carousel'
|
||||||
|
|
@ -8,35 +7,34 @@ import { formatDate } from 'src/utils/timezones'
|
||||||
|
|
||||||
import CopyToClipboard from '../../Transactions/CopyToClipboard'
|
import CopyToClipboard from '../../Transactions/CopyToClipboard'
|
||||||
|
|
||||||
import styles from './PhotosCarousel.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const PhotosCarousel = memo(({ photosData, timezone }) => {
|
const PhotosCarousel = memo(({ photosData, timezone }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const [currentIndex, setCurrentIndex] = useState(0)
|
const [currentIndex, setCurrentIndex] = useState(0)
|
||||||
|
|
||||||
const Label = ({ children }) => {
|
const Label = ({ children }) => {
|
||||||
const classes = useStyles()
|
return (
|
||||||
return <Label1 className={classes.label}>{children}</Label1>
|
<Label1 noMargin className="mb-1 text-comet">
|
||||||
|
{children}
|
||||||
|
</Label1>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isFaceCustomerPhoto = !R.has('id')(photosData[currentIndex])
|
const isFaceCustomerPhoto = !R.has('id')(photosData[currentIndex])
|
||||||
|
|
||||||
const slidePhoto = index => setCurrentIndex(index)
|
const slidePhoto = index => setCurrentIndex(index)
|
||||||
|
|
||||||
|
// TODO hide copy to clipboard shit
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Carousel photosData={photosData} slidePhoto={slidePhoto} />
|
<Carousel photosData={photosData} slidePhoto={slidePhoto} />
|
||||||
{!isFaceCustomerPhoto && (
|
{!isFaceCustomerPhoto && (
|
||||||
<div className={classes.firstRow}>
|
<div className="flex flex-col p-2">
|
||||||
<Label>Session ID</Label>
|
<Label>Session ID</Label>
|
||||||
<CopyToClipboard>
|
<CopyToClipboard>
|
||||||
{photosData && photosData[currentIndex]?.id}
|
{photosData && photosData[currentIndex]?.id}
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={classes.secondRow}>
|
<div className="text-zodiac flex p-2 gap-8">
|
||||||
<div>
|
<div>
|
||||||
<>
|
<>
|
||||||
<Label>Date</Label>
|
<Label>Date</Label>
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import { offColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { p } = typographyStyles
|
|
||||||
|
|
||||||
export default {
|
|
||||||
label: {
|
|
||||||
color: offColor,
|
|
||||||
margin: [[0, 0, 6, 0]]
|
|
||||||
},
|
|
||||||
firstRow: {
|
|
||||||
padding: [[8]],
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column'
|
|
||||||
},
|
|
||||||
secondRow: {
|
|
||||||
extend: p,
|
|
||||||
display: 'flex',
|
|
||||||
padding: [[8]],
|
|
||||||
'& > div': {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
'& > div': {
|
|
||||||
height: 37,
|
|
||||||
marginBottom: 15,
|
|
||||||
marginRight: 55
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import { toUnit } from '@lamassu/coins/lightUtils'
|
import { toUnit } from '@lamassu/coins/lightUtils'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import classnames from 'classnames'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import DataTable from 'src/components/tables/DataTable'
|
import DataTable from 'src/components/tables/DataTable'
|
||||||
|
|
@ -13,21 +11,13 @@ import { ifNotNull } from 'src/utils/nullCheck'
|
||||||
import { formatDate } from 'src/utils/timezones'
|
import { formatDate } from 'src/utils/timezones'
|
||||||
|
|
||||||
import CopyToClipboard from '../../Transactions/CopyToClipboard'
|
import CopyToClipboard from '../../Transactions/CopyToClipboard'
|
||||||
import mainStyles from '../CustomersList.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(mainStyles)
|
|
||||||
|
|
||||||
const TransactionsList = ({ customer, data, loading }) => {
|
const TransactionsList = ({ customer, data, loading }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const LastTxIcon = customer.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon
|
const LastTxIcon = customer.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon
|
||||||
const hasData = !(R.isEmpty(data) || R.isNil(data))
|
const hasData = !(R.isEmpty(data) || R.isNil(data))
|
||||||
const { lastUsedMachineName } = customer
|
const { lastUsedMachineName } = customer
|
||||||
|
|
||||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
const tableSpacingClasses = {
|
|
||||||
[classes.titleAndButtonsContainer]: loading || (!loading && !hasData),
|
|
||||||
[classes.txTableSpacing]: !loading && hasData
|
|
||||||
}
|
|
||||||
|
|
||||||
const summaryElements = [
|
const summaryElements = [
|
||||||
{
|
{
|
||||||
|
|
@ -61,7 +51,7 @@ const TransactionsList = ({ customer, data, loading }) => {
|
||||||
value: ifNotNull(
|
value: ifNotNull(
|
||||||
customer.lastTxFiat,
|
customer.lastTxFiat,
|
||||||
<>
|
<>
|
||||||
<LastTxIcon className={classes.icon} />
|
<LastTxIcon className="mr-3" />
|
||||||
{`${Number.parseFloat(customer.lastTxFiat)}
|
{`${Number.parseFloat(customer.lastTxFiat)}
|
||||||
${customer.lastTxFiatCode}`}
|
${customer.lastTxFiatCode}`}
|
||||||
</>
|
</>
|
||||||
|
|
@ -80,9 +70,9 @@ const TransactionsList = ({ customer, data, loading }) => {
|
||||||
view: it => (
|
view: it => (
|
||||||
<>
|
<>
|
||||||
{it.txClass === 'cashOut' ? (
|
{it.txClass === 'cashOut' ? (
|
||||||
<TxOutIcon className={classes.txClassIconLeft} />
|
<TxOutIcon className="mr-3" />
|
||||||
) : (
|
) : (
|
||||||
<TxInIcon className={classes.txClassIconLeft} />
|
<TxInIcon className="mr-3" />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
@ -96,7 +86,9 @@ const TransactionsList = ({ customer, data, loading }) => {
|
||||||
header: 'Transaction ID',
|
header: 'Transaction ID',
|
||||||
width: 145,
|
width: 145,
|
||||||
view: it => (
|
view: it => (
|
||||||
<CopyToClipboard className={classes.txId}>{it.id}</CopyToClipboard>
|
<CopyToClipboard className="font-museo whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
|
{it.id}
|
||||||
|
</CopyToClipboard>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -144,7 +136,7 @@ const TransactionsList = ({ customer, data, loading }) => {
|
||||||
<Label1
|
<Label1
|
||||||
noMargin
|
noMargin
|
||||||
key={idx}
|
key={idx}
|
||||||
className={classes.txSummaryLabel}
|
className="text-comet mb-1 mr-6"
|
||||||
style={{ width: size }}>
|
style={{ width: size }}>
|
||||||
{header}
|
{header}
|
||||||
</Label1>
|
</Label1>
|
||||||
|
|
@ -152,28 +144,21 @@ const TransactionsList = ({ customer, data, loading }) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{summaryElements.map(({ size, value }, idx) => (
|
{summaryElements.map(({ size, value }, idx) => (
|
||||||
<P
|
<P noMargin key={idx} className="h-4 mr-6" style={{ width: size }}>
|
||||||
noMargin
|
|
||||||
key={idx}
|
|
||||||
className={classes.txSummaryValue}
|
|
||||||
style={{ width: size }}>
|
|
||||||
{value}
|
{value}
|
||||||
</P>
|
</P>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.titleWrapper}>
|
<div className="flex mt-5">
|
||||||
<div className={classnames(tableSpacingClasses)}>
|
{loading ? (
|
||||||
{loading ? (
|
<H4>Loading</H4>
|
||||||
<H4>Loading</H4>
|
) : hasData ? (
|
||||||
) : hasData ? (
|
<DataTable elements={tableElements} data={data} />
|
||||||
''
|
) : (
|
||||||
) : (
|
<H4>No transactions so far</H4>
|
||||||
<H4>No transactions so far</H4>
|
)}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{hasData && <DataTable elements={tableElements} data={data} />}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { useFormikContext } from 'formik'
|
import { useFormikContext } from 'formik'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState, useCallback } from 'react'
|
import React, { useState, useCallback } from 'react'
|
||||||
|
|
@ -7,42 +6,9 @@ import { Label3, H3 } from 'src/components/typography'
|
||||||
import UploadPhotoIcon from 'src/styling/icons/button/photo/zodiac-resized.svg?react'
|
import UploadPhotoIcon from 'src/styling/icons/button/photo/zodiac-resized.svg?react'
|
||||||
import UploadFileIcon from 'src/styling/icons/button/upload-file/zodiac-resized.svg?react'
|
import UploadFileIcon from 'src/styling/icons/button/upload-file/zodiac-resized.svg?react'
|
||||||
|
|
||||||
import { offColor, subheaderColor } from 'src/styling/variables'
|
import classes from './Upload.module.css'
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
box: {
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
width: 450,
|
|
||||||
height: 120,
|
|
||||||
borderStyle: 'dashed',
|
|
||||||
borderColor: offColor,
|
|
||||||
borderRadius: 4,
|
|
||||||
borderWidth: 1,
|
|
||||||
backgroundColor: subheaderColor,
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center'
|
|
||||||
},
|
|
||||||
inputContent: {
|
|
||||||
marginTop: 35,
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
uploadContent: {
|
|
||||||
marginTop: 50,
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
board: {
|
|
||||||
marginTop: 40,
|
|
||||||
width: 450,
|
|
||||||
height: 120
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
margin: [[14, 20, 0, 0]]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const Upload = ({ type }) => {
|
const Upload = ({ type }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const [data, setData] = useState({})
|
const [data, setData] = useState({})
|
||||||
|
|
||||||
const { setFieldValue } = useFormikContext()
|
const { setFieldValue } = useFormikContext()
|
||||||
|
|
@ -71,20 +37,14 @@ const Upload = ({ type }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div {...getRootProps()} className={classes.board}>
|
<div {...getRootProps()} className="mt-10 w-112 h-30">
|
||||||
{R.isEmpty(data) && (
|
{R.isEmpty(data) && (
|
||||||
<div className={classes.box}>
|
<div className={classes.box}>
|
||||||
<input {...getInputProps()} />
|
<input {...getInputProps()} />
|
||||||
<div className={classes.inputContent}>
|
{isImage ? <UploadPhotoIcon /> : <UploadFileIcon />}
|
||||||
{isImage ? (
|
<Label3>{`Drag and drop ${
|
||||||
<UploadPhotoIcon className={classes.icon}></UploadPhotoIcon>
|
isImage ? 'an image' : 'a file'
|
||||||
) : (
|
} or click to open the explorer`}</Label3>
|
||||||
<UploadFileIcon className={classes.icon}></UploadFileIcon>
|
|
||||||
)}
|
|
||||||
<Label3>{`Drag and drop ${
|
|
||||||
isImage ? 'an image' : 'a file'
|
|
||||||
} or click to open the explorer`}</Label3>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!R.isEmpty(data) && isImage && (
|
{!R.isEmpty(data) && isImage && (
|
||||||
|
|
@ -94,7 +54,7 @@ const Upload = ({ type }) => {
|
||||||
)}
|
)}
|
||||||
{!R.isEmpty(data) && !isImage && (
|
{!R.isEmpty(data) && !isImage && (
|
||||||
<div className={classes.box}>
|
<div className={classes.box}>
|
||||||
<H3 className={classes.uploadContent}>{data.preview}</H3>
|
<H3 className="mt-12 flex">{data.preview}</H3>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
.box {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 450px;
|
||||||
|
height: 120px;
|
||||||
|
border-style: dashed;
|
||||||
|
border-color: var(--comet);
|
||||||
|
border-radius: 4px;
|
||||||
|
border-width: 1px;
|
||||||
|
background-color: var(--zircon);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
const OVERRIDE_PENDING = 'automatic'
|
||||||
|
const OVERRIDE_AUTHORIZED = 'verified'
|
||||||
|
const OVERRIDE_REJECTED = 'blocked'
|
||||||
|
|
||||||
|
export { OVERRIDE_PENDING, OVERRIDE_AUTHORIZED, OVERRIDE_REJECTED }
|
||||||
|
|
@ -3,19 +3,13 @@ import Wizard from '../Wizard'
|
||||||
import CustomerDetails from './CustomerDetails'
|
import CustomerDetails from './CustomerDetails'
|
||||||
import CustomerSidebar from './CustomerSidebar'
|
import CustomerSidebar from './CustomerSidebar'
|
||||||
import EditableCard from './EditableCard'
|
import EditableCard from './EditableCard'
|
||||||
import Field from './Field'
|
|
||||||
import IdDataCard from './IdDataCard'
|
|
||||||
import PhotosCarousel from './PhotosCarousel'
|
|
||||||
import TransactionsList from './TransactionsList'
|
import TransactionsList from './TransactionsList'
|
||||||
import Upload from './Upload'
|
import Upload from './Upload'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
PhotosCarousel,
|
|
||||||
CustomerDetails,
|
CustomerDetails,
|
||||||
IdDataCard,
|
|
||||||
TransactionsList,
|
TransactionsList,
|
||||||
CustomerSidebar,
|
CustomerSidebar,
|
||||||
Field,
|
|
||||||
EditableCard,
|
EditableCard,
|
||||||
Wizard,
|
Wizard,
|
||||||
Upload
|
Upload
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,16 @@
|
||||||
import Paper from '@mui/material/Paper'
|
import Paper from '@mui/material/Paper'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classNames from 'classnames'
|
|
||||||
import { React } from 'react'
|
import { React } from 'react'
|
||||||
import { P } from 'src/components/typography'
|
import { P } from 'src/components/typography'
|
||||||
import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react'
|
import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react'
|
||||||
|
|
||||||
import styles from './NoteCard.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const NewNoteCard = ({ setOpenModal }) => {
|
const NewNoteCard = ({ setOpenModal }) => {
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.noteCardWrapper} onClick={() => setOpenModal(true)}>
|
<Paper
|
||||||
<Paper className={classNames(classes.noteCardChip, classes.newNoteCard)}>
|
className="cursor-pointer bg-zircon flex flex-col justify-center items-center"
|
||||||
<AddIcon width={20} height={20} />
|
onClick={() => setOpenModal(true)}>
|
||||||
<P>Add new</P>
|
<AddIcon width={20} height={20} />
|
||||||
</Paper>
|
<P>Add new</P>
|
||||||
</div>
|
</Paper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { Form, Formik, Field } from 'formik'
|
import { Form, Formik, Field } from 'formik'
|
||||||
import { React } from 'react'
|
import { React } from 'react'
|
||||||
import ErrorMessage from 'src/components/ErrorMessage'
|
import ErrorMessage from 'src/components/ErrorMessage'
|
||||||
|
|
@ -8,10 +7,6 @@ import * as Yup from 'yup'
|
||||||
import { Button } from 'src/components/buttons'
|
import { Button } from 'src/components/buttons'
|
||||||
import { TextInput } from 'src/components/inputs/formik'
|
import { TextInput } from 'src/components/inputs/formik'
|
||||||
|
|
||||||
import styles from './NewNoteModal.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
title: '',
|
title: '',
|
||||||
content: ''
|
content: ''
|
||||||
|
|
@ -23,8 +18,6 @@ const validationSchema = Yup.object().shape({
|
||||||
})
|
})
|
||||||
|
|
||||||
const NewNoteModal = ({ showModal, onClose, onSubmit, errorMsg }) => {
|
const NewNoteModal = ({ showModal, onClose, onSubmit, errorMsg }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
|
|
@ -42,7 +35,7 @@ const NewNoteModal = ({ showModal, onClose, onSubmit, errorMsg }) => {
|
||||||
onSubmit={({ title, content }) => {
|
onSubmit={({ title, content }) => {
|
||||||
onSubmit({ title, content })
|
onSubmit({ title, content })
|
||||||
}}>
|
}}>
|
||||||
<Form id="note-form" className={classes.form}>
|
<Form id="note-form" className="flex flex-col h-full gap-5">
|
||||||
<Field
|
<Field
|
||||||
name="title"
|
name="title"
|
||||||
autofocus
|
autofocus
|
||||||
|
|
@ -62,9 +55,12 @@ const NewNoteModal = ({ showModal, onClose, onSubmit, errorMsg }) => {
|
||||||
rows={11}
|
rows={11}
|
||||||
label="Note content"
|
label="Note content"
|
||||||
/>
|
/>
|
||||||
<div className={classes.footer}>
|
<div className="flex flex-row mt-auto mb-6">
|
||||||
{errorMsg && <ErrorMessage>{errorMsg}</ErrorMessage>}
|
{errorMsg && <ErrorMessage>{errorMsg}</ErrorMessage>}
|
||||||
<Button type="submit" form="note-form" className={classes.submit}>
|
<Button
|
||||||
|
type="submit"
|
||||||
|
form="note-form"
|
||||||
|
className="mt-auto ml-auto">
|
||||||
Add note
|
Add note
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import { spacer } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
form: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
height: '100%',
|
|
||||||
'& > *': {
|
|
||||||
marginTop: 20
|
|
||||||
},
|
|
||||||
'& > *:last-child': {
|
|
||||||
marginTop: 'auto'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
submit: {
|
|
||||||
margin: [['auto', 0, 0, 'auto']]
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
margin: [['auto', 0, spacer * 3, 0]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import Paper from '@mui/material/Paper'
|
import Paper from '@mui/material/Paper'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import { React } from 'react'
|
import { React } from 'react'
|
||||||
import { H3, P } from 'src/components/typography'
|
import { H3, P } from 'src/components/typography'
|
||||||
|
|
@ -7,10 +6,6 @@ import DeleteIcon from 'src/styling/icons/action/delete/enabled.svg?react'
|
||||||
|
|
||||||
import { formatDate } from 'src/utils/timezones'
|
import { formatDate } from 'src/utils/timezones'
|
||||||
|
|
||||||
import styles from './NoteCard.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const formatContent = content => {
|
const formatContent = content => {
|
||||||
const fragments = R.split(/\n/)(content)
|
const fragments = R.split(/\n/)(content)
|
||||||
return R.map((it, idx) => {
|
return R.map((it, idx) => {
|
||||||
|
|
@ -25,31 +20,28 @@ const formatContent = content => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const NoteCard = ({ note, deleteNote, handleClick, timezone }) => {
|
const NoteCard = ({ note, deleteNote, handleClick, timezone }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.noteCardWrapper}>
|
<Paper
|
||||||
<Paper className={classes.noteCardChip} onClick={() => handleClick(note)}>
|
className="p-2 cursor-pointer overflow-hidden text-ellipsis"
|
||||||
<div className={classes.noteCardHeader}>
|
onClick={() => handleClick(note)}>
|
||||||
<div className={classes.noteCardTitle}>
|
<div className="flex flex-row justify-between w-full">
|
||||||
<H3 noMargin>{note?.title}</H3>
|
<div className="overflow-hidden whitespace-nowrap overflow-ellipsis">
|
||||||
<P noMargin>{formatDate(note?.created, timezone, 'yyyy-MM-dd')}</P>
|
<H3 noMargin>{note?.title}</H3>
|
||||||
</div>
|
<P noMargin>{formatDate(note?.created, timezone, 'yyyy-MM-dd')}</P>
|
||||||
<div>
|
|
||||||
<DeleteIcon
|
|
||||||
className={classes.deleteIcon}
|
|
||||||
onClick={e => {
|
|
||||||
e.stopPropagation()
|
|
||||||
deleteNote({ noteId: note.id })
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<P noMargin className={classes.noteCardContent}>
|
<div>
|
||||||
{formatContent(note?.content)}
|
<DeleteIcon
|
||||||
</P>
|
onClick={e => {
|
||||||
</Paper>
|
e.stopPropagation()
|
||||||
</div>
|
deleteNote({ noteId: note.id })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<P noMargin className="mt-2 line-clamp-8">
|
||||||
|
{formatContent(note?.content)}
|
||||||
|
</P>
|
||||||
|
</Paper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
import { zircon } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
noteCardWrapper: {
|
|
||||||
flexGrow: 0,
|
|
||||||
flexShrink: 0,
|
|
||||||
flexBasis: `25%`,
|
|
||||||
minWidth: 0,
|
|
||||||
maxWidth: 500,
|
|
||||||
'&:nth-child(4n+1)': {
|
|
||||||
'& > div': {
|
|
||||||
margin: [[0, 10, 0, 0]]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'&:nth-child(4n)': {
|
|
||||||
'& > div': {
|
|
||||||
margin: [[0, 0, 0, 10]]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
margin: [[10, 0]]
|
|
||||||
},
|
|
||||||
noteCardChip: {
|
|
||||||
height: 200,
|
|
||||||
margin: [[0, 10]],
|
|
||||||
padding: [[10, 10]],
|
|
||||||
cursor: 'pointer'
|
|
||||||
},
|
|
||||||
newNoteCard: {
|
|
||||||
backgroundColor: zircon,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
noteCardHeader: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
width: '100%'
|
|
||||||
},
|
|
||||||
noteCardTitle: {
|
|
||||||
overflow: 'hidden',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
marginRight: 10
|
|
||||||
},
|
|
||||||
noteCardContent: {
|
|
||||||
display: 'box',
|
|
||||||
lineClamp: 7,
|
|
||||||
boxOrient: 'vertical',
|
|
||||||
margin: [[15, 0]],
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
wordWrap: 'break-word'
|
|
||||||
},
|
|
||||||
editCardChip: {
|
|
||||||
height: 325,
|
|
||||||
padding: 15
|
|
||||||
},
|
|
||||||
editCardHeader: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: 15
|
|
||||||
},
|
|
||||||
editCardActions: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
'& > *': {
|
|
||||||
marginRight: 10
|
|
||||||
},
|
|
||||||
'& > *:last-child': {
|
|
||||||
marginRight: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
editNotesContent: {
|
|
||||||
'& > div': {
|
|
||||||
'&:after': {
|
|
||||||
borderBottom: 'none'
|
|
||||||
},
|
|
||||||
'&:before': {
|
|
||||||
borderBottom: 'none'
|
|
||||||
},
|
|
||||||
'&:hover:not(.Mui-disabled)::before': {
|
|
||||||
borderBottom: 'none'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import Paper from '@mui/material/Paper'
|
import Paper from '@mui/material/Paper'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { formatDurationWithOptions, intervalToDuration } from 'date-fns/fp'
|
import { formatDurationWithOptions, intervalToDuration } from 'date-fns/fp'
|
||||||
import { Form, Formik, Field } from 'formik'
|
import { Form, Formik, Field } from 'formik'
|
||||||
import { React, useRef } from 'react'
|
import { React, useRef } from 'react'
|
||||||
|
|
@ -14,13 +13,8 @@ import { ActionButton } from 'src/components/buttons'
|
||||||
import { TextInput } from 'src/components/inputs/formik'
|
import { TextInput } from 'src/components/inputs/formik'
|
||||||
import { toTimezone } from 'src/utils/timezones'
|
import { toTimezone } from 'src/utils/timezones'
|
||||||
|
|
||||||
import styles from './NoteCard.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const NoteEdit = ({ note, cancel, edit, timezone }) => {
|
const NoteEdit = ({ note, cancel, edit, timezone }) => {
|
||||||
const formRef = useRef()
|
const formRef = useRef()
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
content: Yup.string()
|
content: Yup.string()
|
||||||
|
|
@ -31,8 +25,8 @@ const NoteEdit = ({ note, cancel, edit, timezone }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className={classes.editCardChip}>
|
<Paper className="p-4">
|
||||||
<div className={classes.editCardHeader}>
|
<div className="flex flex-row justify-between items-center mb-4">
|
||||||
<P noMargin>
|
<P noMargin>
|
||||||
{`Last edited `}
|
{`Last edited `}
|
||||||
{formatDurationWithOptions(
|
{formatDurationWithOptions(
|
||||||
|
|
@ -44,7 +38,7 @@ const NoteEdit = ({ note, cancel, edit, timezone }) => {
|
||||||
)}
|
)}
|
||||||
{` ago`}
|
{` ago`}
|
||||||
</P>
|
</P>
|
||||||
<div className={classes.editCardActions}>
|
<div className="flex flex-row items-center gap-2">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -88,7 +82,7 @@ const NoteEdit = ({ note, cancel, edit, timezone }) => {
|
||||||
<Field
|
<Field
|
||||||
name="content"
|
name="content"
|
||||||
component={TextInput}
|
component={TextInput}
|
||||||
className={classes.editNotesContent}
|
InputProps={{ disableUnderline: true }}
|
||||||
size="sm"
|
size="sm"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
import Paper from '@mui/material/Paper'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
|
||||||
import React, { memo } from 'react'
|
|
||||||
import { MainStatus } from 'src/components/Status'
|
|
||||||
import { H3 } from 'src/components/typography'
|
|
||||||
import AuthorizeReversedIcon from 'src/styling/icons/button/authorize/white.svg?react'
|
|
||||||
import AuthorizeIcon from 'src/styling/icons/button/authorize/zodiac.svg?react'
|
|
||||||
import RejectReversedIcon from 'src/styling/icons/button/cancel/white.svg?react'
|
|
||||||
import RejectIcon from 'src/styling/icons/button/cancel/zodiac.svg?react'
|
|
||||||
import EditReversedIcon from 'src/styling/icons/button/edit/white.svg?react'
|
|
||||||
import EditIcon from 'src/styling/icons/button/edit/zodiac.svg?react'
|
|
||||||
|
|
||||||
import { ActionButton } from 'src/components/buttons'
|
|
||||||
|
|
||||||
import { propertyCardStyles } from './PropertyCard.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(propertyCardStyles)
|
|
||||||
|
|
||||||
const OVERRIDE_PENDING = 'automatic'
|
|
||||||
const OVERRIDE_AUTHORIZED = 'verified'
|
|
||||||
const OVERRIDE_REJECTED = 'blocked'
|
|
||||||
|
|
||||||
const PropertyCard = memo(
|
|
||||||
({
|
|
||||||
className,
|
|
||||||
contentClassName,
|
|
||||||
title,
|
|
||||||
state,
|
|
||||||
authorize,
|
|
||||||
reject,
|
|
||||||
edit,
|
|
||||||
confirm,
|
|
||||||
isEditing,
|
|
||||||
formName,
|
|
||||||
children
|
|
||||||
}) => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const label1ClassNames = {
|
|
||||||
[classes.label1]: true,
|
|
||||||
[classes.label1Pending]: state === OVERRIDE_PENDING,
|
|
||||||
[classes.label1Rejected]: state === OVERRIDE_REJECTED,
|
|
||||||
[classes.label1Accepted]: state === OVERRIDE_AUTHORIZED
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuthorizeButton = () => (
|
|
||||||
<ActionButton
|
|
||||||
className={classes.cardActionButton}
|
|
||||||
color="secondary"
|
|
||||||
Icon={AuthorizeIcon}
|
|
||||||
InverseIcon={AuthorizeReversedIcon}
|
|
||||||
onClick={() => authorize()}>
|
|
||||||
Authorize
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
|
|
||||||
const RejectButton = () => (
|
|
||||||
<ActionButton
|
|
||||||
className={classes.cardActionButton}
|
|
||||||
color="secondary"
|
|
||||||
Icon={RejectIcon}
|
|
||||||
InverseIcon={RejectReversedIcon}
|
|
||||||
onClick={() => reject()}>
|
|
||||||
Reject
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
|
|
||||||
const EditButton = () => (
|
|
||||||
<ActionButton
|
|
||||||
className={classes.cardActionButton}
|
|
||||||
color="secondary"
|
|
||||||
Icon={EditIcon}
|
|
||||||
InverseIcon={EditReversedIcon}
|
|
||||||
onClick={() => edit()}>
|
|
||||||
Edit
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
|
|
||||||
const ConfirmButton = () => (
|
|
||||||
<ActionButton
|
|
||||||
className={classes.cardActionButton}
|
|
||||||
type="submit"
|
|
||||||
form={formName}
|
|
||||||
color="secondary"
|
|
||||||
Icon={AuthorizeIcon}
|
|
||||||
InverseIcon={AuthorizeReversedIcon}>
|
|
||||||
Confirm
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
|
|
||||||
const authorized =
|
|
||||||
state === OVERRIDE_PENDING
|
|
||||||
? { label: 'Pending', type: 'neutral' }
|
|
||||||
: state === OVERRIDE_REJECTED
|
|
||||||
? { label: 'Rejected', type: 'error' }
|
|
||||||
: { label: 'Accepted', type: 'success' }
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper
|
|
||||||
className={classnames(classes.propertyCard, className)}
|
|
||||||
elevation={0}>
|
|
||||||
<H3 className={classes.propertyCardTopRow}>{title}</H3>
|
|
||||||
<div
|
|
||||||
className={classnames(
|
|
||||||
classes.propertyCardBottomRow,
|
|
||||||
contentClassName
|
|
||||||
)}>
|
|
||||||
{state && (
|
|
||||||
<div className={classnames(label1ClassNames)}>
|
|
||||||
<MainStatus statuses={[authorized]} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
<div className={classes.buttonsWrapper}>
|
|
||||||
{authorize && state !== OVERRIDE_AUTHORIZED && AuthorizeButton()}
|
|
||||||
{reject && state !== OVERRIDE_REJECTED && RejectButton()}
|
|
||||||
{edit && !isEditing && EditButton()}
|
|
||||||
{confirm && isEditing && ConfirmButton()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Paper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export {
|
|
||||||
PropertyCard,
|
|
||||||
OVERRIDE_PENDING,
|
|
||||||
OVERRIDE_AUTHORIZED,
|
|
||||||
OVERRIDE_REJECTED
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
import { white, tomato, spring4, comet } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const propertyCardStyles = {
|
|
||||||
label1: {
|
|
||||||
display: 'flex',
|
|
||||||
marginBottom: 2,
|
|
||||||
marginTop: 'auto',
|
|
||||||
width: 85
|
|
||||||
},
|
|
||||||
label1Pending: {
|
|
||||||
color: comet
|
|
||||||
},
|
|
||||||
label1Rejected: {
|
|
||||||
color: tomato
|
|
||||||
},
|
|
||||||
label1Accepted: {
|
|
||||||
color: spring4
|
|
||||||
},
|
|
||||||
cardActionButton: {
|
|
||||||
display: 'flex',
|
|
||||||
height: 28,
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginLeft: 12
|
|
||||||
},
|
|
||||||
propertyCardTopRow: {
|
|
||||||
display: 'flex',
|
|
||||||
margin: [[0, 10, 5, 0]]
|
|
||||||
},
|
|
||||||
propertyCardBottomRow: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
height: 45
|
|
||||||
},
|
|
||||||
propertyCard: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
borderRadius: 8,
|
|
||||||
width: '100%',
|
|
||||||
height: 100,
|
|
||||||
padding: [[20]],
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
boxShadow: '0 0 8px 0 rgba(0, 0, 0, 0.04)',
|
|
||||||
border: 'solid 0',
|
|
||||||
backgroundColor: white,
|
|
||||||
margin: [[20, 0, 0, 0]]
|
|
||||||
},
|
|
||||||
rowSpaceBetween: {
|
|
||||||
display: 'flex',
|
|
||||||
flexFlow: 'row nowrap',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
columnSpaceBetween: {
|
|
||||||
display: 'flex',
|
|
||||||
flexFlow: 'column nowrap',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
width: 90
|
|
||||||
},
|
|
||||||
buttonsWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginTop: 'auto'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { propertyCardStyles }
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
import {
|
|
||||||
PropertyCard,
|
|
||||||
OVERRIDE_PENDING,
|
|
||||||
OVERRIDE_AUTHORIZED,
|
|
||||||
OVERRIDE_REJECTED
|
|
||||||
} from './PropertyCard'
|
|
||||||
|
|
||||||
export {
|
|
||||||
PropertyCard,
|
|
||||||
OVERRIDE_PENDING,
|
|
||||||
OVERRIDE_AUTHORIZED,
|
|
||||||
OVERRIDE_REJECTED
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
|
||||||
import { parse, isValid, format } from 'date-fns/fp'
|
import { parse, isValid, format } from 'date-fns/fp'
|
||||||
import { Field, useFormikContext } from 'formik'
|
import { Field, useFormikContext } from 'formik'
|
||||||
import { parsePhoneNumberFromString } from 'libphonenumber-js'
|
import { parsePhoneNumberFromString } from 'libphonenumber-js'
|
||||||
|
|
@ -14,45 +12,10 @@ import {
|
||||||
TextInput,
|
TextInput,
|
||||||
Autocomplete
|
Autocomplete
|
||||||
} from 'src/components/inputs/formik'
|
} from 'src/components/inputs/formik'
|
||||||
import { errorColor } from 'src/styling/variables'
|
|
||||||
import { MANUAL } from 'src/utils/constants'
|
import { MANUAL } from 'src/utils/constants'
|
||||||
|
|
||||||
import { Upload } from './components'
|
import { Upload } from './components'
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
radio: {
|
|
||||||
padding: 4,
|
|
||||||
margin: 4
|
|
||||||
},
|
|
||||||
radioGroup: {
|
|
||||||
flexDirection: 'row'
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
color: errorColor
|
|
||||||
},
|
|
||||||
specialLabel: {
|
|
||||||
height: 40,
|
|
||||||
padding: 0,
|
|
||||||
width: 250
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
height: 40,
|
|
||||||
padding: 0
|
|
||||||
},
|
|
||||||
specialGrid: {
|
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: [[182, 162, 141]]
|
|
||||||
},
|
|
||||||
picker: {
|
|
||||||
width: 150
|
|
||||||
},
|
|
||||||
field: {
|
|
||||||
'& > *:last-child': {
|
|
||||||
marginBottom: 24
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const CUSTOMER_BLOCKED = 'blocked'
|
const CUSTOMER_BLOCKED = 'blocked'
|
||||||
const CUSTOM = 'custom'
|
const CUSTOM = 'custom'
|
||||||
const REQUIREMENT = 'requirement'
|
const REQUIREMENT = 'requirement'
|
||||||
|
|
@ -215,68 +178,50 @@ const updateRequirementOptions = it => [
|
||||||
]
|
]
|
||||||
|
|
||||||
const EntryType = ({ customInfoRequirementOptions }) => {
|
const EntryType = ({ customInfoRequirementOptions }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const { values } = useFormikContext()
|
const { values } = useFormikContext()
|
||||||
|
|
||||||
const displayCustomOptions = values.entryType === CUSTOM
|
const displayCustomOptions = values.entryType === CUSTOM
|
||||||
const displayRequirementOptions = values.entryType === REQUIREMENT
|
const displayRequirementOptions = values.entryType === REQUIREMENT
|
||||||
|
|
||||||
return (
|
const Entry = ({ title, name, options, className }) => (
|
||||||
<>
|
<div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<H4>Type of entry</H4>
|
<H4>{title}</H4>
|
||||||
</div>
|
</div>
|
||||||
<Field
|
<Field
|
||||||
component={RadioGroup}
|
component={RadioGroup}
|
||||||
|
name={name}
|
||||||
|
options={options}
|
||||||
|
radioClassName="p-1 m-1"
|
||||||
|
labelClassName={className}
|
||||||
|
className="grid grid-cols-[182px_162px_141px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Entry
|
||||||
|
title="Type of entry"
|
||||||
name="entryType"
|
name="entryType"
|
||||||
options={entryOptions}
|
options={entryOptions}
|
||||||
labelClassName={classes.specialLabel}
|
className="w-62"
|
||||||
radioClassName={classes.radio}
|
|
||||||
className={classnames(classes.radioGroup, classes.specialGrid)}
|
|
||||||
/>
|
/>
|
||||||
{displayCustomOptions && (
|
{displayCustomOptions && (
|
||||||
<div>
|
<Entry title="Type of data" name="dataType" options={dataOptions} />
|
||||||
<div className="flex items-center">
|
|
||||||
<H4>Type of data</H4>
|
|
||||||
</div>
|
|
||||||
<Field
|
|
||||||
component={RadioGroup}
|
|
||||||
name="dataType"
|
|
||||||
options={dataOptions}
|
|
||||||
labelClassName={classes.label}
|
|
||||||
radioClassName={classes.radio}
|
|
||||||
className={classnames(classes.radioGroup, classes.specialGrid)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{displayRequirementOptions && (
|
{displayRequirementOptions && (
|
||||||
<div>
|
<Entry
|
||||||
<div className="flex items-center">
|
title="Requirements"
|
||||||
<H4>Requirements</H4>
|
name="requirement"
|
||||||
</div>
|
options={requirementOptions}
|
||||||
<Field
|
/>
|
||||||
component={RadioGroup}
|
|
||||||
name="requirement"
|
|
||||||
options={
|
|
||||||
requirementOptions
|
|
||||||
// TODO: Enable once custom info requirement manual entry is finished
|
|
||||||
// !R.isEmpty(customInfoRequirementOptions)
|
|
||||||
// ? updateRequirementOptions(requirementOptions)
|
|
||||||
// : requirementOptions
|
|
||||||
}
|
|
||||||
labelClassName={classes.label}
|
|
||||||
radioClassName={classes.radio}
|
|
||||||
className={classnames(classes.radioGroup, classes.specialGrid)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ManualDataEntry = ({ selectedValues, customInfoRequirementOptions }) => {
|
const ManualDataEntry = ({ selectedValues, customInfoRequirementOptions }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const typeOfEntrySelected = selectedValues?.entryType
|
const typeOfEntrySelected = selectedValues?.entryType
|
||||||
const dataTypeSelected = selectedValues?.dataType
|
const dataTypeSelected = selectedValues?.dataType
|
||||||
const requirementSelected = selectedValues?.requirement
|
const requirementSelected = selectedValues?.requirement
|
||||||
|
|
@ -316,14 +261,14 @@ const ManualDataEntry = ({ selectedValues, customInfoRequirementOptions }) => {
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
fullWidth
|
fullWidth
|
||||||
label={`Available requests`}
|
label={`Available requests`}
|
||||||
className={classes.picker}
|
className="w-37"
|
||||||
isOptionEqualToValue={R.eqProps('code')}
|
isOptionEqualToValue={R.eqProps('code')}
|
||||||
labelProp={'display'}
|
labelProp={'display'}
|
||||||
options={customInfoRequirementOptions}
|
options={customInfoRequirementOptions}
|
||||||
onChange={(evt, it) => {}}
|
onChange={(evt, it) => {}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className={classes.field}>
|
<div className="mb-6">
|
||||||
{!upload &&
|
{!upload &&
|
||||||
!isCustomInfoRequirement &&
|
!isCustomInfoRequirement &&
|
||||||
elements.options.map(({ label, name }, idx) => (
|
elements.options.map(({ label, name }, idx) => (
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ const CopyToClipboard = ({
|
||||||
className,
|
className,
|
||||||
buttonClassname,
|
buttonClassname,
|
||||||
children,
|
children,
|
||||||
|
variant,
|
||||||
wrapperClassname,
|
wrapperClassname,
|
||||||
removeSpace = true,
|
removeSpace = true,
|
||||||
...props
|
...props
|
||||||
|
|
@ -71,7 +72,7 @@ const CopyToClipboard = ({
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CopyToClipboard
|
export default CopyToClipboard
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@
|
||||||
--neon: #5a67ff;
|
--neon: #5a67ff;
|
||||||
--malachite: #00CD5A;
|
--malachite: #00CD5A;
|
||||||
--orange-yellow: #ffcc00;
|
--orange-yellow: #ffcc00;
|
||||||
|
|
||||||
|
--mont: 'Mont';
|
||||||
|
--museo: 'MuseoSans';
|
||||||
|
--bpmono: 'BPmono';
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
|
|
@ -44,6 +48,13 @@
|
||||||
--color-neon: var(--neon);
|
--color-neon: var(--neon);
|
||||||
--color-malachite: var(--malachite);
|
--color-malachite: var(--malachite);
|
||||||
--color-orange-yellow: var(--orange-yellow);
|
--color-orange-yellow: var(--orange-yellow);
|
||||||
|
--font-mont: var(--mont);
|
||||||
|
--font-museo: var(--museo);
|
||||||
|
--font-bpmono: var(--bpmono);
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility col-span-all {
|
||||||
|
column-span: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue