diff --git a/.env b/.env index c62b767..529f1dd 100644 --- a/.env +++ b/.env @@ -1,2 +1 @@ -REACT_APP_API_URL=http://localhost:5000/api -REACT_APP_API_HOST=http://localhost:5000 \ No newline at end of file +REACT_APP_API_URL=http://localhost:1285 \ No newline at end of file diff --git a/src/components/App.tsx b/src/components/App.tsx index 8a62321..3194e91 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -2,7 +2,7 @@ import React, { useState, useContext } from 'react'; import { Topbar } from './Topbar'; import { Transfer } from './Transfer/Transfer'; import { Scheduler } from './Scheduler'; -import RightBar from './Rightbar'; +import { Rightbar } from './Rightbar'; import { CASContext } from '../contexts/CASProvider'; import styled from 'styled-components'; @@ -13,7 +13,6 @@ const Wrapper = styled.div` export const App = () => { const [isOpenTransfer, setOpenTransfer] = useState(false); - const { logout } = useContext(CASContext)!; const handleTransfer = () => { setOpenTransfer(!isOpenTransfer); @@ -21,11 +20,11 @@ export const App = () => { return ( <> - + - + ); diff --git a/src/components/CourseCard.tsx b/src/components/CourseCard.tsx index 1b85153..eb54f2f 100644 --- a/src/components/CourseCard.tsx +++ b/src/components/CourseCard.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React, { useContext, MouseEvent } from 'react'; import Collapse from '@material-ui/core/Collapse'; import ExpandIcon from '../assets/expand.png'; import { Course, Group } from '../types/index'; @@ -10,7 +10,7 @@ interface ClassExandIconProps { isSelected: boolean; } -const ClassStyled = styled.div` +const CourseStyled = styled.div` display: flex; min-height: 50px; background-color: rgb(100, 181, 246) !important; @@ -25,7 +25,7 @@ const ClassStyled = styled.div` align-items: stretch; `; -const ClassNameStyled = styled.div` +const CourseNameStyled = styled.div` padding-top: 10px; padding-bottom: 10px; `; @@ -68,39 +68,38 @@ const useStyles = makeStyles({ }); interface CourseCardProps { - onCardClick: (e: React.MouseEvent) => void; + onCardClick: (event: MouseEvent) => void; course: Course; id: string; isSelected: boolean; } -export function CourseCard({ onCardClick, course, id, isSelected }: CourseCardProps) { +export const CourseCard = ({ onCardClick, course, id, isSelected }: CourseCardProps) => { const classes = useStyles(); - const { addGroup, courses } = useContext(coursesContext)!; - function onGroupClick(group: Group) { - addGroup(group); - } + const { addChoosenGroup, choosenCourses } = useContext(coursesContext)!; + + const onGroupClick = (group: Group) => addChoosenGroup(group); return ( - - {course.name} + + {course.name} - {courses.map((course, index) => ( - <> + {choosenCourses.map((course) => ( +
{course.groups.map((group, index) => ( onGroupClick(group)}>

{group.time} {group.room}

{group.lecturer} -

{' '} +

))} - +
))}
-
+ ); -} +}; diff --git a/src/components/Dropdown.tsx b/src/components/Dropdown.tsx new file mode 100644 index 0000000..d266b2a --- /dev/null +++ b/src/components/Dropdown.tsx @@ -0,0 +1,110 @@ +import React, { useState, useContext, useEffect, MouseEvent } from 'react'; +import axios from 'axios'; +import { Input } from '@material-ui/core'; +import ClickAwayListener from '@material-ui/core/ClickAwayListener'; +import { coursesContext } from '../contexts/CoursesProvider'; +import { Course } from '../types'; +import styled from 'styled-components'; +import { makeStyles } from '@material-ui/core/styles'; + +const CourseStyled = styled.div` + position: relative; + z-index: 10; + padding: 5px; + padding-left: 20px; + background-color: #e6c759; + font-size: 18px; + font-family: Lato; + :hover { + background-color: #d4b851; + cursor: pointer; + } +`; + +const DropdownStyled = styled.div` + max-height: 400px; + overflow-y: auto; + ::-webkit-scrollbar { + display: none; + } +`; + +const useStyles = makeStyles({ + topbarInput: { + marginTop: '8px', + width: '100%', + }, +}); + +export const Dropdown = () => { + const classes = useStyles(); + + const [open, setOpen] = React.useState(false); + const [input, setInput] = useState(''); + + //courses - choosenCourses + const [filteredCourses, setFilteredCourses] = useState>([]); + + const { courses, choosenCourses, addChoosenCourse } = useContext(coursesContext)!; + + useEffect(() => { + const filterCourses = (input: string) => { + const choosenCoursesNames = choosenCourses.map(({ name }) => name.trim()); + const filteredCourses = courses.filter( + ({ name }) => name.toLowerCase().includes(input.toLowerCase()) && !choosenCoursesNames.includes(name), + ); + setFilteredCourses(filteredCourses); + }; + filterCourses(input); + }, [input, open, choosenCourses]); + + const handleChange = (event: React.ChangeEvent) => setInput(event.target.value); + + const handleClick = () => setOpen(true); + + const handleClickAway = () => setOpen(false); + + const onCourseClick = async (event: MouseEvent) => { + const target = event.currentTarget; + if (target.id && target.textContent) { + const id = target.id; + const name = target.textContent; + + const { data } = await axios.get(`${process.env.REACT_APP_API_URL}/getCourseGroups?id=${id}`); + + //porozmawiać z Filipem, żeby odrobinę przerobił endpoint + const course: Course = { + name: name, + id: parseInt(id), + groups: data, + }; + + addChoosenCourse(course); + setOpen(false); + } + }; + + return ( + +
+ + {open && ( + + {filteredCourses.map(({ name, id }, index) => ( + +

{name}

+
+ ))} +
+ )} +
+
+ ); +}; diff --git a/src/components/Profile.tsx b/src/components/Profile.tsx index ea05cc0..cb97783 100644 --- a/src/components/Profile.tsx +++ b/src/components/Profile.tsx @@ -1,31 +1,20 @@ import { Menu, MenuItem } from '@material-ui/core'; -import React, { FC } from 'react'; +import React, { useContext } from 'react'; +import { CASContext } from '../contexts/CASProvider'; interface ProfileProps { anchorEl: HTMLElement | null; handleClose: () => void; - handleLogout: () => void; } -export const Profile: FC = ({ anchorEl, handleClose, handleLogout, ...restProps }) => { +export const Profile = ({ anchorEl, handleClose }: ProfileProps) => { + const { logout } = useContext(CASContext)!; + return ( - + Profile My account - { - handleLogout(); - }} - > - Logout - + Logout ); }; diff --git a/src/components/Results.tsx b/src/components/Results.tsx deleted file mode 100644 index 31d8655..0000000 --- a/src/components/Results.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import React, { useState, useContext, useEffect } from 'react'; -import axios from 'axios'; -import { Input } from '@material-ui/core'; -import ClickAwayListener from '@material-ui/core/ClickAwayListener'; -import { coursesContext } from '../contexts/CoursesProvider'; -import { Course } from '../types'; -import styled from 'styled-components'; -import { makeStyles } from '@material-ui/core/styles'; - -interface courseData { - name: string; - id: number; -} - -const CourseStyled = styled.div` - position: relative; - z-index: 10; - padding: 5px; - padding-left: 20px; - background-color: #e6c759; - font-size: 18px; - font-family: Lato; - :hover { - background-color: #d4b851; - cursor: pointer; - } -`; - -const Dropdown = styled.div` - max-height: 400px; - overflow-y: auto; - ::-webkit-scrollbar { - display: none; - } -`; - -const useStyles = makeStyles({ - topbarInput: { - marginTop: '8px', - width: '100%', - }, -}); - -export const Results: React.FC = () => { - const classes = useStyles(); - const [input, setInput] = useState(''); - const [coursesData, setcoursesData] = useState>([]); - const [filteredcoursesData, setFilteredcoursesData] = useState>([]); - const [open, setOpen] = React.useState(false); - - const { courses, addCourse } = useContext(coursesContext)!; - - useEffect(() => { - const fetchData = async () => { - const results = await axios.get(`http://localhost:1285/getCourses`); - const coursesData = results.data.map((result: { id: number; name: string }) => ({ - id: result.id, - name: result.name, - })); - - setcoursesData(coursesData); - }; - fetchData(); - }, []); - - useEffect(() => { - const names = courses.map((course) => course.name); - const filtercourses = (value: string) => { - let filteredcourses = coursesData.filter( - (course) => course.name.toLowerCase().includes(value.toLowerCase()) && !names.includes(course.name), - ); - setFilteredcoursesData(filteredcourses); - }; - filtercourses(input); - }, [input, open]); - - const getGroupsByCourseId = async (id: string) => { - const { data } = await axios.get(`http://localhost:1285/getCourseGroups?id=${id}`); - return data; - }; - - const handleChange = (event: React.ChangeEvent) => { - setInput(event.target.value); - }; - - const handleClick = () => { - setOpen(true); - }; - - const handleClickAway = () => { - setOpen(false); - }; - - const onCourseClick = async (e: React.MouseEvent) => { - const target = e.currentTarget as HTMLElement; - if (target.id && target.textContent) { - const id = target.id; - const name = target.textContent; - const groups = await getGroupsByCourseId(id); - const course: Course = { - name: name, - id: parseInt(id), - groups: groups, - }; - addCourse(course); - setOpen(false); - } - - // let groups: Array = []; - // let course = { groups: groups } as course; - // course.id = result[0].course.id; - // course.name = result[0].course.name; - // for (let i = 0; i < result.length; i++) { - // let group = {} as Group; - // group.id = result[i].id; - // group.day = result[i].day; - // group.time = result[i].time; - // group.courser = result[i].courser.title + ' ' + result[i].courser.name + ' ' + result[i].courser.surname; - // group.room = result[i].room.trim(); - // course.groups.push(group); - // } - }; - - return ( - -
- - {open ? ( - - {filteredcoursesData.map((course, index) => ( - -

{course.name}

-
- ))} -
- ) : null} -
-
- ); -}; diff --git a/src/components/Rightbar.tsx b/src/components/Rightbar.tsx index a3d7e51..a39fee6 100644 --- a/src/components/Rightbar.tsx +++ b/src/components/Rightbar.tsx @@ -1,4 +1,4 @@ -import React, { useState, useContext } from 'react'; +import React, { useState, useContext, MouseEvent } from 'react'; import { CourseCard } from './CourseCard'; import { coursesContext } from '../contexts/CoursesProvider'; import styled from 'styled-components'; @@ -30,23 +30,25 @@ const RightbarTextStyled = styled.div` border-bottom: 1px solid; `; -export default function Rightbar() { +export const Rightbar = () => { const [selectedCardId, setSelectedCardId] = useState(null); - const { courses } = useContext(coursesContext)!; + const { choosenCourses } = useContext(coursesContext)!; - const onCardClick = (e: React.MouseEvent) => { - const target = e.currentTarget as HTMLElement; + //działa clunky + const onCardClick = (event: MouseEvent) => { + const target = event.currentTarget; selectedCardId === target.id ? setSelectedCardId(null) : setSelectedCardId(target.id); }; + //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
- {courses.map((course, index) => ( + {choosenCourses.map((course, index) => ( ); -} +}; diff --git a/src/components/Scheduler.tsx b/src/components/Scheduler.tsx index 8d31ff9..a4f851a 100644 --- a/src/components/Scheduler.tsx +++ b/src/components/Scheduler.tsx @@ -1,8 +1,8 @@ -import React, { useEffect, useRef } from "react"; -import { useState } from "react"; -import { SchedulerEvents } from "./SchedulerEvents"; -import { days, hours } from "../constants/index"; -import styled from "styled-components"; +import React, { useEffect, useRef } from 'react'; +import { useState } from 'react'; +import { SchedulerEvents } from './SchedulerEvents'; +import { days, hours } from '../constants/index'; +import styled from 'styled-components'; const SchedulerWrapper = styled.div` flex-grow: 3; @@ -55,7 +55,7 @@ export const Scheduler = () => { } }; handleResize(); - window.addEventListener("resize", handleResize); + window.addEventListener('resize', handleResize); }, []); useEffect(() => { @@ -63,7 +63,7 @@ export const Scheduler = () => { currentEventsIds.map((eventId: string) => { const event = document.getElementById(eventId); if (event) { - event.style.display = "block"; + event.style.display = 'block'; } }); }; @@ -90,15 +90,12 @@ export const Scheduler = () => { {hours.map((hour, indexRow) => ( - {[hour, "", "", "", "", ""].map((value, indexCell) => + {[hour, '', '', '', '', ''].map((value, indexCell) => indexRow === 0 && indexCell === 1 ? ( - + ) : ( {value} - ) + ), )} ))} diff --git a/src/components/SchedulerEvents.tsx b/src/components/SchedulerEvents.tsx index 0a635fb..8687e29 100644 --- a/src/components/SchedulerEvents.tsx +++ b/src/components/SchedulerEvents.tsx @@ -13,14 +13,10 @@ export const SchedulerEvents = ({ cellTop, cellWidth }: SchedulerEventsProps) => const [groupsMappedToEvents, setGroupsMappedToEvents] = useState([]); - // const groups: Array = [{ id: "5", day: "4", time: "11.45", courser: "dr Dorota Blinkiewicz", room: "A2-3" }, - // { id: "28", day: "1", time: "13.45", courser: "dr Barbara Kołodziejczak", room: "D-3" }, - // { id: "69", day: "4", time: "15.30", courser: "dr Karol Gierszewski", room: "A2-3" }]; - interface GroupTimeToEventRowMapping { [time: string]: number; } - + //delete later additional mappings const groupTimeToEventRowMapping: GroupTimeToEventRowMapping = { '08.15': 0, '10.00': 1, @@ -28,6 +24,8 @@ export const SchedulerEvents = ({ cellTop, cellWidth }: SchedulerEventsProps) => '13.45': 3, '15.30': 4, '17.15': 5, + '10.17': 0, + '13.55': 1, }; useEffect(() => { @@ -45,23 +43,20 @@ export const SchedulerEvents = ({ cellTop, cellWidth }: SchedulerEventsProps) => }; setGroupsMappedToEvents((groupsMappedToEvents: any) => [...groupsMappedToEvents, groupMappedToEvent]); } - function alternative(groups: Array) { - const groupsMapped = choosenGroups.map(({ id, day, lecturer, room, time }) => ({ - id, - day, - lecturer, - room, - eventRow: groupTimeToEventRowMapping[time], - })); - setGroupsMappedToEvents(groupsMapped); - } } - mapGroupTimeToEventRow(choosenGroups); + function alternative(choosenGroups: Array) { + const groupsMapped = choosenGroups.map(({ id, day, lecturer, room, time }) => ({ + id, + day, + lecturer, + room, + eventRow: groupTimeToEventRowMapping[time], + })); + setGroupsMappedToEvents(groupsMapped); + } + alternative(choosenGroups); }, [choosenGroups]); - useEffect(() => { - }, [groupsMappedToEvents]); - return (
{[...Array(6)].map((_, index) => ( diff --git a/src/components/SchedulerRow.tsx b/src/components/SchedulerRow.tsx index 94cf8b7..e01227b 100644 --- a/src/components/SchedulerRow.tsx +++ b/src/components/SchedulerRow.tsx @@ -26,8 +26,8 @@ interface SchedulerRowProps { } export const SchedulerRow = ({ groups, indexRow, cellTop, cellWidth }: SchedulerRowProps) => { - console.log(`You passed me these of a groupzzz`); - console.log(groups) + // console.log(`You passed me these of a groupzzz`); + // console.log(groups) return ( <> diff --git a/src/components/Topbar.tsx b/src/components/Topbar.tsx index 0aa2742..62a14de 100644 --- a/src/components/Topbar.tsx +++ b/src/components/Topbar.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, MouseEvent } from 'react'; import Transfer from '../assets/transfer.png'; import Search from '../assets/search.svg'; import UK from '../assets/UK.png'; @@ -6,7 +6,7 @@ import PL from '../assets/PL.png'; import User from '../assets/user.png'; import CloseIcon from '../assets/close.svg'; import { Profile } from './Profile'; -import { Results } from './Results'; +import { Dropdown } from './Dropdown'; import styled from 'styled-components'; const TopbarTextStyled = styled.div` @@ -26,14 +26,14 @@ const TopbarStyled = styled.div` justify-content: space-between; `; -const TopbarLogoStyled = styled.div` +const TopbarLogoWrapperStyled = styled.div` display: flex; align-items: center; flex-grow: 0.5; justify-content: flex-start; `; -const TopbarLogoImageStyled = styled.img` +const TopbarLogoStyled = styled.img` width: 80px; height: 80px; @media only screen and (max-width: 670px) { @@ -42,7 +42,7 @@ const TopbarLogoImageStyled = styled.img` } `; -const TopbarInputDivStyled = styled.div` +const TopbarInputStyled = styled.div` width: 70%; display: flex; flex-grow: 3; @@ -76,38 +76,37 @@ const TopbarIconBox = styled.div` `; interface TopbarProps { - handleTransfer: (e: React.MouseEvent) => void; - handleLogout: () => void; + handleTransfer: (e: MouseEvent) => void; } -export const Topbar = ({ handleTransfer, handleLogout }: TopbarProps) => { +export const Topbar = ({ handleTransfer }: TopbarProps) => { const [isPolish, setIsPolish] = useState(false); const [anchorEl, setAnchorEl] = useState(null); - const onLangChange = (event: React.MouseEvent) => setIsPolish(!isPolish); + const onLangChange = () => setIsPolish(!isPolish); - const handleProfile = (event: React.MouseEvent) => setAnchorEl(event.currentTarget as HTMLImageElement); + const handleProfile = (event: MouseEvent) => setAnchorEl(event.currentTarget); const handleClose = () => setAnchorEl(null); return ( - - + + plan na plan - - + + - + - + - + ); diff --git a/src/contexts/CASProvider.tsx b/src/contexts/CASProvider.tsx index a46f549..a983aff 100644 --- a/src/contexts/CASProvider.tsx +++ b/src/contexts/CASProvider.tsx @@ -27,7 +27,6 @@ export const CASProvider = ({ children }: CASProviderProps) => { redirectToCASLoginService(); } if (ticket) { - console.log(`Ticket is: ${ticket}`); setUser({ ...user, ticket: ticket }); } } diff --git a/src/contexts/CoursesProvider.tsx b/src/contexts/CoursesProvider.tsx index 6993e93..27772ec 100644 --- a/src/contexts/CoursesProvider.tsx +++ b/src/contexts/CoursesProvider.tsx @@ -1,13 +1,14 @@ import React, { useState, createContext, useEffect } from 'react'; import { Course, Group } from '../types'; - -interface courseContext { +import axios from 'axios'; +interface CourseContext { courses: Array; + choosenCourses: Array; choosenGroups: Array; - addCourse: (courses: Course) => void; - addGroup: (group: Group) => void; + addChoosenCourse: (courses: Course) => void; + addChoosenGroup: (group: Group) => void; } -export const coursesContext = createContext(null); +export const coursesContext = createContext(null); interface CoursesProviderProps { children: React.ReactNode; @@ -15,17 +16,36 @@ interface CoursesProviderProps { export const CoursesProvider = ({ children }: CoursesProviderProps) => { const [courses, setCourses] = useState>([]); + const [choosenCourses, setChoosenCourses] = useState>([]); const [choosenGroups, setChoosenGroups] = useState>([]); - const addCourse = (course: Course) => { - setCourses([...courses, course]); + const addChoosenCourse = (choosenCourse: Course) => { + console.log('adding course'); + setChoosenCourses([...choosenCourses, choosenCourse]); }; - const addGroup = (group: Group) => { - setChoosenGroups([...choosenGroups, group]); + const addChoosenGroup = (choosenGroup: Group) => { + setChoosenGroups([...choosenGroups, choosenGroup]); }; + useEffect(() => { + console.log('All courses'); + console.log(courses); + }, [courses]); + useEffect(() => { + console.log('Choosen courses'); + console.log(choosenCourses); + }, [choosenCourses]); + + useEffect(() => { + const fetchData = async () => { + const { data } = await axios.get(`${process.env.REACT_APP_API_URL}/getCourses`); + setCourses(data); + }; + fetchData(); + }, []); + return ( - + {children} ); diff --git a/src/styles/reducers.ts b/src/contexts/reducers.ts similarity index 56% rename from src/styles/reducers.ts rename to src/contexts/reducers.ts index c936812..b3f9ccb 100644 --- a/src/styles/reducers.ts +++ b/src/contexts/reducers.ts @@ -1,6 +1,6 @@ export enum Types { - addCourse = 'ADD_COURSE', + addChoosenCourse = 'ADD_COURSE', removecourse = 'REMOVE_COURSE', - addGroup = 'ADD_GROUP', + addChoosenGroup = 'ADD_GROUP', removeGroup = 'REMOVE_GROUP', }