partial: trigger and transactions
This commit is contained in:
parent
6d6edf578c
commit
42ab9e8fa4
30 changed files with 354 additions and 1116 deletions
|
|
@ -1,25 +1,20 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { CopyToClipboard as ReactCopyToClipboard } from 'react-copy-to-clipboard'
|
||||
import Popover from 'src/components/Popper'
|
||||
import Popover from 'src/components/Popper.jsx'
|
||||
import CopyIcon from 'src/styling/icons/action/copy/copy.svg?react'
|
||||
|
||||
import { comet } from 'src/styling/variables'
|
||||
import { comet } from 'src/styling/variables.js'
|
||||
|
||||
import { cpcStyles } from './Transactions.styles'
|
||||
|
||||
const useStyles = makeStyles(cpcStyles)
|
||||
import { Label1, Mono } from './typography/index.jsx'
|
||||
|
||||
const CopyToClipboard = ({
|
||||
className,
|
||||
buttonClassname,
|
||||
children,
|
||||
variant,
|
||||
wrapperClassname,
|
||||
removeSpace = true,
|
||||
...props
|
||||
removeSpace = true
|
||||
}) => {
|
||||
const [anchorEl, setAnchorEl] = useState(null)
|
||||
|
||||
|
|
@ -27,8 +22,6 @@ const CopyToClipboard = ({
|
|||
if (anchorEl) setTimeout(() => setAnchorEl(null), 3000)
|
||||
}, [anchorEl])
|
||||
|
||||
const classes = useStyles()
|
||||
|
||||
const handleClick = event => {
|
||||
setAnchorEl(anchorEl ? null : event.currentTarget)
|
||||
}
|
||||
|
|
@ -41,16 +34,17 @@ const CopyToClipboard = ({
|
|||
const id = open ? 'simple-popper' : undefined
|
||||
|
||||
return (
|
||||
<div className={classnames(classes.wrapper, wrapperClassname)}>
|
||||
<div className={classnames('flex items-center', wrapperClassname)}>
|
||||
{children && (
|
||||
<>
|
||||
<div className={classnames(classes.address, className)}>
|
||||
<Mono noMargin className={className}>
|
||||
{children}
|
||||
</div>
|
||||
<div className={classnames(classes.buttonWrapper, buttonClassname)}>
|
||||
</Mono>
|
||||
<div className={buttonClassname}>
|
||||
<ReactCopyToClipboard
|
||||
text={removeSpace ? R.replace(/\s/g, '')(children) : children}>
|
||||
<button
|
||||
className="border-0 bg-transparent cursor-pointer"
|
||||
aria-describedby={id}
|
||||
onClick={event => handleClick(event)}>
|
||||
<CopyIcon />
|
||||
|
|
@ -64,10 +58,11 @@ const CopyToClipboard = ({
|
|||
onClose={handleClose}
|
||||
arrowSize={3}
|
||||
bgColor={comet}
|
||||
className="py-1 px-2"
|
||||
placement="top">
|
||||
<div className={classes.popoverContent}>
|
||||
<div>Copied to clipboard!</div>
|
||||
</div>
|
||||
<Label1 noMargin className="text-white rounded-sm">
|
||||
Copied to clipboard!
|
||||
</Label1>
|
||||
</Popover>
|
||||
</>
|
||||
)}
|
||||
|
|
@ -2,7 +2,7 @@ import * as R from 'ramda'
|
|||
import React, { useState } from 'react'
|
||||
import { DeleteDialog } from 'src/components/DeleteDialog'
|
||||
import DataTable from 'src/components/tables/DataTable'
|
||||
import CopyToClipboard from 'src/pages/Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from 'src/components/CopyToClipboard.jsx'
|
||||
import DeleteIcon from 'src/styling/icons/action/delete/enabled.svg?react'
|
||||
|
||||
import { IconButton } from 'src/components/buttons'
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { Label1 } from 'src/components/typography'
|
|||
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
import CopyToClipboard from '../../Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from '../../../components/CopyToClipboard.jsx'
|
||||
|
||||
const PhotosCarousel = memo(({ photosData, timezone }) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
|||
import { ifNotNull } from 'src/utils/nullCheck'
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
import CopyToClipboard from '../../Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from '../../../components/CopyToClipboard.jsx'
|
||||
|
||||
const TransactionsList = ({ customer, data, loading }) => {
|
||||
const LastTxIcon = customer.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useQuery, gql } from "@apollo/client";
|
||||
import { useQuery, gql } from '@apollo/client'
|
||||
import { formatCryptoAddress } from '@lamassu/coins/lightUtils'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
|
|
@ -19,7 +19,7 @@ import {
|
|||
Label1,
|
||||
Label3
|
||||
} from 'src/components/typography'
|
||||
import CopyToClipboard from 'src/pages/Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from 'src/components/CopyToClipboard.jsx'
|
||||
|
||||
import { primaryColor } from 'src/styling/variables'
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import React from 'react'
|
|||
import { Status } from 'src/components/Status'
|
||||
import MachineActions from 'src/components/machineActions/MachineActions'
|
||||
import { H3, Label1, P } from 'src/components/typography'
|
||||
import CopyToClipboard from 'src/pages/Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from 'src/components/CopyToClipboard.jsx'
|
||||
|
||||
const Overview = ({ data, onActionSuccess }) => {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useQuery, useLazyQuery, gql } from "@apollo/client";
|
||||
import { useQuery, useLazyQuery, gql } from '@apollo/client'
|
||||
import { toUnit, formatCryptoAddress } from '@lamassu/coins/lightUtils'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import * as R from 'ramda'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
|
@ -8,18 +7,21 @@ import DetailsRow from 'src/pages/Transactions/DetailsCard'
|
|||
import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
|
||||
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
||||
|
||||
import { mainStyles } from 'src/pages/Transactions/Transactions.styles'
|
||||
import { getStatus } from 'src/pages/Transactions/helper'
|
||||
import * as Customer from 'src/utils/customer'
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
import DataTable from './DataTable'
|
||||
const useStyles = makeStyles(mainStyles)
|
||||
|
||||
const NUM_LOG_RESULTS = 5
|
||||
|
||||
const GET_TRANSACTIONS = gql`
|
||||
query transactions($limit: Int, $from: DateTimeISO, $until: DateTimeISO, $deviceId: String) {
|
||||
query transactions(
|
||||
$limit: Int
|
||||
$from: DateTimeISO
|
||||
$until: DateTimeISO
|
||||
$deviceId: String
|
||||
) {
|
||||
transactions(
|
||||
limit: $limit
|
||||
from: $from
|
||||
|
|
@ -67,8 +69,6 @@ const GET_DATA = gql`
|
|||
`
|
||||
|
||||
const Transactions = ({ id }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const [extraHeight, setExtraHeight] = useState(0)
|
||||
const [clickedId, setClickedId] = useState('')
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ const Transactions = ({ id }) => {
|
|||
{
|
||||
header: 'Address',
|
||||
view: it => formatCryptoAddress(it.cryptoCode, it.toAddress),
|
||||
className: classes.overflowTd,
|
||||
className: 'overflow-hidden whitespace-nowrap text-ellipsis',
|
||||
size: 'sm',
|
||||
textAlign: 'left',
|
||||
width: 140
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useLazyQuery, useMutation, gql } from '@apollo/client'
|
||||
import { toUnit, formatCryptoAddress } from '@lamassu/coins/lightUtils'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames'
|
||||
import { add, differenceInYears, format, sub, parse } from 'date-fns/fp'
|
||||
|
|
@ -34,11 +33,9 @@ import {
|
|||
import { SWEEPABLE_CRYPTOS } from 'src/utils/constants'
|
||||
import * as Customer from 'src/utils/customer'
|
||||
|
||||
import CopyToClipboard from './CopyToClipboard'
|
||||
import styles from './DetailsCard.styles'
|
||||
import CopyToClipboard from '../../components/CopyToClipboard.jsx'
|
||||
import { getStatus, getStatusDetails } from './helper'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
const MINUTES_OFFSET = 3
|
||||
const TX_SUMMARY = gql`
|
||||
query txSummaryAndLogs(
|
||||
|
|
@ -100,12 +97,14 @@ const formatAddress = (cryptoCode = '', address = '') =>
|
|||
formatCryptoAddress(cryptoCode, address).replace(/(.{5})/g, '$1 ')
|
||||
|
||||
const Label = ({ children }) => {
|
||||
const classes = useStyles()
|
||||
return <Label1 className={classes.label}>{children}</Label1>
|
||||
return (
|
||||
<Label1 noMargin className="text-comet mb-1">
|
||||
{children}
|
||||
</Label1>
|
||||
)
|
||||
}
|
||||
|
||||
const DetailsRow = ({ it: tx, timezone }) => {
|
||||
const classes = useStyles()
|
||||
const [action, setAction] = useState({ command: null })
|
||||
const [errorMessage, setErrorMessage] = useState('')
|
||||
|
||||
|
|
@ -183,9 +182,11 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
const errorElements = (
|
||||
<>
|
||||
<Label>Transaction status</Label>
|
||||
<span className={classes.bold}>{getStatus(tx)}</span>
|
||||
<span className="font-bold">{getStatus(tx)}</span>
|
||||
{getStatusDetails(tx) ? (
|
||||
<CopyToClipboard removeSpace={false} className={classes.errorCopy}>
|
||||
<CopyToClipboard
|
||||
removeSpace={false}
|
||||
className="font-museo break-normal max-w-45">
|
||||
{getStatusDetails(tx)}
|
||||
</CopyToClipboard>
|
||||
) : (
|
||||
|
|
@ -195,7 +196,7 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
)
|
||||
|
||||
const walletScoreEl = (
|
||||
<div className={classes.walletScore}>
|
||||
<div className="flex flex-row items-center">
|
||||
<svg width={103} height={10}>
|
||||
{R.range(0, 10).map((it, idx) => (
|
||||
<circle
|
||||
|
|
@ -218,8 +219,8 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
<P
|
||||
noMargin
|
||||
className={classNames({
|
||||
[classes.bold]: true,
|
||||
[classes.error]: hasChainAnalysisError(tx)
|
||||
'font-bold ml-1': true,
|
||||
'text-tomato': hasChainAnalysisError(tx)
|
||||
})}>
|
||||
{tx.walletScore}
|
||||
</P>
|
||||
|
|
@ -234,24 +235,23 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div data-cy="details" className={classes.wrapper}>
|
||||
<div className={classes.row}>
|
||||
<div data-cy="direction" className={classes.direction}>
|
||||
<div data-cy="details" className="flex flex-col mt-6">
|
||||
<div className="flex flex-row mb-9">
|
||||
<div data-cy="direction" className="w-59">
|
||||
<Label>Direction</Label>
|
||||
<div>
|
||||
<span className={classes.txIcon}>
|
||||
<span className="mr-3">
|
||||
{!isCashIn ? <TxOutIcon /> : <TxInIcon />}
|
||||
</span>
|
||||
<span>{!isCashIn ? 'Cash-out' : 'Cash-in'}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-cy="availableIds" className={classes.availableIds}>
|
||||
<div data-cy="availableIds" className="w-58">
|
||||
<Label>Available IDs</Label>
|
||||
<div className="flex">
|
||||
<div className="flex gap-1">
|
||||
{tx.customerPhone && (
|
||||
<IDButton
|
||||
className={classes.idButton}
|
||||
name="phone"
|
||||
Icon={PhoneIdIcon}
|
||||
InverseIcon={PhoneIdInverseIcon}>
|
||||
|
|
@ -260,13 +260,11 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
)}
|
||||
{tx.customerIdCardPhotoPath && !tx.customerIdCardData && (
|
||||
<IDButton
|
||||
popoverClassname={classes.clipboardPopover}
|
||||
className={classes.idButton}
|
||||
popoverClassname="h-41 w-54"
|
||||
name="card"
|
||||
Icon={CardIdIcon}
|
||||
InverseIcon={CardIdInverseIcon}>
|
||||
<img
|
||||
className={classes.idCardPhoto}
|
||||
src={`/id-card-photo/${tx.customerIdCardPhotoPath}`}
|
||||
alt=""
|
||||
/>
|
||||
|
|
@ -274,33 +272,32 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
)}
|
||||
{tx.customerIdCardData && (
|
||||
<IDButton
|
||||
className={classes.idButton}
|
||||
name="card"
|
||||
Icon={CardIdIcon}
|
||||
InverseIcon={CardIdInverseIcon}>
|
||||
<div className={classes.idCardDataCard}>
|
||||
<div>
|
||||
<div className="font-museo flex py-3 px-2 gap-16">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<Label>Name</Label>
|
||||
<div>{customer.name}</div>
|
||||
<P noMargin>{customer.name}</P>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Age</Label>
|
||||
<div>{customer.age}</div>
|
||||
<P noMargin>{customer.age}</P>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Country</Label>
|
||||
<div>{customer.country}</div>
|
||||
<P noMargin>{customer.country}</P>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<Label>ID number</Label>
|
||||
<div>{customer.idCardNumber}</div>
|
||||
<P noMargin>{customer.idCardNumber}</P>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Expiration date</Label>
|
||||
<div>{customer.idCardExpirationDate}</div>
|
||||
<P noMargin>{customer.idCardExpirationDate}</P>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -308,7 +305,6 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
)}
|
||||
{tx.customerFrontCameraPath && (
|
||||
<IDButton
|
||||
className={classes.idButton}
|
||||
name="cam"
|
||||
Icon={CamIdIcon}
|
||||
InverseIcon={CamIdInverseIcon}>
|
||||
|
|
@ -331,17 +327,17 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div data-cy="exchangeRate" className={classes.exchangeRate}>
|
||||
<div data-cy="exchangeRate" className="w-62">
|
||||
<Label>Exchange rate</Label>
|
||||
<div>{crypto > 0 ? displayExRate : '-'}</div>
|
||||
</div>
|
||||
<div data-cy="commission" className={classes.commission}>
|
||||
<div data-cy="commission" className="w-54">
|
||||
<Label>Commission</Label>
|
||||
<div className={classes.container}>
|
||||
<div className="flex">
|
||||
{`${commission} ${tx.fiatCode} (${commissionPercentage} %)`}
|
||||
{discount && (
|
||||
<div className={classes.chip}>
|
||||
<Label1 className={classes.chipLabel}>{discount}</Label1>
|
||||
<div className="flex items-center py-1 px-2 bg-comet text-white h-6 -mb-6 -mt-1 ml-2 rounded-sm">
|
||||
<Label1 className="text-white">{discount}</Label1>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -351,9 +347,9 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
<div>{`${fixedFee} ${tx.fiatCode}`}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.secondRow}>
|
||||
<div data-cy="address" className={classes.address}>
|
||||
<div className={classes.addressHeader}>
|
||||
<div className="flex flex-row justify-between mb-9">
|
||||
<div data-cy="address" className="w-70">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<Label>Address</Label>
|
||||
{!R.isNil(tx.walletScore) && (
|
||||
<HelpTooltip parentElements={walletScoreEl}>
|
||||
|
|
@ -367,7 +363,7 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
</CopyToClipboard>
|
||||
</div>
|
||||
</div>
|
||||
<div data-cy="transactionId" className={classes.transactionId}>
|
||||
<div data-cy="transactionId" className="w-70">
|
||||
<Label>Transaction ID</Label>
|
||||
<div>
|
||||
{tx.txClass === 'cashOut' ? (
|
||||
|
|
@ -378,18 +374,18 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
</div>
|
||||
</div>
|
||||
{tx.txClass === 'cashIn' && (
|
||||
<div data-cy="networkFee" className={classes.blockFee}>
|
||||
<div data-cy="networkFee" className="w-35">
|
||||
<Label>Network Fee</Label>
|
||||
{cryptoFee}
|
||||
</div>
|
||||
)}
|
||||
<div data-cy="sessionId" className={classes.sessionId}>
|
||||
<div data-cy="sessionId" className="w-54">
|
||||
<Label>Session ID</Label>
|
||||
<CopyToClipboard>{tx.id}</CopyToClipboard>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.lastRow}>
|
||||
<div data-cy="status" className={classes.status}>
|
||||
<div className="flex flex-row mb-8">
|
||||
<div data-cy="status" className="62">
|
||||
{errorElements}
|
||||
{((tx.txClass === 'cashOut' && getStatus(tx) === 'Pending') ||
|
||||
(tx.txClass === 'cashIn' && getStatus(tx) === 'Batched')) && (
|
||||
|
|
@ -397,7 +393,7 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
color="primary"
|
||||
Icon={CancelIcon}
|
||||
InverseIcon={CancelInverseIcon}
|
||||
className={classes.cancelTransaction}
|
||||
className="w-40"
|
||||
onClick={() =>
|
||||
setAction({
|
||||
command: 'cancelTx'
|
||||
|
|
@ -408,21 +404,19 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
)}
|
||||
</div>
|
||||
{!R.isNil(tx.swept) && R.includes(tx.cryptoCode, SWEEPABLE_CRYPTOS) && (
|
||||
<div data-cy="swept" className={classes.swept}>
|
||||
<div data-cy="swept" className="w-63">
|
||||
<Label>Sweep status</Label>
|
||||
<span className={classes.bold}>
|
||||
{tx.swept ? `Swept` : `Unswept`}
|
||||
</span>
|
||||
<span className="font-bold">{tx.swept ? `Swept` : `Unswept`}</span>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<Label>Other actions</Label>
|
||||
<div className={classes.otherActionsGroup}>
|
||||
<div className="flex flex-row">
|
||||
<ActionButton
|
||||
color="primary"
|
||||
Icon={Download}
|
||||
InverseIcon={DownloadInverseIcon}
|
||||
className={classes.downloadRawLogs}
|
||||
className="w-45"
|
||||
onClick={() => downloadRawLogs(tx, timezone)}>
|
||||
Download raw logs
|
||||
</ActionButton>
|
||||
|
|
|
|||
|
|
@ -1,146 +0,0 @@
|
|||
import typographyStyles from 'src/components/typography/styles'
|
||||
import { offColor, comet, white, tomato } from 'src/styling/variables'
|
||||
|
||||
const { p, label3 } = typographyStyles
|
||||
|
||||
export default {
|
||||
wrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
marginTop: 24
|
||||
},
|
||||
row: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
marginBottom: 36
|
||||
},
|
||||
secondRow: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 36
|
||||
},
|
||||
lastRow: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
marginBottom: 32
|
||||
},
|
||||
label: {
|
||||
color: offColor,
|
||||
margin: [[0, 0, 6, 0]],
|
||||
whiteSpace: 'nowrap'
|
||||
},
|
||||
txIcon: {
|
||||
marginRight: 10
|
||||
},
|
||||
clipboardPopover: {
|
||||
height: 164,
|
||||
width: 215
|
||||
},
|
||||
idButton: {
|
||||
marginRight: 4
|
||||
},
|
||||
idCardDataCard: {
|
||||
extend: p,
|
||||
display: 'flex',
|
||||
padding: [[11, 8]],
|
||||
'& > div': {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
'& > div': {
|
||||
width: 144,
|
||||
height: 37,
|
||||
marginBottom: 15,
|
||||
'&:last-child': {
|
||||
marginBottom: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
bold: {
|
||||
fontWeight: 700
|
||||
},
|
||||
direction: {
|
||||
width: 233
|
||||
},
|
||||
availableIds: {
|
||||
width: 232
|
||||
},
|
||||
exchangeRate: {
|
||||
width: 250
|
||||
},
|
||||
commission: {
|
||||
width: 217
|
||||
},
|
||||
address: {
|
||||
width: 280
|
||||
},
|
||||
downloadRawLogs: {
|
||||
width: 180
|
||||
},
|
||||
cancelTransaction: {
|
||||
width: 160
|
||||
},
|
||||
status: {
|
||||
width: 230,
|
||||
'& > button': {
|
||||
marginTop: 20
|
||||
}
|
||||
},
|
||||
transactionId: {
|
||||
width: 280
|
||||
},
|
||||
blockFee: {
|
||||
width: 140
|
||||
},
|
||||
sessionId: {
|
||||
width: 215
|
||||
},
|
||||
container: {
|
||||
display: 'flex'
|
||||
},
|
||||
chip: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '4px 8px 4px 8px',
|
||||
backgroundColor: comet,
|
||||
color: white,
|
||||
height: 24,
|
||||
marginBottom: -24,
|
||||
marginTop: -3,
|
||||
marginLeft: 7,
|
||||
borderRadius: 4
|
||||
},
|
||||
chipLabel: {
|
||||
color: white
|
||||
},
|
||||
otherActionsGroup: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
addressHeader: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
},
|
||||
walletScore: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
'& > p': {
|
||||
marginLeft: 5
|
||||
}
|
||||
},
|
||||
error: {
|
||||
color: tomato
|
||||
},
|
||||
swept: {
|
||||
width: 250
|
||||
},
|
||||
errorCopy: {
|
||||
extend: label3,
|
||||
lineBreak: 'normal',
|
||||
maxWidth: 180
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import { useQuery, gql } from "@apollo/client";
|
||||
import { useQuery, gql } from '@apollo/client'
|
||||
import { toUnit, formatCryptoAddress } from '@lamassu/coins/lightUtils'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import * as R from 'ramda'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
|
@ -8,7 +7,6 @@ import { useHistory } from 'react-router-dom'
|
|||
import LogsDowloaderPopover from 'src/components/LogsDownloaderPopper'
|
||||
import SearchBox from 'src/components/SearchBox'
|
||||
import SearchFilter from 'src/components/SearchFilter'
|
||||
import Title from 'src/components/Title'
|
||||
import { HelpTooltip } from 'src/components/Tooltip'
|
||||
import DataTable from 'src/components/tables/DataTable'
|
||||
import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
|
||||
|
|
@ -22,10 +20,8 @@ import * as Customer from 'src/utils/customer'
|
|||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
import DetailsRow from './DetailsCard'
|
||||
import { mainStyles } from './Transactions.styles'
|
||||
import { getStatus } from './helper'
|
||||
|
||||
const useStyles = makeStyles(mainStyles)
|
||||
import TitleSection from '../../components/layout/TitleSection.jsx'
|
||||
|
||||
const NUM_LOG_RESULTS = 1000
|
||||
|
||||
|
|
@ -138,7 +134,6 @@ const getFiltersObj = filters =>
|
|||
R.reduce((s, f) => ({ ...s, [f.type]: f.value }), {}, filters)
|
||||
|
||||
const Transactions = () => {
|
||||
const classes = useStyles()
|
||||
const history = useHistory()
|
||||
|
||||
const [filters, setFilters] = useState([])
|
||||
|
|
@ -187,14 +182,18 @@ const Transactions = () => {
|
|||
width: 202,
|
||||
size: 'sm',
|
||||
view: it => (
|
||||
<div className={classes.flexWrapper}>
|
||||
<div className={classes.overflowTd}>{Customer.displayName(it)}</div>
|
||||
<div className="flex items-center justify-between mr-4">
|
||||
<div className="overflow-hidden whitespace-nowrap text-ellipsis">
|
||||
{Customer.displayName(it)}
|
||||
</div>
|
||||
{!it.isAnonymous && (
|
||||
<div data-cy="customer-link" onClick={() => redirect(it.customerId)}>
|
||||
<div
|
||||
data-cy="customer-link"
|
||||
onClick={() => redirect(it.customerId)}>
|
||||
{it.hasError || it.batchError ? (
|
||||
<CustomerLinkWhiteIcon className={classes.customerLinkIcon} />
|
||||
<CustomerLinkWhiteIcon />
|
||||
) : (
|
||||
<CustomerLinkIcon className={classes.customerLinkIcon} />
|
||||
<CustomerLinkIcon />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -221,7 +220,7 @@ const Transactions = () => {
|
|||
{
|
||||
header: 'Address',
|
||||
view: it => formatCryptoAddress(it.cryptoCode, it.toAddress),
|
||||
className: classes.overflowTd,
|
||||
className: 'overflow-hidden whitespace-nowrap text-ellipsis',
|
||||
size: 'sm',
|
||||
width: 140
|
||||
},
|
||||
|
|
@ -238,7 +237,7 @@ const Transactions = () => {
|
|||
view: it => {
|
||||
if (getStatus(it) === 'Pending')
|
||||
return (
|
||||
<div className={classes.pendingBox}>
|
||||
<div className="flex items-center">
|
||||
{'Pending'}
|
||||
<HelpTooltip width={285}>
|
||||
<SupportLinkButton
|
||||
|
|
@ -332,10 +331,15 @@ const Transactions = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className={classes.titleWrapper}>
|
||||
<div className={classes.titleAndButtonsContainer}>
|
||||
<Title>Transactions</Title>
|
||||
<div className={classes.buttonsWrapper}>
|
||||
<TitleSection
|
||||
title="Transactions"
|
||||
labels={[
|
||||
{ icon: <TxInIcon />, label: 'Cash-in' },
|
||||
{ icon: <TxOutIcon />, label: 'Cash-out' },
|
||||
{ icon: errorLabel, label: 'Transaction error' }
|
||||
]}
|
||||
appendix={
|
||||
<div className="flex ml-4 gap-4">
|
||||
<SearchBox
|
||||
loading={filtersLoading}
|
||||
filters={filters}
|
||||
|
|
@ -343,9 +347,7 @@ const Transactions = () => {
|
|||
inputPlaceholder={'Search transactions'}
|
||||
onChange={onFilterChange}
|
||||
/>
|
||||
</div>
|
||||
{txList && (
|
||||
<div className={classes.buttonsWrapper}>
|
||||
{txList && (
|
||||
<LogsDowloaderPopover
|
||||
title="Download logs"
|
||||
name="transactions"
|
||||
|
|
@ -355,24 +357,10 @@ const Transactions = () => {
|
|||
timezone={timezone}
|
||||
args={{ timezone }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={classes.headerLabels}>
|
||||
<div>
|
||||
<TxInIcon />
|
||||
<span>Cash-in</span>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<TxOutIcon />
|
||||
<span>Cash-out</span>
|
||||
</div>
|
||||
<div>
|
||||
{errorLabel}
|
||||
<span>Transaction error</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
{filters.length > 0 && (
|
||||
<SearchFilter
|
||||
entries={txList.length}
|
||||
|
|
|
|||
|
|
@ -1,147 +0,0 @@
|
|||
import typographyStyles from 'src/components/typography/styles'
|
||||
import baseStyles from 'src/pages/Logs.styles'
|
||||
import {
|
||||
offColor,
|
||||
white,
|
||||
primaryColor,
|
||||
zircon,
|
||||
smallestFontSize,
|
||||
inputFontFamily,
|
||||
inputFontWeight,
|
||||
spacer
|
||||
} from 'src/styling/variables'
|
||||
|
||||
const { label1, mono, p } = typographyStyles
|
||||
const { titleWrapper, titleAndButtonsContainer, buttonsWrapper } = baseStyles
|
||||
|
||||
const cpcStyles = {
|
||||
wrapper: {
|
||||
extend: mono,
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
},
|
||||
address: {
|
||||
lineBreak: 'anywhere'
|
||||
},
|
||||
buttonWrapper: {
|
||||
'& button': {
|
||||
border: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
cursor: 'pointer'
|
||||
}
|
||||
},
|
||||
popoverContent: {
|
||||
extend: label1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
color: white,
|
||||
borderRadius: 4,
|
||||
padding: [[5, 9]]
|
||||
}
|
||||
}
|
||||
|
||||
const detailsRowStyles = {
|
||||
idCardDataCard: {
|
||||
extend: p,
|
||||
display: 'flex',
|
||||
padding: [[11, 8]],
|
||||
'& > div': {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
'& > div': {
|
||||
width: 144,
|
||||
height: 37,
|
||||
marginBottom: 15,
|
||||
'&:last-child': {
|
||||
marginBottom: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const labelStyles = {
|
||||
label: {
|
||||
extend: label1,
|
||||
color: offColor,
|
||||
marginBottom: 4
|
||||
}
|
||||
}
|
||||
|
||||
const mainStyles = {
|
||||
titleWrapper,
|
||||
titleAndButtonsContainer,
|
||||
buttonsWrapper,
|
||||
pendingBox: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
headerLabels: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
'& div': {
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
},
|
||||
'& > div': {
|
||||
marginLeft: 24
|
||||
},
|
||||
'& > div:first-child': {
|
||||
marginLeft: 0
|
||||
},
|
||||
'& span': {
|
||||
extend: label1,
|
||||
marginLeft: 6
|
||||
}
|
||||
},
|
||||
overflowTd: {
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis'
|
||||
},
|
||||
flexWrapper: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginRight: 16
|
||||
},
|
||||
customerLinkIcon: {
|
||||
marginLeft: 2
|
||||
},
|
||||
flexRow: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
machineRedirectContainer: {
|
||||
marginLeft: 10,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5
|
||||
}
|
||||
}
|
||||
|
||||
const chipStyles = {
|
||||
root: {
|
||||
borderRadius: spacer / 2,
|
||||
marginTop: spacer / 2,
|
||||
marginRight: spacer / 4,
|
||||
marginBottom: spacer / 2,
|
||||
marginLeft: spacer / 4,
|
||||
height: spacer * 3,
|
||||
backgroundColor: zircon,
|
||||
'&:hover, &:focus, &:active': {
|
||||
backgroundColor: zircon
|
||||
}
|
||||
},
|
||||
label: {
|
||||
fontSize: smallestFontSize,
|
||||
fontWeight: inputFontWeight,
|
||||
fontFamily: inputFontFamily,
|
||||
paddingRight: spacer / 2,
|
||||
paddingLeft: spacer / 2,
|
||||
color: primaryColor
|
||||
}
|
||||
}
|
||||
|
||||
export { cpcStyles, detailsRowStyles, labelStyles, mainStyles, chipStyles }
|
||||
|
|
@ -30,13 +30,4 @@ const getStatusDetails = it => {
|
|||
return null
|
||||
}
|
||||
|
||||
const getStatusProperties = status => ({
|
||||
hasError: status === 'Error' || null,
|
||||
batchError: status === 'Error' || null,
|
||||
dispense: status === 'Success' || null,
|
||||
expired: status === 'Expired' || null,
|
||||
operatorCompleted: status === 'Cancelled' || null,
|
||||
sendConfirmed: status === 'Sent' || null
|
||||
})
|
||||
|
||||
export { getStatus, getStatusProperties, getStatusDetails }
|
||||
export { getStatus, getStatusDetails }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { useMutation, useQuery, gql } from "@apollo/client";
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import { useMutation, useQuery, gql } from '@apollo/client'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
import { DeleteDialog } from 'src/components/DeleteDialog'
|
||||
|
|
@ -12,10 +10,8 @@ import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
|
|||
import { IconButton, Button, Link } from 'src/components/buttons'
|
||||
import { fromNamespace, namespaces, toNamespace } from 'src/utils/config'
|
||||
|
||||
import styles from './CustomInfoRequests.styles'
|
||||
import DetailsRow from './DetailsCard'
|
||||
import Wizard from './Wizard'
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const inputTypeDisplay = {
|
||||
numerical: 'Numerical',
|
||||
|
|
@ -76,8 +72,6 @@ const CustomInfoRequests = ({
|
|||
toggleWizard,
|
||||
data: customRequests
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const [toBeDeleted, setToBeDeleted] = useState()
|
||||
const [toBeEdited, setToBeEdited] = useState()
|
||||
const [deleteDialog, setDeleteDialog] = useState(false)
|
||||
|
|
@ -178,118 +172,122 @@ const CustomInfoRequests = ({
|
|||
</>
|
||||
)
|
||||
|
||||
return (!configLoading && (<>
|
||||
{customRequests.length > 0 && (
|
||||
<DataTable
|
||||
emptyText="No custom info requests so far"
|
||||
elements={[
|
||||
{
|
||||
header: 'Requirement name',
|
||||
width: 300,
|
||||
textAlign: 'left',
|
||||
size: 'sm',
|
||||
view: it => it.customRequest.name
|
||||
},
|
||||
{
|
||||
header: 'Data entry type',
|
||||
width: 300,
|
||||
textAlign: 'left',
|
||||
size: 'sm',
|
||||
view: it => inputTypeDisplay[it.customRequest.input.type]
|
||||
},
|
||||
{
|
||||
header: 'Constraints',
|
||||
width: 300,
|
||||
textAlign: 'left',
|
||||
size: 'sm',
|
||||
view: it =>
|
||||
constraintTypeDisplay[it.customRequest.input.constraintType]
|
||||
},
|
||||
{
|
||||
header: 'Edit',
|
||||
width: 100,
|
||||
textAlign: 'center',
|
||||
size: 'sm',
|
||||
view: it => {
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setToBeEdited(it)
|
||||
return toggleWizard()
|
||||
}}
|
||||
size="large">
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
header: 'Delete',
|
||||
width: 100,
|
||||
textAlign: 'center',
|
||||
size: 'sm',
|
||||
view: it => {
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setToBeDeleted(it.id)
|
||||
return setDeleteDialog(true)
|
||||
}}
|
||||
size="large">
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
}
|
||||
]}
|
||||
data={customRequests}
|
||||
Details={DetailsRow}
|
||||
expandable
|
||||
rowSize="sm"
|
||||
/>
|
||||
)}
|
||||
{!customRequests.length && (
|
||||
<div className={classes.centerItems}>
|
||||
<Info1 className={classnames(classes.m0, classes.mb10)}>
|
||||
It seems you haven't added any custom information requests yet.
|
||||
</Info1>
|
||||
<Info3 className={classnames(classes.m0, classes.mb10)}>
|
||||
Please read our{' '}
|
||||
<a href="https://support.lamassu.is/hc/en-us/sections/115000817232-Compliance">
|
||||
<Link>Support Article</Link>
|
||||
</a>{' '}
|
||||
on Compliance before adding new information requests.
|
||||
</Info3>
|
||||
<Button onClick={() => toggleWizard()}>
|
||||
Add custom information request
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{showWizard && (
|
||||
<Wizard
|
||||
hasError={hasError}
|
||||
onClose={() => {
|
||||
setToBeEdited(null)
|
||||
setHasError(false)
|
||||
toggleWizard()
|
||||
}}
|
||||
toBeEdited={toBeEdited}
|
||||
onSave={(...args) => handleSave(...args)}
|
||||
existingRequirements={customRequests}
|
||||
/>
|
||||
)}
|
||||
<DeleteDialog
|
||||
errorMessage={hasError ? 'Failed to delete' : ''}
|
||||
open={deleteDialog}
|
||||
onDismissed={() => {
|
||||
setDeleteDialog(false)
|
||||
setHasError(false)
|
||||
}}
|
||||
item={`custom information request`}
|
||||
extraMessage={detailedDeleteMsg}
|
||||
onConfirmed={() => handleDelete(toBeDeleted)}
|
||||
/>
|
||||
</>));
|
||||
return (
|
||||
!configLoading && (
|
||||
<>
|
||||
{customRequests.length > 0 && (
|
||||
<DataTable
|
||||
emptyText="No custom info requests so far"
|
||||
elements={[
|
||||
{
|
||||
header: 'Requirement name',
|
||||
width: 300,
|
||||
textAlign: 'left',
|
||||
size: 'sm',
|
||||
view: it => it.customRequest.name
|
||||
},
|
||||
{
|
||||
header: 'Data entry type',
|
||||
width: 300,
|
||||
textAlign: 'left',
|
||||
size: 'sm',
|
||||
view: it => inputTypeDisplay[it.customRequest.input.type]
|
||||
},
|
||||
{
|
||||
header: 'Constraints',
|
||||
width: 300,
|
||||
textAlign: 'left',
|
||||
size: 'sm',
|
||||
view: it =>
|
||||
constraintTypeDisplay[it.customRequest.input.constraintType]
|
||||
},
|
||||
{
|
||||
header: 'Edit',
|
||||
width: 100,
|
||||
textAlign: 'center',
|
||||
size: 'sm',
|
||||
view: it => {
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setToBeEdited(it)
|
||||
return toggleWizard()
|
||||
}}
|
||||
size="large">
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
header: 'Delete',
|
||||
width: 100,
|
||||
textAlign: 'center',
|
||||
size: 'sm',
|
||||
view: it => {
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setToBeDeleted(it.id)
|
||||
return setDeleteDialog(true)
|
||||
}}
|
||||
size="large">
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
}
|
||||
]}
|
||||
data={customRequests}
|
||||
Details={DetailsRow}
|
||||
expandable
|
||||
rowSize="sm"
|
||||
/>
|
||||
)}
|
||||
{!customRequests.length && (
|
||||
<div className="flex flex-col items-center h-1/2 justify-center">
|
||||
<Info1 className="m-0 mb-3">
|
||||
It seems you haven't added any custom information requests yet.
|
||||
</Info1>
|
||||
<Info3 className="m-0 mb-3">
|
||||
Please read our{' '}
|
||||
<a href="https://support.lamassu.is/hc/en-us/sections/115000817232-Compliance">
|
||||
<Link>Support Article</Link>
|
||||
</a>{' '}
|
||||
on Compliance before adding new information requests.
|
||||
</Info3>
|
||||
<Button onClick={() => toggleWizard()}>
|
||||
Add custom information request
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{showWizard && (
|
||||
<Wizard
|
||||
hasError={hasError}
|
||||
onClose={() => {
|
||||
setToBeEdited(null)
|
||||
setHasError(false)
|
||||
toggleWizard()
|
||||
}}
|
||||
toBeEdited={toBeEdited}
|
||||
onSave={(...args) => handleSave(...args)}
|
||||
existingRequirements={customRequests}
|
||||
/>
|
||||
)}
|
||||
<DeleteDialog
|
||||
errorMessage={hasError ? 'Failed to delete' : ''}
|
||||
open={deleteDialog}
|
||||
onDismissed={() => {
|
||||
setDeleteDialog(false)
|
||||
setHasError(false)
|
||||
}}
|
||||
item={`custom information request`}
|
||||
extraMessage={detailedDeleteMsg}
|
||||
onConfirmed={() => handleDelete(toBeDeleted)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomInfoRequests
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
export default {
|
||||
m0: {
|
||||
margin: 0
|
||||
},
|
||||
mb10: {
|
||||
marginBottom: 10
|
||||
},
|
||||
centerItems: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
height: '50%',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
alignWithTitleSection: {
|
||||
marginTop: -47,
|
||||
display: 'flex'
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +1,8 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import React from 'react'
|
||||
import { Label1, Info2 } from 'src/components/typography'
|
||||
|
||||
const styles = {
|
||||
flex: {
|
||||
display: 'flex'
|
||||
},
|
||||
column: {
|
||||
flexDirection: 'column'
|
||||
},
|
||||
halfWidth: {
|
||||
width: '50%',
|
||||
marginBottom: 15,
|
||||
marginRight: 50
|
||||
},
|
||||
marginTop: {
|
||||
marginTop: 20
|
||||
},
|
||||
marginBottom: {
|
||||
marginBottom: 20
|
||||
}
|
||||
}
|
||||
const useStyles = makeStyles(styles)
|
||||
const DetailsCard = ({ it }) => {
|
||||
const customRequest = it.customRequest
|
||||
const classes = useStyles()
|
||||
|
||||
const getScreen2Data = () => {
|
||||
const label1Display =
|
||||
customRequest.input.constraintType === 'spaceSeparation'
|
||||
|
|
@ -36,12 +12,12 @@ const DetailsCard = ({ it }) => {
|
|||
case 'text':
|
||||
return (
|
||||
<>
|
||||
<div className={classes.halfWidth}>
|
||||
<div className="w-1/2 mb-4 mr-12">
|
||||
<Info2>{label1Display}</Info2>
|
||||
<Label1>{customRequest.input.label1}</Label1>
|
||||
</div>
|
||||
{customRequest.input.constraintType === 'spaceSeparation' && (
|
||||
<div className={classes.halfWidth}>
|
||||
<div className="w-1/2 mb-4 mr-12">
|
||||
<Info2>Second word label</Info2>
|
||||
<Label1>{customRequest.input.label2}</Label1>
|
||||
</div>
|
||||
|
|
@ -51,11 +27,11 @@ const DetailsCard = ({ it }) => {
|
|||
default:
|
||||
return (
|
||||
<>
|
||||
<div className={classes.halfWidth}>
|
||||
<div className="w-1/2 mb-4 mr-12">
|
||||
<Info2>Screen 2 input title</Info2>
|
||||
<Label1>{customRequest.screen2.title}</Label1>
|
||||
</div>
|
||||
<div className={classes.halfWidth}>
|
||||
<div className="w-1/2 mb-4 mr-12">
|
||||
<Info2>Screen 2 input description</Info2>
|
||||
<Label1>{customRequest.screen2.text}</Label1>
|
||||
</div>
|
||||
|
|
@ -87,22 +63,19 @@ const DetailsCard = ({ it }) => {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<div className={classnames(classes.flex, classes.row, classes.marginTop)}>
|
||||
<div className={classes.halfWidth}>
|
||||
<div className="flex mt-5">
|
||||
<div className="w-1/2 mb-4 mr-12">
|
||||
<Info2>Screen 1 title</Info2>
|
||||
<Label1>{customRequest.screen1.title}</Label1>
|
||||
</div>
|
||||
<div className={classnames(classes.halfWidth, classes.flex)}>
|
||||
{getScreen2Data()}
|
||||
</div>
|
||||
<div className="flex w-1/2 mb-4 mr-12">{getScreen2Data()}</div>
|
||||
</div>
|
||||
<div
|
||||
className={classnames(classes.flex, classes.row, classes.marginBottom)}>
|
||||
<div className={classes.halfWidth}>
|
||||
<div className="flex mb-5">
|
||||
<div className="w-1/2 mb-4 mr-12">
|
||||
<Info2>Screen 1 text</Info2>
|
||||
<Label1>{customRequest.screen1.text}</Label1>
|
||||
</div>
|
||||
<div className={classes.halfWidth}>{getInputData()}</div>
|
||||
<div className="w-1/2 mb-4 mr-12">{getInputData()}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import { Field, useFormikContext, FieldArray } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
|
|
@ -10,9 +9,6 @@ import { H4 } from 'src/components/typography'
|
|||
import AddIconInverse from 'src/styling/icons/button/add/white.svg?react'
|
||||
import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react'
|
||||
|
||||
import styles from './formStyles.styles'
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const nonEmptyStr = obj => obj.text && obj.text.length
|
||||
|
||||
const options = [
|
||||
|
|
@ -21,15 +17,14 @@ const options = [
|
|||
]
|
||||
|
||||
const ChoiceList = () => {
|
||||
const classes = useStyles()
|
||||
const context = useFormikContext()
|
||||
const choiceListRef = useRef(null)
|
||||
const listChoices = R.path(['values', 'listChoices'])(context) ?? []
|
||||
const choiceListError = R.path(['errors', 'listChoices'])(context) ?? false
|
||||
|
||||
const showErrorColor = {
|
||||
[classes.radioSubtitle]: true,
|
||||
[classes.error]:
|
||||
'mb-0': true,
|
||||
'text-tomato':
|
||||
!R.path(['values', 'constraintType'])(context) &&
|
||||
R.path(['errors', 'constraintType'])(context)
|
||||
}
|
||||
|
|
@ -56,20 +51,20 @@ const ChoiceList = () => {
|
|||
<Field
|
||||
component={RadioGroup}
|
||||
options={options}
|
||||
className={classes.row}
|
||||
className="flex-col"
|
||||
name="constraintType"
|
||||
/>
|
||||
<FieldArray name="listChoices">
|
||||
{({ push }) => {
|
||||
return (
|
||||
<div className={classnames(classes.flex, classes.column)}>
|
||||
<H4 className={classes.subtitle}>Choices</H4>
|
||||
<div className={classes.choiceList}>
|
||||
<div className="flex flex-col">
|
||||
<H4 className="mb-0">Choices</H4>
|
||||
<div className="flex flex-col max-h-60">
|
||||
{listChoices.map((choice, idx) => {
|
||||
return (
|
||||
<div ref={choiceListRef} key={idx}>
|
||||
<Field
|
||||
className={classes.textInput}
|
||||
className="w-105"
|
||||
error={hasError(choice)}
|
||||
component={TextInput}
|
||||
name={`listChoices[${idx}].text`}
|
||||
|
|
@ -83,7 +78,7 @@ const ChoiceList = () => {
|
|||
Icon={AddIcon}
|
||||
color="primary"
|
||||
InverseIcon={AddIconInverse}
|
||||
className={classes.button}
|
||||
className="w-30 h-7 mt-7"
|
||||
onClick={e => {
|
||||
e.preventDefault()
|
||||
return push({ text: '' })
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import { Field, useFormikContext } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
|
|
@ -7,9 +6,6 @@ import NumberInput from 'src/components/inputs/formik/NumberInput'
|
|||
import RadioGroup from 'src/components/inputs/formik/RadioGroup'
|
||||
import { TL1, H4 } from 'src/components/typography'
|
||||
|
||||
import styles from './formStyles.styles'
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const options = [
|
||||
{ display: 'None', code: 'none' },
|
||||
{ display: 'Date', code: 'date' },
|
||||
|
|
@ -17,7 +13,6 @@ const options = [
|
|||
]
|
||||
|
||||
const NumericalEntry = () => {
|
||||
const classes = useStyles()
|
||||
const context = useFormikContext()
|
||||
|
||||
const isLength =
|
||||
|
|
@ -25,8 +20,8 @@ const NumericalEntry = () => {
|
|||
'length'
|
||||
|
||||
const showErrorColor = {
|
||||
[classes.radioSubtitle]: true,
|
||||
[classes.error]:
|
||||
'mb-0': true,
|
||||
'text-tomat':
|
||||
!R.path(['values', 'constraintType'])(context) &&
|
||||
R.path(['errors', 'constraintType'])(context)
|
||||
}
|
||||
|
|
@ -37,13 +32,13 @@ const NumericalEntry = () => {
|
|||
Numerical entry constraints
|
||||
</H4>
|
||||
<Field
|
||||
className={classes.row}
|
||||
className="flex-row"
|
||||
component={RadioGroup}
|
||||
options={options}
|
||||
name="constraintType"
|
||||
/>
|
||||
{isLength && (
|
||||
<div className={classnames(classes.flex, classes.numberField)}>
|
||||
<div className="flex mt-27 max-w-29">
|
||||
<Field
|
||||
component={NumberInput}
|
||||
name={'inputLength'}
|
||||
|
|
@ -51,7 +46,7 @@ const NumericalEntry = () => {
|
|||
decimalPlaces={0}
|
||||
allowNegative={false}
|
||||
/>
|
||||
<TL1 className={classes.tl1}>digits</TL1>
|
||||
<TL1 className="ml-2 mt-6">digits</TL1>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import { Field, useFormikContext } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
|
|
@ -7,9 +6,6 @@ import RadioGroup from 'src/components/inputs/formik/RadioGroup'
|
|||
import TextInput from 'src/components/inputs/formik/TextInput'
|
||||
import { H4 } from 'src/components/typography'
|
||||
|
||||
import styles from './formStyles.styles'
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const options = [
|
||||
{ display: 'None', code: 'none' },
|
||||
{ display: 'Email', code: 'email' },
|
||||
|
|
@ -21,11 +17,10 @@ const options = [
|
|||
]
|
||||
|
||||
const TextEntry = () => {
|
||||
const classes = useStyles()
|
||||
const context = useFormikContext()
|
||||
const showErrorColor = {
|
||||
[classes.radioSubtitle]: true,
|
||||
[classes.error]:
|
||||
'mt-0': true,
|
||||
'text-tomato':
|
||||
!R.path(['values', 'constraintType'])(context) &&
|
||||
R.path(['errors', 'constraintType'])(context)
|
||||
}
|
||||
|
|
@ -34,15 +29,15 @@ const TextEntry = () => {
|
|||
switch (context.values.constraintType) {
|
||||
case 'spaceSeparation':
|
||||
return (
|
||||
<div className={classes.flex}>
|
||||
<div className="flex">
|
||||
<Field
|
||||
className={classes.label}
|
||||
className="w-50 mr-2"
|
||||
component={TextInput}
|
||||
name={'inputLabel1'}
|
||||
label={'First word label'}
|
||||
/>
|
||||
<Field
|
||||
className={classes.label}
|
||||
className="w-50 mr-2"
|
||||
component={TextInput}
|
||||
name={'inputLabel2'}
|
||||
label={'Second word label'}
|
||||
|
|
@ -52,7 +47,7 @@ const TextEntry = () => {
|
|||
default:
|
||||
return (
|
||||
<Field
|
||||
className={classes.label}
|
||||
className="w-50 mr-2"
|
||||
component={TextInput}
|
||||
name={'inputLabel1'}
|
||||
label={'Text entry label'}
|
||||
|
|
@ -65,7 +60,7 @@ const TextEntry = () => {
|
|||
<>
|
||||
<H4 className={classnames(showErrorColor)}>Text entry constraints</H4>
|
||||
<Field
|
||||
className={classes.row}
|
||||
className="flex-row"
|
||||
component={RadioGroup}
|
||||
options={options}
|
||||
name="constraintType"
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
import { errorColor, spacer } from 'src/styling/variables'
|
||||
|
||||
const styles = {
|
||||
flex: {
|
||||
display: 'flex'
|
||||
},
|
||||
column: {
|
||||
flexDirection: 'column'
|
||||
},
|
||||
choiceList: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
maxHeight: 240,
|
||||
overflowY: 'auto'
|
||||
},
|
||||
button: {
|
||||
width: 120,
|
||||
height: 28,
|
||||
marginTop: 28
|
||||
},
|
||||
textInput: {
|
||||
width: 420
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
subtitle: {
|
||||
marginBottom: 0
|
||||
},
|
||||
radioSubtitle: {
|
||||
marginBottom: 0
|
||||
},
|
||||
error: {
|
||||
color: errorColor
|
||||
},
|
||||
tl1: {
|
||||
marginLeft: 8,
|
||||
marginTop: 25
|
||||
},
|
||||
numberField: {
|
||||
marginTop: 109,
|
||||
maxWidth: 115
|
||||
},
|
||||
label: {
|
||||
width: 200,
|
||||
marginRight: spacer
|
||||
}
|
||||
}
|
||||
|
||||
export default styles
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import { Form, Formik } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
|
@ -32,27 +31,6 @@ import WizardSplash from './WizardSplash'
|
|||
|
||||
const LAST_STEP = 5
|
||||
|
||||
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'
|
||||
}
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const getStep = (step, existingRequirements) =>
|
||||
[
|
||||
{
|
||||
|
|
@ -153,7 +131,6 @@ const Wizard = ({
|
|||
hasError,
|
||||
existingRequirements
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
const isEditing = !R.isNil(toBeEdited)
|
||||
const [step, setStep] = useState(isEditing ? 1 : 0)
|
||||
|
||||
|
|
@ -206,7 +183,7 @@ const Wizard = ({
|
|||
open={true}>
|
||||
{step > 0 && (
|
||||
<Stepper
|
||||
className={classes.stepper}
|
||||
className="mt-4 mb-4 mx-0"
|
||||
steps={LAST_STEP}
|
||||
currentStep={step}
|
||||
/>
|
||||
|
|
@ -221,15 +198,17 @@ const Wizard = ({
|
|||
initialValues={initialValues}
|
||||
validationSchema={stepOptions.validationSchema}>
|
||||
{({ errors }) => (
|
||||
<Form className={classes.form} id={'custom-requirement-form'}>
|
||||
<Form
|
||||
className="h-full flex flex-col"
|
||||
id={'custom-requirement-form'}>
|
||||
<stepOptions.Component />
|
||||
<div className={classes.submit}>
|
||||
<div className="flex flex-row mt-auto mx-0 mb-4">
|
||||
{(hasError || !R.isEmpty(errors)) && (
|
||||
<ErrorMessage>
|
||||
{R.head(R.values(errors)) ?? `Failed to save`}
|
||||
</ErrorMessage>
|
||||
)}
|
||||
<Button className={classes.button} type="submit">
|
||||
<Button className="ml-auto" type="submit">
|
||||
{isLastStep ? 'Save' : 'Next'}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,43 +1,15 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import React from 'react'
|
||||
import { H1, P } from 'src/components/typography'
|
||||
import CustomReqLogo from 'src/styling/icons/compliance/custom-requirement.svg?react'
|
||||
|
||||
import { Button } from 'src/components/buttons'
|
||||
|
||||
const styles = {
|
||||
logo: {
|
||||
maxHeight: 150,
|
||||
maxWidth: 200
|
||||
},
|
||||
title: {
|
||||
margin: [[24, 0, 32, 0]]
|
||||
},
|
||||
text: {
|
||||
margin: 0
|
||||
},
|
||||
button: {
|
||||
marginTop: 'auto',
|
||||
marginBottom: 58
|
||||
},
|
||||
modalContent: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
padding: [[0, 42]],
|
||||
flex: 1
|
||||
}
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const WizardSplash = ({ onContinue }) => {
|
||||
const classes = useStyles()
|
||||
return (
|
||||
<div className={classes.modalContent}>
|
||||
<CustomReqLogo className={classes.logo} />
|
||||
<H1 className={classes.title}>Custom information request</H1>
|
||||
<P className={classes.text}>
|
||||
<div className="flex flex-col items-center py-0 px-10 flex-1">
|
||||
<CustomReqLogo className="max-h-37 max-w-50" />
|
||||
<H1 className="mt-6 mb-8 mx-0">Custom information request</H1>
|
||||
<P className="m-0">
|
||||
A custom information request allows you to have an extra option to ask
|
||||
specific information about your customers when adding a trigger that
|
||||
isn't an option on the default requirements list.
|
||||
|
|
@ -47,7 +19,7 @@ const WizardSplash = ({ onContinue }) => {
|
|||
triggers. You will still need to add a trigger with the new requirement
|
||||
to get this information from your customers.
|
||||
</P>
|
||||
<Button className={classes.button} onClick={onContinue}>
|
||||
<Button className="mt-auto mb-14" onClick={onContinue}>
|
||||
Get started
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { useMutation, gql } from '@apollo/client'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
import { H2 } from 'src/components/typography'
|
||||
|
|
@ -9,12 +8,9 @@ import { Button } from 'src/components/buttons'
|
|||
import { Table as EditableTable } from 'src/components/editableTable'
|
||||
import { fromNamespace, namespaces } from 'src/utils/config'
|
||||
|
||||
import styles from './Triggers.styles'
|
||||
import Wizard from './Wizard'
|
||||
import { Schema, getElements, sortBy, toServer } from './helper'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const SAVE_CONFIG = gql`
|
||||
mutation Save($config: JSONObject) {
|
||||
saveConfig(config: $config)
|
||||
|
|
@ -34,7 +30,6 @@ const TriggerView = ({
|
|||
const currency = R.path(['fiatCurrency'])(
|
||||
fromNamespace(namespaces.LOCALE)(config)
|
||||
)
|
||||
const classes = useStyles()
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
||||
|
|
@ -69,7 +64,7 @@ const TriggerView = ({
|
|||
error={error?.message}
|
||||
save={save}
|
||||
validationSchema={Schema}
|
||||
elements={getElements(currency, classes, customInfoRequests)}
|
||||
elements={getElements(currency, customInfoRequests)}
|
||||
/>
|
||||
{showWizard && (
|
||||
<Wizard
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useQuery, useMutation, gql } from '@apollo/client'
|
||||
import Switch from '@mui/material/Switch'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
|
@ -20,10 +19,8 @@ import { fromNamespace, toNamespace } from 'src/utils/config'
|
|||
|
||||
import CustomInfoRequests from './CustomInfoRequests'
|
||||
import TriggerView from './TriggerView'
|
||||
import styles from './Triggers.styles'
|
||||
import AdvancedTriggers from './components/AdvancedTriggers'
|
||||
import { fromServer } from './helper'
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const SAVE_ACCOUNT = gql`
|
||||
mutation Save($accounts: JSONObject) {
|
||||
|
|
@ -61,7 +58,6 @@ const GET_CUSTOM_REQUESTS = gql`
|
|||
`
|
||||
|
||||
const Triggers = () => {
|
||||
const classes = useStyles()
|
||||
const [wizardType, setWizard] = useState(false)
|
||||
const { data, loading: configLoading, refetch } = useQuery(GET_CONFIG)
|
||||
const { data: customInfoReqData, loading: customInfoLoading } =
|
||||
|
|
@ -109,7 +105,7 @@ const Triggers = () => {
|
|||
}
|
||||
|
||||
const titleSectionWidth = {
|
||||
[classes.tableWidth]: !subMenu === 'customInfoRequests'
|
||||
'w-230': !subMenu === 'customInfoRequests'
|
||||
}
|
||||
|
||||
const setBlur = shouldBlur => {
|
||||
|
|
@ -178,7 +174,7 @@ const Triggers = () => {
|
|||
}}
|
||||
value={rejectAddressReuse}
|
||||
/>
|
||||
<Label2 className={classes.switchLabel}>
|
||||
<Label2 className="m-3 w-6">
|
||||
{rejectAddressReuse ? 'On' : 'Off'}
|
||||
</Label2>
|
||||
<HelpTooltip width={304}>
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
export default {
|
||||
switchLabel: {
|
||||
margin: 6,
|
||||
width: 24
|
||||
},
|
||||
tableRadioGroup: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
tableRadioLabel: {
|
||||
marginRight: 0
|
||||
},
|
||||
tableWidth: {
|
||||
width: 918
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import { Form, Formik, useFormikContext } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState, Fragment, useEffect } from 'react'
|
||||
|
|
@ -8,46 +7,12 @@ import Stepper from 'src/components/Stepper'
|
|||
import { H5, Info3 } from 'src/components/typography'
|
||||
|
||||
import { Button } from 'src/components/buttons'
|
||||
import { comet } from 'src/styling/variables'
|
||||
import { singularOrPlural } from 'src/utils/string'
|
||||
|
||||
import { type, requirements } from './helper'
|
||||
|
||||
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'
|
||||
}
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const getStep = (
|
||||
{ step, config },
|
||||
currency,
|
||||
|
|
@ -74,21 +39,23 @@ const getStep = (
|
|||
}
|
||||
}
|
||||
|
||||
const getText = (step, config, currency, classes) => {
|
||||
const getText = (step, config, currency) => {
|
||||
switch (step) {
|
||||
// case 1:
|
||||
// return `In ${getDirectionText(config)} transactions`
|
||||
case 1:
|
||||
return <>If the user {getTypeText(config, currency, classes)}</>
|
||||
return <>If the user {getTypeText(config, currency)}</>
|
||||
case 2:
|
||||
return <>the user will be {getRequirementText(config, classes)}.</>
|
||||
return <>the user will be {getRequirementText(config)}.</>
|
||||
default:
|
||||
return <></>
|
||||
}
|
||||
}
|
||||
|
||||
const orUnderline = (value, classes) => {
|
||||
const blankSpaceEl = <span className={classes.blankSpace}></span>
|
||||
const orUnderline = value => {
|
||||
const blankSpaceEl = (
|
||||
<span className="py-0 px-7 my-0 mx-1 border-b-1 border-b-comet inline-block"></span>
|
||||
)
|
||||
return R.isEmpty(value) || R.isNil(value) ? blankSpaceEl : value
|
||||
}
|
||||
|
||||
|
|
@ -105,34 +72,34 @@ const orUnderline = (value, classes) => {
|
|||
// }
|
||||
// }
|
||||
|
||||
const getTypeText = (config, currency, classes) => {
|
||||
const getTypeText = (config, currency) => {
|
||||
switch (config.triggerType) {
|
||||
case 'txAmount':
|
||||
return (
|
||||
<>
|
||||
makes a single transaction over{' '}
|
||||
{orUnderline(config.threshold.threshold, classes)} {currency}
|
||||
{orUnderline(config.threshold.threshold)} {currency}
|
||||
</>
|
||||
)
|
||||
case 'txVolume':
|
||||
return (
|
||||
<>
|
||||
makes more than {orUnderline(config.threshold.threshold, classes)}{' '}
|
||||
{currency} worth of transactions within{' '}
|
||||
{orUnderline(config.threshold.thresholdDays, classes)}{' '}
|
||||
makes more than {orUnderline(config.threshold.threshold)} {currency}{' '}
|
||||
worth of transactions within{' '}
|
||||
{orUnderline(config.threshold.thresholdDays)}{' '}
|
||||
{singularOrPlural(config.threshold.thresholdDays, 'day', 'days')}
|
||||
</>
|
||||
)
|
||||
case 'txVelocity':
|
||||
return (
|
||||
<>
|
||||
makes more than {orUnderline(config.threshold.threshold, classes)}{' '}
|
||||
makes more than {orUnderline(config.threshold.threshold)}{' '}
|
||||
{singularOrPlural(
|
||||
config.threshold.threshold,
|
||||
'transaction',
|
||||
'transactions'
|
||||
)}{' '}
|
||||
in {orUnderline(config.threshold.thresholdDays, classes)}{' '}
|
||||
in {orUnderline(config.threshold.thresholdDays)}{' '}
|
||||
{singularOrPlural(config.threshold.thresholdDays, 'day', 'days')}
|
||||
</>
|
||||
)
|
||||
|
|
@ -140,7 +107,7 @@ const getTypeText = (config, currency, classes) => {
|
|||
return (
|
||||
<>
|
||||
at least one transaction every day for{' '}
|
||||
{orUnderline(config.threshold.thresholdDays, classes)}{' '}
|
||||
{orUnderline(config.threshold.thresholdDays)}{' '}
|
||||
{singularOrPlural(config.threshold.thresholdDays, 'day', 'days')}
|
||||
</>
|
||||
)
|
||||
|
|
@ -149,7 +116,7 @@ const getTypeText = (config, currency, classes) => {
|
|||
}
|
||||
}
|
||||
|
||||
const getRequirementText = (config, classes) => {
|
||||
const getRequirementText = config => {
|
||||
switch (config.requirement?.requirement) {
|
||||
case 'email':
|
||||
return <>asked to enter code provided through email verification</>
|
||||
|
|
@ -170,8 +137,7 @@ const getRequirementText = (config, classes) => {
|
|||
case 'suspend':
|
||||
return (
|
||||
<>
|
||||
suspended for{' '}
|
||||
{orUnderline(config.requirement.suspensionDays, classes)}{' '}
|
||||
suspended for {orUnderline(config.requirement.suspensionDays)}{' '}
|
||||
{singularOrPlural(config.requirement.suspensionDays, 'day', 'days')}
|
||||
</>
|
||||
)
|
||||
|
|
@ -182,28 +148,24 @@ const getRequirementText = (config, classes) => {
|
|||
case 'external':
|
||||
return <>redirected to an external verification process</>
|
||||
default:
|
||||
return orUnderline(null, classes)
|
||||
return orUnderline(null)
|
||||
}
|
||||
}
|
||||
|
||||
const InfoPanel = ({ step, config = {}, liveValues = {}, currency }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const oldText = R.range(1, step).map((it, idx) => (
|
||||
<React.Fragment key={idx}>
|
||||
{getText(it, config, currency, classes)}
|
||||
</React.Fragment>
|
||||
<React.Fragment key={idx}>{getText(it, config, currency)}</React.Fragment>
|
||||
))
|
||||
const newText = getText(step, liveValues, currency, classes)
|
||||
const newText = getText(step, liveValues, currency)
|
||||
const isLastStep = step === LAST_STEP
|
||||
|
||||
return (
|
||||
<>
|
||||
<H5 className={classes.infoTitle}>Trigger overview so far</H5>
|
||||
<H5 className="my-5 mx-0">Trigger overview so far</H5>
|
||||
<Info3 noMargin>
|
||||
{oldText}
|
||||
{step !== 1 && ', '}
|
||||
<span className={classes.infoCurrentText}>{newText}</span>
|
||||
<span className="text-comet">{newText}</span>
|
||||
{!isLastStep && '...'}
|
||||
</Info3>
|
||||
</>
|
||||
|
|
@ -229,8 +191,6 @@ const Wizard = ({
|
|||
emailAuth,
|
||||
triggers
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const [liveValues, setLiveValues] = useState({})
|
||||
const [{ step, config }, setState] = useState({
|
||||
step: 1
|
||||
|
|
@ -321,11 +281,7 @@ const Wizard = ({
|
|||
}
|
||||
infoPanelHeight={172}
|
||||
open={true}>
|
||||
<Stepper
|
||||
className={classes.stepper}
|
||||
steps={LAST_STEP}
|
||||
currentStep={step}
|
||||
/>
|
||||
<Stepper className="my-4 mx-0" steps={LAST_STEP} currentStep={step} />
|
||||
<Formik
|
||||
validateOnBlur={false}
|
||||
validateOnChange={true}
|
||||
|
|
@ -334,17 +290,17 @@ const Wizard = ({
|
|||
initialValues={stepOptions.initialValues}
|
||||
validationSchema={stepOptions.schema}>
|
||||
{({ errors, touched, values }) => (
|
||||
<Form className={classes.form}>
|
||||
<Form className="h-full flex flex-col">
|
||||
<GetValues setValues={setLiveValues} />
|
||||
<stepOptions.Component {...stepOptions.props} />
|
||||
<div className={classes.submit}>
|
||||
<div className="flex flex-row mt-auto mx-0 mb-6">
|
||||
{error && <ErrorMessage>Failed to save</ErrorMessage>}
|
||||
{createErrorMessage(errors, touched, values) && (
|
||||
<ErrorMessage>
|
||||
{createErrorMessage(errors, touched, values)}
|
||||
</ErrorMessage>
|
||||
)}
|
||||
<Button className={classes.button} type="submit">
|
||||
<Button className="ml-auto" type="submit">
|
||||
{isLastStep ? 'Finish' : 'Next'}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { makeStyles } from '@mui/styles'
|
||||
import classnames from 'classnames'
|
||||
import { Field, useFormikContext } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
|
|
@ -7,95 +6,9 @@ import { H4, Label2, Label1, Info1, Info2 } from 'src/components/typography'
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import { NumberInput, RadioGroup, Dropdown } from 'src/components/inputs/formik'
|
||||
import { errorColor } from 'src/styling/variables'
|
||||
import { transformNumber } from 'src/utils/number'
|
||||
import { onlyFirstToUpper } from 'src/utils/string'
|
||||
|
||||
// import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
|
||||
// import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
radioLabel: {
|
||||
height: 40,
|
||||
padding: [[0, 10]]
|
||||
},
|
||||
radio: {
|
||||
padding: 4,
|
||||
margin: 4
|
||||
},
|
||||
radioGroup: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
error: {
|
||||
color: errorColor
|
||||
},
|
||||
specialLabel: {
|
||||
height: 40,
|
||||
padding: 0
|
||||
},
|
||||
specialGrid: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: [[182, 162, 181]]
|
||||
},
|
||||
directionIcon: {
|
||||
marginRight: 2
|
||||
},
|
||||
directionName: {
|
||||
marginLeft: 6
|
||||
},
|
||||
thresholdWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
},
|
||||
thresholdTitle: {
|
||||
marginTop: 50
|
||||
},
|
||||
thresholdContentWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
thresholdField: {
|
||||
marginRight: 6,
|
||||
width: 75
|
||||
},
|
||||
description: {
|
||||
marginTop: 7
|
||||
},
|
||||
space: {
|
||||
marginLeft: 6,
|
||||
marginRight: 6
|
||||
},
|
||||
lastSpace: {
|
||||
marginLeft: 6
|
||||
},
|
||||
suspensionDays: {
|
||||
width: 34
|
||||
},
|
||||
input: {
|
||||
marginTop: -2
|
||||
},
|
||||
limitedInput: {
|
||||
width: 50
|
||||
},
|
||||
daysInput: {
|
||||
width: 60
|
||||
},
|
||||
dropdownField: {
|
||||
marginTop: 16,
|
||||
minWidth: 155
|
||||
},
|
||||
externalFields: {
|
||||
'& > *': {
|
||||
marginRight: 15
|
||||
},
|
||||
'& > *:last-child': {
|
||||
marginRight: 0
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// const direction = Yup.string().required()
|
||||
|
||||
const triggerType = Yup.string().required()
|
||||
const threshold = Yup.object().shape({
|
||||
threshold: Yup.number()
|
||||
|
|
@ -171,92 +84,6 @@ const Schema = Yup.object()
|
|||
})
|
||||
})
|
||||
|
||||
// Direction V2 only
|
||||
// const directionSchema = Yup.object().shape({ direction })
|
||||
|
||||
// const directionOptions = [
|
||||
// {
|
||||
// display: 'Both',
|
||||
// code: 'both'
|
||||
// },
|
||||
// {
|
||||
// display: 'Only cash-in',
|
||||
// code: 'cashIn'
|
||||
// },
|
||||
// {
|
||||
// display: 'Only cash-out',
|
||||
// code: 'cashOut'
|
||||
// }
|
||||
// ]
|
||||
|
||||
// const directionOptions2 = [
|
||||
// {
|
||||
// display: (
|
||||
// <>
|
||||
// <TxInIcon /> in
|
||||
// </>
|
||||
// ),
|
||||
// code: 'cashIn'
|
||||
// },
|
||||
// {
|
||||
// display: (
|
||||
// <>
|
||||
// <TxOutIcon /> out
|
||||
// </>
|
||||
// ),
|
||||
// code: 'cashOut'
|
||||
// },
|
||||
// {
|
||||
// display: (
|
||||
// <>
|
||||
// <Box display="flex">
|
||||
// <Box mr={0.25}>
|
||||
// <TxOutIcon />
|
||||
// </Box>
|
||||
// <Box>
|
||||
// <TxInIcon />
|
||||
// </Box>
|
||||
// </Box>
|
||||
// </>
|
||||
// ),
|
||||
// code: 'both'
|
||||
// }
|
||||
// ]
|
||||
|
||||
// const Direction = () => {
|
||||
// const classes = useStyles()
|
||||
// const { errors } = useFormikContext()
|
||||
|
||||
// const titleClass = {
|
||||
// [classes.error]: errors.direction
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// <Box display="flex" alignItems="center">
|
||||
// <H4 className={classnames(titleClass)}>
|
||||
// In which type of transactions will it trigger?
|
||||
// </H4>
|
||||
// </Box>
|
||||
// <Field
|
||||
// component={RadioGroup}
|
||||
// name="direction"
|
||||
// options={directionOptions}
|
||||
// labelClassName={classes.radioLabel}
|
||||
// radioClassName={classes.radio}
|
||||
// className={classes.radioGroup}
|
||||
// />
|
||||
// </>
|
||||
// )
|
||||
// }
|
||||
|
||||
// const txDirection = {
|
||||
// schema: directionSchema,
|
||||
// options: directionOptions,
|
||||
// Component: Direction,
|
||||
// initialValues: { direction: '' }
|
||||
// }
|
||||
|
||||
// TYPE
|
||||
const typeSchema = Yup.object()
|
||||
.shape({
|
||||
|
|
@ -314,18 +141,20 @@ const typeSchema = Yup.object()
|
|||
|
||||
const typeOptions = [
|
||||
{ display: 'Transaction amount', code: 'txAmount' },
|
||||
{ display: 'Transaction volume', code: 'txVolume' },
|
||||
{
|
||||
display: 'Transaction volume',
|
||||
code: 'txVolume'
|
||||
},
|
||||
{ display: 'Transaction velocity', code: 'txVelocity' },
|
||||
{ display: 'Consecutive days', code: 'consecutiveDays' }
|
||||
]
|
||||
|
||||
const Type = ({ ...props }) => {
|
||||
const classes = useStyles()
|
||||
const { errors, touched, values, setTouched, handleChange } =
|
||||
useFormikContext()
|
||||
|
||||
const typeClass = {
|
||||
[classes.error]: errors.triggerType && touched.triggerType
|
||||
'text-tomato': errors.triggerType && touched.triggerType
|
||||
}
|
||||
|
||||
const containsType = R.contains(values?.triggerType)
|
||||
|
|
@ -348,7 +177,7 @@ const Type = ({ ...props }) => {
|
|||
const triggerTypeError = !!(hasDaysError || hasAmountError)
|
||||
|
||||
const thresholdClass = {
|
||||
[classes.error]: triggerTypeError
|
||||
'text-tomato': triggerTypeError
|
||||
}
|
||||
|
||||
const isRadioGroupActive = () => {
|
||||
|
|
@ -369,9 +198,9 @@ const Type = ({ ...props }) => {
|
|||
component={RadioGroup}
|
||||
name="triggerType"
|
||||
options={typeOptions}
|
||||
labelClassName={classes.radioLabel}
|
||||
radioClassName={classes.radio}
|
||||
className={classes.radioGroup}
|
||||
labelClassName="h-10 py-0 px-3"
|
||||
radioClassName="p-1 m-1"
|
||||
className="flex-row"
|
||||
onChange={e => {
|
||||
handleChange(e)
|
||||
setTouched({
|
||||
|
|
@ -381,73 +210,58 @@ const Type = ({ ...props }) => {
|
|||
}}
|
||||
/>
|
||||
|
||||
<div className={classes.thresholdWrapper}>
|
||||
<div className="flex flex-col">
|
||||
{isRadioGroupActive() && (
|
||||
<H4 className={classnames(thresholdClass, classes.thresholdTitle)}>
|
||||
Threshold
|
||||
</H4>
|
||||
<H4 className={classnames(thresholdClass, 'mt-12')}>Threshold</H4>
|
||||
)}
|
||||
<div className={classes.thresholdContentWrapper}>
|
||||
<div className="flex flex-row">
|
||||
{isThresholdCurrencyEnabled && (
|
||||
<>
|
||||
<Field
|
||||
className={classes.thresholdField}
|
||||
className="mr-2 w-19"
|
||||
component={NumberInput}
|
||||
size="lg"
|
||||
name="threshold.threshold"
|
||||
error={hasAmountError}
|
||||
/>
|
||||
<Info1 className={classnames(classes.description)}>
|
||||
{props.currency}
|
||||
</Info1>
|
||||
<Info1 className="mt-2">{props.currency}</Info1>
|
||||
</>
|
||||
)}
|
||||
{isTransactionAmountEnabled && (
|
||||
<>
|
||||
<Field
|
||||
className={classes.thresholdField}
|
||||
className="mr-2 w-19"
|
||||
component={NumberInput}
|
||||
size="lg"
|
||||
name="threshold.threshold"
|
||||
error={hasAmountError}
|
||||
/>
|
||||
<Info1 className={classnames(classes.description)}>
|
||||
transactions
|
||||
</Info1>
|
||||
<Info1 className="mt-2">transactions</Info1>
|
||||
</>
|
||||
)}
|
||||
{isThresholdDaysEnabled && (
|
||||
<>
|
||||
<Info1
|
||||
className={classnames(
|
||||
typeClass,
|
||||
classes.space,
|
||||
classes.description
|
||||
)}>
|
||||
in
|
||||
</Info1>
|
||||
<Info1 className={classnames(typeClass, 'mx-2 mt-2')}>in</Info1>
|
||||
<Field
|
||||
className={classes.thresholdField}
|
||||
className="mr-2 w-19"
|
||||
component={NumberInput}
|
||||
size="lg"
|
||||
name="threshold.thresholdDays"
|
||||
error={hasDaysError}
|
||||
/>
|
||||
<Info1 className={classnames(classes.description)}>days</Info1>
|
||||
<Info1 className="mt-2">days</Info1>
|
||||
</>
|
||||
)}
|
||||
{isConsecutiveDaysEnabled && (
|
||||
<>
|
||||
<Field
|
||||
className={classes.thresholdField}
|
||||
className="mr-2 w-19"
|
||||
component={NumberInput}
|
||||
size="lg"
|
||||
name="threshold.thresholdDays"
|
||||
error={hasDaysError}
|
||||
/>
|
||||
<Info1 className={classnames(classes.description)}>
|
||||
consecutive days
|
||||
</Info1>
|
||||
<Info1 className="mt-2">consecutive days</Info1>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -527,16 +341,27 @@ const requirementSchema = Yup.object()
|
|||
|
||||
const requirementOptions = [
|
||||
{ display: 'SMS verification', code: 'sms' },
|
||||
{ display: 'Email verification', code: 'email' },
|
||||
{
|
||||
display: 'Email verification',
|
||||
code: 'email'
|
||||
},
|
||||
{ display: 'ID card image', code: 'idCardPhoto' },
|
||||
{ display: 'ID data', code: 'idCardData' },
|
||||
{
|
||||
display: 'ID data',
|
||||
code: 'idCardData'
|
||||
},
|
||||
{ display: 'Customer camera', code: 'facephoto' },
|
||||
{ display: 'Sanctions', code: 'sanctions' },
|
||||
{ display: 'US SSN', code: 'usSsn' },
|
||||
// { display: 'Super user', code: 'superuser' },
|
||||
{
|
||||
display: 'US SSN',
|
||||
code: 'usSsn'
|
||||
}, // { display: 'Super user', code: 'superuser' },
|
||||
{ display: 'Suspend', code: 'suspend' },
|
||||
{ display: 'Block', code: 'block' },
|
||||
{ display: 'External verification', code: 'external' }
|
||||
{
|
||||
display: 'External verification',
|
||||
code: 'external'
|
||||
}
|
||||
]
|
||||
|
||||
const hasRequirementError = (errors, touched, values) =>
|
||||
|
|
@ -563,7 +388,6 @@ const Requirement = ({
|
|||
complianceServices,
|
||||
customInfoRequests = []
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
const { touched, errors, values, handleChange, setTouched } =
|
||||
useFormikContext()
|
||||
|
||||
|
|
@ -587,7 +411,10 @@ const Requirement = ({
|
|||
const availableCustomRequirements = R.filter(
|
||||
it =>
|
||||
!R.includes(
|
||||
{ triggerType: config.triggerType, id: it.id },
|
||||
{
|
||||
triggerType: config.triggerType,
|
||||
id: it.id
|
||||
},
|
||||
customRequirementsInUse
|
||||
),
|
||||
customInfoRequests
|
||||
|
|
@ -613,7 +440,7 @@ const Requirement = ({
|
|||
enableCustomRequirement && options.push(customInfoOption)
|
||||
|
||||
const titleClass = {
|
||||
[classes.error]:
|
||||
'text-tomato':
|
||||
(!!errors.requirement && !isSuspend && !isCustom && !isExternal) ||
|
||||
(isSuspend && hasRequirementError(errors, touched, values)) ||
|
||||
(isCustom && hasCustomRequirementError(errors, touched, values)) ||
|
||||
|
|
@ -629,9 +456,9 @@ const Requirement = ({
|
|||
component={RadioGroup}
|
||||
name="requirement.requirement"
|
||||
options={options}
|
||||
labelClassName={classes.specialLabel}
|
||||
radioClassName={classes.radio}
|
||||
className={classnames(classes.radioGroup, classes.specialGrid)}
|
||||
labelClassName="h-10 p-0"
|
||||
radioClassName="p-1 m-1"
|
||||
className="flex-row grid grid-cols-[182px_162px_181px]"
|
||||
onChange={e => {
|
||||
handleChange(e)
|
||||
setTouched({
|
||||
|
|
@ -641,7 +468,7 @@ const Requirement = ({
|
|||
/>
|
||||
{isSuspend && (
|
||||
<Field
|
||||
className={classes.thresholdField}
|
||||
className="mr-2 w-19"
|
||||
component={NumberInput}
|
||||
label="Days"
|
||||
size="lg"
|
||||
|
|
@ -652,7 +479,7 @@ const Requirement = ({
|
|||
{isCustom && (
|
||||
<div>
|
||||
<Field
|
||||
className={classes.dropdownField}
|
||||
className="mt-4 min-w-[155px]"
|
||||
component={Dropdown}
|
||||
label="Available requests"
|
||||
name="requirement.customInfoRequestId"
|
||||
|
|
@ -661,9 +488,9 @@ const Requirement = ({
|
|||
</div>
|
||||
)}
|
||||
{isExternal && (
|
||||
<div className={classes.externalFields}>
|
||||
<div className="flex flex-col gap-4">
|
||||
<Field
|
||||
className={classes.dropdownField}
|
||||
className="mt-4 w-[155px]"
|
||||
component={Dropdown}
|
||||
label="Service"
|
||||
name="requirement.externalService"
|
||||
|
|
@ -714,29 +541,12 @@ const getView = (data, code, compare) => it => {
|
|||
return R.compose(R.prop(code), R.find(R.propEq(compare ?? 'code', it)))(data)
|
||||
}
|
||||
|
||||
// const DirectionDisplay = ({ code }) => {
|
||||
// const classes = useStyles()
|
||||
// const displayName = getView(directionOptions, 'display')(code)
|
||||
// const showCashIn = code === 'cashIn' || code === 'both'
|
||||
// const showCashOut = code === 'cashOut' || code === 'both'
|
||||
|
||||
// return (
|
||||
// <div>
|
||||
// {showCashOut && <TxOutIcon className={classes.directionIcon} />}
|
||||
// {showCashIn && <TxInIcon className={classes.directionIcon} />}
|
||||
// <span className={classes.directionName}>{displayName}</span>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
|
||||
const customReqIdMatches = customReqId => it => {
|
||||
return it.id === customReqId
|
||||
}
|
||||
|
||||
const RequirementInput = ({ customInfoRequests = [] }) => {
|
||||
const { values } = useFormikContext()
|
||||
const classes = useStyles()
|
||||
|
||||
const requirement = values?.requirement?.requirement
|
||||
const customRequestId =
|
||||
R.path(['requirement', 'customInfoRequestId'])(values) ?? ''
|
||||
|
|
@ -753,7 +563,7 @@ const RequirementInput = ({ customInfoRequests = [] }) => {
|
|||
{isSuspend && (
|
||||
<Field
|
||||
bold
|
||||
className={classes.suspensionDays}
|
||||
className="w-8"
|
||||
name="requirement.suspensionDays"
|
||||
component={NumberInput}
|
||||
textAlign="center"
|
||||
|
|
@ -771,7 +581,6 @@ const RequirementView = ({
|
|||
externalService,
|
||||
customInfoRequests = []
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
const display =
|
||||
requirement === 'custom'
|
||||
? (R.path(['customRequest', 'name'])(
|
||||
|
|
@ -785,7 +594,7 @@ const RequirementView = ({
|
|||
<div className="flex items-baseline">
|
||||
{`${display} ${isSuspend ? 'for' : ''}`}
|
||||
{isSuspend && (
|
||||
<Info2 className={classes.space} noMargin>
|
||||
<Info2 className="mx-2" noMargin>
|
||||
{suspensionDays}
|
||||
</Info2>
|
||||
)}
|
||||
|
|
@ -795,12 +604,10 @@ const RequirementView = ({
|
|||
}
|
||||
|
||||
const DisplayThreshold = ({ config, currency, isEdit }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const inputClasses = {
|
||||
[classes.input]: true,
|
||||
[classes.limitedInput]: config?.triggerType === 'txVelocity',
|
||||
[classes.daysInput]: config?.triggerType === 'consecutiveDays'
|
||||
'-mt-1': true,
|
||||
'w-13': config?.triggerType === 'txVelocity',
|
||||
'w-15': config?.triggerType === 'consecutiveDays'
|
||||
}
|
||||
|
||||
const threshold = config?.threshold?.threshold
|
||||
|
|
@ -834,7 +641,7 @@ const DisplayThreshold = ({ config, currency, isEdit }) => {
|
|||
return (
|
||||
<div className="flex items-baseline justify-end">
|
||||
{Threshold}
|
||||
<Label2 noMargin className={classes.lastSpace}>
|
||||
<Label2 noMargin className="ml-2">
|
||||
{currency}
|
||||
</Label2>
|
||||
</div>
|
||||
|
|
@ -843,14 +650,14 @@ const DisplayThreshold = ({ config, currency, isEdit }) => {
|
|||
return (
|
||||
<div className="flex items-baseline justify-end">
|
||||
{Threshold}
|
||||
<Label2 noMargin className={classes.lastSpace}>
|
||||
<Label2 noMargin className="ml-2">
|
||||
{currency}
|
||||
</Label2>
|
||||
<Label1 noMargin className={classes.space}>
|
||||
<Label1 noMargin className="mx-2">
|
||||
in
|
||||
</Label1>
|
||||
{ThresholdDays}
|
||||
<Label1 noMargin className={classes.lastSpace}>
|
||||
<Label1 noMargin className="ml-2">
|
||||
days
|
||||
</Label1>
|
||||
</div>
|
||||
|
|
@ -859,11 +666,11 @@ const DisplayThreshold = ({ config, currency, isEdit }) => {
|
|||
return (
|
||||
<div className="flex items-baseline justify-end">
|
||||
{Threshold}
|
||||
<Label1 className={classes.space} noMargin>
|
||||
<Label1 className="mx-2" noMargin>
|
||||
transactions in
|
||||
</Label1>
|
||||
{ThresholdDays}
|
||||
<Label1 className={classes.lastSpace} noMargin>
|
||||
<Label1 className="ml-2" noMargin>
|
||||
days
|
||||
</Label1>
|
||||
</div>
|
||||
|
|
@ -872,7 +679,7 @@ const DisplayThreshold = ({ config, currency, isEdit }) => {
|
|||
return (
|
||||
<div className="flex items-baseline justify-end">
|
||||
{ThresholdDays}
|
||||
<Label1 className={classes.lastSpace} noMargin>
|
||||
<Label1 className="mx-2" noMargin>
|
||||
days
|
||||
</Label1>
|
||||
</div>
|
||||
|
|
@ -892,7 +699,7 @@ const ThresholdView = ({ config, currency }) => {
|
|||
return <DisplayThreshold config={config} currency={currency} />
|
||||
}
|
||||
|
||||
const getElements = (currency, classes, customInfoRequests) => [
|
||||
const getElements = (currency, customInfoRequests) => [
|
||||
{
|
||||
name: 'triggerType',
|
||||
size: 'sm',
|
||||
|
|
@ -926,18 +733,6 @@ const getElements = (currency, classes, customInfoRequests) => [
|
|||
input: () => <ThresholdInput currency={currency} />,
|
||||
view: (it, config) => <ThresholdView config={config} currency={currency} />
|
||||
}
|
||||
// {
|
||||
// name: 'direction',
|
||||
// size: 'sm',
|
||||
// width: 282,
|
||||
// view: it => <DirectionDisplay code={it} />,
|
||||
// input: RadioGroup,
|
||||
// inputProps: {
|
||||
// labelClassName: classes.tableRadioLabel,
|
||||
// className: classes.tableRadioGroup,
|
||||
// options: directionOptions2
|
||||
// }
|
||||
// }
|
||||
]
|
||||
|
||||
const triggerOrder = R.map(R.prop('code'))(typeOptions)
|
||||
|
|
@ -987,8 +782,7 @@ const toServer = triggers =>
|
|||
|
||||
export {
|
||||
Schema,
|
||||
getElements,
|
||||
// txDirection,
|
||||
getElements, // txDirection,
|
||||
type,
|
||||
requirements,
|
||||
sortBy,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import React, { useState } from 'react'
|
|||
import ErrorMessage from 'src/components/ErrorMessage'
|
||||
import Modal from 'src/components/Modal'
|
||||
import { H1, H3, Info2, P, Mono } from 'src/components/typography'
|
||||
import CopyToClipboard from 'src/pages/Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from 'src/components/CopyToClipboard.jsx'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { Button } from 'src/components/buttons'
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useMutation, gql } from "@apollo/client";
|
||||
import { useMutation, gql } from '@apollo/client'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import ErrorMessage from 'src/components/ErrorMessage'
|
||||
import Modal from 'src/components/Modal'
|
||||
import { Info2, P, Mono } from 'src/components/typography'
|
||||
import CopyToClipboard from 'src/pages/Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from 'src/components/CopyToClipboard.jsx'
|
||||
|
||||
import { urlResolver } from 'src/utils/urlResolver'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useMutation, gql } from "@apollo/client";
|
||||
import { useMutation, gql } from '@apollo/client'
|
||||
import { makeStyles } from '@mui/styles'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import ErrorMessage from 'src/components/ErrorMessage'
|
||||
import Modal from 'src/components/Modal'
|
||||
import { Info2, P, Mono } from 'src/components/typography'
|
||||
import CopyToClipboard from 'src/pages/Transactions/CopyToClipboard'
|
||||
import CopyToClipboard from 'src/components/CopyToClipboard.jsx'
|
||||
|
||||
import { urlResolver } from 'src/utils/urlResolver'
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue