feat: add multicassette support on the dashboard

This commit is contained in:
Sérgio Salgado 2021-10-27 17:26:20 +01:00
parent f32d02a808
commit 18ab230951
7 changed files with 143 additions and 147 deletions

View file

@ -105,6 +105,7 @@ function getMachine (machineId, config) {
cassette2: r.cassette2,
cassette3: r.cassette3,
cassette4: r.cassette4,
numberOfCassettes: r.number_of_cassettes,
version: r.version,
model: r.model,
pairedAt: new Date(r.created),

View file

@ -10,7 +10,6 @@ const useStyles = makeStyles({
display: 'flex'
},
cashCassette: {
width: 80,
height: 36,
marginRight: 14
}

View file

@ -6,6 +6,7 @@ import TableContainer from '@material-ui/core/TableContainer'
import TableHead from '@material-ui/core/TableHead'
import TableRow from '@material-ui/core/TableRow'
import classnames from 'classnames'
import * as R from 'ramda'
import React from 'react'
import { useHistory } from 'react-router-dom'
@ -60,6 +61,10 @@ const MachinesTable = ({ machines, numToRender }) => {
})
}
const maxNumberOfCassettes = Math.max(
...R.map(it => it.numberOfCassettes, machines)
)
return (
<TableContainer className={classes.table}>
<Table>
@ -80,18 +85,17 @@ const MachinesTable = ({ machines, numToRender }) => {
<TxInIcon />
</div>
</HeaderCell> */}
<HeaderCell>
<div className={classes.header}>
<TxOutIcon />
<Label2 className={classes.label}> 1</Label2>
</div>
</HeaderCell>
<HeaderCell>
<div className={classes.header}>
<TxOutIcon />
<Label2 className={classes.label}> 2</Label2>
</div>
</HeaderCell>
{R.map(
it => (
<HeaderCell>
<div className={classes.header}>
<TxOutIcon />
<Label2 className={classes.label}> {it + 1}</Label2>
</div>
</HeaderCell>
),
R.times(R.identity, maxNumberOfCassettes)
)}
</TableRow>
</TableHead>
<TableBody>
@ -120,12 +124,19 @@ const MachinesTable = ({ machines, numToRender }) => {
{/* <StyledCell align="left">
{makePercentageText(machine.cashbox)}
</StyledCell> */}
<StyledCell align="left">
{makePercentageText(machine.cassette1)}
</StyledCell>
<StyledCell align="left">
{makePercentageText(machine.cassette2)}
</StyledCell>
{R.map(
it =>
machine.numberOfCassettes > it ? (
<StyledCell align="left">
{makePercentageText(machine[`cassette${it + 1}`])}
</StyledCell>
) : (
<StyledCell align="left">
<TL2>{`— %`}</TL2>
</StyledCell>
),
R.times(R.identity, maxNumberOfCassettes)
)}
</TableRow>
)
}

View file

