diff --git a/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js b/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js index bf68f3f4..04a556fd 100644 --- a/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js +++ b/new-lamassu-admin/src/pages/Maintenance/CashCassettes.js @@ -5,11 +5,13 @@ import * as R from 'ramda' 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 { ReactComponent as ReverseHistoryIcon } from 'src/styling/icons/circle buttons/history/white.svg' import { ReactComponent as HistoryIcon } from 'src/styling/icons/circle buttons/history/zodiac.svg' import { fromNamespace } from 'src/utils/config' @@ -17,6 +19,7 @@ import { fromNamespace } from 'src/utils/config' import styles from './CashCassettes.styles.js' import CashCassettesFooter from './CashCassettesFooter' import CashboxHistory from './CashboxHistory' +import Wizard from './Wizard/Wizard' const useStyles = makeStyles(styles) @@ -122,6 +125,8 @@ const CashCassettes = () => { const [showHistory, setShowHistory] = useState(false) 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) ?? {} @@ -145,9 +150,7 @@ const CashCassettes = () => { machines ) - const onSave = ( - ...[, { id, cashbox, cassette1, cassette2, cassette3, cassette4 }] - ) => { + const onSave = (id, cashbox, cassette1, cassette2, cassette3, cassette4) => { const oldCashboxCount = cashboxCounts[id] if (cashbox < oldCashboxCount) { createBatch({ @@ -226,6 +229,23 @@ const CashCassettes = () => { 1 ) + elements.push({ + name: 'edit', + header: 'Edit', + width: 87, + view: (value, { id }) => { + return ( + { + setMachineId(id) + setWizard(true) + }}> + + + ) + } + }) + return ( <> { @@ -270,6 +287,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..9c22f313 --- /dev/null +++ b/new-lamassu-admin/src/pages/Maintenance/Wizard/Wizard.js @@ -0,0 +1,103 @@ +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 numberOfCassettes = machine.numberOfCassettes + const numberOfCassetteSteps = R.isEmpty(cashoutSettings) + ? 0 + : numberOfCassettes + const LAST_STEP = numberOfCassetteSteps + 1 + + const title = `Update counts` + const isLastStep = step === LAST_STEP + + const onContinue = it => { + const cashbox = config?.wasCashboxEmptied === 'YES' ? 0 : machine?.cashbox + + console.log('Wizard.js:Wizard:it', it) + if (isLastStep) { + save( + machine.id, + parseInt(cashbox), + parseInt(it[1] ?? 0), + parseInt(it[2] ?? 0), + parseInt(it[3] ?? 0), + parseInt(it[4] ?? 0) + ) + return onClose() + } + + const newConfig = R.merge(config, it) + setState({ + step: step + 1, + config: newConfig + }) + } + + const makeCassetteSteps = R.pipe( + R.range(1), + R.map(i => ({ + type: `cassette ${i}`, + schema: Yup.object().shape({ + [i]: Yup.number() + .required() + .min(0) + .max(CASHBOX_DEFAULT_CAPACITY) + }) + })) + ) + + const steps = R.prepend( + { + type: 'cashbox', + schema: Yup.object().shape({ + wasCashboxEmptied: Yup.string().required() + }) + }, + makeCassetteSteps(numberOfCassetteSteps + 1) + ) + + 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..a5cb66ff --- /dev/null +++ b/new-lamassu-admin/src/pages/Maintenance/Wizard/WizardSplash.js @@ -0,0 +1,81 @@ +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 filledCassettes from 'src/styling/icons/cassettes/both-filled.svg' +import { ReactComponent as WarningIcon } from 'src/styling/icons/warning-icon/comet.svg' +import { comet } from 'src/styling/variables' + +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 + }, + machineName: { + margin: [[5, 0]], + color: comet + } +} + +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..fbf7841f --- /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 tejo3CassetteOne from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-1-left.svg' +import tejo3CassetteTwo from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-2-left.svg' +import tejo3CassetteThree from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-3-left.svg' +import tejo4CassetteOne from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-1-left.svg' +import tejo4CassetteTwo from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-2-left.svg' +import tejo4CassetteThree from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-3-left.svg' +import tejo4CassetteFour from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-4-left.svg' +import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' +import { comet } 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]], + color: comet + }, + 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: comet + } +} + +const useStyles = makeStyles(styles) + +const cassetesArtworks = (numberOfCassettes, step) => + [ + [cassetteOne, cassetteTwo], + [tejo3CassetteOne, tejo3CassetteTwo, tejo3CassetteThree], + [tejo4CassetteOne, tejo4CassetteTwo, tejo4CassetteThree, tejo4CassetteFour] + ][numberOfCassettes - 2][step - 2] + +const WizardStep = ({ + step, + name, + machine, + cashoutSettings, + cassetteCapacity, + error, + lastStep, + steps, + fiatCurrency, + onContinue +}) => { + const classes = useStyles() + + const label = lastStep ? 'Finish' : 'Confirm' + + const stepOneRadioOptions = [ + { display: 'Yes', code: 'YES' }, + { display: 'No', code: 'NO' } + ] + + const cassetteField = `cassette${step - 1}` + const numberOfCassettes = machine.numberOfCassettes + const originalCassetteCount = machine?.[cassetteField] + const cassetteDenomination = cashoutSettings?.[cassetteField] + + const cassetteCount = values => values[`${step - 1}`] || originalCassetteCount + const cassetteTotal = values => cassetteCount(values) * cassetteDenomination + const getPercentage = R.pipe( + cassetteCount, + count => 100 * (count / cassetteCapacity), + R.clamp(0, 100) + ) + + return ( +
+
+ {name} + +
+ + {step === 1 && ( + + {({ values }) => ( +
+
+ cassette +
+
+

Did you empty the cash-in box?

+ +
+

Since previous update

+ +

+ Number of bills inside the cashbox, since the last + cashbox changes. +

+
+
+
+ + {machine?.cashbox} + +

accepted bills

+
+
+
+
+ +
+ )} +
+ )} + + {step > 1 && ( + + {({ values }) => ( +
+
+ cassette +
+
+
+
+ +

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

+
+ +
+

Refill bill count

+
+ +

+ {cassetteDenomination} {fiatCurrency} bills loaded +

+
+

+ = {cassetteTotal(values)} {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/both-filled.svg b/new-lamassu-admin/src/styling/icons/cassettes/both-filled.svg new file mode 100644 index 00000000..6104c6dd --- /dev/null +++ b/new-lamassu-admin/src/styling/icons/cassettes/both-filled.svg @@ -0,0 +1 @@ +both-filled \ 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