Add initial structure for professor classroom screen
This commit is contained in:
parent
faa597726b
commit
7377defce8
13 changed files with 730 additions and 24 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" />} />
|
||||||
|
|
268
src/screens/professor/Classroom/AnnouncementsTab/index.js
Normal file
268
src/screens/professor/Classroom/AnnouncementsTab/index.js
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
|
Link,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material';
|
||||||
|
import AnnouncementCard from '../../../../components/AnnouncementCard';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
import jitsiLogo from '../../../../assets/jitsi.svg';
|
||||||
|
import { createArrayFrom1ToN } from '../../../../utils/createArrayFrom1ToN';
|
||||||
|
|
||||||
|
function AnnouncementsTab({ layoutType, announcementsTabData, classroom }) {
|
||||||
|
const { container, emptyStateContainer } = styles[layoutType];
|
||||||
|
|
||||||
|
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' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<Container
|
||||||
|
disableGutters
|
||||||
|
sx={{ display: 'flex', justifyContent: 'row' }}
|
||||||
|
>
|
||||||
|
<img src={jitsiLogo} alt="Jitsi Meet" />
|
||||||
|
<h3 style={{ fontWeight: 500 }}>Jitsi</h3>
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
href="https://google.com"
|
||||||
|
target="__blank"
|
||||||
|
>
|
||||||
|
Entrar
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<h3 style={{ fontWeight: 500 }}>Próximas Atividades</h3>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px' }}
|
||||||
|
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>
|
||||||
|
</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"
|
||||||
|
>
|
||||||
|
{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' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<Container
|
||||||
|
disableGutters
|
||||||
|
sx={{ display: 'flex', justifyContent: 'row' }}
|
||||||
|
>
|
||||||
|
<img src={jitsiLogo} alt="Jitsi Meet" />
|
||||||
|
<h3 style={{ fontWeight: 500 }}>Jitsi</h3>
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
href="https://google.com"
|
||||||
|
target="__blank"
|
||||||
|
>
|
||||||
|
Entrar
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px' }}
|
||||||
|
elevation={4}
|
||||||
|
variant="elevation"
|
||||||
|
>
|
||||||
|
<Stack justifyContent="flex-start" spacing={1}>
|
||||||
|
<h3 style={{ fontWeight: 500 }}>Próximas Atividades</h3>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
sx={{ width: '100%', padding: '20px' }}
|
||||||
|
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"
|
||||||
|
>
|
||||||
|
{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;
|
48
src/screens/professor/Classroom/AnnouncementsTab/styles.js
Normal file
48
src/screens/professor/Classroom/AnnouncementsTab/styles.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// ========== 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = { desktop, mobile, unset };
|
||||||
|
export default styles;
|
34
src/screens/professor/Classroom/AssignmentsTab/index.js
Normal file
34
src/screens/professor/Classroom/AssignmentsTab/index.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
function AssignmentsTab({ assignmentsTabData, layoutType }) {
|
||||||
|
const layoutResolver = (state, assignments, layoutType) => {
|
||||||
|
if (layoutType === 'desktop') {
|
||||||
|
switch (state) {
|
||||||
|
case 'loading':
|
||||||
|
return <h1>Loading...</h1>;
|
||||||
|
case 'idle':
|
||||||
|
return <h1>Assignments 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>Assignments Tab</h1>;
|
||||||
|
case 'gone':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return layoutResolver(
|
||||||
|
assignmentsTabData && assignmentsTabData.state,
|
||||||
|
assignmentsTabData && assignmentsTabData.assignments,
|
||||||
|
layoutType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AssignmentsTab;
|
0
src/screens/professor/Classroom/AssignmentsTab/styles.js
Normal file
0
src/screens/professor/Classroom/AssignmentsTab/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="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: '20px',
|
||||||
|
});
|
||||||
|
|
||||||
|
const desktopTabs = {
|
||||||
|
marginLeft: '-20px',
|
||||||
|
marginRight: '-20px',
|
||||||
|
marginBottom: '-20px',
|
||||||
|
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: '10px',
|
||||||
|
});
|
||||||
|
|
||||||
|
const mobileTabs = {
|
||||||
|
marginLeft: '-10px',
|
||||||
|
marginRight: '-10px',
|
||||||
|
marginBottom: '-10px',
|
||||||
|
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;
|
39
src/screens/professor/Classroom/View.js
Normal file
39
src/screens/professor/Classroom/View.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { Container } from '@mui/system';
|
||||||
|
import AnnouncementsTab from './AnnouncementsTab';
|
||||||
|
import AssignmentsTab from './AssignmentsTab';
|
||||||
|
import Header from './Header';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
function View({
|
||||||
|
layoutType,
|
||||||
|
classroom,
|
||||||
|
selectedTabOption,
|
||||||
|
onSelectTabOption,
|
||||||
|
announcementsTabData,
|
||||||
|
assignmentsTabData,
|
||||||
|
isLoading,
|
||||||
|
}) {
|
||||||
|
const { container } = styles[layoutType];
|
||||||
|
return (
|
||||||
|
<Container disableGutters sx={container}>
|
||||||
|
<Header
|
||||||
|
layoutType={layoutType}
|
||||||
|
classroom={classroom}
|
||||||
|
selectedTabOption={selectedTabOption}
|
||||||
|
onSelectTabOption={onSelectTabOption}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<AnnouncementsTab
|
||||||
|
layoutType={layoutType}
|
||||||
|
announcementsTabData={announcementsTabData}
|
||||||
|
classroom={classroom && classroom}
|
||||||
|
/>
|
||||||
|
<AssignmentsTab
|
||||||
|
layoutType={layoutType}
|
||||||
|
assignmentsTabData={assignmentsTabData}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default View;
|
101
src/screens/professor/Classroom/index.js
Normal file
101
src/screens/professor/Classroom/index.js
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
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 } = useUser();
|
||||||
|
const [classroom, setClassroom] = useState(null);
|
||||||
|
const [tabData, setTabData] = useState(null);
|
||||||
|
|
||||||
|
const [selectedTabOption, setSelectedTabOption] = useState(
|
||||||
|
TAB_OPTIONS.announcements.value
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchAndPopulateAnnouncementsTabData = useCallback(async () => {
|
||||||
|
setTabData({ tab: 'announcements', state: 'loading' });
|
||||||
|
const announcements = await userService.fetchClassroomAnnouncements(
|
||||||
|
params.id
|
||||||
|
);
|
||||||
|
|
||||||
|
setTabData({
|
||||||
|
tab: 'announcements',
|
||||||
|
state: 'idle',
|
||||||
|
announcements: [...announcements.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getClassroomById(params.id);
|
||||||
|
updateDocumentTitle();
|
||||||
|
}, [userService, userService.fetchClassroomById, params, classroom]);
|
||||||
|
|
||||||
|
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:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('Invalid tab option');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getSelectedTabData();
|
||||||
|
}, [
|
||||||
|
selectedTabOption,
|
||||||
|
params,
|
||||||
|
fetchAndPopulateAnnouncementsTabData,
|
||||||
|
fetchAndPopulateAssignmentsTabData,
|
||||||
|
]);
|
||||||
|
|
||||||
|
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' }
|
||||||
|
}
|
||||||
|
isLoading={tabData && tabData.state === 'loading'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Classroom;
|
34
src/screens/professor/Classroom/styles.js
Normal file
34
src/screens/professor/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;
|
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 };
|
|
@ -7,6 +7,14 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,28 @@ const CommonApi = {
|
||||||
window.localStorage.setItem('$USER', JSON.stringify(data));
|
window.localStorage.setItem('$USER', JSON.stringify(data));
|
||||||
return userData;
|
return userData;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
getClassroomAnnouncementsById: classId =>
|
||||||
|
sleep(300).then(() => {
|
||||||
|
console.log('Get classroon announcements by id ' + classId);
|
||||||
|
return {
|
||||||
|
data: allClassroomAnnouncements.filter(c => c.classroom.id === classId),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
getClassroomById: classId =>
|
||||||
|
sleep(300).then(() => {
|
||||||
|
console.log('Get classroom by id ' + classId);
|
||||||
|
return {
|
||||||
|
data: allClassrooms.filter(c => c.id === classId)[0],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
getAssignmentsByClassId: classId =>
|
||||||
|
sleep(300).then(() => {
|
||||||
|
console.log('Getting assignments by class id ' + classId);
|
||||||
|
return {
|
||||||
|
data: allAssignments.filter(a => a.classrooms[0].id === classId),
|
||||||
|
};
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const StudentApi = {
|
const StudentApi = {
|
||||||
|
@ -53,22 +75,6 @@ const StudentApi = {
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getClassroomById: classId =>
|
|
||||||
sleep(300).then(() => {
|
|
||||||
console.log('Get classroom by id ' + classId);
|
|
||||||
return {
|
|
||||||
data: allClassrooms.filter(c => c.id === classId)[0],
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
getClassroomAnnouncementsById: classId =>
|
|
||||||
sleep(300).then(() => {
|
|
||||||
console.log('Get classroon announcements by id ' + classId);
|
|
||||||
return {
|
|
||||||
data: allClassroomAnnouncements.filter(c => c.classroom.id === classId),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
getUpcomingAssignmentsByClassId: classId =>
|
getUpcomingAssignmentsByClassId: classId =>
|
||||||
sleep(300).then(() => {
|
sleep(300).then(() => {
|
||||||
console.log('Getting upcoming assignments by class id ' + classId);
|
console.log('Getting upcoming assignments by class id ' + classId);
|
||||||
|
@ -95,14 +101,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 =>
|
getPeopleByClassId: classId =>
|
||||||
sleep(400).then(() => {
|
sleep(400).then(() => {
|
||||||
console.log('Getting people by class id ' + classId);
|
console.log('Getting people by class id ' + classId);
|
||||||
|
|
Loading…
Reference in a new issue