Merge branch 'main' of github.com-personal:leomurca/if-salas-web into development
This commit is contained in:
commit
cb192f4b1e
43 changed files with 2522 additions and 93 deletions
|
@ -1,4 +1,5 @@
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
|
import Classroom from '../screens/professor/Classroom';
|
||||||
import Home from '../screens/professor/Home';
|
import Home from '../screens/professor/Home';
|
||||||
|
|
||||||
function ProfessorRoutes() {
|
function ProfessorRoutes() {
|
||||||
|
@ -6,6 +7,9 @@ function ProfessorRoutes() {
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/calendar" element={<h1>Calendar</h1>} />
|
<Route path="/calendar" element={<h1>Calendar</h1>} />
|
||||||
<Route path="/profile" element={<h1>Profile</h1>} />
|
<Route path="/profile" element={<h1>Profile</h1>} />
|
||||||
|
<Route path="/class">
|
||||||
|
<Route path=":id" element={<Classroom />} />
|
||||||
|
</Route>
|
||||||
<Route path="/info" element={<h1>Information</h1>} />
|
<Route path="/info" element={<h1>Information</h1>} />
|
||||||
<Route path="/home" element={<Home />} />
|
<Route path="/home" element={<Home />} />
|
||||||
<Route path="/login" element={<Navigate to="/home" />} />
|
<Route path="/login" element={<Navigate to="/home" />} />
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
|
|
||||||
import Home from '../screens/Home';
|
import Home from '../screens/student/Home';
|
||||||
|
import Classroom from '../screens/student/Classroom';
|
||||||
|
|
||||||
import Information from '../screens/Information';
|
import Information from '../screens/Information';
|
||||||
import Calendar from '../screens/Calendar';
|
import Calendar from '../screens/Calendar';
|
||||||
import Classroom from '../screens/Classroom';
|
|
||||||
import Assignment from '../screens/Assignment';
|
import Assignment from '../screens/Assignment';
|
||||||
import Profile from '../screens/Profile';
|
import Profile from '../screens/Profile';
|
||||||
|
|
||||||
|
|
33
src/components/FormDialog/index.js
Normal file
33
src/components/FormDialog/index.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@mui/material';
|
||||||
|
|
||||||
|
function FormDialog({
|
||||||
|
isOpened,
|
||||||
|
title,
|
||||||
|
contentText,
|
||||||
|
inputs,
|
||||||
|
onDismiss,
|
||||||
|
onSave,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Dialog open={isOpened} onClose={onDismiss}>
|
||||||
|
<DialogTitle>{title}</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>{contentText}</DialogContentText>
|
||||||
|
{[...inputs]}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={onDismiss}>Cancelar</Button>
|
||||||
|
<Button onClick={onSave}>Salvar</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormDialog;
|
64
src/components/PublishAnnouncementCard/index.js
Normal file
64
src/components/PublishAnnouncementCard/index.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Stack,
|
||||||
|
TextField,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
function PublishAnnouncementCard({ layoutType, user, value, onChange }) {
|
||||||
|
const [isComposing, setIsComposing] = useState(false);
|
||||||
|
const { card, publishAnnouncement } = styles[layoutType];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card sx={card} elevation={4} variant="elevation">
|
||||||
|
{isComposing ? (
|
||||||
|
<Stack
|
||||||
|
sx={publishAnnouncement}
|
||||||
|
alignItems="end"
|
||||||
|
direction="column"
|
||||||
|
spacing={2}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
sx={{ width: '100%' }}
|
||||||
|
id="outlined-multiline-static"
|
||||||
|
label="Escreva um comunicado para sua turma"
|
||||||
|
autoFocus
|
||||||
|
multiline
|
||||||
|
minRows={4}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack direction="row" spacing={4}>
|
||||||
|
<Button onClick={() => setIsComposing(false)} variant="text">
|
||||||
|
Cancelar
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button onClick={() => console.log('clicked')} variant="contained">
|
||||||
|
Postar
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
) : (
|
||||||
|
<Stack
|
||||||
|
sx={publishAnnouncement}
|
||||||
|
alignItems="center"
|
||||||
|
direction="row"
|
||||||
|
spacing={2}
|
||||||
|
onClick={() => setIsComposing(true)}
|
||||||
|
>
|
||||||
|
<Avatar alt={user.firstName} src={user.avatar} />
|
||||||
|
<Typography id="outlined-multiline-static" sx={{ width: '100%' }}>
|
||||||
|
Escreva um comunicado para sua turma
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PublishAnnouncementCard;
|
47
src/components/PublishAnnouncementCard/styles.js
Normal file
47
src/components/PublishAnnouncementCard/styles.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// ========== Desktop ==========
|
||||||
|
const desktopCard = {
|
||||||
|
width: '100%',
|
||||||
|
padding: '20px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopPublishAnnouncement = {
|
||||||
|
cursor: 'pointer',
|
||||||
|
':hover': {
|
||||||
|
color: '#32A041',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktop = {
|
||||||
|
publishAnnouncement: desktopPublishAnnouncement,
|
||||||
|
card: desktopCard,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Mobile ==========
|
||||||
|
const mobilePublishAnnouncement = {
|
||||||
|
cursor: 'pointer',
|
||||||
|
padding: '10px',
|
||||||
|
width: '100%',
|
||||||
|
':hover': {
|
||||||
|
color: '#32A041',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileCard = {
|
||||||
|
width: '100%',
|
||||||
|
padding: '10px ',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobile = {
|
||||||
|
publishAnnouncement: mobilePublishAnnouncement,
|
||||||
|
card: mobileCard,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Unset ==========
|
||||||
|
|
||||||
|
const unset = {
|
||||||
|
publishAnnouncement: null,
|
||||||
|
card: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
|
@ -9,19 +9,18 @@ import {
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import { capitalizeFirstLetter } from '../../utils/capitalizeFirstLetter';
|
import { capitalizeFirstLetter } from '../../../utils/capitalizeFirstLetter';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { AssignmentTurnedIn, PendingActions } from '@mui/icons-material';
|
||||||
|
|
||||||
function AssignmentCard({
|
function AssignmentCard({
|
||||||
title,
|
title,
|
||||||
classrooms,
|
classrooms,
|
||||||
dueDate,
|
dueDate,
|
||||||
scores,
|
|
||||||
deliveredByStudents,
|
deliveredByStudents,
|
||||||
reviewed,
|
reviewed,
|
||||||
total,
|
total,
|
||||||
isAssignmentToReview,
|
|
||||||
layoutType,
|
layoutType,
|
||||||
onClick,
|
onClick,
|
||||||
}) {
|
}) {
|
||||||
|
@ -64,29 +63,33 @@ function AssignmentCard({
|
||||||
>
|
>
|
||||||
{classrooms.map(c => c.name).join(', ')}
|
{classrooms.map(c => c.name).join(', ')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Divider sx={dividerMiddle} />
|
|
||||||
|
|
||||||
<Typography sx={typographyDueDate} variant="p" component="div">
|
<Typography sx={typographyDueDate} variant="p" component="div">
|
||||||
<strong>Data de entrega: </strong>{' '}
|
Data de entrega:{' '}
|
||||||
{capitalizeFirstLetter(
|
{capitalizeFirstLetter(dayjs(dueDate).format('dddd, DD/MM'))}
|
||||||
dayjs(dueDate).format('dddd, DD/MM | HH:mm[h]')
|
|
||||||
)}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Divider sx={dividerMiddle} />
|
||||||
{deliveredByStudents >= 0 && total && (
|
{deliveredByStudents >= 0 && total && (
|
||||||
<Typography variant="p" component="div">
|
<Typography
|
||||||
<strong>Entregues: </strong>{' '}
|
variant="p"
|
||||||
{`${deliveredByStudents} de ${total}`}
|
component="div"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: '10px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AssignmentTurnedIn sx={{ marginRight: '5px' }} />
|
||||||
|
{`${reviewed}`} corrigidas.
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
{reviewed >= 0 && total && (
|
{reviewed >= 0 && total && (
|
||||||
<Typography variant="p" component="div">
|
<Typography
|
||||||
<strong>Corrigidas: </strong> {`${reviewed} de ${total}`}
|
variant="p"
|
||||||
</Typography>
|
component="div"
|
||||||
)}
|
sx={{ display: 'flex', alignItems: 'center' }}
|
||||||
{!isAssignmentToReview && (
|
>
|
||||||
<Typography variant="p" component="div">
|
<PendingActions sx={{ marginRight: '5px' }} />{' '}
|
||||||
<strong>Valor: </strong>
|
{`${total - reviewed}`} pendentes.
|
||||||
{scores.map(s => s.value).join(', ')} pts
|
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
@ -121,28 +124,34 @@ function AssignmentCard({
|
||||||
>
|
>
|
||||||
{classrooms.map(c => c.name).join(', ')}
|
{classrooms.map(c => c.name).join(', ')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Divider sx={dividerMiddle} />
|
|
||||||
<Typography sx={typographyDueDate} variant="p" component="div">
|
<Typography sx={typographyDueDate} variant="p" component="div">
|
||||||
<strong>Data de entrega: </strong>
|
Data de entrega:{' '}
|
||||||
{capitalizeFirstLetter(
|
{capitalizeFirstLetter(dayjs(dueDate).format('dddd, DD/MM'))}
|
||||||
dayjs(dueDate).format('dddd, DD/MM | HH:mm[h]')
|
|
||||||
)}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Divider sx={dividerMiddle} />
|
||||||
{deliveredByStudents >= 0 && total && (
|
{deliveredByStudents >= 0 && total && (
|
||||||
<Typography variant="p" component="div">
|
<Typography
|
||||||
<strong>Entregues: </strong>{' '}
|
variant="p"
|
||||||
{`${deliveredByStudents} de ${total}`}
|
component="div"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: '10px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AssignmentTurnedIn sx={{ marginRight: '5px' }} />
|
||||||
|
{`${reviewed}`} corrigidas.
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
{reviewed >= 0 && total && (
|
{reviewed >= 0 && total && (
|
||||||
<Typography variant="p" component="div">
|
<Typography
|
||||||
<strong>Corrigidas: </strong> {`${reviewed} de ${total}`}
|
variant="p"
|
||||||
</Typography>
|
component="div"
|
||||||
)}
|
sx={{ display: 'flex', alignItems: 'center' }}
|
||||||
{!isAssignmentToReview && (
|
>
|
||||||
<Typography variant="p" component="div">
|
<PendingActions sx={{ marginRight: '5px' }} />{' '}
|
||||||
<strong>Valor: </strong>
|
{`${total - reviewed}`} pendentes.
|
||||||
{scores.map(s => s.value).join(', ')} pts
|
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
143
src/components/professor/AssignmentCard/styles.js
Normal file
143
src/components/professor/AssignmentCard/styles.js
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
// ========== Desktop ==========
|
||||||
|
const desktopCardContainer = classrooms => ({
|
||||||
|
position: 'relative',
|
||||||
|
width: '35em',
|
||||||
|
borderLeft: `5px solid ${classrooms[0].color}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const desktopClassroomLinesIndicator = classroom => ({
|
||||||
|
position: 'absolute',
|
||||||
|
height: '100%',
|
||||||
|
borderLeft: `5px solid ${classroom.color}`,
|
||||||
|
left: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const desktopCardActionArea = {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'start',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopCardContent = {
|
||||||
|
width: '100%',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopTypographyTitle = {
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
fontSize: '17px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopStackClassroomNames = {
|
||||||
|
width: '100%',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopTypographyClassroomNames = {
|
||||||
|
fontStyle: 'italic',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopDividerMiddle = {
|
||||||
|
marginTop: '10px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopTypographyDueDate = {
|
||||||
|
marginTop: '5px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
fontStyle: 'italic',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktop = {
|
||||||
|
cardContainer: desktopCardContainer,
|
||||||
|
classroomLinesIndicator: desktopClassroomLinesIndicator,
|
||||||
|
cardActionArea: desktopCardActionArea,
|
||||||
|
cardContent: desktopCardContent,
|
||||||
|
typographyTitle: desktopTypographyTitle,
|
||||||
|
stackClassroomNames: desktopStackClassroomNames,
|
||||||
|
typographyClassroomNames: desktopTypographyClassroomNames,
|
||||||
|
dividerMiddle: desktopDividerMiddle,
|
||||||
|
typographyDueDate: desktopTypographyDueDate,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Mobile ==========
|
||||||
|
const mobileCardContainer = classrooms => ({
|
||||||
|
width: '100%',
|
||||||
|
borderTop: `5px solid ${classrooms[0].color}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mobileClassroomLinesIndicator = classroom => ({
|
||||||
|
position: 'absolute',
|
||||||
|
width: '100%',
|
||||||
|
borderTop: `5px solid ${classroom.color}`,
|
||||||
|
top: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mobileCardActionArea = {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileCardContent = {
|
||||||
|
width: '100%',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileTypographyTitle = {
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
fontSize: '17px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileStackClassroomNames = {
|
||||||
|
width: '100%',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileTypographyClassroomNames = {
|
||||||
|
fontWeight: 'bold',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileDividerMiddle = {
|
||||||
|
marginTop: '10px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileTypographyDueDate = {
|
||||||
|
marginTop: '5px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
fontStyle: 'italic',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobile = {
|
||||||
|
cardContainer: mobileCardContainer,
|
||||||
|
classroomLinesIndicator: mobileClassroomLinesIndicator,
|
||||||
|
cardActionArea: mobileCardActionArea,
|
||||||
|
cardContent: mobileCardContent,
|
||||||
|
typographyTitle: mobileTypographyTitle,
|
||||||
|
stackClassroomNames: mobileStackClassroomNames,
|
||||||
|
typographyClassroomNames: mobileTypographyClassroomNames,
|
||||||
|
dividerMiddle: mobileDividerMiddle,
|
||||||
|
typographyDueDate: mobileTypographyDueDate,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Unset ==========
|
||||||
|
const unset = {
|
||||||
|
cardContainer: null,
|
||||||
|
classroomLinesIndicator: null,
|
||||||
|
cardActionArea: null,
|
||||||
|
cardContent: null,
|
||||||
|
typographyTitle: null,
|
||||||
|
stackClassroomNames: null,
|
||||||
|
typographyClassroomNames: null,
|
||||||
|
dividerMiddle: null,
|
||||||
|
typographyDueDate: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
151
src/components/student/AssignmentCard/index.js
Normal file
151
src/components/student/AssignmentCard/index.js
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
Typography,
|
||||||
|
CardActionArea,
|
||||||
|
Stack,
|
||||||
|
Tooltip,
|
||||||
|
Divider,
|
||||||
|
} from '@mui/material';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import { capitalizeFirstLetter } from '../../../utils/capitalizeFirstLetter';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
import { Assessment, Today } from '@mui/icons-material';
|
||||||
|
|
||||||
|
function AssignmentCard({
|
||||||
|
title,
|
||||||
|
classrooms,
|
||||||
|
dueDate,
|
||||||
|
scores,
|
||||||
|
layoutType,
|
||||||
|
onClick,
|
||||||
|
}) {
|
||||||
|
const {
|
||||||
|
cardContainer,
|
||||||
|
classroomLinesIndicator,
|
||||||
|
cardActionArea,
|
||||||
|
cardContent,
|
||||||
|
typographyTitle,
|
||||||
|
stackClassroomNames,
|
||||||
|
typographyClassroomNames,
|
||||||
|
dividerMiddle,
|
||||||
|
typographyDueDate,
|
||||||
|
} = styles[layoutType];
|
||||||
|
|
||||||
|
if (layoutType === 'desktop') {
|
||||||
|
return (
|
||||||
|
<Card sx={cardContainer(classrooms)}>
|
||||||
|
{classrooms.length > 1 &&
|
||||||
|
classrooms
|
||||||
|
.filter((_, i) => i > 0)
|
||||||
|
.map(c => <div key={c.id} style={classroomLinesIndicator(c)} />)}
|
||||||
|
<CardActionArea onClick={() => onClick()} sx={cardActionArea}>
|
||||||
|
<CardContent sx={cardContent}>
|
||||||
|
<Tooltip title={title}>
|
||||||
|
<Typography
|
||||||
|
sx={typographyTitle}
|
||||||
|
gutterBottom
|
||||||
|
variant="h6"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
</Tooltip>
|
||||||
|
<Stack sx={stackClassroomNames}>
|
||||||
|
<Typography
|
||||||
|
sx={typographyClassroomNames}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
{classrooms.map(c => c.name).join(', ')}
|
||||||
|
</Typography>
|
||||||
|
<Divider sx={dividerMiddle} />
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
...typographyDueDate,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<Today sx={{ marginRight: '5px' }} />
|
||||||
|
{capitalizeFirstLetter(
|
||||||
|
dayjs(dueDate).format('dddd, DD/MM, HH:mm[h]')
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
sx={{ display: 'flex', alignItems: 'center' }}
|
||||||
|
>
|
||||||
|
<Assessment sx={{ marginRight: '5px' }} />
|
||||||
|
{scores.map(s => s.value).join(', ')} pontos
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</CardActionArea>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
} else if (layoutType === 'mobile') {
|
||||||
|
return (
|
||||||
|
<Card sx={cardContainer(classrooms)}>
|
||||||
|
<CardActionArea onClick={() => onClick()} sx={cardActionArea}>
|
||||||
|
{classrooms.length > 1 &&
|
||||||
|
classrooms
|
||||||
|
.filter((_, i) => i > 0)
|
||||||
|
.map(c => <div key={c.id} style={classroomLinesIndicator(c)} />)}
|
||||||
|
<CardContent sx={cardContent}>
|
||||||
|
<Tooltip title={title}>
|
||||||
|
<Typography
|
||||||
|
sx={typographyTitle}
|
||||||
|
gutterBottom
|
||||||
|
variant="h6"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
</Tooltip>
|
||||||
|
<Stack sx={stackClassroomNames}>
|
||||||
|
<Typography
|
||||||
|
sx={typographyClassroomNames}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
{classrooms.map(c => c.name).join(', ')}
|
||||||
|
</Typography>
|
||||||
|
<Divider sx={dividerMiddle} />
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
...typographyDueDate,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<Today sx={{ marginRight: '5px' }} />
|
||||||
|
{capitalizeFirstLetter(
|
||||||
|
dayjs(dueDate).format('dddd, DD/MM, HH:mm[h]')
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
sx={{ display: 'flex', alignItems: 'center' }}
|
||||||
|
>
|
||||||
|
<Assessment sx={{ marginRight: '5px' }} />
|
||||||
|
{scores.map(s => s.value).join(', ')} pontos
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</CardActionArea>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AssignmentCard;
|
|
@ -63,6 +63,7 @@ function View({
|
||||||
type="password"
|
type="password"
|
||||||
value={password}
|
value={password}
|
||||||
onChange={e => onChangePassword(e.target.value)}
|
onChange={e => onChangePassword(e.target.value)}
|
||||||
|
onKeyDown={e => (e.key === 'Enter' ? onTryLogin() : null)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
disabled={!isSubmitable}
|
disabled={!isSubmitable}
|
||||||
|
|
525
src/screens/professor/Classroom/AnnouncementsTab/index.js
Normal file
525
src/screens/professor/Classroom/AnnouncementsTab/index.js
Normal file
|
@ -0,0 +1,525 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
|
IconButton,
|
||||||
|
Link,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
TextField,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material';
|
||||||
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||||
|
import AnnouncementCard from '../../../../components/AnnouncementCard';
|
||||||
|
import PublishAnnouncementCard from '../../../../components/PublishAnnouncementCard';
|
||||||
|
import FormDialog from '../../../../components/FormDialog';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
import jitsiLogo from '../../../../assets/jitsi.svg';
|
||||||
|
import { createArrayFrom1ToN } from '../../../../utils/createArrayFrom1ToN';
|
||||||
|
|
||||||
|
function AnnouncementsTab({
|
||||||
|
layoutType,
|
||||||
|
announcementsTabData,
|
||||||
|
classroom,
|
||||||
|
onChangeEditInput,
|
||||||
|
onSaveEditChanges,
|
||||||
|
user,
|
||||||
|
}) {
|
||||||
|
const [anchorEl, setAnchorEl] = useState({
|
||||||
|
virtualRoom: null,
|
||||||
|
appointmentSlots: null,
|
||||||
|
});
|
||||||
|
const [dialogOpened, setDialogOpened] = useState(null);
|
||||||
|
const [composingTextValue, setComposingTextValue] = useState('');
|
||||||
|
const { container, emptyStateContainer } = styles[layoutType];
|
||||||
|
|
||||||
|
const onSaveEdit = anchorName => {
|
||||||
|
onSaveEditChanges();
|
||||||
|
setDialogOpened(null);
|
||||||
|
setAnchorEl({ ...anchorEl, [anchorName]: null });
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDismissEdit = anchorName => {
|
||||||
|
setDialogOpened(null);
|
||||||
|
setAnchorEl({ ...anchorEl, [anchorName]: null });
|
||||||
|
};
|
||||||
|
|
||||||
|
const layoutResolver = (state, layoutType) => {
|
||||||
|
if (layoutType === 'desktop') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return (
|
||||||
|
<Grid sx={container} container spacing={2}>
|
||||||
|
<Grid sx={{ padding: '0 !important' }} item xs={4}>
|
||||||
|
{createArrayFrom1ToN(3).map(i => (
|
||||||
|
<Skeleton
|
||||||
|
key={i}
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={200}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
<Grid sx={{ paddingTop: '0 !important' }} item xs={8}>
|
||||||
|
{createArrayFrom1ToN(4).map(i => (
|
||||||
|
<Skeleton
|
||||||
|
key={i}
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={250}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
|
||||||
|
case 'idle':
|
||||||
|
return (
|
||||||
|
<Grid sx={container} container spacing={2}>
|
||||||
|
<Grid sx={{ padding: '0 !important' }} item xs={4}>
|
||||||
|
<Stack gap="30px">
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px', paddingTop: '10px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<Container
|
||||||
|
disableGutters
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack direction="row">
|
||||||
|
<img src={jitsiLogo} alt="Jitsi Meet" />
|
||||||
|
<h3 style={{ fontWeight: 500 }}>
|
||||||
|
Sala de aula virtual
|
||||||
|
</h3>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Tooltip title="Opcoes">
|
||||||
|
<IconButton
|
||||||
|
onClick={e =>
|
||||||
|
setAnchorEl({
|
||||||
|
...anchorEl,
|
||||||
|
virtualRoom: e.currentTarget,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
aria-label="edit"
|
||||||
|
size="medium"
|
||||||
|
>
|
||||||
|
<MoreVertIcon fontSize="inherit" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Menu
|
||||||
|
id="menu-appbar-virtual-room"
|
||||||
|
anchorEl={anchorEl.virtualRoom}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
open={Boolean(anchorEl.virtualRoom)}
|
||||||
|
onClose={() =>
|
||||||
|
setAnchorEl({ ...anchorEl, virtualRoom: null })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => setDialogOpened('virtualRoom')}
|
||||||
|
>
|
||||||
|
<Typography textAlign="center">Editar</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
<FormDialog
|
||||||
|
isOpened={dialogOpened === 'virtualRoom'}
|
||||||
|
title="Alterar url da sala de aula virtual"
|
||||||
|
contentText="Edite o campo abaixo para alterar a url da sua sala de aula virtual."
|
||||||
|
inputs={[
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
margin="dense"
|
||||||
|
name="virtualRoom"
|
||||||
|
type="text"
|
||||||
|
value={classroom.virtualRoom}
|
||||||
|
onChange={onChangeEditInput}
|
||||||
|
fullWidth
|
||||||
|
variant="standard"
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
onDismiss={() => onDismissEdit('virtualRoom')}
|
||||||
|
onSave={() => onSaveEdit('virtualRoom')}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
sx={{ marginTop: '15px' }}
|
||||||
|
variant="contained"
|
||||||
|
href={classroom.virtualRoom}
|
||||||
|
target="__blank"
|
||||||
|
>
|
||||||
|
Iniciar aula
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px', paddingTop: '10px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<h3 style={{ fontWeight: 500 }}>Próximas Atividades</h3>
|
||||||
|
{announcementsTabData.upcomingAssignments.length !== 0 ? (
|
||||||
|
announcementsTabData.upcomingAssignments.map(ua => (
|
||||||
|
<Link
|
||||||
|
href={`/assignment/${ua.id}`}
|
||||||
|
sx={{ fontSize: '15px' }}
|
||||||
|
key={ua.id}
|
||||||
|
>
|
||||||
|
{ua.title}
|
||||||
|
</Link>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container disableGutters>
|
||||||
|
<p>Nenhuma atividade encontrada!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px', paddingTop: '10px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<Container
|
||||||
|
disableGutters
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h3 style={{ fontWeight: 500 }}>
|
||||||
|
Horários de Atendimento
|
||||||
|
</h3>
|
||||||
|
<Tooltip title="Opcoes">
|
||||||
|
<IconButton
|
||||||
|
onClick={e =>
|
||||||
|
setAnchorEl({
|
||||||
|
...anchorEl,
|
||||||
|
appointmentSlots: e.currentTarget,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
aria-label="edit"
|
||||||
|
size="medium"
|
||||||
|
>
|
||||||
|
<MoreVertIcon fontSize="inherit" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Menu
|
||||||
|
id="menu-appbar-appointment-slots"
|
||||||
|
anchorEl={anchorEl.appointmentSlots}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
open={Boolean(anchorEl.appointmentSlots)}
|
||||||
|
onClose={() =>
|
||||||
|
setAnchorEl({ ...anchorEl, appointmentSlots: null })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => setDialogOpened('appointmentSlots')}
|
||||||
|
>
|
||||||
|
<Typography textAlign="center">Editar</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
<FormDialog
|
||||||
|
isOpened={dialogOpened === 'appointmentSlots'}
|
||||||
|
title="Alterar horarios de atendimento"
|
||||||
|
contentText="Edite os campos abaixo para alterar os horarios de atendimento da disciplina."
|
||||||
|
inputs={[
|
||||||
|
classroom.appointmentSlots.map((appts, index) => (
|
||||||
|
<TextField
|
||||||
|
key={index}
|
||||||
|
autoFocus
|
||||||
|
margin="dense"
|
||||||
|
name={index}
|
||||||
|
type="text"
|
||||||
|
value={`${appts.weekDay}, ${appts.start}h - ${appts.end}h`}
|
||||||
|
onChange={onChangeEditInput}
|
||||||
|
fullWidth
|
||||||
|
variant="standard"
|
||||||
|
/>
|
||||||
|
)),
|
||||||
|
]}
|
||||||
|
onDismiss={() => onDismissEdit('appointmentSlots')}
|
||||||
|
onSave={() => onSaveEdit('appointmentSlots')}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
{classroom.appointmentSlots.map((appts, index) => (
|
||||||
|
<Typography key={index} variant="body1">
|
||||||
|
{appts.weekDay}, {appts.start}h - {appts.end}h
|
||||||
|
</Typography>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
<Grid sx={{ paddingTop: '0 !important' }} item xs={8}>
|
||||||
|
<Stack
|
||||||
|
sx={{ width: '100%', paddingTop: 0 }}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
flexWrap="wrap"
|
||||||
|
direction="row"
|
||||||
|
gap="30px"
|
||||||
|
>
|
||||||
|
<PublishAnnouncementCard
|
||||||
|
layoutType={layoutType}
|
||||||
|
user={user}
|
||||||
|
value={composingTextValue}
|
||||||
|
onChange={e => setComposingTextValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
{announcementsTabData.announcements.length !== 0 ? (
|
||||||
|
announcementsTabData.announcements.map(announcement => (
|
||||||
|
<AnnouncementCard
|
||||||
|
key={announcement.id}
|
||||||
|
announcement={announcement}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum comunicado encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (layoutType === 'mobile') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
flexWrap="wrap"
|
||||||
|
direction="row"
|
||||||
|
gap="30px"
|
||||||
|
sx={{ marginTop: '30px' }}
|
||||||
|
>
|
||||||
|
{createArrayFrom1ToN(3).map(i => (
|
||||||
|
<Skeleton
|
||||||
|
key={i}
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={200}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{createArrayFrom1ToN(4).map(i => (
|
||||||
|
<Skeleton
|
||||||
|
key={i}
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={250}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
|
||||||
|
case 'idle':
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
flexWrap="wrap"
|
||||||
|
direction="row"
|
||||||
|
gap="30px"
|
||||||
|
sx={{ marginTop: '30px' }}
|
||||||
|
>
|
||||||
|
<Stack gap="30px" sx={{ width: '100%' }}>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px', paddingTop: '10px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<Container
|
||||||
|
disableGutters
|
||||||
|
sx={{ display: 'flex', justifyContent: 'space-between' }}
|
||||||
|
>
|
||||||
|
<Stack direction="row">
|
||||||
|
<img src={jitsiLogo} alt="Jitsi Meet" />
|
||||||
|
<h3 style={{ fontWeight: 500 }}>
|
||||||
|
Sala de aula virtual
|
||||||
|
</h3>
|
||||||
|
</Stack>
|
||||||
|
<Tooltip title="Opcoes">
|
||||||
|
<IconButton
|
||||||
|
onClick={e => setAnchorEl(e.currentTarget)}
|
||||||
|
aria-label="edit"
|
||||||
|
size="medium"
|
||||||
|
>
|
||||||
|
<MoreVertIcon fontSize="inherit" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Menu
|
||||||
|
id="menu-appbar"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={() => setAnchorEl(null)}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => setDialogOpened('virtualRoom')}
|
||||||
|
>
|
||||||
|
<Typography textAlign="center">Editar</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
<FormDialog
|
||||||
|
isOpened={dialogOpened === 'virtualRoom'}
|
||||||
|
title="Alterar url da sala de aula virtual"
|
||||||
|
contentText="Edite o campo abaixo para alterar a url da sua sala de aula virtual."
|
||||||
|
inputs={[
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
margin="dense"
|
||||||
|
name="virtualRoom"
|
||||||
|
type="text"
|
||||||
|
value={classroom.virtualRoom}
|
||||||
|
onChange={onChangeEditInput}
|
||||||
|
fullWidth
|
||||||
|
variant="standard"
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
onDismiss={() => onDismissEdit('virtualRoom')}
|
||||||
|
onSave={() => onSaveEdit('virtualRoom')}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
href={classroom.virtualRoom}
|
||||||
|
target="__blank"
|
||||||
|
>
|
||||||
|
Iniciar aula
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px', paddingTop: '10px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<h3 style={{ fontWeight: 500 }}>Próximas Atividades</h3>
|
||||||
|
|
||||||
|
{announcementsTabData.upcomingAssignments.length !== 0 ? (
|
||||||
|
announcementsTabData.upcomingAssignments.map(ua => (
|
||||||
|
<Link
|
||||||
|
href={`/assignment/${ua.id}`}
|
||||||
|
sx={{ fontSize: '15px' }}
|
||||||
|
key={ua.id}
|
||||||
|
>
|
||||||
|
{ua.title}
|
||||||
|
</Link>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container disableGutters>
|
||||||
|
<p>Nenhuma atividade encontrada!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px', paddingTop: '10px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<h3 style={{ fontWeight: 500 }}>Horários de Atendimento</h3>
|
||||||
|
{classroom.appointmentSlots.map((appts, index) => (
|
||||||
|
<Typography key={index} variant="body1">
|
||||||
|
{appts.weekDay}, {appts.start}h - {appts.end}h
|
||||||
|
</Typography>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
sx={{ width: '100%' }}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
flexWrap="wrap"
|
||||||
|
direction="row"
|
||||||
|
gap="30px"
|
||||||
|
>
|
||||||
|
<PublishAnnouncementCard
|
||||||
|
layoutType={layoutType}
|
||||||
|
user={user}
|
||||||
|
value={composingTextValue}
|
||||||
|
onChange={e => setComposingTextValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
{announcementsTabData.announcements.length !== 0 ? (
|
||||||
|
announcementsTabData.announcements.map(announcement => (
|
||||||
|
<AnnouncementCard
|
||||||
|
key={announcement.id}
|
||||||
|
announcement={announcement}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum comunicado encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return layoutResolver(
|
||||||
|
announcementsTabData && announcementsTabData.state,
|
||||||
|
layoutType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnnouncementsTab;
|
49
src/screens/professor/Classroom/AnnouncementsTab/styles.js
Normal file
49
src/screens/professor/Classroom/AnnouncementsTab/styles.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// ========== Desktop ==========
|
||||||
|
const desktopContainer = {
|
||||||
|
width: '100%',
|
||||||
|
height: '100vh',
|
||||||
|
backgroundColor: '#red',
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
marginTop: '50px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopEmptyStateContainer = {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktop = {
|
||||||
|
container: desktopContainer,
|
||||||
|
emptyStateContainer: desktopEmptyStateContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Mobile ==========
|
||||||
|
const mobileContainer = {
|
||||||
|
width: '90%',
|
||||||
|
backgroundColor: '#red',
|
||||||
|
padding: 0,
|
||||||
|
marginTop: '30px',
|
||||||
|
paddingBottom: '100px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileEmptyStateContainer = {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobile = {
|
||||||
|
container: mobileContainer,
|
||||||
|
emptyStateContainer: mobileEmptyStateContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Unset ==========
|
||||||
|
const unset = {
|
||||||
|
container: null,
|
||||||
|
emptyStateContainer: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
413
src/screens/professor/Classroom/AssignmentsTab/index.js
Normal file
413
src/screens/professor/Classroom/AssignmentsTab/index.js
Normal file
|
@ -0,0 +1,413 @@
|
||||||
|
import {
|
||||||
|
Container,
|
||||||
|
Fab,
|
||||||
|
Link,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material';
|
||||||
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { capitalizeFirstLetter } from '../../../../utils/capitalizeFirstLetter';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
function AssignmentsTab({ assignmentsTabData, layoutType }) {
|
||||||
|
const layoutResolver = (state, assignments, layoutType) => {
|
||||||
|
const {
|
||||||
|
externalContainer,
|
||||||
|
innerContainer,
|
||||||
|
sectionTitle,
|
||||||
|
assignmentContainer,
|
||||||
|
assignmentTypography,
|
||||||
|
assignmentLink,
|
||||||
|
assignmentDueDate,
|
||||||
|
assignmentScores,
|
||||||
|
emptyStateContainer,
|
||||||
|
} = styles[layoutType];
|
||||||
|
if (layoutType === 'desktop') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
sx={{
|
||||||
|
...externalContainer,
|
||||||
|
display: 'block',
|
||||||
|
}}
|
||||||
|
disableGutters
|
||||||
|
>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="90%"
|
||||||
|
height={70}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
<Stack alignItems="flex-start" sx={{ width: '90%' }}>
|
||||||
|
<Skeleton variant="rectangular" height={50} width="95%" />
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
height={20}
|
||||||
|
width={450}
|
||||||
|
sx={{ marginTop: '25px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
height={20}
|
||||||
|
width={300}
|
||||||
|
sx={{ marginTop: '15px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
alignItems="flex-start"
|
||||||
|
sx={{ width: '90%', marginTop: '30px' }}
|
||||||
|
>
|
||||||
|
<Skeleton variant="rectangular" height={50} width="95%" />
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
height={20}
|
||||||
|
width={450}
|
||||||
|
sx={{ marginTop: '25px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
height={20}
|
||||||
|
width={300}
|
||||||
|
sx={{ marginTop: '15px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack sx={{ marginTop: '50px' }} alignItems="center">
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="90%"
|
||||||
|
height={70}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
<Stack alignItems="flex-start" sx={{ width: '90%' }}>
|
||||||
|
<Skeleton variant="rectangular" height={50} width="95%" />
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
height={20}
|
||||||
|
width={450}
|
||||||
|
sx={{ marginTop: '25px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
height={20}
|
||||||
|
width={300}
|
||||||
|
sx={{ marginTop: '15px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
case 'idle':
|
||||||
|
const assesments = assignments.filter(a => a.type === 'assessment');
|
||||||
|
const projects = assignments.filter(a => a.type === 'project');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container sx={externalContainer} disableGutters>
|
||||||
|
<Fab
|
||||||
|
sx={{
|
||||||
|
width: 'fit-content',
|
||||||
|
marginRight: '5%',
|
||||||
|
borderRadius: '4px',
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
aria-label="add"
|
||||||
|
variant="extended"
|
||||||
|
>
|
||||||
|
<AddIcon />
|
||||||
|
Criar atividade
|
||||||
|
</Fab>
|
||||||
|
<Container sx={innerContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h4">
|
||||||
|
Provas
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{assesments.length !== 0 ? (
|
||||||
|
assesments.map(a => (
|
||||||
|
<Container
|
||||||
|
key={a.id}
|
||||||
|
sx={assignmentContainer}
|
||||||
|
disableGutters
|
||||||
|
>
|
||||||
|
<Typography variant="h5" sx={assignmentTypography}>
|
||||||
|
<Link
|
||||||
|
sx={assignmentLink}
|
||||||
|
href={`/assignment/${a.id}`}
|
||||||
|
>
|
||||||
|
{a.title}
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentDueDate}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Data de entrega: </strong>{' '}
|
||||||
|
{capitalizeFirstLetter(
|
||||||
|
dayjs(a.dueDate).format('dddd, DD/MM | HH:mm[h]')
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentScores}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Valor: </strong>
|
||||||
|
{a.scores.map(s => s.value).join(', ')} pts
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhuma prova encontrada!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Container sx={innerContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h4">
|
||||||
|
Trabalhos
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{projects.length !== 0 ? (
|
||||||
|
projects.map(a => (
|
||||||
|
<Container
|
||||||
|
key={a.id}
|
||||||
|
sx={assignmentContainer}
|
||||||
|
disableGutters
|
||||||
|
>
|
||||||
|
<Typography variant="h5" sx={assignmentTypography}>
|
||||||
|
<Link
|
||||||
|
sx={assignmentLink}
|
||||||
|
href={`/assignment/${a.id}`}
|
||||||
|
>
|
||||||
|
{a.title}
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentDueDate}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Data de entrega: </strong>{' '}
|
||||||
|
{capitalizeFirstLetter(
|
||||||
|
dayjs(a.dueDate).format('dddd, DD/MM | HH:mm[h]')
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentScores}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Valor: </strong>
|
||||||
|
{a.scores.map(s => s.value).join(', ')} pts
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum trabalho encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (layoutType === 'mobile') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
alignItems="center"
|
||||||
|
flexWrap="wrap"
|
||||||
|
direction="row"
|
||||||
|
sx={{ marginTop: '30px' }}
|
||||||
|
>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={70}
|
||||||
|
sx={{ marginTop: '30px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={30}
|
||||||
|
sx={{ marginTop: '20px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={15}
|
||||||
|
sx={{ marginTop: '20px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width={250}
|
||||||
|
height={15}
|
||||||
|
sx={{ marginTop: '10px' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={70}
|
||||||
|
sx={{ marginTop: '50px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={30}
|
||||||
|
sx={{ marginTop: '20px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="100%"
|
||||||
|
height={15}
|
||||||
|
sx={{ marginTop: '20px' }}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width={250}
|
||||||
|
height={15}
|
||||||
|
sx={{ marginTop: '10px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
case 'idle':
|
||||||
|
const assesments = assignments.filter(a => a.type === 'assessment');
|
||||||
|
const projects = assignments.filter(a => a.type === 'project');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container sx={externalContainer} disableGutters>
|
||||||
|
<Fab
|
||||||
|
sx={{ width: '100%', borderRadius: '4px' }}
|
||||||
|
color="primary"
|
||||||
|
aria-label="add"
|
||||||
|
variant="extended"
|
||||||
|
>
|
||||||
|
<AddIcon />
|
||||||
|
Criar atividade
|
||||||
|
</Fab>
|
||||||
|
<Container sx={innerContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h4">
|
||||||
|
Provas
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{assesments.length !== 0 ? (
|
||||||
|
assesments.map(a => (
|
||||||
|
<Container
|
||||||
|
key={a.id}
|
||||||
|
sx={assignmentContainer}
|
||||||
|
disableGutters
|
||||||
|
>
|
||||||
|
<Typography variant="body1" sx={assignmentTypography}>
|
||||||
|
<Link
|
||||||
|
sx={assignmentLink}
|
||||||
|
href={`/assignment/${a.id}`}
|
||||||
|
>
|
||||||
|
{a.title}
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentDueDate}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Data de entrega: </strong>{' '}
|
||||||
|
{capitalizeFirstLetter(
|
||||||
|
dayjs(a.dueDate).format('dddd, DD/MM | HH:mm[h]')
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentScores}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Valor: </strong>
|
||||||
|
{a.scores.map(s => s.value).join(', ')} pts
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhuma prova encontrada!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Container sx={innerContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h4">
|
||||||
|
Trabalhos
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{projects.length !== 0 ? (
|
||||||
|
projects.map(a => (
|
||||||
|
<Container
|
||||||
|
key={a.id}
|
||||||
|
sx={assignmentContainer}
|
||||||
|
disableGutters
|
||||||
|
>
|
||||||
|
<Typography variant="body1" sx={assignmentTypography}>
|
||||||
|
<Link
|
||||||
|
sx={assignmentLink}
|
||||||
|
href={`/assignment/${a.id}`}
|
||||||
|
>
|
||||||
|
{a.title}
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentDueDate}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Data de entrega: </strong>{' '}
|
||||||
|
{capitalizeFirstLetter(
|
||||||
|
dayjs(a.dueDate).format('dddd, DD/MM | HH:mm[h]')
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={assignmentScores}
|
||||||
|
variant="p"
|
||||||
|
component="div"
|
||||||
|
>
|
||||||
|
<strong>Valor: </strong>
|
||||||
|
{a.scores.map(s => s.value).join(', ')} pts
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum trabalho encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return layoutResolver(
|
||||||
|
assignmentsTabData && assignmentsTabData.state,
|
||||||
|
assignmentsTabData && assignmentsTabData.assignments,
|
||||||
|
layoutType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AssignmentsTab;
|
138
src/screens/professor/Classroom/AssignmentsTab/styles.js
Normal file
138
src/screens/professor/Classroom/AssignmentsTab/styles.js
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
// ========== Desktop ==========
|
||||||
|
const desktopExternalContainer = {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
marginTop: '50px',
|
||||||
|
height: '100vh',
|
||||||
|
alignItems: 'flex-end',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopInnerContainer = {
|
||||||
|
width: '90%',
|
||||||
|
marginBottom: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopSectionTitle = {
|
||||||
|
padding: '10px',
|
||||||
|
borderBottom: '2px solid #00420D',
|
||||||
|
color: '#00420D',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopAssignmentContainer = {
|
||||||
|
width: '95%',
|
||||||
|
padding: '20px',
|
||||||
|
borderBottom: '2px solid #BCBCBC',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopAssignmentTypography = {};
|
||||||
|
|
||||||
|
const desktopAssignmentLink = {
|
||||||
|
color: 'black',
|
||||||
|
textDecoration: 'underline #000000',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopAssignmentDueDate = {
|
||||||
|
marginTop: '15px',
|
||||||
|
fontSize: '15px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopAssignmentScores = {
|
||||||
|
fontSize: '15px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopEmptyStateContainer = {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktop = {
|
||||||
|
externalContainer: desktopExternalContainer,
|
||||||
|
innerContainer: desktopInnerContainer,
|
||||||
|
sectionTitle: desktopSectionTitle,
|
||||||
|
assignmentContainer: desktopAssignmentContainer,
|
||||||
|
assignmentTypography: desktopAssignmentTypography,
|
||||||
|
assignmentLink: desktopAssignmentLink,
|
||||||
|
assignmentDueDate: desktopAssignmentDueDate,
|
||||||
|
assignmentScores: desktopAssignmentScores,
|
||||||
|
emptyStateContainer: desktopEmptyStateContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Mobile ==========
|
||||||
|
const mobileExternalContainer = {
|
||||||
|
marginTop: '50px',
|
||||||
|
height: '100vh',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileInnerContainer = {
|
||||||
|
width: '100%',
|
||||||
|
marginBottom: '30px',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileSectionTitle = {
|
||||||
|
padding: '10px',
|
||||||
|
borderBottom: '2px solid #00420D',
|
||||||
|
color: '#00420D',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileAssignmentContainer = {
|
||||||
|
width: '100%',
|
||||||
|
padding: '20px',
|
||||||
|
borderBottom: '2px solid #BCBCBC',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileAssignmentTypography = {
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileAssignmentLink = {
|
||||||
|
color: 'black',
|
||||||
|
textDecoration: 'underline #000000',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileAssignmentDueDate = {
|
||||||
|
marginTop: '10px',
|
||||||
|
fontSize: '12px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileAssignmentScores = {
|
||||||
|
fontSize: '12px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileEmptyStateContainer = {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobile = {
|
||||||
|
externalContainer: mobileExternalContainer,
|
||||||
|
innerContainer: mobileInnerContainer,
|
||||||
|
sectionTitle: mobileSectionTitle,
|
||||||
|
assignmentContainer: mobileAssignmentContainer,
|
||||||
|
assignmentTypography: mobileAssignmentTypography,
|
||||||
|
assignmentLink: mobileAssignmentLink,
|
||||||
|
assignmentDueDate: mobileAssignmentDueDate,
|
||||||
|
assignmentScores: mobileAssignmentScores,
|
||||||
|
emptyStateContainer: mobileEmptyStateContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Unset ==========
|
||||||
|
const unset = {
|
||||||
|
externalContainer: null,
|
||||||
|
innerContainer: null,
|
||||||
|
sectionTitle: null,
|
||||||
|
assignmentContainer: null,
|
||||||
|
assignmentTypography: null,
|
||||||
|
assignmentLink: null,
|
||||||
|
assignmentDueDate: null,
|
||||||
|
assignmentScores: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
34
src/screens/professor/Classroom/GradesTab/index.js
Normal file
34
src/screens/professor/Classroom/GradesTab/index.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
function GradesTab({ gradesTabData, layoutType }) {
|
||||||
|
const layoutResolver = (state, grades, layoutType) => {
|
||||||
|
if (layoutType === 'desktop') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return <h1>Loading...</h1>;
|
||||||
|
case 'idle':
|
||||||
|
return <h1>Grades Tab</h1>;
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (layoutType === 'mobile') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return <h1>Loading...</h1>;
|
||||||
|
case 'idle':
|
||||||
|
return <h1>Grades Tab</h1>;
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return layoutResolver(
|
||||||
|
gradesTabData && gradesTabData.state,
|
||||||
|
gradesTabData && gradesTabData.grades,
|
||||||
|
layoutType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GradesTab;
|
0
src/screens/professor/Classroom/GradesTab/styles.js
Normal file
0
src/screens/professor/Classroom/GradesTab/styles.js
Normal file
62
src/screens/professor/Classroom/Header/index.js
Normal file
62
src/screens/professor/Classroom/Header/index.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
AvatarGroup,
|
||||||
|
Container,
|
||||||
|
Paper,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
Tab,
|
||||||
|
Tabs,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { TAB_OPTIONS } from '../tabOptions';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
function Header({
|
||||||
|
layoutType,
|
||||||
|
classroom,
|
||||||
|
selectedTabOption,
|
||||||
|
onSelectTabOption,
|
||||||
|
isLoading,
|
||||||
|
}) {
|
||||||
|
const { title, paper, tabs, avatar, tooltip } = styles[layoutType];
|
||||||
|
return classroom === null ? (
|
||||||
|
<Skeleton variant="rectangular" width="100%" height={240} />
|
||||||
|
) : (
|
||||||
|
<Container disableGutters>
|
||||||
|
<Paper sx={paper(classroom.color)} elevation={4} variant="elevation">
|
||||||
|
<h1 style={title}>{classroom.name}</h1>
|
||||||
|
<Stack alignItems="center" direction="row" spacing={1}>
|
||||||
|
<AvatarGroup total={classroom.teachers.length}>
|
||||||
|
{classroom.teachers.map(t => (
|
||||||
|
<Avatar key={t.name} alt={t.name} src={t.avatar} sx={avatar} />
|
||||||
|
))}
|
||||||
|
</AvatarGroup>
|
||||||
|
<Tooltip title={classroom.teachers.map(t => t.name).join(', ')}>
|
||||||
|
<Typography sx={tooltip} variant="body3" color="text.secondary">
|
||||||
|
{classroom.teachers.map(t => t.name).join(', ')}
|
||||||
|
</Typography>
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
<Tabs
|
||||||
|
value={selectedTabOption}
|
||||||
|
onChange={onSelectTabOption}
|
||||||
|
aria-label="Tabs para informações da disciplina"
|
||||||
|
variant={layoutType === 'mobile' ? 'scrollable' : 'fullWidth'}
|
||||||
|
sx={tabs}
|
||||||
|
>
|
||||||
|
{Object.values(TAB_OPTIONS).map(option => (
|
||||||
|
<Tab
|
||||||
|
key={option.value}
|
||||||
|
label={option.lable}
|
||||||
|
disabled={isLoading && option.value !== selectedTabOption}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Tabs>
|
||||||
|
</Paper>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header;
|
90
src/screens/professor/Classroom/Header/styles.js
Normal file
90
src/screens/professor/Classroom/Header/styles.js
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// ========== Desktop ==========
|
||||||
|
const desktopTitle = {
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopPaper = classColor => ({
|
||||||
|
width: '100%',
|
||||||
|
borderTop: `5px solid ${classColor}`,
|
||||||
|
padding: '30px',
|
||||||
|
});
|
||||||
|
|
||||||
|
const desktopTabs = {
|
||||||
|
marginLeft: '-20px',
|
||||||
|
marginRight: '-20px',
|
||||||
|
marginBottom: '-30px',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopAvatar = {
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopTooltip = {
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktop = {
|
||||||
|
title: desktopTitle,
|
||||||
|
paper: desktopPaper,
|
||||||
|
tabs: desktopTabs,
|
||||||
|
avatar: desktopAvatar,
|
||||||
|
tooltip: desktopTooltip,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Mobile ==========
|
||||||
|
const mobileTitle = {
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: '25px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobilePaper = classColor => ({
|
||||||
|
width: '100%',
|
||||||
|
borderTop: `5px solid ${classColor}`,
|
||||||
|
padding: '20px',
|
||||||
|
});
|
||||||
|
|
||||||
|
const mobileTabs = {
|
||||||
|
marginLeft: '-10px',
|
||||||
|
marginRight: '-10px',
|
||||||
|
marginBottom: '-20px',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileAvatar = {
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileTooltip = {
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobile = {
|
||||||
|
title: mobileTitle,
|
||||||
|
paper: mobilePaper,
|
||||||
|
tabs: mobileTabs,
|
||||||
|
avatar: mobileAvatar,
|
||||||
|
tooltip: mobileTooltip,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Unset ==========
|
||||||
|
const unset = {
|
||||||
|
title: null,
|
||||||
|
paper: null,
|
||||||
|
tabs: null,
|
||||||
|
avatar: null,
|
||||||
|
tooltip: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
|
@ -1,5 +1,5 @@
|
||||||
import { Avatar, Container, Skeleton, Stack, Typography } from '@mui/material';
|
import { Avatar, Container, Skeleton, Stack, Typography } from '@mui/material';
|
||||||
import { createArrayFrom1ToN } from '../../../utils/createArrayFrom1ToN';
|
import { createArrayFrom1ToN } from '../../../../utils/createArrayFrom1ToN';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
function PeopleTab({ layoutType, peopleTabData }) {
|
function PeopleTab({ layoutType, peopleTabData }) {
|
|
@ -24,12 +24,14 @@ const desktopPersonContainer = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const desktopPersonAvatar = {
|
const desktopPersonAvatar = {
|
||||||
width: '60px',
|
width: '50px',
|
||||||
height: '60px',
|
height: '50px',
|
||||||
marginRight: '15px',
|
marginRight: '15px',
|
||||||
};
|
};
|
||||||
|
|
||||||
const desktopPersonName = {};
|
const desktopPersonName = {
|
||||||
|
fontSize: '1.3em',
|
||||||
|
};
|
||||||
|
|
||||||
const desktopEmptyStateContainer = {
|
const desktopEmptyStateContainer = {
|
||||||
display: 'flex',
|
display: 'flex',
|
51
src/screens/professor/Classroom/View.js
Normal file
51
src/screens/professor/Classroom/View.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import { Container } from '@mui/system';
|
||||||
|
import AnnouncementsTab from './AnnouncementsTab';
|
||||||
|
import AssignmentsTab from './AssignmentsTab';
|
||||||
|
import GradesTab from './GradesTab';
|
||||||
|
import Header from './Header';
|
||||||
|
import PeopleTab from './PeopleTab';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
function View({
|
||||||
|
layoutType,
|
||||||
|
classroom,
|
||||||
|
selectedTabOption,
|
||||||
|
onSelectTabOption,
|
||||||
|
announcementsTabData,
|
||||||
|
assignmentsTabData,
|
||||||
|
peopleTabData,
|
||||||
|
gradesTabData,
|
||||||
|
user,
|
||||||
|
onChangeEditInput,
|
||||||
|
onSaveEditChanges,
|
||||||
|
isLoading,
|
||||||
|
}) {
|
||||||
|
const { container } = styles[layoutType];
|
||||||
|
return (
|
||||||
|
<Container disableGutters sx={container}>
|
||||||
|
<Header
|
||||||
|
layoutType={layoutType}
|
||||||
|
classroom={classroom && classroom}
|
||||||
|
selectedTabOption={selectedTabOption}
|
||||||
|
onSelectTabOption={onSelectTabOption}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<AnnouncementsTab
|
||||||
|
layoutType={layoutType}
|
||||||
|
announcementsTabData={announcementsTabData}
|
||||||
|
classroom={classroom && classroom}
|
||||||
|
user={user && user}
|
||||||
|
onChangeEditInput={onChangeEditInput}
|
||||||
|
onSaveEditChanges={onSaveEditChanges}
|
||||||
|
/>
|
||||||
|
<AssignmentsTab
|
||||||
|
layoutType={layoutType}
|
||||||
|
assignmentsTabData={assignmentsTabData}
|
||||||
|
/>
|
||||||
|
<PeopleTab layoutType={layoutType} peopleTabData={peopleTabData} />
|
||||||
|
<GradesTab layoutType={layoutType} gradesTabData={gradesTabData} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default View;
|
156
src/screens/professor/Classroom/index.js
Normal file
156
src/screens/professor/Classroom/index.js
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { useUser } from '../../../context/user';
|
||||||
|
import useLayoutType from '../../../hooks/useLayoutType';
|
||||||
|
import { TAB_OPTIONS } from './tabOptions';
|
||||||
|
import View from './View';
|
||||||
|
|
||||||
|
function Classroom() {
|
||||||
|
const params = useParams();
|
||||||
|
const layoutType = useLayoutType();
|
||||||
|
const { userService, state } = useUser();
|
||||||
|
const [classroom, setClassroom] = useState(null);
|
||||||
|
const [tabData, setTabData] = useState(null);
|
||||||
|
|
||||||
|
const [selectedTabOption, setSelectedTabOption] = useState(
|
||||||
|
TAB_OPTIONS.announcements.value
|
||||||
|
);
|
||||||
|
|
||||||
|
const onChangeEditInput = e => {
|
||||||
|
const name = e.target.name;
|
||||||
|
const value = e.target.value;
|
||||||
|
|
||||||
|
setClassroom(prev => ({ ...prev, [name]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSaveEditChanges = () => {
|
||||||
|
console.log('Saving edit changes...');
|
||||||
|
console.log(classroom);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchAndPopulateAnnouncementsTabData = useCallback(async () => {
|
||||||
|
setTabData({ tab: 'announcements', state: 'loading' });
|
||||||
|
const announcements = await userService.fetchClassroomAnnouncements(
|
||||||
|
params.id
|
||||||
|
);
|
||||||
|
|
||||||
|
const upcomingAssignments =
|
||||||
|
await userService.fetchUpcomingAssignmentsByClassId(params.id);
|
||||||
|
|
||||||
|
setTabData({
|
||||||
|
tab: 'announcements',
|
||||||
|
state: 'idle',
|
||||||
|
announcements: [...announcements.data],
|
||||||
|
upcomingAssignments: [...upcomingAssignments.data],
|
||||||
|
});
|
||||||
|
}, [userService, params.id]);
|
||||||
|
|
||||||
|
const fetchAndPopulateAssignmentsTabData = useCallback(async () => {
|
||||||
|
setTabData({ tab: 'assignments', state: 'loading' });
|
||||||
|
const assignments = await userService.fetchAssignmentsByClassId(params.id);
|
||||||
|
|
||||||
|
setTabData({
|
||||||
|
tab: 'assignments',
|
||||||
|
state: 'idle',
|
||||||
|
assignments: [...assignments.data],
|
||||||
|
});
|
||||||
|
}, [userService, params.id]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function getClassroomById(classId) {
|
||||||
|
document.title = 'Carregando...';
|
||||||
|
const result = await userService.fetchClassroomById(classId);
|
||||||
|
setClassroom(result.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDocumentTitle() {
|
||||||
|
if (classroom !== null) {
|
||||||
|
document.title = classroom.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!classroom) {
|
||||||
|
getClassroomById(params.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDocumentTitle();
|
||||||
|
}, [userService, userService.fetchClassroomById, params, classroom]);
|
||||||
|
|
||||||
|
const fetchAndPopulatePeopleTabData = useCallback(async () => {
|
||||||
|
setTabData({ tab: 'people', state: 'loading' });
|
||||||
|
const people = await userService.fetchPeopleByClassId(params.id);
|
||||||
|
|
||||||
|
setTabData({
|
||||||
|
tab: 'people',
|
||||||
|
state: 'idle',
|
||||||
|
people: [...people.data],
|
||||||
|
});
|
||||||
|
}, [userService, params.id]);
|
||||||
|
|
||||||
|
const fetchAndPopulateGradesTabData = useCallback(async () => {
|
||||||
|
setTabData({ tab: 'people', state: 'loading' });
|
||||||
|
const grades = await userService.fetchPeopleByClassId(params.id);
|
||||||
|
|
||||||
|
setTabData({
|
||||||
|
tab: 'grades',
|
||||||
|
state: 'idle',
|
||||||
|
grades: [...grades.data],
|
||||||
|
});
|
||||||
|
}, [userService, params.id]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function getSelectedTabData() {
|
||||||
|
switch (selectedTabOption) {
|
||||||
|
case TAB_OPTIONS.announcements.value:
|
||||||
|
fetchAndPopulateAnnouncementsTabData();
|
||||||
|
break;
|
||||||
|
case TAB_OPTIONS.assignments.value:
|
||||||
|
fetchAndPopulateAssignmentsTabData();
|
||||||
|
break;
|
||||||
|
case TAB_OPTIONS.people.value:
|
||||||
|
fetchAndPopulatePeopleTabData();
|
||||||
|
break;
|
||||||
|
case TAB_OPTIONS.grades.value:
|
||||||
|
fetchAndPopulateGradesTabData();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('Invalid tab option');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getSelectedTabData();
|
||||||
|
}, [
|
||||||
|
selectedTabOption,
|
||||||
|
params,
|
||||||
|
fetchAndPopulateAnnouncementsTabData,
|
||||||
|
fetchAndPopulateAssignmentsTabData,
|
||||||
|
fetchAndPopulatePeopleTabData,
|
||||||
|
fetchAndPopulateGradesTabData,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
layoutType={layoutType}
|
||||||
|
classroom={classroom}
|
||||||
|
selectedTabOption={selectedTabOption}
|
||||||
|
onSelectTabOption={(_, value) => setSelectedTabOption(value)}
|
||||||
|
announcementsTabData={
|
||||||
|
tabData && tabData.tab === 'announcements' ? tabData : { state: 'gone' }
|
||||||
|
}
|
||||||
|
assignmentsTabData={
|
||||||
|
tabData && tabData.tab === 'assignments' ? tabData : { state: 'gone' }
|
||||||
|
}
|
||||||
|
peopleTabData={
|
||||||
|
tabData && tabData.tab === 'people' ? tabData : { state: 'gone' }
|
||||||
|
}
|
||||||
|
gradesTabData={
|
||||||
|
tabData && tabData.tab === 'grades' ? tabData : { state: 'gone' }
|
||||||
|
}
|
||||||
|
user={state && state.user}
|
||||||
|
onChangeEditInput={onChangeEditInput}
|
||||||
|
onSaveEditChanges={onSaveEditChanges}
|
||||||
|
isLoading={tabData && tabData.state === 'loading'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Classroom;
|
20
src/screens/professor/Classroom/tabOptions.js
Normal file
20
src/screens/professor/Classroom/tabOptions.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
const TAB_OPTIONS = {
|
||||||
|
announcements: {
|
||||||
|
value: 0,
|
||||||
|
lable: 'Comunicados',
|
||||||
|
},
|
||||||
|
assignments: {
|
||||||
|
value: 1,
|
||||||
|
lable: 'Atividades',
|
||||||
|
},
|
||||||
|
people: {
|
||||||
|
value: 2,
|
||||||
|
lable: 'Pessoas',
|
||||||
|
},
|
||||||
|
grades: {
|
||||||
|
value: 3,
|
||||||
|
lable: 'Notas',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export { TAB_OPTIONS };
|
|
@ -1,8 +1,11 @@
|
||||||
import { Grid, Skeleton, Stack } from '@mui/material';
|
import { Grid, Skeleton, Stack } from '@mui/material';
|
||||||
import { Container } from '@mui/system';
|
import { Container } from '@mui/system';
|
||||||
import AssignmentCard from '../../../components/AssignmentCard';
|
|
||||||
|
import AssignmentCard from '../../../components/professor/AssignmentCard';
|
||||||
import ClassCard from '../../../components/ClassCard';
|
import ClassCard from '../../../components/ClassCard';
|
||||||
|
|
||||||
import { createArrayFrom1ToN } from '../../../utils/createArrayFrom1ToN';
|
import { createArrayFrom1ToN } from '../../../utils/createArrayFrom1ToN';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
function View({
|
function View({
|
||||||
|
@ -81,11 +84,9 @@ function View({
|
||||||
title={assignment.title}
|
title={assignment.title}
|
||||||
classrooms={assignment.classrooms}
|
classrooms={assignment.classrooms}
|
||||||
dueDate={assignment.dueDate}
|
dueDate={assignment.dueDate}
|
||||||
scores={assignment.scores}
|
|
||||||
layoutType={layoutType}
|
layoutType={layoutType}
|
||||||
deliveredByStudents={assignment.deliveredByStudents}
|
deliveredByStudents={assignment.deliveredByStudents}
|
||||||
reviewed={assignment.reviewed}
|
reviewed={assignment.reviewed}
|
||||||
isAssignmentToReview={assignment.status !== null}
|
|
||||||
total={assignment.total}
|
total={assignment.total}
|
||||||
onClick={() => onClickAssignmentCard(assignment.id)}
|
onClick={() => onClickAssignmentCard(assignment.id)}
|
||||||
/>
|
/>
|
||||||
|
@ -170,11 +171,9 @@ function View({
|
||||||
title={assignment.title}
|
title={assignment.title}
|
||||||
classrooms={assignment.classrooms}
|
classrooms={assignment.classrooms}
|
||||||
dueDate={assignment.dueDate}
|
dueDate={assignment.dueDate}
|
||||||
scores={assignment.scores}
|
|
||||||
layoutType={layoutType}
|
layoutType={layoutType}
|
||||||
deliveredByStudents={assignment.deliveredByStudents}
|
deliveredByStudents={assignment.deliveredByStudents}
|
||||||
reviewed={assignment.reviewed}
|
reviewed={assignment.reviewed}
|
||||||
isAssignmentToReview={assignment.status !== null}
|
|
||||||
total={assignment.total}
|
total={assignment.total}
|
||||||
onClick={() => onClickAssignmentCard(assignment.id)}
|
onClick={() => onClickAssignmentCard(assignment.id)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -8,11 +8,11 @@ import {
|
||||||
Stack,
|
Stack,
|
||||||
Typography,
|
Typography,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import AnnouncementCard from '../../../components/AnnouncementCard';
|
import AnnouncementCard from '../../../../components/AnnouncementCard';
|
||||||
import { createArrayFrom1ToN } from '../../../utils/createArrayFrom1ToN';
|
import { createArrayFrom1ToN } from '../../../../utils/createArrayFrom1ToN';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import jitsiLogo from '../../../assets/jitsi.svg';
|
import jitsiLogo from '../../../../assets/jitsi.svg';
|
||||||
|
|
||||||
function AnnouncementsTab({ layoutType, announcementsTabData, classroom }) {
|
function AnnouncementsTab({ layoutType, announcementsTabData, classroom }) {
|
||||||
const { container, emptyStateContainer } = styles[layoutType];
|
const { container, emptyStateContainer } = styles[layoutType];
|
||||||
|
@ -64,7 +64,9 @@ function AnnouncementsTab({ layoutType, announcementsTabData, classroom }) {
|
||||||
sx={{ display: 'flex', justifyContent: 'row' }}
|
sx={{ display: 'flex', justifyContent: 'row' }}
|
||||||
>
|
>
|
||||||
<img src={jitsiLogo} alt="Jitsi Meet" />
|
<img src={jitsiLogo} alt="Jitsi Meet" />
|
||||||
<h3 style={{ fontWeight: 500 }}>Jitsi</h3>
|
<h3 style={{ fontWeight: 500 }}>
|
||||||
|
Sala de aula virtual
|
||||||
|
</h3>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
@ -205,7 +207,7 @@ function AnnouncementsTab({ layoutType, announcementsTabData, classroom }) {
|
||||||
sx={{ display: 'flex', justifyContent: 'row' }}
|
sx={{ display: 'flex', justifyContent: 'row' }}
|
||||||
>
|
>
|
||||||
<img src={jitsiLogo} alt="Jitsi Meet" />
|
<img src={jitsiLogo} alt="Jitsi Meet" />
|
||||||
<h3 style={{ fontWeight: 500 }}>Jitsi</h3>
|
<h3 style={{ fontWeight: 500 }}>Sala de aula virtual</h3>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
<Button
|
<Button
|
|
@ -1,6 +1,6 @@
|
||||||
import { Container, Link, Skeleton, Stack, Typography } from '@mui/material';
|
import { Container, Link, Skeleton, Stack, Typography } from '@mui/material';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { capitalizeFirstLetter } from '../../../utils/capitalizeFirstLetter';
|
import { capitalizeFirstLetter } from '../../../../utils/capitalizeFirstLetter';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
function AssignmentsTab({ assignmentsTabData, layoutType }) {
|
function AssignmentsTab({ assignmentsTabData, layoutType }) {
|
244
src/screens/student/Classroom/PeopleTab/index.js
Normal file
244
src/screens/student/Classroom/PeopleTab/index.js
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
import { Avatar, Container, Skeleton, Stack, Typography } from '@mui/material';
|
||||||
|
import { createArrayFrom1ToN } from '../../../../utils/createArrayFrom1ToN';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
function PeopleTab({ layoutType, peopleTabData }) {
|
||||||
|
const layoutResolver = (state, people, layoutType) => {
|
||||||
|
const {
|
||||||
|
externalContainer,
|
||||||
|
sectionContainer,
|
||||||
|
sectionTitle,
|
||||||
|
personContainer,
|
||||||
|
personAvatar,
|
||||||
|
personName,
|
||||||
|
emptyStateContainer,
|
||||||
|
} = styles[layoutType];
|
||||||
|
if (layoutType === 'desktop') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return (
|
||||||
|
<Container sx={externalContainer} disableGutters>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="90%"
|
||||||
|
height={70}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
<Stack
|
||||||
|
flexDirection="row"
|
||||||
|
alignItems="center"
|
||||||
|
sx={{ width: '90%', marginLeft: '20px' }}
|
||||||
|
>
|
||||||
|
<Skeleton variant="circular" width={60} height={60} />
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="70%"
|
||||||
|
height={40}
|
||||||
|
sx={{ marginLeft: '15px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack alignItems="center">
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="90%"
|
||||||
|
height={70}
|
||||||
|
sx={{ marginBottom: '30px', marginTop: '50px' }}
|
||||||
|
/>
|
||||||
|
{createArrayFrom1ToN(5).map(i => (
|
||||||
|
<Stack
|
||||||
|
key={i}
|
||||||
|
flexDirection="row"
|
||||||
|
alignItems="center"
|
||||||
|
sx={{ width: '90%', marginLeft: '20px', marginTop: '25px' }}
|
||||||
|
>
|
||||||
|
<Skeleton variant="circular" width={60} height={60} />
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="70%"
|
||||||
|
height={40}
|
||||||
|
sx={{ marginLeft: '15px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
case 'idle':
|
||||||
|
const professors = people.filter(p => p.role === 'PROFESSOR');
|
||||||
|
const students = people.filter(p => p.role === 'STUDENT');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container sx={externalContainer} disableGutters>
|
||||||
|
<Container sx={sectionContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h4">
|
||||||
|
Docentes
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{professors.length !== 0 ? (
|
||||||
|
professors.map(p => (
|
||||||
|
<Container key={p.id} sx={personContainer} disableGutters>
|
||||||
|
<Avatar alt={p.name} src={p.avatar} sx={personAvatar} />
|
||||||
|
<Typography sx={personName} variant="h5">
|
||||||
|
{p.name}
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum professor encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Container sx={sectionContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h4">
|
||||||
|
Discentes
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{students.length !== 0 ? (
|
||||||
|
students.map(p => (
|
||||||
|
<Container key={p.id} sx={personContainer} disableGutters>
|
||||||
|
<Avatar alt={p.name} src={p.avatar} sx={personAvatar} />
|
||||||
|
<Typography sx={personName} variant="h5">
|
||||||
|
{p.name}
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum estudante encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (layoutType === 'mobile') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return (
|
||||||
|
<Container sx={externalContainer} disableGutters>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="90%"
|
||||||
|
height={50}
|
||||||
|
sx={{ marginBottom: '30px' }}
|
||||||
|
/>
|
||||||
|
<Stack
|
||||||
|
flexDirection="row"
|
||||||
|
alignItems="center"
|
||||||
|
sx={{ width: '90%', marginLeft: '20px' }}
|
||||||
|
>
|
||||||
|
<Skeleton variant="circular" width={40} height={40} />
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="80%"
|
||||||
|
height={30}
|
||||||
|
sx={{ marginLeft: '15px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack alignItems="center">
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="90%"
|
||||||
|
height={50}
|
||||||
|
sx={{ marginBottom: '30px', marginTop: '50px' }}
|
||||||
|
/>
|
||||||
|
{createArrayFrom1ToN(5).map(i => (
|
||||||
|
<Stack
|
||||||
|
key={i}
|
||||||
|
flexDirection="row"
|
||||||
|
alignItems="center"
|
||||||
|
sx={{ width: '90%', marginLeft: '20px', marginTop: '25px' }}
|
||||||
|
>
|
||||||
|
<Skeleton variant="circular" width={40} height={40} />
|
||||||
|
<Skeleton
|
||||||
|
variant="rectangular"
|
||||||
|
width="80%"
|
||||||
|
height={30}
|
||||||
|
sx={{ marginLeft: '15px' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
case 'idle':
|
||||||
|
const professors = people.filter(p => p.role === 'PROFESSOR');
|
||||||
|
const students = people.filter(p => p.role === 'STUDENT');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container sx={externalContainer} disableGutters>
|
||||||
|
<Container sx={sectionContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h5">
|
||||||
|
Docentes
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{professors.length !== 0 ? (
|
||||||
|
professors.map(p => (
|
||||||
|
<Container key={p.id} sx={personContainer} disableGutters>
|
||||||
|
<Avatar alt={p.name} src={p.avatar} sx={personAvatar} />
|
||||||
|
<Typography sx={personName} variant="body1">
|
||||||
|
{p.name}
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum professor encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Container sx={sectionContainer} disableGutters>
|
||||||
|
<Typography sx={sectionTitle} variant="h5">
|
||||||
|
Discentes
|
||||||
|
</Typography>
|
||||||
|
<Stack alignItems="center">
|
||||||
|
{students.length !== 0 ? (
|
||||||
|
students.map(p => (
|
||||||
|
<Container key={p.id} sx={personContainer} disableGutters>
|
||||||
|
<Avatar alt={p.name} src={p.avatar} sx={personAvatar} />
|
||||||
|
<Typography sx={personName} variant="body1">
|
||||||
|
{p.name}
|
||||||
|
</Typography>
|
||||||
|
</Container>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Container sx={emptyStateContainer} disableGutters>
|
||||||
|
<p>Nenhum estudante encontrado!</p>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return layoutResolver(
|
||||||
|
peopleTabData && peopleTabData.state,
|
||||||
|
peopleTabData && peopleTabData.people,
|
||||||
|
layoutType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PeopleTab;
|
118
src/screens/student/Classroom/PeopleTab/styles.js
Normal file
118
src/screens/student/Classroom/PeopleTab/styles.js
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
// ========== Desktop ==========
|
||||||
|
const desktopExternalContainer = {
|
||||||
|
marginTop: '50px',
|
||||||
|
height: '100vh',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopSectionContainer = {
|
||||||
|
width: '90%',
|
||||||
|
marginBottom: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopSectionTitle = {
|
||||||
|
padding: '10px',
|
||||||
|
borderBottom: '2px solid #00420D',
|
||||||
|
color: '#00420D',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopPersonContainer = {
|
||||||
|
width: '95%',
|
||||||
|
padding: '20px',
|
||||||
|
borderBottom: '2px solid #BCBCBC',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopPersonAvatar = {
|
||||||
|
width: '50px',
|
||||||
|
height: '50px',
|
||||||
|
marginRight: '15px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopPersonName = {
|
||||||
|
fontSize: '1.3em',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopEmptyStateContainer = {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktop = {
|
||||||
|
externalContainer: desktopExternalContainer,
|
||||||
|
sectionContainer: desktopSectionContainer,
|
||||||
|
sectionTitle: desktopSectionTitle,
|
||||||
|
personContainer: desktopPersonContainer,
|
||||||
|
personAvatar: desktopPersonAvatar,
|
||||||
|
personName: desktopPersonName,
|
||||||
|
emptyStateContainer: desktopEmptyStateContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Mobile ==========
|
||||||
|
const mobileExternalContainer = {
|
||||||
|
marginTop: '50px',
|
||||||
|
height: '100vh',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileSectionContainer = {
|
||||||
|
width: '90%',
|
||||||
|
marginBottom: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileSectionTitle = {
|
||||||
|
padding: '10px',
|
||||||
|
borderBottom: '2px solid #00420D',
|
||||||
|
color: '#00420D',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobilePersonContainer = {
|
||||||
|
width: '95%',
|
||||||
|
padding: '20px',
|
||||||
|
borderBottom: '2px solid #BCBCBC',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobilePersonAvatar = {
|
||||||
|
width: '40px',
|
||||||
|
height: '40px',
|
||||||
|
marginRight: '15px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobilePersonName = {
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 1,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileEmptyStateContainer = {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: '30px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobile = {
|
||||||
|
externalContainer: mobileExternalContainer,
|
||||||
|
sectionContainer: mobileSectionContainer,
|
||||||
|
sectionTitle: mobileSectionTitle,
|
||||||
|
personContainer: mobilePersonContainer,
|
||||||
|
personAvatar: mobilePersonAvatar,
|
||||||
|
personName: mobilePersonName,
|
||||||
|
emptyStateContainer: mobileEmptyStateContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Unset ==========
|
||||||
|
const unset = {
|
||||||
|
externalContainer: null,
|
||||||
|
sectionContainer: null,
|
||||||
|
sectionTitle: null,
|
||||||
|
personContainer: null,
|
||||||
|
personAvatar: null,
|
||||||
|
personName: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
|
@ -1,7 +1,7 @@
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useUser } from '../../context/user';
|
import { useUser } from '../../../context/user';
|
||||||
import useLayoutType from '../../hooks/useLayoutType';
|
import useLayoutType from '../../../hooks/useLayoutType';
|
||||||
import { TAB_OPTIONS } from './tabOptions';
|
import { TAB_OPTIONS } from './tabOptions';
|
||||||
import View from './View';
|
import View from './View';
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ function Classroom() {
|
||||||
});
|
});
|
||||||
}, [userService, params.id]);
|
}, [userService, params.id]);
|
||||||
|
|
||||||
const fetchAndPopulatePoepleTabData = useCallback(async () => {
|
const fetchAndPopulatePeopleTabData = useCallback(async () => {
|
||||||
setTabData({ tab: 'people', state: 'loading' });
|
setTabData({ tab: 'people', state: 'loading' });
|
||||||
const people = await userService.fetchPeopleByClassId(params.id);
|
const people = await userService.fetchPeopleByClassId(params.id);
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ function Classroom() {
|
||||||
fetchAndPopulateAssignmentsTabData();
|
fetchAndPopulateAssignmentsTabData();
|
||||||
break;
|
break;
|
||||||
case TAB_OPTIONS.people.value:
|
case TAB_OPTIONS.people.value:
|
||||||
fetchAndPopulatePoepleTabData();
|
fetchAndPopulatePeopleTabData();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Invalid tab option');
|
console.log('Invalid tab option');
|
||||||
|
@ -75,7 +75,7 @@ function Classroom() {
|
||||||
params,
|
params,
|
||||||
fetchAndPopulateAnnouncementsTabData,
|
fetchAndPopulateAnnouncementsTabData,
|
||||||
fetchAndPopulateAssignmentsTabData,
|
fetchAndPopulateAssignmentsTabData,
|
||||||
fetchAndPopulatePoepleTabData,
|
fetchAndPopulatePeopleTabData,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
34
src/screens/student/Classroom/styles.js
Normal file
34
src/screens/student/Classroom/styles.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// ========== Desktop ==========
|
||||||
|
const desktopContainer = {
|
||||||
|
width: '100%',
|
||||||
|
height: '100vh',
|
||||||
|
backgroundColor: '#red',
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
marginTop: '50px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktop = {
|
||||||
|
container: desktopContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Mobile ==========
|
||||||
|
const mobileContainer = {
|
||||||
|
width: '90%',
|
||||||
|
backgroundColor: '#red',
|
||||||
|
padding: 0,
|
||||||
|
marginTop: '30px',
|
||||||
|
paddingBottom: '100px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobile = {
|
||||||
|
container: mobileContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== Unset ==========
|
||||||
|
const unset = {
|
||||||
|
container: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
|
@ -1,10 +1,11 @@
|
||||||
import { Container, Grid, Skeleton, Stack } from '@mui/material';
|
import { Container, Grid, Skeleton, Stack } from '@mui/material';
|
||||||
|
|
||||||
import ClassCard from '../../components/ClassCard';
|
import ClassCard from '../../../components/ClassCard';
|
||||||
import AssignmentCard from '../../components/AssignmentCard';
|
import AssignmentCard from '../../../components/student/AssignmentCard';
|
||||||
|
|
||||||
|
import { createArrayFrom1ToN } from '../../../utils/createArrayFrom1ToN';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { createArrayFrom1ToN } from '../../utils/createArrayFrom1ToN';
|
|
||||||
|
|
||||||
function View({
|
function View({
|
||||||
layoutType,
|
layoutType,
|
|
@ -1,8 +1,8 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useUser } from '../../context/user';
|
import { useUser } from '../../../context/user';
|
||||||
import { useDocumentTitle } from '../../hooks/useDocumentTitle';
|
import { useDocumentTitle } from '../../../hooks/useDocumentTitle';
|
||||||
import useLayoutType from '../../hooks/useLayoutType';
|
import useLayoutType from '../../../hooks/useLayoutType';
|
||||||
import View from './View';
|
import View from './View';
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
|
@ -7,6 +7,21 @@ export default class ProfessorService {
|
||||||
|
|
||||||
fetchClassrooms = () => ProfessorApi.getClassrooms(this.user.id);
|
fetchClassrooms = () => ProfessorApi.getClassrooms(this.user.id);
|
||||||
|
|
||||||
|
fetchClassroomById = classId => ProfessorApi.getClassroomById(classId);
|
||||||
|
|
||||||
|
fetchAssignmentsByClassId = classId =>
|
||||||
|
ProfessorApi.getAssignmentsByClassId(classId);
|
||||||
|
|
||||||
fetchAssignmentsToReview = () =>
|
fetchAssignmentsToReview = () =>
|
||||||
ProfessorApi.getAssignmentsToReview(this.user.id);
|
ProfessorApi.getAssignmentsToReview(this.user.id);
|
||||||
|
|
||||||
|
fetchClassroomAnnouncements = classId =>
|
||||||
|
ProfessorApi.getClassroomAnnouncementsById(classId);
|
||||||
|
|
||||||
|
fetchPeopleByClassId = classId => ProfessorApi.getPeopleByClassId(classId);
|
||||||
|
|
||||||
|
fetchGradesByClassId = classId => ProfessorApi.getGradesByClassId(classId);
|
||||||
|
|
||||||
|
fetchUpcomingAssignmentsByClassId = classId =>
|
||||||
|
ProfessorApi.getUpcomingAssignmentsByClassId(classId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
allPeople,
|
allPeople,
|
||||||
professorClassrooms,
|
professorClassrooms,
|
||||||
assignmentsToReview,
|
assignmentsToReview,
|
||||||
|
grades,
|
||||||
} from './responses';
|
} from './responses';
|
||||||
|
|
||||||
const CommonApi = {
|
const CommonApi = {
|
||||||
|
@ -41,18 +42,14 @@ const CommonApi = {
|
||||||
window.localStorage.setItem('$USER', JSON.stringify(data));
|
window.localStorage.setItem('$USER', JSON.stringify(data));
|
||||||
return userData;
|
return userData;
|
||||||
}),
|
}),
|
||||||
};
|
|
||||||
|
|
||||||
const StudentApi = {
|
getClassroomAnnouncementsById: classId =>
|
||||||
...CommonApi,
|
|
||||||
getClassrooms: userId =>
|
|
||||||
sleep(300).then(() => {
|
sleep(300).then(() => {
|
||||||
console.log('Get classrooms ' + userId);
|
console.log('Get classroon announcements by id ' + classId);
|
||||||
return {
|
return {
|
||||||
data: allClassrooms,
|
data: allClassroomAnnouncements.filter(c => c.classroom.id === classId),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getClassroomById: classId =>
|
getClassroomById: classId =>
|
||||||
sleep(300).then(() => {
|
sleep(300).then(() => {
|
||||||
console.log('Get classroom by id ' + classId);
|
console.log('Get classroom by id ' + classId);
|
||||||
|
@ -60,12 +57,19 @@ const StudentApi = {
|
||||||
data: allClassrooms.filter(c => c.id === classId)[0],
|
data: allClassrooms.filter(c => c.id === classId)[0],
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
getAssignmentsByClassId: classId =>
|
||||||
getClassroomAnnouncementsById: classId =>
|
|
||||||
sleep(300).then(() => {
|
sleep(300).then(() => {
|
||||||
console.log('Get classroon announcements by id ' + classId);
|
console.log('Getting assignments by class id ' + classId);
|
||||||
return {
|
return {
|
||||||
data: allClassroomAnnouncements.filter(c => c.classroom.id === classId),
|
data: allAssignments.filter(a => a.classrooms[0].id === classId),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
getPeopleByClassId: classId =>
|
||||||
|
sleep(400).then(() => {
|
||||||
|
console.log('Getting people by class id ' + classId);
|
||||||
|
return {
|
||||||
|
data: allPeople.filter(p => p.classes[0].id === classId),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -78,6 +82,17 @@ const StudentApi = {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const StudentApi = {
|
||||||
|
...CommonApi,
|
||||||
|
getClassrooms: userId =>
|
||||||
|
sleep(300).then(() => {
|
||||||
|
console.log('Get classrooms ' + userId);
|
||||||
|
return {
|
||||||
|
data: allClassrooms,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
getAllAssignments: userId =>
|
getAllAssignments: userId =>
|
||||||
sleep(400).then(() => {
|
sleep(400).then(() => {
|
||||||
|
@ -95,22 +110,6 @@ const StudentApi = {
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getAssignmentsByClassId: classId =>
|
|
||||||
sleep(300).then(() => {
|
|
||||||
console.log('Getting assignments by class id ' + classId);
|
|
||||||
return {
|
|
||||||
data: allAssignments.filter(a => a.classrooms[0].id === classId),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
getPeopleByClassId: classId =>
|
|
||||||
sleep(400).then(() => {
|
|
||||||
console.log('Getting people by class id ' + classId);
|
|
||||||
return {
|
|
||||||
data: allPeople.filter(p => p.classes[0].id === classId),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
getFaq: () =>
|
getFaq: () =>
|
||||||
sleep(300).then(() => {
|
sleep(300).then(() => {
|
||||||
console.log('Fetching FAQ...');
|
console.log('Fetching FAQ...');
|
||||||
|
@ -136,6 +135,13 @@ const ProfessorApi = {
|
||||||
data: assignmentsToReview,
|
data: assignmentsToReview,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
getGradesByClassId: classId =>
|
||||||
|
sleep(400).then(() => {
|
||||||
|
console.log('Getting grades' + classId);
|
||||||
|
return {
|
||||||
|
data: grades,
|
||||||
|
};
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export { StudentApi, ProfessorApi, CommonApi };
|
export { StudentApi, ProfessorApi, CommonApi };
|
||||||
|
|
|
@ -4,6 +4,7 @@ const allClassrooms = [
|
||||||
name: 'Introdução à Ciência de Dados',
|
name: 'Introdução à Ciência de Dados',
|
||||||
abbreviation: 'ICD',
|
abbreviation: 'ICD',
|
||||||
color: '#006FF2',
|
color: '#006FF2',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-icd-321',
|
||||||
teachers: [
|
teachers: [
|
||||||
{
|
{
|
||||||
id: '2342',
|
id: '2342',
|
||||||
|
@ -22,6 +23,7 @@ const allClassrooms = [
|
||||||
name: 'Gestão de Projetos',
|
name: 'Gestão de Projetos',
|
||||||
abbreviation: 'GP',
|
abbreviation: 'GP',
|
||||||
color: '#7900F2',
|
color: '#7900F2',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-gp-123',
|
||||||
teachers: [
|
teachers: [
|
||||||
{
|
{
|
||||||
id: '1234',
|
id: '1234',
|
||||||
|
@ -45,6 +47,7 @@ const allClassrooms = [
|
||||||
name: 'Banco de Dados II',
|
name: 'Banco de Dados II',
|
||||||
abbreviation: 'BDII',
|
abbreviation: 'BDII',
|
||||||
color: '#FF7A00',
|
color: '#FF7A00',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-bdii-666',
|
||||||
teachers: [
|
teachers: [
|
||||||
{
|
{
|
||||||
id: '6781',
|
id: '6781',
|
||||||
|
@ -63,6 +66,7 @@ const allClassrooms = [
|
||||||
name: 'Contabilidade Básica',
|
name: 'Contabilidade Básica',
|
||||||
abbreviation: 'CB',
|
abbreviation: 'CB',
|
||||||
color: '#BB0000',
|
color: '#BB0000',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-cb-765',
|
||||||
teachers: [
|
teachers: [
|
||||||
{
|
{
|
||||||
id: '4321',
|
id: '4321',
|
||||||
|
@ -80,6 +84,7 @@ const allClassrooms = [
|
||||||
name: 'Linguagens de Programação',
|
name: 'Linguagens de Programação',
|
||||||
abbreviation: 'LP',
|
abbreviation: 'LP',
|
||||||
color: '#039200',
|
color: '#039200',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-lp-333',
|
||||||
teachers: [
|
teachers: [
|
||||||
{
|
{
|
||||||
id: '9999',
|
id: '9999',
|
||||||
|
@ -101,6 +106,7 @@ const professorClassrooms = [
|
||||||
name: 'Introdução à Ciência de Dados',
|
name: 'Introdução à Ciência de Dados',
|
||||||
abbreviation: 'ICD',
|
abbreviation: 'ICD',
|
||||||
color: '#006FF2',
|
color: '#006FF2',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-icd-321',
|
||||||
course: 'BSI 2020',
|
course: 'BSI 2020',
|
||||||
appointmentSlots: [
|
appointmentSlots: [
|
||||||
{ weekDay: 'Quarta-feira', start: '10:00', end: '11:40' },
|
{ weekDay: 'Quarta-feira', start: '10:00', end: '11:40' },
|
||||||
|
@ -112,6 +118,7 @@ const professorClassrooms = [
|
||||||
name: 'Teoria dos Grafos',
|
name: 'Teoria dos Grafos',
|
||||||
abbreviation: 'TDG',
|
abbreviation: 'TDG',
|
||||||
color: '#d30000',
|
color: '#d30000',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-tdg-123',
|
||||||
course: 'BSI 2018',
|
course: 'BSI 2018',
|
||||||
appointmentSlots: [
|
appointmentSlots: [
|
||||||
{ weekDay: 'Quarta-feira', start: '11:00', end: '12:00' },
|
{ weekDay: 'Quarta-feira', start: '11:00', end: '12:00' },
|
||||||
|
@ -123,6 +130,7 @@ const professorClassrooms = [
|
||||||
name: 'Matemática Discreta',
|
name: 'Matemática Discreta',
|
||||||
abbreviation: 'MD',
|
abbreviation: 'MD',
|
||||||
color: '#149b00',
|
color: '#149b00',
|
||||||
|
virtualRoom: 'https://meet.jit.si/ifmg-md-666',
|
||||||
course: 'BSI 2020',
|
course: 'BSI 2020',
|
||||||
appointmentSlots: [
|
appointmentSlots: [
|
||||||
{ weekDay: 'Quarta-feira', start: '9:00', end: '10:00' },
|
{ weekDay: 'Quarta-feira', start: '9:00', end: '10:00' },
|
||||||
|
@ -643,6 +651,13 @@ const allPeople = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// TODO: Mock correct data
|
||||||
|
const grades = [
|
||||||
|
{
|
||||||
|
id: 'Some grade',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const studentUser = {
|
const studentUser = {
|
||||||
id: '123',
|
id: '123',
|
||||||
ra: '0021123',
|
ra: '0021123',
|
||||||
|
@ -667,10 +682,11 @@ const professorUser = {
|
||||||
email: 'carlos.junior@ifmg.edu.br',
|
email: 'carlos.junior@ifmg.edu.br',
|
||||||
password: '#carlos1234', // TODO: Remove this!
|
password: '#carlos1234', // TODO: Remove this!
|
||||||
firstName: 'Carlos',
|
firstName: 'Carlos',
|
||||||
lastName: 'Severiano',
|
lastName: 'Alexandre Silva',
|
||||||
token: 'xkhfb9458hnsdfsi9q8345bsdf9b834yr',
|
token: 'xkhfb9458hnsdfsi9q8345bsdf9b834yr',
|
||||||
phone: '31111111111',
|
phone: '31111111111',
|
||||||
avatar: 'https://i.pravatar.cc/300?img=61',
|
avatar:
|
||||||
|
'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=50&q=80',
|
||||||
course: 0,
|
course: 0,
|
||||||
termsAgreed: true,
|
termsAgreed: true,
|
||||||
year: 2018,
|
year: 2018,
|
||||||
|
@ -693,4 +709,5 @@ export {
|
||||||
allUpcomingAssignments,
|
allUpcomingAssignments,
|
||||||
professorClassrooms,
|
professorClassrooms,
|
||||||
assignmentsToReview,
|
assignmentsToReview,
|
||||||
|
grades,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue