partial: migrate AddMachine page css

This commit is contained in:
Rafael Taranto 2025-04-24 15:44:54 +01:00
parent 6f10977fd0
commit b9b7dcdcd7
5 changed files with 61 additions and 295 deletions

View file

@ -1,112 +0,0 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { memo } from 'react'
import CompleteStageIconSpring from 'src/styling/icons/stage/spring/complete.svg?react'
import CurrentStageIconSpring from 'src/styling/icons/stage/spring/current.svg?react'
import EmptyStageIconSpring from 'src/styling/icons/stage/spring/empty.svg?react'
import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg?react'
import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react'
import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react'
import {
primaryColor,
secondaryColor,
offColor,
disabledColor
} from 'src/styling/variables'
const styles = {
stages: {
display: 'flex',
alignItems: 'center'
},
wrapper: {
display: 'flex',
alignItems: 'center',
margin: 0
},
stage: {
display: 'flex',
height: 28,
width: 28,
zIndex: 2,
'& > svg': {
height: '100%',
width: '100%',
overflow: 'visible'
}
},
separator: {
width: 28,
height: 2,
border: [[2, 'solid']],
zIndex: 1
},
separatorSpring: {
borderColor: secondaryColor
},
separatorZodiac: {
borderColor: primaryColor
},
separatorSpringEmpty: {
borderColor: disabledColor
},
separatorZodiacEmpty: {
borderColor: offColor
}
}
const useStyles = makeStyles(styles)
const Stage = memo(({ stages, currentStage, color = 'spring', className }) => {
if (currentStage < 1 || currentStage > stages)
throw Error('Value of currentStage is invalid')
if (stages < 1) throw Error('Value of stages is invalid')
const classes = useStyles()
const separatorClasses = {
[classes.separator]: true,
[classes.separatorSpring]: color === 'spring',
[classes.separatorZodiac]: color === 'zodiac'
}
const separatorEmptyClasses = {
[classes.separator]: true,
[classes.separatorSpringEmpty]: color === 'spring',
[classes.separatorZodiacEmpty]: color === 'zodiac'
}
return (
<div className={classnames(className, classes.stages)}>
{R.range(1, currentStage).map(idx => (
<div key={idx} className={classes.wrapper}>
{idx > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}>
{color === 'spring' && <CompleteStageIconSpring />}
{color === 'zodiac' && <CompleteStageIconZodiac />}
</div>
</div>
))}
<div className={classes.wrapper}>
{currentStage > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}>
{color === 'spring' && <CurrentStageIconSpring />}
{color === 'zodiac' && <CurrentStageIconZodiac />}
</div>
</div>
{R.range(currentStage + 1, stages + 1).map(idx => (
<div key={idx} className={classes.wrapper}>
<div className={classnames(separatorEmptyClasses)} />
<div className={classes.stage}>
{color === 'spring' && <EmptyStageIconSpring />}
{color === 'zodiac' && <EmptyStageIconZodiac />}
</div>
</div>
))}
</div>
)
})
export default Stage

View file

@ -1,12 +1,11 @@
import { useMutation, useQuery, gql } from "@apollo/client"; import { useMutation, useQuery, gql } from '@apollo/client'
import Dialog from '@mui/material/Dialog' import Dialog from '@mui/material/Dialog'
import DialogContent from '@mui/material/DialogContent' import DialogContent from '@mui/material/DialogContent'
import SvgIcon from '@mui/material/SvgIcon' import SvgIcon from '@mui/material/SvgIcon'
import IconButton from '@mui/material/IconButton' import IconButton from '@mui/material/IconButton'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import { Form, Formik, FastField } from 'formik' import { Form, Formik, FastField } from 'formik'
import {QRCodeSVG as QRCode} from 'qrcode.react' import { QRCodeSVG as QRCode } from 'qrcode.react'
import * as R from 'ramda' import * as R from 'ramda'
import React, { memo, useState, useEffect, useRef } from 'react' import React, { memo, useState, useEffect, useRef } from 'react'
import Title from 'src/components/Title' import Title from 'src/components/Title'
@ -25,8 +24,6 @@ import { Button } from 'src/components/buttons'
import { TextInput } from 'src/components/inputs/formik' import { TextInput } from 'src/components/inputs/formik'
import { primaryColor } from 'src/styling/variables' import { primaryColor } from 'src/styling/variables'
import styles from './styles'
const SAVE_CONFIG = gql` const SAVE_CONFIG = gql`
mutation createPairingTotem($name: String!) { mutation createPairingTotem($name: String!) {
createPairingTotem(name: $name) createPairingTotem(name: $name)
@ -41,11 +38,9 @@ const GET_MACHINES = gql`
} }
` `
const useStyles = makeStyles(styles)
const getSize = R.compose(R.length, R.pathOr([], ['machines'])) const getSize = R.compose(R.length, R.pathOr([], ['machines']))
const QrCodeComponent = ({ classes, qrCode, name, count, onPaired }) => { const QrCodeComponent = ({ qrCode, name, count, onPaired }) => {
const timeout = useRef(null) const timeout = useRef(null)
const CLOSE_SCREEN_TIMEOUT = 2000 const CLOSE_SCREEN_TIMEOUT = 2000
const { data } = useQuery(GET_MACHINES, { pollInterval: 10000 }) const { data } = useQuery(GET_MACHINES, { pollInterval: 10000 })
@ -69,43 +64,42 @@ const QrCodeComponent = ({ classes, qrCode, name, count, onPaired }) => {
return ( return (
<> <>
<Info2 className={classes.qrTitle}> <Info2>Scan QR code with your new cryptomat</Info2>
Scan QR code with your new cryptomat <div className="flex gap-20 pt-6">
</Info2> <div
<div className={classes.qrCodeWrapper}> className="bg-white p-1 rounded-2xl border-solid border-zodiac border-5"
<div className={classes.qrCodeImageWrapper} data-cy={qrCode}> data-cy={qrCode}>
<QRCode <QRCode
size={280} size={280}
fgColor={primaryColor} fgColor={primaryColor}
marginSize={4} marginSize={3}
value={qrCode} value={qrCode}
className={classes.qrCodeBorder}
/> />
<div className={classes.qrCodeScanMessage}> <div className="flex items-center mb-5 ml-5">
<CameraIcon /> <CameraIcon />
<P noMargin>Snap a picture and scan</P> <P noMargin className="ml-3">
Snap a picture and scan
</P>
</div> </div>
</div> </div>
<div className={classes.qrTextWrapper}> <div className="max-w-100">
<div className={classes.qrTextInfoWrapper}> <div className="flex gap-4 mb-4">
<div className={classes.qrTextIcon}> <div>
<WarningIcon /> <WarningIcon />
</div> </div>
<div className={classes.textWrapper}> <P noMargin>
<P className={classes.qrText}> To pair the machine you need scan the QR code with your machine.
To pair the machine you need scan the QR code with your machine. To do this either snap a picture of this QR code or download it
To do this either snap a picture of this QR code or download it through the button above and scan it with the scanning bay on your
through the button above and scan it with the scanning bay on machine.
your machine. </P>
</P>
</div>
</div> </div>
{hasNewMachine && ( {hasNewMachine && (
<div className={classes.successMessageWrapper}> <div className="bg-spring3 flex gap-4 p-2">
<div className={classes.successMessageIcon}> <div className="flex items-center">
<CompleteStageIconSpring /> <CompleteStageIconSpring />
</div> </div>
<Info2 className={classes.successMessage}> <Info2 className="text-spring2 m-0">
Machine has been successfully paired! Machine has been successfully paired!
</Info2> </Info2>
</div> </div>
@ -135,7 +129,7 @@ const validationSchema = Yup.object().shape({
) )
}) })
const MachineNameComponent = ({ nextStep, classes, setQrCode, setName }) => { const MachineNameComponent = ({ nextStep, setQrCode, setName }) => {
const [register] = useMutation(SAVE_CONFIG, { const [register] = useMutation(SAVE_CONFIG, {
onCompleted: ({ createPairingTotem }) => { onCompleted: ({ createPairingTotem }) => {
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
@ -162,9 +156,7 @@ const MachineNameComponent = ({ nextStep, classes, setQrCode, setName }) => {
return ( return (
<> <>
<Info2 className={classes.nameTitle}> <Info2 className="mb-6">Machine Name (ex: Coffee shop 01)</Info2>
Machine Name (ex: Coffee shop 01)
</Info2>
<Formik <Formik
validateOnBlur={false} validateOnBlur={false}
validateOnChange={false} validateOnChange={false}
@ -175,7 +167,7 @@ const MachineNameComponent = ({ nextStep, classes, setQrCode, setName }) => {
register({ variables: { name } }) register({ variables: { name } })
}}> }}>
{({ errors }) => ( {({ errors }) => (
<Form className={classes.form}> <Form>
<div> <div>
<FastField <FastField
name="name" name="name"
@ -183,8 +175,8 @@ const MachineNameComponent = ({ nextStep, classes, setQrCode, setName }) => {
component={TextInput} component={TextInput}
/> />
</div> </div>
{errors && <P className={classes.errorMessage}>{errors.message}</P>} {errors && <P className="text-tomato">{errors.message}</P>}
<div className={classes.button}> <div className="mt-16">
<Button type="submit">Submit</Button> <Button type="submit">Submit</Button>
</div> </div>
</Form> </Form>
@ -205,18 +197,18 @@ const steps = [
} }
] ]
const renderStepper = (step, it, idx, classes) => { const renderStepper = (step, it, idx) => {
const active = step === idx const active = step === idx
const past = idx < step const past = idx < step
const future = idx > step const future = idx > step
return ( return (
<div className={classes.item}> <div className="flex relative my-3">
<span <span
className={classnames({ className={classnames({
[classes.itemText]: true, 'mr-6 text-comet': true,
[classes.itemTextActive]: active, 'text-zodiac font-bold': active,
[classes.itemTextPast]: past 'text-zodiac': past
})}> })}>
{it.label} {it.label}
</span> </span>
@ -226,8 +218,8 @@ const renderStepper = (step, it, idx, classes) => {
{idx < steps.length - 1 && ( {idx < steps.length - 1 && (
<div <div
className={classnames({ className={classnames({
[classes.stepperPath]: true, 'absolute h-7 w-px border border-comet border-solid right-2 top-[18px]': true,
[classes.stepperPast]: past 'border-zodiac': past
})}></div> })}></div>
)} )}
</div> </div>
@ -235,7 +227,6 @@ const renderStepper = (step, it, idx, classes) => {
} }
const AddMachine = memo(({ close, onPaired }) => { const AddMachine = memo(({ close, onPaired }) => {
const classes = useStyles()
const { data } = useQuery(GET_MACHINES) const { data } = useQuery(GET_MACHINES)
const [qrCode, setQrCode] = useState('') const [qrCode, setQrCode] = useState('')
const [name, setName] = useState('') const [name, setName] = useState('')
@ -246,14 +237,12 @@ const AddMachine = memo(({ close, onPaired }) => {
return ( return (
<div> <div>
<Dialog <Dialog fullScreen open={true} aria-labelledby="form-dialog-title">
fullScreen <DialogContent className="p-0 pt-5 bg-ghost">
className={classes.dialog} <div
open={true} className=" mx-auto flex flex-col flex-col flex-col flex-col
aria-labelledby="form-dialog-title"> flex-col flex-col flex-col flex-col w-[1200px] h-full ">
<DialogContent className={classes.dialog}> <div className="flex items-center justify-between">
<div className={classes.wrapper}>
<div className={classes.headerDiv}>
<Title>Add Machine</Title> <Title>Add Machine</Title>
<IconButton onClick={close} size="large"> <IconButton onClick={close} size="large">
<SvgIcon color="error"> <SvgIcon color="error">
@ -261,13 +250,12 @@ const AddMachine = memo(({ close, onPaired }) => {
</SvgIcon> </SvgIcon>
</IconButton> </IconButton>
</div> </div>
<div className={classes.contentDiv}> <div className="flex flex-1">
<Sidebar> <Sidebar>
{steps.map((it, idx) => renderStepper(step, it, idx, classes))} {steps.map((it, idx) => renderStepper(step, it, idx))}
</Sidebar> </Sidebar>
<div className={classes.contentWrapper}> <div className="px-12 flex-1">
<Component <Component
classes={classes}
nextStep={() => setStep(1)} nextStep={() => setStep(1)}
count={count} count={count}
onPaired={onPaired} onPaired={onPaired}
@ -282,7 +270,7 @@ const AddMachine = memo(({ close, onPaired }) => {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</div> </div>
); )
}) })
export default AddMachine export default AddMachine

View file

@ -1,7 +1,6 @@
import typographyStyles from 'src/components/typography/styles' import typographyStyles from 'src/components/typography/styles'
import { import {
placeholderColor, placeholderColor,
backgroundColor,
primaryColor, primaryColor,
mainWidth, mainWidth,
spring2, spring2,
@ -15,14 +14,6 @@ const fill = '100%'
const flexDirection = 'column' const flexDirection = 'column'
const styles = { const styles = {
dialog: {
backgroundColor,
width: fill,
minHeight: fill,
display: 'flex',
flexDirection,
padding: 0
},
wrapper: { wrapper: {
width: mainWidth, width: mainWidth,
height: fill, height: fill,
@ -43,106 +34,6 @@ const styles = {
}, },
contentWrapper: { contentWrapper: {
marginLeft: 48 marginLeft: 48
},
button: {
marginTop: 64
},
nameTitle: {
marginTop: 16,
marginBottom: 25
},
qrTitle: {
marginTop: 12,
marginBottom: 40
},
qrCodeWrapper: {
display: 'flex'
},
qrTextInfoWrapper: {
display: 'flex',
flexDirection: 'row'
},
qrTextWrapper: {
width: 381,
marginLeft: 80,
display: 'flex',
flexDirection: 'column'
},
textWrapper: {
display: 'flex',
flexDirection: 'column'
},
qrTextIcon: {
marginRight: 16
},
qrText: {
marginTop: 0
},
item: {
position: 'relative',
margin: '12px 0 12px 0',
display: 'flex'
},
itemText: {
extend: p,
color: placeholderColor,
marginRight: 24
},
itemTextActive: {
extend: tl2,
color: primaryColor
},
itemTextPast: {
color: primaryColor
},
stepperPath: {
position: 'absolute',
height: 25,
width: 1,
border: [[1, 'solid', placeholderColor]],
right: 8,
top: 18
},
stepperPast: {
border: [[1, 'solid', primaryColor]]
},
successMessageWrapper: {
backgroundColor: spring3,
display: 'flex',
flexDirection: 'row',
padding: '0px 10px',
borderRadius: '8px'
},
successMessage: {
color: spring2,
margin: '8px 0px'
},
successMessageIcon: {
marginRight: 16,
marginBottom: 2,
display: 'flex',
flexDirection: 'col',
alignItems: 'center'
},
errorMessage: {
color: errorColor
},
qrCodeImageWrapper: {
display: 'flex',
flexDirection: 'column',
backgroundColor: 'white',
border: `5px solid ${primaryColor}`,
padding: 5,
borderRadius: 15
},
qrCodeScanMessage: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
margin: [[0, 0, 20, 20]],
'& > p': {
marginLeft: 10
}
} }
} }

View file

@ -1,6 +1,5 @@
import Fade from '@mui/material/Fade' import Fade from '@mui/material/Fade'
import Slide from '@mui/material/Slide' import Slide from '@mui/material/Slide'
import { makeStyles } from '@mui/styles'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useContext } from 'react' import React, { useContext } from 'react'
import { import {
@ -24,14 +23,7 @@ import PrivateRoute from './PrivateRoute'
import PublicRoute from './PublicRoute' import PublicRoute from './PublicRoute'
import getLamassuRoutes from './lamassu.routes' import getLamassuRoutes from './lamassu.routes'
const useStyles = makeStyles({ const wrapperClasses = 'flex flex-1 flex-col h-full'
wrapper: {
flex: 1,
display: 'flex',
flexDirection: 'column',
height: '100%'
}
})
const tree = getLamassuRoutes() const tree = getLamassuRoutes()
@ -65,8 +57,6 @@ const getParent = route =>
)(flattened) )(flattened)
const Routes = () => { const Routes = () => {
const classes = useStyles()
const history = useHistory() const history = useHistory()
const location = useLocation() const location = useLocation()
const { wizardTested, userData } = useContext(AppContext) const { wizardTested, userData } = useContext(AppContext)
@ -115,12 +105,12 @@ const Routes = () => {
</PrivateRoute> </PrivateRoute>
<PrivateRoute path={'/dashboard'}> <PrivateRoute path={'/dashboard'}>
<Transition <Transition
className={classes.wrapper} className={wrapperClasses}
{...transitionProps} {...transitionProps}
in={true} in={true}
mountOnEnter mountOnEnter
unmountOnExit> unmountOnExit>
<div className={classes.wrapper}> <div className={wrapperClasses}>
<Dashboard /> <Dashboard />
</div> </div>
</Transition> </Transition>
@ -134,12 +124,12 @@ const Routes = () => {
{getFilteredRoutes().map(({ route, component: Page, key }) => ( {getFilteredRoutes().map(({ route, component: Page, key }) => (
<PrivateRoute path={route} key={key}> <PrivateRoute path={route} key={key}>
<Transition <Transition
className={classes.wrapper} className={wrapperClasses}
{...transitionProps} {...transitionProps}
in={!!matchPath(location.pathname, { path: route })} in={!!matchPath(location.pathname, { path: route })}
mountOnEnter mountOnEnter
unmountOnExit> unmountOnExit>
<div className={classes.wrapper}> <div className={wrapperClasses}>
<PrivateRoute path={route} key={key}> <PrivateRoute path={route} key={key}>
<Page name={key} /> <Page name={key} />
</PrivateRoute> </PrivateRoute>

View file

@ -9,6 +9,11 @@
:root { :root {
--zodiac: #1b2559; --zodiac: #1b2559;
--spring: #48f694; --spring: #48f694;
--spring2: #44e188;
--spring3: #ecfbef;
--comet: #5f668a;
--tomato: #ff584a;
--ghost: #fafbff; --ghost: #fafbff;
--zircon: #ebefff; --zircon: #ebefff;
@ -17,6 +22,10 @@
@theme { @theme {
--color-zodiac: var(--zodiac); --color-zodiac: var(--zodiac);
--color-spring: var(--spring); --color-spring: var(--spring);
--color-spring2: var(--spring2);
--color-spring3: var(--spring3);
--color-comet: var(--comet);
--color-tomato: var(--tomato);
--color-ghost: var(--ghost); --color-ghost: var(--ghost);
--color-zircon: var(--zircon); --color-zircon: var(--zircon);
} }