Merge pull request #1837 from RafaelTaranto/chore/update-mui-v6

LAM-1414 chore: update mui to v7
This commit is contained in:
Rafael Taranto 2025-05-12 09:46:25 +01:00 committed by GitHub
commit 8b3f93d8f0
357 changed files with 7823 additions and 14059 deletions

View file

@ -1,4 +0,0 @@
SKIP_PREFLIGHT_CHECK=true
HTTPS=true
REACT_APP_TYPE_CHECK_SANCTUARY=false
PORT=3001

View file

@ -1,28 +0,0 @@
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
location /graphql {
proxy_pass https://lamassu-admin-server/graphql;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

File diff suppressed because it is too large Load diff

View file

@ -5,12 +5,9 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@apollo/client": "^3.13.7", "@apollo/client": "^3.13.7",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@lamassu/coins": "v1.6.1", "@lamassu/coins": "v1.6.1",
"@mui/icons-material": "^5.17.1", "@mui/icons-material": "^7.1.0",
"@mui/material": "^5.17.1", "@mui/material": "^7.1.0",
"@mui/styles": "^5.17.1",
"@simplewebauthn/browser": "^3.0.0", "@simplewebauthn/browser": "^3.0.0",
"apollo-upload-client": "^18.0.0", "apollo-upload-client": "^18.0.0",
"bignumber.js": "9.0.0", "bignumber.js": "9.0.0",
@ -33,7 +30,6 @@
"react-copy-to-clipboard": "^5.0.2", "react-copy-to-clipboard": "^5.0.2",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-dropzone": "^11.4.2", "react-dropzone": "^11.4.2",
"react-material-ui-carousel": "^3.4.2",
"react-number-format": "^4.4.1", "react-number-format": "^4.4.1",
"react-otp-input": "3.1.1", "react-otp-input": "3.1.1",
"react-router-dom": "5.1.2", "react-router-dom": "5.1.2",
@ -44,6 +40,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.16.0", "@eslint/js": "^9.16.0",
"@tailwindcss/vite": "^4.1.4",
"@vitejs/plugin-react-swc": "^3.7.2", "@vitejs/plugin-react-swc": "^3.7.2",
"esbuild-plugin-react-virtualized": "^1.0.4", "esbuild-plugin-react-virtualized": "^1.0.4",
"eslint": "^9.16.0", "eslint": "^9.16.0",
@ -53,6 +50,7 @@
"globals": "^15.13.0", "globals": "^15.13.0",
"lint-staged": "^15.2.10", "lint-staged": "^15.2.10",
"prettier": "3.4.1", "prettier": "3.4.1",
"tailwindcss": "^4.1.4",
"vite": "^6.0.1", "vite": "^6.0.1",
"vite-plugin-svgr": "^4.3.0" "vite-plugin-svgr": "^4.3.0"
}, },

View file

@ -1,12 +0,0 @@
diff --git a/node_modules/react-scripts/config/webpack.config.js b/node_modules/react-scripts/config/webpack.config.js
index 80c6ac2..3420936 100644
--- a/node_modules/react-scripts/config/webpack.config.js
+++ b/node_modules/react-scripts/config/webpack.config.js
@@ -752,6 +752,7 @@ module.exports = function (webpackEnv) {
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
context: paths.appSrc,
+ cache: true,
// ESLint class options
cwd: paths.appPath,
resolvePluginsRelativeTo: __dirname,

View file

@ -1,137 +1,14 @@
import { useQuery, gql } from "@apollo/client";
import CssBaseline from '@mui/material/CssBaseline' import CssBaseline from '@mui/material/CssBaseline'
import Grid from '@mui/material/Grid' import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles'
import Slide from '@mui/material/Slide' import React, { useState } from 'react'
import { StylesProvider, jssPreset, makeStyles } from '@mui/styles'; import { BrowserRouter as Router } from 'react-router-dom'
import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';
import { create } from 'jss'
import extendJss from 'jss-plugin-extend'
import React, { useContext, useState } from 'react'
import {
useLocation,
useHistory,
BrowserRouter as Router
} from 'react-router-dom'
import Header from 'src/components/layout/Header'
import Sidebar from 'src/components/layout/Sidebar'
import TitleSection from 'src/components/layout/TitleSection'
import { tree, hasSidebar, Routes, getParent } from 'src/routing/routes'
import ApolloProvider from 'src/utils/apollo' import ApolloProvider from 'src/utils/apollo'
import AppContext from 'src/AppContext' import AppContext from 'src/AppContext'
import global from 'src/styling/global'
import theme from 'src/styling/theme' import theme from 'src/styling/theme'
import { backgroundColor, mainWidth } from 'src/styling/variables'
const jss = create({ import Main from './Main'
plugins: [extendJss(), ...jssPreset().plugins] import './styling/global/global.css'
})
const fill = '100%'
const flexDirection = 'column'
const useStyles = makeStyles({
...global,
root: {
backgroundColor,
width: fill,
minHeight: fill,
display: 'flex',
flexDirection
},
wrapper: {
width: mainWidth,
height: fill,
margin: '0 auto',
flex: 1,
display: 'flex',
flexDirection
},
grid: {
flex: 1,
height: '100%'
},
contentWithSidebar: {
flex: 1,
marginLeft: 48,
paddingTop: 15
},
contentWithoutSidebar: {
width: mainWidth
}
})
const GET_USER_DATA = gql`
query userData {
userData {
id
username
role
enabled
last_accessed
last_accessed_from
last_accessed_address
}
}
`
const Main = () => {
const classes = useStyles()
const location = useLocation()
const history = useHistory()
const { wizardTested, userData, setUserData } = useContext(AppContext)
const { loading } = useQuery(GET_USER_DATA, {
onCompleted: userResponse => {
if (!userData && userResponse?.userData)
setUserData(userResponse.userData)
}
})
const route = location.pathname
const sidebar = hasSidebar(route)
const parent = sidebar ? getParent(route) : {}
const is404 = location.pathname === '/404'
const isSelected = it => location.pathname === it.route
const onClick = it => history.push(it.route)
const contentClassName = sidebar
? classes.contentWithSidebar
: classes.contentWithoutSidebar
return (
<div className={classes.root}>
{!is404 && wizardTested && userData && (
<Header tree={tree} user={userData} />
)}
<main className={classes.wrapper}>
{sidebar && !is404 && wizardTested && (
<Slide direction="left" in={true} mountOnEnter unmountOnExit>
<div>
<TitleSection title={parent.title}></TitleSection>
</div>
</Slide>
)}
<Grid container className={classes.grid}>
{sidebar && !is404 && wizardTested && (
<Sidebar
data={parent.children}
isSelected={isSelected}
displayName={it => it.label}
onClick={onClick}
/>
)}
<div className={contentClassName}>{!loading && <Routes />}</div>
</Grid>
</main>
</div>
)
}
const App = () => { const App = () => {
const [wizardTested, setWizardTested] = useState(false) const [wizardTested, setWizardTested] = useState(false)
@ -148,18 +25,16 @@ const App = () => {
value={{ wizardTested, setWizardTested, userData, setUserData, setRole }}> value={{ wizardTested, setWizardTested, userData, setUserData, setRole }}>
<Router> <Router>
<ApolloProvider> <ApolloProvider>
<StylesProvider jss={jss}> <StyledEngineProvider enableCssLayer>
<StyledEngineProvider injectFirst> <ThemeProvider theme={theme}>
<ThemeProvider theme={theme}> <CssBaseline />
<CssBaseline /> <Main />
<Main /> </ThemeProvider>
</ThemeProvider> </StyledEngineProvider>
</StyledEngineProvider>
</StylesProvider>
</ApolloProvider> </ApolloProvider>
</Router> </Router>
</AppContext.Provider> </AppContext.Provider>
); )
} }
export default App export default App

View file

@ -0,0 +1,83 @@
import { useHistory, useLocation } from 'react-router-dom'
import React, { useContext } from 'react'
import { gql, useQuery } from '@apollo/client'
import Slide from '@mui/material/Slide'
import Grid from '@mui/material/Grid'
import Header from './components/layout/Header.jsx'
import Sidebar from './components/layout/Sidebar.jsx'
import TitleSection from './components/layout/TitleSection.jsx'
import { getParent, hasSidebar, Routes, tree } from './routing/routes.jsx'
import AppContext from './AppContext.js'
const GET_USER_DATA = gql`
query userData {
userData {
id
username
role
enabled
last_accessed
last_accessed_from
last_accessed_address
}
}
`
const Main = () => {
const location = useLocation()
const history = useHistory()
const { wizardTested, userData, setUserData } = useContext(AppContext)
const { loading } = useQuery(GET_USER_DATA, {
onCompleted: userResponse => {
if (!userData && userResponse?.userData)
setUserData(userResponse.userData)
}
})
const route = location.pathname
const sidebar = hasSidebar(route)
const parent = sidebar ? getParent(route) : {}
const is404 = location.pathname === '/404'
const isSelected = it => location.pathname === it.route
const onClick = it => history.push(it.route)
const contentClassName = sidebar ? 'flex-1 ml-12 pt-4' : 'w-[1200px]'
return (
<div className="flex flex-col w-full min-h-full">
{!is404 && wizardTested && userData && (
<Header tree={tree} user={userData} />
)}
<main className="flex flex-1 flex-col my-0 mx-auto h-full w-[1200px]">
{sidebar && !is404 && wizardTested && (
<Slide direction="left" in={true} mountOnEnter unmountOnExit>
<div>
<TitleSection title={parent.title}></TitleSection>
</div>
</Slide>
)}
<Grid sx={{ flex: 1, height: 1 }} container>
{sidebar && !is404 && wizardTested && (
<Sidebar
data={parent.children}
isSelected={isSelected}
displayName={it => it.label}
onClick={onClick}
/>
)}
<div className={contentClassName}>{!loading && <Routes />}</div>
</Grid>
</main>
</div>
)
}
export default Main

View file

@ -1,63 +1,48 @@
import { makeStyles } from '@mui/styles' import React, { memo, useState } from 'react'
import React, { memo } from 'react' import styles from './Carousel.module.css'
import ReactCarousel from 'react-material-ui-carousel'
import LeftArrow from 'src/styling/icons/arrow/carousel-left-arrow.svg?react' import LeftArrow from 'src/styling/icons/arrow/carousel-left-arrow.svg?react'
import RightArrow from 'src/styling/icons/arrow/carousel-right-arrow.svg?react' import RightArrow from 'src/styling/icons/arrow/carousel-right-arrow.svg?react'
const useStyles = makeStyles({
imgWrapper: {
alignItems: 'center',
justifyContent: 'center',
display: 'flex'
},
imgInner: {
objectFit: 'contain',
objectPosition: 'center',
width: 500,
height: 400,
marginBottom: 40
}
})
export const Carousel = memo(({ photosData, slidePhoto }) => { export const Carousel = memo(({ photosData, slidePhoto }) => {
const classes = useStyles() const [activeIndex, setActiveIndex] = useState(0)
const handlePrev = () => {
const newIndex = activeIndex === 0 ? photosData.length - 1 : activeIndex - 1
setActiveIndex(newIndex)
slidePhoto(newIndex)
}
const handleNext = () => {
const newIndex = activeIndex === photosData.length - 1 ? 0 : activeIndex + 1
setActiveIndex(newIndex)
slidePhoto(newIndex)
}
if (!photosData || photosData.length === 0) {
return null
}
return ( return (
<> <div className={styles.carouselContainer}>
<ReactCarousel {photosData.length > 1 && (
PrevIcon={<LeftArrow />} <button onClick={handlePrev} className={styles.navButton}>
NextIcon={<RightArrow />} <LeftArrow />
navButtonsProps={{ </button>
style: { )}
backgroundColor: 'transparent',
borderRadius: 0, <div className={styles.imageContainer}>
color: 'transparent', <img
opacity: 1 className={styles.image}
} src={`/${photosData[activeIndex]?.photoDir}/${photosData[activeIndex]?.path}`}
}} alt=""
navButtonsWrapperProps={{ />
style: { </div>
marginLeft: -22,
marginRight: -22 {photosData.length > 1 && (
} <button onClick={handleNext} className={styles.navButton}>
}} <RightArrow />
autoPlay={false} </button>
indicators={false} )}
navButtonsAlwaysVisible={true} </div>
next={activeIndex => slidePhoto(activeIndex)}
prev={activeIndex => slidePhoto(activeIndex)}>
{photosData.map((item, i) => (
<div key={i}>
<div className={classes.imgWrapper}>
<img
className={classes.imgInner}
src={`/${item?.photoDir}/${item?.path}`}
alt=""
/>
</div>
</div>
))}
</ReactCarousel>
</>
) )
}) })

View file

