feat: reuse the cash cassettes page components for the machine profile instead of duplicated code
This commit is contained in:
parent
6474017563
commit
e55ebd5d84
6 changed files with 96 additions and 187 deletions
|
|
@ -81,7 +81,7 @@ const Row = ({
|
||||||
)}
|
)}
|
||||||
</Tr>
|
</Tr>
|
||||||
</div>
|
</div>
|
||||||
{expandable && expanded && (
|
{expanded && (
|
||||||
<div className={classes.after}>
|
<div className={classes.after}>
|
||||||
<Tr className={classnames({ [classes.expanded]: expanded })}>
|
<Tr className={classnames({ [classes.expanded]: expanded })}>
|
||||||
<Td width={width}>
|
<Td width={width}>
|
||||||
|
|
@ -99,6 +99,7 @@ const DataTable = ({
|
||||||
data = [],
|
data = [],
|
||||||
Details,
|
Details,
|
||||||
className,
|
className,
|
||||||
|
tableClassName,
|
||||||
expandable,
|
expandable,
|
||||||
initialExpanded,
|
initialExpanded,
|
||||||
onClick,
|
onClick,
|
||||||
|
|
@ -169,7 +170,7 @@ const DataTable = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex" flex="1" flexDirection="column">
|
<Box display="flex" flex="1" flexDirection="column">
|
||||||
<Table className={classes.table}>
|
<Table className={classnames(classes.table, tableClassName)}>
|
||||||
<THead>
|
<THead>
|
||||||
{elements.map(({ width, className, textAlign, header }, idx) => (
|
{elements.map(({ width, className, textAlign, header }, idx) => (
|
||||||
<Th
|
<Th
|
||||||
|
|
|
||||||
|
|
@ -3,92 +3,17 @@ import { makeStyles } from '@material-ui/core'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import * as Yup from 'yup'
|
|
||||||
|
|
||||||
import { IconButton } from 'src/components/buttons'
|
import DataTable from 'src/components/tables/DataTable'
|
||||||
import { Table as EditableTable } from 'src/components/editableTable'
|
import CashUnitDetails from 'src/pages/Maintenance/CashUnitDetails'
|
||||||
import { CashOut, CashIn } from 'src/components/inputs/cashbox/Cashbox'
|
|
||||||
import { NumberInput, CashCassetteInput } from 'src/components/inputs/formik'
|
|
||||||
import Wizard from 'src/pages/Maintenance/Wizard/Wizard'
|
import Wizard from 'src/pages/Maintenance/Wizard/Wizard'
|
||||||
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
|
import helper from 'src/pages/Maintenance/helper'
|
||||||
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: 203, cassette: 280, cassetteGraph: 80, editWidth: 87 },
|
|
||||||
3: { cashbox: 164, cassette: 200, cassetteGraph: 60, editWidth: 87 },
|
|
||||||
4: { cashbox: 131, cassette: 158, cassetteGraph: 40, editWidth: 87 }
|
|
||||||
}
|
|
||||||
|
|
||||||
const ValidationSchema = Yup.object().shape({
|
|
||||||
name: Yup.string().required('Required'),
|
|
||||||
cashbox: Yup.number()
|
|
||||||
.label('Cash box')
|
|
||||||
.required()
|
|
||||||
.integer()
|
|
||||||
.min(0)
|
|
||||||
.max(1000),
|
|
||||||
cassette1: Yup.number()
|
|
||||||
.required('Required')
|
|
||||||
.integer()
|
|
||||||
.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)
|
|
||||||
.max(500),
|
|
||||||
stacker1f: Yup.number()
|
|
||||||
.label('Stacker 1F')
|
|
||||||
.required('Required')
|
|
||||||
.integer()
|
|
||||||
.min(0)
|
|
||||||
.max(40),
|
|
||||||
stacker1r: Yup.number()
|
|
||||||
.label('Stacker 1R')
|
|
||||||
.required('Required')
|
|
||||||
.integer()
|
|
||||||
.min(0)
|
|
||||||
.max(60),
|
|
||||||
stacker2f: Yup.number()
|
|
||||||
.label('Stacker 2F')
|
|
||||||
.required('Required')
|
|
||||||
.integer()
|
|
||||||
.min(0)
|
|
||||||
.max(60),
|
|
||||||
stacker2r: Yup.number()
|
|
||||||
.label('Stacker 2R')
|
|
||||||
.required('Required')
|
|
||||||
.integer()
|
|
||||||
.min(0)
|
|
||||||
.max(60),
|
|
||||||
stacker3f: Yup.number()
|
|
||||||
.label('Stacker 3F')
|
|
||||||
.required('Required')
|
|
||||||
.integer()
|
|
||||||
.min(0)
|
|
||||||
.max(60),
|
|
||||||
stacker3r: Yup.number()
|
|
||||||
.label('Stacker 3R')
|
|
||||||
.required('Required')
|
|
||||||
.integer()
|
|
||||||
.min(0)
|
|
||||||
.max(60)
|
|
||||||
})
|
|
||||||
|
|
||||||
const SET_CASSETTE_BILLS = gql`
|
const SET_CASSETTE_BILLS = gql`
|
||||||
mutation MachineAction(
|
mutation MachineAction(
|
||||||
$deviceId: ID!
|
$deviceId: ID!
|
||||||
|
|
@ -114,6 +39,13 @@ const SET_CASSETTE_BILLS = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const widths = {
|
||||||
|
name: 0,
|
||||||
|
cashbox: 175,
|
||||||
|
cassettes: 585,
|
||||||
|
edit: 90
|
||||||
|
}
|
||||||
|
|
||||||
const CashCassettes = ({ machine, config, refetchData, bills }) => {
|
const CashCassettes = ({ machine, config, refetchData, bills }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
|
|
@ -121,89 +53,14 @@ const CashCassettes = ({ machine, config, refetchData, bills }) => {
|
||||||
|
|
||||||
const cashout = config && fromNamespace('cashOut')(config)
|
const cashout = config && fromNamespace('cashOut')(config)
|
||||||
const locale = config && fromNamespace('locale')(config)
|
const locale = config && fromNamespace('locale')(config)
|
||||||
const fillingPercentageSettings =
|
|
||||||
config && fromNamespace('notifications', 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 }) =>
|
|
||||||
!getCashoutSettings(deviceId).active
|
|
||||||
|
|
||||||
const elements = [
|
const elements = R.filter(it => it.name !== 'name')(
|
||||||
{
|
helper.getElements(classes, config, bills, setWizard, widths)
|
||||||
name: 'cashbox',
|
|
||||||
header: 'Cash box',
|
|
||||||
width: widthsByNumberOfCassettes[numberOfCassettes].cashbox,
|
|
||||||
stripe: false,
|
|
||||||
view: value => (
|
|
||||||
<CashIn
|
|
||||||
currency={{ code: fiatCurrency }}
|
|
||||||
notes={value}
|
|
||||||
total={R.sum(R.map(it => it.fiat)(bills))}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
input: NumberInput,
|
|
||||||
inputProps: {
|
|
||||||
decimalPlaces: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
R.until(
|
|
||||||
R.gt(R.__, numberOfCassettes),
|
|
||||||
it => {
|
|
||||||
elements.push({
|
|
||||||
name: `cassette${it}`,
|
|
||||||
header: `Cash cassette ${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}
|
|
||||||
threshold={
|
|
||||||
fillingPercentageSettings[`fillingPercentageCassette${it}`]
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
isHidden: ({ numberOfCassettes }) => it > numberOfCassettes,
|
|
||||||
input: CashCassetteInput,
|
|
||||||
inputProps: {
|
|
||||||
decimalPlaces: 0,
|
|
||||||
width: widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph,
|
|
||||||
inputClassName: classes.cashbox
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return R.add(1, it)
|
|
||||||
},
|
|
||||||
1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
elements.push({
|
|
||||||
name: 'edit',
|
|
||||||
header: 'Edit',
|
|
||||||
width: widthsByNumberOfCassettes[numberOfCassettes].editWidth,
|
|
||||||
view: () => {
|
|
||||||
return (
|
|
||||||
<IconButton
|
|
||||||
onClick={() => {
|
|
||||||
setWizard(true)
|
|
||||||
}}>
|
|
||||||
<EditIcon />
|
|
||||||
</IconButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
|
const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
|
||||||
refetchQueries: () => refetchData()
|
refetchQueries: () => refetchData()
|
||||||
})
|
})
|
||||||
|
|
@ -218,18 +75,26 @@ const CashCassettes = ({ machine, config, refetchData, bills }) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const InnerCashUnitDetails = ({ it }) => (
|
||||||
|
<CashUnitDetails
|
||||||
|
machine={it}
|
||||||
|
bills={bills[it.id] ?? []}
|
||||||
|
currency={fiatCurrency}
|
||||||
|
config={config}
|
||||||
|
hideMachineData
|
||||||
|
widths
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
return machine.name ? (
|
return machine.name ? (
|
||||||
<>
|
<>
|
||||||
<EditableTable
|
<DataTable
|
||||||
error={error?.message}
|
|
||||||
editWidth={widthsByNumberOfCassettes[numberOfCassettes].editWidth}
|
|
||||||
stripeWhen={isCashOutDisabled}
|
|
||||||
disableRowEdit={isCashOutDisabled}
|
|
||||||
name="cashboxes"
|
|
||||||
elements={elements}
|
elements={elements}
|
||||||
data={[machine]}
|
data={[machine]}
|
||||||
save={onSave}
|
Details={InnerCashUnitDetails}
|
||||||
validationSchema={ValidationSchema}
|
emptyText="No machines so far"
|
||||||
|
initialExpanded={0}
|
||||||
|
tableClassName={classes.dataTable}
|
||||||
/>
|
/>
|
||||||
{wizard && (
|
{wizard && (
|
||||||
<Wizard
|
<Wizard
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,34 @@
|
||||||
|
import { offDarkColor } from 'src/styling/variables'
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
cashbox: {
|
unitsRow: {
|
||||||
height: 36
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
margin: [[10, 0]],
|
||||||
|
'& > *': {
|
||||||
|
marginRight: 30
|
||||||
|
},
|
||||||
|
'& > *:last-child': {
|
||||||
|
marginRight: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
units: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
'& > *': {
|
||||||
|
marginRight: 10
|
||||||
|
},
|
||||||
|
'& > *:last-child': {
|
||||||
|
marginRight: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
verticalLine: {
|
||||||
|
height: '100%',
|
||||||
|
width: 1,
|
||||||
|
backgroundColor: offDarkColor
|
||||||
|
},
|
||||||
|
dataTable: {
|
||||||
|
minHeight: 290
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,10 @@ const styles = {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
minWidth: 210
|
minWidth: 210
|
||||||
},
|
},
|
||||||
billList: {
|
billList: ({ hideMachineData }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
minWidth: 160,
|
minWidth: hideMachineData ? 80 : 160,
|
||||||
'& > span': {
|
'& > span': {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -48,7 +48,7 @@ const styles = {
|
||||||
minWidth: 30
|
minWidth: 30
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
unitList: {
|
unitList: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -82,8 +82,14 @@ const styles = {
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const CashUnitDetails = ({ machine, bills, currency, config }) => {
|
const CashUnitDetails = ({
|
||||||
const classes = useStyles()
|
machine,
|
||||||
|
bills,
|
||||||
|
currency,
|
||||||
|
config,
|
||||||
|
hideMachineData = false
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles({ hideMachineData })
|
||||||
const billCount = R.countBy(it => it.fiat)(bills)
|
const billCount = R.countBy(it => it.fiat)(bills)
|
||||||
const fillingPercentageSettings = fromNamespace('notifications', config)
|
const fillingPercentageSettings = fromNamespace('notifications', config)
|
||||||
const cashout = fromNamespace('cashOut')(config)
|
const cashout = fromNamespace('cashOut')(config)
|
||||||
|
|
@ -91,10 +97,12 @@ const CashUnitDetails = ({ machine, bills, currency, config }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<div className={classes.machineData}>
|
{!hideMachineData && (
|
||||||
<Label1>Machine Model</Label1>
|
<div className={classes.machineData}>
|
||||||
<span>{modelPrettifier[machine.model]}</span>
|
<Label1>Machine Model</Label1>
|
||||||
</div>
|
<span>{modelPrettifier[machine.model]}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className={classes.billList}>
|
<div className={classes.billList}>
|
||||||
<Label1>Cash box</Label1>
|
<Label1>Cash box</Label1>
|
||||||
{R.isEmpty(billCount) && <TL2 noMargin>Empty</TL2>}
|
{R.isEmpty(billCount) && <TL2 noMargin>Empty</TL2>}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,13 @@ const GET_BATCHES_CSV = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const widths = {
|
||||||
|
name: 250,
|
||||||
|
cashbox: 200,
|
||||||
|
cassettes: 575,
|
||||||
|
edit: 90
|
||||||
|
}
|
||||||
|
|
||||||
const CashCassettes = () => {
|
const CashCassettes = () => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const [showHistory, setShowHistory] = useState(false)
|
const [showHistory, setShowHistory] = useState(false)
|
||||||
|
|
@ -176,12 +183,12 @@ const CashCassettes = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const elements = helper.getElements(
|
const elements = helper.getElements(
|
||||||
machines,
|
|
||||||
classes,
|
classes,
|
||||||
config,
|
config,
|
||||||
bills,
|
bills,
|
||||||
setMachineId,
|
setWizard,
|
||||||
setWizard
|
widths,
|
||||||
|
setMachineId
|
||||||
)
|
)
|
||||||
|
|
||||||
const InnerCashUnitDetails = ({ it }) => (
|
const InnerCashUnitDetails = ({ it }) => (
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ import { fromNamespace } from 'src/utils/config'
|
||||||
import { cashUnitCapacity } from 'src/utils/machine'
|
import { cashUnitCapacity } from 'src/utils/machine'
|
||||||
|
|
||||||
const getElements = (
|
const getElements = (
|
||||||
machines,
|
|
||||||
classes,
|
classes,
|
||||||
config,
|
config,
|
||||||
bills,
|
bills,
|
||||||
setMachineId,
|
setWizard,
|
||||||
setWizard
|
widths,
|
||||||
|
setMachineId
|
||||||
) => {
|
) => {
|
||||||
const fillingPercentageSettings = fromNamespace('notifications', config)
|
const fillingPercentageSettings = fromNamespace('notifications', config)
|
||||||
const locale = fromNamespace('locale')(config)
|
const locale = fromNamespace('locale')(config)
|
||||||
|
|
@ -25,14 +25,14 @@ const getElements = (
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
header: 'Machine',
|
header: 'Machine',
|
||||||
width: 250,
|
width: widths.name,
|
||||||
view: m => <>{m.name}</>,
|
view: m => <>{m.name}</>,
|
||||||
input: ({ field: { value: name } }) => <>{name}</>
|
input: ({ field: { value: name } }) => <>{name}</>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'cashbox',
|
name: 'cashbox',
|
||||||
header: 'Cashbox',
|
header: 'Cashbox',
|
||||||
width: 200,
|
width: widths.cashbox,
|
||||||
view: m => (
|
view: m => (
|
||||||
<CashIn
|
<CashIn
|
||||||
currency={{ code: fiatCurrency }}
|
currency={{ code: fiatCurrency }}
|
||||||
|
|
@ -51,7 +51,7 @@ const getElements = (
|
||||||
{
|
{
|
||||||
name: 'cassettes',
|
name: 'cassettes',
|
||||||
header: 'Cassettes & Recyclers',
|
header: 'Cassettes & Recyclers',
|
||||||
width: 575,
|
width: widths.cassettes,
|
||||||
view: m => {
|
view: m => {
|
||||||
return (
|
return (
|
||||||
<div className={classes.unitsRow}>
|
<div className={classes.unitsRow}>
|
||||||
|
|
@ -112,13 +112,13 @@ const getElements = (
|
||||||
{
|
{
|
||||||
name: 'edit',
|
name: 'edit',
|
||||||
header: 'Edit',
|
header: 'Edit',
|
||||||
width: 90,
|
width: widths.edit,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
view: m => {
|
view: m => {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMachineId(m.id)
|
!R.isNil(setMachineId) && setMachineId(m.id)
|
||||||
setWizard(true)
|
setWizard(true)
|
||||||
}}>
|
}}>
|
||||||
<EditIcon />
|
<EditIcon />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue