diff --git a/.eslintrc.js b/.eslintrc.js
index 45af087..072442c 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,28 +1,28 @@
-module.exports = {
- parser: '@typescript-eslint/parser',
- extends: [
- 'plugin:react/recommended',
- 'plugin:@typescript-eslint/recommended',
- 'prettier/@typescript-eslint',
- 'plugin:prettier/recommended',
- 'plugin:react-hooks/recommended',
- ],
- parserOptions: {
- ecmaVersion: 2020,
- sourceType: 'module',
- ecmaFeatures: {
- jsx: true,
- },
- },
- rules: {
- '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_|^req|^next' }],
- '@typescript-eslint/no-explicit-any': 0,
- '@typescript-eslint/explicit-function-return-type': 0,
- 'react/prop-types': 0,
- },
- settings: {
- react: {
- version: 'detect',
- },
- },
-};
+// module.exports = {
+// parser: '@typescript-eslint/parser',
+// extends: [
+// 'plugin:react/recommended',
+// 'plugin:@typescript-eslint/recommended',
+// 'prettier/@typescript-eslint',
+// 'plugin:prettier/recommended',
+// 'plugin:react-hooks/recommended',
+// ],
+// parserOptions: {
+// ecmaVersion: 2020,
+// sourceType: 'module',
+// ecmaFeatures: {
+// jsx: true,
+// },
+// },
+// rules: {
+// '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_|^req|^next' }],
+// '@typescript-eslint/no-explicit-any': 0,
+// '@typescript-eslint/explicit-function-return-type': 0,
+// 'react/prop-types': 0,
+// },
+// settings: {
+// react: {
+// version: 'detect',
+// },
+// },
+// };
diff --git a/package-lock.json b/package-lock.json
index 8205261..7433740 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2012,71 +2012,6 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw=="
},
- "@typescript-eslint/experimental-utils": {
- "version": "3.9.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.1.tgz",
- "integrity": "sha512-lkiZ8iBBaYoyEKhCkkw4SAeatXyBq9Ece5bZXdLe1LWBUwTszGbmbiqmQbwWA8cSYDnjWXp9eDbXpf9Sn0hLAg==",
- "dev": true,
- "requires": {
- "@types/json-schema": "^7.0.3",
- "@typescript-eslint/types": "3.9.1",
- "@typescript-eslint/typescript-estree": "3.9.1",
- "eslint-scope": "^5.0.0",
- "eslint-utils": "^2.0.0"
- }
- },
- "@typescript-eslint/parser": {
- "version": "3.9.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.9.1.tgz",
- "integrity": "sha512-y5QvPFUn4Vl4qM40lI+pNWhTcOWtpZAJ8pOEQ21fTTW4xTJkRplMjMRje7LYTXqVKKX9GJhcyweMz2+W1J5bMg==",
- "dev": true,
- "requires": {
- "@types/eslint-visitor-keys": "^1.0.0",
- "@typescript-eslint/experimental-utils": "3.9.1",
- "@typescript-eslint/types": "3.9.1",
- "@typescript-eslint/typescript-estree": "3.9.1",
- "eslint-visitor-keys": "^1.1.0"
- }
- },
- "@typescript-eslint/types": {
- "version": "3.9.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.9.1.tgz",
- "integrity": "sha512-15JcTlNQE1BsYy5NBhctnEhEoctjXOjOK+Q+rk8ugC+WXU9rAcS2BYhoh6X4rOaXJEpIYDl+p7ix+A5U0BqPTw==",
- "dev": true
- },
- "@typescript-eslint/typescript-estree": {
- "version": "3.9.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.1.tgz",
- "integrity": "sha512-IqM0gfGxOmIKPhiHW/iyAEXwSVqMmR2wJ9uXHNdFpqVvPaQ3dWg302vW127sBpAiqM9SfHhyS40NKLsoMpN2KA==",
- "dev": true,
- "requires": {
- "@typescript-eslint/types": "3.9.1",
- "@typescript-eslint/visitor-keys": "3.9.1",
- "debug": "^4.1.1",
- "glob": "^7.1.6",
- "is-glob": "^4.0.1",
- "lodash": "^4.17.15",
- "semver": "^7.3.2",
- "tsutils": "^3.17.1"
- },
- "dependencies": {
- "semver": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
- "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
- "dev": true
- }
- }
- },
- "@typescript-eslint/visitor-keys": {
- "version": "3.9.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.1.tgz",
- "integrity": "sha512-zxdtUjeoSh+prCpogswMwVUJfEFmCOjdzK9rpNjNBfm6EyPt99x3RrJoBOGZO23FCt0WPKUCOL5mb/9D5LjdwQ==",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^1.1.0"
- }
- },
"@webassemblyjs/ast": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@@ -8794,6 +8729,15 @@
"sort-keys": "^1.0.0"
}
},
+ "notistack": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/notistack/-/notistack-1.0.1.tgz",
+ "integrity": "sha512-2T1WkokzRCM8N9EdueaXja160IMFIMHVhRu0fGkDje7qCzwBHlTMZY2NULQzB2GFOO6iGVzl5GCX2XrJIzI8bw==",
+ "requires": {
+ "clsx": "^1.1.0",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -10636,6 +10580,11 @@
"whatwg-fetch": "^3.0.0"
}
},
+ "react-click-away-listener": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/react-click-away-listener/-/react-click-away-listener-1.4.3.tgz",
+ "integrity": "sha512-c7d6mfZuHu/rIdnEHnovX/QsScQXlqtdAynSnZUyyH+6kPOAyB40k2c5br56c/qp4KBkHD0JQV4C7rVuAmroMw=="
+ },
"react-dev-utils": {
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.1.tgz",
diff --git a/package.json b/package.json
index f0c6554..a5ee4b5 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,9 @@
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
+ "notistack": "^1.0.1",
"react": "^16.13.1",
+ "react-click-away-listener": "^1.4.3",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"styled-components": "^5.1.1"
@@ -21,7 +23,6 @@
"@types/react": "^16.9.46",
"@types/react-dom": "^16.9.8",
"@types/styled-components": "^5.1.2",
- "@typescript-eslint/parser": "^3.9.1",
"prettier": "^2.0.5",
"typescript": "^3.9.7"
},
diff --git a/public/index.html b/public/index.html
index 2a7a20a..cbfdddb 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,22 +1,24 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ PlanNaPlan
+
+
+
+
+
+
- PlanNaPlan
-
-
-
-
-
\ No newline at end of file
diff --git a/src/assets/PL.png b/src/assets/PL.png
deleted file mode 100644
index 656d382..0000000
Binary files a/src/assets/PL.png and /dev/null differ
diff --git a/src/assets/UK.png b/src/assets/UK.png
deleted file mode 100644
index 0f5e14b..0000000
Binary files a/src/assets/UK.png and /dev/null differ
diff --git a/src/assets/account.svg b/src/assets/account.svg
new file mode 100644
index 0000000..87ffb3b
--- /dev/null
+++ b/src/assets/account.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/bin.svg b/src/assets/bin.svg
new file mode 100644
index 0000000..cbfe7d7
--- /dev/null
+++ b/src/assets/bin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/expand.png b/src/assets/expand.png
deleted file mode 100644
index 239474f..0000000
Binary files a/src/assets/expand.png and /dev/null differ
diff --git a/src/assets/expand.svg b/src/assets/expand.svg
new file mode 100644
index 0000000..d89d637
--- /dev/null
+++ b/src/assets/expand.svg
@@ -0,0 +1,41 @@
+
+
+
+
diff --git a/src/assets/poland.svg b/src/assets/poland.svg
new file mode 100644
index 0000000..d5a386e
--- /dev/null
+++ b/src/assets/poland.svg
@@ -0,0 +1,42 @@
+
+
+
diff --git a/src/assets/united-kingdom.svg b/src/assets/united-kingdom.svg
new file mode 100644
index 0000000..60da99a
--- /dev/null
+++ b/src/assets/united-kingdom.svg
@@ -0,0 +1,115 @@
+
+
+
diff --git a/src/assets/user.png b/src/assets/user.png
deleted file mode 100644
index 4b429a0..0000000
Binary files a/src/assets/user.png and /dev/null differ
diff --git a/src/components/App.tsx b/src/components/App.tsx
index 5390571..ff473d8 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -8,6 +8,8 @@ import styled from 'styled-components';
const Wrapper = styled.div`
display: flex;
height: calc(100vh - 80px);
+ background-color: #ECEEF4;
+ padding: 20px;
`;
export const App = () => {
diff --git a/src/components/CourseCard.tsx b/src/components/CourseCard.tsx
index ad7d482..8fae122 100644
--- a/src/components/CourseCard.tsx
+++ b/src/components/CourseCard.tsx
@@ -1,72 +1,87 @@
import React, { useState, useContext, MouseEvent } from 'react';
import Collapse from '@material-ui/core/Collapse';
-import ExpandIcon from '../assets/expand.png';
-import { Course, Group, GroupType } from '../types/index';
+import { ReactComponent as Expand } from '../assets/expand.svg';
+import { Course, Group } from '../types/index';
import { coursesContext } from '../contexts/CoursesProvider';
import styled from 'styled-components';
import { makeStyles } from '@material-ui/core/styles';
-import { ReactComponent as CloseIcon } from '../assets/close.svg';
+import { ReactComponent as Bin } from '../assets/bin.svg';
-interface ClassExandIconProps {
- isSelected: boolean;
-}
-
-const CourseStyled = styled.div`
+const CourseCardWrapper = styled.div`
+ position: relative;
display: flex;
min-height: 40px;
- background-color: rgb(100, 181, 246) !important;
+ background-color: rgb(100, 181, 246);
align-items: center;
justify-content: center;
flex-direction: column;
margin-top: 10px;
- padding-top: 10px;
- padding-bottom: 10px;
- border-radius: 10px;
+ border-radius: 10px;
cursor: pointer;
align-items: stretch;
- position: relative;
- box-shadow: 9px 9px 8px -2px rgba(0,0,0,0.59);
+ box-shadow: 9px 9px 8px -2px rgba(0, 0, 0, 0.59);
`;
-const CourseNameStyled = styled.div`
-padding-top:20px;
-padding-bottom:10px;
-padding-left:35px;
-padding-right:35px;
+
+const TitleWrapper = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 10px;
+`
+
+const BinIcon = styled(Bin)`
+ width: 20px;
+ height: 20px;
+ max-width: 20px;
+ min-width: 20px;
+ cursor: pointer;
+ &:hover {
+ fill: white;
+ }
`;
-interface ClassGroupProps {
- groupType: GroupType;
-}
+const CourseName = styled.div`
+ padding-left: 3px;
+ padding-right: 3px;
+ font-size: 16px;
+ user-select: none;
+`;
const ClassGroupStyled = styled.div`
-position:relative;
+ position: relative;
padding-top: 1px;
padding-bottom: 1px;
:hover {
cursor: pointer;
- background-color:#9ED3FF;
+ background-color: #9ed3ff;
}
`;
-const ClassExandIconStyled = styled.img`
- margin-top: 5px;
+interface ExpandIconProps {
+ isSelected: boolean;
+}
+
+const ExpandIcon = styled(Expand) `
width: 20px;
+ height: 20px;
+ max-width: 20px;
+ min-width: 20px;
transition: 0.2s;
- transform: ${(props) => (props.isSelected ? 'scaleY(-1);' : 'scaleY(1);')};
+ transform: ${({ isSelected }) => (isSelected ? 'scaleY(-1);' : 'scaleY(1);')};
`;
const TypeClass = styled.div`
- font-size:12px;
- position:absolute;
- border-radius:15px;
- background-color:#00506B;
- border:2px solid;
- min-width:45px;
- top:5px;
- left:5px;
- color:white;
- font-weight:bold;
+ font-size: 12px;
+ position: absolute;
+ border-radius: 15px;
+ background-color: #00506b;
+ border: 2px solid;
+ min-width: 45px;
+ top: 5px;
+ left: 5px;
+ color: white;
+ font-weight: bold;
`;
const useStyles = makeStyles({
@@ -87,16 +102,7 @@ const useStyles = makeStyles({
},
});
-const DeleteFromBasketIcon = styled(CloseIcon)`
- width: 20px;
- cursor: pointer;
- position: absolute;
- left: 230px;
- top: -5px;
- &:hover {
- fill: white;
- }
-`;
+
interface CourseCardProps {
course: Course;
@@ -111,24 +117,24 @@ export const CourseCard = ({ course }: CourseCardProps) => {
const onGroupClick = (group: Group, id: number) => addGroup(group, id);
return (
-
- deleteFromBasket(course.id)}>
- setSelected(!isSelected)}>{course.name}
+
+
+ deleteFromBasket(course.id)}>
+ setSelected(!isSelected)}>{course.name}
+ setSelected(!isSelected)} isSelected={isSelected} />
+
{groups
.sort((a, b) => b.type.localeCompare(a.type))
.map((group, index) => (
onGroupClick(group, course.id)}>
- {group.type==="CLASS"? "Ćw." : "Wyk."}
+ {group.type === 'CLASS' ? 'Ćw.' : 'Wyk.'}
{group.time} {group.room}
{group.lecturer}
))}
- setSelected(!isSelected)}>
-
-
-
+
);
};
diff --git a/src/components/Dropdown.tsx b/src/components/Dropdown.tsx
index b270f2d..206ce34 100644
--- a/src/components/Dropdown.tsx
+++ b/src/components/Dropdown.tsx
@@ -1,20 +1,19 @@
-import React, { useState, useContext, useEffect, MouseEvent, ChangeEvent } from 'react';
-import axios from 'axios';
-import { Input } from '@material-ui/core';
-import ClickAwayListener from '@material-ui/core/ClickAwayListener';
+import React, { useState, useContext, useEffect, MouseEvent, forwardRef } from 'react';
import { coursesContext } from '../contexts/CoursesProvider';
-import { Course, Basket } from '../types';
+import { Course } from '../types';
import styled from 'styled-components';
-import { makeStyles } from '@material-ui/core/styles';
-const DropdownStyled = styled.div`
+
+
+const DropdownContainer = styled.div`
+ position: relative;
+ z-index: 99999999;
max-height: 420px;
+ border-radius: 3px;
overflow-y: auto;
+ box-shadow: 0.05em 0.2em 0.6em rgba(0, 0, 0, 0.2);
scroll-snap-type: y mandatory;
scroll-behavior: smooth;
- z-index: 100;
- position: relative;
- border-radius:0px 0px 0px 15px;
::-webkit-scrollbar-track {
border-radius: 10px;
background-color: #f5f5f5;
@@ -25,70 +24,69 @@ const DropdownStyled = styled.div`
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
- background-color: #d4b851;
+ background-color: black;
border: 1px solid;
}
`;
-const CourseStyled = styled.div`
- position: relative;
- z-index: 10;
+const CourseContainer = styled.div`
padding: 5px;
padding-left: 20px;
- background-color: #e6c759;
+ background-color: #f2f4f7;
font-size: 18px;
- font-family: Lato;
+ font-weight: 500;
scroll-snap-align: end;
- border-bottom:1px solid;
:hover {
- background-color: #d4b851;
+ background-color: #eceef4;
cursor: pointer;
}
`;
-const useStyles = makeStyles({
- topbarInput: {
- marginTop: '8px',
- width: '100%',
- },
-});
-
interface DropdownProps {
- clearInput: boolean;
- handleClearInput: () => void;
+ open: boolean;
+ input: string;
+ handleCloseDropdown: () => void;
}
-export const Dropdown = ({ clearInput, handleClearInput }: DropdownProps) => {
- const classes = useStyles();
-
- const [open, setOpen] = React.useState(false);
- const [input, setInput] = useState('');
-
+export const Dropdown = forwardRef(({ open, input, handleCloseDropdown }: DropdownProps, ref: any) => {
//courses - choosenCourses
const [filteredCourses, setFilteredCourses] = useState>([]);
const { courses, basket, addToBasket } = useContext(coursesContext)!;
+ useEffect(() => {
+ console.log('wut');
+ }, [open, input, handleCloseDropdown]);
+
+ useEffect(() => {
+ console.log('input is: ', input);
+ }, [input]);
+
+ useEffect(() => {
+ console.log('is open: ', open);
+ }, [open]);
+
useEffect(() => {
const filterCourses = (input: string) => {
const choosenCoursesNames = basket.map(({ name }) => name.trim());
const filteredCourses = courses.filter(
- ({ name }) => name.toLowerCase().includes(input.toLowerCase()) && !choosenCoursesNames.includes(name),
+ ({ name }) =>
+ name
+ .toLowerCase()
+ .normalize('NFD')
+ .replace(/[\u0300-\u036f]/g, '')
+ .includes(
+ input
+ .toLowerCase()
+ .normalize('NFD')
+ .replace(/[\u0300-\u036f]/g, ''),
+ ) && !choosenCoursesNames.includes(name),
);
setFilteredCourses(filteredCourses);
};
+ console.log("filtering courses");
filterCourses(input);
- }, [input, open, basket]);
-
- useEffect(() => {
- clearInput && (setInput(''), handleClearInput());
- }, [clearInput]);
-
- const handleChange = (event: ChangeEvent) => setInput(event.target.value);
-
- const handleClick = () => setOpen(true);
-
- const handleClickAway = () => setOpen(false);
+ }, [open, input, basket]);
const onCourseClick = async (event: MouseEvent) => {
const target = event.currentTarget;
@@ -97,31 +95,21 @@ export const Dropdown = ({ clearInput, handleClearInput }: DropdownProps) => {
console.log('added course is');
console.log(course);
addToBasket(course);
- setOpen(false);
+ handleCloseDropdown();
}
};
return (
-
-
-
- {open && (
-
- {filteredCourses.map(({ name, id }, index) => (
-
- {name}
-
- ))}
-
- )}
-
-
+
+ {open && (
+ <>
+ {filteredCourses.map(({ name, id }, index) => (
+
+ {name}
+
+ ))}
+ >
+ )}
+
);
-};
+});
diff --git a/src/components/Profile.tsx b/src/components/Profile.tsx
index cb97783..c50de4b 100644
--- a/src/components/Profile.tsx
+++ b/src/components/Profile.tsx
@@ -12,9 +12,8 @@ export const Profile = ({ anchorEl, handleClose }: ProfileProps) => {
return (
);
};
diff --git a/src/components/Rightbar.tsx b/src/components/Rightbar.tsx
index ec93536..66554f3 100644
--- a/src/components/Rightbar.tsx
+++ b/src/components/Rightbar.tsx
@@ -1,17 +1,14 @@
import React, { useContext } from 'react';
-import Snackbar from '@material-ui/core/Snackbar';
import { CourseCard } from './CourseCard';
import { coursesContext } from '../contexts/CoursesProvider';
-import MuiAlert, { AlertProps } from '@material-ui/lab/Alert';
import styled from 'styled-components';
-import { debounce } from "lodash";
+import { debounce } from 'lodash';
const RightbarStyled = styled.div`
padding-top: 10px;
padding-left: 15px;
padding-right: 15px;
text-align: center;
- font-family: Lato;
height: 100%;
width: 300px;
overflow-y: scroll;
@@ -25,40 +22,32 @@ const RightbarStyled = styled.div`
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
- background-color: #d4b851;
+ background-color: black;
border: 1px solid;
}
+ background-color: white;
+ border-radius: 5px;
+ box-shadow: 3px 3px 3px -2px rgba(0, 0, 0, 0.59);
`;
-const RightbarTextStyled = styled.div`
- display: flex;
- flex-direction: column;
-`;
-
const SaveButton = styled.div`
display: flex;
justify-content: center;
align-items: center;
- background-color: #417cab !important;
+ user-select: none;
+ background-color: #417cab;
border-radius: 10px;
cursor: pointer;
height: 40px;
- background-color: red;
margin-bottom: 10px;
&:hover {
color: white;
}
- box-shadow: 6px 6px 6px -2px rgba(0,0,0,0.59);
+ box-shadow: 6px 6px 6px -2px rgba(0, 0, 0, 0.59);
`;
-function Alert(props: AlertProps) {
- return ;
-}
-
export const Rightbar = () => {
const { courses, basket, saveBasket } = useContext(coursesContext)!;
- const [open, setOpen] = React.useState(false);
-
const getBasketGroups = () => {
const names = basket.map(({ name }) => name);
return courses.filter(({ name }) => names.includes(name));
@@ -66,38 +55,15 @@ export const Rightbar = () => {
const filteredCourses = getBasketGroups();
- const save = debounce(() => {
- saveBasket();
- setOpen(true);
- console.log("zmiana")
- },500);
-
- const handleClose = (event?: React.SyntheticEvent, reason?: string) => {
- if (reason === 'clickaway') {
- return;
- }
-
- setOpen(false);
- };
+ const handleSave = debounce(() => saveBasket(), 500);
//need to insert student name from db and course maybe based on current time or from db too
return (
-
-
- Hubert Wrzesiński
- Semestr zimowy 2020/2021
-
- ZAPISZ
-
+ ZAPISZ
{filteredCourses.map((course, index) => (
))}
-
-
- Zapisano plan!
-
-
);
};
diff --git a/src/components/Scheduler.tsx b/src/components/Scheduler.tsx
index 1db75bd..b37e12d 100644
--- a/src/components/Scheduler.tsx
+++ b/src/components/Scheduler.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, MouseEvent, useRef } from 'react';
+import React, { useEffect, MouseEvent, useRef, useCallback, useLayoutEffect } from 'react';
import { useState } from 'react';
import { SchedulerEvents } from './SchedulerEvents';
import { days, hours } from '../constants/index';
@@ -6,74 +6,93 @@ import styled from 'styled-components/macro';
const SchedulerWrapper = styled.div`
border-collapse: collapse;
- flex-grow: 1;
+ flex: 1;
+ background-color: white;
+ padding: 10px 40px 25px 10px;
+ border-radius: 5px;
+ margin-right: 20px;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ box-shadow: 3px 3px 3px -2px rgba(0, 0, 0, 0.59);
`;
const TableBody = styled.div`
+ position: relative;
width: 100%;
display: flex;
flex-direction: column;
+ height: calc(100% * 25 / 26);
`;
const TableRow = styled.div`
display: flex;
+ height: 100%;
`;
const TableHead = styled.div`
display: flex;
width: 100%;
+ height: calc(100% / 26);
`;
interface TableCellProps {
- height: number;
+ cellHeight?: number;
+ isHourColumn?: boolean;
}
const TableCell = styled.div`
- height: ${({ height }) => height}px;
- border: 1px solid #ddd;
+ border-width: ${({ isHourColumn }) => !isHourColumn && '2px'};
+ border-style: ${({ isHourColumn }) => !isHourColumn && 'none solid dotted none'};
+ border-color: rgb(242, 243, 245);
display: flex;
align-items: center;
- justify-content: center;
- flex: 1;
- font-size: 1.25vw;
-`;
-
-const T = styled.table`
- width: 100%;
- height: 100%;
+ justify-content: ${({ isHourColumn }) => (isHourColumn ? 'flex-end' : 'center')};
+ flex: ${({ isHourColumn }) => (isHourColumn ? '1' : '5')};
+ margin-right: ${({ isHourColumn }) => (isHourColumn ? '10px' : '0px')};
+ margin-top: ${({ isHourColumn, cellHeight }) => (isHourColumn ? `-${cellHeight}px` : '0px')};
+ font-size: 0.75vw;
+ user-select: none;
+ border-collapse: collapse;
+ :nth-child(2) {
+ border-left: 2px solid rgb(242, 243, 245);
+ }
+ font-weight: bold;
`;
export const Scheduler = () => {
const cellRef = useRef(null);
const [cellWidth, setCellWidth] = useState(0);
const [cellTop, setCellTop] = useState(0);
+ const [cellHeight, setCellHeight] = useState(0);
- const wrapperRef = useRef(null);
- const [wrapperHeight, setWrapperHeight] = useState(0);
+ console.log('cell height: ', cellHeight);
useEffect(() => {
const handleResize = () => {
- if (cellRef.current && wrapperRef.current) {
+ if (cellRef.current) {
setCellWidth(cellRef.current.getBoundingClientRect().width);
setCellTop(cellRef.current.getBoundingClientRect().top);
- setWrapperHeight(wrapperRef.current.getBoundingClientRect().height);
+ setCellHeight(cellRef.current.getBoundingClientRect().height);
+ cellRef.current.style.backgroundColor = 'blue';
}
};
handleResize();
window.addEventListener('resize', handleResize);
+ return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<>
-
+
{days.map((day, indexCell) =>
indexCell === 0 ? (
-
+
{day}
) : (
-
+
{day}
),
@@ -84,19 +103,31 @@ export const Scheduler = () => {
{[hour, '', '', '', '', ''].map((value, indexCell) =>
indexCell === 0 ? (
-
+
+ {value}
+
+ ) : indexRow === 0 && indexCell === 1 ? (
+
+ {value}
+
+ ) : indexRow === 23 ? (
+
+ {value}
+
+ ) : indexCell === 5 ? (
+ {value}
+ ) : indexRow % 2 !== 0 ? (
+
{value}
) : (
-
- {value}
-
+ {value}
),
)}
))}
+
-
>
);
diff --git a/src/components/SchedulerEvents.tsx b/src/components/SchedulerEvents.tsx
index da8c9db..75a7048 100644
--- a/src/components/SchedulerEvents.tsx
+++ b/src/components/SchedulerEvents.tsx
@@ -11,13 +11,10 @@ interface SchedulerEventsProps {
export const SchedulerEvents = ({ cellTop, cellWidth, cellHeight }: SchedulerEventsProps) => {
const { basket } = useContext(coursesContext)!;
-
+ console.log(`values: cellTop: ${cellTop}, cellWidth: ${cellWidth}, cellHeight: ${cellHeight}`);
const [choosenGroupsMappedToEvents, setChoosenGroupsMappedToEvents] = useState([]);
- interface GroupTimeToEventRowMapping {
- [time: string]: number;
- }
- const groupTimeToEventRowMapping: GroupTimeToEventRowMapping = {
+ const groupTimeToEventRowMapping: { [time: string]: number } = {
'8.15': 0,
'10.00': 1,
'11.45': 2,
@@ -33,7 +30,7 @@ export const SchedulerEvents = ({ cellTop, cellWidth, cellHeight }: SchedulerEve
const merged = [...classes, ...lectures];
//deleted if statement, maybe it is needed
- const groupsMapped = merged.map(({ id, day, lecturer, room, time, name,type }) => ({
+ const groupsMapped = merged.map(({ id, day, lecturer, room, time, name, type }) => ({
id,
day,
lecturer,
@@ -56,17 +53,17 @@ export const SchedulerEvents = ({ cellTop, cellWidth, cellHeight }: SchedulerEve
indexRow={index}
cellTop={
index === 0
- ? cellTop + (cellHeight + cellHeight * 2 * index + cellHeight / 4)
+ ? cellHeight / 2
: index === 1
- ? cellTop + (cellHeight + cellHeight * 2 * index)
+ ? cellHeight * 4
: index === 2
- ? cellTop + (cellHeight + cellHeight * 2 * index - cellHeight / 4)
+ ? cellHeight * 7.5
: index === 3
- ? cellTop + (cellHeight + cellHeight * 2 * index - cellHeight / 4)
+ ? cellHeight * 11.5
: index === 4
- ? cellTop + (cellHeight + cellHeight * 2 * index - cellHeight / 2)
+ ? cellHeight * 15
: index === 5
- ? cellTop + (cellHeight + cellHeight * 2 * index - (cellHeight * 3) / 4)
+ ? cellHeight * 18.5
: 0
}
cellWidth={cellWidth}
diff --git a/src/components/SchedulerRow.tsx b/src/components/SchedulerRow.tsx
index cb45953..5c0aced 100644
--- a/src/components/SchedulerRow.tsx
+++ b/src/components/SchedulerRow.tsx
@@ -1,4 +1,4 @@
-import React, { MouseEvent, useEffect, useState } from 'react';
+import React, { MouseEvent, useState } from 'react';
import { Group, GroupType } from '../types';
import styled from 'styled-components/macro';
import Popover from '@material-ui/core/Popover';
@@ -18,44 +18,41 @@ const useStyles = makeStyles((theme: Theme) =>
}),
);
-interface SchedulerEventProps {
+interface ClassesWrapperProps {
eventIndex: number;
cellTop: number;
cellWidth: number;
cellHeight: number;
}
-const SchedulerEvent = styled.div`
+const ClassesWrapper = styled.div`
position: absolute;
display: flex;
top: ${({ cellTop }) => cellTop}px;
- left: ${({ cellWidth, eventIndex }) => cellWidth + 5 + cellWidth * eventIndex}px;
- width: ${({ cellWidth }) => (cellWidth * 2.5) / 3}px;
- height: ${({ cellHeight }) => (cellHeight * 2 * 3) / 4}px;
+ left: ${({ cellWidth, eventIndex }) => (cellWidth * 1) / 5 + 15 + cellWidth * eventIndex}px;
+ width: ${({ cellWidth }) => cellWidth - 10}px;
+ height: ${({ cellHeight }) => cellHeight * 3}px;
z-index: 2;
+ padding-left: 10px;
`;
-interface ClassesProps{
- cellWidth: number;
+interface ClassesProps {
cellHeight: number;
groupType: GroupType;
}
const Classes = styled.div`
display: flex;
+ flex: 1;
justify-content: center;
align-items: center;
z-index: 2;
border-radius: 10px;
-
- font-size:0.90vw;
- /* background-color: rgb(100, 181, 246); */
- width: ${({ cellWidth }) => (cellWidth * 2.5) / 3}px;
- height: ${({ cellHeight }) => (cellHeight * 2 * 3) / 4}px;
+ height: ${({ cellHeight }) => cellHeight * 3}px;
margin-right: 5px;
- text-align: center;
- background-color:${({groupType})=>groupType === "CLASS" ? "#FFDC61" : "#A68820"};
- box-shadow: 9px 9px 8px -2px rgba(0,0,0,0.59);
+ text-align: left;
+ background-color: ${({ groupType }) => (groupType === 'CLASS' ? '#FFDC61' : '#9ed3ff')};
+ box-shadow: 9px 9px 8px -2px rgba(0, 0, 0, 0.59);
`;
interface SchedulerRowProps {
@@ -85,9 +82,9 @@ export const SchedulerRow = ({ groups, indexRow, cellTop, cellWidth, cellHeight
const open = Boolean(anchorEl);
return (
- <>
+
{[...Array(5)].map((_, eventIndex) => (
-
{
+ console.log('group: ', group);
+ }}
groupType={group.type}
- cellWidth={cellWidth}
cellHeight={cellHeight}
id={`eventRow${indexRow}eventCol${eventIndex}${index}`}
key={index}
@@ -110,11 +109,10 @@ export const SchedulerRow = ({ groups, indexRow, cellTop, cellWidth, cellHeight
onMouseEnter={(e) => handlePopoverOpen(e)}
onMouseLeave={handlePopoverClose}
>
-
- {groups[index].name}
-
- {groups[index].room}
-
+
+
{groups[index].name}
+
{groups[index].room}
+
),
)}
-
+
))}
- >
+
);
};
diff --git a/src/components/Topbar.tsx b/src/components/Topbar.tsx
index 1b2f0f5..a7789ff 100644
--- a/src/components/Topbar.tsx
+++ b/src/components/Topbar.tsx
@@ -1,80 +1,111 @@
-import React, { useState, MouseEvent } from 'react';
+import React, { useState, MouseEvent, ChangeEvent, useEffect } from 'react';
import Transfer from '../assets/transfer.png';
import Search from '../assets/search.svg';
-import UK from '../assets/UK.png';
-import PL from '../assets/PL.png';
-import User from '../assets/user.png';
-import CloseIcon from '../assets/close.svg';
+import { ReactComponent as Close } from '../assets/close.svg';
+import ProfileIcon from '../assets/account.svg';
import { Profile } from './Profile';
import { Dropdown } from './Dropdown';
-import styled from 'styled-components';
-
-const TopbarTextStyled = styled.div`
- @media only screen and (max-width: 670px) {
- display: none;
- }
-`;
+import PolishIcon from '../assets/poland.svg';
+import EnglishIcon from '../assets/united-kingdom.svg';
+import styled from 'styled-components/macro';
+import ClickAwayListener from 'react-click-away-listener';
const Topbar = styled.div`
- background-color: #ffdc61;
+ background-color: #E3E5ED;
height: 80px;
padding: 5px;
- font-family: comic sans MS;
font-size: 24px;
font-weight: bold;
display: flex;
justify-content: space-between;
`;
-const TopbarLogoWrapperStyled = styled.div`
+const LogoWrapper = styled.div`
display: flex;
- align-items: center;
- flex-grow: 0.5;
justify-content: flex-start;
+ align-items: center;
+ flex: 2;
+ margin-left: 10px;
`;
-const TopbarLogoStyled = styled.img`
- width: 80px;
- height: 80px;
+const Logo = styled.img`
+ width: 70px;
+ height: 70px;
@media only screen and (max-width: 670px) {
width: 60px;
height: 60px;
}
`;
-const TopbarInputStyled = styled.div`
- width: 70%;
+const Text = styled.div`
+ margin-left: 10px;
+ font-size: 1.4rem;
+ user-select: none;
+ @media only screen and (max-width: 670px) {
+ display: none;
+ }
+`;
+
+const FlexboxColumn = styled.div`
display: flex;
- flex-grow: 3;
+ flex-direction: column;
+ flex: 12;
`;
-const TopbarInputFieldStyled = styled.div`
- width: 96%;
- margin-top: 10px;
+const InputWrapper = styled.div`
+ display: flex;
+ margin-top: 15px;
+ background-color: #f2f4f7;
+ border-radius: 6px;
+ align-items: center;
`;
-const TopbarInputIconStyled = styled.img`
- width: 35px;
+const Input = styled.input`
+ background-color: #f1f2f5;
+ font-size: 20px;
+ height: 40px;
+ width: 100%;
+ border: none;
+ margin-left: 5px;
+ border-top-left-radius: 6px;
+ border-bottom-left-radius: 6px;
+ &:focus {
+ outline: none;
+ }
+`;
+
+const CloseIcon = styled(Close)`
+ width: 30px;
+ height: 30px;
+ margin-right: 5px;
@media only screen and (max-width: 670px) {
width: 25px;
}
cursor: pointer;
+ :hover {
+ fill: grey;
+ }
`;
-const TopbarIcon = styled.img`
- width: 50px;
+const IconWrapper = styled.div`
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ width: 335px;
+`;
+
+const Icon = styled.img`
+ width: 40px;
+ margin: 5px;
cursor: pointer;
@media only screen and (max-width: 670px) {
width: 35px;
}
`;
-const TopbarIconBox = styled.div`
- display: flex;
- align-items: center;
- justify-content: space-around;
- flex-grow: 1.5;
-`;
+
+
+
interface TopbarProps {
handleTransfer: (e: MouseEvent) => void;
@@ -84,6 +115,8 @@ export default function ({ handleTransfer }: TopbarProps) {
const [clearInput, setClearInput] = useState(false);
const [isPolish, setIsPolish] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
+ const [open, setOpen] = useState(false);
+ const [input, setInput] = useState('');
const onLangChange = () => setIsPolish(!isPolish);
@@ -93,25 +126,41 @@ export default function ({ handleTransfer }: TopbarProps) {
const handleClearInput = () => setClearInput(!clearInput);
+ const handleChange = (event: ChangeEvent) => setInput(event.target.value);
+
+ const handleClick = () => setOpen(true);
+
+ const handleCloseDropdown = () => setOpen(false);
+
+ const handleClickAway = () => setOpen(false);
+
+ useEffect(() => {
+ clearInput && (setInput(''), handleClearInput());
+ }, [clearInput]);
+
return (
-
-
- plan na plan
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ plan na plan
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Maciej Głowacki */}
+ {/* */}
+
+
-
+
);
}
diff --git a/src/components/Transfer.tsx b/src/components/Transfer.tsx
index 58442b4..4c542b4 100644
--- a/src/components/Transfer.tsx
+++ b/src/components/Transfer.tsx
@@ -53,7 +53,6 @@ const TransferReceiveStyled = styled.div`
`;
const TransferTextStyled = styled.div`
- font-family: Lato;
font-size: 30px;
margin-bottom: 10px;
`;
diff --git a/src/constants/index.ts b/src/constants/index.ts
index cd6753a..7898ca9 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -8,15 +8,30 @@ export const days = [
];
export const hours = [
"8:00",
+ "",
"9:00",
+ "",
"10:00",
+ "",
"11:00",
+ "",
"12:00",
+ "",
"13:00",
+ "",
"14:00",
+ "",
"15:00",
+ "",
"16:00",
+ "",
"17:00",
+ "",
"18:00",
+ "",
"19:00",
+ "",
];
+
+
+export const MONDAY_TO_FRIDAY = 5;
\ No newline at end of file
diff --git a/src/contexts/CoursesProvider.tsx b/src/contexts/CoursesProvider.tsx
index 56d7de7..29f2650 100644
--- a/src/contexts/CoursesProvider.tsx
+++ b/src/contexts/CoursesProvider.tsx
@@ -1,7 +1,8 @@
import React, { useState, createContext, useEffect, ReactNode, useContext } from 'react';
import { Course, Group, Basket, GroupType } from '../types';
import axios from 'axios';
-import { CASContext, CASProvider } from './CASProvider';
+import { CASContext } from './CASProvider';
+import { useSnackbar } from 'notistack';
interface CourseContext {
courses: Array;
@@ -22,44 +23,73 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
const [courses, setCourses] = useState>([]);
const [basket, setBasket] = useState>([]);
+ const { enqueueSnackbar } = useSnackbar();
+ const { closeSnackbar } = useSnackbar();
+
const CAS = useContext(CASContext)!;
const token = CAS?.user?.token;
+ const selectBasketIds = (basket: Array) => {
+ const classesIds = basket.map((course) => course.classes.id);
+ const lecturesIds = basket.map((course) => course?.lecture?.id);
+
+ return lecturesIds[0] === undefined ? classesIds : [...classesIds, ...lecturesIds];
+ };
+
const addToBasket = (course: Course) => {
- const courseToBasket = {
+ const courseToBasket: Basket = {
name: course.name,
id: course.id,
classes: course.classes[0],
lecture: course.lectures !== undefined ? course.lectures[0] : undefined,
- } as Basket;
+ };
setBasket([...basket, courseToBasket]);
};
+
const deleteFromBasket = (id: number) => setBasket(basket.filter((course) => course.id !== id));
const saveBasket = async () => {
+ const basketIds = selectBasketIds(basket);
+
+ const config = {
+ method: 'post' as const,
+ url: `${process.env.REACT_APP_API_URL}/api/v1/commisions/add?`,
+ headers: {
+ Authorization: `Bearer ${token}`,
+ 'Content-Type': 'application/json',
+ },
+ data: JSON.stringify(basketIds),
+ };
+
+ const action = (key: any) => (
+ <>
+
+ >
+ );
+
try {
- let data = [7, 43, 54];
- let json = JSON.stringify(data);
- let post_data = { json_data: json };
- const ech = await axios.post>(
- `${process.env.REACT_APP_API_URL}/api/v1/commisions/add?`,
- [7, 43, 54],
- {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- },
- );
- console.log('api response;', ech);
+ await axios.request(config);
+ enqueueSnackbar('Plan został zapisany', {
+ variant: 'success',
+ action,
+ });
} catch (e) {
- console.log(e);
+ enqueueSnackbar('Zapisywanie planu nie powiodło się', {
+ variant: 'error',
+ action,
+ });
}
- console.log('saving to basket');
};
const addGroup = (choosenGroup: Group, id: number) => {
const basketCourse = basket.filter((course) => course.id === id)[0];
- const type = choosenGroup.type;
+ const { type } = choosenGroup;
if (type === GroupType.CLASS) {
setBasket(
basket.map((basket) => (basket.id === basketCourse.id ? { ...basket, classes: choosenGroup } : basket)),
@@ -71,23 +101,43 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
}
};
- useEffect(() => {
- const fetchData = async () => {
- const { data } = await axios.get }>>(
+ const getNewestTimetable = async () => {
+ const config = {
+ method: 'get' as const,
+ url: `${process.env.REACT_APP_API_URL}/api/v1/assignments/getCurrentAssignments`,
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ };
+ try {
+ let { data: basket } = await axios.request(config);
+ if (basket === '') {
+ basket = [];
+ }
+ setBasket(basket);
+ } catch (e) {
+ console.log(e);
+ }
+ };
+
+ const fetchClasses = async () => {
+ try {
+ const { data: courses } = await axios.get>(
`${process.env.REACT_APP_API_URL}/api/v1/courses/getCoursesWithGroups`,
);
- const courses = data.map(({ id, name, groups }) => ({
- id: parseInt(id),
- name,
- lectures: groups.filter(({ type }) => type === GroupType.LECTURE),
- classes: groups.filter(({ type }) => type === GroupType.CLASS),
- })) as Array;
- courses.sort((a: Course, b: Course) => (a.name > b.name ? 1 : -1));
-
+ courses.sort((a, b) => (a.name > b.name ? 1 : -1));
setCourses(courses);
- };
- fetchData();
- }, []);
+ } catch (e) {
+ console.log(e);
+ }
+ };
+
+ useEffect(() => {
+ fetchClasses();
+ if (token) {
+ getNewestTimetable();
+ }
+ }, [token]);
return (
diff --git a/src/index.tsx b/src/index.tsx
index d3ecd06..0e9ee27 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -4,15 +4,24 @@ import { App } from './components/App';
import { CASProvider } from './contexts/CASProvider';
import { CoursesProvider } from './contexts/CoursesProvider';
import { GlobalStyles } from './styles/GlobalStyles';
+import { SnackbarProvider } from 'notistack';
ReactDOM.render(
<>
-
-
-
-
-
-
+
+
+
+
+
+
+
+
>,
document.getElementById('root'),
);
diff --git a/src/styles/GlobalStyles.ts b/src/styles/GlobalStyles.ts
index 4f68eaa..91281b6 100644
--- a/src/styles/GlobalStyles.ts
+++ b/src/styles/GlobalStyles.ts
@@ -11,7 +11,7 @@ export const GlobalStyles = createGlobalStyle`
margin: 0;
padding: 0;
line-height: 24px;
-
+ font-family: 'Roboto', sans-serif;
}
body::-webkit-scrollbar {