feat: added multicassette to notifications override
This commit is contained in:
parent
f32d02a808
commit
20a3c40c48
5 changed files with 171 additions and 130 deletions
|
|
@ -132,7 +132,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
|
|||
SuffixComponent = TL2,
|
||||
textStyle = it => {},
|
||||
isHidden = it => false,
|
||||
view = it => it?.toString(),
|
||||
view = it => it?.toString() ?? '—',
|
||||
inputProps = {}
|
||||
} = config
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const GET_INFO = gql`
|
|||
machines {
|
||||
name
|
||||
deviceId
|
||||
numberOfCassettes
|
||||
}
|
||||
cryptoCurrencies {
|
||||
code
|
||||
|
|
@ -52,7 +53,7 @@ const Notifications = ({
|
|||
const [error, setError] = useState(null)
|
||||
const [editingKey, setEditingKey] = useState(null)
|
||||
|
||||
const { data } = useQuery(GET_INFO)
|
||||
const { data, loading } = useQuery(GET_INFO)
|
||||
|
||||
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
||||
refetchQueries: ['getData'],
|
||||
|
|
@ -100,40 +101,42 @@ const Notifications = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<NotificationsCtx.Provider value={contextValue}>
|
||||
{displayTitle && <TitleSection title="Notifications" />}
|
||||
{displaySetup && (
|
||||
<Section title="Setup" error={error && !section}>
|
||||
<Setup forceDisable={!!editingKey} wizard={wizard} />
|
||||
</Section>
|
||||
)}
|
||||
{displayTransactionAlerts && (
|
||||
<Section title="Transaction alerts" error={error && section === 'tx'}>
|
||||
<TransactionAlerts section="tx" fieldWidth={FIELDS_WIDTH} />
|
||||
</Section>
|
||||
)}
|
||||
{displayFiatAlerts && (
|
||||
<Section
|
||||
title="Fiat balance alerts"
|
||||
error={error && section === 'fiat'}>
|
||||
<FiatBalanceAlerts section="fiat" max={500} fieldWidth={50} />
|
||||
{displayOverrides && <FiatBalanceOverrides section="fiat" />}
|
||||
</Section>
|
||||
)}
|
||||
{displayCryptoAlerts && (
|
||||
<Section
|
||||
title="Crypto balance alerts"
|
||||
error={error && section === 'crypto'}>
|
||||
<CryptoBalanceAlerts section="crypto" fieldWidth={FIELDS_WIDTH} />
|
||||
{displayOverrides && (
|
||||
<CryptoBalanceOverrides
|
||||
section="crypto"
|
||||
fieldWidth={FIELDS_WIDTH}
|
||||
/>
|
||||
)}
|
||||
</Section>
|
||||
)}
|
||||
</NotificationsCtx.Provider>
|
||||
!loading && (
|
||||
<NotificationsCtx.Provider value={contextValue}>
|
||||
{displayTitle && <TitleSection title="Notifications" />}
|
||||
{displaySetup && (
|
||||
<Section title="Setup" error={error && !section}>
|
||||
<Setup forceDisable={!!editingKey} wizard={wizard} />
|
||||
</Section>
|
||||
)}
|
||||
{displayTransactionAlerts && (
|
||||
<Section title="Transaction alerts" error={error && section === 'tx'}>
|
||||
<TransactionAlerts section="tx" fieldWidth={FIELDS_WIDTH} />
|
||||
</Section>
|
||||
)}
|
||||
{displayFiatAlerts && (
|
||||
<Section
|
||||
title="Fiat balance alerts"
|
||||
error={error && section === 'fiat'}>
|
||||
<FiatBalanceAlerts section="fiat" max={500} fieldWidth={50} />
|
||||
{displayOverrides && <FiatBalanceOverrides section="fiat" />}
|
||||
</Section>
|
||||
)}
|
||||
{displayCryptoAlerts && (
|
||||
<Section
|
||||
title="Crypto balance alerts"
|
||||
error={error && section === 'crypto'}>
|
||||
<CryptoBalanceAlerts section="crypto" fieldWidth={FIELDS_WIDTH} />
|
||||
{displayOverrides && (
|
||||
<CryptoBalanceOverrides
|
||||
section="crypto"
|
||||
fieldWidth={FIELDS_WIDTH}
|
||||
/>
|
||||
)}
|
||||
</Section>
|
||||
)}
|
||||
</NotificationsCtx.Provider>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { makeStyles } from '@material-ui/core'
|
||||
import { Form, Formik } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
import React, { useContext } from 'react'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
|
|
@ -17,6 +18,7 @@ import styles from './FiatBalanceAlerts.styles.js'
|
|||
const useStyles = makeStyles(styles)
|
||||
|
||||
const NAME = 'fiatBalanceAlerts'
|
||||
const DEFAULT_NUMBER_OF_CASSETTES = 2
|
||||
|
||||
const FiatBalance = ({
|
||||
section,
|
||||
|
|
@ -24,11 +26,20 @@ const FiatBalance = ({
|
|||
max = Number.MAX_SAFE_INTEGER,
|
||||
fieldWidth = 80
|
||||
}) => {
|
||||
const { isEditing, isDisabled, setEditing, data, save } = useContext(
|
||||
NotificationsCtx
|
||||
)
|
||||
const {
|
||||
isEditing,
|
||||
isDisabled,
|
||||
setEditing,
|
||||
data,
|
||||
save,
|
||||
machines
|
||||
} = useContext(NotificationsCtx)
|
||||
const classes = useStyles()
|
||||
|
||||
const maxNumberOfCassettes =
|
||||
Math.max(...R.map(it => it.numberOfCassettes, machines)) ??
|
||||
DEFAULT_NUMBER_OF_CASSETTES
|
||||
|
||||
const editing = isEditing(NAME)
|
||||
|
||||
const schema = Yup.object().shape({
|
||||
|
|
@ -39,6 +50,18 @@ const FiatBalance = ({
|
|||
.max(max)
|
||||
.nullable(),
|
||||
fiatBalanceCassette2: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(min)
|
||||
.max(max)
|
||||
.nullable(),
|
||||
fiatBalanceCassette3: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(min)
|
||||
.max(max)
|
||||
.nullable(),
|
||||
fiatBalanceCassette4: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(min)
|
||||
|
|
@ -46,10 +69,12 @@ const FiatBalance = ({
|
|||
.nullable()
|
||||
})
|
||||
|
||||
const fiatBalanceCassette1Percent =
|
||||
(100 * (data?.fiatBalanceCassette1 ?? 0)) / max
|
||||
const fiatBalanceCassette2Percent =
|
||||
(100 * (data?.fiatBalanceCassette2 ?? 0)) / max
|
||||
const percentages = {
|
||||
cassette1: (100 * (data?.fiatBalanceCassette1 ?? 0)) / max,
|
||||
cassette2: (100 * (data?.fiatBalanceCassette2 ?? 0)) / max,
|
||||
cassette3: (100 * (data?.fiatBalanceCassette3 ?? 0)) / max,
|
||||
cassette4: (100 * (data?.fiatBalanceCassette4 ?? 0)) / max
|
||||
}
|
||||
|
||||
return (
|
||||
<Formik
|
||||
|
|
@ -58,7 +83,9 @@ const FiatBalance = ({
|
|||
enableReinitialize
|
||||
initialValues={{
|
||||
fiatBalanceCassette1: data?.fiatBalanceCassette1 ?? '',
|
||||
fiatBalanceCassette2: data?.fiatBalanceCassette2 ?? ''
|
||||
fiatBalanceCassette2: data?.fiatBalanceCassette2 ?? '',
|
||||
fiatBalanceCassette3: data?.fiatBalanceCassette3 ?? '',
|
||||
fiatBalanceCassette4: data?.fiatBalanceCassette4 ?? ''
|
||||
}}
|
||||
validationSchema={schema}
|
||||
onSubmit={it => save(section, schema.cast(it))}
|
||||
|
|
@ -74,46 +101,32 @@ const FiatBalance = ({
|
|||
setEditing={it => setEditing(NAME, it)}
|
||||
/>
|
||||
<div className={classes.wrapper}>
|
||||
<div className={classes.first}>
|
||||
<div className={classes.row}>
|
||||
<Cashbox
|
||||
labelClassName={classes.cashboxLabel}
|
||||
emptyPartClassName={classes.cashboxEmptyPart}
|
||||
percent={fiatBalanceCassette1Percent}
|
||||
cashOut
|
||||
/>
|
||||
<div className={classes.col2}>
|
||||
<TL2 className={classes.title}>Cassette 1 (Top)</TL2>
|
||||
<EditableNumber
|
||||
label="Alert me under"
|
||||
name="fiatBalanceCassette1"
|
||||
editing={editing}
|
||||
displayValue={x => (x === '' ? '-' : x)}
|
||||
decoration="notes"
|
||||
width={fieldWidth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.row}>
|
||||
<Cashbox
|
||||
labelClassName={classes.cashboxLabel}
|
||||
emptyPartClassName={classes.cashboxEmptyPart}
|
||||
percent={fiatBalanceCassette2Percent}
|
||||
cashOut
|
||||
/>
|
||||
<div className={classes.col2}>
|
||||
<TL2 className={classes.title}>Cassette 2 (Bottom)</TL2>
|
||||
<EditableNumber
|
||||
label="Alert me under"
|
||||
name="fiatBalanceCassette2"
|
||||
editing={editing}
|
||||
displayValue={x => (x === '' ? '-' : x)}
|
||||
decoration="notes"
|
||||
width={fieldWidth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{R.map(
|
||||
it => (
|
||||
<>
|
||||
<div className={classes.row}>
|
||||
<Cashbox
|
||||
labelClassName={classes.cashboxLabel}
|
||||
emptyPartClassName={classes.cashboxEmptyPart}
|
||||
percent={percentages[`cassette${it + 1}`]}
|
||||
cashOut
|
||||
/>
|
||||
<div className={classes.col2}>
|
||||
<TL2 className={classes.title}>Cassette {it + 1}</TL2>
|
||||
<EditableNumber
|
||||
label="Alert me under"
|
||||
name={`fiatBalanceCassette${it + 1}`}
|
||||
editing={editing}
|
||||
displayValue={x => (x === '' ? '-' : x)}
|
||||
decoration="notes"
|
||||
width={fieldWidth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
R.times(R.identity, maxNumberOfCassettes)
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
|
|
|||
|
|
@ -7,14 +7,11 @@ export default {
|
|||
form: {
|
||||
marginBottom: 36
|
||||
},
|
||||
first: {
|
||||
width: 236
|
||||
},
|
||||
title: {
|
||||
marginTop: 0
|
||||
},
|
||||
row: {
|
||||
width: 183,
|
||||
width: 236,
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2,1fr)',
|
||||
gridTemplateRows: '1fr',
|
||||
|
|
|
|||
|
|
@ -11,9 +11,18 @@ import NotificationsCtx from '../NotificationsContext'
|
|||
|
||||
const CASSETTE_1_KEY = 'fiatBalanceCassette1'
|
||||
const CASSETTE_2_KEY = 'fiatBalanceCassette2'
|
||||
const CASSETTE_3_KEY = 'fiatBalanceCassette3'
|
||||
const CASSETTE_4_KEY = 'fiatBalanceCassette4'
|
||||
const MACHINE_KEY = 'machine'
|
||||
const NAME = 'fiatBalanceOverrides'
|
||||
|
||||
const CASSETTE_LIST = [
|
||||
CASSETTE_1_KEY,
|
||||
CASSETTE_2_KEY,
|
||||
CASSETTE_3_KEY,
|
||||
CASSETTE_4_KEY
|
||||
]
|
||||
|
||||
const FiatBalanceOverrides = ({ section }) => {
|
||||
const {
|
||||
machines = [],
|
||||
|
|
@ -41,42 +50,62 @@ const FiatBalanceOverrides = ({ section }) => {
|
|||
const initialValues = {
|
||||
[MACHINE_KEY]: null,
|
||||
[CASSETTE_1_KEY]: '',
|
||||
[CASSETTE_2_KEY]: ''
|
||||
[CASSETTE_2_KEY]: '',
|
||||
[CASSETTE_3_KEY]: '',
|
||||
[CASSETTE_4_KEY]: ''
|
||||
}
|
||||
|
||||
const maxNumberOfCassettes = Math.max(
|
||||
...R.map(it => it.numberOfCassettes, machines)
|
||||
)
|
||||
|
||||
const notesMin = 0
|
||||
const notesMax = 9999999
|
||||
const validationSchema = Yup.object().shape(
|
||||
{
|
||||
const validationSchema = Yup.object()
|
||||
.shape({
|
||||
[MACHINE_KEY]: Yup.string()
|
||||
.label('Machine')
|
||||
.nullable()
|
||||
.required(),
|
||||
[CASSETTE_1_KEY]: Yup.number()
|
||||
.label('Cassette 1 (top)')
|
||||
.when(CASSETTE_2_KEY, {
|
||||
is: CASSETTE_2_KEY => !CASSETTE_2_KEY,
|
||||
then: Yup.number().required()
|
||||
})
|
||||
.label('Cassette 1')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(notesMin)
|
||||
.max(notesMax)
|
||||
.nullable(),
|
||||
[CASSETTE_2_KEY]: Yup.number()
|
||||
.label('Cassette 2 (bottom)')
|
||||
.when(CASSETTE_1_KEY, {
|
||||
is: CASSETTE_1_KEY => !CASSETTE_1_KEY,
|
||||
then: Yup.number().required()
|
||||
})
|
||||
.label('Cassette 2')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(notesMin)
|
||||
.max(notesMax)
|
||||
.nullable(),
|
||||
[CASSETTE_3_KEY]: Yup.number()
|
||||
.label('Cassette 3')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(notesMin)
|
||||
.max(notesMax)
|
||||
.nullable(),
|
||||
[CASSETTE_4_KEY]: Yup.number()
|
||||
.label('Cassette 4')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(notesMin)
|
||||
.max(notesMax)
|
||||
.nullable()
|
||||
},
|
||||
[CASSETTE_1_KEY, CASSETTE_2_KEY]
|
||||
)
|
||||
})
|
||||
.test((values, context) => {
|
||||
const picked = R.pick(CASSETTE_LIST, values)
|
||||
|
||||
if (CASSETTE_LIST.some(it => !R.isNil(picked[it]))) return
|
||||
|
||||
return context.createError({
|
||||
path: CASSETTE_1_KEY,
|
||||
message: 'At least one of the cassettes must have a value'
|
||||
})
|
||||
})
|
||||
|
||||
const viewMachine = it =>
|
||||
R.compose(R.path(['name']), R.find(R.propEq('deviceId', it)))(machines)
|
||||
|
|
@ -93,35 +122,34 @@ const FiatBalanceOverrides = ({ section }) => {
|
|||
valueProp: 'deviceId',
|
||||
labelProp: 'name'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: CASSETTE_1_KEY,
|
||||
display: 'Cash-out 1',
|
||||
width: 155,
|
||||
textAlign: 'right',
|
||||
doubleHeader: 'Cash-out (Cassette Empty)',
|
||||
bold: true,
|
||||
input: NumberInput,
|
||||
suffix: 'notes',
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
name: CASSETTE_2_KEY,
|
||||
display: 'Cash-out 2',
|
||||
width: 155,
|
||||
textAlign: 'right',
|
||||
doubleHeader: 'Cash-out (Cassette Empty)',
|
||||
bold: true,
|
||||
input: NumberInput,
|
||||
suffix: 'notes',
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
R.until(
|
||||
R.gt(R.__, maxNumberOfCassettes),
|
||||
it => {
|
||||
elements.push({
|
||||
name: `fiatBalanceCassette${it}`,
|
||||
display: `Cash-out ${it}`,
|
||||
width: 155,
|
||||
textAlign: 'right',
|
||||
doubleHeader: 'Cash-out (Cassette Empty)',
|
||||
bold: true,
|
||||
input: NumberInput,
|
||||
suffix: 'notes',
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
},
|
||||
isHidden: value =>
|
||||
it >
|
||||
machines.find(({ deviceId }) => deviceId === value.machine)
|
||||
?.numberOfCassettes
|
||||
})
|
||||
return R.add(1, it)
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
return (
|
||||
<EditableTable
|
||||
name={NAME}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue