feat: add multicassette support on the dashboard
This commit is contained in:
parent
f32d02a808
commit
18ab230951
7 changed files with 143 additions and 147 deletions
|
|
@ -105,6 +105,7 @@ function getMachine (machineId, config) {
|
||||||
cassette2: r.cassette2,
|
cassette2: r.cassette2,
|
||||||
cassette3: r.cassette3,
|
cassette3: r.cassette3,
|
||||||
cassette4: r.cassette4,
|
cassette4: r.cassette4,
|
||||||
|
numberOfCassettes: r.number_of_cassettes,
|
||||||
version: r.version,
|
version: r.version,
|
||||||
model: r.model,
|
model: r.model,
|
||||||
pairedAt: new Date(r.created),
|
pairedAt: new Date(r.created),
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ const useStyles = makeStyles({
|
||||||
display: 'flex'
|
display: 'flex'
|
||||||
},
|
},
|
||||||
cashCassette: {
|
cashCassette: {
|
||||||
width: 80,
|
|
||||||
height: 36,
|
height: 36,
|
||||||
marginRight: 14
|
marginRight: 14
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import TableContainer from '@material-ui/core/TableContainer'
|
||||||
import TableHead from '@material-ui/core/TableHead'
|
import TableHead from '@material-ui/core/TableHead'
|
||||||
import TableRow from '@material-ui/core/TableRow'
|
import TableRow from '@material-ui/core/TableRow'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
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 (
|
return (
|
||||||
<TableContainer className={classes.table}>
|
<TableContainer className={classes.table}>
|
||||||
<Table>
|
<Table>
|
||||||
|
|
@ -80,18 +85,17 @@ const MachinesTable = ({ machines, numToRender }) => {
|
||||||
<TxInIcon />
|
<TxInIcon />
|
||||||
</div>
|
</div>
|
||||||
</HeaderCell> */}
|
</HeaderCell> */}
|
||||||
<HeaderCell>
|
{R.map(
|
||||||
<div className={classes.header}>
|
it => (
|
||||||
<TxOutIcon />
|
<HeaderCell>
|
||||||
<Label2 className={classes.label}> 1</Label2>
|
<div className={classes.header}>
|
||||||
</div>
|
<TxOutIcon />
|
||||||
</HeaderCell>
|
<Label2 className={classes.label}> {it + 1}</Label2>
|
||||||
<HeaderCell>
|
</div>
|
||||||
<div className={classes.header}>
|
</HeaderCell>
|
||||||
<TxOutIcon />
|
),
|
||||||
<Label2 className={classes.label}> 2</Label2>
|
R.times(R.identity, maxNumberOfCassettes)
|
||||||
</div>
|
)}
|
||||||
</HeaderCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
|
|
@ -120,12 +124,19 @@ const MachinesTable = ({ machines, numToRender }) => {
|
||||||
{/* <StyledCell align="left">
|
{/* <StyledCell align="left">
|
||||||
{makePercentageText(machine.cashbox)}
|
{makePercentageText(machine.cashbox)}
|
||||||
</StyledCell> */}
|
</StyledCell> */}
|
||||||
<StyledCell align="left">
|
{R.map(
|
||||||
{makePercentageText(machine.cassette1)}
|
it =>
|
||||||
</StyledCell>
|
machine.numberOfCassettes > it ? (
|
||||||
<StyledCell align="left">
|
<StyledCell align="left">
|
||||||
{makePercentageText(machine.cassette2)}
|
{makePercentageText(machine[`cassette${it + 1}`])}
|
||||||
</StyledCell>
|
</StyledCell>
|
||||||
|
) : (
|
||||||
|
<StyledCell align="left">
|
||||||
|
<TL2>{`— %`}</TL2>
|
||||||
|
</StyledCell>
|
||||||
|
),
|
||||||
|
R.times(R.identity, maxNumberOfCassettes)
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ const GET_DATA = gql`
|
||||||
cashbox
|
cashbox
|
||||||
cassette1
|
cassette1
|
||||||
cassette2
|
cassette2
|
||||||
|
cassette3
|
||||||
|
cassette4
|
||||||
|
numberOfCassettes
|
||||||
statuses {
|
statuses {
|
||||||
label
|
label
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,26 @@
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
import { useMutation } from '@apollo/react-hooks'
|
import { useMutation } from '@apollo/react-hooks'
|
||||||
import { makeStyles } from '@material-ui/core'
|
import { makeStyles } from '@material-ui/core'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
|
|
||||||
import { Table as EditableTable } from 'src/components/editableTable'
|
import { Table as EditableTable } from 'src/components/editableTable'
|
||||||
import { CashOut, CashIn } from 'src/components/inputs/cashbox/Cashbox'
|
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 { fromNamespace } from 'src/utils/config'
|
||||||
|
|
||||||
import styles from './Cassettes.styles'
|
import styles from './Cassettes.styles'
|
||||||
|
|
||||||
const useStyles = makeStyles(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({
|
const ValidationSchema = Yup.object().shape({
|
||||||
name: Yup.string().required('Required'),
|
name: Yup.string().required('Required'),
|
||||||
cashbox: Yup.number()
|
cashbox: Yup.number()
|
||||||
|
|
@ -27,6 +35,16 @@ const ValidationSchema = Yup.object().shape({
|
||||||
.min(0)
|
.min(0)
|
||||||
.max(500),
|
.max(500),
|
||||||
cassette2: Yup.number()
|
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')
|
.required('Required')
|
||||||
.integer()
|
.integer()
|
||||||
.min(0)
|
.min(0)
|
||||||
|
|
@ -69,6 +87,7 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
||||||
const cashout = data?.config && fromNamespace('cashOut')(data.config)
|
const cashout = data?.config && fromNamespace('cashOut')(data.config)
|
||||||
const locale = data?.config && fromNamespace('locale')(data.config)
|
const locale = data?.config && fromNamespace('locale')(data.config)
|
||||||
const fiatCurrency = locale?.fiatCurrency
|
const fiatCurrency = locale?.fiatCurrency
|
||||||
|
const numberOfCassettes = machine.numberOfCassettes
|
||||||
|
|
||||||
const getCashoutSettings = deviceId => fromNamespace(deviceId)(cashout)
|
const getCashoutSettings = deviceId => fromNamespace(deviceId)(cashout)
|
||||||
const isCashOutDisabled = ({ deviceId }) =>
|
const isCashOutDisabled = ({ deviceId }) =>
|
||||||
|
|
@ -78,7 +97,7 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
||||||
{
|
{
|
||||||
name: 'cashbox',
|
name: 'cashbox',
|
||||||
header: 'Cashbox',
|
header: 'Cashbox',
|
||||||
width: 240,
|
width: widthsByNumberOfCassettes[numberOfCassettes].cashbox,
|
||||||
stripe: false,
|
stripe: false,
|
||||||
view: value => (
|
view: value => (
|
||||||
<CashIn currency={{ code: fiatCurrency }} notes={value} total={0} />
|
<CashIn currency={{ code: fiatCurrency }} notes={value} total={0} />
|
||||||
|
|
@ -87,87 +106,44 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
||||||
inputProps: {
|
inputProps: {
|
||||||
decimalPlaces: 0
|
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, {
|
const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
|
||||||
refetchQueries: () => refetchData()
|
refetchQueries: () => refetchData()
|
||||||
})
|
})
|
||||||
|
|
@ -191,11 +167,13 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
||||||
return machine.name ? (
|
return machine.name ? (
|
||||||
<EditableTable
|
<EditableTable
|
||||||
error={error?.message}
|
error={error?.message}
|
||||||
|
enableEdit
|
||||||
|
editWidth={widthsByNumberOfCassettes[numberOfCassettes].editWidth}
|
||||||
stripeWhen={isCashOutDisabled}
|
stripeWhen={isCashOutDisabled}
|
||||||
disableRowEdit={isCashOutDisabled}
|
disableRowEdit={isCashOutDisabled}
|
||||||
name="cashboxes"
|
name="cashboxes"
|
||||||
elements={elements}
|
elements={elements}
|
||||||
data={[machine] || []}
|
data={[machine]}
|
||||||
save={onSave}
|
save={onSave}
|
||||||
validationSchema={ValidationSchema}
|
validationSchema={ValidationSchema}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
const styles = {
|
const styles = {
|
||||||
cashbox: {
|
cashbox: {
|
||||||
width: 80,
|
|
||||||
height: 36
|
height: 36
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ const GET_INFO = gql`
|
||||||
cashbox
|
cashbox
|
||||||
cassette1
|
cassette1
|
||||||
cassette2
|
cassette2
|
||||||
|
cassette3
|
||||||
|
cassette4
|
||||||
|
numberOfCassettes
|
||||||
statuses {
|
statuses {
|
||||||
label
|
label
|
||||||
type
|
type
|
||||||
|
|
@ -48,7 +51,7 @@ const getMachineID = path => path.slice(path.lastIndexOf('/') + 1)
|
||||||
|
|
||||||
const Machines = () => {
|
const Machines = () => {
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const { data, refetch } = useQuery(GET_INFO, {
|
const { data, loading, refetch } = useQuery(GET_INFO, {
|
||||||
variables: {
|
variables: {
|
||||||
deviceId: getMachineID(location.pathname)
|
deviceId: getMachineID(location.pathname)
|
||||||
}
|
}
|
||||||
|
|
@ -62,59 +65,61 @@ const Machines = () => {
|
||||||
const machineID = R.path(['deviceId'])(machine) ?? null
|
const machineID = R.path(['deviceId'])(machine) ?? null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container className={classes.grid}>
|
!loading && (
|
||||||
<Grid item xs={3}>
|
<Grid container className={classes.grid}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={3}>
|
||||||
<div className={classes.breadcrumbsContainer}>
|
<Grid item xs={12}>
|
||||||
<Breadcrumbs separator={<NavigateNextIcon fontSize="small" />}>
|
<div className={classes.breadcrumbsContainer}>
|
||||||
<Link to="/dashboard" className={classes.breadcrumbLink}>
|
<Breadcrumbs separator={<NavigateNextIcon fontSize="small" />}>
|
||||||
<Label3 noMargin className={classes.subtitle}>
|
<Link to="/dashboard" className={classes.breadcrumbLink}>
|
||||||
Dashboard
|
<Label3 noMargin className={classes.subtitle}>
|
||||||
</Label3>
|
Dashboard
|
||||||
</Link>
|
</Label3>
|
||||||
<TL2 noMargin className={classes.subtitle}>
|
</Link>
|
||||||
{machineName}
|
<TL2 noMargin className={classes.subtitle}>
|
||||||
</TL2>
|
{machineName}
|
||||||
</Breadcrumbs>
|
</TL2>
|
||||||
<Overview data={machine} onActionSuccess={refetch} />
|
</Breadcrumbs>
|
||||||
</div>
|
<Overview data={machine} onActionSuccess={refetch} />
|
||||||
</Grid>
|
</div>
|
||||||
<Grid item xs={12}>
|
</Grid>
|
||||||
{/* on hold for now <Sidebar
|
<Grid item xs={12}>
|
||||||
|
{/* on hold for now <Sidebar
|
||||||
isSelected={R.equals(selectedMachine)}
|
isSelected={R.equals(selectedMachine)}
|
||||||
selectItem={setSelectedMachine}
|
selectItem={setSelectedMachine}
|
||||||
data={machines}
|
data={machines}
|
||||||
getText={R.prop('name')}
|
getText={R.prop('name')}
|
||||||
getKey={R.prop('deviceId')}
|
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>
|
</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>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue