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">
</div> Snap a picture and scan
</div>
<div className={classes.qrTextWrapper}>
<div className={classes.qrTextInfoWrapper}>
<div className={classes.qrTextIcon}>
<WarningIcon />
</div>
<div className={classes.textWrapper}>
<P className={classes.qrText}>
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
through the button above and scan it with the scanning bay on
your machine.
</P> </P>
</div> </div>
</div> </div>
<div className="max-w-100">
<div className="flex gap-4 mb-4">
<div>
<WarningIcon />
</div>
<P noMargin>
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
through the button above and scan it with the scanning bay on your
machine.
</P>
</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);
} }