@ -27,6 +27,9 @@ const GET_DATA = gql`
cashbox
cassette1
cassette2
cassette3
cassette4
numberOfCassettes
statuses {
label
type

View file

@ -1,18 +1,26 @@
/* eslint-disable no-unused-vars */
import { 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 * as Yup from 'yup'
import { Table as EditableTable } from 'src/components/editableTable'
import { CashOut, CashIn } from 'src/components/inputs/cashbox/Cashbox'
import { NumberInput } from 'src/components/inputs/formik'
import { NumberInput, CashCassetteInput } from 'src/components/inputs/formik'
import { fromNamespace } from 'src/utils/config'
import styles from './Cassettes.styles'
const useStyles = makeStyles(styles)
const widthsByNumberOfCassettes = {
2: { cashbox: 116, cassette: 280, cassetteGraph: 80, editWidth: 174 },
3: { cashbox: 106, cassette: 200, cassetteGraph: 60, editWidth: 145 },
4: { cashbox: 106, cassette: 164, cassetteGraph: 40, editWidth: 90 }
}
const ValidationSchema = Yup.object().shape({
name: Yup.string().required('Required'),
cashbox: Yup.number()
@ -27,6 +35,16 @@ const ValidationSchema = Yup.object().shape({
.min(0)
.max(500),
cassette2: Yup.number()
.required('Required')
.integer()
.min(0)
.max(500),
cassette3: Yup.number()
.required('Required')
.integer()
.min(0)
.max(500),
cassette4: Yup.number()
.required('Required')
.integer()
.min(0)
@ -69,6 +87,7 @@ const CashCassettes = ({ machine, config, refetchData }) => {
const cashout = data?.config && fromNamespace('cashOut')(data.config)
const locale = data?.config && fromNamespace('locale')(data.config)
const fiatCurrency = locale?.fiatCurrency
const numberOfCassettes = machine.numberOfCassettes
const getCashoutSettings = deviceId => fromNamespace(deviceId)(cashout)
const isCashOutDisabled = ({ deviceId }) =>
@ -78,7 +97,7 @@ const CashCassettes = ({ machine, config, refetchData }) => {
{
name: 'cashbox',
header: 'Cashbox',
width: 240,
width: widthsByNumberOfCassettes[numberOfCassettes].cashbox,
stripe: false,
view: value => (
<CashIn currency={{ code: fiatCurrency }} notes={value} total={0} />
@ -87,87 +106,44 @@ const CashCassettes = ({ machine, config, refetchData }) => {
inputProps: {
decimalPlaces: 0
}
},
{
name: 'cassette1',
header: 'Cash-out 1',
width: 265,
stripe: true,
view: (value, { deviceId }) => (
<CashOut
className={classes.cashbox}
denomination={getCashoutSettings(deviceId)?.cassette1}
currency={{ code: fiatCurrency }}
notes={value}
/>
),
input: NumberInput,
inputProps: {
decimalPlaces: 0
}
},
{
name: 'cassette2',
header: 'Cash-out 2',
width: 265,
stripe: true,
view: (value, { deviceId }) => {
return (
<CashOut
className={classes.cashbox}
denomination={getCashoutSettings(deviceId)?.cassette2}
currency={{ code: fiatCurrency }}
notes={value}
/>
)
},
input: NumberInput,
inputProps: {
decimalPlaces: 0
}
},
{
name: 'cassette3',
header: 'Cash-out 3',
width: 265,
stripe: true,
view: (value, { deviceId }) => {
return (
<CashOut
className={classes.cashbox}
denomination={getCashoutSettings(deviceId)?.cassette2}
currency={{ code: fiatCurrency }}
notes={value}
/>
)
},
input: NumberInput,
inputProps: {
decimalPlaces: 0
}
},
{
name: 'cassette4',
header: 'Cash-out 4',
width: 265,
stripe: true,
view: (value, { deviceId }) => {
return (
<CashOut
className={classes.cashbox}
denomination={getCashoutSettings(deviceId)?.cassette2}
currency={{ code: fiatCurrency }}
notes={value}
/>
)
},
input: NumberInput,
inputProps: {
decimalPlaces: 0
}
}
]
R.until(
R.gt(R.__, numberOfCassettes),
it => {
elements.push({
name: `cassette${it}`,
header: `Cash-out ${it}`,
width: widthsByNumberOfCassettes[numberOfCassettes].cassette,
stripe: true,
doubleHeader: 'Cash-out',
view: value => {
return (
<CashOut
className={classes.cashbox}
denomination={
getCashoutSettings(machine.deviceId)?.[`cassette${it}`]
}
currency={{ code: fiatCurrency }}
notes={value}
width={widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph}
/>
)
},
isHidden: ({ numberOfCassettes }) => it > numberOfCassettes,
input: CashCassetteInput,
inputProps: {
decimalPlaces: 0,
width: widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph,
inputClassName: classes.cashbox
}
})
return R.add(1, it)
},
1
)
const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
refetchQueries: () => refetchData()
})
@ -191,11 +167,13 @@ const CashCassettes = ({ machine, config, refetchData }) => {
return machine.name ? (
<EditableTable
error={error?.message}
enableEdit
editWidth={widthsByNumberOfCassettes[numberOfCassettes].editWidth}
stripeWhen={isCashOutDisabled}
disableRowEdit={isCashOutDisabled}
name="cashboxes"
elements={elements}
data={[machine] || []}
data={[machine]}
save={onSave}
validationSchema={ValidationSchema}
/>

View file

@ -1,6 +1,5 @@
const styles = {
cashbox: {
width: 80,
height: 36
}
}

View file

@ -32,6 +32,9 @@ const GET_INFO = gql`
cashbox
cassette1
cassette2
cassette3
cassette4
numberOfCassettes
statuses {
label
type
@ -48,7 +51,7 @@ const getMachineID = path => path.slice(path.lastIndexOf('/') + 1)
const Machines = () => {
const location = useLocation()
const { data, refetch } = useQuery(GET_INFO, {
const { data, loading, refetch } = useQuery(GET_INFO, {
variables: {
deviceId: getMachineID(location.pathname)
}
@ -62,59 +65,61 @@ const Machines = () => {
const machineID = R.path(['deviceId'])(machine) ?? null
return (
<Grid container className={classes.grid}>
<Grid item xs={3}>
<Grid item xs={12}>
<div className={classes.breadcrumbsContainer}>
<Breadcrumbs separator={<NavigateNextIcon fontSize="small" />}>
<Link to="/dashboard" className={classes.breadcrumbLink}>
<Label3 noMargin className={classes.subtitle}>
Dashboard
</Label3>
</Link>
<TL2 noMargin className={classes.subtitle}>
{machineName}
</TL2>
</Breadcrumbs>
<Overview data={machine} onActionSuccess={refetch} />
</div>
</Grid>
<Grid item xs={12}>
{/* on hold for now <Sidebar
!loading && (
<Grid container className={classes.grid}>
<Grid item xs={3}>
<Grid item xs={12}>
<div className={classes.breadcrumbsContainer}>
<Breadcrumbs separator={<NavigateNextIcon fontSize="small" />}>
<Link to="/dashboard" className={classes.breadcrumbLink}>
<Label3 noMargin className={classes.subtitle}>
Dashboard
</Label3>
</Link>
<TL2 noMargin className={classes.subtitle}>
{machineName}
</TL2>
</Breadcrumbs>
<Overview data={machine} onActionSuccess={refetch} />
</div>
</Grid>
<Grid item xs={12}>
{/* on hold for now <Sidebar
isSelected={R.equals(selectedMachine)}
selectItem={setSelectedMachine}
data={machines}
getText={R.prop('name')}
getKey={R.prop('deviceId')}
/> */}
</Grid>
</Grid>
<Grid item xs={9}>
<div className={classes.content}>
<div
className={classnames(classes.detailItem, classes.detailsMargin)}>
<TL1 className={classes.subtitle}>{'Details'}</TL1>
<Details data={machine} />
</div>
<div className={classes.detailItem}>
<TL1 className={classes.subtitle}>{'Cash cassettes'}</TL1>
<Cassettes
refetchData={refetch}
machine={machine}
config={config ?? false}
/>
</div>
<div className={classes.transactionsItem}>
<TL1 className={classes.subtitle}>{'Latest transactions'}</TL1>
<Transactions id={machineID} />
</div>
<div className={classes.detailItem}>
<TL1 className={classes.subtitle}>{'Commissions'}</TL1>
<Commissions name={'commissions'} id={machineID} />
</div>
</div>
</Grid>
</Grid>
<Grid item xs={9}>
<div className={classes.content}>
<div
className={classnames(classes.detailItem, classes.detailsMargin)}>
<TL1 className={classes.subtitle}>{'Details'}</TL1>
<Details data={machine} />
</div>
<div className={classes.detailItem}>
<TL1 className={classes.subtitle}>{'Cash cassettes'}</TL1>
<Cassettes
refetchData={refetch}
machine={machine}
config={config ?? false}
/>
</div>
<div className={classes.transactionsItem}>
<TL1 className={classes.subtitle}>{'Latest transactions'}</TL1>
<Transactions id={machineID} />
</div>
<div className={classes.detailItem}>
<TL1 className={classes.subtitle}>{'Commissions'}</TL1>
<Commissions name={'commissions'} id={machineID} />
</div>
</div>
</Grid>
</Grid>
)
)
}