diff --git a/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js b/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js index e411e5dc..a0732a3b 100644 --- a/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js +++ b/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js @@ -2,18 +2,21 @@ import { useQuery, useMutation } from '@apollo/react-hooks' import { makeStyles } from '@material-ui/core' import gql from 'graphql-tag' import * as R from 'ramda' -import React from 'react' +import React, { useState } from 'react' import * as Yup from 'yup' +import { IconButton } from 'src/components/buttons' import { Table as EditableTable } from 'src/components/editableTable' import { CashOut, CashIn } from 'src/components/inputs/cashbox/Cashbox' import { NumberInput, CashCassetteInput } from 'src/components/inputs/formik' import TitleSection from 'src/components/layout/TitleSection' import { EmptyTable } from 'src/components/table' +import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg' import { fromNamespace } from 'src/utils/config' import styles from './CashCassettes.styles.js' import CashCassettesFooter from './CashCassettesFooter' +import Wizard from './Wizard/Wizard' const useStyles = makeStyles(styles) @@ -89,6 +92,8 @@ const CashCassettes = () => { const classes = useStyles() const { data } = useQuery(GET_MACHINES_AND_CONFIG) + const [wizard, setWizard] = useState(false) + const [machineId, setMachineId] = useState('') const machines = R.path(['machines'])(data) ?? [] const config = R.path(['config'])(data) ?? {} @@ -103,7 +108,7 @@ const CashCassettes = () => { const locale = data?.config && fromNamespace('locale')(data.config) const fiatCurrency = locale?.fiatCurrency - const onSave = (...[, { id, cashbox, cassette1, cassette2 }]) => { + const onSave = (id, cashbox, cassette1, cassette2) => { return setCassetteBills({ variables: { action: 'setCassetteBills', @@ -174,6 +179,22 @@ const CashCassettes = () => { inputProps: { decimalPlaces: 0 } + }, + { + name: 'edit', + header: 'Edit', + width: 87, + view: (value, { id }) => { + return ( + { + setMachineId(id) + setWizard(true) + }}> + + + ) + } } ] @@ -184,11 +205,9 @@ const CashCassettes = () => { @@ -204,6 +223,18 @@ const CashCassettes = () => { bills={bills} deviceIds={deviceIds} /> + {wizard && ( + { + setWizard(false) + }} + error={error?.message} + save={onSave} + locale={locale} + /> + )} ) } diff --git a/new-lamassu-admin/src/pages/Maintenance/Wizard/Wizard.js b/new-lamassu-admin/src/pages/Maintenance/Wizard/Wizard.js new file mode 100644 index 00000000..61b1ab5d --- /dev/null +++ b/new-lamassu-admin/src/pages/Maintenance/Wizard/Wizard.js @@ -0,0 +1,109 @@ +import * as R from 'ramda' +import React, { useState } from 'react' +import * as Yup from 'yup' + +import Modal from 'src/components/Modal' + +import WizardSplash from './WizardSplash' +import WizardStep from './WizardStep' + +const MODAL_WIDTH = 554 +const MODAL_HEIGHT = 520 +const CASHBOX_DEFAULT_CAPACITY = 500 + +const Wizard = ({ machine, cashoutSettings, locale, onClose, save, error }) => { + const [{ step, config }, setState] = useState({ + step: 0, + config: { active: true } + }) + + const LAST_STEP = R.isEmpty(cashoutSettings) ? 1 : 3 + + const title = `Update counts` + const isLastStep = step === LAST_STEP + + const onContinue = it => { + const cashbox = config?.wasCashboxEmptied === 'YES' ? 0 : machine?.cashbox + + const newConfig = R.merge(config, it) + if (isLastStep) { + save( + machine.id, + parseInt(cashbox), + parseInt(it.cassette1Count ?? 0), + parseInt(it.cassette2Count ?? 0) + ) + return onClose() + } + + setState({ + step: step + 1, + config: newConfig + }) + } + + const steps = [ + { + type: 'cashbox', + schema: Yup.object().shape({ + wasCashboxEmptied: Yup.string().required() + }), + cashoutRequired: false + }, + { + type: 'cassette 1', + schema: Yup.object().shape({ + cassette1Count: Yup.number() + .required() + .min(0) + .max(CASHBOX_DEFAULT_CAPACITY) + }), + cashoutRequired: true + }, + { + type: 'cassette 2', + schema: Yup.object().shape({ + cassette2Count: Yup.number() + .required() + .min(0) + .max(CASHBOX_DEFAULT_CAPACITY) + }), + cashoutRequired: true + } + ] + + const filteredSteps = R.filter(it => { + return ( + !it.cashoutRequired || (!R.isEmpty(cashoutSettings) && it.cashoutRequired) + ) + }, steps) + + return ( + + {step === 0 && ( + onContinue()} /> + )} + {step !== 0 && ( + + )} + + ) +} + +export default Wizard diff --git a/new-lamassu-admin/src/pages/Maintenance/Wizard/WizardSplash.js b/new-lamassu-admin/src/pages/Maintenance/Wizard/WizardSplash.js new file mode 100644 index 00000000..26836564 --- /dev/null +++ b/new-lamassu-admin/src/pages/Maintenance/Wizard/WizardSplash.js @@ -0,0 +1,76 @@ +import { makeStyles } from '@material-ui/core' +import React from 'react' + +import { Button } from 'src/components/buttons' +import { H1, P, Info2 } from 'src/components/typography' +import cassetteOne from 'src/styling/icons/cassettes/cashout-cassette-1.svg' +import { ReactComponent as WarningIcon } from 'src/styling/icons/warning-icon/comet.svg' + +const styles = { + button: { + margin: [[35, 'auto', 0, 'auto']] + }, + modalContent: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + flex: 1, + padding: [[0, 34]] + }, + splashTitle: { + marginTop: 15 + }, + warningInfo: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + marginTop: 15 + }, + warningIcon: { + width: 25, + height: 25, + marginRight: 8, + display: 'block' + }, + warningText: { + flexBasis: '100%', + flexGrow: 1 + } +} + +const useStyles = makeStyles(styles) + +const WizardSplash = ({ name, onContinue }) => { + const classes = useStyles() + + return ( +
+ cassette +

+ Update counts +

+ + {name} + +
+ +

+ Before updating counts on Lamassu Admin, make sure you've done it + before on the machines. +

+
+
+ +

+ For cash-out cassettes, please make sure you've removed the remaining + bills before adding the new ones. +

+
+ +
+ ) +} + +export default WizardSplash diff --git a/new-lamassu-admin/src/pages/Maintenance/Wizard/WizardStep.js b/new-lamassu-admin/src/pages/Maintenance/Wizard/WizardStep.js new file mode 100644 index 00000000..558c3ad0 --- /dev/null +++ b/new-lamassu-admin/src/pages/Maintenance/Wizard/WizardStep.js @@ -0,0 +1,289 @@ +import { makeStyles } from '@material-ui/core' +import classnames from 'classnames' +import { Formik, Form, Field } from 'formik' +import * as R from 'ramda' +import React from 'react' + +import Stepper from 'src/components/Stepper' +import { Tooltip } from 'src/components/Tooltip' +import { Button } from 'src/components/buttons' +import { Cashbox } from 'src/components/inputs/cashbox/Cashbox' +import { NumberInput, RadioGroup } from 'src/components/inputs/formik' +import { Info2, H4, P, Info1 } from 'src/components/typography' +import cashbox from 'src/styling/icons/cassettes/acceptor-left.svg' +import cassetteOne from 'src/styling/icons/cassettes/dispenser-1.svg' +import cassetteTwo from 'src/styling/icons/cassettes/dispenser-2.svg' +import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' +import { zircon2 } from 'src/styling/variables' + +const styles = { + content: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + flex: 1, + paddingBottom: 32 + }, + titleDiv: { + marginBottom: 32 + }, + title: { + margin: [[0, 0, 12, 0]] + }, + stepImage: { + width: 148, + height: 196 + }, + form: { + paddingBottom: 95 + }, + verticalAlign: { + display: 'flex', + flexDirection: 'column' + }, + horizontalAlign: { + display: 'flex', + flexDirection: 'row' + }, + centerAlignment: { + alignItems: 'center' + }, + lineAlignment: { + alignItems: 'baseline' + }, + fullWidth: { + margin: [[0, 'auto']], + flexBasis: 'auto' + }, + formWrapper: { + flexBasis: '100%', + display: 'flex', + justifyContent: 'center' + }, + submit: { + float: 'right' + }, + cashboxBills: { + marginRight: 5 + }, + cassetteCashbox: { + width: 40, + height: 35 + }, + cassetteFormTitle: { + marginTop: 18 + }, + cassetteFormTitleContent: { + marginLeft: 10, + marginRight: 25 + }, + smBottomMargin: { + marginBottom: 25 + }, + fiatTotal: { + color: zircon2 + } +} + +const useStyles = makeStyles(styles) + +const WizardStep = ({ + step, + name, + machine, + cashoutSettings, + cassetteCapacity, + error, + lastStep, + steps, + fiatCurrency, + onContinue +}) => { + const classes = useStyles() + + const label = lastStep ? 'Finish' : 'Confirm' + + const cassetesArtworks = { + 1: cashbox, + 2: cassetteOne, + 3: cassetteTwo + } + + const stepOneRadioOptions = [ + { display: 'Yes', code: 'YES' }, + { display: 'No', code: 'NO' } + ] + + const cassetteInfo = { + amount: step === 2 ? machine?.cassette1 : machine?.cassette2, + denomination: step === 2 ? cashoutSettings.top : cashoutSettings.bottom + } + + const getPercentage = values => + R.clamp( + 0, + 100, + (100 * + (step === 2 + ? values.cassette1Count ?? cassetteInfo.amount + : values.cassette2Count ?? cassetteInfo.amount)) / + cassetteCapacity + ) + + return ( +
+
+ {name} + +
+ + {step === 1 && ( + + {({ values }) => ( +
+
+ cassette +
+
+

Did you empty the cash-in box?

+ +
+

Since previous update

+ Insert tooltip text here. +
+
+ + {machine?.cashbox} + +

accepted bills

+
+ {steps[step - 1].fiatAmount && ( +

+ = {steps[step - 1].fiatAmount} {fiatCurrency} +

+ )} +
+
+
+ +
+ )} +
+ )} + + {(step === 2 || step === 3) && ( + + {({ values }) => ( +
+
+ cassette +
+
+
+
+ +

+ Cash-out {step - 1} (dispenser) +

+
+ +
+

Refill bill count

+
+ +

+ {cassetteInfo.denomination} {fiatCurrency} bills loaded +

+
+

+ ={' '} + {step === 2 + ? (values.cassette1Count ?? 0) * + cassetteInfo.denomination + : (values.cassette2Count ?? 0) * + cassetteInfo.denomination}{' '} + {fiatCurrency} +

+
+
+
+ +
+ )} +
+ )} +
+ ) +} + +export default WizardStep diff --git a/new-lamassu-admin/src/styling/icons/cassettes/acceptor-left-filled.svg b/new-lamassu-admin/src/styling/icons/cassettes/acceptor-left-filled.svg new file mode 100644 index 00000000..c2a9b20c --- /dev/null +++ b/new-lamassu-admin/src/styling/icons/cassettes/acceptor-left-filled.svg @@ -0,0 +1 @@ +acceptor-left-filled \ No newline at end of file diff --git a/new-lamassu-admin/src/styling/icons/cassettes/acceptor-left.svg b/new-lamassu-admin/src/styling/icons/cassettes/acceptor-left.svg new file mode 100644 index 00000000..06519d18 --- /dev/null +++ b/new-lamassu-admin/src/styling/icons/cassettes/acceptor-left.svg @@ -0,0 +1 @@ +acceptor-left \ No newline at end of file diff --git a/new-lamassu-admin/src/styling/icons/cassettes/dispenser-1.svg b/new-lamassu-admin/src/styling/icons/cassettes/dispenser-1.svg new file mode 100644 index 00000000..a255b0b3 --- /dev/null +++ b/new-lamassu-admin/src/styling/icons/cassettes/dispenser-1.svg @@ -0,0 +1 @@ +v2-1 \ No newline at end of file diff --git a/new-lamassu-admin/src/styling/icons/cassettes/dispenser-2.svg b/new-lamassu-admin/src/styling/icons/cassettes/dispenser-2.svg new file mode 100644 index 00000000..68c9ea1b --- /dev/null +++ b/new-lamassu-admin/src/styling/icons/cassettes/dispenser-2.svg @@ -0,0 +1 @@ +v2-2 \ No newline at end of file