diff options
Diffstat (limited to 'src/screens/professor/Classroom')
-rw-r--r-- | src/screens/professor/Classroom/AnnouncementsTab/index.js | 525 | ||||
-rw-r--r-- | src/screens/professor/Classroom/AnnouncementsTab/styles.js | 49 | ||||
-rw-r--r-- | src/screens/professor/Classroom/AssignmentsTab/index.js | 409 | ||||
-rw-r--r-- | src/screens/professor/Classroom/AssignmentsTab/styles.js | 138 | ||||
-rw-r--r-- | src/screens/professor/Classroom/GradesTab/index.js | 34 | ||||
-rw-r--r-- | src/screens/professor/Classroom/GradesTab/styles.js | 0 | ||||
-rw-r--r-- | src/screens/professor/Classroom/Header/index.js | 62 | ||||
-rw-r--r-- | src/screens/professor/Classroom/Header/styles.js | 90 | ||||
-rw-r--r-- | src/screens/professor/Classroom/PeopleTab/index.js | 244 | ||||
-rw-r--r-- | src/screens/professor/Classroom/PeopleTab/styles.js | 116 | ||||
-rw-r--r-- | src/screens/professor/Classroom/View.js | 51 | ||||
-rw-r--r-- | src/screens/professor/Classroom/index.js | 156 | ||||
-rw-r--r-- | src/screens/professor/Classroom/styles.js | 34 | ||||
-rw-r--r-- | src/screens/professor/Classroom/tabOptions.js | 20 |
14 files changed, 1928 insertions, 0 deletions
diff --git a/src/screens/professor/Classroom/AnnouncementsTab/index.js b/src/screens/professor/Classroom/AnnouncementsTab/index.js new file mode 100644 index 0000000..74fbe3b --- /dev/null +++ b/src/screens/professor/Classroom/AnnouncementsTab/index.js @@ -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; diff --git a/src/screens/professor/Classroom/AnnouncementsTab/styles.js b/src/screens/professor/Classroom/AnnouncementsTab/styles.js new file mode 100644 index 0000000..46b3813 --- /dev/null +++ b/src/screens/professor/Classroom/AnnouncementsTab/styles.js @@ -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; diff --git a/src/screens/professor/Classroom/AssignmentsTab/index.js b/src/screens/professor/Classroom/AssignmentsTab/index.js new file mode 100644 index 0000000..2060c40 --- /dev/null +++ b/src/screens/professor/Classroom/AssignmentsTab/index.js @@ -0,0 +1,409 @@ +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%' }} + 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; + } + } 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%' }} + 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; diff --git a/src/screens/professor/Classroom/AssignmentsTab/styles.js b/src/screens/professor/Classroom/AssignmentsTab/styles.js new file mode 100644 index 0000000..0493789 --- /dev/null +++ b/src/screens/professor/Classroom/AssignmentsTab/styles.js @@ -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; diff --git a/src/screens/professor/Classroom/GradesTab/index.js b/src/screens/professor/Classroom/GradesTab/index.js new file mode 100644 index 0000000..785bd50 --- /dev/null +++ b/src/screens/professor/Classroom/GradesTab/index.js @@ -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; diff --git a/src/screens/professor/Classroom/GradesTab/styles.js b/src/screens/professor/Classroom/GradesTab/styles.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/screens/professor/Classroom/GradesTab/styles.js diff --git a/src/screens/professor/Classroom/Header/index.js b/src/screens/professor/Classroom/Header/index.js new file mode 100644 index 0000000..e077313 --- /dev/null +++ b/src/screens/professor/Classroom/Header/index.js @@ -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; diff --git a/src/screens/professor/Classroom/Header/styles.js b/src/screens/professor/Classroom/Header/styles.js new file mode 100644 index 0000000..03ba4ab --- /dev/null +++ b/src/screens/professor/Classroom/Header/styles.js @@ -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; diff --git a/src/screens/professor/Classroom/PeopleTab/index.js b/src/screens/professor/Classroom/PeopleTab/index.js new file mode 100644 index 0000000..9dfde7b --- /dev/null +++ b/src/screens/professor/Classroom/PeopleTab/index.js @@ -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; diff --git a/src/screens/professor/Classroom/PeopleTab/styles.js b/src/screens/professor/Classroom/PeopleTab/styles.js new file mode 100644 index 0000000..30668db --- /dev/null +++ b/src/screens/professor/Classroom/PeopleTab/styles.js @@ -0,0 +1,116 @@ +// ========== 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: '60px', + height: '60px', + marginRight: '15px', +}; + +const desktopPersonName = {}; + +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; diff --git a/src/screens/professor/Classroom/View.js b/src/screens/professor/Classroom/View.js new file mode 100644 index 0000000..59dbd92 --- /dev/null +++ b/src/screens/professor/Classroom/View.js @@ -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; diff --git a/src/screens/professor/Classroom/index.js b/src/screens/professor/Classroom/index.js new file mode 100644 index 0000000..fa86816 --- /dev/null +++ b/src/screens/professor/Classroom/index.js @@ -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; diff --git a/src/screens/professor/Classroom/styles.js b/src/screens/professor/Classroom/styles.js new file mode 100644 index 0000000..fe6018c --- /dev/null +++ b/src/screens/professor/Classroom/styles.js @@ -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; diff --git a/src/screens/professor/Classroom/tabOptions.js b/src/screens/professor/Classroom/tabOptions.js new file mode 100644 index 0000000..fdc3e98 --- /dev/null +++ b/src/screens/professor/Classroom/tabOptions.js @@ -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 }; |