frontend/src/components/SchedulerRow.tsx

248 lines
7.8 KiB
TypeScript
Raw Normal View History

2020-12-12 17:54:13 +01:00
import React, { Fragment, MouseEvent, useState, useEffect, useContext } from 'react';
2020-11-21 04:02:38 +01:00
import { GroupType, SchedulerEvent } from '../types';
2020-11-26 01:53:07 +01:00
import styled, { css } from 'styled-components/macro';
import Popover from '@material-ui/core/Popover';
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
2020-11-21 04:02:38 +01:00
import { MONDAY_TO_FRIDAY } from '../constants';
import { coursesContext } from '../contexts/CoursesProvider';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
popover: {
2020-11-25 03:14:39 +01:00
fontSize: '14px',
},
paper: {
2020-11-25 03:14:39 +01:00
padding: '15px 15px 15px 15px',
textAlign: 'left',
lineHeight: `1 !important`,
},
}),
);
2020-08-12 04:13:14 +02:00
2020-11-25 03:14:39 +01:00
const PopoverSpan = styled.span`
2020-11-26 01:53:07 +01:00
font-weight: bold;
2020-11-25 03:14:39 +01:00
margin-right: 2px;
`;
2020-11-21 04:02:38 +01:00
interface SchedulerEventsWrapperProps {
2020-08-12 04:13:14 +02:00
eventIndex: number;
2020-11-21 04:02:38 +01:00
rowTop: number;
2020-08-12 04:13:14 +02:00
cellWidth: number;
cellHeight: number;
2020-08-12 04:13:14 +02:00
}
2020-11-21 04:02:38 +01:00
const SchedulerEventsWrapper = styled.div<SchedulerEventsWrapperProps>`
2020-08-12 04:13:14 +02:00
position: absolute;
display: flex;
2020-11-21 04:02:38 +01:00
top: ${({ rowTop }) => rowTop}px;
2020-11-20 20:39:36 +01:00
left: ${({ cellWidth, eventIndex }) => (cellWidth * 1) / 5 + 4 + cellWidth * eventIndex}px;
2020-11-19 21:57:34 +01:00
width: ${({ cellWidth }) => cellWidth - 10}px;
2020-11-13 23:05:10 +01:00
height: ${({ cellHeight }) => cellHeight * 3}px;
2020-09-11 18:56:14 +02:00
z-index: 2;
2020-11-19 21:57:34 +01:00
padding-left: 10px;
2020-09-11 18:56:14 +02:00
`;
2020-11-21 04:02:38 +01:00
interface SchedulerEventProps {
2020-11-20 15:58:51 +01:00
cellWidth: number;
2020-09-28 20:16:54 +02:00
cellHeight: number;
groupType: GroupType;
isHovered: boolean;
2020-09-28 20:16:54 +02:00
}
2020-11-21 04:02:38 +01:00
const StyledSchedulerEvent = styled.div<SchedulerEventProps>`
2020-09-28 18:36:38 +02:00
display: flex;
2020-11-24 19:01:20 +01:00
flex-direction: column;
2020-09-28 18:36:38 +02:00
justify-content: center;
align-items: center;
2020-12-02 09:04:06 +01:00
z-index: 20000;
2020-11-20 15:58:51 +01:00
font-size: 0.65vw;
line-height: normal;
2020-09-11 18:56:14 +02:00
border-radius: 10px;
2020-11-19 21:57:34 +01:00
height: ${({ cellHeight }) => cellHeight * 3}px;
2020-11-21 04:02:38 +01:00
width: ${({ cellWidth }) => (cellWidth * 3) / 4}px;
2020-11-19 21:57:34 +01:00
margin-right: 5px;
2020-11-24 19:01:20 +01:00
padding: 5px 5px 0 5px;
2020-11-20 15:58:51 +01:00
text-align: center;
background-color: ${({ groupType, isHovered }) => {
if (isHovered) {
2020-12-12 19:57:16 +01:00
return groupType === 'CLASS' ? '#FFE485' : '#D2EBFF';
} else {
return groupType === 'CLASS' ? '#FFDC61' : '#9ed3ff';
}
}};
2020-12-12 17:54:13 +01:00
${({ isHovered }) =>
isHovered &&
css`
2020-12-12 19:57:16 +01:00
transition: background-color ease-in 0.4s;
2020-12-12 17:54:13 +01:00
`}
2020-12-12 19:57:16 +01:00
transition: background-color ease-out 0.4s;
2020-11-21 04:02:38 +01:00
box-shadow: 3px 3px 3px 0px rgba(0, 0, 0, 0.75);
2020-12-29 01:06:39 +01:00
cursor: pointer;
2020-08-12 04:13:14 +02:00
`;
2020-08-09 20:44:35 +02:00
const threeStyles = () => {
2020-11-26 01:53:07 +01:00
return css`
white-space: nowrap;
text-overflow: ellipsis;
max-width: 70px;
`;
};
type BoldParagraphProps = {
isThree?: boolean;
};
const BoldParagraph = styled.p<BoldParagraphProps>`
overflow: hidden;
2020-11-25 00:19:59 +01:00
flex: 3;
${({ isThree }) => isThree && threeStyles}
2020-11-25 00:19:59 +01:00
`;
const ClassWrap = styled.div`
2020-11-24 19:01:20 +01:00
font-weight: 700;
2020-11-25 00:19:59 +01:00
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
line-height: normal;
2020-11-24 19:01:20 +01:00
`;
const TextWrapper = styled.div`
2020-11-25 00:19:59 +01:00
flex: 1;
2020-11-24 19:01:20 +01:00
width: inherit;
2020-11-25 09:14:25 +01:00
padding: 0 3px 5px 3px;
2020-11-24 19:01:20 +01:00
display: flex;
justify-content: space-between;
`;
2020-08-09 20:44:35 +02:00
interface SchedulerRowProps {
2020-11-21 04:02:38 +01:00
groups: Array<SchedulerEvent>;
2020-08-09 20:44:35 +02:00
indexRow: number;
2020-11-21 04:02:38 +01:00
rowTop: number;
2020-08-09 20:44:35 +02:00
cellWidth: number;
cellHeight: number;
2020-08-09 20:44:35 +02:00
}
2020-11-25 00:19:59 +01:00
const getGroupsPerDay = (groups: Array<SchedulerEvent>) => {
const groupsPerDay: any = { 0: 0, 1: 0, 2: 0, 3: 0, 4: 0 };
for (const group of groups) {
groupsPerDay[group.day]++;
}
return groupsPerDay;
};
2020-11-25 00:19:59 +01:00
2020-11-21 04:02:38 +01:00
export const SchedulerRow = ({ groups, indexRow, rowTop, cellWidth, cellHeight }: SchedulerRowProps) => {
2020-12-02 09:04:06 +01:00
const { hoveredGroup } = useContext(coursesContext)!;
const classes = useStyles();
2020-11-25 03:14:39 +01:00
const groupsPerDay = getGroupsPerDay(groups);
const [anchorEl, setAnchorEl] = React.useState<HTMLDivElement | null>(null);
2020-09-28 18:36:38 +02:00
const [popoverId, setPopoverId] = useState<string | null>(null);
//looks weird
const handlePopoverOpen = (event: MouseEvent<HTMLDivElement, globalThis.MouseEvent>) => {
setAnchorEl(event.currentTarget);
2020-09-28 18:36:38 +02:00
setPopoverId(event.currentTarget.id);
};
2020-12-02 09:04:06 +01:00
const handlePopoverClose = (e: MouseEvent<any>) => {
setPopoverId(null);
2020-12-02 09:04:06 +01:00
setAnchorEl(null);
};
2020-12-02 09:04:06 +01:00
useEffect(() => {
}, [anchorEl]);
const open = Boolean(anchorEl);
2020-12-02 09:04:06 +01:00
const id = open ? 'simple-popover' : undefined;
2020-08-09 20:44:35 +02:00
return (
2020-11-13 23:05:10 +01:00
<div>
2020-11-21 04:02:38 +01:00
{[...Array(MONDAY_TO_FRIDAY)].map((_, eventIndex) => (
<SchedulerEventsWrapper
2020-08-12 04:13:14 +02:00
eventIndex={eventIndex}
2020-11-21 04:02:38 +01:00
rowTop={rowTop}
2020-08-12 04:13:14 +02:00
cellWidth={cellWidth}
cellHeight={cellHeight}
2020-08-18 00:21:21 +02:00
key={eventIndex}
2020-08-09 21:41:52 +02:00
id={`eventRow${indexRow}eventCol${eventIndex}`}
2020-08-09 20:44:35 +02:00
>
2020-09-11 18:56:14 +02:00
{groups.map(
(group, index) =>
group.day === eventIndex && (
2020-11-22 17:21:22 +01:00
<Fragment key={index}>
2020-11-21 04:02:38 +01:00
<StyledSchedulerEvent
2020-12-02 09:04:06 +01:00
aria-describedby={id}
isHovered={group.id === hoveredGroup?.id}
2020-09-28 20:16:54 +02:00
groupType={group.type}
2020-11-20 15:58:51 +01:00
cellWidth={cellWidth}
cellHeight={cellHeight}
id={`eventRow${indexRow}eventCol${eventIndex}${index}`}
key={index}
aria-owns={open ? `mouse-over-popover` : undefined}
aria-haspopup="true"
2020-12-02 09:04:06 +01:00
onClick={(e) => handlePopoverOpen(e)}
>
2020-11-25 00:19:59 +01:00
<ClassWrap>
<BoldParagraph isThree={groupsPerDay[group.day] >= 3}>{groups[index].name}</BoldParagraph>
{groupsPerDay[group.day] < 3 ? (
<TextWrapper>
2020-12-29 01:06:39 +01:00
<div>{`${groups[index].time}-${groups[index].endTime}`}</div>
2020-12-29 17:32:06 +01:00
<div>
{groups[index].takenPlaces}/{groups[index].capacity}
</div>
</TextWrapper>
) : (
<TextWrapper style={{ flexDirection: 'column' }}>
2020-12-29 17:32:06 +01:00
<div style={{ alignSelf: 'flex-end' }}>
{groups[index].takenPlaces}/{groups[index].capacity}
</div>
</TextWrapper>
)}
2020-11-25 00:19:59 +01:00
</ClassWrap>
2020-11-21 04:02:38 +01:00
</StyledSchedulerEvent>
<Popover
2020-12-02 09:04:06 +01:00
id={id}
className={classes.popover}
classes={{
paper: classes.paper,
}}
2020-09-28 18:36:38 +02:00
open={popoverId === `eventRow${indexRow}eventCol${eventIndex}${index}`}
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'center',
horizontal: 'left',
}}
onClose={handlePopoverClose}
disableRestoreFocus
>
2020-12-12 19:57:16 +01:00
<div style={{ display: 'flex', flexDirection: 'column', zIndex: 20000 }} onClick={() => {}}>
2020-11-25 03:14:39 +01:00
<p style={{ margin: '7px 0 7px 0', fontWeight: 'bold' }}>{groups[index].name}</p>
<p style={{ margin: '2px 0 2px 0' }}>
<PopoverSpan>Prowadzący:</PopoverSpan> {groups[index].lecturer}
</p>
<p style={{ margin: '2px 0 2px 0' }}>
2020-11-26 01:53:07 +01:00
<PopoverSpan>Sala zajęć</PopoverSpan>: {groups[index].room}
2020-11-25 03:14:39 +01:00
</p>
<p style={{ margin: '2px 0 2px 0' }}>
2020-11-26 01:53:07 +01:00
<PopoverSpan>Kod przedmiotu: </PopoverSpan>ACB129
2020-11-25 03:14:39 +01:00
</p>
<p style={{ margin: '2px 0 2px 0' }}>
2020-11-26 01:53:07 +01:00
<PopoverSpan>Kod grupy: </PopoverSpan>FVJ753
2020-11-25 03:14:39 +01:00
</p>
<p style={{ margin: '2px 0 2px 0' }}>
2020-11-26 01:53:07 +01:00
<PopoverSpan>Punkty ECTS:</PopoverSpan> 2
2020-11-25 03:14:39 +01:00
</p>
</div>
</Popover>
2020-11-22 17:21:22 +01:00
</Fragment>
2020-09-11 18:56:14 +02:00
),
)}
2020-11-21 04:02:38 +01:00
</SchedulerEventsWrapper>
2020-08-09 20:44:35 +02:00
))}
2020-11-13 23:05:10 +01:00
</div>
2020-08-09 20:44:35 +02:00
);
};