feat: added multicassette to notifications override

This commit is contained in:
Sérgio Salgado 2021-10-27 15:32:19 +01:00
parent f32d02a808
commit 20a3c40c48
5 changed files with 171 additions and 130 deletions

View file

@ -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

View file

@ -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>
)
)
}

View file

@ -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>

View file

@ -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',

View file

@ -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}