partial: Maintenance css migration

This commit is contained in:
Rafael Taranto 2025-05-06 18:14:49 +01:00
parent b95dd5cbbf
commit a90833726e
12 changed files with 176 additions and 725 deletions

View file

@ -1,87 +1,12 @@
import { makeStyles } from '@mui/styles'
import Chip from '@mui/material/Chip'
import * as R from 'ramda'
import React from 'react'
import { Label1, TL2 } from 'src/components/typography'
import { CashOut } from 'src/components/inputs'
import { offDarkColor } from 'src/styling/variables'
import { fromNamespace } from 'src/utils/config'
import { getCashUnitCapacity, modelPrettifier } from 'src/utils/machine'
const styles = {
wrapper: {
display: 'flex',
flexDirection: 'row',
marginTop: 12,
marginBottom: 16,
'& > *': {
marginRight: 40
},
'& > *:last-child': {
marginRight: 0
},
minHeight: 120
},
row: {
display: 'flex',
flexDirection: 'row'
},
col: {
display: 'flex',
flexDirection: 'column'
},
machineData: {
display: 'flex',
flexDirection: 'column',
minWidth: 210
},
billList: ({ hideMachineData }) => ({
display: 'flex',
flexDirection: 'column',
minWidth: hideMachineData ? 60 : 160,
'& > span': {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
'& > p': {
minWidth: 30
}
}
}),
unitList: {
display: 'flex',
flexDirection: 'row',
'& > *': {
marginRight: 20
},
'& > *:last-child': {
marginRight: 0
},
marginTop: 10
},
verticalLine: {
height: '100%',
width: 1,
backgroundColor: offDarkColor
},
label: {
marginBottom: 10
},
loadingBoxes: {
display: 'flex',
flexDirection: 'column',
'& > *': {
marginBottom: 20
},
'& > *:last-child': {
marginBottom: 0
}
}
}
const useStyles = makeStyles(styles)
const CashUnitDetails = ({
machine,
bills,
@ -89,38 +14,40 @@ const CashUnitDetails = ({
config,
hideMachineData = false
}) => {
const classes = useStyles({ hideMachineData })
const billCount = R.countBy(it => it.fiat)(bills)
const fillingPercentageSettings = fromNamespace('notifications', config)
const cashout = fromNamespace('cashOut')(config)
const getCashoutSettings = id => fromNamespace(id)(cashout)
const minWidth = hideMachineData ? 'min-w-15' : 'min-w-40'
const VerticalLine = () => <span className="h-full w-[1px] bg-comet2" />
return (
<div className={classes.wrapper}>
<div className="flex flex-row mt-3 mb-4 gap-10 min-h-30">
{!hideMachineData && (
<div className={classes.machineData}>
<div className="min-w-52">
<Label1>Machine Model</Label1>
<span>{modelPrettifier[machine.model]}</span>
</div>
)}
<div className={classes.billList}>
<div className={`flex flex-col ${minWidth}`}>
<Label1>Cash box</Label1>
{R.isEmpty(billCount) && <TL2 noMargin>Empty</TL2>}
{R.keys(billCount).map((it, idx) => (
<span key={idx}>
<TL2 noMargin>{billCount[it]}</TL2>
<span className="flex items-center" key={idx}>
<TL2 className="min-w-7" noMargin>
{billCount[it]}
</TL2>
<Chip label={`${it} ${currency}`} />
</span>
))}
</div>
<div className={classes.unitList}>
<div className="flex gap-5">
{machine.numberOfRecyclers === 0 &&
R.map(it => (
<>
<div className={classes.col}>
<Label1
noMargin
className={classes.label}>{`Cassette ${it}`}</Label1>
<div className="flex flex-col gap-2">
<Label1 noMargin>{`Cassette ${it}`}</Label1>
<CashOut
width={60}
height={40}
@ -137,18 +64,14 @@ const CashUnitDetails = ({
capacity={getCashUnitCapacity(machine.model, 'cassette')}
/>
</div>
{it !== machine.numberOfCassettes && (
<span className={classes.verticalLine} />
)}
{it !== machine.numberOfCassettes && <VerticalLine />}
</>
))(R.range(1, machine.numberOfCassettes + 1))}
{machine.numberOfRecyclers > 0 && (
<>
<div className={classes.col}>
<Label1
noMargin
className={classes.label}>{`Loading boxes`}</Label1>
<div className={classes.loadingBoxes}>
<div className="flex flex-col gap-2">
<Label1 noMargin>{`Loading boxes`}</Label1>
<div className="flex flex-col gap-5">
{R.range(1, machine.numberOfCassettes + 1).map((it, idx) => (
<CashOut
key={idx}
@ -171,18 +94,18 @@ const CashUnitDetails = ({
))}
</div>
</div>
<span className={classes.verticalLine} />
<VerticalLine />
{R.map(it => (
<>
<div className={classes.col}>
<Label1 noMargin className={classes.label}>
<div className="flex flex-col gap-2">
<Label1 noMargin>
{`Recycler ${
machine.model === 'aveiro'
? `${it} f/r`
: `${it * 2 - 1} - ${it * 2}`
}`}
</Label1>
<div className={classes.loadingBoxes}>
<div className="flex flex-col gap-5">
<CashOut
width={60}
height={40}
@ -219,9 +142,7 @@ const CashUnitDetails = ({
/>
</div>
</div>
{it !== machine.numberOfRecyclers / 2 && (
<span className={classes.verticalLine} />
)}
{it !== machine.numberOfRecyclers / 2 && <VerticalLine />}
</>
))(R.range(1, machine.numberOfRecyclers / 2 + 1))}
</>

View file

@ -1,6 +1,5 @@
import { useQuery, useMutation, gql } from '@apollo/client'
import DialogActions from '@mui/material/DialogActions'
import { makeStyles } from '@mui/styles'
import * as R from 'ramda'
import React, { useState } from 'react'
import LogsDowloaderPopover from 'src/components/LogsDownloaderPopper'
@ -21,14 +20,11 @@ import { MANUAL, AUTOMATIC } from 'src/utils/constants'
import { onlyFirstToUpper } from 'src/utils/string'
import CashUnitDetails from './CashUnitDetails'
import styles from './CashUnits.styles'
import CashCassettesFooter from './CashUnitsFooter'
import CashboxHistory from './CashboxHistory'
import Wizard from './Wizard/Wizard'
import helper from './helper'
const useStyles = makeStyles(styles)
const GET_MACHINES_AND_CONFIG = gql`
query getData($billFilters: JSONObject) {
machines {
@ -114,7 +110,6 @@ const widths = {
}
const CashCassettes = () => {
const classes = useStyles()
const [showHistory, setShowHistory] = useState(false)
const [editingSchema, setEditingSchema] = useState(null)
const [selectedRadio, setSelectedRadio] = useState(null)
@ -219,7 +214,7 @@ const CashCassettes = () => {
{
component: showHistory ? (
<LogsDowloaderPopover
className={classes.downloadLogsButton}
className="ml-4"
title="Download logs"
name="cashboxHistory"
query={GET_BATCHES_CSV}
@ -232,8 +227,7 @@ const CashCassettes = () => {
)
}
]}
iconClassName={classes.listViewButton}
className={classes.tableWidth}
className="flex items-center mr-[1px]"
appendix={
<HelpTooltip width={220}>
<P>
@ -248,18 +242,17 @@ const CashCassettes = () => {
</HelpTooltip>
}>
{!showHistory && (
<div className="flex items-center justify-end">
<Label1 className={classes.cashboxReset}>Cash box resets</Label1>
<div className="flex flex-col items-end">
<Label1 noMargin className="text-comet">
Cash box resets
</Label1>
<div className="flex items-center justify-end -mr-1">
{cashboxReset && (
<P className={classes.selection}>
<P noMargin className="mr-2">
{onlyFirstToUpper(cashboxReset)}
</P>
)}
<IconButton
onClick={() => setEditingSchema(true)}
className={classes.button}
size="large">
<IconButton onClick={() => setEditingSchema(true)} size="large">
<EditIcon />
</IconButton>
</div>
@ -275,7 +268,7 @@ const CashCassettes = () => {
Details={InnerCashUnitDetails}
emptyText="No machines so far"
expandable
tableClassName={classes.dataTable}
tableClassName="mb-20"
/>
{data && R.isEmpty(machines) && (
@ -315,7 +308,7 @@ const CashCassettes = () => {
width={478}
handleClose={() => setEditingSchema(null)}
open={true}>
<P className={classes.descriptions}>
<P className="text-comet mt-0">
We can automatically assume you emptied a bill validator's cash
box when the machine detects that it has been removed.
</P>
@ -324,9 +317,8 @@ const CashCassettes = () => {
value={selectedRadio ?? cashboxReset}
options={[radioButtonOptions[0]]}
onChange={handleRadioButtons}
className={classes.radioButtons}
/>
<P className={classes.descriptions}>
<P className="text-comet mt-0">
Assume the cash box is emptied whenever it's removed, creating a
new batch on the history screen and setting its current balance to
zero.
@ -336,14 +328,13 @@ const CashCassettes = () => {
value={selectedRadio ?? cashboxReset}
options={[radioButtonOptions[1]]}
onChange={handleRadioButtons}
className={classes.radioButtons}
/>
<P className={classes.descriptions}>
<P className="text-comet mt-0">
Cash boxes won't be assumed emptied when removed, nor their counts
modified. Instead, to update the count and create a new batch,
you'll click the 'Edit' button on this panel.
</P>
<DialogActions className={classes.actions}>
<DialogActions>
<Button onClick={() => saveCashboxOption(selectedRadio)}>
Confirm
</Button>

View file

@ -1,33 +0,0 @@
import { offColor, offDarkColor } from 'src/styling/variables'
export default {
cashbox: {
height: 36
},
tBody: {
maxHeight: 'calc(100vh - 350px)',
overflow: 'auto'
},
tableWidth: {
display: 'flex',
alignItems: 'center',
marginRight: 1
},
descriptions: {
color: offColor,
marginTop: 0
},
cashboxReset: {
color: offColor,
margin: [[13, 0, -5, 20]]
},
selection: {
marginRight: 12
},
downloadLogsButton: {
marginLeft: 13
},
dataTable: {
marginBottom: 80
}
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import BigNumber from 'bignumber.js'
import * as R from 'ramda'
import React from 'react'
@ -9,10 +8,6 @@ import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
import { fromNamespace } from 'src/utils/config'
import { numberToFiatAmount } from 'src/utils/number'
import styles from './CashUnitsFooter.styles'
const useStyles = makeStyles(styles)
const CashCassettesFooter = ({
machines,
config,
@ -20,7 +15,6 @@ const CashCassettesFooter = ({
bills,
deviceIds
}) => {
const classes = useStyles()
const cashout = config && fromNamespace('cashOut')(config)
const getCashoutSettings = id => fromNamespace(id)(cashout)
const cashoutReducerFn = (
@ -84,33 +78,33 @@ const CashCassettesFooter = ({
).toFormat(0)
return (
<div className={classes.footerContainer}>
<div className={classes.footerContent}>
<Info3 className={classes.footerLabel}>Cash value in System</Info3>
<div className={classes.flex}>
<TxInIcon className={classes.icon} />
<Info2 className={classes.iconLabel}>Cash-in:</Info2>
<Info1 className={classes.valueDisplay}>
<div className="fixed h-16 left-0 bottom-0 w-[100vw] bg-white flex justify-around shadow-2xl">
<div className="w-300 max-h-16 flex fixed justify-around">
<Info3 className="text-comet self-center">Cash value in System</Info3>
<div className="flex">
<TxInIcon className="self-center h-5 w-5 mr-2" />
<Info2 className="self-center mr-2">Cash-in:</Info2>
<Info1 className="self-center">
{numberToFiatAmount(totalInCashBox)} {currencyCode}
</Info1>
</div>
<div className={classes.flex}>
<TxOutIcon className={classes.icon} />
<Info2 className={classes.iconLabel}>Cash-out:</Info2>
<Info1 className={classes.valueDisplay}>
<div className="flex gap-2">
<TxOutIcon className="self-center h-5 w-5" />
<Info2 className="self-center">Cash-out:</Info2>
<Info1 className="self-center">
{numberToFiatAmount(totalInCassettes)} {currencyCode}
</Info1>
</div>
<div className={classes.flex}>
<TxOutIcon className={classes.icon} />
<Info2 className={classes.iconLabel}>Recycle:</Info2>
<Info1 className={classes.valueDisplay}>
<div className="flex gap-2">
<TxOutIcon className="self-center h-5 w-5" />
<Info2 className="self-center">Recycle:</Info2>
<Info1 className="self-center">
{numberToFiatAmount(totalInRecyclers)} {currencyCode}
</Info1>
</div>
<div className={classes.flex}>
<Info2 className={classes.iconLabel}>Total:</Info2>
<Info1 className={classes.valueDisplay}>
<div className="flex gap-2">
<Info2 className="self-center">Total:</Info2>
<Info1 className="self-center">
{numberToFiatAmount(total)} {currencyCode}
</Info1>
</div>

View file

@ -1,42 +0,0 @@
import { comet } from 'src/styling/variables'
export default {
footerLabel: {
color: comet,
alignSelf: 'center'
},
footerContent: {
width: 1200,
maxHeight: 64,
display: 'flex',
justifyContent: 'space-around',
position: 'fixed'
},
footerContainer: {
position: 'fixed',
height: 64,
left: 0,
bottom: 0,
width: '100vw',
backgroundColor: 'white',
display: 'flex',
justifyContent: 'space-around',
boxShadow: [[0, -1, 10, 0, 'rgba(50, 50, 50, 0.1)']]
},
flex: {
display: 'flex'
},
icon: {
alignSelf: 'center',
height: 20,
width: 20,
marginRight: 8
},
iconLabel: {
alignSelf: 'center',
marginRight: 8
},
valueDisplay: {
alignSelf: 'center'
}
}

View file

@ -1,17 +1,11 @@
import { useQuery, gql } from "@apollo/client";
import { makeStyles } from '@mui/styles'
import { useQuery, gql } from '@apollo/client'
import * as R from 'ramda'
import React from 'react'
// import * as Yup from 'yup'
// import { Link, IconButton } from 'src/components/buttons'
// import { TextInput } from 'src/components/inputs'
import DataTable from 'src/components/tables/DataTable'
import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
import { NumberInput } from 'src/components/inputs/formik'
// import EditIconDisabled from 'src/styling/icons/action/edit/disabled.svg?react'
// import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
import { formatDate } from 'src/utils/timezones'
const GET_BATCHES = gql`
@ -29,55 +23,9 @@ const GET_BATCHES = gql`
}
`
/* const EDIT_BATCH = gql`
mutation editBatch($id: ID, $performedBy: String) {
editBatch(id: $id, performedBy: $performedBy) {
id
}
}
` */
const styles = {
operationType: {
marginLeft: 8
},
operationTypeWrapper: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
},
saveAndCancel: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between'
},
tableWrapper: {
display: 'flex',
flexDirection: 'column',
flex: 1,
marginBottom: 80
}
}
/* const schema = Yup.object().shape({
performedBy: Yup.string().nullable()
}) */
const useStyles = makeStyles(styles)
const CashboxHistory = ({ machines, currency, timezone }) => {
const classes = useStyles()
/* const [error, setError] = useState(false)
const [field, setField] = useState(null)
const [editing, setEditing] = useState(false) */
const { data: batchesData, loading: batchesLoading } = useQuery(GET_BATCHES)
/* const [editBatch] = useMutation(EDIT_BATCH, {
refetchQueries: () => ['cashboxBatches']
}) */
const loading = batchesLoading
const batches = R.path(['cashboxBatches'])(batchesData)
@ -89,18 +37,14 @@ const CashboxHistory = ({ machines, currency, timezone }) => {
`cash-cassette-${i}-refill`,
<>
<TxOutIcon />
<span className={classes.operationType}>
Cash cassette {i} refill
</span>
<span>Cash cassette {i} refill</span>
</>
),
R.assoc(
`cash-cassette-${i}-empty`,
<>
<TxOutIcon />
<span className={classes.operationType}>
Cash cassette {i} emptied
</span>
<span>Cash cassette {i} emptied</span>
</>
)
)(ret),
@ -108,35 +52,13 @@ const CashboxHistory = ({ machines, currency, timezone }) => {
'cash-box-empty': (
<>
<TxInIcon />
<span className={classes.operationType}>Cash box emptied</span>
<span>Cash box emptied</span>
</>
)
},
R.range(1, 5)
)
/* const save = row => {
const performedBy = field.performedBy === '' ? null : field.performedBy
schema
.isValid(field)
.then(() => {
setError(false)
editBatch({
variables: { id: row.id, performedBy: performedBy }
})
})
.catch(setError(true))
return close()
}
const close = () => {
setEditing(false)
setField(null)
}
const notEditing = id => field?.id !== id */
const elements = [
{
name: 'operation',
@ -144,7 +66,7 @@ const CashboxHistory = ({ machines, currency, timezone }) => {
width: 200,
textAlign: 'left',
view: it => (
<div className={classes.operationTypeWrapper}>
<div className="flex items-center gap-2">
{getOperationRender[it.operationType]}
</div>
)
@ -198,57 +120,10 @@ const CashboxHistory = ({ machines, currency, timezone }) => {
textAlign: 'right',
view: it => formatDate(it.created, timezone, 'HH:mm')
}
/* {
name: 'performedBy',
header: 'Performed by',
width: 180,
textAlign: 'left',
view: it => {
if (notEditing(it.id))
return R.isNil(it.performedBy) ? 'Unknown entity' : it.performedBy
return (
<TextInput
onChange={e => setField({ ...field, performedBy: e.target.value })}
error={error}
width={190 * 0.85}
value={field?.performedBy}
/>
)
}
},
{
name: '',
header: 'Edit',
width: 80,
textAlign: 'right',
view: it => {
if (notEditing(it.id))
return (
<IconButton
disabled={editing}
onClick={() => {
setField({ id: it.id, performedBy: it.performedBy })
setEditing(true)
}}>
{editing ? <EditIconDisabled /> : <EditIcon />}
</IconButton>
)
return (
<div className={classes.saveAndCancel}>
<Link type="submit" color="primary" onClick={() => save(it)}>
Save
</Link>
<Link color="secondary" onClick={close}>
Cancel
</Link>
</div>
)
}
} */
]
return (
<div className={classes.tableWrapper}>
<div className="flex flex-col flex-1 mb-20">
<DataTable
loading={loading}
name="cashboxHistory"

View file

@ -1,143 +1,61 @@
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import BigNumber from 'bignumber.js'
import React from 'react'
// import { Status } from 'src/components/Status'
// import LinkIcon from 'src/styling/icons/button/link/zodiac.svg?react'
import MachineActions from 'src/components/machineActions/MachineActions'
import { Label1 } from 'src/components/typography/index.jsx'
import { modelPrettifier } from 'src/utils/machine'
import { formatDate } from 'src/utils/timezones'
import { labelStyles, machineDetailsStyles } from './MachineDetailsCard.styles'
// const supportArtices = [
// {
// // Default article for non-maped statuses
// code: undefined,
// label: 'Troubleshooting',
// article:
// 'https://support.lamassu.is/hc/en-us/categories/115000075249-Troubleshooting'
// }
// // TODO add Stuck and Fully Functional statuses articles for the new-admins
// ]
// const article = ({ code: status }) =>
// supportArtices.find(({ code: article }) => article === status)
const useLStyles = makeStyles(labelStyles)
const Label = ({ children }) => {
const classes = useLStyles()
return <div className={classes.label}>{children}</div>
return <Label1 className="text-comet mb-1">{children}</Label1>
}
const useMDStyles = makeStyles(machineDetailsStyles)
const Container = ({ children, ...props }) => (
<Grid container spacing={4} {...props}>
{children}
</Grid>
)
const Item = ({ children, ...props }) => (
<Grid item xs {...props}>
{children}
</Grid>
)
const MachineDetailsRow = ({ it: machine, onActionSuccess, timezone }) => {
const classes = useMDStyles()
return (
<Container className={classes.wrapper}>
{/* <Item xs={5}>
<Container>
<Item>
<Label>Statuses</Label>
<ul className={classes.list}>
{machine.statuses.map((status, index) => (
<li className={classes.item} key={index}>
<Status status={status} />
</li>
))}
</ul>
</Item>
<Item>
<Label>Lamassu Support article</Label>
<ul className={classes.list}>
{machine.statuses
.map(article)
.map(({ label, article }, index) => (
<li className={classes.item} key={index}>
<a
className={classes.link}
target="_blank"
rel="noopener noreferrer"
href={article}>
'{label}' <LinkIcon />
</a>
</li>
))}
</ul>
</Item>
</Container>
</Item>
<Divider
orientation="vertical"
flexItem
className={classes.separator}
/> */}
<Item xs>
<Container className={classes.row}>
<Item xs={2}>
<Label>Machine model</Label>
<span>{modelPrettifier[machine.model]}</span>
</Item>
<Item xs={4}>
<Label>Paired at</Label>
<span>
{timezone &&
formatDate(machine.pairedAt, timezone, 'yyyy-MM-dd HH:mm:ss')}
</span>
</Item>
<Item xs={6}>
<MachineActions
machine={machine}
onActionSuccess={onActionSuccess}></MachineActions>
</Item>
<Item xs={2}>
<Label>Network speed</Label>
<span>
{machine.downloadSpeed
? new BigNumber(machine.downloadSpeed).toFixed(4).toString() +
' MB/s'
: 'unavailable'}
</span>
</Item>
<Item xs={2}>
<Label>Latency</Label>
<span>
{machine.responseTime
? new BigNumber(machine.responseTime).toFixed(3).toString() +
' ms'
: 'unavailable'}
</span>
</Item>
<Item xs={2}>
<Label>Packet loss</Label>
<span>
{machine.packetLoss
? new BigNumber(machine.packetLoss).toFixed(3).toString() +
' %'
: 'unavailable'}
</span>
</Item>
</Container>
</Item>
</Container>
<div className="flex flex-wrap mt-3 mb-4 text-sm">
<div className="w-1/4">
<Label>Machine model</Label>
<span>{modelPrettifier[machine.model]}</span>
</div>
<div className="w-1/4">
<Label>Paired at</Label>
<span>
{timezone &&
formatDate(machine.pairedAt, timezone, 'yyyy-MM-dd HH:mm:ss')}
</span>
</div>
<div className="w-1/2 flex-1/2">
<MachineActions
machine={machine}
onActionSuccess={onActionSuccess}></MachineActions>
</div>
<div className="w-1/6">
<Label>Network speed</Label>
<span>
{machine.downloadSpeed
? new BigNumber(machine.downloadSpeed).toFixed(4).toString() +
' MB/s'
: 'unavailable'}
</span>
</div>
<div className="w-1/6">
<Label>Latency</Label>
<span>
{machine.responseTime
? new BigNumber(machine.responseTime).toFixed(3).toString() + ' ms'
: 'unavailable'}
</span>
</div>
<div className="w-1/6">
<Label>Packet loss</Label>
<span>
{machine.packetLoss
? new BigNumber(machine.packetLoss).toFixed(3).toString() + ' %'
: 'unavailable'}
</span>
</div>
</div>
)
}

View file

@ -1,47 +0,0 @@
import { alpha } from '@mui/material/styles'
import {
detailsRowStyles,
labelStyles
} from 'src/pages/Transactions/Transactions.styles'
import { spacer, comet, primaryColor, fontSize4 } from 'src/styling/variables'
const machineDetailsStyles = {
...detailsRowStyles,
wrapper: {
display: 'flex',
// marginTop: 24,
// marginBottom: 32,
marginTop: 12,
marginBottom: 16,
fontSize: fontSize4
},
row: {
display: 'flex',
flexDirection: 'row'
// marginBottom: 36
},
list: {
padding: 0,
margin: 0,
listStyle: 'none'
},
item: {
height: spacer * 3,
marginBottom: spacer * 1.5
},
link: {
color: primaryColor,
textDecoration: 'none'
},
separator: {
width: 1,
height: 170,
zIndex: 1,
marginRight: 60,
marginLeft: 'auto',
background: alpha(comet, 0.5)
}
}
export { labelStyles, machineDetailsStyles }

View file

@ -1,5 +1,4 @@
import { useQuery, gql } from "@apollo/client";
import { makeStyles } from '@mui/styles'
import { useQuery, gql } from '@apollo/client'
import { formatDistance } from 'date-fns'
import * as R from 'ramda'
import React from 'react'
@ -7,12 +6,11 @@ import { useHistory, useLocation } from 'react-router-dom'
import { MainStatus } from 'src/components/Status'
import Title from 'src/components/Title'
import DataTable from 'src/components/tables/DataTable'
import { Label1 } from 'src/components/typography/index.jsx'
import MachineRedirectIcon from 'src/styling/icons/month arrows/right.svg?react'
import WarningIcon from 'src/styling/icons/status/pumpkin.svg?react'
import ErrorIcon from 'src/styling/icons/status/tomato.svg?react'
import { mainStyles } from 'src/pages/Transactions/Transactions.styles'
import MachineDetailsRow from './MachineDetailsCard'
const GET_MACHINES = gql`
@ -56,10 +54,7 @@ const GET_DATA = gql`
}
`
const useStyles = makeStyles(mainStyles)
const MachineStatus = () => {
const classes = useStyles()
const history = useHistory()
const { state } = useLocation()
const addedMachineId = state?.id
@ -78,10 +73,9 @@ const MachineStatus = () => {
size: 'sm',
textAlign: 'left',
view: m => (
<div className={classes.flexRow}>
<div className="flex items-center gap-2">
{m.name}
<div
className={classes.machineRedirectContainer}
onClick={() => {
history.push(`/machines/${m.deviceId}`)
}}>
@ -131,18 +125,16 @@ const MachineStatus = () => {
return (
<>
<div className={classes.titleWrapper}>
<div className={classes.titleAndButtonsContainer}>
<Title>Machine status</Title>
</div>
<div className={classes.headerLabels}>
<div>
<div className="flex justify-between items-center">
<Title>Machine status</Title>
<div className="flex gap-6">
<div className="flex items-center gap-2">
<WarningIcon />
<span>Warning</span>
<Label1 noMargin>Warning</Label1>
</div>
<div>
<div className="flex items-center gap-2">
<ErrorIcon />
<span>Error</span>
<Label1 noMargin>Error</Label1>
</div>
</div>
</div>

View file

@ -1,77 +1,35 @@
import { makeStyles } from '@mui/styles'
import React from 'react'
import { H1, P, Info2 } from 'src/components/typography'
import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react'
import { Button } from 'src/components/buttons'
import filledCassettes from 'src/styling/icons/cassettes/both-filled.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 (
<div className={classes.modalContent}>
<div className="flex flex-col items-center flex-1 pt-0 pb-12 px-8 gap-4">
<img width="148" height="196" alt="cassette" src={filledCassettes}></img>
<H1 className={classes.splashTitle} noMargin>
Update counts
</H1>
<Info2 className={classes.machineName} noMargin>
{name}
</Info2>
<div className={classes.warningInfo}>
<WarningIcon className={classes.warningIcon} />
<P noMargin className={classes.warningText}>
<div className="flex flex-col items-center">
<H1 noMargin>Update counts</H1>
<Info2 noMargin className="text-comet my-1">
{name}
</Info2>
</div>
<div className="flex items-center gap-2">
<WarningIcon className="h-6 w-6" />
<P noMargin className="flex-1">
Before updating counts on Lamassu Admin, make sure you've done it
before on the machines.
</P>
</div>
<div className={classes.warningInfo}>
<WarningIcon className={classes.warningIcon} />
<P noMargin className={classes.warningText}>
<div className="flex items-center gap-2">
<WarningIcon className="h-6 w-6" />
<P noMargin className="flex-1">
For cash cassettes, please make sure you've removed the remaining
bills before adding the new ones.
</P>
</div>
<Button className={classes.button} onClick={onContinue}>
<Button className="m-auto mb-0" onClick={onContinue}>
Get started
</Button>
</div>

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import { Formik, Form, Field } from 'formik'
import * as R from 'ramda'
@ -22,89 +21,10 @@ import tejo4CassetteOne from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cas
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 { comet, errorColor } from 'src/styling/variables'
import { getCashUnitCapacity } from 'src/utils/machine'
import { numberToFiatAmount } from 'src/utils/number'
import { startCase } from 'src/utils/string'
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
},
errorMessage: {
color: errorColor
},
stepErrorMessage: {
maxWidth: 275,
marginTop: 25
}
}
const useStyles = makeStyles(styles)
import classes from './WizardStep.module.css'
const CASHBOX_STEP = 1
@ -171,8 +91,6 @@ const WizardStep = ({
onContinue,
initialValues
}) => {
const classes = useStyles()
const label = lastStep ? 'Finish' : 'Confirm'
const stepOneRadioOptions = [
@ -197,9 +115,11 @@ const WizardStep = ({
)
return (
<div className={classes.content}>
<div className={classes.titleDiv}>
<Info2 className={classes.title}>{name}</Info2>
<div className="flex flex-col flex-1 pb-6 gap-6">
<div className="mb-4">
<Info2 noMargin className="mb-3">
{name}
</Info2>
<Stepper steps={steps.length} currentStep={step} />
</div>
@ -212,19 +132,14 @@ const WizardStep = ({
enableReinitialize
validationSchema={steps[0].schema}>
{({ errors }) => (
<Form>
<div
className={classnames(classes.horizontalAlign, classes.form)}>
<Form className="flex flex-col flex-1">
<div className="flex flex-row pb-25">
<img
className={classes.stepImage}
alt={cashUnitCategory}
src={cashbox}></img>
<div className={classes.formWrapper}>
<div
className={classnames(
classes.verticalAlign,
classes.fullWidth
)}>
<div className={classes.verticalAlign}>
<H4 noMargin>Did you empty the cash box?</H4>
<Field
component={RadioGroup}
@ -233,14 +148,14 @@ const WizardStep = ({
className={classes.horizontalAlign}
/>
{errors.wasCashboxEmptied && (
<div className={classes.errorMessage}>
<div className="text-tomato">
{errors.wasCashboxEmptied}
</div>
)}
<div
className={classnames(
classes.horizontalAlign,
classes.centerAlignment
'items-center'
)}>
<P>Since previous update</P>
<HelpTooltip width={215}>
@ -253,9 +168,9 @@ const WizardStep = ({
<div
className={classnames(
classes.horizontalAlign,
classes.lineAlignment
'items-baseline'
)}>
<Info1 noMargin className={classes.cashboxBills}>
<Info1 noMargin className="mr-1">
{machine?.cashUnits.cashbox}
</Info1>
<P noMargin>accepted bills</P>
@ -263,7 +178,7 @@ const WizardStep = ({
</div>
</div>
</div>
<Button className={classes.submit} type="submit">
<Button className="mt-auto ml-auto" type="submit">
{label}
</Button>
</Form>
@ -280,9 +195,8 @@ const WizardStep = ({
enableReinitialize
validationSchema={steps[step - 1].schema}>
{({ values, errors }) => (
<Form>
<div
className={classnames(classes.horizontalAlign, classes.form)}>
<Form className="flex flex-col flex-1">
<div className={classnames(classes.horizontalAlign, 'pb-6')}>
<img
className={classes.stepImage}
alt={cashUnitCategory}
@ -292,25 +206,13 @@ const WizardStep = ({
numberOfRecyclers
)}></img>
<div className={classes.formWrapper}>
<div
className={classnames(
classes.verticalAlign,
classes.fullWidth
)}>
<div className={classes.verticalAlign}>
<div
className={classnames(
classes.horizontalAlign,
classes.smBottomMargin
)}>
className={classnames(classes.horizontalAlign, 'mb-6')}>
<div
className={classnames(
classes.horizontalAlign,
classes.cassetteFormTitle
)}>
className={classnames(classes.horizontalAlign, 'mt-4')}>
<TxOutIcon />
<H4
className={classes.cassetteFormTitleContent}
noMargin>
<H4 className="ml-2 mr-6" noMargin>
{startCase(cashUnitField)} (
{cashUnitCategory === 'cassette'
? `dispenser`
@ -321,7 +223,7 @@ const WizardStep = ({
</H4>
</div>
<Cashbox
className={classes.cassetteCashbox}
className="h-10 w-9"
percent={getPercentage(values)}
cashOut
/>
@ -330,7 +232,7 @@ const WizardStep = ({
<div
className={classnames(
classes.horizontalAlign,
classes.lineAlignment
'items-baseline'
)}>
<Field
component={NumberInput}
@ -338,26 +240,26 @@ const WizardStep = ({
width={50}
placeholder={originalCashUnitCount.toString()}
name={cashUnitField}
className={classes.cashboxBills}
className="mr-1"
autoFocus
/>
<P>
{cashUnitDenomination} {fiatCurrency} bills loaded
</P>
</div>
<P noMargin className={classes.fiatTotal}>
<P noMargin className="text-comet">
= {numberToFiatAmount(cassetteTotal(values))}{' '}
{fiatCurrency}
</P>
{!R.isEmpty(errors) && (
<ErrorMessage className={classes.stepErrorMessage}>
<ErrorMessage className="max-w-68 mt-6">
{R.head(R.values(errors))}
</ErrorMessage>
)}
</div>
</div>
</div>
<Button className={classes.submit} type="submit">
<Button className="ml-auto mt-auto" type="submit">
{label}
</Button>
</Form>

View file

@ -0,0 +1,22 @@
.stepImage {
width: 148px;
height: 196px;
}
.formWrapper {
flex-basis: 100%;
display: flex;
justify-content: center;
}
.verticalAlign {
display: flex;
flex-direction: column;
margin: 0 auto;
flex-basis: auto;
}
.horizontalAlign {
display: flex;
flex-direction: row;
}