@ -0,0 +1,45 @@
.carouselContainer {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.imageContainer {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
overflow: hidden;
max-width: 80%;
}
.image {
object-fit: contain;
object-position: center;
width: 100%;
height: 100%;
margin-bottom: 40px;
}
.navButton {
background-color: transparent;
border: none;
border-radius: 0;
color: transparent;
opacity: 1;
cursor: pointer;
padding: 8px;
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
}
.navButton:hover {
background-color: rgba(0, 0, 0, 0.04);
}

View file

@ -1,34 +0,0 @@
import Chip from '@mui/material/Chip'
import { withStyles } from '@mui/styles'
import React, { memo } from 'react'
import {
fontColor,
inputFontWeight,
subheaderColor,
smallestFontSize,
inputFontFamily
} from 'src/styling/variables'
const styles = theme => ({
root: {
backgroundColor: subheaderColor,
borderRadius: 4,
margin: theme.spacing(0.5, 0.25),
height: 18
},
label: {
fontSize: smallestFontSize,
color: fontColor,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
paddingRight: 4,
paddingLeft: 4
}
})
const LsChip = memo(({ classes, ...props }) => (
<Chip size="small" classes={classes} {...props} />
))
export default withStyles(styles)(LsChip)

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,51 +1,27 @@
import Dialog from '@mui/material/Dialog' import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions' import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent' import DialogContent from '@mui/material/DialogContent'
import IconButton from '@mui/material/IconButton'
import InputLabel from '@mui/material/InputLabel' import InputLabel from '@mui/material/InputLabel'
import { makeStyles } from '@mui/styles'
import React, { memo, useState } from 'react' import React, { memo, useState } from 'react'
import { H4, P } from 'src/components/typography' import { H4, P } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { Button, IconButton } from 'src/components/buttons' import { Button } from 'src/components/buttons'
import { TextInput } from 'src/components/inputs' import { TextInput } from 'src/components/inputs'
import { spacer } from 'src/styling/variables'
import ErrorMessage from './ErrorMessage' import ErrorMessage from './ErrorMessage'
import SvgIcon from '@mui/material/SvgIcon'
const useStyles = makeStyles({
dialogContent: {
width: 434,
padding: spacer * 2,
paddingRight: spacer * 3.5
},
dialogTitle: {
padding: spacer * 2,
paddingRight: spacer * 1.5,
display: 'flex',
'justify-content': 'space-between',
'& > h4': {
margin: 0
},
'& > button': {
padding: 0,
marginTop: -(spacer / 2)
}
},
dialogActions: {
padding: spacer * 4,
paddingTop: spacer * 2
}
})
export const DialogTitle = ({ children, onClose }) => { export const DialogTitle = ({ children, onClose }) => {
const classes = useStyles()
return ( return (
<div className={classes.dialogTitle}> <div className="p-4 pr-3 flex justify-between">
{children} {children}
{onClose && ( {onClose && (
<IconButton size={16} aria-label="close" onClick={onClose}> <IconButton aria-label="close" onClick={onClose} className="p-0 -mt-1">
<CloseIcon /> <SvgIcon fontSize="small">
<CloseIcon />
</SvgIcon>
</IconButton> </IconButton>
)} )}
</div> </div>
@ -67,7 +43,6 @@ export const ConfirmDialog = memo(
disabled = false, disabled = false,
...props ...props
}) => { }) => {
const classes = useStyles()
const [value, setValue] = useState(initialValue) const [value, setValue] = useState(initialValue)
const [error, setError] = useState(false) const [error, setError] = useState(false)
const handleChange = event => setValue(event.target.value) const handleChange = event => setValue(event.target.value)
@ -84,7 +59,7 @@ export const ConfirmDialog = memo(
return ( return (
<Dialog open={open} aria-labelledby="form-dialog-title" {...props}> <Dialog open={open} aria-labelledby="form-dialog-title" {...props}>
<DialogTitle id="customized-dialog-title" onClose={innerOnClose}> <DialogTitle id="customized-dialog-title" onClose={innerOnClose}>
<H4>{title}</H4> <H4 noMargin>{title}</H4>
</DialogTitle> </DialogTitle>
{errorMessage && ( {errorMessage && (
<DialogTitle> <DialogTitle>
@ -98,7 +73,7 @@ export const ConfirmDialog = memo(
</ErrorMessage> </ErrorMessage>
</DialogTitle> </DialogTitle>
)} )}
<DialogContent className={classes.dialogContent}> <DialogContent className="w-108 p-4 pr-7">
{message && <P>{message}</P>} {message && <P>{message}</P>}
<InputLabel htmlFor="confirm-input">{confirmationMessage}</InputLabel> <InputLabel htmlFor="confirm-input">{confirmationMessage}</InputLabel>
<TextInput <TextInput
@ -116,7 +91,7 @@ export const ConfirmDialog = memo(
onChange={handleChange} onChange={handleChange}
/> />
</DialogContent> </DialogContent>
<DialogActions className={classes.dialogActions}> <DialogActions className="p-8 pt-4">
<Button <Button
color="green" color="green"
disabled={isOnErrorState} disabled={isOnErrorState}

View file

@ -1,24 +1,20 @@
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, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { CopyToClipboard as ReactCopyToClipboard } from 'react-copy-to-clipboard' import { CopyToClipboard as ReactCopyToClipboard } from 'react-copy-to-clipboard'
import Popover from 'src/components/Popper' import Popover from 'src/components/Popper.jsx'
import CopyIcon from 'src/styling/icons/action/copy/copy.svg?react' import CopyIcon from 'src/styling/icons/action/copy/copy.svg?react'
import { comet } from 'src/styling/variables' import { comet } from 'src/styling/variables.js'
import { cpcStyles } from './Transactions.styles' import { Label1, Mono } from './typography/index.jsx'
const useStyles = makeStyles(cpcStyles)
const CopyToClipboard = ({ const CopyToClipboard = ({
className, className,
buttonClassname, buttonClassname,
children, children,
wrapperClassname, wrapperClassname,
removeSpace = true, removeSpace = true
...props
}) => { }) => {
const [anchorEl, setAnchorEl] = useState(null) const [anchorEl, setAnchorEl] = useState(null)
@ -26,8 +22,6 @@ const CopyToClipboard = ({
if (anchorEl) setTimeout(() => setAnchorEl(null), 3000) if (anchorEl) setTimeout(() => setAnchorEl(null), 3000)
}, [anchorEl]) }, [anchorEl])
const classes = useStyles()
const handleClick = event => { const handleClick = event => {
setAnchorEl(anchorEl ? null : event.currentTarget) setAnchorEl(anchorEl ? null : event.currentTarget)
} }
@ -40,16 +34,19 @@ const CopyToClipboard = ({
const id = open ? 'simple-popper' : undefined const id = open ? 'simple-popper' : undefined
return ( return (
<div className={classnames(classes.wrapper, wrapperClassname)}> <div className={classnames('flex items-center', wrapperClassname)}>
{children && ( {children && (
<> <>
<div className={classnames(classes.address, className)}> <Mono
noMargin
className={classnames('linebreak-anywhere', className)}>
{children} {children}
</div> </Mono>
<div className={classnames(classes.buttonWrapper, buttonClassname)}> <div className={buttonClassname}>
<ReactCopyToClipboard <ReactCopyToClipboard
text={removeSpace ? R.replace(/\s/g, '')(children) : children}> text={removeSpace ? R.replace(/\s/g, '')(children) : children}>
<button <button
className="border-0 bg-transparent cursor-pointer"
aria-describedby={id} aria-describedby={id}
onClick={event => handleClick(event)}> onClick={event => handleClick(event)}>
<CopyIcon /> <CopyIcon />
@ -61,12 +58,12 @@ const CopyToClipboard = ({
open={open} open={open}
anchorEl={anchorEl} anchorEl={anchorEl}
onClose={handleClose} onClose={handleClose}
arrowSize={3}
bgColor={comet} bgColor={comet}
className="py-1 px-2"
placement="top"> placement="top">
<div className={classes.popoverContent}> <Label1 noMargin className="text-white rounded-sm">
<div>Copied to clipboard!</div> Copied to clipboard!
</div> </Label1>
</Popover> </Popover>
</> </>
)} )}

View file

@ -1,54 +1,25 @@
import Dialog from '@mui/material/Dialog' import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions' import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent' import DialogContent from '@mui/material/DialogContent'
import { makeStyles } from '@mui/styles' import IconButton from '@mui/material/IconButton'
import React from 'react' import React from 'react'
import { H4, P } from 'src/components/typography' import { H4, P } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { Button, IconButton } from 'src/components/buttons' import { Button } from 'src/components/buttons'
import { spacer } from 'src/styling/variables'
import ErrorMessage from './ErrorMessage' import ErrorMessage from './ErrorMessage'
import SvgIcon from '@mui/material/SvgIcon'
const useStyles = makeStyles({
content: {
width: 434,
padding: spacer * 2,
paddingRight: spacer * 3.5
},
titleSection: {
padding: spacer * 2,
paddingRight: spacer * 1.5,
display: 'flex',
justifyContent: 'space-between',
margin: 0
},
actions: {
padding: spacer * 4,
paddingTop: spacer * 2
},
title: {
margin: 0
},
closeButton: {
padding: 0,
marginTop: -(spacer / 2)
}
})
export const DialogTitle = ({ children, close }) => { export const DialogTitle = ({ children, close }) => {
const classes = useStyles()
return ( return (
<div className={classes.titleSection}> <div className="p-4 pr-3 flex justify-between m-0">
{children} {children}
{close && ( {close && (
<IconButton <IconButton aria-label="close" onClick={close} className="p-0 -mt-1">
size={16} <SvgIcon fontSize="small">
aria-label="close" <CloseIcon />
onClick={close} </SvgIcon>
className={classes.closeButton}>
<CloseIcon />
</IconButton> </IconButton>
)} )}
</div> </div>
@ -65,12 +36,10 @@ export const DeleteDialog = ({
extraMessage, extraMessage,
errorMessage = '' errorMessage = ''
}) => { }) => {
const classes = useStyles()
return ( return (
<Dialog open={open} aria-labelledby="form-dialog-title"> <Dialog open={open} aria-labelledby="form-dialog-title">
<DialogTitle close={() => onDismissed()}> <DialogTitle close={() => onDismissed()}>
<H4 className={classes.title}>{title}</H4> <H4 className="m-0">{title}</H4>
</DialogTitle> </DialogTitle>
{errorMessage && ( {errorMessage && (
<DialogTitle> <DialogTitle>
@ -84,11 +53,11 @@ export const DeleteDialog = ({
</ErrorMessage> </ErrorMessage>
</DialogTitle> </DialogTitle>
)} )}
<DialogContent className={classes.content}> <DialogContent className="w-108 p-4 pr-7">
{confirmationMessage && <P>{confirmationMessage}</P>} {confirmationMessage && <P>{confirmationMessage}</P>}
{extraMessage} {extraMessage}
</DialogContent> </DialogContent>
<DialogActions className={classes.actions}> <DialogActions className="p-8 pt-4">
<Button onClick={onConfirmed}>Confirm</Button> <Button onClick={onConfirmed}>Confirm</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>

View file

@ -1,38 +1,16 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React from 'react' import React from 'react'
import ErrorIcon from 'src/styling/icons/warning-icon/tomato.svg?react' import ErrorIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
import { errorColor } from 'src/styling/variables'
import { Info3 } from './typography' import { Info3 } from './typography'
const styles = { const ErrorMessage = ({ className, children }) => {
wrapper: {
display: 'flex',
alignItems: 'center',
'& > svg': {
marginRight: 10
}
},
message: {
display: 'flex',
alignItems: 'center',
color: errorColor,
margin: 0,
whiteSpace: 'break-spaces'
}
}
const useStyles = makeStyles(styles)
const ErrorMessage = ({ className, children, ...props }) => {
const classes = useStyles()
return ( return (
<div className={classnames(classes.wrapper, className)}> <div className={classnames('flex items-center', className)}>
<ErrorIcon /> <ErrorIcon className="mr-3" />
<Info3 className={classes.message}>{children}</Info3> <Info3 className="flex items-center text-tomato m-0 whitespace-break-spaces">
{children}
</Info3>
</div> </div>
) )
} }

View file

@ -1,5 +1,4 @@
import ClickAwayListener from '@mui/material/ClickAwayListener' import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo, useState } from 'react' import React, { memo, useState } from 'react'
import Popper from 'src/components/Popper' import Popper from 'src/components/Popper'
@ -8,18 +7,8 @@ import ZoomIcon from 'src/styling/icons/circle buttons/search/zodiac.svg?react'
import { FeatureButton } from 'src/components/buttons' import { FeatureButton } from 'src/components/buttons'
import imagePopperStyles from './ImagePopper.styles'
const useStyles = makeStyles(imagePopperStyles)
const ImagePopper = memo( const ImagePopper = memo(
({ className, width, height, popupWidth, popupHeight, src }) => { ({ className, width, height, popupWidth, popupHeight, src }) => {
const classes = useStyles({
width,
height,
popupWidth,
popupHeight
})
const [popperAnchorEl, setPopperAnchorEl] = useState(null) const [popperAnchorEl, setPopperAnchorEl] = useState(null)
const handleOpenPopper = event => { const handleOpenPopper = event => {
@ -32,23 +21,30 @@ const ImagePopper = memo(
const popperOpen = Boolean(popperAnchorEl) const popperOpen = Boolean(popperAnchorEl)
const Image = ({ className }) => ( const Image = ({ className, style }) => (
<img className={classnames(className)} src={src} alt="" /> <img className={classnames(className)} style={style} src={src} alt="" />
) )
return ( return (
<ClickAwayListener onClickAway={handleClosePopper}> <ClickAwayListener onClickAway={handleClosePopper}>
<div className={classnames(classes.row, className)}> <div className={classnames('flex flex-row', className)}>
<Image className={classes.image} /> <Image
className="object-cover rounded-tl-lg"
style={{ width, height }}
/>
<FeatureButton <FeatureButton
Icon={ZoomIcon} Icon={ZoomIcon}
InverseIcon={ZoomIconInverse} InverseIcon={ZoomIconInverse}
className={classes.button} className="rounded-none rounded-tr-lg rounded-br-lg"
style={{ height }}
onClick={handleOpenPopper} onClick={handleOpenPopper}
/> />
<Popper open={popperOpen} anchorEl={popperAnchorEl} placement="top"> <Popper open={popperOpen} anchorEl={popperAnchorEl} placement="top">
<div className={classes.popoverContent}> <div className="py-2 px-4">
<Image className={classes.popupImage} /> <Image
className="object-cover"
style={{ width: popupWidth, height: popupHeight }}
/>
</div> </div>
</Popper> </Popper>
</div> </div>

View file

@ -1,25 +0,0 @@
export default {
row: {
display: 'flex',
flexDirection: 'row'
},
image: ({ width, height }) => ({
objectFit: 'cover',
borderRadius: '8px 0px 0px 8px',
width,
height
}),
popupImage: ({ popupWidth, popupHeight }) => ({
objectFit: 'cover',
width: popupWidth,
height: popupHeight
}),
button: ({ height }) => ({
borderRadius: '0px 8px 8px 0px',
height
}),
popoverContent: {
display: 'block',
padding: [[10, 15]]
}
}

View file

@ -1,26 +0,0 @@
import Box from '@mui/material/Box'
import { makeStyles } from '@mui/styles'
import React from 'react'
import { Label1 } from 'src/components/typography'
import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react'
const useStyles = makeStyles({
message: ({ width }) => ({
width,
marginTop: 4,
marginLeft: 16
})
})
const InfoMessage = ({ children, width = 330, className }) => {
const classes = useStyles({ width })
return (
<Box display="flex" className={className}>
<WarningIcon />
<Label1 className={classes.message}>{children}</Label1>
</Box>
)
}
export default InfoMessage

View file

@ -1,43 +1,13 @@
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 { makeStyles } from '@mui/styles' import SvgIcon from '@mui/material/SvgIcon'
import IconButton from '@mui/material/IconButton'
import React, { memo } from 'react' import React, { memo } from 'react'
import { H1 } from 'src/components/typography' import { H1 } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { IconButton } from 'src/components/buttons'
import { spacer } from 'src/styling/variables'
const useStyles = makeStyles({
closeButton: {
display: 'flex',
padding: [[spacer * 2, spacer * 2, 0, spacer * 2]],
paddingRight: spacer * 1.5,
justifyContent: 'end'
},
title: {
margin: [[0, spacer * 2, spacer, spacer * 2 + 4]]
}
})
export const DialogTitle = ({ children, onClose }) => {
const classes = useStyles()
return (
<div className={classes.dialogTitle}>
{children}
{onClose && (
<IconButton size={16} aria-label="close" onClick={onClose}>
<CloseIcon />
</IconButton>
)}
</div>
)
}
export const InformativeDialog = memo( export const InformativeDialog = memo(
({ title = '', open, onDissmised, disabled = false, data, ...props }) => { ({ title = '', open, onDissmised, disabled = false, data, ...props }) => {
const classes = useStyles()
const innerOnClose = () => { const innerOnClose = () => {
onDissmised() onDissmised()
} }
@ -53,13 +23,16 @@ export const InformativeDialog = memo(
open={open} open={open}
aria-labelledby="form-dialog-title" aria-labelledby="form-dialog-title"
{...props}> {...props}>
<div className={classes.closeButton}> <div className="flex justify-end pt-4 pr-3 pb-0 pl-4">
<IconButton size={16} aria-label="close" onClick={innerOnClose}> <IconButton aria-label="close" onClick={innerOnClose}>
<SvgIcon fontSize="small">
<CloseIcon />
</SvgIcon>
<CloseIcon /> <CloseIcon />
</IconButton> </IconButton>
</div> </div>
<H1 className={classes.title}>{title}</H1> <H1 className="mt-0 mr-4 mb-2 ml-5">{title}</H1>
<DialogContent className={classes.dialogContent}>{data}</DialogContent> <DialogContent>{data}</DialogContent>
</Dialog> </Dialog>
) )
} }

View file

@ -1,6 +1,5 @@
import { useLazyQuery } from "@apollo/client"; import { useLazyQuery } from '@apollo/client'
import ClickAwayListener from '@mui/material/ClickAwayListener' import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import { format, set } from 'date-fns/fp' import { format, set } from 'date-fns/fp'
import FileSaver from 'file-saver' import FileSaver from 'file-saver'
@ -11,68 +10,32 @@ import DownloadInverseIcon from 'src/styling/icons/button/download/white.svg?rea
import Download from 'src/styling/icons/button/download/zodiac.svg?react' import Download from 'src/styling/icons/button/download/zodiac.svg?react'
import { FeatureButton, Link } from 'src/components/buttons' import { FeatureButton, Link } from 'src/components/buttons'
import { primaryColor, offColor, zircon } from 'src/styling/variables'
import { formatDate } from 'src/utils/timezones' import { formatDate } from 'src/utils/timezones'
import Popper from './Popper' import Popper from './Popper'
import DateRangePicker from './date-range-picker/DateRangePicker' import DateRangePicker from './date-range-picker/DateRangePicker'
import { RadioGroup } from './inputs' import { RadioGroup } from './inputs'
import typographyStyles from './typography/styles' import typographyStyles from './typography/styles'
import { H4, Info1, Label1, Label2 } from './typography/index.jsx'
const { info1, label1, label2, h4 } = typographyStyles const DateContainer = ({ date, children }) => {
const dateContainerStyles = {
wrapper: {
height: 46,
width: 99
},
container: {
display: 'flex'
},
monthWeekDayContainer: {
display: 'flex',
flexDirection: 'column'
},
label: {
extend: label1,
lineHeight: 1.33,
color: primaryColor
},
bigNumber: {
extend: info1,
lineHeight: 1,
marginRight: 7
},
monthYear: {
extend: label2,
lineHeight: 1.17,
color: primaryColor
},
weekDay: {
extend: label1,
lineHeight: 1.33,
color: offColor
}
}
const dateContainerUseStyles = makeStyles(dateContainerStyles)
const DateContainer = ({ date, children, ...props }) => {
const classes = dateContainerUseStyles()
return ( return (
<div className={classes.wrapper}> <div className="h-11 w-25">
<div className={classes.label}>{children}</div> <Label1 noMargin>{children}</Label1>
{date && ( {date && (
<> <>
<div className={classes.container}> <div className="flex">
<div className={classes.bigNumber}>{format('d', date)}</div> <Info1 noMargin className="mr-2">
<div className={classes.monthWeekDayContainer}> {format('d', date)}
<span className={classes.monthYear}>{`${format( </Info1>
<div className="flex flex-col">
<Label2 noMargin>{`${format(
'MMM', 'MMM',
date date
)} ${format('yyyy', date)}`}</span> )} ${format('yyyy', date)}`}</Label2>
<span className={classes.weekDay}>{format('EEEE', date)}</span> <Label1 noMargin className="text-comet">
{format('EEEE', date)}
</Label1>
</div> </div>
</div> </div>
</> </>
@ -81,54 +44,6 @@ const DateContainer = ({ date, children, ...props }) => {
) )
} }
const styles = {
popoverContent: {
width: 280
},
popoverHeader: {
extend: h4,
padding: [[15, 15, 0, 15]]
},
radioButtonsContainer: {
padding: [[5, 15, 5, 15]]
},
radioButtons: {
display: 'flex',
justifyContent: 'space-between',
flexDirection: 'row',
color: primaryColor
},
dateRangePickerShowing: {
display: 'block',
height: '100%'
},
dateRangePickerHidden: {
display: 'none',
height: 0
},
download: {
padding: [[10, 15]]
},
dateContainerWrapper: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
position: 'relative',
backgroundColor: zircon,
padding: [[0, 15]],
minHeight: 70
},
arrowContainer: {
position: 'absolute',
left: 125,
top: 26
},
arrow: {
margin: 'auto'
}
}
const useStyles = makeStyles(styles)
const ALL = 'all' const ALL = 'all'
const RANGE = 'range' const RANGE = 'range'
const ADVANCED = 'advanced' const ADVANCED = 'advanced'
@ -153,11 +68,9 @@ const LogsDownloaderPopover = ({
onCompleted: data => createLogsFile(getLogs(data), range) onCompleted: data => createLogsFile(getLogs(data), range)
}) })
const classes = useStyles()
const dateRangePickerClasses = { const dateRangePickerClasses = {
[classes.dateRangePickerShowing]: selectedRadio === RANGE, 'block h-full': selectedRadio === RANGE,
[classes.dateRangePickerHidden]: selectedRadio === ALL hidden: selectedRadio === ALL
} }
const handleRadioButtons = evt => { const handleRadioButtons = evt => {
@ -255,26 +168,28 @@ const LogsDownloaderPopover = ({
variant="contained" variant="contained"
/> />
<Popper id={id} open={open} anchorEl={anchorEl} placement="bottom"> <Popper id={id} open={open} anchorEl={anchorEl} placement="bottom">
<div className={classes.popoverContent}> <div className="w-70">
<div className={classes.popoverHeader}>{title}</div> <H4 noMargin className="p-4 pb-0">
<div className={classes.radioButtonsContainer}> {title}
</H4>
<div className="py-1 px-4">
<RadioGroup <RadioGroup
name="logs-select" name="logs-select"
value={selectedRadio} value={selectedRadio}
options={radioButtonOptions} options={radioButtonOptions}
ariaLabel="logs-select" ariaLabel="logs-select"
onChange={handleRadioButtons} onChange={handleRadioButtons}
className={classes.radioButtons} className="flex flex-row justify-between text-zodiac"
/> />
</div> </div>
{selectedRadio === RANGE && ( {selectedRadio === RANGE && (
<div className={classnames(dateRangePickerClasses)}> <div className={classnames(dateRangePickerClasses)}>
<div className={classes.dateContainerWrapper}> <div className="flex justify-between items-center py-0 px-4 bg-zircon relative min-h-20">
{range && ( {range && (
<> <>
<DateContainer date={range.from}>From</DateContainer> <DateContainer date={range.from}>From</DateContainer>
<div className={classes.arrowContainer}> <div className="absolute left-31 top-6">
<Arrow className={classes.arrow} /> <Arrow className="m-auto" />
</div> </div>
<DateContainer date={range.until}>To</DateContainer> <DateContainer date={range.until}>To</DateContainer>
</> </>
@ -295,18 +210,18 @@ const LogsDownloaderPopover = ({
</div> </div>
)} )}
{simplified && ( {simplified && (
<div className={classes.radioButtonsContainer}> <div className="py-1 px-4">
<RadioGroup <RadioGroup
name="simplified-tx-logs" name="simplified-tx-logs"
value={selectedAdvancedRadio} value={selectedAdvancedRadio}
options={advancedRadioButtonOptions} options={advancedRadioButtonOptions}
ariaLabel="simplified-tx-logs" ariaLabel="simplified-tx-logs"
onChange={handleAdvancedRadioButtons} onChange={handleAdvancedRadioButtons}
className={classes.radioButtons} className="flex flex-row justify-between text-zodiac"
/> />
</div> </div>
)} )}
<div className={classes.download}> <div className="py-3 px-4">
<Link color="primary" onClick={() => downloadLogs(range, args)}> <Link color="primary" onClick={() => downloadLogs(range, args)}>
Download Download
</Link> </Link>

View file

@ -1,75 +1,12 @@
import MaterialModal from '@mui/material/Modal' import MaterialModal from '@mui/material/Modal'
import IconButton from '@mui/material/IconButton'
import SvgIcon from '@mui/material/SvgIcon'
import Paper from '@mui/material/Paper' import Paper from '@mui/material/Paper'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React from 'react' import React from 'react'
import { H1, H4 } from 'src/components/typography' import { H1, H4 } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import { IconButton } from 'src/components/buttons'
const styles = {
modal: {
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
alignItems: 'center'
},
wrapper: ({ width, height }) => ({
width,
height,
display: 'flex',
flexDirection: 'column',
minHeight: height ?? 400,
maxHeight: '90vh',
overflowY: 'auto',
borderRadius: 8,
outline: 0
}),
infoPanelWrapper: ({ width, infoPanelHeight }) => ({
width,
height: infoPanelHeight,
marginTop: 16,
display: 'flex',
flexDirection: 'column',
minHeight: infoPanelHeight ?? 200,
maxHeight: '90vh',
overflowY: 'auto',
borderRadius: 8,
outline: 0
}),
panelContent: {
width: '100%',
display: 'flex',
flexDirection: 'column',
flex: 1,
padding: [[0, 24]]
},
content: ({ small, xl }) => ({
width: '100%',
display: 'flex',
flexDirection: 'column',
flex: 1,
padding: xl ? [[0, 60 + 28]] : small ? [[0, 16]] : [[0, 32]]
}),
button: ({ small, xl }) => ({
padding: [[0, 0, xl ? 26 : 0, 0]],
margin: xl
? [[0, 0, 'auto', 'auto']]
: small
? [[12, 12, 'auto', 'auto']]
: [[16, 16, 'auto', 'auto']]
}),
header: {
display: 'flex'
},
title: ({ small }) => ({
margin: small ? [[20, 0, 8, 16]] : [[28, 0, 8, 32]]
})
}
const useStyles = makeStyles(styles)
const Modal = ({ const Modal = ({
width, width,
height, height,
@ -86,7 +23,6 @@ const Modal = ({
closeOnBackdropClick, closeOnBackdropClick,
...props ...props
}) => { }) => {
const classes = useStyles({ width, height, small, infoPanelHeight, xl })
const TitleCase = small ? H4 : H1 const TitleCase = small ? H4 : H1
const closeSize = xl ? 28 : small ? 16 : 20 const closeSize = xl ? 28 : small ? 16 : 20
@ -96,24 +32,61 @@ const Modal = ({
handleClose() handleClose()
} }
const marginBySize = xl ? 0 : small ? 12 : 16
const paddingBySize = xl ? 88 : small ? 16 : 32
return ( return (
<MaterialModal onClose={innerClose} className={classes.modal} {...props}> <MaterialModal
onClose={innerClose}
className="flex justify-center flex-col items-center"
{...props}>
<> <>
<Paper className={classnames(classes.wrapper, className)}> <Paper
<div className={classes.header}> style={{ width, height, minHeight: height ?? 400 }}
{title && <TitleCase className={classes.title}>{title}</TitleCase>} className={classnames(
<IconButton 'flex flex-col max-h-[90vh] rounded-lg outline-0',
size={closeSize} className
className={classes.button} )}>
onClick={() => handleClose()}> <div className="flex">
<CloseIcon /> {title && (
</IconButton> <TitleCase
className={
small ? 'mt-5 mr-0 mb-2 ml-4' : 'mt-7 mr-0 mb-2 ml-8'
}>
{title}
</TitleCase>
)}
<div
className="ml-auto"
style={{ marginRight: marginBySize, marginTop: marginBySize }}>
<IconButton
className="p-0 mb-auto ml-auto"
onClick={() => handleClose()}>
<SvgIcon fontSize={xl ? 'large' : 'small'}>
<CloseIcon />
</SvgIcon>
</IconButton>
</div>
</div>
<div
className="w-full flex flex-col flex-1"
style={{ paddingRight: paddingBySize, paddingLeft: paddingBySize }}>
{children}
</div> </div>
<div className={classes.content}>{children}</div>
</Paper> </Paper>
{infoPanel && ( {infoPanel && (
<Paper className={classnames(classes.infoPanelWrapper, className)}> <Paper
<div className={classes.panelContent}>{infoPanel}</div> style={{
width,
height: infoPanelHeight,
minHeight: infoPanelHeight ?? 200
}}
className={classnames(
'mt-4 flex flex-col max-h-[90vh] overflow-y-auto rounded-lg outline-0',
className
)}>
<div className="w-full flex flex-col flex-1 py-0 px-6">
{infoPanel}
</div>
</Paper> </Paper>
)} )}
</> </>

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, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import ActionButton from 'src/components/buttons/ActionButton' 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 ClearAllIcon from 'src/styling/icons/stage/zodiac/empty.svg?react'
import ShowUnreadIcon from 'src/styling/icons/stage/zodiac/full.svg?react' import ShowUnreadIcon from 'src/styling/icons/stage/zodiac/full.svg?react'
import styles from './NotificationCenter.styles'
import NotificationRow from './NotificationRow' import NotificationRow from './NotificationRow'
import classes from './NotificationCenter.module.css'
const useStyles = makeStyles(styles)
const GET_NOTIFICATIONS = gql` const GET_NOTIFICATIONS = gql`
query getNotifications { query getNotifications {
@ -63,7 +60,6 @@ const NotificationCenter = ({
const [xOffset, setXoffset] = useState(300) const [xOffset, setXoffset] = useState(300)
const [showingUnread, setShowingUnread] = useState(false) const [showingUnread, setShowingUnread] = useState(false)
const classes = useStyles({ buttonCoords, xOffset })
const machines = R.compose( const machines = R.compose(
R.map(R.prop('name')), R.map(R.prop('name')),
R.indexBy(R.prop('deviceId')) R.indexBy(R.prop('deviceId'))
@ -120,7 +116,13 @@ const NotificationCenter = ({
<div className={classes.container}> <div className={classes.container}>
<div className={classes.header}> <div className={classes.header}>
<H5 className={classes.headerText}>Notifications</H5> <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 /> <NotificationIconZodiac />
{hasUnread && <div className={classes.hasUnread} />} {hasUnread && <div className={classes.hasUnread} />}
</button> </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,143 +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: 2,
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 classnames from 'classnames'
import prettyMs from 'pretty-ms' import prettyMs from 'pretty-ms'
import * as R from 'ramda' 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 Transaction from 'src/styling/icons/arrow/transaction.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 './NotificationCenter.styles' import classes from './NotificationCenter.module.css'
const useStyles = makeStyles(styles)
const types = { const types = {
transaction: { transaction: {
@ -46,8 +44,6 @@ const NotificationRow = ({
valid, valid,
toggleClear toggleClear
}) => { }) => {
const classes = useStyles()
const typeDisplay = R.path([type, 'display'])(types) ?? null const typeDisplay = R.path([type, 'display'])(types) ?? null
const icon = R.path([type, 'icon'])(types) ?? ( const icon = R.path([type, 'icon'])(types) ?? (
<Wrench height={16} width={16} /> <Wrench height={16} width={16} />

View file

@ -1,120 +1,15 @@
import MaterialPopper from '@mui/material/Popper' import MaterialPopper from '@mui/material/Popper'
import Paper from '@mui/material/Paper' import Paper from '@mui/material/Paper'
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 { white } from 'src/styling/variables' import { white } from 'src/styling/variables'
import classes from './Popper.module.css'
const Popover = ({ const Popover = ({ children, bgColor = white, className, ...props }) => {
children,
bgColor = white,
arrowSize = 6,
className,
...props
}) => {
const [arrowRef, setArrowRef] = useState(null) const [arrowRef, setArrowRef] = useState(null)
const styles = {
popover: {
zIndex: 3000,
backgroundColor: bgColor,
borderRadius: 4
},
arrow: {
position: 'absolute',
fontSize: arrowSize,
width: '3em',
height: '3em'
},
arrowBottom: {
top: 0,
width: 0,
height: 0,
borderLeft: [['2em', 'solid', 'transparent']],
borderRight: [['2em', 'solid', 'transparent']],
borderBottom: [['2em', 'solid', bgColor]],
marginTop: '-1.9em',
'&:after': {
zIndex: -10,
content: '""',
position: 'absolute',
width: arrowSize * 3,
height: arrowSize * 3,
marginLeft: 0,
bottom: 0,
top: 'calc(50% - 0px)',
left: 0,
border: '5px solid #fff',
borderColor: 'transparent transparent #fff #fff',
transformOrigin: '0 0',
transform: 'rotate(45deg)',
boxShadow:
'0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)'
}
},
arrowTop: {
bottom: 0,
width: 0,
height: 0,
borderLeft: [['2em', 'solid', 'transparent']],
borderRight: [['2em', 'solid', 'transparent']],
borderTop: [['2em', 'solid', bgColor]],
marginBottom: '-1.9em',
'&:after': {
zIndex: -10,
content: '""',
position: 'absolute',
width: arrowSize * 3,
height: arrowSize * 3,
marginLeft: 0,
bottom: 0,
top: -(arrowSize * 4 + 2),
left: 0,
border: '5px solid #fff',
borderColor: 'transparent transparent #fff #fff',
transformOrigin: '0 0',
transform: 'rotate(45deg)',
boxShadow:
'0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)'
}
},
arrowRight: {
left: 0,
width: 0,
height: 0,
borderTop: [['2em', 'solid', 'transparent']],
borderBottom: [['2em', 'solid', 'transparent']],
borderRight: [['2em', 'solid', bgColor]],
marginLeft: '-1.9em'
},
arrowLeft: {
right: 0,
width: 0,
height: 0,
borderTop: [['2em', 'solid', 'transparent']],
borderBottom: [['2em', 'solid', 'transparent']],
borderLeft: [['2em', 'solid', bgColor]],
marginRight: '-1.9em'
},
root: {
backgroundColor: bgColor
}
}
const useStyles = makeStyles(styles)
const classes = useStyles()
const getArrowClasses = placement => ({
[classes.arrow]: true,
[classes.arrowBottom]: placement === 'bottom',
[classes.arrowTop]: placement === 'top',
[classes.arrowRight]: placement === 'right',
[classes.arrowLeft]: placement === 'left'
})
const flipPlacements = { const flipPlacements = {
top: ['bottom'], top: ['bottom'],
bottom: ['top'], bottom: ['top'],
@ -164,17 +59,16 @@ const Popover = ({
<MaterialPopper <MaterialPopper
disablePortal={false} disablePortal={false}
modifiers={modifiers} modifiers={modifiers}
className={classes.popover} className={classnames(classes.tooltip, 'z-3000 rounded-sm')}
{...props}> {...props}>
{({ placement }) => ( <Paper style={{ backgroundColor: bgColor }} className={className}>
<Paper className={classnames(classes.root, className)}> <span
<span className={classes.newArrow}
className={classnames(getArrowClasses(placement))} data-popper-arrow
ref={setArrowRef} ref={setArrowRef}
/> />
{children} {children}
</Paper> </Paper>
)}
</MaterialPopper> </MaterialPopper>
</> </>
) )

View file

@ -0,0 +1,33 @@
.newArrow,
.newArrow::before {
position: absolute;
width: 8px;
height: 8px;
background: inherit;
}
.newArrow {
visibility: hidden;
}
.newArrow::before {
visibility: visible;
content: '';
transform: rotate(45deg);
}
.tooltip[data-popper-placement^='top'] > div > span {
bottom: -4px;
}
.tooltip[data-popper-placement^='bottom'] > div > span {
top: -4px;
}
.tooltip[data-popper-placement^='left'] > div > span {
right: -4px;
}
.tooltip[data-popper-placement^='right'] > div > span {
left: -4px;
}

View file

@ -1,16 +1,11 @@
import InputBase from '@mui/material/InputBase' import InputBase from '@mui/material/InputBase'
import Paper from '@mui/material/Paper' import Paper from '@mui/material/Paper'
import { makeStyles } from '@mui/styles'
import MAutocomplete from '@mui/material/Autocomplete' import MAutocomplete from '@mui/material/Autocomplete'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo, useState } from 'react' import React, { memo, useState } from 'react'
import { P } from 'src/components/typography' import { P } from 'src/components/typography'
import SearchIcon from 'src/styling/icons/circle buttons/search/zodiac.svg?react' import SearchIcon from 'src/styling/icons/circle buttons/search/zodiac.svg?react'
import styles from './SearchBox.styles'
const useStyles = makeStyles(styles)
const SearchBox = memo( const SearchBox = memo(
({ ({
loading = false, loading = false,
@ -21,13 +16,11 @@ const SearchBox = memo(
onChange, onChange,
...props ...props
}) => { }) => {
const classes = useStyles({ size })
const [popupOpen, setPopupOpen] = useState(false) const [popupOpen, setPopupOpen] = useState(false)
const inputClasses = { const inputClasses = {
[classes.input]: true, 'flex flex-1 h-8 px-2 py-2 font-md items-center rounded-2xl bg-zircon text-comet': true,
[classes.inputWithPopup]: popupOpen 'rounded-b-none': popupOpen
} }
const innerOnChange = filters => onChange(filters) const innerOnChange = filters => onChange(filters)
@ -35,15 +28,16 @@ const SearchBox = memo(
return ( return (
<MAutocomplete <MAutocomplete
loading={loading} loading={loading}
classes={{ option: classes.autocomplete }}
value={filters} value={filters}
options={options} options={options}
getOptionLabel={it => it.label || it.value} getOptionLabel={it => it.label || it.value}
renderOption={(props, it) => ( renderOption={(props, it) => (
<li {...props}> <li {...props}>
<div className={classes.item}> <div className="flex flex-row w-full h-8">
<P className={classes.itemLabel}>{it.label || it.value}</P> <P className="m-0 whitespace-nowrap overflow-hidden text-ellipsis">
<P className={classes.itemType}>{it.type}</P> {it.label || it.value}
</P>
<P className="m-0 ml-auto text-sm text-come">{it.type}</P>
</div> </div>
</li> </li>
)} )}
@ -53,25 +47,16 @@ const SearchBox = memo(
multiple multiple
filterSelectedOptions filterSelectedOptions
isOptionEqualToValue={(option, value) => option.type === value.type} isOptionEqualToValue={(option, value) => option.type === value.type}
PaperComponent={({ children }) => (
<Paper elevation={0} className={classes.popup}>
<div className={classes.separator} />
{children}
</Paper>
)}
renderInput={params => { renderInput={params => {
return ( return (
<InputBase <InputBase
ref={params.InputProps.ref} ref={params.InputProps.ref}
{...params} {...params}
className={classnames(inputClasses)} className={classnames(inputClasses)}
startAdornment={<SearchIcon className={classes.iconButton} />} startAdornment={<SearchIcon className="mr-3" />}
placeholder={inputPlaceholder} placeholder={inputPlaceholder}
inputProps={{ inputProps={{
className: classes.bold, className: 'font-bold',
classes: {
root: classes.size
},
...params.inputProps ...params.inputProps
}} }}
/> />
@ -81,8 +66,17 @@ const SearchBox = memo(
onClose={() => setPopupOpen(false)} onClose={() => setPopupOpen(false)}
onChange={(_, filters) => innerOnChange(filters)} onChange={(_, filters) => innerOnChange(filters)}
{...props} {...props}
/> slots={{
) paper: ({ children }) => (
<Paper
elevation={0}
className="flex flex-col rounded-b-xl bg-zircon shadow-2xl">
<div className="w-[88%] h-[1px] my-p mx-auto border-1 border-comet" />
{children}
</Paper>
)
}} />
);
} }
) )

View file

@ -1,78 +0,0 @@
import baseButtonStyles from 'src/components/buttons/BaseButton.styles'
import { bySize, bold } from 'src/styling/helpers'
import { zircon, comet, primaryColor } from 'src/styling/variables'
const { baseButton } = baseButtonStyles
const searchBoxBorderRadius = baseButton.height / 2
const searchBoxHeight = 32
const popupBorderRadiusFocus = baseButton.height / 4
const hoverColor = 'rgba(0, 0, 0, 0.08)'
const boxShadow = `0 4px 4px 0 ${hoverColor}`
const styles = {
size: ({ size }) => ({
marginTop: size === 'lg' ? 0 : 2,
...bySize(size)
}),
bold,
autocomplete: {
'&[data-focus="true"]': {
backgroundColor: hoverColor
}
},
popup: {
display: 'flex',
flexDirection: 'column',
borderRadius: [[0, 0, popupBorderRadiusFocus, popupBorderRadiusFocus]],
backgroundColor: zircon,
boxShadow
},
separator: {
width: '88%',
height: 1,
margin: '0 auto',
border: 'solid 0.5px',
borderColor: comet
},
item: {
display: 'flex',
flexDirection: 'row',
width: '100%',
height: 36,
alignItems: 'center'
},
itemLabel: {
margin: [0],
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
},
itemType: {
marginLeft: 'auto',
fontSize: 12,
color: comet,
margin: [0]
},
input: {
display: 'flex',
flex: 1,
width: 273,
padding: [[8, 12]],
alignItems: 'center',
height: searchBoxHeight,
borderRadius: searchBoxBorderRadius,
backgroundColor: zircon,
color: primaryColor
},
inputWithPopup: {
borderRadius: [[popupBorderRadiusFocus, popupBorderRadiusFocus, 0, 0]],
boxShadow
},
iconButton: {
marginRight: 12
}
}
export default styles

View file

@ -1,6 +1,5 @@
import { makeStyles } from '@mui/styles' import Chip from '@mui/material/Chip'
import React from 'react' import React from 'react'
import Chip from 'src/components/Chip'
import { P, Label3 } from 'src/components/typography' import { P, Label3 } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
import FilterIcon from 'src/styling/icons/button/filter/white.svg?react' import FilterIcon from 'src/styling/icons/button/filter/white.svg?react'
@ -9,48 +8,39 @@ import ReverseFilterIcon from 'src/styling/icons/button/filter/zodiac.svg?react'
import { ActionButton } from 'src/components/buttons' import { ActionButton } from 'src/components/buttons'
import { onlyFirstToUpper, singularOrPlural } from 'src/utils/string' import { onlyFirstToUpper, singularOrPlural } from 'src/utils/string'
import { chipStyles, styles } from './SearchFilter.styles'
const useChipStyles = makeStyles(chipStyles)
const useStyles = makeStyles(styles)
const SearchFilter = ({ const SearchFilter = ({
filters, filters,
onFilterDelete, onFilterDelete,
deleteAllFilters, deleteAllFilters,
entries = 0 entries = 0
}) => { }) => {
const chipClasses = useChipStyles()
const classes = useStyles()
return ( return (
<> <>
<P className={classes.text}>{'Filters:'}</P> <P className="mx-0">{'Filters:'}</P>
<div className={classes.filters}> <div className="flex mb-4">
<div className={classes.chips}> <div className="mt-auto">
{filters.map((f, idx) => ( {filters.map((f, idx) => (
<Chip <Chip
key={idx} key={idx}
classes={chipClasses}
label={`${onlyFirstToUpper(f.type)}: ${f.label || f.value}`} label={`${onlyFirstToUpper(f.type)}: ${f.label || f.value}`}
onDelete={() => onFilterDelete(f)} onDelete={() => onFilterDelete(f)}
deleteIcon={<CloseIcon className={classes.button} />} deleteIcon={<CloseIcon className="w-2 h-2 mx-2" />}
/> />
))} ))}
</div> </div>
<div className={classes.deleteWrapper}> <div className="flex ml-auto justify-end flex-row">
{ {
<Label3 className={classes.entries}>{`${entries} ${singularOrPlural( <Label3 className="text-comet m-auto mr-3">{`${entries} ${singularOrPlural(
entries, entries,
`entry`, `entry`,
`entries` `entries`
)}`}</Label3> )}`}</Label3>
} }
<ActionButton <ActionButton
altTextColor
color="secondary" color="secondary"
Icon={ReverseFilterIcon} Icon={ReverseFilterIcon}
InverseIcon={FilterIcon} InverseIcon={FilterIcon}
className={classes.deleteButton}
onClick={deleteAllFilters}> onClick={deleteAllFilters}>
Delete filters Delete filters
</ActionButton> </ActionButton>

View file

@ -1,62 +0,0 @@
import {
primaryColor,
zircon,
smallestFontSize,
inputFontFamily,
inputFontWeight,
spacer,
offColor
} from 'src/styling/variables'
const chipStyles = {
root: {
marginLeft: 0,
height: 20,
backgroundColor: zircon,
'&:hover, &:focus, &:active': {
backgroundColor: zircon
},
marginBottom: 'auto'
},
label: {
fontSize: smallestFontSize,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
paddingRight: 0,
paddingLeft: spacer,
color: primaryColor
}
}
const styles = {
button: {
width: 8,
height: 8,
marginLeft: 8,
marginRight: 8
},
text: {
marginTop: 0,
marginBottom: 0
},
filters: {
display: 'flex',
marginBottom: 16
},
deleteWrapper: {
display: 'flex',
marginLeft: 'auto',
justifyContent: 'flex-end',
flexDirection: 'row'
},
entries: {
color: offColor,
margin: 'auto',
marginRight: 12
},
chips: {
marginTop: 'auto'
}
}
export { chipStyles, styles }

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,59 +1,8 @@
import Chip from '@mui/material/Chip' import Chip from '@mui/material/Chip'
import { makeStyles } from '@mui/styles'
import React from 'react' import React from 'react'
import {
tomato,
mistyRose,
pumpkin,
secondaryColorDarker as spring4,
inputFontWeight,
spring3,
zircon,
primaryColor,
smallestFontSize,
inputFontFamily,
spacer,
linen
} from '../styling/variables'
const colors = {
error: tomato,
warning: pumpkin,
success: spring4,
neutral: primaryColor
}
const backgroundColors = {
error: mistyRose,
warning: linen,
success: spring3,
neutral: zircon
}
const useStyles = makeStyles({
root: {
borderRadius: spacer / 2,
marginTop: spacer / 2,
marginRight: spacer / 4,
marginBottom: spacer / 2,
marginLeft: spacer / 4,
height: spacer * 3,
backgroundColor: ({ type }) => backgroundColors[type]
},
label: {
fontSize: smallestFontSize,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
paddingRight: spacer / 2,
paddingLeft: spacer / 2,
color: ({ type }) => colors[type]
}
})
const Status = ({ status }) => { const Status = ({ status }) => {
const classes = useStyles({ type: status.type }) return <Chip color={status.type} label={status.label} />
return <Chip type={status.type} label={status.label} classes={classes} />
} }
const MainStatus = ({ statuses }) => { const MainStatus = ({ statuses }) => {

View file

@ -1,4 +1,3 @@
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, { memo } from 'react' import React, { memo } from 'react'
@ -9,79 +8,29 @@ import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg
import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.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 EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react'
import { import classes from './Stepper.module.css'
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 Stepper = memo(({ steps, currentStep, color = 'spring', className }) => { const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => {
if (currentStep < 1 || currentStep > steps) if (currentStep < 1 || currentStep > steps)
throw Error('Value of currentStage is invalid') throw Error('Value of currentStage is invalid')
if (steps < 1) throw Error('Value of stages is invalid') if (steps < 1) throw Error('Value of stages is invalid')
const classes = useStyles()
const separatorClasses = { const separatorClasses = {
[classes.separator]: true, 'w-7 h-[2px] border-2 z-1': true,
[classes.separatorSpring]: color === 'spring', 'border-spring': color === 'spring',
[classes.separatorZodiac]: color === 'zodiac' 'border-zodiac': color === 'zodiac'
} }
const separatorEmptyClasses = { const separatorEmptyClasses = {
[classes.separator]: true, 'w-7 h-[2px] border-2 z-1': true,
[classes.separatorSpringEmpty]: color === 'spring', 'border-dust': color === 'spring',
[classes.separatorZodiacEmpty]: color === 'zodiac' 'border-comet': color === 'zodiac'
} }
return ( return (
<div className={classnames(className, classes.stages)}> <div className={classnames(className, 'flex items-center')}>
{R.range(1, currentStep).map(idx => ( {R.range(1, currentStep).map(idx => (
<div key={idx} className={classes.wrapper}> <div key={idx} className="flex items-center m-0">
{idx > 1 && <div className={classnames(separatorClasses)} />} {idx > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}> <div className={classes.stage}>
{color === 'spring' && <CompleteStageIconSpring />} {color === 'spring' && <CompleteStageIconSpring />}
@ -89,7 +38,7 @@ const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => {
</div> </div>
</div> </div>
))} ))}
<div className={classes.wrapper}> <div className="flex items-center m-0">
{currentStep > 1 && <div className={classnames(separatorClasses)} />} {currentStep > 1 && <div className={classnames(separatorClasses)} />}
<div className={classes.stage}> <div className={classes.stage}>
{color === 'spring' && <CurrentStageIconSpring />} {color === 'spring' && <CurrentStageIconSpring />}
@ -97,7 +46,7 @@ const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => {
</div> </div>
</div> </div>
{R.range(currentStep + 1, steps + 1).map(idx => ( {R.range(currentStep + 1, steps + 1).map(idx => (
<div key={idx} className={classes.wrapper}> <div key={idx} className="flex items-center m-0">
<div className={classnames(separatorEmptyClasses)} /> <div className={classnames(separatorEmptyClasses)} />
<div className={classes.stage}> <div className={classes.stage}>
{color === 'spring' && <EmptyStageIconSpring />} {color === 'spring' && <EmptyStageIconSpring />}

View file

@ -0,0 +1,12 @@
.stage {
display: flex;
height: 28px;
width: 28px;
z-index: 2;
}
.stage > svg {
height: 100%;
width: 100%;
overflow: visible;
}

View file

@ -1,27 +1,12 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo } from 'react' import React, { memo } from 'react'
import { spacer, offColor } from 'src/styling/variables'
import { TL1 } from './typography' import { TL1 } from './typography'
const useStyles = makeStyles({
subtitle: {
color: offColor,
marginTop: spacer * 2,
marginBottom: spacer * 2
},
extraMarginTop: {
marginTop: spacer * 9
}
})
const Subtitle = memo(({ children, className, extraMarginTop }) => { const Subtitle = memo(({ children, className, extraMarginTop }) => {
const classes = useStyles()
const classNames = { const classNames = {
[classes.subtitle]: true, 'text-comet my-4': true,
[classes.extraMarginTop]: extraMarginTop 'mt-18': extraMarginTop
} }
return <TL1 className={classnames(classNames, className)}>{children}</TL1> return <TL1 className={classnames(classNames, className)}>{children}</TL1>

View file

@ -1,35 +0,0 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
import { Label1 } from './typography'
const useStyles = makeStyles({
wrapper: {
display: 'flex',
alignItems: 'center'
},
colorIndicator: {
borderRadius: 3,
height: 12,
width: 12,
marginRight: 8
}
})
const TableLabel = ({ className, label, color, ...props }) => {
const classes = useStyles()
return (
<div className={classnames(classes.wrapper, className)} {...props}>
{color && (
<div
className={classes.colorIndicator}
style={{ backgroundColor: color }}
/>
)}
<Label1 {...props}>{label}</Label1>
</div>
)
}
export default TableLabel

View file

@ -1,20 +1,9 @@
import { makeStyles } from '@mui/styles'
import React, { memo } from 'react' import React, { memo } from 'react'
import { spacer } from 'src/styling/variables'
import { H1 } from './typography' import { H1 } from './typography'
const useStyles = makeStyles({
title: {
marginTop: spacer * 3,
marginBottom: spacer * 3
}
})
const Title = memo(({ children }) => { const Title = memo(({ children }) => {
const classes = useStyles() return <H1 className="my-6">{children}</H1>
return <H1 className={classes.title}>{children}</H1>
}) })
export default Title export default Title

View file

@ -1,11 +1,10 @@
import ClickAwayListener from '@mui/material/ClickAwayListener' import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState, memo } from 'react' import React, { useState, memo } from 'react'
import Popper from 'src/components/Popper' import Popper from 'src/components/Popper'
import HelpIcon from 'src/styling/icons/action/help/zodiac.svg?react' import HelpIcon from 'src/styling/icons/action/help/zodiac.svg?react'
const useStyles = makeStyles({ const useStyles = {
transparentButton: { transparentButton: {
border: 'none', border: 'none',
backgroundColor: 'transparent', backgroundColor: 'transparent',
@ -27,10 +26,9 @@ const useStyles = makeStyles({
width, width,
padding: [[10, 15]] padding: [[10, 15]]
}) })
}) }
const usePopperHandler = width => { const usePopperHandler = () => {
const classes = useStyles({ width })
const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null) const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null)
const handleOpenHelpPopper = event => { const handleOpenHelpPopper = event => {
@ -48,7 +46,6 @@ const usePopperHandler = width => {
const helpPopperOpen = Boolean(helpPopperAnchorEl) const helpPopperOpen = Boolean(helpPopperAnchorEl)
return { return {
classes,
helpPopperAnchorEl, helpPopperAnchorEl,
helpPopperOpen, helpPopperOpen,
handleOpenHelpPopper, handleOpenHelpPopper,
@ -62,15 +59,13 @@ const HelpTooltip = memo(({ children, width }) => {
return ( return (
<ClickAwayListener onClickAway={handler.handleCloseHelpPopper}> <ClickAwayListener onClickAway={handler.handleCloseHelpPopper}>
<div <div className="relative" onMouseLeave={handler.handleCloseHelpPopper}>
className={handler.classes.relativelyPositioned}
onMouseLeave={handler.handleCloseHelpPopper}>
{handler.helpPopperOpen && ( {handler.helpPopperOpen && (
<div className={handler.classes.safeSpace}></div> <div className="absolute bg-transparent h-10 -left-1/2 w-[200%]"></div>
)} )}
<button <button
type="button" type="button"
className={handler.classes.transparentButton} className="border-0 bg-transparent outline-0 cursor-pointer mt-1"
onMouseEnter={handler.openHelpPopper}> onMouseEnter={handler.openHelpPopper}>
<HelpIcon /> <HelpIcon />
</button> </button>
@ -79,7 +74,9 @@ const HelpTooltip = memo(({ children, width }) => {
anchorEl={handler.helpPopperAnchorEl} anchorEl={handler.helpPopperAnchorEl}
arrowEnabled={true} arrowEnabled={true}
placement="bottom"> placement="bottom">
<div className={handler.classes.popoverContent}>{children}</div> <div className="py-2 px-4" style={{ width }}>
{children}
</div>
</Popper> </Popper>
</div> </div>
</ClickAwayListener> </ClickAwayListener>
@ -104,7 +101,7 @@ const HoverableTooltip = memo(({ parentElements, children, width }) => {
type="button" type="button"
onMouseEnter={handler.handleOpenHelpPopper} onMouseEnter={handler.handleOpenHelpPopper}
onMouseLeave={handler.handleCloseHelpPopper} onMouseLeave={handler.handleCloseHelpPopper}
className={handler.classes.transparentButton}> className="border-0 bg-transparent outline-0 cursor-pointer mt-1">
<HelpIcon /> <HelpIcon />
</button> </button>
)} )}
@ -112,7 +109,9 @@ const HoverableTooltip = memo(({ parentElements, children, width }) => {
open={handler.helpPopperOpen} open={handler.helpPopperOpen}
anchorEl={handler.helpPopperAnchorEl} anchorEl={handler.helpPopperAnchorEl}
placement="bottom"> placement="bottom">
<div className={handler.classes.popoverContent}>{children}</div> <div className="py-2 px-4" style={{ width }}>
{children}
</div>
</Popper> </Popper>
</div> </div>
</ClickAwayListener> </ClickAwayListener>

View file

@ -1,93 +0,0 @@
import { makeStyles } from '@mui/styles'
import Chip from '@mui/material/Chip'
import * as R from 'ramda'
import React from 'react'
import {
secondaryColorLighter,
secondaryColorDarker,
offErrorColor,
errorColor,
offColor,
inputFontWeight,
smallestFontSize,
inputFontFamily,
spacer
} from 'src/styling/variables'
import { onlyFirstToUpper } from 'src/utils/string'
import typographyStyles from './typography/styles'
const { label1 } = typographyStyles
const colors = {
running: secondaryColorDarker,
notRunning: offErrorColor
}
const backgroundColors = {
running: secondaryColorLighter,
notRunning: errorColor
}
const styles = {
uptimeContainer: {
display: 'inline-block',
minWidth: 104,
margin: [[0, 20]]
},
name: {
extend: label1,
paddingLeft: 4,
color: offColor
}
}
const useStyles = makeStyles(styles)
const useChipStyles = makeStyles({
root: {
borderRadius: spacer / 2,
marginTop: spacer / 2,
marginRight: spacer / 4,
marginBottom: spacer / 2,
marginLeft: spacer / 4,
height: spacer * 3,
backgroundColor: ({ type }) => backgroundColors[type]
},
label: {
fontSize: smallestFontSize,
fontWeight: inputFontWeight,
fontFamily: inputFontFamily,
padding: [[spacer / 2, spacer]],
color: ({ type }) => colors[type]
}
})
const Uptime = ({ process, ...props }) => {
const classes = useStyles()
const uptime = time => {
if (time < 60) return `${time}s`
if (time < 3600) return `${Math.floor(time / 60)}m`
if (time < 86400) return `${Math.floor(time / 60 / 60)}h`
return `${Math.floor(time / 60 / 60 / 24)}d`
}
return (
<div className={classes.uptimeContainer}>
<div className={classes.name}>{R.toLower(process.name)}</div>
<Chip
label={
process.state === 'RUNNING'
? `Running for ${uptime(process.uptime)}`
: onlyFirstToUpper(process.state)
}
classes={useChipStyles({
type: process.state === 'RUNNING' ? 'running' : 'notRunning'
})}
/>
</div>
)
}
export default Uptime

View file

@ -1,5 +1,4 @@
import { makeStyles } from '@mui/styles' import IconButton from '@mui/material/IconButton'
import classnames from 'classnames'
import { useFormikContext, Form, Formik, Field as FormikField } from 'formik' import { useFormikContext, Form, Formik, Field as FormikField } from 'formik'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState, memo } from 'react' import React, { useState, memo } from 'react'
@ -11,13 +10,10 @@ import FalseIcon from 'src/styling/icons/table/false.svg?react'
import TrueIcon from 'src/styling/icons/table/true.svg?react' import TrueIcon from 'src/styling/icons/table/true.svg?react'
import * as Yup from 'yup' import * as Yup from 'yup'
import { Link, IconButton } from 'src/components/buttons' import { Link } from 'src/components/buttons'
import { RadioGroup } from 'src/components/inputs/formik' import { RadioGroup } from 'src/components/inputs/formik'
import { Table, TableBody, TableRow, TableCell } from 'src/components/table' import { Table, TableBody, TableRow, TableCell } from 'src/components/table'
import SvgIcon from '@mui/material/SvgIcon'
import { booleanPropertiesTableStyles } from './BooleanPropertiesTable.styles'
const useStyles = makeStyles(booleanPropertiesTableStyles)
const BooleanCell = ({ name }) => { const BooleanCell = ({ name }) => {
const { values } = useFormikContext() const { values } = useFormikContext()
@ -26,6 +22,8 @@ const BooleanCell = ({ name }) => {
const BooleanPropertiesTable = memo( const BooleanPropertiesTable = memo(
({ title, disabled, data, elements, save, forcedEditing = false }) => { ({ title, disabled, data, elements, save, forcedEditing = false }) => {
const [editing, setEditing] = useState(forcedEditing)
const initialValues = R.fromPairs( const initialValues = R.fromPairs(
elements.map(it => [it.name, data[it.name]?.toString() ?? 'false']) elements.map(it => [it.name, data[it.name]?.toString() ?? 'false'])
) )
@ -39,10 +37,6 @@ const BooleanPropertiesTable = memo(
) )
) )
const [editing, setEditing] = useState(forcedEditing)
const classes = useStyles()
const innerSave = async values => { const innerSave = async values => {
const toBoolean = (num, _) => R.equals(num, 'true') const toBoolean = (num, _) => R.equals(num, 'true')
save(R.mapObjIndexed(toBoolean, R.filter(R.complement(R.isNil))(values))) save(R.mapObjIndexed(toBoolean, R.filter(R.complement(R.isNil))(values)))
@ -54,7 +48,7 @@ const BooleanPropertiesTable = memo(
{ display: 'No', code: 'false' } { display: 'No', code: 'false' }
] ]
return ( return (
<div className={classes.booleanPropertiesTableWrapper}> <div className="flex w-sm flex-col ">
<Formik <Formik
validateOnBlur={false} validateOnBlur={false}
validateOnChange={false} validateOnChange={false}
@ -65,16 +59,16 @@ const BooleanPropertiesTable = memo(
{({ resetForm }) => { {({ resetForm }) => {
return ( return (
<Form> <Form>
<div className={classes.rowWrapper}> <div className="flex items-center">
<H4>{title}</H4> <H4>{title}</H4>
{editing ? ( {editing ? (
<div className={classes.rightAligned}> <div className="ml-auto">
<Link type="submit" color="primary"> <Link type="submit" color="primary">
Save Save
</Link> </Link>
<Link <Link
type="reset" type="reset"
className={classes.rightLink} className="ml-5"
onClick={() => { onClick={() => {
resetForm() resetForm()
setEditing(false) setEditing(false)
@ -85,34 +79,30 @@ const BooleanPropertiesTable = memo(
</div> </div>
) : ( ) : (
<IconButton <IconButton
className={classes.transparentButton} className="my-auto mx-3"
onClick={() => setEditing(true)} onClick={() => setEditing(true)}>
size="large"> <SvgIcon fontSize="small">
{disabled ? <EditIconDisabled /> : <EditIcon />} {disabled ? <EditIconDisabled /> : <EditIcon />}
</SvgIcon>
</IconButton> </IconButton>
)} )}
</div> </div>
<PromptWhenDirty /> <PromptWhenDirty />
<Table className={classes.fillColumn}> <Table className="w-full">
<TableBody className={classes.fillColumn}> <TableBody className="w-full">
{elements.map((it, idx) => ( {elements.map((it, idx) => (
<TableRow <TableRow
key={idx} key={idx}
size="sm" size="sm"
className={classes.tableRow}> className="h-auto py-2 px-4 flex items-center justify-between min-h-8 even:bg-transparent odd:bg-zircon">
<TableCell className={classes.leftTableCell}> <TableCell className="p-0 w-50">{it.display}</TableCell>
{it.display} <TableCell className="p-0 flex">
</TableCell>
<TableCell className={classes.rightTableCell}>
{editing && ( {editing && (
<FormikField <FormikField
component={RadioGroup} component={RadioGroup}
name={it.name} name={it.name}
options={radioButtonOptions} options={radioButtonOptions}
className={classnames( className="flex flex-row m-[-15px] p-0"
classes.radioButtons,
classes.rightTableCell
)}
/> />
)} )}
{!editing && <BooleanCell name={it.name} />} {!editing && <BooleanCell name={it.name} />}
@ -122,11 +112,11 @@ const BooleanPropertiesTable = memo(
</TableBody> </TableBody>
</Table> </Table>
</Form> </Form>
); )
}} }}
</Formik> </Formik>
</div> </div>
); )
} }
) )

View file

@ -1,74 +0,0 @@
import baseStyles from 'src/pages/Logs.styles'
import { backgroundColor, zircon } from 'src/styling/variables'
const { fillColumn } = baseStyles
const booleanPropertiesTableStyles = {
booleanPropertiesTableWrapper: {
display: 'flex',
flexDirection: 'column',
width: 396
},
tableRow: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
'&:nth-child(even)': {
backgroundColor: backgroundColor
},
'&:nth-child(odd)': {
backgroundColor: zircon
},
minHeight: 32,
height: 'auto',
padding: [[8, 16, 8, 24]],
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)'
},
leftTableCell: {
display: 'flex',
alignItems: 'center',
justifyContent: 'left',
width: 200,
padding: [0]
},
rightTableCell: {
display: 'flex',
alignItems: 'center',
justifyContent: 'right',
padding: [0]
},
transparentButton: {
'& > *': {
margin: 'auto 12px'
},
'& button': {
border: 'none',
backgroundColor: 'transparent',
cursor: 'pointer'
}
},
rowWrapper: {
display: 'flex',
alignItems: 'center',
position: 'relative',
flex: 'wrap'
},
rightAligned: {
marginLeft: 'auto'
},
radioButtons: {
display: 'flex',
flexDirection: 'row',
margin: [-15]
},
rightLink: {
marginLeft: '20px'
},
fillColumn,
popoverContent: {
width: 272,
padding: [[10, 15]]
}
}
export { booleanPropertiesTableStyles }

View file

@ -1,34 +1,41 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo } from 'react' import React, { memo } from 'react'
import styles from './ActionButton.styles' import moduleStyles from './ActionButton.module.css'
const useStyles = makeStyles(styles)
const ActionButton = memo( const ActionButton = memo(
({ className, Icon, InverseIcon, color, children, ...props }) => { ({
const classes = useStyles() className,
altTextColor,
Icon,
InverseIcon,
color,
center,
children,
...props
}) => {
const classNames = { const classNames = {
[classes.actionButton]: true, [moduleStyles.actionButton]: true,
[classes.primary]: color === 'primary', [moduleStyles.altText]: altTextColor || color !== 'primary',
[classes.secondary]: color === 'secondary', [moduleStyles.primary]: color === 'primary',
[classes.spring]: color === 'spring', [moduleStyles.secondary]: color === 'secondary',
[classes.tomato]: color === 'tomato' [moduleStyles.spring]: color === 'spring',
[moduleStyles.tomato]: color === 'tomato',
[moduleStyles.center]: center
} }
return ( return (
<button className={classnames(classNames, className)} {...props}> <button className={classnames(classNames, className)} {...props}>
{Icon && ( {Icon && (
<div className={classes.actionButtonIcon}> <div className={moduleStyles.actionButtonIcon}>
<Icon /> <Icon />
</div> </div>
)} )}
{InverseIcon && ( {InverseIcon && (
<div <div
className={classnames( className={classnames(
classes.actionButtonIcon, moduleStyles.actionButtonIcon,
classes.actionButtonIconActive moduleStyles.actionButtonIconActive
)}> )}>
<InverseIcon /> <InverseIcon />
</div> </div>

View file

@ -0,0 +1,145 @@
.actionButton {
composes: p from '../typography/typography.module.css';
cursor: pointer;
border: none;
height: 28px;
outline: 0;
border-radius: 6px;
padding: 0 8px;
display: flex;
align-items: center;
}
.actionButton.altText {
color: white;
}
.primary {
background-color: var(--zircon);
}
.primary:hover {
background-color: var(--zircon2);
}
.primary:active {
background-color: var(--comet);
color: white;
}
.primary .actionButtonIconActive {
display: none;
}
.primary:active .actionButtonIcon {
display: none;
}
.primary:active .actionButtonIconActive {
display: flex;
}
.secondary {
background-color: var(--comet);
color: white;
}
.secondary:hover {
background-color: var(--comet2);
}
.secondary:active {
background-color: var(--comet3);
}
.secondary .actionButtonIcon {
display: none;
}
.secondary .actionButtonIconActive {
display: flex;
}
.secondary:active .actionButtonIcon {
display: flex;
}
.secondary:active .actionButtonIconActive {
display: none;
}
.spring {
background-color: var(--spring2);
color: white;
}
.spring:hover {
background-color: var(--spring);
}
.spring:active {
background-color: var(--spring4);
}
.spring .actionButtonIcon {
display: none;
}
.spring .actionButtonIconActive {
display: flex;
}
.spring:active .actionButtonIcon {
display: flex;
}
.spring:active .actionButtonIconActive {
display: none;
}
.tomato {
background-color: var(--tomato);
color: white;
}
.tomato:hover {
background-color: var(--tomato);
}
.tomato:active {
background-color: var(--tomato);
}
.tomato .actionButtonIcon {
display: none;
}
.tomato .actionButtonIconActive {
display: flex;
}
.tomato:active .actionButtonIcon {
display: flex;
}
.tomato:active .actionButtonIconActive {
display: none;
}
.actionButtonIcon {
display: flex;
padding-right: 7px;
}
.actionButtonIcon svg {
width: 14px;
height: 14px;
}
.center {
align-items: center;
justify-content: center;
}
.actionButtonIconActive {
}

View file

@ -1,123 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
white,
subheaderColor,
subheaderDarkColor,
offColor,
offDarkColor,
offDarkerColor,
secondaryColor,
secondaryColorDark,
secondaryColorDarker,
errorColor,
errorColorDark,
errorColorDarker
} from 'src/styling/variables'
const { p } = typographyStyles
const colors = (color1, color2, color3) => {
return {
backgroundColor: color1,
'&:hover': {
backgroundColor: color2
},
'&:active': {
backgroundColor: color3
}
}
}
export default {
actionButton: {
extend: p,
cursor: 'pointer',
border: 'none',
height: 28,
outline: 0,
borderRadius: 6,
padding: '0 8px',
display: 'flex',
alignItems: 'center'
},
primary: {
extend: colors(subheaderColor, subheaderDarkColor, offColor),
'&:active': {
color: white,
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
'& $actionButtonIconActive': {
display: 'none'
}
},
secondary: {
extend: colors(offColor, offDarkColor, offDarkerColor),
color: white,
'&:active': {
'& $actionButtonIcon': {
display: 'flex'
},
'& $actionButtonIconActive': {
display: 'none'
}
},
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
spring: {
extend: colors(secondaryColorDark, secondaryColor, secondaryColorDarker),
color: white,
'&:active': {
'& $actionButtonIcon': {
display: 'flex'
},
'& $actionButtonIconActive': {
display: 'none'
}
},
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
tomato: {
extend: colors(errorColorDark, errorColor, errorColorDarker),
color: white,
'&:active': {
'& $actionButtonIcon': {
display: 'flex'
},
'& $actionButtonIconActive': {
display: 'none'
}
},
'& $actionButtonIcon': {
display: 'none'
},
'& $actionButtonIconActive': {
display: 'flex'
}
},
actionButtonIcon: {
display: 'flex',
paddingRight: 7,
'@global': {
svg: {
width: 14,
height: 14
}
}
},
actionButtonIconActive: {}
}

View file

@ -1,47 +1,10 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo } from 'react' import React, { memo } from 'react'
import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react' import AddIcon from 'src/styling/icons/button/add/zodiac.svg?react'
import typographyStyles from 'src/components/typography/styles' import classes from './AddButton.module.css'
import { zircon, zircon2, comet, fontColor, white } from 'src/styling/variables'
const { p } = typographyStyles
const styles = {
button: {
extend: p,
border: 'none',
backgroundColor: zircon,
cursor: 'pointer',
outline: 0,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 167,
height: 48,
color: fontColor,
'&:hover': {
backgroundColor: zircon2
},
'&:active': {
backgroundColor: comet,
color: white,
'& svg g *': {
stroke: white
}
},
'& svg': {
marginRight: 8
}
}
}
const useStyles = makeStyles(styles)
const SimpleButton = memo(({ className, children, ...props }) => { const SimpleButton = memo(({ className, children, ...props }) => {
const classes = useStyles()
return ( return (
<button className={classnames(classes.button, className)} {...props}> <button className={classnames(classes.button, className)} {...props}>
<AddIcon /> <AddIcon />

View file

@ -0,0 +1,30 @@
.button {
composes: p from '../typography/typography.module.css';
border: none;
background-color: var(--zircon);
cursor: pointer;
outline: 0;
display: flex;
justify-content: center;
align-items: center;
width: 167px;
height: 48px;
color: var(--zodiac);
}
.button:hover {
background-color: var(--zircon2);
}
.button:active {
background-color: var(--comet);
color: white;
}
.button:active svg g * {
stroke: white;
}
.button svg {
margin-right: 8px;
}

View file

@ -1,25 +1,37 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo } from 'react' import React, { memo } from 'react'
import styles from './Button.styles' import moduleStyles from './Button.module.css'
import { spacer } from '../../styling/variables.js'
const useStyles = makeStyles(styles) const pickSize = size => {
switch (size) {
case 'xl':
return spacer * 7.625
case 'sm':
return spacer * 4
case 'lg':
default:
return spacer * 5
}
}
const ActionButton = memo( const ActionButton = memo(
({ ({ size = 'lg', children, className, buttonClassName, ...props }) => {
size = 'lg', const height = pickSize(size)
children,
className,
buttonClassName,
backgroundColor,
...props
}) => {
const classes = useStyles({ size, backgroundColor })
return ( return (
<div className={classnames(className, classes.wrapper)}> <div className={className} style={{ height: height + height / 12 }}>
<button <button
className={classnames(buttonClassName, classes.button)} className={classnames(
buttonClassName,
moduleStyles.button,
'text-white',
{
[moduleStyles.buttonSm]: size === 'sm',
[moduleStyles.buttonXl]: size === 'xl'
}
)}
{...props}> {...props}>
{children} {children}
</button> </button>

View file

@ -0,0 +1,49 @@
.button {
composes: h3 from '../typography/typography.module.css';
border: none;
cursor: pointer;
outline: 0;
font-weight: 900;
background-color: var(--spring);
height: 40px;
padding: 0 20px;
border-radius: 10px;
box-shadow: 0 3px var(--spring4);
}
.buttonXl {
composes: h1 from '../typography/typography.module.css';
height: 61px;
border-radius: 15px
}
.buttonSm {
height: 32px;
padding: 0 16px;
border-radius: 8px
}
.button:disabled {
background-color: var(--dust);
box-shadow: none;
}
.button:disabled:hover {
background-color: var(--dust);
box-shadow: none;
}
.button:disabled:active {
margin-top: 0;
}
.button:hover {
background-color: var(--spring2);
box-shadow: 0 3px var(--spring4);
}
.button:active {
margin-top: 2px;
background-color: var(--spring2);
box-shadow: 0 2px var(--spring4);
}

View file

@ -1,79 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import {
white,
disabledColor,
secondaryColor,
secondaryColorDark,
secondaryColorDarker,
offColor,
offDarkColor,
offDarkerColor,
spacer
} from 'src/styling/variables'
const { h1, h3 } = typographyStyles
const pickSize = size => {
switch (size) {
case 'xl':
return spacer * 7.625
case 'sm':
return spacer * 4
case 'lg':
default:
return spacer * 5
}
}
export default {
wrapper: ({ size }) => {
const height = pickSize(size)
const shadowSize = height / 12
return { height: height + shadowSize / 2 }
},
button: ({ size, backgroundColor }) => {
const height = pickSize(size)
const shadowSize = size === 'xl' ? 3 : height / 12
const padding = size === 'xl' ? 20 : height / 2
const isGrey = backgroundColor === 'grey'
return {
extend: size === 'xl' ? h1 : h3,
border: 'none',
color: white,
cursor: 'pointer',
fontWeight: 900,
outline: 0,
backgroundColor: isGrey ? offDarkColor : secondaryColor,
'&:disabled': {
backgroundColor: disabledColor,
boxShadow: 'none',
'&:hover': {
backgroundColor: disabledColor,
boxShadow: 'none'
},
'&:active': {
marginTop: 0
}
},
shadowSize,
height,
padding: `0 ${padding}px`,
borderRadius: height / 4,
boxShadow: `0 ${shadowSize}px ${isGrey ? offColor : secondaryColorDark}`,
'&:hover': {
backgroundColor: isGrey ? offColor : secondaryColorDark,
boxShadow: `0 ${shadowSize}px ${
isGrey ? offDarkerColor : secondaryColorDarker
}`
},
'&:active': {
marginTop: shadowSize / 2,
backgroundColor: isGrey ? offDarkColor : secondaryColorDark,
boxShadow: `0 ${shadowSize / 2}px ${
isGrey ? offDarkerColor : secondaryColorDarker
}`
}
}
}
}

View file

@ -1,53 +0,0 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { memo } from 'react'
import DeleteIcon from 'src/styling/icons/button/cancel/zodiac.svg?react'
import typographyStyles from 'src/components/typography/styles'
import { zircon, zircon2, comet, fontColor, white } from 'src/styling/variables'
const { p } = typographyStyles
const styles = {
button: {
extend: p,
border: 'none',
backgroundColor: zircon,
cursor: 'pointer',
outline: 0,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 167,
height: 48,
color: fontColor,
'&:hover': {
backgroundColor: zircon2
},
'&:active': {
backgroundColor: comet,
color: white,
'& svg g *': {
stroke: white
}
},
'& svg': {
marginRight: 8
}
}
}
const useStyles = makeStyles(styles)
const SimpleButton = memo(({ className, children, ...props }) => {
const classes = useStyles()
return (
<button className={classnames(classes.button, className)} {...props}>
<DeleteIcon />
{children}
</button>
)
})
export default SimpleButton

View file

@ -1,47 +1,19 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo } from 'react' import React, { memo } from 'react'
import baseButtonStyles from './BaseButton.styles' import classes from './FeatureButton.module.css'
const { baseButton, primary } = baseButtonStyles
const styles = {
featureButton: {
extend: baseButton,
width: baseButton.height,
borderRadius: baseButton.height / 2,
display: 'flex',
padding: 0
},
primary,
buttonIcon: {
margin: 'auto',
'& svg': {
width: 16,
height: 16,
overflow: 'visible',
'& g': {
strokeWidth: 1.8
}
}
},
buttonIconActive: {} // required to extend primary
}
const useStyles = makeStyles(styles)
const FeatureButton = memo( const FeatureButton = memo(
({ className, Icon, InverseIcon, children, ...props }) => { ({ className, Icon, InverseIcon, children, ...props }) => {
const classes = useStyles()
const classNames = {
[classes.featureButton]: true,
[classes.primary]: true
}
return ( return (
<button className={classnames(classNames, className)} {...props}> <button
className={classnames(
classes.baseButton,
classes.roundButton,
classes.primary,
className
)}
{...props}>
{Icon && ( {Icon && (
<div className={classes.buttonIcon}> <div className={classes.buttonIcon}>
<Icon /> <Icon />

View file

@ -0,0 +1,87 @@
.baseButton {
cursor: pointer;
border: none;
outline: 0;
height: 32px;
color: var(--zodiac);
}
.roundButton {
width: 32px;
border-radius: 16px;
display: flex;
padding: 0;
}
.roundButton .buttonIcon {
margin: auto;
}
.roundButton .buttonIcon svg {
width: 16px;
height: 16px;
overflow: visible;
}
.roundButton .buttonIcon svg g {
stroke-width: 2px;
}
.baseButton:active {
color: white;
}
.primary {
background-color: var(--zircon);
}
.primary:hover {
background-color: var(--zircon2);
}
.primary:active {
background-color: var(--comet);
color: white;
}
.primary .buttonIconActive {
display: none;
}
.primary:active .buttonIcon {
display: none;
}
.primary:active .buttonIconActive {
display: block;
}
.secondary {
background-color: var(--comet);
color: white;
}
.secondary:hover {
background-color: var(--comet2);
}
.secondary:active {
background-color: white;
color: var(--zodiac);
}
.secondary .buttonIcon {
display: none;
}
.secondary .buttonIconActive {
display: flex;
}
.secondary:active .buttonIcon {
display: flex;
}
.secondary:active .buttonIconActive {
display: none;
}

View file

@ -1,68 +1,9 @@
import ClickAwayListener from '@mui/material/ClickAwayListener' import ClickAwayListener from '@mui/material/ClickAwayListener'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { useState, memo } from 'react' import React, { useState, memo } from 'react'
import Popover from 'src/components/Popper' import Popover from 'src/components/Popper'
import typographyStyles from 'src/components/typography/styles' import classes from './IDButton.module.css'
import {
subheaderColor,
subheaderDarkColor,
offColor
} from 'src/styling/variables'
const { info2 } = typographyStyles
const colors = (color1, color2, color3) => {
return {
backgroundColor: color1,
'&:hover': {
backgroundColor: color2
},
'&:active': {
backgroundColor: color3
}
}
}
const styles = {
idButton: {
width: 34,
height: 28,
display: 'flex',
borderRadius: 4,
padding: 0,
border: 'none',
cursor: 'pointer'
},
buttonIcon: {
margin: 'auto',
lineHeight: 1,
'& svg': {
overflow: 'visible'
}
},
closed: {
extend: colors(subheaderColor, subheaderDarkColor, offColor)
},
open: {
extend: colors(offColor, offColor, offColor)
},
popoverContent: {
extend: info2,
padding: 8,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 4,
'& img': {
height: 145,
minWidth: 200
}
}
}
const useStyles = makeStyles(styles)
const IDButton = memo( const IDButton = memo(
({ ({
@ -77,8 +18,6 @@ const IDButton = memo(
}) => { }) => {
const [anchorEl, setAnchorEl] = useState(null) const [anchorEl, setAnchorEl] = useState(null)
const classes = useStyles()
const open = Boolean(anchorEl) const open = Boolean(anchorEl)
const id = open ? `simple-popper-${name}` : undefined const id = open ? `simple-popper-${name}` : undefined
@ -127,7 +66,6 @@ const IDButton = memo(
open={open} open={open}
anchorEl={anchorEl} anchorEl={anchorEl}
onClose={handleClose} onClose={handleClose}
arrowSize={3}
placement="top" placement="top"
flip> flip>
<div className={classes.popoverContent}> <div className={classes.popoverContent}>

View file

@ -0,0 +1,58 @@
.idButton {
width: 34px;
height: 28px;
display: flex;
border-radius: 4px;
padding: 0;
border: none;
cursor: pointer;
}
.buttonIcon {
margin: auto;
line-height: 1px;
}
.buttonIcon svg {
overflow: visible;
}
.closed {
background-color: var(--zircon);
}
.closed:hover {
background-color: var(--zircon2);
}
.closed:active {
background-color: var(--comet);
color: white;
}
.open {
background-color: var(--comet);
color: white;
}
.open:hover {
background-color: var(--comet2);
}
.open:active {
background-color: var(--comet3);
}
.popoverContent {
composes: info2 from '../typography/typography.module.css';
padding: 8px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 4px;
}
.popoverContent img {
height: 145px;
min-width: 200px;
}

View file

@ -1,45 +0,0 @@
import IconB from '@mui/material/IconButton'
import { makeStyles } from '@mui/styles'
import React from 'react'
import { comet } from 'src/styling/variables'
const styles = {
root: ({ size }) => ({
width: size,
height: size,
'& svg': {
flex: 1
},
'&:hover': {
backgroundColor: 'inherit'
},
'&:hover rect': {
stroke: comet
},
'&:hover polygon': {
stroke: comet
},
'&:hover path': {
stroke: comet
}
})
}
const useStyles = makeStyles(styles)
const IconButton = ({ size, children, onClick, ...props }) => {
const classes = useStyles({ size })
return (
<IconB
{...props}
size="small"
classes={{ root: classes.root }}
disableRipple
onClick={onClick}>
{children}
</IconB>
)
}
export default IconButton

View file

@ -1,14 +1,10 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo } from 'react' import React, { memo } from 'react'
import styles from './Link.styles' import classes from './Link.module.css'
const useStyles = makeStyles(styles)
const Link = memo( const Link = memo(
({ submit, className, children, color = 'primary', ...props }) => { ({ submit, className, children, color = 'primary', ...props }) => {
const classes = useStyles()
const classNames = { const classNames = {
[classes.link]: true, [classes.link]: true,
[classes.primary]: color === 'primary', [classes.primary]: color === 'primary',

View file

@ -0,0 +1,47 @@
.link {
composes: h4 from '../typography/typography.module.css';
text-decoration: none;
border: none;
background-color: transparent;
cursor: pointer;
padding: 0;
height: 100%;
}
.primary {
box-shadow: inset 0 -4px 0 0 rgba(72, 246, 148, 0.8);
}
.primary:hover {
box-shadow: none;
background-color: rgba(72, 246, 148, 0.8);
}
.secondary {
box-shadow: inset 0 -4px 0 0 rgba(255, 88, 74, 0.8);
}
.secondary:hover {
box-shadow: none;
background-color: rgba(255, 88, 74, 0.8);
color: white;
}
.noColor {
box-shadow: inset 0 -4px 0 0 rgba(255, 255, 255, 0.8);
}
.noColor:hover {
box-shadow: none;
background-color: rgba(255, 255, 255, 0.8);
}
.action {
box-shadow: inset 0 -4px 0 0 rgba(72, 246, 148, 0.8);
color: var(--zircon);
}
.action:hover {
box-shadow: none;
background-color: rgba(72, 246, 148, 0.8);
}

View file

@ -1,47 +0,0 @@
import { alpha } from '@mui/material/styles'
import typographyStyles from 'src/components/typography/styles'
import {
white,
linkPrimaryColor,
linkSecondaryColor,
zircon
} from 'src/styling/variables'
const { h4 } = typographyStyles
const color = color => ({
boxShadow: `inset 0 -4px 0 0 ${alpha(color, 0.8)}`,
'&:hover': {
boxShadow: 'none',
backgroundColor: alpha(color, 0.8)
}
})
export default {
link: {
extend: h4,
textDecoration: 'none',
border: 'none',
backgroundColor: 'transparent',
cursor: 'pointer',
padding: '0',
height: '100%'
},
primary: {
extend: color(linkPrimaryColor)
},
secondary: {
extend: color(linkSecondaryColor),
'&:hover': {
color: white
}
},
noColor: {
extend: color(white)
},
action: {
extend: color(linkPrimaryColor),
color: zircon
}
}

View file

@ -1,12 +1,9 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React, { memo, useState } from 'react' import React, { memo, useState } from 'react'
import { H4 } from 'src/components/typography' import { H4 } from 'src/components/typography'
import CancelIconInverse from 'src/styling/icons/button/cancel/white.svg?react' import CancelIconInverse from 'src/styling/icons/button/cancel/white.svg?react'
import subpageButtonStyles from './SubpageButton.styles' import classes from './SubpageButton.module.css'
const useStyles = makeStyles(subpageButtonStyles)
const SubpageButton = memo( const SubpageButton = memo(
({ ({
@ -19,11 +16,10 @@ const SubpageButton = memo(
}) => { }) => {
const [active, setActive] = useState(false) const [active, setActive] = useState(false)
const isActive = forceDisable ? false : active const isActive = forceDisable ? false : active
const classes = useStyles()
const classNames = { const classNames = {
[classes.button]: true, [classes.button]: true,
[classes.normalButton]: !isActive, [classes.normal]: !isActive,
[classes.activeButton]: isActive [classes.active]: isActive
} }
const normalButton = <Icon className={classes.buttonIcon} /> const normalButton = <Icon className={classes.buttonIcon} />
@ -36,7 +32,7 @@ const SubpageButton = memo(
classes.buttonIconActiveLeft classes.buttonIconActiveLeft
)} )}
/> />
<H4 className={classes.white}>{children}</H4> <H4 className="text-white">{children}</H4>
<CancelIconInverse <CancelIconInverse
className={classnames( className={classnames(
classes.buttonIcon, classes.buttonIcon,

View file

@ -0,0 +1,51 @@
.button {
cursor: pointer;
border: none;
outline: 0;
height: 32px;
padding: 0;
color: white;
border-radius: 16px;
background-color: var(--zircon);
}
.button:hover {
background-color: var(--zircon2);
}
.normal {
width: 32px;
}
.active {
display: flex;
flex-direction: row;
align-items: center;
background-color: var(--comet);
font-weight: bold;
padding: 0 5px;
}
.active:hover {
background-color: var(--comet);
}
.buttonIcon {
width: 16px;
height: 16px;
overflow: visible;
}
.buttonIcon g {
stroke-width: 1.8px;
}
.buttonIconActiveLeft {
margin-right: 12px;
margin-left: 4px;
}
.buttonIconActiveRight {
margin-right: 5px;
margin-left: 20px;
}

View file

@ -1,31 +1,18 @@
import { makeStyles } from '@mui/styles'
import React from 'react' import React from 'react'
import InverseLinkIcon from 'src/styling/icons/action/external link/white.svg?react' import InverseLinkIcon from 'src/styling/icons/action/external link/white.svg?react'
import LinkIcon from 'src/styling/icons/action/external link/zodiac.svg?react' import LinkIcon from 'src/styling/icons/action/external link/zodiac.svg?react'
import { ActionButton } from 'src/components/buttons' import { ActionButton } from 'src/components/buttons'
import { spacer, primaryColor } from 'src/styling/variables'
const useStyles = makeStyles({
actionButton: {
marginBottom: spacer * 4
},
actionButtonLink: {
textDecoration: 'none',
color: primaryColor
}
})
const SupportLinkButton = ({ link, label }) => { const SupportLinkButton = ({ link, label }) => {
const classes = useStyles()
return ( return (
<a <a
className={classes.actionButtonLink} className="no-underline text-zodiac"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
href={link}> href={link}>
<ActionButton <ActionButton
className={classes.actionButton} className="mb-8"
color="primary" color="primary"
Icon={LinkIcon} Icon={LinkIcon}
InverseIcon={InverseLinkIcon}> InverseIcon={InverseLinkIcon}>

View file

@ -1,10 +1,8 @@
import ActionButton from './ActionButton' import ActionButton from './ActionButton'
import AddButton from './AddButton' import AddButton from './AddButton'
import Button from './Button' import Button from './Button'
import DeleteButton from './DeleteButton'
import FeatureButton from './FeatureButton' import FeatureButton from './FeatureButton'
import IDButton from './IDButton' import IDButton from './IDButton'
import IconButton from './IconButton'
import Link from './Link' import Link from './Link'
import SubpageButton from './SubpageButton' import SubpageButton from './SubpageButton'
import SupportLinkButton from './SupportLinkButton' import SupportLinkButton from './SupportLinkButton'
@ -14,10 +12,8 @@ export {
Link, Link,
ActionButton, ActionButton,
FeatureButton, FeatureButton,
IconButton,
IDButton, IDButton,
AddButton, AddButton,
SupportLinkButton, SupportLinkButton,
SubpageButton, SubpageButton
DeleteButton
} }

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import { import {
add, add,
differenceInMonths, differenceInMonths,
@ -18,77 +17,12 @@ import React, { useState } from 'react'
import Arrow from 'src/styling/icons/arrow/month_change.svg?react' import Arrow from 'src/styling/icons/arrow/month_change.svg?react'
import RightArrow from 'src/styling/icons/arrow/month_change_right.svg?react' import RightArrow from 'src/styling/icons/arrow/month_change_right.svg?react'
import typographyStyles from 'src/components/typography/styles'
import { primaryColor, zircon } from 'src/styling/variables'
import Tile from './Tile' import Tile from './Tile'
import classes from './Calendar.module.css'
const { p, label2 } = typographyStyles
const styles = {
wrapper: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
button: {
outline: 'none'
},
navbar: {
extend: p,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
padding: [[15, 15]],
color: primaryColor,
'& button': {
display: 'flex',
alignItems: 'center',
padding: 0,
border: 'none',
backgroundColor: zircon,
cursor: 'pointer',
borderRadius: '50%',
width: 20,
height: 20,
position: 'relative',
overflow: 'hidden',
'& svg': {
position: 'absolute',
left: 0
}
}
},
table: {
borderCollapse: 'collapse',
width: '100%',
color: primaryColor,
'& tr': {
'&:first-child': {
paddingLeft: 5
},
'&:last-child': {
paddingRight: 5
}
},
'& th, & td': {
margin: 0,
padding: [[3, 0, 3, 0]]
},
'& th': {
extend: label2
}
}
}
const useStyles = makeStyles(styles)
const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => { const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(new Date()) const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(new Date())
const classes = useStyles()
const weekdays = Array.from(Array(7)).map((_, i) => const weekdays = Array.from(Array(7)).map((_, i) =>
format('EEEEE', add({ days: i }, startOfWeek(new Date()))) format('EEEEE', add({ days: i }, startOfWeek(new Date())))
) )

View file

@ -0,0 +1,66 @@
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
}
.button {
outline: none;
}
.navbar {
font-size: 14px;
font-family: var(--museo);
font-weight: 500;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 15px 15px;
color: var(--zodiac);
}
.navbar button {
display: flex;
align-items: center;
padding: 0;
border: none;
background-color: var(--zircon);
cursor: pointer;
border-radius: 50%;
width: 20px;
height: 20px;
position: relative;
overflow: hidden;
}
.navbar button svg {
position: absolute;
left: 0;
}
.table {
border-collapse: collapse;
width: 100%;
color: var(--zodiac);
}
.table tr:first-child {
padding-left: 5px;
}
.table tr:last-child {
padding-right: 5px;
}
.table th,
.table td {
margin: 0;
padding: 3px 0 3px 0;
}
.table th {
font-size: 13px;
font-family: var(--museo);
font-weight: 700;
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import { compareAsc, differenceInDays, set } from 'date-fns/fp' import { compareAsc, differenceInDays, set } from 'date-fns/fp'
import * as R from 'ramda' import * as R from 'ramda'
@ -6,15 +5,6 @@ import React, { useState, useEffect } from 'react'
import Calendar from './Calendar' import Calendar from './Calendar'
const styles = {
wrapper: {
backgroundColor: 'white',
borderRadius: 10
}
}
const useStyles = makeStyles(styles)
const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => { const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
const [from, setFrom] = useState(null) const [from, setFrom] = useState(null)
const [to, setTo] = useState(null) const [to, setTo] = useState(null)
@ -23,8 +13,6 @@ const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
onRangeChange(from, to) onRangeChange(from, to)
}, [from, onRangeChange, to]) }, [from, onRangeChange, to])
const classes = useStyles()
const handleSelect = day => { const handleSelect = day => {
if ( if (
(maxDate && compareAsc(maxDate, day) > 0) || (maxDate && compareAsc(maxDate, day) > 0) ||
@ -55,7 +43,7 @@ const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
return ( return (
<> <>
<div className={classnames(classes.wrapper, className)}> <div className={classnames('bg-white rounded-xl', className)}>
<Calendar <Calendar
from={from} from={from}
to={to} to={to}

View file

@ -1,76 +1,15 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React from 'react' import React from 'react'
import typographyStyles from 'src/components/typography/styles' import classes from './Tile.module.css'
import {
primaryColor,
spring2,
spring3,
disabledColor
} from 'src/styling/variables'
const { label1 } = typographyStyles
const styles = {
wrapper: {
height: 26,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
overflow: 'hidden'
},
button: {
outline: 'none',
extend: label1,
border: 'none',
cursor: 'pointer',
backgroundColor: 'transparent',
color: primaryColor,
zIndex: 2
},
lowerBound: {
left: '50%'
},
upperBound: {
right: '50%'
},
selected: {
width: 26,
height: 26,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: spring2,
borderRadius: '50%',
position: 'absolute',
zIndex: 1
},
between: {
position: 'absolute',
width: '100%',
height: '100%',
zIndex: 0,
backgroundColor: spring3
},
disabled: {
color: disabledColor,
cursor: 'default'
}
}
const useStyles = makeStyles(styles)
const Tile = ({ const Tile = ({
isLowerBound, isLowerBound,
isUpperBound, isUpperBound,
isBetween, isBetween,
isDisabled, isDisabled,
children, children
...props
}) => { }) => {
const classes = useStyles()
const selected = isLowerBound || isUpperBound const selected = isLowerBound || isUpperBound
const rangeClasses = { const rangeClasses = {

View file

@ -0,0 +1,53 @@
.wrapper {
height: 26px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.button {
outline: none;
font-size: 13px;
font-family: var(--museo);
font-weight: 500;
border: none;
cursor: pointer;
background-color: transparent;
color: var(--zodiac);
z-index: 2;
}
.lowerBound {
left: 50%;
}
.upperBound {
right: 50%;
}
.selected {
width: 26px;
height: 26px;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--spring2);
border-radius: 50%;
position: absolute;
z-index: 1;
}
.between {
position: absolute;
width: 100%;
height: 100%;
z-index: 0;
background-color: var(--spring3);
}
.disabled {
color: var(--dust);
cursor: default;
}

View file

@ -1,74 +0,0 @@
import { makeStyles } from '@mui/styles'
import React, { useState, memo } from 'react'
import { H4, P } from 'src/components/typography'
import EditIconDisabled from 'src/styling/icons/action/edit/disabled.svg?react'
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
import { Link } from 'src/components/buttons'
import { RadioGroup } from 'src/components/inputs'
import { editablePropertyStyles } from './EditableProperty.styles'
const useStyles = makeStyles(editablePropertyStyles)
const EditableProperty = memo(
({ title, prefixText, disabled, options, code, save }) => {
const [editing, setEditing] = useState(false)
const [currentCode, setCurrentCode] = useState(code)
const classes = useStyles()
const innerSave = () => {
save(currentCode)
setEditing(false)
}
const innerCancel = () => setEditing(false)
return (
<>
<div className={classes.rowWrapper}>
<H4>{title}</H4>
{editing ? (
<div className={classes.leftSpace}>
<Link
className={classes.leftSpace}
onClick={innerCancel}
color="secondary">
Cancel
</Link>
<Link
className={classes.leftSpace}
onClick={innerSave}
color="primary">
Save
</Link>
</div>
) : (
<div className={classes.transparentButton}>
<button disabled={disabled} onClick={() => setEditing(true)}>
{disabled ? <EditIconDisabled /> : <EditIcon />}
</button>
</div>
)}
</div>
{editing ? (
<RadioGroup
options={options}
value={currentCode}
onChange={event => setCurrentCode(event.target.value)}
className={classes.radioButtons}
/>
) : (
<P>
{`${prefixText} ${options
.find(it => it.code === currentCode)
.display.toLowerCase()}`}
</P>
)}
</>
)
}
)
export default EditableProperty

View file

@ -1,36 +0,0 @@
const optionsRowHeigth = 43
const editablePropertyStyles = {
transparentButton: {
'& > *': {
margin: 'auto 12px'
},
'& button': {
border: 'none',
backgroundColor: 'transparent',
cursor: 'pointer'
}
},
rowWrapper: {
display: 'flex',
alignItems: 'center',
position: 'relative',
flex: 'wrap',
height: optionsRowHeigth
},
rightAligned: {
display: 'flex',
position: 'absolute',
right: 0
},
radioButtons: {
display: 'flex',
flexDirection: 'row',
height: optionsRowHeigth
},
leftSpace: {
marginLeft: '20px'
}
}
export { editablePropertyStyles }

View file

@ -1,3 +0,0 @@
import EditableProperty from './EditableProperty'
export { EditableProperty }

View file

@ -1,4 +1,3 @@
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, { useContext } from 'react' import React, { useContext } from 'react'
@ -13,14 +12,6 @@ import { sentenceCase } from 'src/utils/string'
import TableCtx from './Context' import TableCtx from './Context'
const styles = {
orderedBySpan: {
whiteSpace: 'nowrap'
}
}
const useStyles = makeStyles(styles)
const groupSecondHeader = elements => { const groupSecondHeader = elements => {
const doubleHeader = R.prop('doubleHeader') const doubleHeader = R.prop('doubleHeader')
const sameDoubleHeader = (a, b) => doubleHeader(a) === doubleHeader(b) const sameDoubleHeader = (a, b) => doubleHeader(a) === doubleHeader(b)
@ -46,7 +37,6 @@ const groupSecondHeader = elements => {
} }
const Header = () => { const Header = () => {
const classes = useStyles()
const { const {
elements, elements,
enableEdit, enableEdit,
@ -79,7 +69,7 @@ const Header = () => {
idx idx
) => { ) => {
const orderClasses = classnames({ const orderClasses = classnames({
[classes.orderedBySpan]: 'whitespace-nowrap':
R.isNil(header) && !R.isNil(orderedBy) && R.equals(name, orderedBy.code) R.isNil(header) && !R.isNil(orderedBy) && R.equals(name, orderedBy.code)
}) })

View file

@ -1,5 +1,6 @@
import { makeStyles } from '@mui/styles'
import Switch from '@mui/material/Switch' import Switch from '@mui/material/Switch'
import IconButton from '@mui/material/IconButton'
import SvgIcon from '@mui/material/SvgIcon'
import classnames from 'classnames' import classnames from 'classnames'
import { Field, useFormikContext } from 'formik' import { Field, useFormikContext } from 'formik'
import * as R from 'ramda' import * as R from 'ramda'
@ -13,15 +14,12 @@ import DisabledEditIcon from 'src/styling/icons/action/edit/disabled.svg?react'
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react' import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
import StripesSvg from 'src/styling/icons/stripes.svg?react' import StripesSvg from 'src/styling/icons/stripes.svg?react'
import { Link, IconButton } from 'src/components/buttons' import { Link } from 'src/components/buttons'
import TableCtx from './Context' import TableCtx from './Context'
import styles from './Row.styles' import moduleStyles from './Row.module.css'
const useStyles = makeStyles(styles)
const ActionCol = ({ disabled, editing }) => { const ActionCol = ({ disabled, editing }) => {
const classes = useStyles()
const { values, submitForm, resetForm } = useFormikContext() const { values, submitForm, resetForm } = useFormikContext()
const { const {
editWidth, editWidth,
@ -59,7 +57,7 @@ const ActionCol = ({ disabled, editing }) => {
{editing && ( {editing && (
<Td textAlign="center" width={actionColSize}> <Td textAlign="center" width={actionColSize}>
<Link <Link
className={classes.saveButton} className={moduleStyles.saveButton}
type="submit" type="submit"
color="primary" color="primary"
onClick={submitForm}> onClick={submitForm}>
@ -76,10 +74,11 @@ const ActionCol = ({ disabled, editing }) => {
<Td textAlign="center" width={editWidth}> <Td textAlign="center" width={editWidth}>
<IconButton <IconButton
disabled={disableEdit} disabled={disableEdit}
className={classes.editButton}
onClick={() => onEdit && onEdit(values.id)} onClick={() => onEdit && onEdit(values.id)}
size="large"> size="small">
{disableEdit ? <DisabledEditIcon /> : <EditIcon />} <SvgIcon>
{disableEdit ? <DisabledEditIcon /> : <EditIcon />}
</SvgIcon>
</IconButton> </IconButton>
</Td> </Td>
)} )}
@ -90,8 +89,10 @@ const ActionCol = ({ disabled, editing }) => {
onClick={() => { onClick={() => {
setDeleteDialog(true) setDeleteDialog(true)
}} }}
size="large"> size="small">
{disabled ? <DisabledDeleteIcon /> : <DeleteIcon />} <SvgIcon>
{disabled ? <DisabledDeleteIcon /> : <DeleteIcon />}
</SvgIcon>
</IconButton> </IconButton>
<DeleteDialog <DeleteDialog
open={deleteDialog} open={deleteDialog}
@ -116,7 +117,7 @@ const ActionCol = ({ disabled, editing }) => {
</Td> </Td>
)} )}
</> </>
); )
} }
const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => { const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
@ -151,11 +152,6 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
const isEditing = editing && isEditable(editable) const isEditing = editing && isEditable(editable)
const isField = !bypassField const isField = !bypassField
const classes = useStyles({
textAlign: isEditing ? editingAlign : textAlign,
size
})
const innerProps = { const innerProps = {
fullWidth: true, fullWidth: true,
autoFocus: focus, autoFocus: focus,
@ -165,16 +161,20 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
...inputProps ...inputProps
} }
const newAlign = isEditing ? editingAlign : textAlign
const justifyContent = newAlign === 'right' ? 'flex-end' : newAlign
const style = suffix || prefix ? { justifyContent } : {}
return ( return (
<div className={classes.fields}> <div className={moduleStyles.fields}>
{fields.map((f, idx) => ( {fields.map((f, idx) => (
<Td <Td
style={style}
key={idx} key={idx}
className={{ className={{
[classes.extraPaddingRight]: extraPaddingRight, [moduleStyles.extraPaddingRight]: extraPaddingRight,
[classes.extraPadding]: extraPadding, [moduleStyles.extraPadding]: extraPadding,
[classes.withSuffix]: suffix, 'flex items-center': suffix || prefix
[classes.withPrefix]: prefix
}} }}
width={width} width={width}
size={size} size={size}
@ -182,7 +182,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
textAlign={textAlign}> textAlign={textAlign}>
{prefix && !isHidden(values) && ( {prefix && !isHidden(values) && (
<PrefixComponent <PrefixComponent
className={classes.prefix} className={moduleStyles.prefix}
style={isEditing ? {} : textStyle(values, isEditing)}> style={isEditing ? {} : textStyle(values, isEditing)}>
{typeof prefix === 'function' ? prefix(f) : prefix} {typeof prefix === 'function' ? prefix(f) : prefix}
</PrefixComponent> </PrefixComponent>
@ -200,7 +200,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
)} )}
{suffix && !isHidden(values) && ( {suffix && !isHidden(values) && (
<SuffixComponent <SuffixComponent
className={classes.suffix} className={moduleStyles.suffix}
style={isEditing ? {} : textStyle(values, isEditing)}> style={isEditing ? {} : textStyle(values, isEditing)}>
{suffix} {suffix}
</SuffixComponent> </SuffixComponent>
@ -241,8 +241,6 @@ const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
stripeWhen stripeWhen
} = useContext(TableCtx) } = useContext(TableCtx)
const classes = useStyles()
const shouldStripe = !editing && stripeWhen && stripeWhen(values) const shouldStripe = !editing && stripeWhen && stripeWhen(values)
const innerElements = shouldStripe ? groupStriped(elements) : elements const innerElements = shouldStripe ? groupStriped(elements) : elements
@ -261,7 +259,7 @@ const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
) )
const classNames = { const classNames = {
[classes.lastOfGroup]: lastOfGroup [moduleStyles.lastOfGroup]: lastOfGroup
} }
const touchedErrors = R.pick(R.keys(touched), errors) const touchedErrors = R.pick(R.keys(touched), errors)

View file

@ -0,0 +1,29 @@
.saveButton {
margin-right: 20px;
}
.lastOfGroup {
margin-bottom: 24px;
}
.extraPadding {
padding-left: 35px;
padding-right: 30px;
}
.extraPaddingRight {
padding-right: 39px;
}
.suffix {
margin: 0 0 0 7px;
}
.prefix {
margin: 0 7px 0 0;
}
.fields {
display: flex;
flex-direction: column;
}

View file

@ -1,45 +0,0 @@
import { bySize, bold } from 'src/styling/helpers'
export default {
saveButton: {
marginRight: 20
},
lastOfGroup: {
marginBottom: 24
},
extraPadding: {
paddingLeft: 35,
paddingRight: 30
},
extraPaddingRight: {
paddingRight: 39
},
withSuffix: ({ textAlign }) => {
const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign
return {
display: 'flex',
alignItems: 'center',
justifyContent
}
},
suffix: {
margin: [[0, 0, 0, 7]]
},
withPrefix: ({ textAlign }) => {
const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign
return {
display: 'flex',
alignItems: 'center',
justifyContent
}
},
prefix: {
margin: [[0, 7, 0, 0]]
},
size: ({ size }) => bySize(size),
bold,
fields: {
display: 'flex',
flexDirection: 'column'
}
}

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import { Form, Formik } from 'formik' import { Form, Formik } from 'formik'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
@ -13,13 +12,11 @@ import { AddButton } from 'src/components/buttons/index'
import TableCtx from './Context' import TableCtx from './Context'
import Header from './Header' import Header from './Header'
import ERow from './Row' import ERow from './Row'
import styles from './Table.styles' import classes from './Table.module.css'
const ACTION_COL_SIZE = 87 const ACTION_COL_SIZE = 87
const DEFAULT_COL_SIZE = 100 const DEFAULT_COL_SIZE = 100
const useStyles = makeStyles(styles)
const getWidth = R.compose( const getWidth = R.compose(
R.reduce(R.add)(0), R.reduce(R.add)(0),
R.map(it => it.width ?? DEFAULT_COL_SIZE) R.map(it => it.width ?? DEFAULT_COL_SIZE)
@ -129,8 +126,6 @@ const ETable = ({
const width = getWidth(elements) + actionColSize const width = getWidth(elements) + actionColSize
const classes = useStyles({ width })
const showButtonOnEmpty = !data.length && enableCreate && !adding const showButtonOnEmpty = !data.length && enableCreate && !adding
const canAdd = !forceDisable && !editingId && !disableAdd && !adding const canAdd = !forceDisable && !editingId && !disableAdd && !adding
const showTable = adding || data.length !== 0 const showTable = adding || data.length !== 0
@ -162,7 +157,7 @@ const ETable = ({
return ( return (
<TableCtx.Provider value={ctxValue}> <TableCtx.Provider value={ctxValue}>
<div className={classes.wrapper}> <div style={{ width }}>
{showButtonOnEmpty && canAdd && ( {showButtonOnEmpty && canAdd && (
<AddButton onClick={addField}>{createText}</AddButton> <AddButton onClick={addField}>{createText}</AddButton>
)} )}

View file

@ -0,0 +1,16 @@
.addLink {
margin-left: auto;
}
.title {
margin: 0;
color: var(--comet);
}
.outerHeader {
min-height: 16px;
margin-bottom: 24px;
display: flex;
justify-content: space-between;
align-items: center;
}

View file

@ -1,21 +0,0 @@
import { offColor } from 'src/styling/variables'
export default {
wrapper: ({ width }) => ({
width: width
}),
addLink: {
marginLeft: 'auto'
},
title: {
margin: 0,
color: offColor
},
outerHeader: {
minHeight: 16,
marginBottom: 24,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}
}

View file

@ -1,14 +1,10 @@
import Card from '@mui/material/Card' import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent' import CardContent from '@mui/material/CardContent'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React from 'react' import React from 'react'
import { Link } from 'src/components/buttons' import { Link } from 'src/components/buttons'
import styles from './Table.module.css'
import styles from './Table.styles'
const useStyles = makeStyles(styles)
const Table = ({ children, className, ...props }) => ( const Table = ({ children, className, ...props }) => (
<div className={classnames(className)} {...props}> <div className={classnames(className)} {...props}>
@ -17,17 +13,12 @@ const Table = ({ children, className, ...props }) => (
) )
const THead = ({ children, className }) => { const THead = ({ children, className }) => {
const classes = useStyles() return <div className={classnames(className, styles.header)}>{children}</div>
return <div className={classnames(className, classes.header)}>{children}</div>
} }
const TDoubleLevelHead = ({ children, className }) => { const TDoubleLevelHead = ({ children, className }) => {
const classes = useStyles()
return ( return (
<div className={classnames(className, classes.doubleHeader)}> <div className={classnames(className, styles.doubleHeader)}>{children}</div>
{children}
</div>
) )
} }
@ -36,6 +27,7 @@ const TBody = ({ children, className }) => {
} }
const Td = ({ const Td = ({
style = {},
children, children,
header, header,
className, className,
@ -45,15 +37,28 @@ const Td = ({
textAlign, textAlign,
action action
}) => { }) => {
const classes = useStyles({ textAlign, width, size }) const inlineStyle = {
const classNames = { ...style,
[classes.td]: true, width,
[classes.tdHeader]: header, textAlign,
[classes.actionCol]: action, fontSize: size === 'sm' ? '14px' : size === 'lg' ? '24px' : ''
[classes.size]: !header,
[classes.bold]: !header && bold
} }
return <div data-cy={`td-${header}`} className={classnames(className, classNames)}>{children}</div>
const cssClasses = {
[styles.td]: !header,
[styles.tdHeader]: header,
'font-bold': !header && (bold || size === 'lg'),
[styles.actionCol]: action
}
return (
<div
data-cy={`td-${header}`}
className={classnames(className, cssClasses)}
style={inlineStyle}>
{children}
</div>
)
} }
const Th = ({ children, ...props }) => { const Th = ({ children, ...props }) => {
@ -65,11 +70,11 @@ const Th = ({ children, ...props }) => {
} }
const ThDoubleLevel = ({ title, children, className, width }) => { const ThDoubleLevel = ({ title, children, className, width }) => {
const classes = useStyles({ width })
return ( return (
<div className={classnames(className, classes.thDoubleLevel)}> <div
<div>{title}</div> className={classnames(className, styles.thDoubleLevel)}
style={{ width }}>
<div className={styles.thDoubleLevelFirst}>{title}</div>
<div>{children}</div> <div>{children}</div>
</div> </div>
) )
@ -85,23 +90,30 @@ const Tr = ({
size, size,
newRow newRow
}) => { }) => {
const classes = useStyles({ size }) const inlineStyle = {
const cardClasses = { root: classes.cardContentRoot } minHeight: size === 'sm' ? '34px' : size === 'lg' ? '68px' : '48px'
const classNames = { }
[classes.tr]: true, const cardClasses = {
[classes.trError]: error, [styles.card]: true,
[classes.card]: true, [styles.trError]: error,
[classes.trAdding]: newRow, [styles.trAdding]: newRow
className }
const mainContentClasses = {
[styles.mainContent]: true,
[styles.sizeSm]: size === 'sm',
[styles.sizeLg]: size === 'lg'
} }
return ( return (
<> <>
<Card className={classnames(classNames, className)} onClick={onClick}> <Card className={classnames(className, cardClasses)} onClick={onClick}>
<CardContent classes={cardClasses}> <CardContent className={styles.cardContentRoot}>
<div className={classes.mainContent}>{children}</div> <div className={classnames(mainContentClasses)} style={inlineStyle}>
{children}
</div>
{error && shouldShowError && ( {error && shouldShowError && (
<div className={classes.errorContent}>{errorMessage}</div> <div className={styles.errorContent}>{errorMessage}</div>
)} )}
</CardContent> </CardContent>
</Card> </Card>

View file

@ -0,0 +1,106 @@
.header {
composes: tl2 from '../typography/typography.module.css';
background-color: var(--zodiac);
height: 32px;
text-align: left;
color: white;
display: flex;
align-items: center;
}
.doubleHeader {
composes: tl2 from '../typography/typography.module.css';
background-color: var(--zodiac);
height: 64px;
color: white;
display: table-row;
}
.thDoubleLevel {
display: table-cell;
}
.thDoubleLevelFirst {
composes: label1 from '../typography/typography.module.css';
margin: 0 10px;
font-weight: 700;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--comet);
color: white;
border-radius: 0 0 8px 8px;
height: 28px;
}
.thDoubleLevel > :last-child {
padding: 0 11px;
display: table-cell;
vertical-align: middle;
height: 36px;
}
.cellDoubleLevel {
display: flex;
padding: 0 16px;
}
.td {
padding: 1px 24px 0 24px;
}
.tdHeader {
vertical-align: middle;
display: table-cell;
padding: 0 24px;
}
.trError {
background-color: var(--misty-rose);
}
.trAdding {
background-color: var(--spring3);
}
.mainContent {
display: flex;
align-items: center;
}
.cardContentRoot {
margin: 0;
padding: 0;
}
.cardContentRoot:last-child {
padding: 0;
}
.card {
composes: p from '../typography/typography.module.css';
margin: 4px 0 0 0;
width: 100%;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.08);
}
.card:before {
height: 0;
}
.actionCol {
margin-left: auto;
}
.errorContent {
padding: 12px 0 12px 24px;
color: var(--tomato);
}
.sizeSm {
min-height: 34px;
}
.sizeLg {
min-height: 68px;
}

View file

@ -1,114 +0,0 @@
import typographyStyles from 'src/components/typography/styles'
import { bySize, bold } from 'src/styling/helpers'
import {
tableHeaderColor,
tableHeaderHeight,
tableErrorColor,
tableSuccessColor,
spacer,
white,
tableDoubleHeaderHeight,
offColor,
errorColor
} from 'src/styling/variables'
const { tl2, p, label1 } = typographyStyles
export default {
size: ({ size }) => bySize(size),
bold,
header: {
extend: tl2,
backgroundColor: tableHeaderColor,
height: tableHeaderHeight,
textAlign: 'left',
color: white,
display: 'flex',
alignItems: 'center'
},
doubleHeader: {
extend: tl2,
backgroundColor: tableHeaderColor,
height: tableDoubleHeaderHeight,
color: white,
display: 'table-row'
},
thDoubleLevel: ({ width }) => ({
width,
display: 'table-cell',
'& > :first-child': {
margin: [[0, 10]],
extend: label1,
fontWeight: 700,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: offColor,
color: white,
borderRadius: [[0, 0, 8, 8]],
height: 28
},
'& > :last-child': {
padding: [[0, 11]],
display: 'table-cell',
verticalAlign: 'middle',
height: tableDoubleHeaderHeight - 28
}
}),
cellDoubleLevel: {
display: 'flex',
padding: [[0, spacer * 2]]
},
td: ({ textAlign, width }) => ({
width,
padding: [[1, spacer * 3, 0, spacer * 3]],
textAlign
}),
tdHeader: {
verticalAlign: 'middle',
display: 'table-cell',
padding: [[0, spacer * 3]]
},
trError: {
backgroundColor: tableErrorColor
},
trAdding: {
backgroundColor: tableSuccessColor
},
mainContent: ({ size }) => {
const sizes = {
sm: 34,
lg: 68
}
const minHeight = sizes[size] || 48
return {
display: 'flex',
alignItems: 'center',
minHeight
}
},
// mui-overrides
cardContentRoot: {
margin: 0,
padding: 0,
'&:last-child': {
padding: 0
}
},
card: {
extend: p,
'&:before': {
height: 0
},
margin: [[4, 0, 0, 0]],
width: '100%',
boxShadow: [[0, 0, 4, 0, 'rgba(0, 0, 0, 0.08)']]
},
actionCol: {
marginLeft: 'auto'
},
errorContent: {
padding: [[12, 0, 12, 24]],
color: errorColor
}
}

View file

@ -1,13 +1,11 @@
import Box from '@mui/material/Box'
import MAutocomplete from '@mui/material/Autocomplete' import MAutocomplete from '@mui/material/Autocomplete'
import classnames from 'classnames'
import sort from 'match-sorter' import sort from 'match-sorter'
import * as R from 'ramda' import * as R from 'ramda'
import React from 'react' import React from 'react'
import { HoverableTooltip } from 'src/components/Tooltip' import { HoverableTooltip } from 'src/components/Tooltip'
import { P } from 'src/components/typography' import { P } from 'src/components/typography'
import { errorColor, orangeYellow, spring4 } from 'src/styling/variables'
import TextInput from './TextInput' import TextInput from './TextInput'
const Autocomplete = ({ const Autocomplete = ({
@ -82,7 +80,6 @@ const Autocomplete = ({
openOnFocus openOnFocus
autoHighlight autoHighlight
disableClearable disableClearable
ChipProps={{ onDelete: null }}
clearOnEscape clearOnEscape
isOptionEqualToValue={R.eqProps(valueProp)} isOptionEqualToValue={R.eqProps(valueProp)}
{...props} {...props}
@ -104,39 +101,30 @@ const Autocomplete = ({
if (!props.warning && !props.warningMessage) if (!props.warning && !props.warningMessage)
return <li {...iprops}>{R.path([labelProp])(props)}</li> return <li {...iprops}>{R.path([labelProp])(props)}</li>
const warningColors = { const className = {
clean: spring4, 'flex w-4 h-4 rounded-md': true,
partial: orangeYellow, 'bg-spring4': props.warning === 'clean',
important: errorColor 'bg-orange-yellow': props.warning === 'partial',
'bg-tomato': props.warning === 'important'
} }
const hoverableElement = ( const hoverableElement = <div className={classnames(className)} />
<Box
width={18}
height={18}
borderRadius="6px"
bgcolor={warningColors[props.warning]}
/>
)
return ( return (
<li {...iprops}> <li {...iprops}>
<Box <div className="flex flex-row justify-between items-center w-full">
width="100%" <div className="flex">{R.path([labelProp])(props)}</div>
display="flex"
flexDirection="row"
justifyContent="space-between"
alignItems="center">
<Box>{R.path([labelProp])(props)}</Box>
<HoverableTooltip parentElements={hoverableElement} width={250}> <HoverableTooltip parentElements={hoverableElement} width={250}>
<P>{props.warningMessage}</P> <P>{props.warningMessage}</P>
</HoverableTooltip> </HoverableTooltip>
</Box> </div>
</li> </li>
) )
}} }}
/> slotProps={{
) chip: { onDelete: null }
}} />
);
} }
export default Autocomplete export default Autocomplete

View file

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

View file

@ -1,14 +1,8 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import React from 'react' import React from 'react'
import OtpInput from 'react-otp-input' import OtpInput from 'react-otp-input'
import typographyStyles from 'src/components/typography/styles' import classes from './CodeInput.module.css'
import styles from './CodeInput.styles'
const useStyles = makeStyles(styles)
const useTypographyStyles = makeStyles(typographyStyles)
const CodeInput = ({ const CodeInput = ({
name, name,
@ -19,9 +13,6 @@ const CodeInput = ({
inputStyle, inputStyle,
containerStyle containerStyle
}) => { }) => {
const classes = useStyles()
const typographyClasses = useTypographyStyles()
return ( return (
<OtpInput <OtpInput
id={name} id={name}
@ -30,19 +21,15 @@ const CodeInput = ({
numInputs={numInputs} numInputs={numInputs}
renderSeparator={<span> </span>} renderSeparator={<span> </span>}
shouldAutoFocus shouldAutoFocus
containerStyle={classnames(containerStyle, classes.container)} containerStyle={classnames(containerStyle, 'justify-evenly')}
inputStyle={classnames( inputStyle={classnames(
inputStyle, inputStyle,
classes.input, classes.input,
typographyClasses.confirmationCode, 'font-museo font-black text-4xl',
error && classes.error error && 'border-tomato'
)} )}
inputType={'tel'} inputType={'tel'}
renderInput={(props) => ( renderInput={props => <input {...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 Radio from '@mui/material/Radio'
import MRadioGroup from '@mui/material/RadioGroup' import MRadioGroup from '@mui/material/RadioGroup'
import FormControlLabel from '@mui/material/FormControlLabel' import FormControlLabel from '@mui/material/FormControlLabel'
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' 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 = ({ const RadioGroup = ({
name, name,
label, label,
@ -36,10 +15,11 @@ const RadioGroup = ({
labelClassName, labelClassName,
radioClassName radioClassName
}) => { }) => {
const classes = useStyles()
return ( return (
<> <>
{label && <Label1 className={classes.label}>{label}</Label1>} {label && (
<Label1 className="h-4 leading-4 m-0 mb-1 pl-1">{label}</Label1>
)}
<MRadioGroup <MRadioGroup
name={name} name={name}
value={value} value={value}
@ -51,12 +31,16 @@ const RadioGroup = ({
<FormControlLabel <FormControlLabel
disabled={option.disabled} disabled={option.disabled}
value={option.code} value={option.code}
control={<Radio className={classnames(classes.radio, radioClassName)} />} control={
<Radio
className={classnames('text-spring', radioClassName)}
/>
}
label={option.display} label={option.display}
className={classnames(labelClassName)} className={classnames(labelClassName)}
/> />
{option.subtitle && ( {option.subtitle && (
<Label1 className={classes.subtitle}>{option.subtitle}</Label1> <Label1 className="-mt-2 ml-8">{option.subtitle}</Label1>
)} )}
</div> </div>
</React.Fragment> </React.Fragment>

View file

@ -1,16 +1,12 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames' import classnames from 'classnames'
import { useSelect } from 'downshift' import { useSelect } from 'downshift'
import * as R from 'ramda' import * as R from 'ramda'
import React from 'react' import React from 'react'
import Arrowdown from 'src/styling/icons/action/arrow/regular.svg?react' import Arrowdown from 'src/styling/icons/action/arrow/regular.svg?react'
import styles from './Select.styles' import styles from './Select.module.css'
const useStyles = makeStyles(styles)
function Select({ className, label, items, ...props }) { function Select({ className, label, items, ...props }) {
const classes = useStyles()
const { const {
isOpen, isOpen,
@ -28,18 +24,18 @@ function Select({ className, label, items, ...props }) {
}) })
const selectClassNames = { const selectClassNames = {
[classes.select]: true, [styles.select]: true,
[classes.selectFiltered]: props.defaultAsFilter [styles.selectFiltered]: props.defaultAsFilter
? true ? true
: !R.equals(selectedItem, props.default), : !R.equals(selectedItem, props.default),
[classes.open]: isOpen [styles.open]: isOpen
} }
return ( return (
<div className={classnames(selectClassNames, className)}> <div className={classnames(selectClassNames, className)}>
<label {...getLabelProps()}>{label}</label> <label {...getLabelProps()}>{label}</label>
<button {...getToggleButtonProps()}> <button {...getToggleButtonProps()}>
<span className={classes.selectedItem}>{selectedItem.display}</span> <span className={styles.selectedItem}>{selectedItem.display}</span>
<Arrowdown /> <Arrowdown />
</button> </button>
<ul {...getMenuProps()}> <ul {...getMenuProps()}>

View file

@ -0,0 +1,100 @@
.selectedItem {
width: 111px;
display: block;
white-space: nowrap;
overflow: hidden;
}
.select {
width: 152px;
z-index: 1;
}
.select label {
font-size: 13px;
font-family: var(--museo);
font-weight: 500;
color: var(--comet);
padding-left: 10px;
}
.select button {
font-size: 14px;
font-family: var(--museo);
font-weight: 500;
position: relative;
border: 0;
background-color: var(--zircon);
width: 152px;
padding: 6px 0 6px 12px;
border-radius: 20px;
line-height: 1.14;
text-align: left;
color: var(--comet);
cursor: pointer;
outline: 0 none;
}
.select ul {
max-height: 200px;
width: 152px;
overflow-y: auto;
position: absolute;
margin: 0;
border-top: 0;
padding: 0;
border-radius: 0 0 8px 8px;
background-color: var(--zircon);
outline: 0 none;
}
.select ul li {
font-size: 14px;
font-family: var(--museo);
font-weight: 500;
list-style-type: none;
padding: 6px 12px;
cursor: pointer;
}
.select ul li span {
width: 100%;
display: block;
overflow: hidden;
white-space: nowrap;
}
.select ul li:hover {
background-color: var(--comet);
color: white;
}
.select svg {
position: absolute;
top: 12px;
right: 14px;
fill: var(--comet);
}
.selectFiltered button {
background-color: var(--comet);
color: white;
}
.selectFiltered ul li {
background-color: var(--comet);
color: white;
}
.selectFiltered ul li:hover {
background-color: var(--zircon);
color: var(--comet);
}
.selectFiltered svg {
fill: white !important;
}
.open button {
border-radius: 8px 8px 0 0;
}

View file

@ -1,96 +0,0 @@
import { subheaderColor, offColor, white } from '../../../styling/variables'
import typographyStyles from '../../typography/styles'
const { p, label1 } = typographyStyles
const WIDTH = 152
export default {
selectedItem: {
width: WIDTH - 41,
display: 'block',
whiteSpace: 'nowrap',
overflow: 'hidden'
},
select: {
width: WIDTH,
zIndex: 1,
'& label': {
extend: label1,
color: offColor,
paddingLeft: 10
},
'& button': {
extend: p,
position: 'relative',
border: 0,
backgroundColor: subheaderColor,
width: WIDTH,
padding: [[6, 0, 6, 12]],
borderRadius: 20,
lineHeight: '1.14',
textAlign: 'left',
color: offColor,
cursor: 'pointer',
outline: '0 none'
},
'& ul': {
maxHeight: '200px',
width: WIDTH,
overflowY: 'auto',
position: 'absolute',
margin: 0,
borderTop: 0,
padding: 0,
borderRadius: [[0, 0, 8, 8]],
backgroundColor: subheaderColor,
outline: '0 none',
'& li': {
extend: p,
listStyleType: 'none',
padding: [[6, 12]],
cursor: 'pointer',
'& span': {
width: '100%',
display: 'block',
overflow: 'hidden',
whiteSpace: 'nowrap'
}
},
'& li:hover': {
backgroundColor: offColor,
color: white
}
},
'& svg': {
position: 'absolute',
top: 12,
right: 14,
fill: offColor
}
},
selectFiltered: {
'& button': {
backgroundColor: offColor,
color: white
},
'& ul': {
'& li': {
backgroundColor: offColor,
color: white
},
'& li:hover': {
backgroundColor: subheaderColor,
color: offColor
}
},
'& svg': {
fill: [[white], '!important']
}
},
open: {
'& button': {
borderRadius: [[8, 8, 0, 0]]
}
}
}

View file

@ -1,12 +1,9 @@
import { makeStyles } from '@mui/styles'
import TextField from '@mui/material/TextField' import TextField from '@mui/material/TextField'
import classnames from 'classnames' import classnames from 'classnames'
import * as R from 'ramda' import * as R from 'ramda'
import React, { memo } from 'react' import React, { memo } from 'react'
import styles from './TextInput.styles' import styles from './TextInput.module.css'
const useStyles = makeStyles(styles)
const TextInput = memo( const TextInput = memo(
({ ({
@ -19,6 +16,7 @@ const TextInput = memo(
suffix, suffix,
textAlign, textAlign,
width, width,
inputClasses,
// lg or sm // lg or sm
size, size,
bold, bold,
@ -26,11 +24,23 @@ const TextInput = memo(
InputProps, InputProps,
...props ...props
}) => { }) => {
const classes = useStyles({ textAlign, width, size })
const isTextFilled = !error && !R.isNil(value) && !R.isEmpty(value) const isTextFilled = !error && !R.isNil(value) && !R.isEmpty(value)
const filled = isPasswordFilled || isTextFilled const filled = isPasswordFilled || isTextFilled
const inputClasses = {
[classes.bold]: bold const style = {
width: width,
textAlign: textAlign
}
const sizeClass =
size === 'sm'
? styles.sizeSm
: size === 'lg'
? styles.sizeLg
: styles.size
const divClass = {
[styles.bold]: bold
} }
return ( return (
@ -41,17 +51,22 @@ const TextInput = memo(
onBlur={onBlur} onBlur={onBlur}
error={error} error={error}
value={value} value={value}
classes={{ root: classes.root }}
className={className} className={className}
InputProps={{ style={style}
className: classnames(inputClasses), {...props}
classes: { slotProps={{
root: classes.size, input: {
underline: filled ? classes.underline : null className: classnames(divClass),
classes: {
root: sizeClass,
underline: filled ? styles.underline : null,
input: inputClasses
},
...InputProps
}, },
...InputProps
}} htmlInput: { style: { textAlign } }
{...props} /> }} />
); );
} }
) )

View file

@ -0,0 +1,24 @@
.size {
font-size: 16px;
}
.sizeSm {
font-size: 14px;
}
.sizeLg {
font-size: 24px;
font-weight: 700;
}
.bold {
font-weight: 700;
}
.underline:before {
border-bottom-color: var(--spring);
}
.underline:hover:not(.Mui-disabled)::before {
border-bottom-color: var(--spring);
}

View file

@ -1,24 +0,0 @@
import { bySize, bold } from 'src/styling/helpers'
import { secondaryColor } from 'src/styling/variables'
export default {
size: ({ size }) => ({
marginTop: size === 'lg' ? 0 : 2,
...bySize(size)
}),
bold,
root: ({ width, textAlign }) => ({
width,
'& input': {
textAlign
}
}),
underline: {
'&:before': {
borderBottomColor: secondaryColor
},
'&:hover:not(.Mui-disabled)::before': {
borderBottomColor: secondaryColor
}
}
}

View file

@ -1,38 +1,8 @@
import { makeStyles } from '@mui/styles'
import MUIToggleButtonGroup from '@mui/material/ToggleButtonGroup' import MUIToggleButtonGroup from '@mui/material/ToggleButtonGroup'
import ToggleButton from '@mui/material/ToggleButton' import ToggleButton from '@mui/material/ToggleButton'
import React from 'react' import React from 'react'
import { H4, P } from 'src/components/typography' import { H4, P } from 'src/components/typography'
import { backgroundColor, comet } from 'src/styling/variables'
const styles = {
noTextTransform: {
textTransform: 'none'
},
flex: {
display: 'flex',
alignItems: 'center',
justifyContent: 'start',
width: '90%',
overflow: 'hidden',
maxHeight: 80
},
buttonTextContent: {
marginLeft: 32,
textTransform: 'none',
textAlign: 'left'
},
button: {
backgroundColor: backgroundColor,
marginBottom: 16
},
paragraph: {
color: comet,
marginTop: -10
}
}
const useStyles = makeStyles(styles)
const ToggleButtonGroup = ({ const ToggleButtonGroup = ({
name, name,
orientation = 'vertical', orientation = 'vertical',
@ -42,7 +12,6 @@ const ToggleButtonGroup = ({
size = 'small', size = 'small',
...props ...props
}) => { }) => {
const classes = useStyles()
return ( return (
<MUIToggleButtonGroup <MUIToggleButtonGroup
size={size} size={size}
@ -54,15 +23,15 @@ const ToggleButtonGroup = ({
{props.options.map(option => { {props.options.map(option => {
return ( return (
<ToggleButton <ToggleButton
className={classes.button} className="bg-ghost"
value={option.value} value={option.value}
aria-label={option.value} aria-label={option.value}
key={option.value}> key={option.value}>
<div className={classes.flex}> <div className="flex items-center justify-start w-9/10 overflow-hidden max-h-20">
<option.icon /> <option.icon />
<div className={classes.buttonTextContent}> <div className="ml-8 normal-case text-left">
<H4>{option.title}</H4> <H4>{option.title}</H4>
<P className={classes.paragraph}> {option.description}</P> <P className="text-comet -mt-2"> {option.description}</P>
</div> </div>
</div> </div>
</ToggleButton> </ToggleButton>

View file

@ -1,54 +1,59 @@
import { makeStyles } from '@mui/styles' import Chip from '@mui/material/Chip'
import classnames from 'classnames' import classnames from 'classnames'
import React from 'react' import React from 'react'
import Chip from 'src/components/Chip'
import { Info2, Label1, Label2 } from 'src/components/typography' import { Info2, Label1, Label2 } from 'src/components/typography'
import { numberToFiatAmount } from 'src/utils/number' import { numberToFiatAmount } from 'src/utils/number'
import { cashboxStyles, gridStyles } from './Cashbox.styles' import classes from './Cashbox.module.css'
import { primaryColor as zodiac, tomato } from '../../../styling/variables.js'
const cashboxClasses = makeStyles(cashboxStyles) const colors = {
const gridClasses = makeStyles(gridStyles) cashOut: {
empty: tomato,
full: zodiac
},
cashIn: {
empty: zodiac,
full: tomato
}
}
const Cashbox = ({ const Cashbox = ({
percent = 0, percent = 0,
cashOut = false, cashOut = false,
width, width = 80,
height, height = 118,
className, className,
emptyPartClassName, emptyPartClassName,
labelClassName, labelClassName,
applyColorVariant,
applyFiatBalanceAlertsStyling,
omitInnerPercentage, omitInnerPercentage,
isLow isLow
}) => { }) => {
const classes = cashboxClasses({
percent,
cashOut,
width,
height,
applyColorVariant,
isLow
})
const ltHalf = percent <= 51 const ltHalf = percent <= 51
const color =
const showCashBox = { colors[cashOut ? 'cashOut' : 'cashIn'][!isLow ? 'full' : 'empty']
[classes.fiatBalanceAlertCashbox]: applyFiatBalanceAlertsStyling,
[classes.cashbox]: !applyFiatBalanceAlertsStyling
}
return ( return (
<div className={classnames(className, showCashBox)}> <div
<div className={classnames(emptyPartClassName, classes.emptyPart)}> style={{ height, width, backgroundColor: color, borderColor: color }}
className={classnames(className, classes.cashbox)}>
<div
className={classnames(emptyPartClassName, classes.emptyPart)}
style={{ height: `${100 - percent}%` }}>
{!omitInnerPercentage && ltHalf && ( {!omitInnerPercentage && ltHalf && (
<Label2 className={labelClassName}>{percent.toFixed(0)}%</Label2> <Label2
style={{ color }}
className={classnames(labelClassName, classes.emptyPartP)}>
{percent.toFixed(0)}%
</Label2>
)} )}
</div> </div>
<div className={classes.fullPart}> <div style={{ backgroundColor: color }}>
{!omitInnerPercentage && !ltHalf && ( {!omitInnerPercentage && !ltHalf && (
<Label2 className={labelClassName}>{percent.toFixed(0)}%</Label2> <Label2 className={classnames(classes.fullPartP, labelClassName)}>
{percent.toFixed(0)}%
</Label2>
)} )}
</div> </div>
</div> </div>
@ -71,7 +76,6 @@ const CashIn = ({
}) => { }) => {
const percent = (100 * notes) / capacity const percent = (100 * notes) / capacity
const isLow = percent < threshold const isLow = percent < threshold
const classes = gridClasses()
return ( return (
<> <>
<div className={classes.row}> <div className={classes.row}>
@ -117,7 +121,6 @@ const CashOut = ({
}) => { }) => {
const percent = (100 * notes) / capacity const percent = (100 * notes) / capacity
const isLow = percent < threshold const isLow = percent < threshold
const classes = gridClasses()
return ( return (
<> <>
<div className={classes.row}> <div className={classes.row}>
@ -136,10 +139,7 @@ const CashOut = ({
<div className={classes.col2}> <div className={classes.col2}>
<div className={classes.innerRow}> <div className={classes.innerRow}>
<Info2 className={classes.noMarginText}>{notes}</Info2> <Info2 className={classes.noMarginText}>{notes}</Info2>
<Chip <Chip label={`${denomination} ${currency.code}`} />
className={classes.chip}
label={`${denomination} ${currency.code}`}
/>
</div> </div>
<div className={classes.innerRow}> <div className={classes.innerRow}>
<Label1 className={classes.noMarginText}> <Label1 className={classes.noMarginText}>
@ -163,7 +163,6 @@ const CashOutLite = ({
}) => { }) => {
const percent = (100 * notes) / capacity const percent = (100 * notes) / capacity
const isLow = percent < threshold const isLow = percent < threshold
const classes = gridClasses()
return ( return (
<div className={classes.col}> <div className={classes.col}>
<Cashbox <Cashbox

View file

@ -0,0 +1,52 @@
.row {
display: flex;
align-items: center;
}
.col {
display: flex;
flex-direction: column;
align-items: center;
}
.innerRow {
display: flex;
justify-content: flex-start;
}
.col2 {
margin-left: 14px;
}
.noMarginText {
margin-top: 0;
margin-bottom: 0;
}
.link {
margin-top: 8px;
}
.fullPartP {
color: white;
display: inline;
}
.emptyPart {
background-color: var(--ghost);
position: relative;
}
.emptyPartP {
display: inline-block;
position: absolute;
margin: 0;
bottom: 0;
right: 0;
}
.cashbox {
border: 2px solid;
text-align: end;
display: inline-block;
}

View file

@ -1,88 +0,0 @@
import { spacer, tomato, primaryColor as zodiac } from 'src/styling/variables'
const colors = {
cashOut: {
empty: tomato,
full: zodiac
},
cashIn: {
empty: zodiac,
full: tomato
}
}
const colorPicker = ({ cashOut, applyColorVariant, isLow }) => {
return colors[cashOut ? 'cashOut' : 'cashIn'][
applyColorVariant || !isLow ? 'full' : 'empty'
]
}
const cashboxStyles = {
cashbox: {
borderColor: colorPicker,
backgroundColor: colorPicker,
height: ({ height }) => height ?? 118,
width: ({ width }) => width ?? 80,
border: '2px solid',
textAlign: 'end',
display: 'inline-block'
},
fiatBalanceAlertCashbox: {
borderColor: colorPicker,
backgroundColor: colorPicker,
height: 118,
width: 80,
border: '4px solid'
},
emptyPart: {
backgroundColor: 'white',
height: ({ percent }) => `${100 - percent}%`,
position: 'relative',
'& > p': {
color: colorPicker,
display: 'inline-block',
position: 'absolute',
margin: 0,
bottom: 0,
right: 0
}
},
fullPart: {
backgroundColor: colorPicker,
'& > p': {
color: 'white',
display: 'inline'
}
}
}
const gridStyles = {
row: {
display: 'flex',
alignItems: 'center'
},
col: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
innerRow: {
display: 'flex',
justifyContent: 'flex-start'
},
col2: {
marginLeft: 14
},
noMarginText: {
marginTop: 0,
marginBottom: 0
},
link: {
marginTop: spacer
},
chip: {
margin: [[0, 0, 0, 7]]
}
}
export { cashboxStyles, gridStyles }

View file

@ -1,30 +1,19 @@
import { makeStyles } from '@mui/styles'
import classNames from 'classnames' import classNames from 'classnames'
import React, { memo, useState } from 'react' import React, { memo, useState } from 'react'
import { CashOut } from 'src/components/inputs/cashbox/Cashbox' import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
import { NumberInput } from '../base' import { NumberInput } from '../base'
const useStyles = makeStyles({
flex: {
display: 'flex'
},
cashCassette: {
height: 36,
marginRight: 14
}
})
const CashCassetteInput = memo( const CashCassetteInput = memo(
({ decimalPlaces, width, threshold, inputClassName, ...props }) => { ({ decimalPlaces, width, threshold, inputClassName, ...props }) => {
const classes = useStyles()
const { name, onChange, onBlur, value } = props.field const { name, onChange, onBlur, value } = props.field
const { touched, errors } = props.form const { touched, errors } = props.form
const [notes, setNotes] = useState(value) const [notes, setNotes] = useState(value)
const error = !!(touched[name] && errors[name]) const error = !!(touched[name] && errors[name])
return ( return (
<div className={classes.flex}> <div className="flex">
<CashOut <CashOut
className={classNames(classes.cashCassette, inputClassName)} className={classNames('h-9 mr-4', inputClassName)}
notes={notes} notes={notes}
editingMode={true} editingMode={true}
width={width} 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 ClickAwayListener from '@mui/material/ClickAwayListener'
import Popper from '@mui/material/Popper' import Popper from '@mui/material/Popper'
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, { memo, useState, useEffect, useRef } from 'react' 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 NotificationCenter from 'src/components/NotificationCenter'
import AddMachine from 'src/pages/AddMachine' import AddMachine from 'src/pages/AddMachine'
import styles from './Header.styles' import styles from './Header.module.css'
const useStyles = makeStyles(styles)
const HAS_UNREAD = gql` const HAS_UNREAD = gql`
query getUnread { query getUnread {
@ -26,22 +23,22 @@ const HAS_UNREAD = gql`
} }
` `
const Subheader = ({ item, classes, user }) => { const Subheader = ({ item, user }) => {
const [prev, setPrev] = useState(null) const [prev, setPrev] = useState(null)
return ( return (
<div className={classes.subheader}> <div className={styles.subheader}>
<div className={classes.content}> <div className={styles.content}>
<nav> <nav>
<ul className={classes.subheaderUl}> <ul className={styles.subheaderUl}>
{item.children.map((it, idx) => { {item.children.map((it, idx) => {
if (!R.includes(user.role, it.allowedRoles)) return <></> if (!R.includes(user.role, it.allowedRoles)) return <></>
return ( return (
<li key={idx} className={classes.subheaderLi}> <li key={idx} className={styles.subheaderLi}>
<NavLink <NavLink
to={{ pathname: it.route, state: { prev } }} to={{ pathname: it.route, state: { prev } }}
className={classes.subheaderLink} className={styles.subheaderLink}
activeClassName={classes.activeSubheaderLink} activeClassName={styles.activeSubheaderLink}
isActive={match => { isActive={match => {
if (!match) return false if (!match) return false
setPrev(it.route) setPrev(it.route)
@ -72,7 +69,6 @@ const Header = memo(({ tree, user }) => {
const notifCenterButtonRef = useRef() const notifCenterButtonRef = useRef()
const popperRef = useRef() const popperRef = useRef()
const history = useHistory() const history = useHistory()
const classes = useStyles()
useEffect(() => { useEffect(() => {
if (data?.hasUnreadNotifications) return setHasUnread(true) if (data?.hasUnreadNotifications) return setHasUnread(true)
@ -112,20 +108,20 @@ const Header = memo(({ tree, user }) => {
const popperOpen = Boolean(anchorEl) const popperOpen = Boolean(anchorEl)
const id = popperOpen ? 'notifications-popper' : undefined const id = popperOpen ? 'notifications-popper' : undefined
return ( return (
<header className={classes.headerContainer}> <header className={styles.headerContainer}>
<div className={classes.header}> <div className={styles.header}>
<div className={classes.content}> <div className={styles.content}>
<div <div
onClick={() => { onClick={() => {
setActive(false) setActive(false)
history.push('/dashboard') history.push('/dashboard')
}} }}
className={classnames(classes.logo, classes.logoLink)}> className={classnames(styles.logo, styles.logoLink)}>
<Logo /> <Logo />
<H4 className={classes.white}>Lamassu Admin</H4> <H4 className="text-white">Lamassu Admin</H4>
</div> </div>
<nav className={classes.nav}> <nav className={styles.nav}>
<ul className={classes.ul}> <ul className={styles.ul}>
{tree.map((it, idx) => { {tree.map((it, idx) => {
if (!R.includes(user.role, it.allowedRoles)) return <></> if (!R.includes(user.role, it.allowedRoles)) return <></>
return ( return (
@ -137,11 +133,11 @@ const Header = memo(({ tree, user }) => {
setActive(it) setActive(it)
return true return true
}} }}
className={classnames(classes.link, classes.whiteLink)} className={classnames(styles.link)}
activeClassName={classes.activeLink}> activeClassName={styles.activeLink}>
<li className={classes.li}> <li className={styles.li}>
<span <span
className={classes.forceSize} className={styles.forceSize}
data-forcesize={it.label}> data-forcesize={it.label}>
{it.label} {it.label}
</span> </span>
@ -151,8 +147,9 @@ const Header = memo(({ tree, user }) => {
})} })}
</ul> </ul>
</nav> </nav>
<div className={classes.actionButtonsContainer}> <div className={styles.actionButtonsContainer}>
<ActionButton <ActionButton
altTextColor
color="secondary" color="secondary"
Icon={AddIcon} Icon={AddIcon}
InverseIcon={AddIconReverse} InverseIcon={AddIconReverse}
@ -163,16 +160,16 @@ const Header = memo(({ tree, user }) => {
<div ref={notifCenterButtonRef}> <div ref={notifCenterButtonRef}>
<button <button
onClick={handleClick} onClick={handleClick}
className={classes.notificationIcon}> className={styles.notificationIcon}>
<NotificationIcon /> <NotificationIcon />
{hasUnread && <div className={classes.hasUnread} />} {hasUnread && <div className={styles.hasUnread} />}
</button> </button>
<Popper <Popper
ref={popperRef} ref={popperRef}
id={id} id={id}
open={popperOpen} open={popperOpen}
anchorEl={anchorEl} anchorEl={anchorEl}
className={classes.popper} className={styles.popper}
disablePortal={false} disablePortal={false}
placement="bottom-end" placement="bottom-end"
modifiers={[ modifiers={[
@ -187,8 +184,8 @@ const Header = memo(({ tree, user }) => {
name: 'preventOverflow', name: 'preventOverflow',
enabled: true, enabled: true,
options: { options: {
rootBoundary: 'viewport', rootBoundary: 'viewport'
}, }
} }
]}> ]}>
<NotificationCenter <NotificationCenter
@ -204,9 +201,7 @@ const Header = memo(({ tree, user }) => {
</div> </div>
</div> </div>
</div> </div>
{active && active.children && ( {active && active.children && <Subheader item={active} user={user} />}
<Subheader item={active} classes={classes} user={user} />
)}
{open && <AddMachine close={() => setOpen(false)} onPaired={onPaired} />} {open && <AddMachine close={() => setOpen(false)} onPaired={onPaired} />}
</header> </header>
) )

Some files were not shown because too many files have changed in this diff Show more