Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • kszk/devteam/org/bodysch/bodysch-frontend
1 result
Show changes
Commits on Source (19)
Showing
with 617 additions and 145 deletions
......@@ -18,5 +18,6 @@ module.exports = {
'object-curly-newline': 0,
'implicit-arrow-linebreak': 0,
'react/prop-types': 0,
'react/jsx-wrap-multilines': ['error', { arrow: true, return: true, declaration: true }],
},
};
# stages:
# - Build
# # - Test
# - Docker build
# - Deploy
stages:
- Build
# #services:
# # - mongo
# variables:
# CONTAINER_IMAGE: 'registry.kszk.bme.hu/bodysch/frontend:$CI_COMMIT_REF_NAME'
# # MONGODB_TEST_URI: 'mongodb://mongo/bodysch-test'
# Build:
# stage: Build
# tags: [kszk]
# image: node:14
# script:
# - npm install
# - npm run build
# cache:
# paths:
# - node_modules/
# - build/
# artifacts:
# expire_in: 1 day
# paths:
# - node_modules/
# - build/
# Docker build:
# stage: Docker build
# tags: [kszk]
# only:
# - master
# - DEV
# image:
# name: gcr.io/kaniko-project/executor:debug
# entrypoint: ['']
# script:
# - echo "{\"auths\":{\"registry.kszk.bme.hu\":{\"username\":\"$REGISTRY_USER\",\"password\":\"$REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
# - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CONTAINER_IMAGE
# Deploy dev:
# stage: Deploy
# tags: [kszk-deploy] # request the custom SSH executor
# only:
# - DEV
# script: # your deploy logic
# - echo "$REGISTRY_PASSWORD" | docker login registry.kszk.bme.hu --username $REGISTRY_USER --password-stdin
# - cp docker-compose.dev.yml /home/kszk-gitlab-deployer/bodysch-dev/
# - cd /home/kszk-gitlab-deployer/bodysch-dev/
# - docker-compose -f docker-compose.dev.yml --no-ansi pull
# - docker-compose -f docker-compose.dev.yml up -d
# - docker system prune -f
# variables:
# SSH_HOST: donald.sch.bme.hu # required
# SSH_USER: kszk-gitlab-deployer # default: kszk-gitlab-deployer
# SSH_PORT: 10122 # default: 22
Build:
stage: Build
tags: [kszk]
image: node:16
script:
- npm install
- npm run build
cache:
paths:
- node_modules/
- build/
artifacts:
expire_in: 1 day
paths:
- node_modules/
- build/
FROM nginx:1.19.2
FROM docker.io/nginx:1.21.0
# copy the files builded with npm run build
COPY build /var/www
......
## BodySCH Frontend
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
#### Local proxy
`./tools/local_proxy/Caddyfile/`
Create a local proxy with caddy:
`docker run -d -it --name caddyFrontend -v /path/to/Caddyfile:/etc/caddy/Caddyfile --network host caddy`
When you change the config just `docker stop ...` and `docker start ...`.
If you experience any error check it with `docker logs ...`.
version: '3.7'
services:
bodysch-backend-dev:
container_name: bodysch-backend-dev
image: registry.kszk.bme.hu/bodysch/backend:dev
restart: always
ports:
- '3030:8000'
links:
- bodysch-mongo-dev
env_file:
- .env
depends_on:
- bodysch-mongo-dev
bodysch-mongo-dev:
container_name: bodysch-mongo-dev
image: mongo
volumes:
- ./data:/data/db
expose:
- '27017'
bodysch-frontend-dev:
container_name: bodysch-frontend-dev
image: registry.kszk.bme.hu/bodysch/frontend:DEV
restart: always
ports:
- '3040:3040'
depends_on:
- bodysch-backend-dev
......@@ -2081,6 +2081,11 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
"@types/lodash": {
"version": "4.14.168",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz",
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q=="
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
......
......@@ -47,8 +47,10 @@
"dependencies": {
"@material-ui/core": "^4.11.2",
"@material-ui/icons": "^4.11.2",
"@types/lodash": "^4.14.168",
"axios": "^0.21.1",
"http-proxy-middleware": "^1.0.6",
"lodash": "^4.17.20",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-hook-form": "^6.14.2",
......
......@@ -12,6 +12,11 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
......
......@@ -4,7 +4,7 @@ import { ClientContextProvider } from './context';
import ThemeProvider from './context/ThemeProvider';
import { UserStateProvider } from './context/UserContext';
import Routes from './Routes';
import { darkTheme } from './theme';
import darkTheme from './styles/darkTheme';
function App(): React.ReactElement {
return (
......
import React from 'react';
import { Route, Switch } from 'react-router';
import ProfileButton from './components/ProfileButton';
import { Redirect, Route, Switch } from 'react-router';
import NewsPage from './pages/NewsPage';
import RulesPage from './pages/RulesPage';
const Routes: React.FC = () => (
<Switch>
<Route path="/" exact>
<ProfileButton />
<Redirect to="/news" />
</Route>
<Route path="/news">
<NewsPage />
</Route>
<Route path="/rules">
<RulesPage />
</Route>
</Switch>
);
......
import { Divider, Drawer, Grid, List, ListItem, ListItemText, makeStyles } from '@material-ui/core';
import React from 'react';
import SCHBodyIcon from '../svg/SCHBodyIcon';
import { MENU_ITEMS } from './Header';
import WrapperLink from './WrapperLink';
type DrawerMenuProps = {
open: boolean;
toggleOpen: () => void;
handleLogout: () => void;
};
const useStyles = makeStyles((theme) => ({
item: {
textAlign: 'center',
fontWeight: 500,
color: theme.palette.secondary.main,
'&:hover': {
color: theme.palette.text.primary,
backgroundColor: theme.palette.grey[700],
},
},
grid: {
marginTop: `${theme.spacing(2)}px`,
marginBottom: `${theme.spacing(2)}px`,
},
list: {
minWidth: '250px',
},
}));
const DrawerMenu: React.FC<DrawerMenuProps> = ({ open, toggleOpen, handleLogout }) => {
const classes = useStyles();
return (
<Drawer anchor="left" open={open} onClose={toggleOpen}>
<div className={classes.list}>
<Grid className={classes.grid} container justify="center">
<div>
<SCHBodyIcon width="64px" height="48px" />
</div>
</Grid>
<List>
{MENU_ITEMS.map((item) => (
<WrapperLink key={item.id} to={item.redirectTo}>
<ListItem className={classes.item}>
<ListItemText>{item.title}</ListItemText>
</ListItem>
</WrapperLink>
))}
</List>
<Divider />
<List>
<ListItem className={classes.item} button onClick={handleLogout}>
<ListItemText>Kijelentkezés</ListItemText>
</ListItem>
</List>
</div>
</Drawer>
);
};
export default DrawerMenu;
import {
Box,
IconButton,
makeStyles,
Typography,
useMediaQuery,
useTheme,
} from '@material-ui/core';
import FacebookIcon from '@material-ui/icons/Facebook';
import MailIcon from '@material-ui/icons/Mail';
import React from 'react';
import DevTeamIcon from './svg/DevTeamIcon';
import SchdesignIcon from './svg/SchdesignIcon';
const Footer: React.FC = () => <div>Footer</div>;
const useMobileStyles = makeStyles((theme) => ({
footer: {
background: theme.footer.background,
padding: theme.spacing(1),
},
contactText: {
color: theme.palette.primary.contrastText,
fontSize: '1.7rem',
fontWeight: 500,
marginBottom: theme.spacing(1),
marginTop: theme.spacing(1),
},
social: {
color: theme.palette.secondary.main,
marginLeft: theme.spacing(3),
marginRight: theme.spacing(3),
marginBottom: theme.spacing(1),
marginTop: theme.spacing(1),
fontSize: '2rem',
},
socialButton: {
margin: 0,
padding: 0,
},
devteam: {
color: '#3051bf',
fontSize: '1.5rem',
paddingLeft: theme.spacing(1),
fontWeight: 500,
},
schdesign: {
marginTop: '0.65rem',
},
groups: {
marginTop: theme.spacing(1),
},
groupButton: {
paddingTop: '0.1rem',
paddingBottom: '0.1rem',
},
}));
const useDesktopStyles = makeStyles((theme) => ({
footer: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
},
contactText: {
fontSize: '1.8rem',
},
devteam: {
fontSize: '1.7rem',
paddingLeft: theme.spacing(1),
},
schdesignButton: {
paddingTop: '0.55rem',
},
contact: {
marginRight: theme.spacing(3),
},
social: {
fontSize: '1.5rem',
margin: '0',
marginRight: theme.spacing(1),
marginTop: theme.spacing(0.5),
marginBottom: theme.spacing(0.5),
},
socialText: {
color: theme.palette.secondary.main,
},
}));
const Footer: React.FC = () => {
const mClasses = useMobileStyles();
const dClasses = useDesktopStyles();
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('xs'));
const SmallScreen: React.FC = () => (
<Box display="flex" justifyContent="center" flexDirection="column">
<Typography align="center" className={mClasses.contactText}>
Kapcsolat
</Typography>
<Box display="flex" justifyContent="center">
<IconButton
className={mClasses.socialButton}
onClick={(): void => {
window.open('https://www.facebook.com/groups/schbody/');
}}
>
<FacebookIcon className={mClasses.social} />
</IconButton>
<IconButton
className={mClasses.socialButton}
onClick={(): void => {
window.location.href = 'mailto:body@sch.bme.hu';
}}
>
<MailIcon className={mClasses.social} />
</IconButton>
</Box>
<Box display="flex" justifyContent="space-around" className={mClasses.groups}>
<IconButton
className={mClasses.groupButton}
onClick={(): void => {
window.open('https://kszk.bme.hu/');
}}
>
<Box display="flex" justifyContent="center" alignItems="center">
<DevTeamIcon width="1.8rem" height="1.8rem" />
<Typography className={mClasses.devteam}>DevTeam</Typography>
</Box>
</IconButton>
<IconButton
className={mClasses.groupButton}
onClick={(): void => {
window.open('https://schdesign.hu/');
}}
>
<Box className={mClasses.schdesign}>
<SchdesignIcon
width="7.5rem"
height="2.5rem"
color1={theme.palette.primary.contrastText}
/>
</Box>
</IconButton>
</Box>
</Box>
);
const LargeScreen: React.FC = () => (
<Box display="flex" justifyContent="space-between">
<Box
display="flex"
justifyContent="space-around"
alignItems="center"
className={mClasses.groups}
>
<IconButton
className={mClasses.groupButton}
onClick={(): void => {
window.open('https://kszk.bme.hu/');
}}
>
<Box display="flex" justifyContent="center" alignItems="center">
<DevTeamIcon width="2.25rem" height="2.25rem" />
<Typography className={`${mClasses.devteam} ${dClasses.devteam}`}>DevTeam</Typography>
</Box>
</IconButton>
<IconButton
className={`${mClasses.groupButton} ${dClasses.schdesignButton}`}
onClick={(): void => {
window.open('https://schdesign.hu/');
}}
>
<SchdesignIcon
width="8.75rem"
height="3.125rem"
color1={theme.palette.primary.contrastText}
/>
</IconButton>
</Box>
<Box
display="flex"
flexDirection="column"
alignItems="flex-start"
className={dClasses.contact}
>
<Typography align="center" className={`${mClasses.contactText} ${dClasses.contactText}`}>
Kapcsolat
</Typography>
<Box display="flex" flexDirection="column" alignItems="flex-start">
<IconButton
className={mClasses.socialButton}
onClick={(): void => {
window.open('https://www.facebook.com/groups/schbody/');
}}
>
<Box display="flex" alignItems="center" justifyContent="center">
<FacebookIcon className={`${mClasses.social} ${dClasses.social}`} />
<Typography className={dClasses.socialText}>Facebook</Typography>
</Box>
</IconButton>
<IconButton
className={mClasses.socialButton}
onClick={(): void => {
window.location.href = 'mailto:body@sch.bme.hu';
}}
>
<MailIcon className={`${mClasses.social} ${dClasses.social}`} />
<Typography className={dClasses.socialText}>body@sch.bme.hu</Typography>
</IconButton>
</Box>
</Box>
</Box>
);
return (
<Box component="footer" className={`${mClasses.footer} ${!isSmallScreen && dClasses.footer}`}>
{isSmallScreen ? <SmallScreen /> : <LargeScreen />}
</Box>
);
};
export default Footer;
import {
AppBar,
Badge,
Box,
Button,
Grid,
IconButton,
makeStyles,
Tab,
Tabs,
Toolbar,
Typography,
} from '@material-ui/core';
import { ExitToApp, MailOutline, Report } from '@material-ui/icons';
import { isNil } from 'lodash';
import React, { useState } from 'react';
import { useHistory } from 'react-router';
import { useUserContext } from '../hooks/useUserContext';
import SCHBodyIcon from '../svg/SCHBodyIcon';
interface AppBarMenuItem {
export interface AppBarMenuItem {
id: number;
title: string;
redirectTo: string;
}
const MENU_ITEMS: AppBarMenuItem[] = [
export const MENU_ITEMS: AppBarMenuItem[] = [
{
id: 0,
title: 'News',
title: 'Hírek',
redirectTo: '/news',
},
{
id: 1,
title: 'About',
title: 'Rólunk',
redirectTo: '/about',
},
{
id: 2,
title: 'FAQ',
redirectTo: '/faq',
title: 'Házirend',
redirectTo: '/rules',
},
];
const USER_MENU_ITEMS: AppBarMenuItem[] = [
{
id: 3,
title: 'Időszakok',
redirectTo: '/terms',
},
];
const ADMIN_MENU_ITEMS: AppBarMenuItem[] = [
{
id: 4,
title: 'Felhasználók',
redirectTo: '/users',
},
];
const useStyles = makeStyles((theme) => ({
appBar: {
backgroundColor: theme.palette.primary.main,
padding: theme.spacing(1),
},
tabContainer: {
flexGrow: 1,
height: '100%',
},
tabs: {
height: '100%',
marginRight: `${theme.spacing(1)}px`,
},
tab: {
color: theme.palette.secondary.main,
fontWeight: 600,
padding: '0px',
minWidth: '0px',
},
indicator: {
height: '5px',
backgroundColor: theme.palette.secondary.main,
},
navItem: {
flex: 1,
alignItems: 'center',
'&:first-child': {
marginRight: 'auto;',
},
'&:last-child': {
marginRight: 'auto;',
},
texts: {
flexShrink: 0,
marginRight: `${theme.spacing(1)}px`,
marginLeft: `${theme.spacing(1)}px`,
},
}));
const Header: React.FC = () => {
export type HeaderProps = {
customToolbar?: React.ReactElement;
menuItems?: AppBarMenuItem[];
handleLogout?: () => void;
};
const Header: React.FC<HeaderProps> = ({ customToolbar, handleLogout, menuItems = MENU_ITEMS }) => {
const classes = useStyles();
const history = useHistory();
const { profile } = useUserContext();
const [value, setValue] = useState(
MENU_ITEMS.find((item) => history.location.pathname === item.redirectTo)?.id ?? 0,
menuItems.find((item) => history.location.pathname === item.redirectTo)?.id ?? 0,
);
return (
<AppBar className={classes.appBar} position="static">
<Toolbar>
<Grid container>
<Grid className={classes.navItem} item container justify="flex-start">
{customToolbar !== undefined ? (
customToolbar
) : (
<Toolbar>
<div>
<SCHBodyIcon width="64px" height="48px" />
</div>
<Grid item className={classes.tabContainer} container justify="flex-end">
<Tabs
className={classes.tabs}
classes={{ flexContainer: classes.tabs }}
value={value}
onChange={(event, val): void => {
setValue(val);
}}
TabIndicatorProps={{ className: classes.indicator }}
>
{MENU_ITEMS.map((item) => (
{menuItems.map((item) => (
<Tab
key={item.id}
className={classes.tab}
......@@ -89,18 +130,70 @@ const Header: React.FC = () => {
}}
/>
))}
{!isNil(profile) && (
<>
{USER_MENU_ITEMS.map((item) => (
<Tab
key={item.id}
className={classes.tab}
label={item.title}
onClick={(): void => {
history.push(item.redirectTo);
}}
/>
))}
{profile.role === 'ADMIN' && (
<>
{ADMIN_MENU_ITEMS.map((item) => (
<Tab
key={item.id}
className={classes.tab}
label={item.title}
onClick={(): void => {
history.push(item.redirectTo);
}}
/>
))}
</>
)}
</>
)}
</Tabs>
</Grid>
<Grid className={classes.navItem} item container justify="center">
<Typography variant="h4">SCH-BODY</Typography>
</Grid>
<Grid className={classes.navItem} item container justify="flex-end">
{!isNil(profile) ? (
<>
<IconButton size="medium">
<Badge
badgeContent={profile.notices.filter((item) => !item.isSeen).length}
color="error"
>
<MailOutline style={{ color: 'white' }} />
</Badge>
</IconButton>
{profile.warnings.length > 0 && (
<IconButton size="medium" disableRipple>
<Report color="error" />
</IconButton>
)}
<Typography variant="h6" align="center" className={classes.texts}>
{profile.name}
</Typography>
<Box color="secondary.main">
<IconButton color="inherit" size="medium" onClick={handleLogout}>
<ExitToApp />
</IconButton>
</Box>
</>
) : (
<Button color="secondary" variant="contained">
Login
Belépés
</Button>
</Grid>
</Grid>
</Toolbar>
)}
</Toolbar>
)}
</AppBar>
);
};
......
import { IconButton, Toolbar } from '@material-ui/core';
import { Menu as MenuIcon, Person } from '@material-ui/icons';
import React from 'react';
import SCHBodyIcon from '../svg/SCHBodyIcon';
import Header, { HeaderProps } from './Header';
export type MobileHeaderProps = HeaderProps & {
onMenuClick: () => void;
};
const MobileHeader: React.FC<MobileHeaderProps> = ({ onMenuClick }) => {
return (
<Header
customToolbar={
<Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu" onClick={onMenuClick}>
<MenuIcon />
</IconButton>
<div style={{ flexGrow: 1 }}>
<SCHBodyIcon width="64px" height="48px" />
</div>
{/* TODO: Profile image if present */}
<Person />
</Toolbar>
}
/>
);
};
export default MobileHeader;
import { Link } from 'react-router-dom';
import styled from 'styled-components';
// Link component with removed underline style
// For wrap components, which needs navigation
const WrapperLink = styled(Link)`
text-decoration: none;
&:focus,
&:hover,
&:visited,
&:link,
&:active {
text-decoration: none;
color: inherit;
}
`;
export default WrapperLink;
import * as React from 'react';
interface IDevTeamIconProps extends React.SVGProps<SVGSVGElement> {
color1?: string;
color2?: string;
}
const DevTeamIcon: React.FC<IDevTeamIconProps> = ({
height = '1.5rem',
width = '1.5rem',
color1 = '#3051bf',
color2 = '#a806c9',
...props
}) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height={height}
width={width}
viewBox="0 0 1024 1024"
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
>
<title>devteam</title>
<g id="prefix__Layer_2" data-name="Layer 2">
<path
id="prefix__path4536"
d="M550.27 281.1L433.38 631.8a577.52 577.52 0 0067 30.16l119.25-357.74z"
fill={color2}
/>
<path
d="M511.22 1023.85A511.83 511.83 0 11611.18 10c117.09 23.11 223.44 86 299.46 177 77.74 93 117.85 209 113 326.55 0 .86-.1 1.72-.19 2.58C1010.52 630 954 713.64 860.07 758.1c-71.2 33.68-160.89 43.27-259.39 27.72-89.68-14.17-180.26-48.58-254.93-96.91l-.41-.27L126 542.41a36.56 36.56 0 010-60.83l219.34-146.22 40.55 60.83L212.18 512l173.51 115.67c121.63 78.64 312.82 126 443.11 64.34 70.56-33.38 111.53-94.88 121.8-182.83 7.75-202.4-144-386-353.61-427.51-204.84-40.54-411.24 70.18-490.77 263.27s-11 417 163 532.53C442.85 992.73 675.38 969 822.15 821.06l51.9 51.49a510.56 510.56 0 01-362.83 151.3z"
fill={color1}
/>
<path
d="M678.34 688.64l-40.55-60.84L811.5 512 637.79 396.19l40.55-60.83 219.34 146.22a36.55 36.55 0 010 60.83z"
fill={color1}
/>
</g>
</svg>
);
};
export default DevTeamIcon;
import * as React from 'react';
interface ISchdesignIconProps extends React.SVGProps<SVGSVGElement> {
color1?: string;
color2?: string;
}
const SchdesignIcon: React.FC<ISchdesignIconProps> = ({
height = '2.5rem',
width = '6.25rem',
color1 = '#3d3d3d',
color2 = '#f8485e',
...props
}) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1259.51 337.41"
height={height}
width={width}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
>
<title>{'logoEszk\xF6z 2'}</title>
<g id="prefix__R\xE9teg_2" data-name="R\xE9teg 2">
<g id="prefix__Layer_1" data-name="Layer 1">
<path
d="M563 0v93.23l-.08-.06a70 70 0 00-113.35 52.55v4.77A69.6 69.6 0 00460 184.93a71 71 0 0010 12.68 70 70 0 0092.87 5.39h.13a68.51 68.51 0 006-5.37A70.46 70.46 0 00579 185a69.61 69.61 0 0010.51-36.2V78h.15V0zm-43.49 191.42a43.39 43.39 0 1143.36-44.87v2.98a43.39 43.39 0 01-43.36 41.89zM919.66 78.53h26.49V218.1h-26.49zM1249.08 111.15a70 70 0 00-129.59 34.35v5a69.86 69.86 0 0020.51 47.11 70.64 70.64 0 006.15 5.45v-52.83c0-.76-.06-1.52-.06-2.29s0-1.52.06-2.28a43.12 43.12 0 016.41-20.52 43.77 43.77 0 016.25-7.88 43.38 43.38 0 0161.32 0 43.78 43.78 0 016.27 7.93 43.06 43.06 0 016.43 21.28V218h26.67v-70.78a69.63 69.63 0 00-10.42-36.07zM745 134.63a70 70 0 00-138.73 11v4.9a70 70 0 00119.47 47.11L707 178.77a43.39 43.39 0 01-72-17.28h110a69.82 69.82 0 001.28-12.69v-1.45a70.06 70.06 0 00-1.28-12.72zm-110 0a43.4 43.4 0 0182.52 0zM1092.4 111.1a71 71 0 00-10.12-12.76 71.82 71.82 0 00-6.12-5.44 70 70 0 00-86.68 0 68.35 68.35 0 00-6.18 5.48A69.89 69.89 0 00963.21 140c-.2 1.8-.34 3.61-.4 5.45v4.89a69.67 69.67 0 0010.45 34.45 70.91 70.91 0 0010.07 12.67 70 70 0 0098.95 0 69.91 69.91 0 0020.55-48.83v-1.45a69.66 69.66 0 00-10.43-36.08zm-59.6 80.19a43.37 43.37 0 01-43.32-41.11q-.06-1.12-.06-2.28t.06-2.28a43.38 43.38 0 0186.68.79v2.98a43.29 43.29 0 01-6.49 21.4 43.9 43.9 0 01-6.22 7.82 43.26 43.26 0 01-30.65 12.68zM1102.83 267.38a69.89 69.89 0 01-20.55 49.55 69.77 69.77 0 01-49.48 20.48 69.71 69.71 0 01-43.32-15 70.83 70.83 0 01-6.15-5.45l6.15-6.16 12.68-12.71a43.37 43.37 0 0074-29.21v-1.49-1.49a43.25 43.25 0 00-12.71-29.21l12.71-12.69 6.12-6.13a70.65 70.65 0 0110.12 12.76 69.75 69.75 0 0110.43 36.75z"
fill={color2}
/>
<path
d="M276.15 197.63a70 70 0 01-119.47-47.11v-4.9a70 70 0 01119.47-47.11l-18.83 18.86a43.39 43.39 0 100 61.4zM412.31 98.48a68.9 68.9 0 00-6.14-5.48 70.06 70.06 0 00-86.67 0V0h-26.69v150.46a69.77 69.77 0 0020.52 47.12 70.51 70.51 0 006.14 5.45v-52.71q-.06-1.14-.06-2.28t.06-2.28a43.13 43.13 0 016.42-20.53 43.39 43.39 0 0180.25 20.88v71.99h26.69V148a69.83 69.83 0 00-20.52-49.52zM138.73 134.63h-110A43.39 43.39 0 0170 104.69a43.22 43.22 0 0130.65 12.68l18.83-18.86a70 70 0 00-92.8-5.46 68.35 68.35 0 00-6.18 5.48 70.33 70.33 0 00-10.07 12.7A69.83 69.83 0 000 145.62v4.9a70.69 70.69 0 001.24 11h110a43.39 43.39 0 01-71.91 17.29l-12.68 12.7-6.15 6.16a70 70 0 0099 0A69.79 69.79 0 00140 148.8v-1.45a71 71 0 00-1.27-12.72zM70 148.13l-.16.1.12-.12.07.07z"
fill={color1}
/>
<circle cx={932.35} cy={13.33} r={13.33} fill={color2} />
<path
d="M901.72 134.63h-110a43.68 43.68 0 014.35-9.37 44.48 44.48 0 016.25-7.88 43.4 43.4 0 0161.32 0l18.82-18.86a70 70 0 00-92.8-5.46 68.23 68.23 0 00-6.17 5.48A69.66 69.66 0 00763 145.62v4.9a69.49 69.49 0 001.24 11h110a43.39 43.39 0 01-71.91 17.29l-12.68 12.7-6.15 6.16a70.76 70.76 0 006.15 5.46 70.06 70.06 0 0092.81-5.47 70.55 70.55 0 0010-12.64A69.79 69.79 0 00903 148.8v-1.45a70.06 70.06 0 00-1.28-12.72zM833 148.13l-.17.1.13-.12.06.07z"
fill={color2}
/>
</g>
</g>
</svg>
);
};
export default SchdesignIcon;
......@@ -6,17 +6,16 @@ import {
} from '@material-ui/core/styles';
import React, { useMemo } from 'react';
import { ThemeProvider as SCThemeProvider } from 'styled-components';
import { theme as defaultTheme } from '../theme';
import lightTheme from '../styles/lightTheme';
export interface ThemeProviderProps {
theme?: Theme;
}
const ThemeProvider: React.FC<ThemeProviderProps> = ({ theme: themeProp, children }) => {
const theme = useMemo(
() => (themeProp ? createMuiTheme(defaultTheme, themeProp) : defaultTheme),
[themeProp],
);
const theme = useMemo(() => (themeProp ? createMuiTheme(lightTheme, themeProp) : lightTheme), [
themeProp,
]);
return (
<StylesProvider injectFirst>
<MUIThemeProvider theme={theme}>
......
import React, { createContext, useState } from 'react';
import { IProfile, Role } from '../types/Profile';
interface ContextProps {
profile: IProfile;
export interface UserContextType {
profile: IProfile | undefined;
setProfile: (profile: IProfile) => void;
}
// Context
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const initialState: IProfile = {
externalId: 'abcd',
studentCardNumber: '1234',
roomNumber: 104,
role: Role.User,
role: Role.Admin,
email: 'alma@gmail.com',
name: 'Nagy Gizike',
warnings: [],
notices: [],
notices: [{ _id: '123', text: 'Asd', isSeen: false }],
};
export const userContext = createContext({} as ContextProps);
const { Provider } = userContext;
export const UserContext = createContext({} as UserContextType);
const { Provider } = UserContext;
export const UserStateProvider: React.FC = ({ children }) => {
const [profile, setProfile] = useState<IProfile>(initialState);
const [profile, setProfile] = useState<IProfile | undefined>(initialState);
return <Provider value={{ profile, setProfile }}>{children}</Provider>;
};
export default { userContext, UserStateProvider };
export default { UserContext, UserStateProvider };
import { useRef, useState } from 'react';
// eslint-disable-next-line import/prefer-default-export
export function useToggle(
defaultState = false,
): [boolean, { toggleOn: () => void; toggleOff: () => void; toggle: () => void }] {
const [state, setState] = useState(defaultState);
const toggleOn = useRef(() => setState(true));
const toggleOff = useRef(() => setState(false));
const toggle = useRef(() => setState((s) => !s));
return [
state,
{
toggleOn: toggleOn.current,
toggleOff: toggleOff.current,
toggle: toggle.current,
},
];
}