partial: second batch of components

This commit is contained in:
Rafael Taranto 2025-05-08 16:22:10 +01:00
parent 8cd7374ee8
commit 9f4bf1de7b
35 changed files with 616 additions and 1044 deletions

View file

@ -1,5 +1,4 @@
import { useQuery, useMutation, gql } from "@apollo/client";
import { makeStyles } from '@mui/styles'
import { useQuery, useMutation, gql } from '@apollo/client'
import * as R from 'ramda'
import React, { useState, useEffect } from 'react'
import ActionButton from 'src/components/buttons/ActionButton'
@ -9,10 +8,8 @@ import ClearAllIconInverse from 'src/styling/icons/stage/spring/empty.svg?react'
import ClearAllIcon from 'src/styling/icons/stage/zodiac/empty.svg?react'
import ShowUnreadIcon from 'src/styling/icons/stage/zodiac/full.svg?react'
import styles from './NotificationCenter.styles'
import NotificationRow from './NotificationRow'
const useStyles = makeStyles(styles)
import classes from './NotificationCenter.module.css'
const GET_NOTIFICATIONS = gql`
query getNotifications {
@ -63,7 +60,6 @@ const NotificationCenter = ({
const [xOffset, setXoffset] = useState(300)
const [showingUnread, setShowingUnread] = useState(false)
const classes = useStyles({ buttonCoords, xOffset })
const machines = R.compose(
R.map(R.prop('name')),
R.indexBy(R.prop('deviceId'))
@ -120,7 +116,13 @@ const NotificationCenter = ({
<div className={classes.container}>
<div className={classes.header}>
<H5 className={classes.headerText}>Notifications</H5>
<button onClick={close} className={classes.notificationIcon}>
<button
onClick={close}
className={classes.notificationIcon}
style={{
top: buttonCoords?.y ?? 0,
left: buttonCoords?.x ? buttonCoords.x - xOffset : 0
}}>
<NotificationIconZodiac />
{hasUnread && <div className={classes.hasUnread} />}
</button>

View file

@ -0,0 +1,145 @@
.container {
width: 40vw;
height: 110vh;
right: 0;
background-color: white;
box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.24);
}
.container @media only screen and (max-width: 1920px) {
width: 30vw;
}
.header {
display: flex;
justify-content: space-between;
}
.headerText {
margin-top: 20px;
margin-left: 12px;
}
.actionButtons {
display: flex;
margin-left: 16px;
height: 0;
}
.notificationIcon {
position: absolute;
cursor: pointer;
background: transparent;
box-shadow: 0 0 0 transparent;
border: 0 solid transparent;
text-shadow: 0 0 0 transparent;
outline: none;
}
.clearAllButton {
margin-top: -16px;
margin-left: 8px;
background-color: var(--zircon);
}
.notificationsList {
height: 90vh;
max-height: 100vh;
margin-top: 24px;
margin-left: 0;
overflow-y: auto;
overflow-x: hidden;
background-color: white;
z-index: 10;
}
.notificationRow {
display: flex;
flex-direction: row;
justify-content: flex-start;
position: relative;
margin-bottom: 16px;
padding-top: 12px;
gap: 10px;
}
.notificationRow > *:first-child {
margin-right: 24px;
}
.notificationContent {
display: flex;
flex-direction: column;
justify-content: center;
width: 300px;
}
.unread {
background-color: var(--spring3)
}
.notificationRowIcon {
align-self: center;
}
.notificationRowIcon > * {
margin-left: 24px
}
.readIconWrapper {
flex-grow: 1
}
.unreadIcon {
margin-top: 5px;
margin-left: 8px;
width: 12px;
height: 12px;
background-color: var(--spring);
border-radius: 50%;
cursor: pointer;
z-index: 1;
}
.readIcon {
margin-left: 8px;
margin-top: 5px;
width: 12px;
height: 12px;
border: 1px solid var(--comet);
border-radius: 50%;
cursor: pointer;
z-index: 1;
}
.notificationTitle {
margin: 0;
color: var(--comet);
}
.notificationBody {
margin: 0
}
.notificationSubtitle {
margin: 0;
margin-bottom: 8px;
color: var(--comet);
}
.stripes {
position: absolute;
height: 100%;
top: 0;
opacity: 60%;
}
.hasUnread {
position: absolute;
top: 0;
left: 16px;
width: 9px;
height: 9px;
background-color: var(--spring);
border-radius: 50%;
}

View file

@ -1,144 +0,0 @@
import {
spacer,
white,
zircon,
secondaryColor,
spring3,
comet
} from 'src/styling/variables'
const styles = {
container: {
'@media only screen and (max-width: 1920px)': {
width: '30vw'
},
width: '40vw',
height: '110vh',
right: 0,
backgroundColor: white,
boxShadow: '0 0 14px 0 rgba(0, 0, 0, 0.24)'
},
header: {
display: 'flex',
justifyContent: 'space-between'
},
headerText: {
marginTop: spacer * 2.5,
marginLeft: spacer * 3
},
actionButtons: {
display: 'flex',
marginLeft: spacer * 2,
height: 0
},
notificationIcon: ({ buttonCoords, xOffset }) => ({
position: 'absolute',
top: buttonCoords ? buttonCoords.y : 0,
left: buttonCoords ? buttonCoords.x - xOffset : 0,
cursor: 'pointer',
background: 'transparent',
boxShadow: '0px 0px 0px transparent',
border: '0px solid transparent',
textShadow: '0px 0px 0px transparent',
outline: 'none'
}),
clearAllButton: {
marginTop: -spacer * 2,
marginLeft: spacer,
backgroundColor: zircon
},
notificationsList: {
height: '90vh',
maxHeight: '100vh',
marginTop: spacer * 3,
marginLeft: 0,
overflowY: 'auto',
overflowX: 'hidden',
backgroundColor: white,
zIndex: 10
},
notificationRow: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-start',
position: 'relative',
marginBottom: spacer / 2,
paddingTop: spacer * 1.5,
'& > *:first-child': {
marginRight: 24
},
'& > *': {
marginRight: 10
},
'& > *:last-child': {
marginRight: 0
}
},
notificationContent: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
width: 300
},
unread: {
backgroundColor: spring3
},
notificationRowIcon: {
alignSelf: 'center',
'& > *': {
marginLeft: spacer * 3
}
},
readIconWrapper: {
flexGrow: 1
},
unreadIcon: {
marginTop: 5,
marginLeft: spacer,
width: '12px',
height: '12px',
backgroundColor: secondaryColor,
borderRadius: '50%',
cursor: 'pointer',
zIndex: 1
},
readIcon: {
marginLeft: spacer,
marginTop: 5,
width: '12px',
height: '12px',
border: [[1, 'solid', comet]],
borderRadius: '50%',
cursor: 'pointer',
zIndex: 1
},
notificationTitle: {
margin: 0,
color: comet
},
notificationBody: {
margin: 0
},
notificationSubtitle: {
margin: 0,
marginBottom: spacer,
color: comet
},
stripes: {
position: 'absolute',
height: '100%',
top: '0px',
opacity: '60%'
},
hasUnread: {
position: 'absolute',
top: 0,
left: 16,
width: '9px',
height: '9px',
backgroundColor: secondaryColor,
borderRadius: '50%'
}
}
export default styles

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import prettyMs from 'pretty-ms'
import * as R from 'ramda'
@ -8,8 +7,7 @@ import Wrench from 'src/styling/icons/action/wrench/zodiac.svg?react'
import Transaction from 'src/styling/icons/arrow/transaction.svg?react'
import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
import styles from './NotificationCenter.styles'
const useStyles = makeStyles(styles)
import classes from './NotificationCenter.module.css'
const types = {
transaction: {
@ -46,8 +44,6 @@ const NotificationRow = ({
valid,
toggleClear
}) => {
const classes = useStyles()
const typeDisplay = R.path([type, 'display'])(types) ?? null
const icon = R.path([type, 'icon'])(types) ?? (
<Wrench height={16} width={16} />

View file

@ -1,60 +1,22 @@
import Checkbox from '@mui/material/Checkbox'
import { makeStyles } from '@mui/styles'
import CheckBoxIcon from '@mui/icons-material/CheckBox'
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'
import React from 'react'
import { Label2, Info3 } from 'src/components/typography'
import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react'
import {
fontSize2,
fontSize3,
secondaryColor,
offColor
} from 'src/styling/variables'
const useStyles = makeStyles({
root: {
color: secondaryColor,
'&.Mui-checked': {
color: secondaryColor
}
},
checked: {},
checkBoxLabel: {
display: 'flex'
},
wrapper: {
display: 'flex',
alignItems: 'center',
'& > svg': {
marginRight: 10
}
},
message: {
display: 'flex',
alignItems: 'center',
color: offColor,
margin: 0,
whiteSpace: 'break-spaces'
}
})
import { fontSize2, fontSize3 } from 'src/styling/variables'
const CheckboxInput = ({ name, onChange, value, settings, ...props }) => {
const { enabled, label, disabledMessage, rightSideLabel } = settings
const classes = useStyles()
return (
<>
{enabled ? (
<div className={classes.checkBoxLabel}>
<div className="flex">
{!rightSideLabel && <Label2>{label}</Label2>}
<Checkbox
id={name}
classes={{
root: classes.root,
checked: classes.checked
}}
onChange={onChange}
value={value}
checked={value}
@ -70,9 +32,11 @@ const CheckboxInput = ({ name, onChange, value, settings, ...props }) => {
{rightSideLabel && <Label2>{label}</Label2>}
</div>
) : (
<div className={classes.wrapper}>
<div className="flex items-center gap-2">
<WarningIcon />
<Info3 className={classes.message}>{disabledMessage}</Info3>
<Info3 className="flex items-center text-comet m-0 whitespace-break-spaces">
{disabledMessage}
</Info3>
</div>
)}
</>

View file

@ -1,14 +1,8 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import OtpInput from 'react-otp-input'
import typographyStyles from 'src/components/typography/styles'
import styles from './CodeInput.styles'
const useStyles = makeStyles(styles)
const useTypographyStyles = makeStyles(typographyStyles)
import classes from './CodeInput.module.css'
const CodeInput = ({
name,
@ -19,9 +13,6 @@ const CodeInput = ({
inputStyle,
containerStyle
}) => {
const classes = useStyles()
const typographyClasses = useTypographyStyles()
return (
<OtpInput
id={name}
@ -30,19 +21,15 @@ const CodeInput = ({
numInputs={numInputs}
renderSeparator={<span> </span>}
shouldAutoFocus
containerStyle={classnames(containerStyle, classes.container)}
containerStyle={classnames(containerStyle, 'justify-evenly')}
inputStyle={classnames(
inputStyle,
classes.input,
typographyClasses.confirmationCode,
error && classes.error
'font-museo font-black text-4xl',
error && 'border-tomato'
)}
inputType={'tel'}
renderInput={(props) => (
<input
{...props}
/>
)}
renderInput={props => <input {...props} />}
/>
)
}

View file

@ -0,0 +1,14 @@
.input {
width: 3.5rem !important;
height: 5rem;
border: 2px solid;
border-color: var(--zircon);
border-radius: 4px;
}
.input:focus {
border: 2px solid;
border-color: var(--zodiac);
border-radius: 4px;
outline: none;
}

View file

@ -1,27 +0,0 @@
import { primaryColor, zircon, errorColor } from 'src/styling/variables'
const styles = {
input: {
width: '3.5rem !important',
height: '5rem',
border: '2px solid',
borderColor: zircon,
borderRadius: '4px',
'&:focus': {
border: '2px solid',
borderColor: primaryColor,
borderRadius: '4px',
'&:focus': {
outline: 'none'
}
},
},
error: {
borderColor: errorColor
},
container: {
justifyContent: 'space-evenly'
}
}
export default styles

View file

@ -1,31 +1,10 @@
import Radio from '@mui/material/Radio'
import MRadioGroup from '@mui/material/RadioGroup'
import FormControlLabel from '@mui/material/FormControlLabel'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import { Label1 } from 'src/components/typography'
import { offColor, secondaryColor } from 'src/styling/variables'
const styles = {
label: {
height: 16,
lineHeight: '16px',
margin: [[0, 0, 4, 0]],
paddingLeft: 3
},
subtitle: {
marginTop: -8,
marginLeft: 32,
color: offColor
},
radio: {
color: secondaryColor
}
}
const useStyles = makeStyles(styles)
const RadioGroup = ({
name,
label,
@ -36,10 +15,11 @@ const RadioGroup = ({
labelClassName,
radioClassName
}) => {
const classes = useStyles()
return (
<>
{label && <Label1 className={classes.label}>{label}</Label1>}
{label && (
<Label1 className="h-4 leading-4 m-0 mb-1 pl-1">{label}</Label1>
)}
<MRadioGroup
name={name}
value={value}
@ -51,12 +31,16 @@ const RadioGroup = ({
<FormControlLabel
disabled={option.disabled}
value={option.code}
control={<Radio className={classnames(classes.radio, radioClassName)} />}
control={
<Radio
className={classnames('text-spring', radioClassName)}
/>
}
label={option.display}
className={classnames(labelClassName)}
/>
{option.subtitle && (
<Label1 className={classes.subtitle}>{option.subtitle}</Label1>
<Label1 className="-mt-2 ml-8">{option.subtitle}</Label1>
)}
</div>
</React.Fragment>

View file

@ -1,30 +1,19 @@
import { makeStyles } from '@mui/styles'
import classNames from 'classnames'
import React, { memo, useState } from 'react'
import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
import { NumberInput } from '../base'
const useStyles = makeStyles({
flex: {
display: 'flex'
},
cashCassette: {
height: 36,
marginRight: 14
}
})
const CashCassetteInput = memo(
({ decimalPlaces, width, threshold, inputClassName, ...props }) => {
const classes = useStyles()
const { name, onChange, onBlur, value } = props.field
const { touched, errors } = props.form
const [notes, setNotes] = useState(value)
const error = !!(touched[name] && errors[name])
return (
<div className={classes.flex}>
<div className="flex">
<CashOut
className={classNames(classes.cashCassette, inputClassName)}
className={classNames('h-9 mr-4', inputClassName)}
notes={notes}
editingMode={true}
width={width}

View file

@ -1,36 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
fontColor,
offColor,
inputFontSize,
inputFontWeight
} from 'src/styling/variables'
const { info3 } = typographyStyles
const styles = {
masked: {
position: 'absolute',
bottom: 5,
left: 4,
color: fontColor,
fontSize: inputFontSize,
fontWeight: inputFontWeight
},
secretSpan: {
extend: info3,
color: offColor
},
hideSpan: {
display: 'none'
},
maskedInput: {
'& input': {
pointerEvents: 'none',
backgroundColor: 'transparent',
zIndex: -1
}
}
}
export { styles }

View file

@ -1,7 +1,6 @@
import { useQuery, gql } from "@apollo/client";
import { useQuery, gql } from '@apollo/client'
import ClickAwayListener from '@mui/material/ClickAwayListener'
import Popper from '@mui/material/Popper'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { memo, useState, useEffect, useRef } from 'react'
@ -16,9 +15,7 @@ import NotificationIcon from 'src/styling/icons/menu/notification.svg?react'
import NotificationCenter from 'src/components/NotificationCenter'
import AddMachine from 'src/pages/AddMachine'
import styles from './Header.styles'
const useStyles = makeStyles(styles)
import styles from './Header.module.css'
const HAS_UNREAD = gql`
query getUnread {
@ -26,22 +23,22 @@ const HAS_UNREAD = gql`
}
`
const Subheader = ({ item, classes, user }) => {
const Subheader = ({ item, user }) => {
const [prev, setPrev] = useState(null)
return (
<div className={classes.subheader}>
<div className={classes.content}>
<div className={styles.subheader}>
<div className={styles.content}>
<nav>
<ul className={classes.subheaderUl}>
<ul className={styles.subheaderUl}>
{item.children.map((it, idx) => {
if (!R.includes(user.role, it.allowedRoles)) return <></>
return (
<li key={idx} className={classes.subheaderLi}>
<li key={idx} className={styles.subheaderLi}>
<NavLink
to={{ pathname: it.route, state: { prev } }}
className={classes.subheaderLink}
activeClassName={classes.activeSubheaderLink}
className={styles.subheaderLink}
activeClassName={styles.activeSubheaderLink}
isActive={match => {
if (!match) return false
setPrev(it.route)
@ -72,7 +69,6 @@ const Header = memo(({ tree, user }) => {
const notifCenterButtonRef = useRef()
const popperRef = useRef()
const history = useHistory()
const classes = useStyles()
useEffect(() => {
if (data?.hasUnreadNotifications) return setHasUnread(true)
@ -112,20 +108,20 @@ const Header = memo(({ tree, user }) => {
const popperOpen = Boolean(anchorEl)
const id = popperOpen ? 'notifications-popper' : undefined
return (
<header className={classes.headerContainer}>
<div className={classes.header}>
<div className={classes.content}>
<header className={styles.headerContainer}>
<div className={styles.header}>
<div className={styles.content}>
<div
onClick={() => {
setActive(false)
history.push('/dashboard')
}}
className={classnames(classes.logo, classes.logoLink)}>
className={classnames(styles.logo, styles.logoLink)}>
<Logo />
<H4 className={classes.white}>Lamassu Admin</H4>
<H4 className="text-white">Lamassu Admin</H4>
</div>
<nav className={classes.nav}>
<ul className={classes.ul}>
<nav className={styles.nav}>
<ul className={styles.ul}>
{tree.map((it, idx) => {
if (!R.includes(user.role, it.allowedRoles)) return <></>
return (
@ -137,11 +133,11 @@ const Header = memo(({ tree, user }) => {
setActive(it)
return true
}}
className={classnames(classes.link, classes.whiteLink)}
activeClassName={classes.activeLink}>
<li className={classes.li}>
className={classnames(styles.link)}
activeClassName={styles.activeLink}>
<li className={styles.li}>
<span
className={classes.forceSize}
className={styles.forceSize}
data-forcesize={it.label}>
{it.label}
</span>
@ -151,7 +147,7 @@ const Header = memo(({ tree, user }) => {
})}
</ul>
</nav>
<div className={classes.actionButtonsContainer}>
<div className={styles.actionButtonsContainer}>
<ActionButton
color="secondary"
Icon={AddIcon}
@ -163,16 +159,16 @@ const Header = memo(({ tree, user }) => {
<div ref={notifCenterButtonRef}>
<button
onClick={handleClick}
className={classes.notificationIcon}>
className={styles.notificationIcon}>
<NotificationIcon />
{hasUnread && <div className={classes.hasUnread} />}
{hasUnread && <div className={styles.hasUnread} />}
</button>
<Popper
ref={popperRef}
id={id}
open={popperOpen}
anchorEl={anchorEl}
className={classes.popper}
className={styles.popper}
disablePortal={false}
placement="bottom-end"
modifiers={[
@ -187,8 +183,8 @@ const Header = memo(({ tree, user }) => {
name: 'preventOverflow',
enabled: true,
options: {
rootBoundary: 'viewport',
},
rootBoundary: 'viewport'
}
}
]}>
<NotificationCenter
@ -204,9 +200,7 @@ const Header = memo(({ tree, user }) => {
</div>
</div>
</div>
{active && active.children && (
<Subheader item={active} classes={classes} user={user} />
)}
{active && active.children && <Subheader item={active} user={user} />}
{open && <AddMachine close={() => setOpen(false)} onPaired={onPaired} />}
</header>
)

View file

@ -0,0 +1,175 @@
.headerContainer {
position: relative;
}
.header {
background-color: var(--zodiac);
color: white;
height: 56px;
display: flex;
}
.content {
max-width: 1200px;
flex: 1;
display: flex;
align-items: center;
margin: 0 auto;
}
.nav {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
}
.ul {
display: flex;
padding-left: 36px;
height: 56px;
margin: 0;
}
.li {
list-style: none;
color: white;
margin: 20px 20px 0 20px;
position: relative;
line-height: 17px;
}
.li:hover {
color: white;
}
.li:hover::after {
width: 50%;
margin-left: -25%;
}
.li::after {
content: "";
display: block;
background: white;
width: 0;
height: 4px;
left: 50%;
margin-left: 0;
position: absolute;
border-radius: 1000px;
transition: all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94);
}
.link {
text-decoration: none;
border: none;
color: white;
background-color: transparent;
}
.forceSize {
display: inline-block;
text-align: center;
}
.forceSize::after {
display: block;
content: attr(data-forcesize);
font-weight: 700;
height: 0;
overflow: hidden;
visibility: hidden;
}
.activeLink {
color: white;
}
.activeLink li::after {
width: 50%;
margin-left: -25%;
}
.addMachine {
margin-left: auto;
}
.subheader {
background-color: var(--zircon);
color: white;
height: 40px;
display: flex;
}
.subheaderUl {
display: flex;
padding-left: 0;
margin: 0;
}
.subheaderLi {
list-style: none;
padding: 0 20px;
}
.subheaderLi:first-child {
padding-left: 0;
}
.subheaderLink {
text-decoration: none;
border: none;
color: var(--comet);
}
.activeSubheaderLink {
text-shadow: 0.2px 0 0 currentColor;
color: var(--zodiac);
}
.logo {
display: flex;
align-items: center;
}
.logo > svg {
margin-right: 16px;
}
.logoLink {
cursor: pointer;
}
.actionButtonsContainer {
z-index: 1;
position: relative;
display: flex;
justify-content: space-between;
min-width: 200px;
transform: translateZ(0);
}
.notificationIcon {
margin-top: 4px;
cursor: pointer;
background: transparent;
box-shadow: 0px 0px 0px transparent;
border: 0px solid transparent;
text-shadow: 0px 0px 0px transparent;
outline: none;
}
.hasUnread {
position: absolute;
top: 4px;
left: 186px;
width: 9px;
height: 9px;
background-color: var(--spring);
border-radius: 50%;
}
.popper {
z-index: 1;
}

View file

@ -1,182 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
version,
mainWidth,
spacer,
white,
primaryColor,
secondaryColor,
placeholderColor,
subheaderColor,
fontColor
} from 'src/styling/variables'
const { p } = typographyStyles
let headerHeight = spacer * 7
let subheaderHeight = spacer * 5
if (version === 8) {
headerHeight = spacer * 8
subheaderHeight = spacer * 7
}
const styles = {
headerContainer: {
position: 'relative'
},
header: {
backgroundColor: primaryColor,
color: white,
height: headerHeight,
display: 'flex'
},
content: {
maxWidth: mainWidth,
flex: 1,
display: 'flex',
alignItems: 'center',
margin: '0 auto'
},
nav: {
flex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between'
},
ul: {
display: 'flex',
paddingLeft: spacer * 4.5,
height: spacer * 7,
margin: 0
},
li: {
// extend: tl2,
// height: spacer * 7,
listStyle: 'none',
color: white,
margin: [[spacer * 2.5, spacer * 2.5, 0, spacer * 2.5]],
'&:hover': {
color: white
},
'&:hover::after': {
width: '50%',
marginLeft: '-25%'
},
position: 'relative',
'&:after': {
content: '""',
display: 'block',
background: white,
width: 0,
height: 4,
left: '50%',
marginLeft: 0,
bottom: -8,
position: 'absolute',
borderRadius: 1000,
transition: [['all', '0.2s', 'cubic-bezier(0.95, 0.1, 0.45, 0.94)']]
}
},
link: {
extend: p,
textDecoration: 'none',
border: 'none',
color: white,
backgroundColor: 'transparent'
},
forceSize: {
display: 'inline-block',
textAlign: 'center',
'&:after': {
display: 'block',
content: 'attr(data-forcesize)',
fontWeight: 700,
height: 0,
overflow: 'hidden',
visibility: 'hidden'
}
},
activeLink: {
color: white,
'& li::after': {
width: '50%',
marginLeft: '-25%'
}
},
addMachine: {
marginLeft: 'auto'
},
subheader: {
backgroundColor: subheaderColor,
color: white,
height: subheaderHeight,
display: 'flex'
},
subheaderUl: {
display: 'flex',
paddingLeft: 0,
margin: 0
},
subheaderLi: {
listStyle: 'none',
padding: [[0, spacer * 2.5]],
'&:first-child': {
paddingLeft: 0
}
},
subheaderLink: {
extend: p,
textDecoration: 'none',
border: 'none',
color: placeholderColor
},
activeSubheaderLink: {
textShadow: '0.2px 0 0 currentColor',
color: fontColor
},
white: {
color: white
},
logo: {
display: 'flex',
alignItems: 'center',
'& > svg': {
marginRight: 16
}
},
logoLink: {
cursor: 'pointer'
},
actionButtonsContainer: {
zIndex: 1,
position: 'relative',
display: 'flex',
justifyContent: 'space-between',
minWidth: 200,
transform: 'translateZ(0)'
},
notificationIcon: {
marginTop: spacer / 2,
cursor: 'pointer',
background: 'transparent',
boxShadow: '0px 0px 0px transparent',
border: '0px solid transparent',
textShadow: '0px 0px 0px transparent',
outline: 'none'
},
hasUnread: {
position: 'absolute',
top: 4,
left: 186,
width: '9px',
height: '9px',
backgroundColor: secondaryColor,
borderRadius: '50%'
},
popper: {
zIndex: 1
}
}
export default styles

View file

@ -1,19 +1,13 @@
import { makeStyles } from '@mui/styles'
import React from 'react'
import ErrorMessage from 'src/components/ErrorMessage'
import Subtitle from 'src/components/Subtitle'
import styles from './Section.styles'
const useStyles = makeStyles(styles)
const Section = ({ error, children, title }) => {
const classes = useStyles()
return (
<div className={classes.section}>
<div className="mb-8">
{(title || error) && (
<div className={classes.sectionHeader}>
<Subtitle className={classes.sectionTitle}>{title}</Subtitle>
<div className="flex items-center">
<Subtitle className="mt-4 mr-5 mb-6 ml-0">{title}</Subtitle>
{error && <ErrorMessage>Failed to save changes</ErrorMessage>}
</div>
)}

View file

@ -1,12 +0,0 @@
export default {
section: {
marginBottom: 72
},
sectionHeader: {
display: 'flex',
alignItems: 'center'
},
sectionTitle: {
margin: [[16, 20, 23, 0]]
}
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import { P } from 'src/components/typography'
@ -6,9 +5,7 @@ import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg
import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react'
import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react'
import styles from './Sidebar.styles'
const useStyles = makeStyles(styles)
import styles from './Sidebar.module.css'
const Sidebar = ({
data,
@ -19,23 +16,21 @@ const Sidebar = ({
itemRender,
loading = false
}) => {
const classes = useStyles()
return (
<div className={classes.sidebar}>
<div className={styles.sidebar}>
{loading && <P>Loading...</P>}
{!loading &&
data?.map((it, idx) => (
<div
key={idx}
className={classes.linkWrapper}
className={styles.linkWrapper}
onClick={() => onClick(it)}>
<div
className={classnames({
[classes.activeLink]: isSelected(it),
[classes.customRenderActiveLink]: itemRender && isSelected(it),
[classes.customRenderLink]: itemRender,
[classes.link]: true
[styles.activeLink]: isSelected(it),
[styles.customRenderActiveLink]: itemRender && isSelected(it),
[styles.customRenderLink]: itemRender,
[styles.link]: true
})}>
{itemRender ? itemRender(it, isSelected(it)) : displayName(it)}
</div>
@ -49,18 +44,17 @@ const Sidebar = ({
export default Sidebar
const Stepper = ({ step, it, idx, steps }) => {
const classes = useStyles()
const active = step === idx
const past = idx < step
const future = idx > step
return (
<div className={classes.item}>
<div className={styles.item}>
<span
className={classnames({
[classes.itemText]: true,
[classes.itemTextActive]: active,
[classes.itemTextPast]: past
[styles.itemText]: true,
[styles.itemTextActive]: active,
[styles.itemTextPast]: past
})}>
{it.label}
</span>
@ -70,8 +64,8 @@ const Stepper = ({ step, it, idx, steps }) => {
{idx < steps.length - 1 && (
<div
className={classnames({
[classes.stepperPath]: true,
[classes.stepperPast]: past
[styles.stepperPath]: true,
[styles.stepperPast]: past
})}></div>
)}
</div>

View file

@ -0,0 +1,106 @@
:root {
--sidebar-color: var(--zircon);
}
.sidebar {
display: flex;
background-color: var(--sidebar-color);
width: 520px;
margin-left: -300px;
box-shadow: -500px 0px 0px 0px var(--sidebar-color);
border-radius: 0 20px 0 0;
align-items: flex-end;
padding: 24px;
flex-direction: column;
}
@media (max-width: 1440px) {
.sidebar {
width: auto;
margin-left: 0;
min-width: 250px;
box-shadow: -200px 0px 0px 0px var(--sidebar-color);
}
}
.linkWrapper {
cursor: pointer;
}
.link {
position: relative;
color: var(--comet);
margin: 12px 24px 12px 0;
cursor: pointer;
}
.link:hover::after {
height: 140%;
}
.link::after {
content: "";
display: block;
background: var(--zodiac);
width: 4px;
height: 0;
left: 100%;
margin-left: 20px;
bottom: -2px;
position: absolute;
border-radius: 1000px;
transition: all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94);
}
.activeLink {
font-weight: 700;
color: var(--zodiac);
}
.activeLink::after {
height: 140%;
}
.customRenderLink:hover::after {
height: 100%;
}
.customRenderLink::after {
bottom: 0;
}
.customRenderActiveLink::after {
height: 100%;
}
.item {
position: relative;
margin: 12px 0 12px 0;
display: flex;
}
.itemText {
color: var(--comet);
margin-right: 24px;
}
.itemTextActive {
color: var(--zodiac);
}
.itemTextPast {
color: var(--zodiac);
}
.stepperPath {
position: absolute;
height: 25px;
width: 1px;
border: 1px solid var(--comet);
right: 8px;
top: 18px;
}
.stepperPast {
border: 1px solid var(--zodiac);
}

View file

@ -1,107 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import { respondTo } from 'src/styling/helpers'
import {
primaryColor,
spacer,
placeholderColor,
zircon,
xxl
} from 'src/styling/variables'
const { tl2, p } = typographyStyles
const sidebarColor = zircon
export default {
sidebar: {
display: 'flex',
backgroundColor: sidebarColor,
width: 520,
marginLeft: -300,
boxShadow: `-500px 0px 0px 0px ${sidebarColor}`,
borderRadius: '0 20px 0 0',
alignItems: 'flex-end',
padding: spacer * 3,
flexDirection: 'column',
[respondTo(xxl)]: {
width: 'auto',
marginLeft: 0,
minWidth: 250,
boxShadow: `-200px 0px 0px 0px ${sidebarColor}`
}
},
linkWrapper: {
cursor: 'pointer'
},
link: {
extend: p,
position: 'relative',
color: placeholderColor,
margin: '12px 24px 12px 0',
cursor: 'pointer',
'&:hover::after': {
height: '140%'
},
'&:after': {
content: '""',
display: 'block',
background: primaryColor,
width: 4,
height: 0,
left: '100%',
marginLeft: 20,
bottom: -2,
position: 'absolute',
borderRadius: 1000,
transition: 'all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94)'
}
},
activeLink: {
extend: tl2,
color: primaryColor,
'&::after': {
height: '140%'
}
},
customRenderLink: {
'&:hover::after': {
height: '100%'
},
'&:after': {
bottom: 0
}
},
customRenderActiveLink: {
'&::after': {
height: '100%'
}
},
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]]
}
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React from 'react'
@ -8,10 +7,6 @@ import { Info1, Label1 } from 'src/components/typography'
import { SubpageButton } from 'src/components/buttons'
import styles from './TitleSection.styles'
const useStyles = makeStyles(styles)
const TitleSection = ({
className,
title,
@ -22,15 +17,16 @@ const TitleSection = ({
appendix,
appendixRight
}) => {
const classes = useStyles()
return (
<div className={classnames(classes.titleWrapper, className)}>
<div className={classes.titleAndButtonsContainer}>
<div
className={classnames(
'flex justify-between items-center flex-row',
className
)}>
<div className="flex items-center">
<Title>{title}</Title>
{!!appendix && appendix}
{error && (
<ErrorMessage className={classes.error}>Failed to save</ErrorMessage>
)}
{error && <ErrorMessage className="ml-3">Failed to save</ErrorMessage>}
{buttons.length > 0 && (
<>
{buttons.map((button, idx) =>
@ -39,12 +35,14 @@ const TitleSection = ({
) : (
<SubpageButton
key={idx}
className={classes.subpageButton}
className="ml-3"
Icon={button.icon}
InverseIcon={button.inverseIcon}
toggle={button.toggle}
forceDisable={button.forceDisable}>
<Info1 className={classes.buttonText}>{button.text}</Info1>
<Info1 className="text-ghost font-mont text-base">
{button.text}
</Info1>
</SubpageButton>
)
)}
@ -54,8 +52,8 @@ const TitleSection = ({
<div className="flex flex-row items-center">
{(labels ?? []).map(({ icon, label }, idx) => (
<div key={idx} className="flex items-center">
<div className={classes.icon}>{icon}</div>
<Label1 className={classes.label}>{label}</Label1>
<div className="mr-1">{icon}</div>
<Label1 className="mr-6">{label}</Label1>
</div>
))}
{appendixRight}

View file

@ -1,31 +0,0 @@
import { backgroundColor } from 'src/styling/variables'
export default {
titleWrapper: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row'
},
titleAndButtonsContainer: {
display: 'flex',
alignItems: 'center'
},
error: {
marginLeft: 12
},
subpageButton: {
marginLeft: 12
},
buttonText: {
color: backgroundColor,
fontFamily: 'Mont',
fontSize: 15
},
icon: {
marginRight: 6
},
label: {
marginRight: 24
}
}

View file

@ -1,5 +1,4 @@
import { useLazyQuery, useQuery, gql } from "@apollo/client";
import { makeStyles } from '@mui/styles'
import { useLazyQuery, useQuery, gql } from '@apollo/client'
import { subMinutes } from 'date-fns'
import FileSaver from 'file-saver'
import React, { useState, useEffect } from 'react'
@ -8,10 +7,6 @@ import { H3, P } from 'src/components/typography'
import { Button } from 'src/components/buttons'
import { diagnosticsModal } from './MachineActions.styles'
const useStyles = makeStyles(diagnosticsModal)
const STATES = {
INITIAL: 'INITIAL',
EMPTY: 'EMPTY',
@ -59,7 +54,6 @@ const createCsv = async ({ machineLogsCsv }) => {
}
const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
const classes = useStyles()
const [state, setState] = useState(STATES.INITIAL)
const [timestamp, setTimestamp] = useState(null)
let timeout = null
@ -103,6 +97,8 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
sendAction()
}
const messageClass = 'm-auto flex flex-col items-center justify-center'
return (
<Modal
closeOnBackdropClick={true}
@ -111,27 +107,27 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
handleClose={onClose}
open={true}>
{state === STATES.INITIAL && (
<div className={classes.message}>
<div className={messageClass}>
<H3>Loading...</H3>
</div>
)}
{state === STATES.EMPTY && (
<div className={classes.message}>
<div className={messageClass}>
<H3>No diagnostics available</H3>
<P>Run diagnostics to generate a report</P>
</div>
)}
{state === STATES.RUNNING && (
<div className={classes.message}>
<div className={messageClass}>
<H3>Running Diagnostics...</H3>
<P>This page should refresh automatically</P>
</div>
)}
{state === STATES.FAILURE && (
<div className={classes.message}>
<div className={messageClass}>
<H3>Failed to run diagnostics</H3>
<P>Please try again. If the problem persists, contact support.</P>
</div>
@ -139,11 +135,11 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
{state === STATES.FILLED && (
<div>
<div className={classes.photoWrapper}>
<div className="flex mt-6">
<div>
<H3>Scan</H3>
<img
className={classes.photo}
className="w-88"
src={path + 'scan.jpg'}
alt="Failure getting photo"
/>
@ -151,7 +147,7 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
<div>
<H3>Front</H3>
<img
className={classes.photo}
className="w-88"
src={path + 'front.jpg'}
alt="Failure getting photo"
/>
@ -163,7 +159,7 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
</div>
</div>
)}
<div className={classes.footer}>
<div className="flex flex-row mt-auto ml-auto mr-2 mb-0">
<Button
disabled={state !== STATES.FILLED || !timestamp}
onClick={() => {
@ -176,7 +172,7 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
}
})
}}
className={classes.downloadLogs}>
className="mt-auto ml-auto mr-2 mb-0">
Download Logs
</Button>
<Button

View file

@ -1,5 +1,4 @@
import { useMutation, useLazyQuery, gql } from "@apollo/client";
import { makeStyles } from '@mui/styles'
import { useMutation, useLazyQuery, gql } from '@apollo/client'
import React, { memo, useState } from 'react'
import { ConfirmDialog } from 'src/components/ConfirmDialog'
import ActionButton from 'src/components/buttons/ActionButton'
@ -14,9 +13,6 @@ import UnpairReversedIcon from 'src/styling/icons/button/unpair/white.svg?react'
import UnpairIcon from 'src/styling/icons/button/unpair/zodiac.svg?react'
import DiagnosticsModal from './DiagnosticsModal'
import { machineActionsStyles } from './MachineActions.styles'
const useStyles = makeStyles(machineActionsStyles)
const MACHINE_ACTION = gql`
mutation MachineAction(
@ -67,10 +63,9 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
const [preflightOptions, setPreflightOptions] = useState({})
const [showModal, setShowModal] = useState(false)
const [errorMessage, setErrorMessage] = useState(null)
const classes = useStyles()
const warningMessage = (
<span className={classes.warning}>
<span className="text-tomato">
A user may be in the middle of a transaction and they could lose their
funds if you continue.
</span>
@ -113,10 +108,9 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
return (
<div>
<H3>Actions</H3>
<div className={classes.stack}>
<div className="flex flex-row flex-wrap justify-start gap-2">
<ActionButton
color="primary"
className={classes.mr}
Icon={EditIcon}
InverseIcon={EditReversedIcon}
disabled={loading}
@ -131,7 +125,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
</ActionButton>
<ActionButton
color="primary"
className={classes.mr}
Icon={UnpairIcon}
InverseIcon={UnpairReversedIcon}
disabled={loading}
@ -145,7 +138,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
</ActionButton>
<ActionButton
color="primary"
className={classes.mr}
Icon={RebootIcon}
InverseIcon={RebootReversedIcon}
disabled={loading}
@ -159,7 +151,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
</ActionButton>
<ActionButton
color="primary"
className={classes.mr}
Icon={ShutdownIcon}
InverseIcon={ShutdownReversedIcon}
disabled={loading}
@ -175,7 +166,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
</ActionButton>
<ActionButton
color="primary"
className={classes.inlineChip}
Icon={RebootIcon}
InverseIcon={RebootReversedIcon}
disabled={loading}
@ -190,7 +180,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
{machine.model === 'aveiro' && (
<ActionButton
color="primary"
className={classes.mr}
Icon={RebootIcon}
InverseIcon={RebootReversedIcon}
disabled={loading}
@ -208,7 +197,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
{machine.model === 'aveiro' && (
<ActionButton
color="primary"
className={classes.inlineChip}
Icon={RebootIcon}
InverseIcon={RebootReversedIcon}
disabled={loading}
@ -225,7 +213,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
)}
<ActionButton
color="primary"
className={classes.mr}
Icon={RebootIcon}
InverseIcon={RebootReversedIcon}
disabled={loading}

View file

@ -1,61 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import { offColor, spacer, errorColor } from 'src/styling/variables'
const { label1 } = typographyStyles
const machineActionsStyles = {
label: {
extend: label1,
color: offColor,
marginBottom: 4
},
inlineChip: {
marginInlineEnd: '0.25em'
},
stack: {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'start'
},
mr: {
marginRight: spacer,
marginBottom: spacer
},
warning: {
color: errorColor
}
}
const diagnosticsModal = {
modal: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '1em'
},
photo: {
width: 350
},
photoWrapper: {
marginTop: spacer * 3,
display: 'flex'
},
footer: {
display: 'flex',
flexDirection: 'row',
margin: [['auto', 0, spacer * 3, 0]]
},
downloadLogs: {
margin: [['auto', spacer, 0, 'auto']]
},
message: {
margin: 'auto',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
}
}
export { machineActionsStyles, diagnosticsModal }

View file

@ -1,5 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import {
Table,
@ -13,9 +11,7 @@ import EditIcon from 'src/styling/icons/action/edit/white.svg?react'
import { IconButton } from 'src/components/buttons'
import styles from './SingleRowTable.styles'
const useStyles = makeStyles(styles)
import { Label1, P } from '../typography/index.jsx'
const SingleRowTable = ({
width = 378,
@ -25,34 +21,44 @@ const SingleRowTable = ({
onEdit,
className
}) => {
const classes = useStyles({ width, height })
return (
<>
<Table className={classnames(className, classes.table)}>
<Table className={className} style={{ width }}>
<THead>
<Th className={classes.head}>
<Th className="flex flex-1 justify-between items-center pr-3">
{title}
<IconButton onClick={onEdit} className={classes.button} size="large">
<IconButton onClick={onEdit} className="mb-[1px]" size="large">
<EditIcon />
</IconButton>
</Th>
</THead>
<TBody>
<Tr className={classes.tr}>
<Tr className="m-0" style={{ height }}>
<Td width={width}>
{items && (
<>
{items[0] && (
<div className={classes.itemWrapper}>
<div className={classes.label}>{items[0].label}</div>
<div className={classes.item}>{items[0].value}</div>
<div className="flex flex-col mt-4 min-h-9">
<Label1 noMargin className="color-comet mb-1">
{items[0].label}
</Label1>
<P
noMargin
className="overflow-hidden text-ellipsis whitespace-nowrap">
{items[0].value}
</P>
</div>
)}
{items[1] && (
<div className={classes.itemWrapper}>
<div className={classes.label}>{items[1].label}</div>
<div className={classes.item}>{items[1].value}</div>
<div className="flex flex-col mt-4 min-h-9">
<Label1 noMargin className="color-comet mb-1">
{items[1].label}
</Label1>
<P
noMargin
className="overflow-hidden text-ellipsis whitespace-nowrap">
{items[1].value}
</P>
</div>
)}
</>
@ -62,7 +68,7 @@ const SingleRowTable = ({
</TBody>
</Table>
</>
);
)
}
export default SingleRowTable

View file

@ -1,41 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import { offColor } from 'src/styling/variables'
const { label1, p } = typographyStyles
export default {
tr: ({ height }) => ({
margin: 0,
height
}),
table: ({ width }) => ({
width
}),
head: {
display: 'flex',
flex: 1,
justifyContent: 'space-between',
alignItems: 'center',
paddingRight: 12
},
button: {
marginBottom: 1
},
itemWrapper: {
display: 'flex',
flexDirection: 'column',
marginTop: 16,
minHeight: 35
},
label: {
extend: label1,
color: offColor,
marginBottom: 4
},
item: {
extend: p,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
}

View file

@ -1,26 +1,15 @@
import { makeStyles } from '@mui/styles'
import classNames from 'classnames'
import React, { memo } from 'react'
import { H4 } from 'src/components/typography'
import EmptyTableIcon from 'src/styling/icons/table/empty-table.svg?react'
const styles = {
emptyTable: {
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
marginTop: 52
}
}
const useStyles = makeStyles(styles)
const EmptyTable = memo(({ message, className }) => {
const classes = useStyles()
return (
<div className={classNames(className, classes.emptyTable)}>
<div
className={classNames(
className,
'flex flex-col items-center w-full mt-13 text-sm font-bold font-museo'
)}>
<EmptyTableIcon />
<H4>{message}</H4>
</div>

View file

@ -1,20 +1,14 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
const useStyles = makeStyles({
table: {
// backgroundColor: tableHeaderColor,
tableLayout: 'fixed',
borderCollapse: 'separate',
borderSpacing: '0 0'
}
})
const Table = memo(({ className, children, ...props }) => {
const classes = useStyles()
return (
<table {...props} className={classnames(classes.table, className)}>
<table
{...props}
className={classnames(
'table-fixed border-separate border-spacing-0',
className
)}>
{children}
</table>
)

View file

@ -1,24 +1,11 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import { spacer } from 'src/styling/variables'
const useStyles = makeStyles({
td: {
padding: [[0, spacer * 3]]
},
alignRight: {
textAlign: 'right'
}
})
const TableCell = memo(
({ colspan, rightAlign, className, children, ...props }) => {
const classes = useStyles()
const styles = {
[classes.td]: true,
[classes.alignRight]: rightAlign
'py-0 px-6': true,
'text-right': rightAlign
}
return (

View file

@ -30,8 +30,8 @@ const TableHeaderCell = memo(
({ rightAlign, children, className, ...props }) => {
const classes = useStyles()
const styles = {
[classes.th]: true,
[classes.alignRight]: rightAlign
'bg-zodiac text-white py-0 px-6 h-8 font-': true,
'text-right': rightAlign
}
return (

View file

@ -1,54 +1,18 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import typographyStyles from 'src/components/typography/styles'
import {
tableCellColor,
tableCellHeight,
tableSmCellHeight,
tableLgCellHeight,
tableErrorColor,
tableSuccessColor
} from 'src/styling/variables'
const { info2, p } = typographyStyles
const useStyles = makeStyles({
tr: {
extend: p,
padding: 4,
height: tableCellHeight,
backgroundColor: tableCellColor
},
lg: {
extend: info2,
height: tableLgCellHeight
},
sm: {
height: tableSmCellHeight
},
error: {
backgroundColor: tableErrorColor
},
success: {
backgroundColor: tableSuccessColor
}
})
const TableRow = memo(
({ className, children, header, error, success, size = 'sm', ...props }) => {
const classes = useStyles()
const classnamesObj = {
[classes.tr]: !header,
[classes.sm]: !header && size === 'sm',
[classes.lg]: !header && size === 'lg',
[classes.error]: error,
[classes.success]: success
'p-1 h-12 bg-white': !header,
'h-8': !header && size === 'sm',
'h-9 font-bold text-base ': !header && size === 'lg',
'bg-misty-rose': error,
'bg-spring3': success
}
return (
<tr className={classnames(classnamesObj, className)} {...props}>
<tr className={classnames(classnamesObj, className, 'text-')} {...props}>
{children}
</tr>
)

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { useState, useEffect } from 'react'
@ -22,10 +21,6 @@ import ExpandOpenIcon from 'src/styling/icons/action/expand/open.svg?react'
import { EmptyTable } from 'src/components/table'
import styles from './DataTable.styles'
const useStyles = makeStyles(styles)
const Row = ({
id,
index,
@ -41,20 +36,18 @@ const Row = ({
size,
...props
}) => {
const classes = useStyles()
const hasPointer = onClick || expandable
const trClasses = {
[classes.pointer]: hasPointer,
[classes.row]: true,
[classes.expanded]: expanded
'cursor-pointer': hasPointer,
'border-2 border-transparent': true,
'border-2 border-zircon shadow-xl': expanded
}
return (
<div className={classes.rowWrapper}>
<div className="p-[1px]">
<div
data-cy={id}
className={classnames({ [classes.before]: expanded && index !== 0 })}>
className={classnames({ 'pt-3': expanded && index !== 0 })}>
<Tr
size={size}
className={classnames(trClasses)}
@ -74,7 +67,7 @@ const Row = ({
<Td width={expWidth} textAlign="center">
<button
onClick={() => expandRow(id, data)}
className={classes.expandButton}>
className="outline-0 border-0 bg-transparent cursor-pointer p-1">
{expanded && <ExpandOpenIcon />}
{!expanded && <ExpandClosedIcon />}
</button>
@ -83,8 +76,11 @@ const Row = ({
</Tr>
</div>
{expanded && (
<div className={classes.after}>
<Tr className={classnames({ [classes.expanded]: expanded })}>
<div className="pb-3">
<Tr
className={classnames({
'border-2 border-zircon shadow-md': expanded
})}>
<Td width={width}>
<Details it={data} timezone={props.timezone} />
</Td>
@ -118,8 +114,6 @@ const DataTable = ({
const expWidth = maxWidth - coreWidth
const width = coreWidth + (expandable ? expWidth : 0)
const classes = useStyles({ width })
const expandRow = (id, data) => {
if (data.id) {
cache.clear(data.id)
@ -176,7 +170,12 @@ const DataTable = ({
'flex flex-1 flex-col': true,
[className]: !!className
})}>
<Table className={classnames(classes.table, tableClassName)}>
<Table
className={classnames(
'mb-12 min-h-50 flex-1 flex flex-col',
tableClassName
)}
style={{ width }}>
<THead>
{elements.map(({ width, className, textAlign, header }, idx) => (
<Th
@ -189,7 +188,7 @@ const DataTable = ({
))}
{expandable && <Th width={expWidth}></Th>}
</THead>
<TBody className={classes.body}>
<TBody className="flex-auto">
{loading && <H4>Loading...</H4>}
{!loading && R.isEmpty(data) && <EmptyTable message={emptyText} />}
{!loading && !R.isEmpty(data) && (

View file

@ -1,50 +0,0 @@
import { zircon } from 'src/styling/variables'
export default {
expandButton: {
outline: 'none',
border: 'none',
backgroundColor: 'transparent',
cursor: 'pointer',
padding: 4
},
rowWrapper: {
// workaround to shadows cut by r-virtualized when scroll is visible
padding: 1
},
row: {
border: [[2, 'solid', 'transparent']],
borderRadius: 0
},
expanded: {
border: [[2, 'solid', zircon]],
boxShadow: '0 0 8px 0 rgba(0,0,0,0.08)'
},
before: {
paddingTop: 12
},
after: {
paddingBottom: 12
},
pointer: {
cursor: 'pointer'
},
body: {
flex: [[1, 1, 'auto']]
},
table: ({ width }) => ({
marginBottom: 30,
minHeight: 200,
width,
flex: 1,
display: 'flex',
flexDirection: 'column'
}),
emptyTable: {
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
marginTop: 52
}
}

View file

@ -1,11 +0,0 @@
import React from 'react'
import { Td } from 'src/components/fake-table/Table'
import StripesSvg from 'src/styling/icons/stripes.svg?react'
const Stripes = ({ width }) => (
<Td width={width}>
<StripesSvg />
</Td>
)
export default Stripes

View file

@ -164,6 +164,16 @@ theme = createTheme(theme, {
}
}
},
MuiCheckbox: {
styleOverrides: {
root: {
color: secondaryColor,
'&.Mui-checked': {
color: secondaryColor
}
}
}
},
MuiChip: {
styleOverrides: {
root: {