Major refactoring
This commit is contained in:
14
src/App.scss
14
src/App.scss
@ -1,14 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.wraper{
|
||||
display: flex;
|
||||
&__calendar{
|
||||
flex-grow: 3;
|
||||
}
|
||||
}
|
||||
|
85
src/App.tsx
85
src/App.tsx
@ -1,55 +1,40 @@
|
||||
import React, { useState } from "react";
|
||||
import TopBar from "./components/TopBar/";
|
||||
import Transfer from "./components/Transfer/";
|
||||
import "./App.scss";
|
||||
import {Scheduler} from "./components/Scheduler";
|
||||
import RightBar from "./components/RightBar";
|
||||
import { lectures } from "./businesslogic/mockData/lectures";
|
||||
import React, { useState, useContext } from 'react';
|
||||
import TopBar from './components/TopBar/';
|
||||
import Transfer from './components/Transfer/';
|
||||
import { Scheduler } from './components/Scheduler';
|
||||
import RightBar from './components/RightBar';
|
||||
import { CASContext } from './contexts/CASProvider';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import BusinessLogicContext from "./businesslogic/BusinessLogicContext";
|
||||
import { BuisnessProvided } from "./businesslogic/BusinessLogicProvider";
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
function App() {
|
||||
const [isOpenTransfer, setOpenTransfer] = useState(false);
|
||||
export const App = () => {
|
||||
const [isOpenTransfer, setOpenTransfer] = useState(false);
|
||||
|
||||
const { logout } = useContext(CASContext)!;
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<BusinessLogicContext.Consumer>
|
||||
{(context) => (
|
||||
<TopBar
|
||||
handleTransfer={(e) => {
|
||||
setOpenTransfer(!isOpenTransfer);
|
||||
}}
|
||||
onLangChange={(e) => {
|
||||
console.log(e);
|
||||
}}
|
||||
handleLogout={() => {
|
||||
(context as BuisnessProvided).reducers.userlogout();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</BusinessLogicContext.Consumer>
|
||||
<Transfer
|
||||
isOpen={isOpenTransfer}
|
||||
handleClose={(e) => {
|
||||
setOpenTransfer(!isOpenTransfer);
|
||||
}}
|
||||
/>
|
||||
<div className="wraper">
|
||||
<div className="wraper__calendar">
|
||||
<Scheduler />
|
||||
</div>
|
||||
<div className="wraper__rightbar">
|
||||
<RightBar
|
||||
lectures={lectures}
|
||||
onGroupMouseOver={(id, name) => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const handleCloseTransfer = () => {
|
||||
setOpenTransfer(!isOpenTransfer);
|
||||
};
|
||||
|
||||
export default App;
|
||||
const onLangChange = () => {
|
||||
console.log('Language changed');
|
||||
};
|
||||
|
||||
const onGroupMouseOver = () => {
|
||||
console.log(`On groupmouse over`);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<TopBar handleTransfer={handleCloseTransfer} onLangChange={onLangChange} handleLogout={logout} />
|
||||
<Transfer isOpen={isOpenTransfer} handleClose={handleCloseTransfer} />
|
||||
<Wrapper>
|
||||
<Scheduler />
|
||||
<RightBar onGroupMouseOver={onGroupMouseOver} />
|
||||
</Wrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,5 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
const BusinessLogicContext = React.createContext({});
|
||||
|
||||
export default BusinessLogicContext;
|
@ -1,76 +0,0 @@
|
||||
import BusinessLogicContext from "./BusinessLogicContext";
|
||||
import React, { Component } from "react";
|
||||
import { User } from "./types/user";
|
||||
|
||||
export interface BuisnessProvided {
|
||||
states: BusinessState;
|
||||
reducers: {
|
||||
userlogout: () => void;
|
||||
};
|
||||
}
|
||||
|
||||
interface BusinessState {
|
||||
user: User | null;
|
||||
}
|
||||
|
||||
interface Props {}
|
||||
|
||||
class BusinessLogicProvider extends Component<Props, BusinessState> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
user: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.login();
|
||||
}
|
||||
|
||||
login() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const ticket = urlParams.get("ticket");
|
||||
|
||||
if (!ticket) {
|
||||
this.redirectToCASLoginService();
|
||||
}
|
||||
if (ticket) {
|
||||
this.setState({ user: { ticket } });
|
||||
}
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.redirectToCASLogoutService();
|
||||
}
|
||||
|
||||
redirectToCASLogoutService() {
|
||||
window.location.replace(
|
||||
`https://cas.amu.edu.pl/cas/logout?service=${window.origin}`
|
||||
);
|
||||
}
|
||||
|
||||
redirectToCASLoginService() {
|
||||
window.location.replace(
|
||||
`https://cas.amu.edu.pl/cas/login?service=${window.origin}&locale=pl`
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<BusinessLogicContext.Provider
|
||||
value={{
|
||||
states: this.state,
|
||||
reducers: {
|
||||
userlogout: () => {
|
||||
this.logout();
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{this.props.children}
|
||||
</BusinessLogicContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BusinessLogicProvider;
|
@ -1,33 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { Lecture } from "./types/lecture";
|
||||
import { Group } from "./types/group";
|
||||
interface ILectureContext {
|
||||
lectures: Array<Lecture>;
|
||||
addLecture: (lectures: Lecture) => void;
|
||||
}
|
||||
export const LecturesContext = React.createContext({
|
||||
lectures: Array<Lecture>(),
|
||||
choosenGroups: Array<Group>(),
|
||||
addLecture: (lecture: Lecture) => {},
|
||||
addGroup: (group : Group) => {}
|
||||
});
|
||||
|
||||
export const LecturesProvider: React.FC = (props) => {
|
||||
const [lectures, setLectures] = useState<Array<Lecture>>([]);
|
||||
const [choosenGroups, setChoosenGroups] = useState<Array<Group>>([]);
|
||||
const addLecture = (lecture: Lecture) => {
|
||||
setLectures([...lectures, lecture]);
|
||||
};
|
||||
const addGroup = (group : Group) => {
|
||||
setChoosenGroups([...choosenGroups, group]);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<LecturesContext.Provider
|
||||
value={{ lectures, choosenGroups, addLecture, addGroup }}
|
||||
>
|
||||
{props.children}
|
||||
</LecturesContext.Provider>
|
||||
);
|
||||
};
|
@ -1,42 +0,0 @@
|
||||
import { Lecture } from "../types/lecture";
|
||||
|
||||
export const lectures: Array<Lecture> = [
|
||||
{
|
||||
name: "E-gospodarka - narzędzia i bezpieczeństwo",
|
||||
groups: [
|
||||
{
|
||||
id: "1CB",
|
||||
day: "Pn",
|
||||
time: "10:00",
|
||||
lecturer: "dr inż. Michał Ren",
|
||||
room: "A2-01",
|
||||
},
|
||||
{
|
||||
id: "1XD",
|
||||
day: "Wt",
|
||||
time: "12:00",
|
||||
lecturer: "dr inż. Michał Ren",
|
||||
room: "A3-01",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Statystyka",
|
||||
groups: [
|
||||
{
|
||||
id: "2CB",
|
||||
day: "Pn",
|
||||
time: "10:00",
|
||||
lecturer: "dr inż. Michał Ren",
|
||||
room: "A2-01",
|
||||
},
|
||||
{
|
||||
id: "2XD",
|
||||
day: "Wt",
|
||||
time: "12:00",
|
||||
lecturer: "dr inż. Michał Ren",
|
||||
room: "A3-01",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
@ -1,7 +0,0 @@
|
||||
export interface Group {
|
||||
id: string;
|
||||
day: string;
|
||||
time: string;
|
||||
lecturer: string;
|
||||
room: string;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import { Group } from "./group";
|
||||
|
||||
export interface Lecture {
|
||||
id?: number;
|
||||
name: string;
|
||||
groups: Array<Group>;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export interface LectureInit {
|
||||
name: string;
|
||||
id: number;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
export interface User {
|
||||
name?: string;
|
||||
surname?: string;
|
||||
ticket: string | null;
|
||||
};
|
@ -1,10 +1,9 @@
|
||||
import React, {useContext} from "react";
|
||||
import "./index.scss";
|
||||
import Collapse from "@material-ui/core/Collapse";
|
||||
import ExpandIcon from "./expand.png";
|
||||
import { Lecture } from "../../../businesslogic/types/lecture";
|
||||
import { Group } from "../../../businesslogic/types/group";
|
||||
import { LecturesContext } from "../../../businesslogic/LecturesProvider";
|
||||
import React, { useContext } from 'react';
|
||||
import './index.scss';
|
||||
import Collapse from '@material-ui/core/Collapse';
|
||||
import ExpandIcon from './expand.png';
|
||||
import { Lecture, Group } from '../../../types/index';
|
||||
import { LecturesContext } from '../../../contexts/LecturesProvider';
|
||||
|
||||
interface LectureCardProps {
|
||||
onGroupMouseOver: (id: string, name: string) => void;
|
||||
@ -14,31 +13,17 @@ interface LectureCardProps {
|
||||
isSelected: boolean;
|
||||
}
|
||||
|
||||
export default function LectureCard({
|
||||
onGroupMouseOver,
|
||||
onCardClick,
|
||||
lecture,
|
||||
id,
|
||||
isSelected,
|
||||
}: LectureCardProps) {
|
||||
export default function LectureCard({ onGroupMouseOver, onCardClick, lecture, id, isSelected }: LectureCardProps) {
|
||||
const { addGroup } = useContext(LecturesContext)!;
|
||||
|
||||
const {addGroup} = useContext(LecturesContext);
|
||||
|
||||
|
||||
function onGroupClick(group : Group){
|
||||
addGroup(group);
|
||||
function onGroupClick(group: Group) {
|
||||
addGroup(group);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="class" onClick={onCardClick} id={id}>
|
||||
<div className="class__name">{lecture.name}</div>
|
||||
<Collapse
|
||||
className="expanded"
|
||||
in={isSelected}
|
||||
timeout="auto"
|
||||
unmountOnExit
|
||||
>
|
||||
<Collapse className="expanded" in={isSelected} timeout="auto" unmountOnExit>
|
||||
{lecture.groups.map((group, index) => (
|
||||
<div
|
||||
className="class__group"
|
||||
@ -48,16 +33,12 @@ export default function LectureCard({
|
||||
>
|
||||
<p>
|
||||
{group.time} {group.room} <br></br> {group.lecturer}
|
||||
</p>{" "}
|
||||
</p>{' '}
|
||||
</div>
|
||||
))}
|
||||
</Collapse>
|
||||
<div onClick={onCardClick} id={id}>
|
||||
<img
|
||||
alt="expand"
|
||||
src={ExpandIcon}
|
||||
className={`class__expandIcon${isSelected ? "Rotate" : ""}`}
|
||||
/>
|
||||
<img alt="expand" src={ExpandIcon} className={`class__expandIcon${isSelected ? 'Rotate' : ''}`} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,27 +1,21 @@
|
||||
import React, { useState, useContext } from "react";
|
||||
import "./index.scss";
|
||||
import { Lecture } from "../../businesslogic/types/lecture";
|
||||
import LectureCard from "./LectureCard";
|
||||
import { LecturesContext } from "../../businesslogic/LecturesProvider";
|
||||
import React, { useState, useContext } from 'react';
|
||||
import './index.scss';
|
||||
import { Lecture } from '../../types';
|
||||
import LectureCard from './LectureCard';
|
||||
import { LecturesContext } from '../../contexts/LecturesProvider';
|
||||
|
||||
interface RightBarProps {
|
||||
onGroupMouseOver: (id: string, name: string) => void;
|
||||
lectures: Array<Lecture>;
|
||||
}
|
||||
|
||||
export default function RightBar({
|
||||
lectures,
|
||||
onGroupMouseOver,
|
||||
}: RightBarProps) {
|
||||
export default function RightBar({ onGroupMouseOver }: RightBarProps) {
|
||||
const [selectedCardId, setSelectedCardId] = useState<string | null>(null);
|
||||
|
||||
const lecturesContext = useContext(LecturesContext);
|
||||
|
||||
const onCardClick = (e: React.MouseEvent) => {
|
||||
const target = e.currentTarget as HTMLElement;
|
||||
selectedCardId === target.id
|
||||
? setSelectedCardId(null)
|
||||
: setSelectedCardId(target.id);
|
||||
selectedCardId === target.id ? setSelectedCardId(null) : setSelectedCardId(target.id);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -30,7 +24,7 @@ export default function RightBar({
|
||||
Hubert Wrzesiński<br></br>
|
||||
Semestr zimowy 2020/2021
|
||||
</div>
|
||||
{lecturesContext.lectures.map((lecture, index) => (
|
||||
{lecturesContext?.lectures.map((lecture, index) => (
|
||||
<LectureCard
|
||||
lecture={lecture}
|
||||
key={index}
|
||||
|
@ -1,23 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
interface CellProps {
|
||||
colIndex: number;
|
||||
index: number;
|
||||
term?: string;
|
||||
handleClick?: (e: React.MouseEvent) => void;
|
||||
isEventable?: boolean;
|
||||
}
|
||||
|
||||
export const Cell = ({
|
||||
colIndex,
|
||||
index,
|
||||
term,
|
||||
handleClick,
|
||||
isEventable,
|
||||
}: CellProps) => {
|
||||
return (
|
||||
<div id={`${colIndex} ${index}`} className="td" onClick={handleClick}>
|
||||
{isEventable || term}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
import React from "react";
|
||||
import { Cell } from "../Cell";
|
||||
|
||||
interface ColumnProps {
|
||||
hours: Array<string>;
|
||||
handleClick?: (e: React.MouseEvent) => void;
|
||||
children?: React.ReactNode;
|
||||
colIndex?: number;
|
||||
isEventable?: boolean;
|
||||
}
|
||||
|
||||
export const Column = ({
|
||||
hours,
|
||||
colIndex,
|
||||
isEventable,
|
||||
children,
|
||||
...rest
|
||||
}: ColumnProps) => {
|
||||
return (
|
||||
<div className="tbody__column">
|
||||
{hours.map((hour, index) => (
|
||||
<Cell
|
||||
{...rest}
|
||||
index={index}
|
||||
term={hour}
|
||||
colIndex={colIndex || 0}
|
||||
isEventable={isEventable}
|
||||
/>
|
||||
))}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,86 +1,81 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { SchedulerRow } from "../SchedulerRow";
|
||||
import { LecturesContext } from "../../../businesslogic/LecturesProvider";
|
||||
import { Group } from "../../../businesslogic/types/group";
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { SchedulerRow } from '../SchedulerRow';
|
||||
import { LecturesContext } from '../../../contexts/LecturesProvider';
|
||||
import { Group } from '../../../types';
|
||||
|
||||
interface SchedulerEventsProps {
|
||||
cellTop: number;
|
||||
cellWidth: number;
|
||||
}
|
||||
|
||||
export const SchedulerEvents = ({
|
||||
cellTop,
|
||||
cellWidth,
|
||||
}: SchedulerEventsProps) => {
|
||||
// const handleEventClick = (e: React.MouseEvent) => {
|
||||
// const eventDiv = e.target as HTMLDivElement;
|
||||
// eventDiv.style.backgroundColor = "#1547C5";
|
||||
// };
|
||||
|
||||
const { choosenGroups } = useContext(LecturesContext);
|
||||
export const SchedulerEvents = ({ cellTop, cellWidth }: SchedulerEventsProps) => {
|
||||
const { choosenGroups } = useContext(LecturesContext)!;
|
||||
|
||||
const [groupsMappedToEvents, setGroupsMappedToEvents] = useState<any>([]);
|
||||
|
||||
|
||||
|
||||
// const groups: Array<Group> = [{ id: "5", day: "4", time: "11.45", lecturer: "dr Dorota Blinkiewicz", room: "A2-3" },
|
||||
// { id: "28", day: "1", time: "13.45", lecturer: "dr Barbara Kołodziejczak", room: "D-3" },
|
||||
// { id: "69", day: "4", time: "15.30", lecturer: "dr Karol Gierszewski", room: "A2-3" }];
|
||||
|
||||
|
||||
interface GroupTimeToEventRowMapping {
|
||||
[time: string]: number
|
||||
[time: string]: number;
|
||||
}
|
||||
|
||||
const groupTimeToEventRowMapping: GroupTimeToEventRowMapping = {
|
||||
"8.15": 0,
|
||||
"10.00": 1,
|
||||
"11.45": 2,
|
||||
"13.45": 3,
|
||||
"15.30": 4,
|
||||
"17.15": 5,
|
||||
}
|
||||
|
||||
|
||||
|
||||
'8.15': 0,
|
||||
'10.00': 1,
|
||||
'11.45': 2,
|
||||
'13.45': 3,
|
||||
'15.30': 4,
|
||||
'17.15': 5,
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
function mapGroupTimeToEventRow(groups: Array<Group>) {
|
||||
for (const group of groups) {
|
||||
console.log(group);
|
||||
const groupTime = group.time
|
||||
const groupTime = group.time;
|
||||
const eventRow: number = groupTimeToEventRowMapping[groupTime];
|
||||
const groupMappedToEvent: any = { id: group.id, day: group.day, eventRow: eventRow, lecturer: group.lecturer, room: group.room };
|
||||
const groupMappedToEvent: any = {
|
||||
id: group.id,
|
||||
day: group.day,
|
||||
eventRow: eventRow,
|
||||
lecturer: group.lecturer,
|
||||
room: group.room,
|
||||
};
|
||||
setGroupsMappedToEvents((groupsMappedToEvents: any) => [...groupsMappedToEvents, groupMappedToEvent]);
|
||||
}
|
||||
function alternative(groups: Array<Group>) {
|
||||
const groupsMapped = choosenGroups.map(({ id, day, lecturer, room, time }) => ({
|
||||
id,
|
||||
day,
|
||||
lecturer,
|
||||
room,
|
||||
eventRow: groupTimeToEventRowMapping[time],
|
||||
}));
|
||||
setGroupsMappedToEvents(groupsMapped);
|
||||
}
|
||||
}
|
||||
mapGroupTimeToEventRow(choosenGroups);
|
||||
}, [choosenGroups]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
console.log(groupsMappedToEvents);
|
||||
|
||||
}, [groupsMappedToEvents]);
|
||||
|
||||
|
||||
return (
|
||||
|
||||
|
||||
<div>
|
||||
{
|
||||
[...Array(6)].map((_, index) => (
|
||||
<SchedulerRow
|
||||
key={index}
|
||||
groups={groupsMappedToEvents.filter((group: any) => { return group.eventRow === index })}
|
||||
indexRow={index}
|
||||
cellTop={cellTop + (10 + 70 * index)}
|
||||
cellWidth={cellWidth}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
{[...Array(6)].map((_, index) => (
|
||||
<SchedulerRow
|
||||
key={index}
|
||||
groups={groupsMappedToEvents.filter((group: any) => {
|
||||
return group.eventRow === index;
|
||||
})}
|
||||
indexRow={index}
|
||||
cellTop={cellTop + (10 + 70 * index)}
|
||||
cellWidth={cellWidth}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,5 +1,22 @@
|
||||
import React from "react";
|
||||
import { Group } from "../../../businesslogic/types/group";
|
||||
import React from 'react';
|
||||
import { Group } from '../../../types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface SchedulerEventProps {
|
||||
eventIndex: number;
|
||||
cellTop: number;
|
||||
cellWidth: number;
|
||||
}
|
||||
|
||||
const SchedulerEvent = styled.div<SchedulerEventProps>`
|
||||
position: absolute;
|
||||
top: ${(props) => props.cellTop}px;
|
||||
left: ${(props) => props.cellWidth + 5 + props.cellWidth * props.eventIndex}px;
|
||||
width: ${(props) => (props.cellWidth * 2) / 3}px;
|
||||
height: 60px;
|
||||
background-color: lightblue;
|
||||
z-index: 2;
|
||||
`;
|
||||
|
||||
interface SchedulerRowProps {
|
||||
groups: Array<Group>;
|
||||
@ -8,44 +25,24 @@ interface SchedulerRowProps {
|
||||
cellWidth: number;
|
||||
}
|
||||
|
||||
export const SchedulerRow = ({
|
||||
groups,
|
||||
indexRow,
|
||||
cellTop,
|
||||
cellWidth,
|
||||
}: SchedulerRowProps) => {
|
||||
// const handleEventClick = (e: React.MouseEvent) => {
|
||||
// const eventDiv = e.target as HTMLDivElement;
|
||||
// eventDiv.style.backgroundColor = "#1547C5";
|
||||
// };
|
||||
|
||||
console.log(`You passed me these of a groupzzz: ${groups}`)
|
||||
|
||||
export const SchedulerRow = ({ groups, indexRow, cellTop, cellWidth }: SchedulerRowProps) => {
|
||||
console.log(`You passed me these of a groupzzz: ${groups}`);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
{[...Array(5)].map((value, eventIndex) => (
|
||||
<div
|
||||
<SchedulerEvent
|
||||
eventIndex={eventIndex}
|
||||
cellTop={cellTop}
|
||||
cellWidth={cellWidth}
|
||||
key={`eventRow${indexRow}eventCol${eventIndex}`}
|
||||
id={`eventRow${indexRow}eventCol${eventIndex}`}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: cellTop,
|
||||
left: cellWidth + 5 + cellWidth * eventIndex,
|
||||
width: (cellWidth * 2) / 3,
|
||||
height: 60,
|
||||
backgroundColor: "lightblue",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
|
||||
{groups.map((group, index) =>
|
||||
(
|
||||
parseInt(group.day) === eventIndex ? <div key={index}>{groups[index]?.lecturer}</div>
|
||||
: null
|
||||
))}
|
||||
</div>
|
||||
parseInt(group.day) === eventIndex ? <div key={index}>{groups[index]?.lecturer}</div> : null,
|
||||
)}
|
||||
</SchedulerEvent>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,26 +0,0 @@
|
||||
.scheduler {
|
||||
margin-top: 20px;
|
||||
border-collapse: collapse;
|
||||
|
||||
|
||||
.tbody {
|
||||
display: flex;
|
||||
&__column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.td,
|
||||
.th {
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
.td:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
}
|
@ -1,61 +1,45 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { useState } from "react";
|
||||
import "./index.scss";
|
||||
import { SchedulerEvents } from "./SchedulerEvents";
|
||||
const days = ["", "poniedziałek", "wtorek", "środa", "czwartek", "piątek"];
|
||||
import { days, hours } from "../../constants/index";
|
||||
import styled from "styled-components";
|
||||
|
||||
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",
|
||||
];
|
||||
const SchedulerWrapper = styled.div`
|
||||
flex-grow: 3;
|
||||
margin-top: 20px;
|
||||
border-collapse: collapse;
|
||||
`;
|
||||
|
||||
let events: Array<number> = [];
|
||||
for (let i = 0; i < hours.length / 2; i++) {
|
||||
events.push(i);
|
||||
}
|
||||
const TableBody = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
let center: "center" = "center";
|
||||
let row: "row" = "row";
|
||||
let column: "column" = "column";
|
||||
// const collapse: "collapse" = "collapse";
|
||||
const tbodyStyles = {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: column,
|
||||
};
|
||||
const TableRow = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
const rowStyles = {
|
||||
display: "flex",
|
||||
flexDirection: row,
|
||||
};
|
||||
const TableCell = styled.div`
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const cellStyles = {
|
||||
border: "1px solid #ddd",
|
||||
padding: "10px",
|
||||
textAlign: center,
|
||||
flex: 1,
|
||||
};
|
||||
const TableHead = styled.div`
|
||||
display: flex;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const theadStyles = {
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
};
|
||||
|
||||
// const scheduler = {
|
||||
// marginTop: "20px",
|
||||
// borderCollapse: collapse,
|
||||
// };
|
||||
const TableHeadCell = styled.div`
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
export const Scheduler = () => {
|
||||
const [currentEventsIds, setCurrentEventsIds] = useState<Array<string>>([]);
|
||||
@ -63,7 +47,6 @@ export const Scheduler = () => {
|
||||
const [cellWidth, setCellWidth] = useState(0);
|
||||
const [cellTop, setCellTop] = useState(0);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (cellRef.current) {
|
||||
@ -98,29 +81,30 @@ export const Scheduler = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="scheduler">
|
||||
<div style={theadStyles}>
|
||||
<SchedulerWrapper>
|
||||
<TableHead>
|
||||
{days.map((day, index) => (
|
||||
<div className="th" key={index}>
|
||||
{day}
|
||||
</div>
|
||||
<TableHeadCell key={index}>{day}</TableHeadCell>
|
||||
))}
|
||||
</div>
|
||||
<div style={tbodyStyles}>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{hours.map((hour, indexRow) => (
|
||||
<div key={indexRow} style={rowStyles}>
|
||||
<TableRow key={indexRow}>
|
||||
{[hour, "", "", "", "", ""].map((value, indexCell) =>
|
||||
indexRow === 0 && indexCell === 1 ? (
|
||||
<div key={`${indexRow}${indexCell}`} ref={cellRef} style={cellStyles}></div>
|
||||
<TableCell
|
||||
key={`${indexRow}${indexCell}`}
|
||||
ref={cellRef}
|
||||
></TableCell>
|
||||
) : (
|
||||
<div key={`${indexRow}${indexCell}`} style={cellStyles}>{value}</div>
|
||||
<TableCell key={`${indexRow}${indexCell}`}>{value}</TableCell>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</TableRow>
|
||||
))}
|
||||
</div>
|
||||
</TableBody>
|
||||
<SchedulerEvents cellTop={cellTop} cellWidth={cellWidth} />
|
||||
</div>
|
||||
</SchedulerWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,11 +1,10 @@
|
||||
import React, { useState, useContext, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
import { Input } from "@material-ui/core";
|
||||
import "./index.scss";
|
||||
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
|
||||
import { LecturesContext } from "../../../businesslogic/LecturesProvider";
|
||||
import { Lecture } from "../../../businesslogic/types/lecture";
|
||||
import { Group } from "../../../businesslogic/types/group";
|
||||
import React, { useState, useContext, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import { Input } from '@material-ui/core';
|
||||
import './index.scss';
|
||||
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
|
||||
import { LecturesContext } from '../../../contexts/LecturesProvider';
|
||||
import { Lecture, Group } from '../../../types';
|
||||
|
||||
interface LectureData {
|
||||
name: string;
|
||||
@ -13,14 +12,12 @@ interface LectureData {
|
||||
}
|
||||
|
||||
export const Results: React.FC = () => {
|
||||
const [input, setInput] = useState<string>("");
|
||||
const [input, setInput] = useState<string>('');
|
||||
const [lecturesData, setLecturesData] = useState<Array<LectureData>>([]);
|
||||
const [filteredLecturesData, setFilteredLecturesData] = useState<
|
||||
Array<LectureData>
|
||||
>([]);
|
||||
const [filteredLecturesData, setFilteredLecturesData] = useState<Array<LectureData>>([]);
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
const lecturesContext = useContext(LecturesContext);
|
||||
const lecturesContext = useContext(LecturesContext)!;
|
||||
|
||||
//fetch lectures ids and lectures names
|
||||
// useEffect(() => {
|
||||
@ -36,12 +33,10 @@ export const Results: React.FC = () => {
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const results = await axios.get(`http://localhost:1287/getCourses?name=`);
|
||||
const lecturesData = results.data.map(
|
||||
(result: { id: number; name: string }) => ({
|
||||
id: result.id,
|
||||
name: result.name,
|
||||
})
|
||||
);
|
||||
const lecturesData = results.data.map((result: { id: number; name: string }) => ({
|
||||
id: result.id,
|
||||
name: result.name,
|
||||
}));
|
||||
|
||||
setLecturesData(lecturesData);
|
||||
};
|
||||
@ -51,8 +46,8 @@ export const Results: React.FC = () => {
|
||||
useEffect(() => {
|
||||
const names = lecturesContext.lectures.map((lecture) => lecture.name);
|
||||
const filterLectures = (value: string) => {
|
||||
let filteredLectures = lecturesData.filter((lecture) =>
|
||||
lecture.name.toLowerCase().includes(value.toLowerCase()) && !names.includes(lecture.name)
|
||||
let filteredLectures = lecturesData.filter(
|
||||
(lecture) => lecture.name.toLowerCase().includes(value.toLowerCase()) && !names.includes(lecture.name),
|
||||
);
|
||||
setFilteredLecturesData(filteredLectures);
|
||||
};
|
||||
@ -60,9 +55,7 @@ export const Results: React.FC = () => {
|
||||
}, [input, open]);
|
||||
|
||||
const getLecturesById = async (id: string) => {
|
||||
const { data } = await axios.get(
|
||||
`http://localhost:1287/getClassesByCourseId?id=${id}`
|
||||
);
|
||||
const { data } = await axios.get(`http://localhost:1287/getClassesByCourseId?id=${id}`);
|
||||
return data;
|
||||
};
|
||||
|
||||
@ -92,12 +85,7 @@ export const Results: React.FC = () => {
|
||||
group.id = result[i].id;
|
||||
group.day = result[i].day;
|
||||
group.time = result[i].time;
|
||||
group.lecturer =
|
||||
result[i].lecturer.title +
|
||||
" " +
|
||||
result[i].lecturer.name +
|
||||
" " +
|
||||
result[i].lecturer.surname;
|
||||
group.lecturer = result[i].lecturer.title + ' ' + result[i].lecturer.name + ' ' + result[i].lecturer.surname;
|
||||
group.room = result[i].room.trim();
|
||||
lecture.groups.push(group);
|
||||
}
|
||||
@ -113,7 +101,7 @@ export const Results: React.FC = () => {
|
||||
<div>
|
||||
<Input
|
||||
placeholder="Wyszukaj..."
|
||||
inputProps={{ "aria-label": "description" }}
|
||||
inputProps={{ 'aria-label': 'description' }}
|
||||
className="top-bar__input-field"
|
||||
onChange={handleChange}
|
||||
onClick={handleClick}
|
||||
@ -122,12 +110,7 @@ export const Results: React.FC = () => {
|
||||
{open ? (
|
||||
<div className="dropdown">
|
||||
{filteredLecturesData.map((lecture, index) => (
|
||||
<div
|
||||
className="lecture"
|
||||
key={index}
|
||||
id={String(lecture.id)}
|
||||
onClick={onLectureClick}
|
||||
>
|
||||
<div className="lecture" key={index} id={String(lecture.id)} onClick={onLectureClick}>
|
||||
<p>{lecture.name} </p>
|
||||
</div>
|
||||
))}
|
||||
|
22
src/constants/index.ts
Normal file
22
src/constants/index.ts
Normal file
@ -0,0 +1,22 @@
|
||||
export const days = [
|
||||
"",
|
||||
"poniedziałek",
|
||||
"wtorek",
|
||||
"środa",
|
||||
"czwartek",
|
||||
"piątek",
|
||||
];
|
||||
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",
|
||||
];
|
48
src/contexts/CASProvider.tsx
Normal file
48
src/contexts/CASProvider.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { User } from '../types';
|
||||
|
||||
export interface CASContext {
|
||||
user: User | null;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
export const CASContext = React.createContext<CASContext | null>(null);
|
||||
|
||||
export interface CASProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const CASProvider = ({ children }: CASProviderProps) => {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
login();
|
||||
}, []);
|
||||
|
||||
function login() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const ticket = urlParams.get('ticket');
|
||||
|
||||
if (!ticket) {
|
||||
redirectToCASLoginService();
|
||||
}
|
||||
if (ticket) {
|
||||
console.log(`Ticket is: ${ticket}`);
|
||||
setUser({ ...user, ticket: ticket });
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
redirectToCASLogoutService();
|
||||
}
|
||||
|
||||
function redirectToCASLogoutService() {
|
||||
window.location.replace(`https://cas.amu.edu.pl/cas/logout?service=${window.origin}`);
|
||||
}
|
||||
|
||||
function redirectToCASLoginService() {
|
||||
window.location.replace(`https://cas.amu.edu.pl/cas/login?service=${window.origin}&locale=pl`);
|
||||
}
|
||||
|
||||
return <CASContext.Provider value={{ user, logout }}>{children}</CASContext.Provider>;
|
||||
};
|
32
src/contexts/LecturesProvider.tsx
Normal file
32
src/contexts/LecturesProvider.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React, { useState, createContext } from 'react';
|
||||
import { Lecture, Group } from '../types';
|
||||
|
||||
interface LectureContext {
|
||||
lectures: Array<Lecture>;
|
||||
choosenGroups: Array<Group>;
|
||||
addLecture: (lectures: Lecture) => void;
|
||||
addGroup: (group: Group) => void;
|
||||
}
|
||||
export const LecturesContext = createContext<LectureContext | null>(null);
|
||||
|
||||
interface LecturesProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const LecturesProvider = ({ children }: LecturesProviderProps) => {
|
||||
const [lectures, setLectures] = useState<Array<Lecture>>([]);
|
||||
const [choosenGroups, setChoosenGroups] = useState<Array<Group>>([]);
|
||||
|
||||
const addLecture = (lecture: Lecture) => {
|
||||
setLectures([...lectures, lecture]);
|
||||
};
|
||||
const addGroup = (group: Group) => {
|
||||
setChoosenGroups([...choosenGroups, group]);
|
||||
};
|
||||
|
||||
return (
|
||||
<LecturesContext.Provider value={{ lectures, choosenGroups, addLecture, addGroup }}>
|
||||
{children}
|
||||
</LecturesContext.Provider>
|
||||
);
|
||||
};
|
8
src/contexts/reducers.ts
Normal file
8
src/contexts/reducers.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export enum Types {
|
||||
addLecture = 'ADD_LECTURE',
|
||||
removeLecture = 'REMOVE_LECTURE',
|
||||
addGroup = 'ADD_GROUP',
|
||||
removeGroup = 'ADD_GROUP',
|
||||
addCourse = 'ADD_COURSE',
|
||||
removeCourse = 'REMOVE_COURSE',
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import BuisnessLogicProvider from "./businesslogic/BusinessLogicProvider";
|
||||
import { LecturesProvider } from "./businesslogic/LecturesProvider";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { App } from './App';
|
||||
import { CASProvider } from './contexts/CASProvider';
|
||||
import { LecturesProvider } from './contexts/LecturesProvider';
|
||||
import { GlobalStyles } from './styles/GlobalStyles';
|
||||
|
||||
ReactDOM.render(
|
||||
<>
|
||||
<LecturesProvider>
|
||||
<BuisnessLogicProvider>
|
||||
<App />
|
||||
</BuisnessLogicProvider>
|
||||
</LecturesProvider>
|
||||
</>,
|
||||
document.getElementById("root")
|
||||
<>
|
||||
<LecturesProvider>
|
||||
<CASProvider>
|
||||
<GlobalStyles />
|
||||
<App />
|
||||
</CASProvider>
|
||||
</LecturesProvider>
|
||||
</>,
|
||||
document.getElementById('root'),
|
||||
);
|
||||
|
20
src/styles/GlobalStyles.ts
Normal file
20
src/styles/GlobalStyles.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { createGlobalStyle } from 'styled-components';
|
||||
|
||||
export const GlobalStyles = createGlobalStyle`
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 24px;
|
||||
|
||||
}
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
`;
|
@ -1,27 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const styles = {
|
||||
root: {
|
||||
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
|
||||
border: 0,
|
||||
borderRadius: 3,
|
||||
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
|
||||
color: 'white',
|
||||
height: 48,
|
||||
padding: '0 30px',
|
||||
},
|
||||
};
|
||||
|
||||
function HigherOrderComponent(props: { classes: any; }) {
|
||||
const { classes } = props;
|
||||
return <Button className={classes.root}>Higher-order component</Button>;
|
||||
}
|
||||
|
||||
HigherOrderComponent.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(HigherOrderComponent);
|
21
src/types/index.ts
Normal file
21
src/types/index.ts
Normal file
@ -0,0 +1,21 @@
|
||||
export interface Group {
|
||||
id: string;
|
||||
day: string;
|
||||
time: string;
|
||||
lecturer: string;
|
||||
room: string;
|
||||
}
|
||||
export interface Lecture {
|
||||
id?: number;
|
||||
name: string;
|
||||
groups: Array<Group>;
|
||||
}
|
||||
export interface LectureInit {
|
||||
name: string;
|
||||
id: number;
|
||||
}
|
||||
export interface User {
|
||||
name?: string;
|
||||
surname?: string;
|
||||
ticket: string | null;
|
||||
}
|
Reference in New Issue
Block a user