partial: Dashboard and Locales css migration

This commit is contained in:
Rafael Taranto 2025-05-06 13:44:23 +01:00
parent d7b2e12f94
commit 5f81487dcc
25 changed files with 314 additions and 883 deletions

View file

@ -1,10 +1,8 @@
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import React from 'react' import React from 'react'
import { white } from 'src/styling/variables' import Paper from '@mui/material/Paper'
import classnames from 'classnames'
const cardState = Object.freeze({ const cardState = Object.freeze({
DEFAULT: 'default', DEFAULT: 'default',
@ -12,24 +10,11 @@ const cardState = Object.freeze({
EXPANDED: 'expanded' EXPANDED: 'expanded'
}) })
const styles = {
card: {
wordWrap: 'break-word',
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)',
borderRadius: 12,
padding: 24,
backgroundColor: white
}
}
const useStyles = makeStyles(styles)
const CollapsibleCard = ({ className, state, shrunkComponent, children }) => { const CollapsibleCard = ({ className, state, shrunkComponent, children }) => {
const classes = useStyles()
return ( return (
<Grid item className={classnames(className, classes.card)}> <Paper className={classnames('p-6', className)}>
{state === cardState.SHRUNK ? shrunkComponent : children} {state === cardState.SHRUNK ? shrunkComponent : children}
</Grid> </Paper>
) )
} }

View file

@ -1,14 +1,12 @@
import { useQuery, gql } from "@apollo/client"; import { useQuery, gql } from '@apollo/client'
import Button from '@mui/material/Button' import Button from '@mui/material/Button'
import Grid from '@mui/material/Grid' import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import * as R from 'ramda' import * as R from 'ramda'
import React from 'react' import React from 'react'
import { cardState } from 'src/components/CollapsibleCard' import { cardState } from 'src/components/CollapsibleCard'
import { Label1, H4 } from 'src/components/typography' import { Label1, H4 } from 'src/components/typography'
import styles from './Alerts.styles'
import AlertsTable from './AlertsTable' import AlertsTable from './AlertsTable'
const NUM_TO_RENDER = 3 const NUM_TO_RENDER = 3
@ -31,10 +29,7 @@ const GET_ALERTS = gql`
} }
` `
const useStyles = makeStyles(styles)
const Alerts = ({ onReset, onExpand, size }) => { const Alerts = ({ onReset, onExpand, size }) => {
const classes = useStyles()
const showAllItems = size === cardState.EXPANDED const showAllItems = size === cardState.EXPANDED
const { data } = useQuery(GET_ALERTS) const { data } = useQuery(GET_ALERTS)
const alerts = R.path(['alerts'])(data) ?? [] const alerts = R.path(['alerts'])(data) ?? []
@ -44,35 +39,30 @@ const Alerts = ({ onReset, onExpand, size }) => {
)(data?.machines ?? []) )(data?.machines ?? [])
const alertsLength = alerts.length const alertsLength = alerts.length
const alertsTableContainerClasses = {
[classes.alertsTableContainer]: !showAllItems,
[classes.expandedAlertsTableContainer]: showAllItems
}
return ( return (
<> <>
<div className={classes.container}> <div className="flex justify-between">
<H4 className={classes.h4}>{`Alerts (${alertsLength})`}</H4> <H4 noMargin>{`Alerts (${alertsLength})`}</H4>
{showAllItems && ( {showAllItems && (
<Label1 className={classes.upperButtonLabel}> <Label1 noMargin className="-mt-1">
<Button <Button
onClick={onReset} onClick={onReset}
size="small" size="small"
disableRipple disableRipple
disableFocusRipple disableFocusRipple
className={classes.button}> className="p-0 text-zodiac normal-case">
{'Show less'} {'Show less'}
</Button> </Button>
</Label1> </Label1>
)} )}
</div> </div>
<Grid <Grid
className={classnames(alertsTableContainerClasses)} className={classnames({ 'm-0': true, 'max-h-115': showAllItems })}
container container
spacing={1}> spacing={1}>
<Grid item xs={12}> <Grid item xs={12}>
{!alerts.length && ( {!alerts.length && (
<Label1 className={classes.noAlertsLabel}> <Label1 className="text-comet -ml-1 h-30">
No new alerts. Your system is running smoothly. No new alerts. Your system is running smoothly.
</Label1> </Label1>
)} )}
@ -85,13 +75,13 @@ const Alerts = ({ onReset, onExpand, size }) => {
</Grid> </Grid>
{!showAllItems && alertsLength > NUM_TO_RENDER && ( {!showAllItems && alertsLength > NUM_TO_RENDER && (
<Grid item xs={12}> <Grid item xs={12}>
<Label1 className={classes.centerLabel}> <Label1 className="text-center mb-0">
<Button <Button
onClick={() => onExpand('alerts')} onClick={() => onExpand('alerts')}
size="small" size="small"
disableRipple disableRipple
disableFocusRipple disableFocusRipple
className={classes.button}> className="p-0 text-zodiac normal-case">
{`Show all (${alerts.length})`} {`Show all (${alerts.length})`}
</Button> </Button>
</Label1> </Label1>

View file

@ -1,57 +0,0 @@
import { primaryColor, comet } from 'src/styling/variables'
const styles = {
container: {
display: 'flex',
justifyContent: 'space-between'
},
h4: {
margin: 0,
marginBottom: 10
},
centerLabel: {
marginBottom: 0,
padding: 0,
textAlign: 'center'
},
upperButtonLabel: {
marginTop: -3,
marginBottom: 24
},
button: {
color: primaryColor,
marginTop: 0,
minHeight: 0,
minWidth: 0,
padding: 0,
textTransform: 'none',
'&:hover': {
backgroundColor: 'transparent'
}
},
alertsTableContainer: {
margin: 0
},
expandedAlertsTableContainer: {
margin: 0,
maxHeight: 460
},
noAlertsLabel: {
color: comet,
marginLeft: -5,
height: 100
},
table: {
maxHeight: 465,
overflowX: 'hidden',
overflowY: 'auto'
},
listItemText: {
margin: '8px 0 8px 0'
},
linkIcon: {
marginLeft: 'auto',
cursor: 'pointer'
}
}
export default styles

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import List from '@mui/material/List' import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem' import ListItem from '@mui/material/ListItem'
import * as R from 'ramda' import * as R from 'ramda'
@ -10,9 +9,6 @@ import CashBoxEmpty from 'src/styling/icons/cassettes/cashbox-empty.svg?react'
import AlertLinkIcon from 'src/styling/icons/month arrows/right.svg?react' import AlertLinkIcon from 'src/styling/icons/month arrows/right.svg?react'
import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react' import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
import styles from './Alerts.styles'
const useStyles = makeStyles(styles)
const icons = { const icons = {
error: <WarningIcon style={{ height: 20, width: 20, marginRight: 12 }} />, error: <WarningIcon style={{ height: 20, width: 20, marginRight: 12 }} />,
fiatBalance: ( fiatBalance: (
@ -28,7 +24,6 @@ const links = {
const AlertsTable = ({ numToRender, alerts, machines }) => { const AlertsTable = ({ numToRender, alerts, machines }) => {
const history = useHistory() const history = useHistory()
const classes = useStyles()
const alertsToRender = R.slice(0, numToRender, alerts) const alertsToRender = R.slice(0, numToRender, alerts)
const alertMessage = alert => { const alertMessage = alert => {
@ -40,16 +35,16 @@ const AlertsTable = ({ numToRender, alerts, machines }) => {
} }
return ( return (
<List dense className={classes.table}> <List dense className="max-h-116 overflow-y-auto overflow-x-hidden">
{alertsToRender.map((alert, idx) => { {alertsToRender.map((alert, idx) => {
return ( return (
<ListItem key={idx}> <ListItem key={idx}>
{icons[alert.type] || ( {icons[alert.type] || (
<Wrench style={{ height: 23, width: 23, marginRight: 8 }} /> <Wrench style={{ height: 23, width: 23, marginRight: 8 }} />
)} )}
<P className={classes.listItemText}>{alertMessage(alert)}</P> <P className="my-2">{alertMessage(alert)}</P>
<AlertLinkIcon <AlertLinkIcon
className={classes.linkIcon} className="ml-auto cursor-pointer"
onClick={() => history.push(links[alert.type] || '/dashboard')} onClick={() => history.push(links[alert.type] || '/dashboard')}
/> />
</ListItem> </ListItem>

View file

@ -1,6 +1,4 @@
import { useQuery, gql } from "@apollo/client"; import { useQuery, gql } from '@apollo/client'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState } from 'react' import React, { useState } from 'react'
import { useHistory } from 'react-router-dom' import { useHistory } from 'react-router-dom'
@ -13,11 +11,10 @@ import { Button } from 'src/components/buttons'
import AddMachine from 'src/pages/AddMachine' import AddMachine from 'src/pages/AddMachine'
import { errorColor } from 'src/styling/variables' import { errorColor } from 'src/styling/variables'
import styles from './Dashboard.styles'
import Footer from './Footer' import Footer from './Footer'
import LeftSide from './LeftSide'
import RightSide from './RightSide' import RightSide from './RightSide'
const useStyles = makeStyles(styles) import Paper from '@mui/material/Paper'
import SystemPerformance from './SystemPerformance/index.js'
const GET_DATA = gql` const GET_DATA = gql`
query getData { query getData {
@ -30,7 +27,6 @@ const GET_DATA = gql`
const Dashboard = () => { const Dashboard = () => {
const history = useHistory() const history = useHistory()
const classes = useStyles()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const { data, loading } = useQuery(GET_DATA) const { data, loading } = useQuery(GET_DATA)
@ -44,16 +40,16 @@ const Dashboard = () => {
!R.isEmpty(data.machines) ? ( !R.isEmpty(data.machines) ? (
<> <>
<TitleSection title="Dashboard"> <TitleSection title="Dashboard">
<div className={classes.headerLabels}> <div className="flex gap-6">
<div> <div className="flex items-center gap-2">
<TxInIcon /> <TxInIcon />
<span>Cash-in</span> <span>Cash-in</span>
</div> </div>
<div> <div className="flex items-center gap-2">
<TxOutIcon /> <TxOutIcon />
<span>Cash-out</span> <span>Cash-out</span>
</div> </div>
<div> <div className="flex items-center gap-2">
<svg width={12} height={12}> <svg width={12} height={12}>
<rect width={12} height={12} rx={3} fill={errorColor} /> <rect width={12} height={12} rx={3} fill={errorColor} />
</svg> </svg>
@ -61,15 +57,15 @@ const Dashboard = () => {
</div> </div>
</div> </div>
</TitleSection> </TitleSection>
<div className={classes.root}> <div className="flex mb-30 gap-4">
<Grid container> <div className="flex flex-col flex-1">
<Grid container direction="column" item xs={6}> <Paper className="p-6">
<LeftSide /> <SystemPerformance />
</Grid> </Paper>
<Grid container direction="column" item xs={6}> </div>
<div className="flex flex-col flex-1">
<RightSide /> <RightSide />
</Grid> </div>
</Grid>
</div> </div>
<Footer /> <Footer />
</> </>
@ -79,17 +75,17 @@ const Dashboard = () => {
<AddMachine close={() => setOpen(false)} onPaired={onPaired} /> <AddMachine close={() => setOpen(false)} onPaired={onPaired} />
)} )}
<TitleSection title="Dashboard"> <TitleSection title="Dashboard">
<div className={classes.headerLabels}> <div className="flex flex-row">
<span> <span>
<TL2 className={classes.inline}>{data?.serverVersion}</TL2>{' '} <TL2 className="inline">{data?.serverVersion}</TL2>{' '}
<Label1 className={classes.inline}> server version</Label1> <Label1 className="inline"> server version</Label1>
</span> </span>
</div> </div>
</TitleSection> </TitleSection>
<div className={classes.emptyMachinesRoot}> <div className="h-75 bg-zircon border-zircon2 border-2">
<div className={classes.emptyMachinesContent}> <div className="flex flex-col h-full justify-center items-center gap-6">
<H1 className={classes.offColor}>No machines on your system yet</H1> <H1 className="text-comet2">No machines on your system yet</H1>
<Info2 className={classes.offColor}> <Info2 className="text-comet2">
To fully take advantage of Lamassu Admin, add a new machine to To fully take advantage of Lamassu Admin, add a new machine to
your system your system
</Info2> </Info2>

View file

@ -1,120 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
spacer,
white,
primaryColor,
zircon,
zircon2,
offDarkColor
} from 'src/styling/variables'
const { label1 } = typographyStyles
const styles = {
headerLabels: {
display: 'flex',
flexDirection: 'row',
'& > div:first-child': {
display: 'flex',
alignItems: 'center',
marginLeft: 0
},
'& > div': {
display: 'flex',
alignItems: 'center',
marginLeft: 25
},
'& > div:last-child': {
display: 'flex',
alignItems: 'center',
marginLeft: 64
},
'& > div > span': {
extend: label1,
marginLeft: 7
}
},
root: {
flexGrow: 1,
display: 'flex',
marginBottom: 120
},
emptyMachinesRoot: {
height: 300,
backgroundColor: zircon,
border: `solid 2px ${zircon2}`
},
card: {
wordWrap: 'break-word',
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)',
borderRadius: 12,
padding: 24,
backgroundColor: white,
flex: 1,
marginRight: 24
},
container: {
display: 'flex',
justifyContent: 'space-between'
},
button: {
color: primaryColor,
minHeight: 0,
minWidth: 0,
padding: 0,
textTransform: 'none',
'&:hover': {
backgroundColor: 'transparent'
}
},
upperButtonLabel: {
textAlign: 'center',
marginBottom: 0,
marginTop: 0,
marginLeft: spacer
},
alertsCard: {
marginBottom: spacer
},
h4: {
marginTop: 0
},
centerLabel: {
marginTop: 40,
marginBottom: 0
},
systemStatusCard: {
flex: 1,
marginTop: spacer
},
expandedCard: {
flex: 0.9
},
shrunkCard: {
flex: 0.1
},
displayFlex: {
display: 'flex',
flexDirection: 'column'
},
inline: {
display: 'inline'
},
emptyMachinesContent: {
display: 'flex',
flexDirection: 'column',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
'& > :first-child': {
marginTop: 0
},
'& > *': {
marginTop: 25
}
},
offColor: {
color: offDarkColor
}
}
export default styles

View file

@ -1,8 +1,6 @@
import { useQuery, gql } from "@apollo/client"; import { useQuery, gql } from '@apollo/client'
import { makeStyles } from '@mui/styles' import { makeStyles } from '@mui/styles'
import Grid from '@mui/material/Grid'
import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import classnames from 'classnames'
import * as R from 'ramda' import * as R from 'ramda'
import React from 'react' import React from 'react'
import { Label2 } from 'src/components/typography' import { Label2 } from 'src/components/typography'
@ -11,7 +9,8 @@ import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
import { fromNamespace } from 'src/utils/config' import { fromNamespace } from 'src/utils/config'
import styles from './Footer.styles' import classes from './Footer.module.css'
const GET_DATA = gql` const GET_DATA = gql`
query getData { query getData {
cryptoRates cryptoRates
@ -29,12 +28,10 @@ const GET_DATA = gql`
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP }) BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
const useStyles = makeStyles(styles)
const Footer = () => { const Footer = () => {
const { data } = useQuery(GET_DATA) const { data } = useQuery(GET_DATA)
const withCommissions = R.path(['cryptoRates', 'withCommissions'])(data) ?? {} const withCommissions = R.path(['cryptoRates', 'withCommissions'])(data) ?? {}
const classes = useStyles()
const config = R.path(['config'])(data) ?? {} const config = R.path(['config'])(data) ?? {}
// const canExpand = R.keys(withCommissions).length > 4 // const canExpand = R.keys(withCommissions).length > 4
@ -72,36 +69,31 @@ const Footer = () => {
).toFormat(2) ).toFormat(2)
return ( return (
<Grid key={key} item xs={3}> <div className="flex flex-col w-1/4">
<Label2 className={classes.label}> <Label2 className="text-comet mt-3 mb-2">
{cryptoCurrencies[idx].display} {cryptoCurrencies[idx].display}
</Label2> </Label2>
<div className={classes.headerLabels}> <div className="flex gap-6">
<div className={classes.headerLabel}> <div className="flex items-center gap-1">
<TxInIcon /> <TxInIcon />
<Label2>{` ${cashIn} ${localeFiatCurrency}`}</Label2> <Label2 noMargin>{`${cashIn} ${localeFiatCurrency}`}</Label2>
</div> </div>
<div className={classnames(classes.headerLabel, classes.txOutMargin)}> <div className="flex items-center gap-1">
<TxOutIcon /> <TxOutIcon />
<Label2>{` ${cashOut} ${localeFiatCurrency}`}</Label2> <Label2 noMargin>{`${cashOut} ${localeFiatCurrency}`}</Label2>
</div> </div>
</div> </div>
<Label2 <Label2 className="text-comet mt-2">
className={ {`${tickerName}: ${avgOfAskBid} ${localeFiatCurrency}`}
classes.tickerLabel </Label2>
}>{`${tickerName}: ${avgOfAskBid} ${localeFiatCurrency}`}</Label2> </div>
</Grid>
) )
} }
return ( return (
<div className={classes.footer1}> <div className={classes.footer1}>
<div className={classes.content1}> <div className={classes.content1}>
<Grid container>
<Grid container className={classes.footerContainer1}>
{R.keys(withCommissions).map(key => renderFooterItem(key))} {R.keys(withCommissions).map(key => renderFooterItem(key))}
</Grid>
</Grid>
</div> </div>
</div> </div>
) )

View file

@ -0,0 +1,28 @@
.footer1 {
left: 0;
bottom: 0;
position: fixed;
width: 100vw;
background-color: white;
text-align: left;
z-index: 1;
box-shadow: 0 -1px 10px 0 rgba(50, 50, 50, 0.1);
min-height: 48px;
transition: min-height 0.5s ease-out;
}
.footer1:hover {
transition: min-height 0.5s ease-in;
min-height: 200px;
}
.content1 {
width: 1200px;
max-height: 100px;
background-color: white;
z-index: 2;
bottom: -8px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}

View file

@ -1,50 +0,0 @@
import { offColor, white, spacer } from 'src/styling/variables'
const styles = {
label: {
color: offColor
},
headerLabels: {
whiteSpace: 'pre',
display: 'flex',
flexDirection: 'row',
marginTop: -20
},
headerLabel: {
display: 'flex',
alignItems: 'center'
},
txOutMargin: {
marginLeft: spacer * 3
},
tickerLabel: {
color: offColor,
marginTop: -5
},
footer1: {
left: 0,
bottom: 0,
position: 'fixed',
width: '100vw',
backgroundColor: white,
textAlign: 'left',
zIndex: 1,
boxShadow: '0px -1px 10px 0px rgba(50, 50, 50, 0.1)',
minHeight: spacer * 12,
transition: 'min-height 0.5s ease-out',
'&:hover': {
transition: 'min-height 0.5s ease-in',
minHeight: 200
}
},
content1: {
width: 1200,
maxHeight: 100,
backgroundColor: white,
zIndex: 2,
bottom: -spacer,
margin: '0 auto'
}
}
export default styles

View file

@ -1,22 +0,0 @@
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import React from 'react'
import styles from './Dashboard.styles'
import SystemPerformance from './SystemPerformance'
const useStyles = makeStyles(styles)
const LeftSide = () => {
const classes = useStyles()
return (
<Grid item xs={12} className={classes.displayFlex}>
<div className={classes.card}>
<SystemPerformance />
</div>
</Grid>
)
}
export default LeftSide

View file

@ -1,29 +1,23 @@
import Button from '@mui/material/Button' import Button from '@mui/material/Button'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { useState } from 'react' import React, { useState } from 'react'
import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard' import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard'
import { H4, Label1 } from 'src/components/typography' import { H4, Label1 } from 'src/components/typography'
import Alerts from './Alerts' import Alerts from './Alerts'
import styles from './Dashboard.styles'
import SystemStatus from './SystemStatus' import SystemStatus from './SystemStatus'
const useStyles = makeStyles(styles)
const ShrunkCard = ({ title, buttonName, onUnshrink }) => { const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
const classes = useStyles()
return ( return (
<div className={classes.container}> <div className="flex justify-between">
<H4 className={classes.h4}>{title}</H4> <H4 className="mt-0">{title}</H4>
<Label1 className={classes.upperButtonLabel}> <Label1 className="text-center my-0">
<Button <Button
onClick={onUnshrink} onClick={onUnshrink}
size="small" size="small"
disableRipple disableRipple
disableFocusRipple disableFocusRipple
className={classes.button}> className="p-0 text-zodiac normal-case">
{buttonName} {buttonName}
</Button> </Button>
</Label1> </Label1>
@ -32,7 +26,6 @@ const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
} }
const RightSide = () => { const RightSide = () => {
const classes = useStyles()
const [systemStatusSize, setSystemStatusSize] = useState(cardState.DEFAULT) const [systemStatusSize, setSystemStatusSize] = useState(cardState.DEFAULT)
const [alertsSize, setAlertsSize] = useState(cardState.DEFAULT) const [alertsSize, setAlertsSize] = useState(cardState.DEFAULT)
@ -41,14 +34,12 @@ const RightSide = () => {
setSystemStatusSize(cardState.DEFAULT) setSystemStatusSize(cardState.DEFAULT)
} }
return ( return (
<Grid item xs={12} className={classes.displayFlex}> <div className="flex flex-1 flex-col">
<div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}> <div className="flex-1 flex flex-col gap-4">
<>
<CollapsibleCard <CollapsibleCard
className={classnames({ className={classnames({
[classes.alertsCard]: alertsSize !== cardState.SHRUNK, 'flex-[0.1]': alertsSize === cardState.SHRUNK,
[classes.shrunkCard]: alertsSize === cardState.SHRUNK, 'flex-[0.9]': alertsSize === cardState.EXPANDED
[classes.expandedCard]: alertsSize === cardState.EXPANDED
})} })}
state={alertsSize} state={alertsSize}
shrunkComponent={ shrunkComponent={
@ -69,9 +60,9 @@ const RightSide = () => {
</CollapsibleCard> </CollapsibleCard>
<CollapsibleCard <CollapsibleCard
className={classnames({ className={classnames({
[classes.shrunkCard]: systemStatusSize === cardState.SHRUNK, 'flex-[0.1]': systemStatusSize === cardState.SHRUNK,
[classes.systemStatusCard]: systemStatusSize !== cardState.SHRUNK, 'flex-1': systemStatusSize === cardState.DEFAULT,
[classes.expandedCard]: alertsSize === cardState.EXPANDED 'flex-[0.9]': systemStatusSize === cardState.EXPANDED
})} })}
state={systemStatusSize} state={systemStatusSize}
shrunkComponent={ shrunkComponent={
@ -90,9 +81,8 @@ const RightSide = () => {
size={systemStatusSize} size={systemStatusSize}
/> />
</CollapsibleCard> </CollapsibleCard>
</>
</div> </div>
</Grid> </div>
) )
} }

View file

@ -1,77 +1,30 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React from 'react' import React from 'react'
import { Label1 } from 'src/components/typography/index' import { Label1 } from 'src/components/typography/index'
import { java, neon, white } from 'src/styling/variables'
const styles = {
wrapper: {
display: 'flex',
height: 142
},
percentageBox: {
height: 142,
borderRadius: 4,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
whiteSpace: 'pre'
},
label: {
color: white
},
inColor: {
backgroundColor: java
},
outColor: {
backgroundColor: neon
},
other: {
minWidth: '6px',
borderRadius: 2
},
inWidth: {
width: value => `${value}%`,
marginRight: value => (value === 100 ? 0 : 4)
},
outWidth: {
width: value => `${100 - value}%`
}
}
const useStyles = makeStyles(styles)
const PercentageChart = ({ cashIn, cashOut }) => { const PercentageChart = ({ cashIn, cashOut }) => {
const value = cashIn || cashOut !== 0 ? cashIn : 50 const value = cashIn || cashOut !== 0 ? cashIn : 50
const classes = useStyles(value)
const buildPercentageView = value => { const buildPercentageView = value => {
if (value <= 15) return if (value <= 15) return
return <Label1 className={classes.label}>{value}%</Label1> return <Label1 className="text-white">{value}%</Label1>
} }
const percentageClasses = { const percentageClasses = {
[classes.percentageBox]: true, 'h-35 rounded-sm flex items-center justify-center': true,
[classes.other]: value < 5 && value > 0 'min-w-2 rounded-xs': value < 5 && value > 0
} }
return ( return (
<div className={classes.wrapper}> <div className="flex h-35 gap-1">
<div <div
className={classnames( className={classnames(percentageClasses, 'bg-java')}
percentageClasses, style={{ width: `${value}%` }}>
classes.inColor,
classes.inWidth
)}>
{buildPercentageView(value, 'cashIn')} {buildPercentageView(value, 'cashIn')}
</div> </div>
<div <div
className={classnames( className={classnames(percentageClasses, 'bg-neon')}
percentageClasses, style={{ width: `${100 - value}%` }}>
classes.outColor,
classes.outWidth
)}>
{buildPercentageView(100 - value, 'cashOut')} {buildPercentageView(100 - value, 'cashOut')}
</div> </div>
</div> </div>

View file

@ -2,8 +2,6 @@ import * as d3 from 'd3'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useEffect, useRef, useCallback } from 'react' import React, { useEffect, useRef, useCallback } from 'react'
import { backgroundColor, zircon, primaryColor } from 'src/styling/variables'
const transactionProfit = R.prop('profit') const transactionProfit = R.prop('profit')
const mockPoint = (tx, offsetMs, profit) => { const mockPoint = (tx, offsetMs, profit) => {
@ -106,7 +104,7 @@ const RefLineChart = ({
.attr('y', -margin.top) .attr('y', -margin.top)
.attr('width', width + margin.left + margin.right) .attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top) .attr('height', height + margin.top)
.attr('fill', backgroundColor) .attr('fill', 'var(--ghost)')
.attr('transform', `translate(${0},${margin.top})`) .attr('transform', `translate(${0},${margin.top})`)
// gradient color for the graph (creates the "url", the color is applied by calling the url, in the area color fill ) // gradient color for the graph (creates the "url", the color is applied by calling the url, in the area color fill )
@ -120,9 +118,9 @@ const RefLineChart = ({
.attr('y2', '100%') .attr('y2', '100%')
.selectAll('stop') .selectAll('stop')
.data([ .data([
{ offset: '0%', color: zircon }, { offset: '0%', color: 'var(--zircon)' },
{ offset: '25%', color: zircon }, { offset: '25%', color: 'var(--zircon)' },
{ offset: '100%', color: backgroundColor } { offset: '100%', color: 'var(--ghost)' }
]) ])
.enter() .enter()
.append('stop') .append('stop')
@ -181,7 +179,7 @@ const RefLineChart = ({
.attr('fill', 'none') .attr('fill', 'none')
.attr('stroke-width', '2') .attr('stroke-width', '2')
.attr('stroke-linejoin', 'round') .attr('stroke-linejoin', 'round')
.attr('stroke', primaryColor) .attr('stroke', 'var(--zodiac)')
}, [realData, timeFrame, previousTimeData, previousProfit]) }, [realData, timeFrame, previousTimeData, previousProfit])
useEffect(() => { useEffect(() => {

View file

@ -4,14 +4,6 @@ import { getTimezoneOffset } from 'date-fns-tz'
import { add, format, startOfWeek, startOfYear } from 'date-fns/fp' import { add, format, startOfWeek, startOfYear } from 'date-fns/fp'
import React, { useCallback, useEffect, useMemo, useRef } from 'react' import React, { useCallback, useEffect, useMemo, useRef } from 'react'
import {
java,
neon,
subheaderDarkColor,
offColor,
fontSecondary,
backgroundColor
} from 'src/styling/variables'
import { numberToFiatAmount } from 'src/utils/number' import { numberToFiatAmount } from 'src/utils/number'
import { MINUTE, DAY, WEEK, MONTH } from 'src/utils/time' import { MINUTE, DAY, WEEK, MONTH } from 'src/utils/time'
@ -143,7 +135,7 @@ const Graph = ({ data, timeFrame, timezone }) => {
.attr('y', GRAPH_MARGIN.top) .attr('y', GRAPH_MARGIN.top)
.attr('width', GRAPH_WIDTH) .attr('width', GRAPH_WIDTH)
.attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.top - GRAPH_MARGIN.bottom) .attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.top - GRAPH_MARGIN.bottom)
.attr('fill', backgroundColor) .attr('fill', 'var(--ghost)')
}, },
[GRAPH_MARGIN] [GRAPH_MARGIN]
) )
@ -191,8 +183,8 @@ const Graph = ({ data, timeFrame, timezone }) => {
const buildGrid = useCallback( const buildGrid = useCallback(
g => { g => {
g.attr('stroke', subheaderDarkColor) g.attr('stroke', 'var(--zircon2)')
.attr('fill', subheaderDarkColor) .attr('fill', 'var(--zircon2)')
// Vertical lines // Vertical lines
.call(g => .call(g =>
g g
@ -277,10 +269,10 @@ const Graph = ({ data, timeFrame, timezone }) => {
() => () =>
d3 d3
.selectAll('.tick text') .selectAll('.tick text')
.style('stroke', offColor) .style('stroke', 'var(--comet)')
.style('fill', offColor) .style('fill', 'var(--comet)')
.style('stroke-width', 0) .style('stroke-width', 0)
.style('font-family', fontSecondary), .style('font-family', 'var(--museo)'),
[] []
) )
@ -288,10 +280,10 @@ const Graph = ({ data, timeFrame, timezone }) => {
() => () =>
d3 d3
.selectAll('text') .selectAll('text')
.style('stroke', offColor) .style('stroke', 'var(--comet)')
.style('fill', offColor) .style('fill', 'var(--comet)')
.style('stroke-width', 0) .style('stroke-width', 0)
.style('font-family', fontSecondary), .style('font-family', 'var(--museo)'),
[] []
) )
@ -311,7 +303,9 @@ const Graph = ({ data, timeFrame, timezone }) => {
return x(created.setTime(created.getTime() + offset)) return x(created.setTime(created.getTime() + offset))
}) })
.attr('cy', d => y(new BigNumber(d.fiat).toNumber())) .attr('cy', d => y(new BigNumber(d.fiat).toNumber()))
.attr('fill', d => (d.txClass === 'cashIn' ? java : neon)) .attr('fill', d =>
d.txClass === 'cashIn' ? 'var(--java)' : 'var(--neon)'
)
.attr('r', 3.5) .attr('r', 3.5)
}, },
[data, offset, x, y] [data, offset, x, y]

View file

@ -2,10 +2,10 @@ import React from 'react'
import { Info1, Label1 } from 'src/components/typography/index' import { Info1, Label1 } from 'src/components/typography/index'
const InfoWithLabel = ({ info, label }) => { const InfoWithLabel = ({ info, label }) => {
return ( return (
<> <div className="flex flex-col">
<Info1 style={{ marginBottom: 0 }}>{info}</Info1> <Info1 className="mb-0">{info}</Info1>
<Label1 style={{ margin: 0 }}>{label}</Label1> <Label1 className="m-0">{label}</Label1>
</> </div>
) )
} }

View file

@ -1,16 +1,11 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState } from 'react' import React, { useState } from 'react'
import { H4 } from 'src/components/typography' import { H4 } from 'src/components/typography'
import styles from './SystemPerformance.styles'
const useStyles = makeStyles(styles)
const ranges = ['Month', 'Week', 'Day'] const ranges = ['Month', 'Week', 'Day']
const Nav = ({ handleSetRange, showPicker }) => { const Nav = ({ handleSetRange, showPicker }) => {
const classes = useStyles()
const [clickedItem, setClickedItem] = useState('Day') const [clickedItem, setClickedItem] = useState('Day')
const isSelected = R.equals(clickedItem) const isSelected = R.equals(clickedItem)
@ -20,22 +15,20 @@ const Nav = ({ handleSetRange, showPicker }) => {
} }
return ( return (
<div className={classnames(classes.titleWrapper)}> <div className="flex justify-between items-center">
<div className={classes.titleAndButtonsContainer}> <H4 noMargin>{'System performance'}</H4>
<H4 className={classes.h4}>{'System performance'}</H4>
</div>
{showPicker && ( {showPicker && (
<div className={classes.navContainer}> <div className="flex gap-6">
{ranges.map((it, idx) => { {ranges.map((it, idx) => {
return ( return (
<div <div
key={idx} key={idx}
onClick={e => handleClick(e.target.innerText)} onClick={e => handleClick(e.target.innerText)}
className={ className={classnames({
'cursor-pointer text-comet': true,
'font-bold text-zodiac border-b-zodiac border-b-2':
isSelected(it) isSelected(it)
? classnames(classes.newHighlightedLabel, classes.navButton) })}>
: classnames(classes.label, classes.navButton)
}>
{it} {it}
</div> </div>
) )

View file

@ -1,12 +1,10 @@
import { useQuery, gql } from "@apollo/client"; import { useQuery, gql } from '@apollo/client'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import classnames from 'classnames' import classnames from 'classnames'
import { isAfter } from 'date-fns/fp' import { isAfter } from 'date-fns/fp'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState } from 'react' import React, { useState } from 'react'
import { Label1, Label2, P } from 'src/components/typography/index' import { Info2, Label1, Label2, P } from 'src/components/typography/index'
import PercentDownIcon from 'src/styling/icons/dashboard/down.svg?react' import PercentDownIcon from 'src/styling/icons/dashboard/down.svg?react'
import PercentNeutralIcon from 'src/styling/icons/dashboard/equal.svg?react' import PercentNeutralIcon from 'src/styling/icons/dashboard/equal.svg?react'
import PercentUpIcon from 'src/styling/icons/dashboard/up.svg?react' import PercentUpIcon from 'src/styling/icons/dashboard/up.svg?react'
@ -23,12 +21,10 @@ import LineChart from './Graphs/RefLineChart'
import Scatterplot from './Graphs/RefScatterplot' import Scatterplot from './Graphs/RefScatterplot'
import InfoWithLabel from './InfoWithLabel' import InfoWithLabel from './InfoWithLabel'
import Nav from './Nav' import Nav from './Nav'
import styles from './SystemPerformance.styles'
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP }) BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
const getFiats = R.map(R.prop('fiat')) const getFiats = R.map(R.prop('fiat'))
const useStyles = makeStyles(styles)
const GET_DATA = gql` const GET_DATA = gql`
query getData($excludeTestingCustomers: Boolean) { query getData($excludeTestingCustomers: Boolean) {
@ -54,7 +50,6 @@ const GET_DATA = gql`
` `
const SystemPerformance = () => { const SystemPerformance = () => {
const classes = useStyles()
const [selectedRange, setSelectedRange] = useState('Day') const [selectedRange, setSelectedRange] = useState('Day')
const { data, loading } = useQuery(GET_DATA, { const { data, loading } = useQuery(GET_DATA, {
variables: { excludeTestingCustomers: true } variables: { excludeTestingCustomers: true }
@ -162,17 +157,17 @@ const SystemPerformance = () => {
const percentChange = getPercentChange() const percentChange = getPercentChange()
const percentageClasses = { const percentageClasses = {
[classes.percentDown]: percentChange < 0, 'text-tomato': percentChange < 0,
[classes.percentUp]: percentChange > 0, 'text-spring4': percentChange > 0,
[classes.percentNeutral]: percentChange === 0 'text-comet': percentChange === 0,
'flex items-center justify-center gap-1': true
} }
const getPercentageIcon = () => { const getPercentageIcon = () => {
if (percentChange === 0) const className = 'w-4 h-4'
return <PercentNeutralIcon className={classes.directionIcon} /> if (percentChange === 0) return <PercentNeutralIcon className={className} />
if (percentChange > 0) if (percentChange > 0) return <PercentUpIcon className={className} />
return <PercentUpIcon className={classes.directionIcon} /> return <PercentDownIcon className={className} />
return <PercentDownIcon className={classes.directionIcon} />
} }
return ( return (
@ -182,49 +177,43 @@ const SystemPerformance = () => {
handleSetRange={setSelectedRange} handleSetRange={setSelectedRange}
/> />
{!loading && R.isEmpty(data.transactions) && ( {!loading && R.isEmpty(data.transactions) && (
<EmptyTable <EmptyTable className="pt-10" message="No transactions so far" />
className={classes.emptyTransactions}
message="No transactions so far"
/>
)} )}
{!loading && !R.isEmpty(data.transactions) && ( {!loading && !R.isEmpty(data.transactions) && (
<> <div className="flex flex-col gap-12">
<Grid container spacing={2}> <div className="flex gap-16">
<Grid item xs={3}> <InfoWithLabel info={getNumTransactions()} label={'transactions'} />
<InfoWithLabel
info={getNumTransactions()}
label={'transactions'}
/>
</Grid>
<Grid item xs={3}>
<InfoWithLabel <InfoWithLabel
info={getFiatVolume()} info={getFiatVolume()}
label={`${data?.config.locale_fiatCurrency} volume`} label={`${data?.config.locale_fiatCurrency} volume`}
/> />
</Grid> </div>
{/* todo new customers */} <div className="h-62">
</Grid> <div className="flex justify-between mb-4">
<Grid container className={classes.txGraphContainer}>
<Grid item xs={12}>
<div className={classes.graphHeader}>
<Label2 noMargin>Transactions</Label2> <Label2 noMargin>Transactions</Label2>
<div className={classes.labelWrapper}> <div className="flex items-center">
<P noMargin> <P noMargin>
{timezones[timezone]?.short ?? timezones[timezone]?.long}{' '} {timezones[timezone]?.short ?? timezones[timezone]?.long}{' '}
timezone timezone
</P> </P>
<span className={classes.verticalLine} /> <span className="h-4 w-[1px] bg-comet2 mr-4 ml-8" />
<div> <div className="flex flex-row gap-4">
<div className="flex items-center">
<svg width={8} height={8}> <svg width={8} height={8}>
<rect width={8} height={8} rx={4} fill={java} /> <rect width={8} height={8} rx={4} fill={java} />
</svg> </svg>
<Label1 noMargin>In</Label1> <Label1 noMargin className="ml-2">
In
</Label1>
</div> </div>
<div> <div className="flex items-center">
<svg width={8} height={8}> <svg width={8} height={8}>
<rect width={8} height={8} rx={4} fill={neon} /> <rect width={8} height={8} rx={4} fill={neon} />
</svg> </svg>
<Label1 noMargin>Out</Label1> <Label1 noMargin className="ml-2">
Out
</Label1>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -233,23 +222,22 @@ const SystemPerformance = () => {
data={transactionsToShow} data={transactionsToShow}
timezone={timezone} timezone={timezone}
/> />
</Grid> </div>
</Grid> <div className="flex h-62">
<Grid container className={classes.commissionGraphContainer}> <div className="flex-2">
<Grid item xs={8}> <Label2 noMargin className="mb-4">
<Label2 noMargin className={classes.commissionProfitTitle}>
Profit from commissions Profit from commissions
</Label2> </Label2>
<div className={classes.profitContainer}> <div className="flex justify-between mt-6 mr-7 -mb-8 ml-4 relative">
<div className={classes.profitLabel}> <Info2 noMargin>
{`${getProfit(transactionsToShow).toFormat(2)} ${ {`${getProfit(transactionsToShow).toFormat(2)} ${
data?.config.locale_fiatCurrency data?.config.locale_fiatCurrency
}`} }`}
</div> </Info2>
<div className={classnames(percentageClasses)}> <Info2 noMargin className={classnames(percentageClasses)}>
{getPercentageIcon()} {getPercentageIcon()}
{`${new BigNumber(percentChange).toFormat(2)}%`} {`${new BigNumber(percentChange).toFormat(2)}%`}
</div> </Info2>
</div> </div>
<LineChart <LineChart
timeFrame={selectedRange} timeFrame={selectedRange}
@ -257,34 +245,36 @@ const SystemPerformance = () => {
previousTimeData={transactionsLastTimePeriod} previousTimeData={transactionsLastTimePeriod}
previousProfit={getProfit(transactionsLastTimePeriod)} previousProfit={getProfit(transactionsLastTimePeriod)}
/> />
</Grid> </div>
<Grid item xs={4}> <div className="flex-1">
<Grid container className={classes.graphHeader}> <div className="flex items-center justify-between mb-4">
<Label2 noMargin>Direction</Label2> <Label2 noMargin>Direction</Label2>
<div className={classes.labelWrapper}> <div className="flex flex-row gap-4">
<div> <div className="flex items-center">
<svg width={8} height={8}> <svg width={8} height={8}>
<rect width={8} height={8} rx={2} fill={java} /> <rect width={8} height={8} rx={2} fill={java} />
</svg> </svg>
<Label1 noMargin>In</Label1> <Label1 noMargin className="ml-2">
In
</Label1>
</div> </div>
<div> <div className="flex items-center">
<svg width={8} height={8}> <svg width={8} height={8}>
<rect width={8} height={8} rx={2} fill={neon} /> <rect width={8} height={8} rx={2} fill={neon} />
</svg> </svg>
<Label1 noMargin>Out</Label1> <Label1 noMargin className="ml-2">
Out
</Label1>
</div>
</div> </div>
</div> </div>
</Grid>
<Grid item xs>
<PercentageChart <PercentageChart
cashIn={getDirectionPercent().cashIn} cashIn={getDirectionPercent().cashIn}
cashOut={getDirectionPercent().cashOut} cashOut={getDirectionPercent().cashOut}
/> />
</Grid> </div>
</Grid> </div>
</Grid> </div>
</>
)} )}
</> </>
) )

View file

@ -1,154 +0,0 @@
import {
offColor,
offDarkColor,
spacer,
primaryColor,
fontSize3,
fontSecondary,
fontColor,
spring4,
tomato,
comet
} from 'src/styling/variables'
const styles = {
titleWrapper: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row'
},
titleAndButtonsContainer: {
display: 'flex'
},
error: {
marginLeft: 12
},
icon: {
marginRight: 6
},
h4: {
margin: 0,
marginRight: spacer * 8
},
label: {
cursor: 'pointer',
minHeight: 0,
minWidth: 0,
padding: 0,
color: offColor,
textTransform: 'none',
borderBottom: `2px solid transparent`,
display: 'inline-block',
lineHeight: 1.5,
'&:hover': {
backgroundColor: 'transparent'
}
},
newHighlightedLabel: {
cursor: 'pointer',
color: primaryColor,
fontWeight: 700,
borderRadius: 0,
minHeight: 0,
minWidth: 0,
textTransform: 'none',
borderBottom: `2px solid ${primaryColor}`,
display: 'inline-block',
lineHeight: 1.5,
'&:hover': {
backgroundColor: 'transparent'
}
},
navButton: {
marginLeft: 24
},
navContainer: {
display: 'flex'
},
percentUp: {
fontSize: fontSize3,
fontFamily: fontSecondary,
fontWeight: 700,
color: spring4,
height: 10
},
percentDown: {
fontSize: fontSize3,
fontFamily: fontSecondary,
fontWeight: 700,
color: tomato,
height: 13
},
percentNeutral: {
fontSize: fontSize3,
fontFamily: fontSecondary,
fontWeight: 700,
color: comet
},
profitContainer: {
display: 'flex',
justifyContent: 'space-between',
margin: '23px 26px -30px 16px',
position: 'relative'
},
profitLabel: {
fontSize: fontSize3,
fontFamily: fontSecondary,
fontWeight: 700,
color: fontColor
},
directionIcon: {
width: 16,
height: 16,
marginBottom: -2,
marginRight: 4
},
emptyTransactions: {
paddingTop: 40
},
commissionProfitTitle: {
marginBottom: 16
},
graphHeader: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 16
},
labelWrapper: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
'& > div': {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
marginLeft: 15,
'&:first-child': {
marginLeft: 0
},
'& > p': {
marginLeft: 8
}
}
},
txGraphContainer: {
height: 300,
marginTop: 30
},
commissionsGraphContainer: {
height: 250,
marginTop: 30
},
verticalLine: {
height: 15,
width: 1,
backgroundColor: offDarkColor,
marginLeft: 31,
marginRight: 16
}
}
export default styles

View file

@ -1,12 +1,11 @@
import { useQuery, gql } from "@apollo/client"; import { useQuery, gql } from '@apollo/client'
import { makeStyles, withStyles } from '@mui/styles' import { styled } from '@mui/material/styles'
import Table from '@mui/material/Table' import Table from '@mui/material/Table'
import TableBody from '@mui/material/TableBody' import TableBody from '@mui/material/TableBody'
import TableCell from '@mui/material/TableCell' import TableCell from '@mui/material/TableCell'
import TableContainer from '@mui/material/TableContainer' import TableContainer from '@mui/material/TableContainer'
import TableHead from '@mui/material/TableHead' import TableHead from '@mui/material/TableHead'
import TableRow from '@mui/material/TableRow' import TableRow from '@mui/material/TableRow'
import classnames from 'classnames'
import * as R from 'ramda' 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'
@ -15,11 +14,8 @@ import { Label2, TL2 } from 'src/components/typography'
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react' import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
import MachineLinkIcon from 'src/styling/icons/month arrows/right.svg?react' import MachineLinkIcon from 'src/styling/icons/month arrows/right.svg?react'
// import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
import { fromNamespace } from 'src/utils/config' import { fromNamespace } from 'src/utils/config'
import styles from './MachinesTable.styles'
// percentage threshold where below this number the text in the cash cassettes percentage turns red // percentage threshold where below this number the text in the cash cassettes percentage turns red
const PERCENTAGE_THRESHOLD = 20 const PERCENTAGE_THRESHOLD = 20
@ -29,27 +25,20 @@ const GET_CONFIG = gql`
} }
` `
const useStyles = makeStyles(styles) const StyledCell = styled(TableCell)({
const StyledCell = withStyles({
root: {
borderBottom: '4px solid white', borderBottom: '4px solid white',
padding: 0, padding: 0,
paddingLeft: 15 paddingLeft: '15px'
} })
})(TableCell)
const HeaderCell = withStyles({ const HeaderCell = styled(TableCell)({
root: {
borderBottom: '4px solid white', borderBottom: '4px solid white',
padding: 0, padding: 0,
paddingLeft: 15, paddingLeft: '15px',
backgroundColor: 'white' backgroundColor: 'white'
} })
})(TableCell)
const MachinesTable = ({ machines = [], numToRender }) => { const MachinesTable = ({ machines = [], numToRender }) => {
const classes = useStyles()
const history = useHistory() const history = useHistory()
const { data } = useQuery(GET_CONFIG) const { data } = useQuery(GET_CONFIG)
@ -69,7 +58,7 @@ const MachinesTable = ({ machines = [], numToRender }) => {
R.defaultTo(PERCENTAGE_THRESHOLD) R.defaultTo(PERCENTAGE_THRESHOLD)
)(fillingPercentageSettings) )(fillingPercentageSettings)
return percent < percentageThreshold ? ( return percent < percentageThreshold ? (
<TL2 className={classes.error}>{`${percent}%`}</TL2> <TL2 className="text-tomato">{`${percent}%`}</TL2>
) : ( ) : (
<TL2>{`${percent}%`}</TL2> <TL2>{`${percent}%`}</TL2>
) )
@ -87,30 +76,32 @@ const MachinesTable = ({ machines = [], numToRender }) => {
) )
return ( return (
<TableContainer className={classes.table}> <TableContainer className="max-h-110">
<Table> <Table>
<TableHead> <TableHead>
<TableRow> <TableRow>
<HeaderCell> <HeaderCell>
<div className={classes.header}> <div className="flex items-center">
<Label2 className={classes.label}>Machines</Label2> <Label2 noMargin className="text-comet">
Machines
</Label2>
</div> </div>
</HeaderCell> </HeaderCell>
<HeaderCell> <HeaderCell>
<div className={`${classes.header} ${classes.statusHeader}`}> <div className="flex items-center">
<Label2 className={classes.label}>Status</Label2> <Label2 noMargin className="text-comet">
Status
</Label2>
</div> </div>
</HeaderCell> </HeaderCell>
{/* <HeaderCell>
<div className={classes.header}>
<TxInIcon />
</div>
</HeaderCell> */}
{R.times(R.identity, maxNumberOfCassettes).map((it, idx) => ( {R.times(R.identity, maxNumberOfCassettes).map((it, idx) => (
<HeaderCell key={idx}> <HeaderCell key={idx}>
<div className={classes.header}> <div className="flex items-center whitespace-pre">
<TxOutIcon /> <TxOutIcon />
<Label2 className={classes.label}> {it + 1}</Label2> <Label2 noMargin className="text-comet">
{' '}
{it + 1}
</Label2>
</div> </div>
</HeaderCell> </HeaderCell>
))} ))}
@ -122,20 +113,23 @@ const MachinesTable = ({ machines = [], numToRender }) => {
return ( return (
<TableRow <TableRow
onClick={() => redirect(machine)} onClick={() => redirect(machine)}
className={classnames(classes.row)} className="boder-b-0 bg-ghost"
key={machine.deviceId + idx}> key={machine.deviceId + idx}>
<StyledCell align="left"> <TableCell
<div className={classes.machineNameWrapper}> sx={{
borderBottom: '4px solid white',
padding: 0,
paddingLeft: '15px'
}}
align="left">
<div className="flex items-center">
<TL2>{machine.name}</TL2> <TL2>{machine.name}</TL2>
<MachineLinkIcon <MachineLinkIcon
className={classnames( className="cursor-pointer ml-2"
classes.machineRedirectIcon,
classes.clickableRow
)}
onClick={() => redirect(machine)} onClick={() => redirect(machine)}
/> />
</div> </div>
</StyledCell> </TableCell>
<StyledCell> <StyledCell>
<Status status={machine.statuses[0]} /> <Status status={machine.statuses[0]} />
</StyledCell> </StyledCell>

View file

@ -6,10 +6,6 @@ import {
} from 'src/styling/variables' } from 'src/styling/variables'
const styles = { const styles = {
container: {
display: 'flex',
justifyContent: 'space-between'
},
label: { label: {
margin: 0, margin: 0,
color: offColor color: offColor
@ -45,30 +41,12 @@ const styles = {
bottom: 160, bottom: 160,
marginBottom: 0 marginBottom: 0
}, },
upperButtonLabel: {
textAlign: 'center',
marginBottom: 0,
marginTop: 0
},
statusHeader: { statusHeader: {
marginLeft: 2 marginLeft: 2
}, },
table: {
maxHeight: 440,
'&::-webkit-scrollbar': {
width: 7
},
'&::-webkit-scrollbar-thumb': {
backgroundColor: offColor,
borderRadius: 5
}
},
tableBody: { tableBody: {
overflow: 'auto' overflow: 'auto'
}, },
h4: {
marginTop: 0
},
tl2: { tl2: {
display: 'inline' display: 'inline'
}, },
@ -76,11 +54,9 @@ const styles = {
display: 'inline' display: 'inline'
}, },
machinesTableContainer: { machinesTableContainer: {
marginTop: 10,
height: 220 height: 220
}, },
expandedMachinesTableContainer: { expandedMachinesTableContainer: {
marginTop: 10,
height: 414 height: 414
}, },
centerLabel: { centerLabel: {

View file

@ -1,18 +1,12 @@
import { useQuery, gql } from "@apollo/client"; import { useQuery, gql } from '@apollo/client'
import Button from '@mui/material/Button' import Button from '@mui/material/Button'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import * as R from 'ramda' import * as R from 'ramda'
import React from 'react' import React from 'react'
import { cardState as cardState_ } from 'src/components/CollapsibleCard' import { cardState as cardState_ } from 'src/components/CollapsibleCard'
// import ActionButton from 'src/components/buttons/ActionButton'
import { H4, TL2, Label1 } from 'src/components/typography' import { H4, TL2, Label1 } from 'src/components/typography'
import MachinesTable from './MachinesTable' import MachinesTable from './MachinesTable'
import styles from './MachinesTable.styles'
const useStyles = makeStyles(styles)
// number of machines in the table to render on page load // number of machines in the table to render on page load
const NUM_TO_RENDER = 4 const NUM_TO_RENDER = 4
@ -59,29 +53,28 @@ const GET_DATA = gql`
} */ } */
const SystemStatus = ({ onReset, onExpand, size }) => { const SystemStatus = ({ onReset, onExpand, size }) => {
const classes = useStyles()
const { data, loading } = useQuery(GET_DATA) const { data, loading } = useQuery(GET_DATA)
const machines = R.path(['machines'])(data) ?? [] const machines = R.path(['machines'])(data) ?? []
const showAllItems = size === cardState_.EXPANDED const showAllItems = size === cardState_.EXPANDED
const machinesTableContainerClasses = { const machinesTableContainerClasses = {
[classes.machinesTableContainer]: !showAllItems, 'h-55': !showAllItems,
[classes.expandedMachinesTableContainer]: showAllItems 'h-103': showAllItems
} }
// const uptime = data?.uptime ?? [{}] // const uptime = data?.uptime ?? [{}]
return ( return (
<> <>
<div className={classes.container}> <div className="flex justify-between">
<H4 className={classes.h4}>System status</H4>{' '} <H4 className="mt-0">System status</H4>
{showAllItems && ( {showAllItems && (
<Label1 className={classes.upperButtonLabel}> <Label1 noMargin className="-mt-1">
<Button <Button
onClick={onReset} onClick={onReset}
size="small" size="small"
disableRipple disableRipple
disableFocusRipple disableFocusRipple
className={classes.button}> className="p-0 text-zodiac normal-case">
{'Show less'} {'Show less'}
</Button> </Button>
</Label1> </Label1>
@ -89,54 +82,29 @@ const SystemStatus = ({ onReset, onExpand, size }) => {
</div> </div>
{!loading && ( {!loading && (
<> <>
<Grid container spacing={1}> <div className="mb-4">
{/* <TL2 className="inline">{data?.serverVersion}</TL2>
On hold until system uptime is implemented <Label1 className="inline"> server version</Label1>
<Grid item xs={4}> </div>
<TL2 className={classes.tl2}> <div className={classnames(machinesTableContainerClasses)}>
{parseUptime(uptime[0].time)}
</TL2>
<Label1 className={classes.label1}> System up time</Label1>
</Grid> */}
<Grid item xs={4}>
<TL2 className={classes.tl2}>{data?.serverVersion}</TL2>
<Label1 className={classes.label1}> server version</Label1>
</Grid>
<Grid item xs={4}>
{/*
On hold until system update features are implemented
<ActionButton
color="primary"
className={classes.actionButton}
onClick={() => console.log('Upgrade button clicked')}>
Update to v10.6.0
</ActionButton> */}
</Grid>
</Grid>
<Grid
container
spacing={1}
className={classnames(machinesTableContainerClasses)}>
<Grid item xs={12}>
<MachinesTable <MachinesTable
numToRender={showAllItems ? Infinity : NUM_TO_RENDER} numToRender={showAllItems ? Infinity : NUM_TO_RENDER}
machines={machines} machines={machines}
/> />
</Grid> </div>
</Grid>
{!showAllItems && machines.length > NUM_TO_RENDER && ( {!showAllItems && machines.length > NUM_TO_RENDER && (
<Grid item xs={12}> <div>
<Label1 className={classes.centerLabel}> <Label1 className="text-center mb-0">
<Button <Button
onClick={() => onExpand()} onClick={() => onExpand()}
size="small" size="small"
disableRipple disableRipple
disableFocusRipple disableFocusRipple
className={classes.button}> className="p-0 text-zodiac normal-case">
{`Show all (${machines.length})`} {`Show all (${machines.length})`}
</Button> </Button>
</Label1> </Label1>
</Grid> </div>
)} )}
</> </>
)} )}

View file

@ -1,5 +1,4 @@
import { useQuery, useMutation, gql } from "@apollo/client"; import { useQuery, useMutation, gql } from '@apollo/client'
import { makeStyles } from '@mui/styles'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState } from 'react' import React, { useState } from 'react'
import Modal from 'src/components/Modal' import Modal from 'src/components/Modal'
@ -15,7 +14,6 @@ import { Link, SupportLinkButton } from 'src/components/buttons'
import { Table as EditableTable } from 'src/components/editableTable' import { Table as EditableTable } from 'src/components/editableTable'
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config' import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
import { styles } from './Locales.styles'
import { import {
mainFields, mainFields,
overrides, overrides,
@ -25,8 +23,6 @@ import {
overridesDefaults overridesDefaults
} from './helper' } from './helper'
const useStyles = makeStyles(styles)
const GET_DATA = gql` const GET_DATA = gql`
query getData { query getData {
config config
@ -75,8 +71,6 @@ const GET_MARKETS = gql`
` `
const FiatCurrencyChangeAlert = ({ open, close, save }) => { const FiatCurrencyChangeAlert = ({ open, close, save }) => {
const classes = useStyles()
return ( return (
<Modal <Modal
title={'Change fiat currency?'} title={'Change fiat currency?'}
@ -94,11 +88,11 @@ const FiatCurrencyChangeAlert = ({ open, close, save }) => {
Also, if you have cash-out enabled, you must define new dispenser bill Also, if you have cash-out enabled, you must define new dispenser bill
counts for the new currency for cash-out on the new currency to work. counts for the new currency for cash-out on the new currency to work.
</P> </P>
<div className={classes.rightAligned}> <div className="ml-auto">
<Link onClick={close} color="secondary"> <Link onClick={close} color="secondary">
Cancel Cancel
</Link> </Link>
<Link className={classes.rightLink} onClick={save} color="primary"> <Link className="ml-5" onClick={save} color="primary">
Save Save
</Link> </Link>
</div> </div>

View file

@ -1,12 +0,0 @@
const styles = {
rightAligned: {
marginTop: '20px',
marginLeft: 'auto',
marginBottom: '20px'
},
rightLink: {
marginLeft: '20px'
}
}
export { styles }

View file

@ -22,6 +22,7 @@
--ghost: #fafbff; --ghost: #fafbff;
--zircon: #ebefff; --zircon: #ebefff;
--zircon2: #dbdfed;
--java: #16d6d3; --java: #16d6d3;
--neon: #5a67ff; --neon: #5a67ff;
@ -45,6 +46,8 @@
--color-tomato: var(--tomato); --color-tomato: var(--tomato);
--color-ghost: var(--ghost); --color-ghost: var(--ghost);
--color-zircon: var(--zircon); --color-zircon: var(--zircon);
--color-zircon2: var(--zircon2);
--color-java: var(--java);
--color-neon: var(--neon); --color-neon: var(--neon);
--color-malachite: var(--malachite); --color-malachite: var(--malachite);
--color-orange-yellow: var(--orange-yellow); --color-orange-yellow: var(--orange-yellow);

View file

@ -151,6 +151,13 @@ theme = createTheme(theme, {
} }
} }
}, },
MuiPaper: {
styleOverrides: {
elevation1: {
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)'
}
}
},
MuiChip: { MuiChip: {
styleOverrides: { styleOverrides: {
root: { root: {