From a580f2c199aa3347a79121fb611a72cbdd11c383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Sun, 27 Nov 2022 20:54:30 -0300 Subject: [PATCH 1/8] Initial structure for professor home screen --- src/app/ProfessorRoutes.js | 3 +- src/screens/professor/Home/View.js | 123 +++++++++++++++++++++++++++ src/screens/professor/Home/index.js | 38 +++++++++ src/screens/professor/Home/styles.js | 31 +++++++ 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 src/screens/professor/Home/View.js create mode 100644 src/screens/professor/Home/index.js create mode 100644 src/screens/professor/Home/styles.js diff --git a/src/app/ProfessorRoutes.js b/src/app/ProfessorRoutes.js index 419cb42..cec7984 100644 --- a/src/app/ProfessorRoutes.js +++ b/src/app/ProfessorRoutes.js @@ -1,4 +1,5 @@ import { Navigate, Route, Routes } from 'react-router-dom'; +import Home from '../screens/professor/Home'; function ProfessorRoutes() { return ( @@ -6,7 +7,7 @@ function ProfessorRoutes() { Calendar} /> Profile} /> Information} /> - Home} /> + } /> } /> } /> } /> diff --git a/src/screens/professor/Home/View.js b/src/screens/professor/Home/View.js new file mode 100644 index 0000000..64046f5 --- /dev/null +++ b/src/screens/professor/Home/View.js @@ -0,0 +1,123 @@ +import { Grid, Skeleton, Stack } from '@mui/material'; +import { Container } from '@mui/system'; +import ClassCard from '../../../components/ClassCard'; +import { createArrayFrom1ToN } from '../../../utils/createArrayFrom1ToN'; +import styles from './styles'; + +function View({ layoutType, classrooms, onClickClassCard }) { + const { container, divider, assignmentsStack } = styles[layoutType]; + + if (layoutType === 'desktop') { + return ( + + +

Minhas Turmas

+ + {classrooms === null ? ( + createArrayFrom1ToN(6).map(i => ( + + )) + ) : classrooms.length !== 0 ? ( + classrooms.map(classroom => ( + onClickClassCard(classroom.id)} + /> + )) + ) : ( + +

Nenhuma sala de aula encontrada!

+
+ )} +
+
+ +

Atividades para corrigir

+

Atribuídas

+ +

Atividade 1

+

Atividade 2

+
+
+
+ ); + } else if (layoutType === 'mobile') { + return ( + +

Minhas Turmas

+ + {classrooms === null ? ( + createArrayFrom1ToN(6).map(i => ( + + )) + ) : classrooms.length !== 0 ? ( + classrooms.map(classroom => ( + onClickClassCard(classroom.id)} + /> + )) + ) : ( + +

Nenhuma sala de aula encontrada!

+
+ )} +
+

Atividades para corrigir

+

Atribuídas

+ +

Atividade 1

+

Atividade 2

+
+
+ ); + } +} + +export default View; diff --git a/src/screens/professor/Home/index.js b/src/screens/professor/Home/index.js new file mode 100644 index 0000000..91eddc3 --- /dev/null +++ b/src/screens/professor/Home/index.js @@ -0,0 +1,38 @@ +import { useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useUser } from '../../../context/user'; +import { useDocumentTitle } from '../../../hooks/useDocumentTitle'; +import useLayoutType from '../../../hooks/useLayoutType'; +import View from './View'; + +function Home() { + useDocumentTitle('Página Inicial'); + const navigate = useNavigate(); + const layoutType = useLayoutType(); + const { fetchClassrooms } = useUser(); + const [classrooms, setClassrooms] = useState(null); + + useEffect(() => { + async function getClassrooms() { + const result = await fetchClassrooms(); + setClassrooms(result.data); + } + getClassrooms(); + }, [fetchClassrooms]); + + const onClickClassCard = id => { + navigate(`/class/${id}`); + }; + + console.log(classrooms); + + return ( + + ); +} + +export default Home; diff --git a/src/screens/professor/Home/styles.js b/src/screens/professor/Home/styles.js new file mode 100644 index 0000000..1a8a842 --- /dev/null +++ b/src/screens/professor/Home/styles.js @@ -0,0 +1,31 @@ +// ========== Desktop ========== +const desktopContainer = { + height: '100vh', + margin: 0, +}; + +const desktop = { + container: desktopContainer, +}; + +// ========== Mobile ========== +const mobileContainer = { + height: 'inherit', + width: '100%', + padding: '10px 20px ', + margin: 0, +}; + +const mobile = { + container: mobileContainer, +}; + +// ========== Unset ========== +const unset = { + container: null, + divider: null, + assignmentsStack: null, +}; + +const styles = { desktop, mobile, unset }; +export default styles; From bbea9b2f0fe07661c558ccb97811df0663b23343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Tue, 29 Nov 2022 11:33:03 -0300 Subject: [PATCH 2/8] Split services between student and professor roles --- src/context/user.js | 85 ++++----------------------- src/screens/Assignment/index.js | 6 +- src/screens/Classroom/index.js | 31 ++++------ src/screens/Home/index.js | 10 ++-- src/screens/Information/index.js | 6 +- src/screens/professor/Home/index.js | 6 +- src/services/professor-service.js | 5 ++ src/services/student-service.js | 37 ++++++++++++ src/services/user-service-provider.js | 28 +++++++++ 9 files changed, 108 insertions(+), 106 deletions(-) create mode 100644 src/services/professor-service.js create mode 100644 src/services/student-service.js create mode 100644 src/services/user-service-provider.js diff --git a/src/context/user.js b/src/context/user.js index 23a3df4..afb4527 100644 --- a/src/context/user.js +++ b/src/context/user.js @@ -1,23 +1,14 @@ import { createContext, useContext, useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; +import { UserServiceProvider } from '../services/user-service-provider'; import { useAuthState } from './auth'; -import { - getAllAssignments, - getAssignmentById, - getAssignmentsByClassId, - getClassroomAnnouncementsById, - getClassroomById, - getClassrooms, - getFaq, - getPeopleByClassId, - getUpcomingAssignmentsByClassId, -} from '../services/user-service'; const UserContext = createContext(); function UserProvider(props) { const { user } = useAuthState(); const { pathname } = useLocation(); + const [userService, setUserService] = useState(null); const [state, setState] = useState({ user: null, error: null, @@ -26,73 +17,23 @@ function UserProvider(props) { useEffect(() => { setState({ user, pathname }); + + async function initUserService() { + if (user) { + const instance = await UserServiceProvider.getInstance(user); + setUserService(instance); + } + } + initUserService(); }, [user, pathname]); - const fetchClassrooms = () => getClassrooms(user.id); - - const fetchAllAssignments = () => getAllAssignments(user.id); - - const fetchAssignmentById = assignmentId => getAssignmentById(assignmentId); - - const fetchAssignmentsByClassId = classId => getAssignmentsByClassId(classId); - - const fetchClassroomById = classId => getClassroomById(classId); - - const fetchFAQ = () => getFaq(); - - const fetchClassroomAnnouncements = classId => - getClassroomAnnouncementsById(classId); - - const fetchUpcomingAssignmentsByClassId = classId => - getUpcomingAssignmentsByClassId(classId); - - const fetchPeopleByClassId = classId => getPeopleByClassId(classId); - - return ( - - ); + return ; } function useUser() { - const { - state, - fetchClassrooms, - fetchAssignmentById, - fetchAllAssignments, - fetchAssignmentsByClassId, - fetchClassroomById, - fetchFAQ, - fetchClassroomAnnouncements, - fetchUpcomingAssignmentsByClassId, - fetchPeopleByClassId, - } = useContext(UserContext); + const { state, userService } = useContext(UserContext); - return { - state, - fetchClassrooms, - fetchAllAssignments, - fetchAssignmentById, - fetchAssignmentsByClassId, - fetchClassroomById, - fetchFAQ, - fetchClassroomAnnouncements, - fetchUpcomingAssignmentsByClassId, - fetchPeopleByClassId, - }; + return { state, userService }; } export { UserProvider, useUser }; diff --git a/src/screens/Assignment/index.js b/src/screens/Assignment/index.js index 3559d3b..3357c2b 100644 --- a/src/screens/Assignment/index.js +++ b/src/screens/Assignment/index.js @@ -8,14 +8,14 @@ import View from './View'; function Assignment() { const params = useParams(); const layoutType = useLayoutType(); - const { fetchAssignmentById } = useUser(); + const { userService } = useUser(); const [assignment, setAssignment] = useState(null); const dropzone = useDropzone({ maxFiles: 5 }); useEffect(() => { async function getAssignmentById(assignmentId) { document.title = 'Carregando...'; - const result = await fetchAssignmentById(assignmentId); + const result = await userService.fetchAssignmentById(assignmentId); setAssignment(result.data); } @@ -27,7 +27,7 @@ function Assignment() { getAssignmentById(params.id); updateDocumentTitle(); - }, [params, fetchAssignmentById, assignment]); + }, [params, userService, userService.fetchAssignmentById, assignment]); return ( diff --git a/src/screens/Classroom/index.js b/src/screens/Classroom/index.js index 7410515..10fc044 100644 --- a/src/screens/Classroom/index.js +++ b/src/screens/Classroom/index.js @@ -8,13 +8,7 @@ import View from './View'; function Classroom() { const params = useParams(); const layoutType = useLayoutType(); - const { - fetchClassroomById, - fetchClassroomAnnouncements, - fetchUpcomingAssignmentsByClassId, - fetchAssignmentsByClassId, - fetchPeopleByClassId, - } = useUser(); + const { userService } = useUser(); const [classroom, setClassroom] = useState(null); const [tabData, setTabData] = useState(null); const [selectedTabOption, setSelectedTabOption] = useState( @@ -23,10 +17,11 @@ function Classroom() { const fetchAndPopulateAnnouncementsTabData = useCallback(async () => { setTabData({ tab: 'announcements', state: 'loading' }); - const announcements = await fetchClassroomAnnouncements(params.id); - const upcomingAssignments = await fetchUpcomingAssignmentsByClassId( + const announcements = await userService.fetchClassroomAnnouncements( params.id ); + const upcomingAssignments = + await userService.fetchUpcomingAssignmentsByClassId(params.id); setTabData({ tab: 'announcements', @@ -34,33 +29,29 @@ function Classroom() { announcements: [...announcements.data], upcomingAssignments: [...upcomingAssignments.data], }); - }, [ - fetchClassroomAnnouncements, - fetchUpcomingAssignmentsByClassId, - params.id, - ]); + }, [userService, params.id]); const fetchAndPopulateAssignmentsTabData = useCallback(async () => { setTabData({ tab: 'assignments', state: 'loading' }); - const assignments = await fetchAssignmentsByClassId(params.id); + const assignments = await userService.fetchAssignmentsByClassId(params.id); setTabData({ tab: 'assignments', state: 'idle', assignments: [...assignments.data], }); - }, [fetchAssignmentsByClassId, params.id]); + }, [userService, params.id]); const fetchAndPopulatePoepleTabData = useCallback(async () => { setTabData({ tab: 'people', state: 'loading' }); - const people = await fetchPeopleByClassId(params.id); + const people = await userService.fetchPeopleByClassId(params.id); setTabData({ tab: 'people', state: 'idle', people: [...people.data], }); - }, [fetchPeopleByClassId, params.id]); + }, [userService, params.id]); useEffect(() => { async function getSelectedTabData() { @@ -90,7 +81,7 @@ function Classroom() { useEffect(() => { async function getClassroomById(classId) { document.title = 'Carregando...'; - const result = await fetchClassroomById(classId); + const result = await userService.fetchClassroomById(classId); setClassroom(result.data); } @@ -102,7 +93,7 @@ function Classroom() { getClassroomById(params.id); updateDocumentTitle(); - }, [fetchClassroomById, params, classroom]); + }, [userService, userService.fetchClassroomById, params, classroom]); return ( { async function getClassrooms() { - const result = await fetchClassrooms(); + const result = await userService.fetchClassrooms(); setClassrooms(result.data); } getClassrooms(); - }, [fetchClassrooms]); + }, [userService, userService.fetchClassrooms]); useEffect(() => { async function getAssignments() { - const result = await fetchAllAssignments(); + const result = await userService.fetchAllAssignments(); setAssignments(result.data); } getAssignments(); - }, [fetchAllAssignments]); + }, [userService, userService.fetchAllAssignments]); const onClickClassCard = id => { navigate(`/class/${id}`); diff --git a/src/screens/Information/index.js b/src/screens/Information/index.js index b1f7965..1042060 100644 --- a/src/screens/Information/index.js +++ b/src/screens/Information/index.js @@ -9,16 +9,16 @@ import { sectors } from './data'; function Information() { useDocumentTitle('Informações'); const layoutType = useLayoutType(); - const { fetchFAQ } = useUser(); + const { userService } = useUser(); const [faq, setFaq] = useState(null); useEffect(() => { async function getClassrooms() { - const result = await fetchFAQ(); + const result = await userService.fetchFAQ(); setFaq(result.data); } getClassrooms(); - }, [fetchFAQ]); + }, [userService, userService.fetchFAQ]); return ; } diff --git a/src/screens/professor/Home/index.js b/src/screens/professor/Home/index.js index 91eddc3..32580b6 100644 --- a/src/screens/professor/Home/index.js +++ b/src/screens/professor/Home/index.js @@ -9,16 +9,16 @@ function Home() { useDocumentTitle('Página Inicial'); const navigate = useNavigate(); const layoutType = useLayoutType(); - const { fetchClassrooms } = useUser(); + const { userService } = useUser(); const [classrooms, setClassrooms] = useState(null); useEffect(() => { async function getClassrooms() { - const result = await fetchClassrooms(); + const result = await userService.fetchClassrooms(); setClassrooms(result.data); } getClassrooms(); - }, [fetchClassrooms]); + }, [userService, userService.fetchClassrooms]); const onClickClassCard = id => { navigate(`/class/${id}`); diff --git a/src/services/professor-service.js b/src/services/professor-service.js new file mode 100644 index 0000000..5589b51 --- /dev/null +++ b/src/services/professor-service.js @@ -0,0 +1,5 @@ +export default class ProfessorService { + constructor(user) { + this.user = user; + } +} diff --git a/src/services/student-service.js b/src/services/student-service.js new file mode 100644 index 0000000..5b9f297 --- /dev/null +++ b/src/services/student-service.js @@ -0,0 +1,37 @@ +import { + getAllAssignments, + getAssignmentById, + getAssignmentsByClassId, + getClassroomAnnouncementsById, + getClassroomById, + getClassrooms, + getFaq, + getPeopleByClassId, + getUpcomingAssignmentsByClassId, +} from './user-service'; + +export default class StudentService { + constructor(user) { + this.user = user; + } + + fetchClassrooms = () => getClassrooms(this.user.id); + + fetchAllAssignments = () => getAllAssignments(this.user.id); + + fetchAssignmentById = assignmentId => getAssignmentById(assignmentId); + + fetchAssignmentsByClassId = classId => getAssignmentsByClassId(classId); + + fetchClassroomById = classId => getClassroomById(classId); + + fetchFAQ = () => getFaq(); + + fetchClassroomAnnouncements = classId => + getClassroomAnnouncementsById(classId); + + fetchUpcomingAssignmentsByClassId = classId => + getUpcomingAssignmentsByClassId(classId); + + fetchPeopleByClassId = classId => getPeopleByClassId(classId); +} diff --git a/src/services/user-service-provider.js b/src/services/user-service-provider.js new file mode 100644 index 0000000..98224fc --- /dev/null +++ b/src/services/user-service-provider.js @@ -0,0 +1,28 @@ +export const UserServiceProvider = (function () { + let instance; + + async function createInstance(user) { + if (user.role === 'STUDENT') { + const service = await import('../services/student-service'); + if (service) { + return new service.default(user); + } + } else if (user.role === 'PROFESSOR') { + const service = await import('../services/professor-service'); + if (service) { + return new service.default(user); + } + } else { + throw new Error('Invalid Role!'); + } + } + + return { + getInstance: function (user) { + if (!instance) { + instance = createInstance(user); + } + return instance; + }, + }; +})(); From 2c181d49b06d79233f8f4f7064d5f842856cdbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Tue, 29 Nov 2022 11:36:55 -0300 Subject: [PATCH 3/8] Use switch case to create instance --- src/services/user-service-provider.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/services/user-service-provider.js b/src/services/user-service-provider.js index 98224fc..31f51cf 100644 --- a/src/services/user-service-provider.js +++ b/src/services/user-service-provider.js @@ -2,18 +2,21 @@ export const UserServiceProvider = (function () { let instance; async function createInstance(user) { - if (user.role === 'STUDENT') { - const service = await import('../services/student-service'); - if (service) { - return new service.default(user); - } - } else if (user.role === 'PROFESSOR') { - const service = await import('../services/professor-service'); - if (service) { - return new service.default(user); - } - } else { - throw new Error('Invalid Role!'); + switch (user.role) { + case 'STUDENT': + const studentService = await import('../services/student-service'); + if (studentService) { + return new studentService.default(user); + } + break; + case 'PROFESSOR': + const professorService = await import('../services/professor-service'); + if (professorService) { + return new professorService.default(user); + } + break; + default: + throw new Error('Invalid Role!'); } } From b48114b8bb07a048f0228317caee10c2a4a11b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Tue, 29 Nov 2022 11:41:23 -0300 Subject: [PATCH 4/8] Rename and move files --- src/context/auth.js | 2 +- src/context/user.js | 2 +- src/services/{professor-service.js => professor.js} | 0 src/services/{user-service-provider.js => provider.js} | 4 ++-- src/services/{student-service.js => student.js} | 2 +- src/{services/user-service.js => utils/mocks/api.js} | 4 ++-- src/{services/mocks.js => utils/mocks/responses.js} | 0 7 files changed, 7 insertions(+), 7 deletions(-) rename src/services/{professor-service.js => professor.js} (100%) rename src/services/{user-service-provider.js => provider.js} (79%) rename src/services/{student-service.js => student.js} (96%) rename src/{services/user-service.js => utils/mocks/api.js} (98%) rename src/{services/mocks.js => utils/mocks/responses.js} (100%) diff --git a/src/context/auth.js b/src/context/auth.js index fd5104b..3cf7d40 100644 --- a/src/context/auth.js +++ b/src/context/auth.js @@ -1,5 +1,5 @@ import { createContext, useContext, useEffect, useState } from 'react'; -import { getUser, registerUser } from '../services/user-service'; +import { getUser, registerUser } from '../utils/mocks/api'; const AuthContext = createContext(); diff --git a/src/context/user.js b/src/context/user.js index afb4527..4225201 100644 --- a/src/context/user.js +++ b/src/context/user.js @@ -1,6 +1,6 @@ import { createContext, useContext, useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; -import { UserServiceProvider } from '../services/user-service-provider'; +import { UserServiceProvider } from '../services/provider'; import { useAuthState } from './auth'; const UserContext = createContext(); diff --git a/src/services/professor-service.js b/src/services/professor.js similarity index 100% rename from src/services/professor-service.js rename to src/services/professor.js diff --git a/src/services/user-service-provider.js b/src/services/provider.js similarity index 79% rename from src/services/user-service-provider.js rename to src/services/provider.js index 31f51cf..30ddf81 100644 --- a/src/services/user-service-provider.js +++ b/src/services/provider.js @@ -4,13 +4,13 @@ export const UserServiceProvider = (function () { async function createInstance(user) { switch (user.role) { case 'STUDENT': - const studentService = await import('../services/student-service'); + const studentService = await import('./student'); if (studentService) { return new studentService.default(user); } break; case 'PROFESSOR': - const professorService = await import('../services/professor-service'); + const professorService = await import('./professor'); if (professorService) { return new professorService.default(user); } diff --git a/src/services/student-service.js b/src/services/student.js similarity index 96% rename from src/services/student-service.js rename to src/services/student.js index 5b9f297..1fcd107 100644 --- a/src/services/student-service.js +++ b/src/services/student.js @@ -8,7 +8,7 @@ import { getFaq, getPeopleByClassId, getUpcomingAssignmentsByClassId, -} from './user-service'; +} from '../utils/mocks/api'; export default class StudentService { constructor(user) { diff --git a/src/services/user-service.js b/src/utils/mocks/api.js similarity index 98% rename from src/services/user-service.js rename to src/utils/mocks/api.js index 0f0fb92..8735207 100644 --- a/src/services/user-service.js +++ b/src/utils/mocks/api.js @@ -1,4 +1,4 @@ -import { sleep } from '../utils/sleep'; +import { sleep } from '../sleep'; import { allClassrooms, allAssignments, @@ -9,7 +9,7 @@ import { allClassroomAnnouncements, allUpcomingAssignments, allPeople, -} from './mocks'; +} from './responses'; const getClassrooms = userId => sleep(300).then(() => { diff --git a/src/services/mocks.js b/src/utils/mocks/responses.js similarity index 100% rename from src/services/mocks.js rename to src/utils/mocks/responses.js From 38284ec7bf582e34edf8a2bd2276f6d81a62cd51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Tue, 29 Nov 2022 18:08:14 -0300 Subject: [PATCH 5/8] Update getInstance --- src/services/provider.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/provider.js b/src/services/provider.js index 30ddf81..038bf5c 100644 --- a/src/services/provider.js +++ b/src/services/provider.js @@ -21,9 +21,9 @@ export const UserServiceProvider = (function () { } return { - getInstance: function (user) { + getInstance: async function (user) { if (!instance) { - instance = createInstance(user); + instance = await createInstance(user); } return instance; }, From 2b1302ad3a6b90e9b3387339330b6ea6e6249a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Tue, 29 Nov 2022 18:24:13 -0300 Subject: [PATCH 6/8] Structure mocks in different apis --- src/context/auth.js | 6 +- src/services/professor.js | 4 + src/services/student.js | 32 ++---- src/utils/mocks/api.js | 230 +++++++++++++++++++------------------- 4 files changed, 136 insertions(+), 136 deletions(-) diff --git a/src/context/auth.js b/src/context/auth.js index 3cf7d40..59ccd82 100644 --- a/src/context/auth.js +++ b/src/context/auth.js @@ -1,5 +1,5 @@ import { createContext, useContext, useEffect, useState } from 'react'; -import { getUser, registerUser } from '../utils/mocks/api'; +import { CommonApi } from '../utils/mocks/api'; const AuthContext = createContext(); @@ -23,7 +23,7 @@ function AuthProvider(props) { const register = data => { setState({ ...state, status: 'pending' }); - return registerUser(data).then(data => { + return CommonApi.registerUser(data).then(data => { if (data.message) { return setState({ status: 'error', user: null, error: data }); } else { @@ -35,7 +35,7 @@ function AuthProvider(props) { const login = (email, password) => { setState({ ...state, status: 'pending' }); - return getUser(email, password).then(data => { + return CommonApi.getUser(email, password).then(data => { if (data.message) { return setState({ status: 'error', user: null, error: data }); } else { diff --git a/src/services/professor.js b/src/services/professor.js index 5589b51..9820227 100644 --- a/src/services/professor.js +++ b/src/services/professor.js @@ -1,5 +1,9 @@ +import { ProfessorApi } from '../utils/mocks/api'; + export default class ProfessorService { constructor(user) { this.user = user; } + + fetchClassrooms = () => ProfessorApi.getClassrooms(this.user.id); } diff --git a/src/services/student.js b/src/services/student.js index 1fcd107..294edd3 100644 --- a/src/services/student.js +++ b/src/services/student.js @@ -1,37 +1,29 @@ -import { - getAllAssignments, - getAssignmentById, - getAssignmentsByClassId, - getClassroomAnnouncementsById, - getClassroomById, - getClassrooms, - getFaq, - getPeopleByClassId, - getUpcomingAssignmentsByClassId, -} from '../utils/mocks/api'; +import { StudentApi } from '../utils/mocks/api'; export default class StudentService { constructor(user) { this.user = user; } - fetchClassrooms = () => getClassrooms(this.user.id); + fetchClassrooms = () => StudentApi.getClassrooms(this.user.id); - fetchAllAssignments = () => getAllAssignments(this.user.id); + fetchAllAssignments = () => StudentApi.getAllAssignments(this.user.id); - fetchAssignmentById = assignmentId => getAssignmentById(assignmentId); + fetchAssignmentById = assignmentId => + StudentApi.getAssignmentById(assignmentId); - fetchAssignmentsByClassId = classId => getAssignmentsByClassId(classId); + fetchAssignmentsByClassId = classId => + StudentApi.getAssignmentsByClassId(classId); - fetchClassroomById = classId => getClassroomById(classId); + fetchClassroomById = classId => StudentApi.getClassroomById(classId); - fetchFAQ = () => getFaq(); + fetchFAQ = () => StudentApi.getFaq(); fetchClassroomAnnouncements = classId => - getClassroomAnnouncementsById(classId); + StudentApi.getClassroomAnnouncementsById(classId); fetchUpcomingAssignmentsByClassId = classId => - getUpcomingAssignmentsByClassId(classId); + StudentApi.getUpcomingAssignmentsByClassId(classId); - fetchPeopleByClassId = classId => getPeopleByClassId(classId); + fetchPeopleByClassId = classId => StudentApi.getPeopleByClassId(classId); } diff --git a/src/utils/mocks/api.js b/src/utils/mocks/api.js index 8735207..9f31001 100644 --- a/src/utils/mocks/api.js +++ b/src/utils/mocks/api.js @@ -11,118 +11,122 @@ import { allPeople, } from './responses'; -const getClassrooms = userId => - sleep(300).then(() => { - console.log('Get classrooms ' + userId); - return { - data: allClassrooms, - }; - }); +const CommonApi = { + getUser: (email, password) => + sleep(300).then(() => { + let user; + if (email === 'p@test.com' && password === 'p123') { + user = professorUser; + } else if (email === 's@test.com' && password === 's123') { + user = studentUser; + } else { + return authFailure; + } + window.localStorage.setItem('$USER', JSON.stringify(user)); + return user; + }), -const getClassroomById = classId => - sleep(300).then(() => { - console.log('Get classroom by id ' + classId); - return { - data: allClassrooms.filter(c => c.id === classId)[0], - }; - }); - -const getClassroomAnnouncementsById = classId => - sleep(300).then(() => { - console.log('Get classroon announcements by id ' + classId); - return { - data: allClassroomAnnouncements.filter(c => c.classroom.id === classId), - }; - }); - -const getUpcomingAssignmentsByClassId = classId => - sleep(300).then(() => { - console.log('Getting upcoming assignments by class id ' + classId); - return { - data: allUpcomingAssignments.filter( - a => a.classrooms.filter(c => c.id === classId)[0] - ), - }; - }); - -const getAllAssignments = userId => - sleep(400).then(() => { - console.log('Getting all assignments ' + userId); - return { - data: allAssignments, - }; - }); - -const getAssignmentById = assignmentId => - sleep(400).then(() => { - console.log('Getting assignment by id ' + assignmentId); - return { - data: allAssignments.filter(a => a.id === assignmentId)[0], - }; - }); - -const getAssignmentsByClassId = classId => - sleep(300).then(() => { - console.log('Getting assignments by class id ' + classId); - return { - data: allAssignments.filter(a => a.classrooms[0].id === classId), - }; - }); - -const getPeopleByClassId = classId => - sleep(400).then(() => { - console.log('Getting people by class id ' + classId); - return { - data: allPeople.filter(p => p.classes[0].id === classId), - }; - }); - -const getFaq = () => - sleep(300).then(() => { - console.log('Fetching FAQ...'); - return { - data: faq, - }; - }); - -const getUser = (email, password) => - sleep(300).then(() => { - let user; - if (email === 'p@test.com' && password === 'p123') { - user = professorUser; - } else if (email === 's@test.com' && password === 's123') { - user = studentUser; - } else { - return authFailure; - } - window.localStorage.setItem('$USER', JSON.stringify(user)); - return user; - }); - -const registerUser = data => - sleep(300).then(() => { - let userData; - if (data.email === 'p@test.com') { - userData = { ...data, role: 'PROFESSOR' }; - } else if (data.email === 's@test.com') { - userData = { ...data, role: 'STUDENT' }; - } else { - return authFailure; - } - window.localStorage.setItem('$USER', JSON.stringify(data)); - return userData; - }); - -export { - getClassrooms, - getClassroomById, - getAllAssignments, - getAssignmentById, - getAssignmentsByClassId, - getClassroomAnnouncementsById, - getUpcomingAssignmentsByClassId, - getPeopleByClassId, - getFaq, - getUser, - registerUser, + registerUser: data => + sleep(300).then(() => { + let userData; + if (data.email === 'p@test.com') { + userData = { ...data, role: 'PROFESSOR' }; + } else if (data.email === 's@test.com') { + userData = { ...data, role: 'STUDENT' }; + } else { + return authFailure; + } + window.localStorage.setItem('$USER', JSON.stringify(data)); + return userData; + }), }; + +const StudentApi = { + ...CommonApi, + getClassrooms: userId => + sleep(300).then(() => { + console.log('Get classrooms ' + userId); + return { + data: allClassrooms, + }; + }), + + 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 => + sleep(300).then(() => { + console.log('Getting upcoming assignments by class id ' + classId); + return { + data: allUpcomingAssignments.filter( + a => a.classrooms.filter(c => c.id === classId)[0] + ), + }; + }), + + getAllAssignments: userId => + sleep(400).then(() => { + console.log('Getting all assignments ' + userId); + return { + data: allAssignments, + }; + }), + + getAssignmentById: assignmentId => + sleep(400).then(() => { + console.log('Getting assignment by id ' + assignmentId); + return { + data: allAssignments.filter(a => a.id === assignmentId)[0], + }; + }), + + 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: () => + sleep(300).then(() => { + console.log('Fetching FAQ...'); + return { + data: faq, + }; + }), +}; + +const ProfessorApi = { + ...CommonApi, + getClassrooms: userId => + sleep(300).then(() => { + console.log('Get classrooms ' + userId); + return { + data: allClassrooms, + }; + }), +}; + +export { StudentApi, ProfessorApi, CommonApi }; From faf7890efa1b2393f8f1725ae81f46ed8fb6a63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Wed, 30 Nov 2022 16:03:18 -0300 Subject: [PATCH 7/8] Add custom class card for professor --- src/components/ClassCard/index.js | 75 ++++++++++++++++------------ src/screens/professor/Home/View.js | 2 + src/screens/professor/Home/styles.js | 11 ++++ src/utils/mocks/api.js | 3 +- src/utils/mocks/responses.js | 36 +++++++++++++ 5 files changed, 94 insertions(+), 33 deletions(-) diff --git a/src/components/ClassCard/index.js b/src/components/ClassCard/index.js index 79bf495..6c78254 100644 --- a/src/components/ClassCard/index.js +++ b/src/components/ClassCard/index.js @@ -17,6 +17,7 @@ function ClassCard({ title, color, teachers, + course, layoutType, onClick, }) { @@ -45,23 +46,30 @@ function ClassCard({ > {title} - - - {teachers.map(t => ( - - ))} - - t.name).join(', ')}> - - {teachers.map(t => t.name).join(', ')} - - - + {teachers && ( + + + {teachers.map(t => ( + + ))} + + t.name).join(', ')}> + + {teachers.map(t => t.name).join(', ')} + + + + )} + {course && {course}} @@ -82,21 +90,24 @@ function ClassCard({ > {title} - - - {teachers.map(t => ( - - ))} - - - {teachers.map(t => t.name).join(', ')} - - + {teachers && ( + + + {teachers.map(t => ( + + ))} + + + {teachers.map(t => t.name).join(', ')} + + + )} + {course && {course}} diff --git a/src/screens/professor/Home/View.js b/src/screens/professor/Home/View.js index 64046f5..c7cb6a2 100644 --- a/src/screens/professor/Home/View.js +++ b/src/screens/professor/Home/View.js @@ -30,6 +30,7 @@ function View({ layoutType, classrooms, onClickClassCard }) { title={classroom.name} color={classroom.color} teachers={classroom.teachers} + course={classroom.course} layoutType={layoutType} onClick={() => onClickClassCard(classroom.id)} /> @@ -92,6 +93,7 @@ function View({ layoutType, classrooms, onClickClassCard }) { title={classroom.name} color={classroom.color} teachers={classroom.teachers} + course={classroom.course} layoutType={layoutType} onClick={() => onClickClassCard(classroom.id)} /> diff --git a/src/screens/professor/Home/styles.js b/src/screens/professor/Home/styles.js index 1a8a842..cd02a41 100644 --- a/src/screens/professor/Home/styles.js +++ b/src/screens/professor/Home/styles.js @@ -4,8 +4,13 @@ const desktopContainer = { margin: 0, }; +const desktopDivider = { + borderLeft: '4px solid #CFCFCF', +}; + const desktop = { container: desktopContainer, + divider: desktopDivider, }; // ========== Mobile ========== @@ -16,8 +21,14 @@ const mobileContainer = { margin: 0, }; +const mobileDivider = { + borderTop: '2px solid #CFCFCF', + paddingTop: '15px', +}; + const mobile = { container: mobileContainer, + divider: mobileDivider, }; // ========== Unset ========== diff --git a/src/utils/mocks/api.js b/src/utils/mocks/api.js index 9f31001..55e4889 100644 --- a/src/utils/mocks/api.js +++ b/src/utils/mocks/api.js @@ -9,6 +9,7 @@ import { allClassroomAnnouncements, allUpcomingAssignments, allPeople, + professorClassrooms, } from './responses'; const CommonApi = { @@ -124,7 +125,7 @@ const ProfessorApi = { sleep(300).then(() => { console.log('Get classrooms ' + userId); return { - data: allClassrooms, + data: professorClassrooms, }; }), }; diff --git a/src/utils/mocks/responses.js b/src/utils/mocks/responses.js index a3bfb97..661a166 100644 --- a/src/utils/mocks/responses.js +++ b/src/utils/mocks/responses.js @@ -95,6 +95,41 @@ const allClassrooms = [ }, ]; +const professorClassrooms = [ + { + id: '321', + name: 'Introdução à Ciência de Dados', + abbreviation: 'ICD', + color: '#006FF2', + course: 'BSI 2020', + appointmentSlots: [ + { weekDay: 'Quarta-feira', start: '10:00', end: '11:40' }, + { weekDay: 'Sexta-feira', start: '10:00', end: '11:40' }, + ], + }, + { + id: '123', + name: 'Teoria dos Grafos', + abbreviation: 'TDG', + color: '#d30000', + course: 'BSI 2018', + appointmentSlots: [ + { weekDay: 'Quarta-feira', start: '11:00', end: '12:00' }, + { weekDay: 'Segunda-feira', start: '10:00', end: '11:40' }, + ], + }, + { + id: '123', + name: 'Matemática Discreta', + abbreviation: 'MD', + color: '#149b00', + course: 'BSI 2020', + appointmentSlots: [ + { weekDay: 'Quarta-feira', start: '9:00', end: '10:00' }, + ], + }, +]; + const allAssignments = [ { id: '5435', @@ -582,4 +617,5 @@ export { professorUser, authFailure, allUpcomingAssignments, + professorClassrooms, }; From 2dee31526112782354a0cc39d453a42333dc41a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Mur=C3=A7a?= Date: Wed, 30 Nov 2022 21:26:11 -0300 Subject: [PATCH 8/8] Add assignments to review card --- src/components/AssignmentCard/index.js | 47 ++++++++++--- src/screens/professor/Home/View.js | 91 +++++++++++++++++++++++--- src/screens/professor/Home/index.js | 15 ++++- src/services/professor.js | 3 + src/utils/mocks/api.js | 8 +++ src/utils/mocks/responses.js | 77 +++++++++++++++++++++- 6 files changed, 223 insertions(+), 18 deletions(-) diff --git a/src/components/AssignmentCard/index.js b/src/components/AssignmentCard/index.js index e893b3d..fc5758b 100644 --- a/src/components/AssignmentCard/index.js +++ b/src/components/AssignmentCard/index.js @@ -18,6 +18,10 @@ function AssignmentCard({ classrooms, dueDate, scores, + deliveredByStudents, + reviewed, + total, + isAssignmentToReview, layoutType, onClick, }) { @@ -61,16 +65,30 @@ function AssignmentCard({ {classrooms.map(c => c.name).join(', ')} + Data de entrega: {' '} {capitalizeFirstLetter( dayjs(dueDate).format('dddd, DD/MM | HH:mm[h]') )} - - Valor: - {scores.map(s => s.value).join(', ')} pts - + {deliveredByStudents >= 0 && total && ( + + Entregues: {' '} + {`${deliveredByStudents} de ${total}`} + + )} + {reviewed >= 0 && total && ( + + Corrigidas: {`${reviewed} de ${total}`} + + )} + {!isAssignmentToReview && ( + + Valor: + {scores.map(s => s.value).join(', ')} pts + + )} @@ -110,10 +128,23 @@ function AssignmentCard({ dayjs(dueDate).format('dddd, DD/MM | HH:mm[h]') )} - - Valor: - {scores.map(s => s.value).join(', ')} pts - + {deliveredByStudents >= 0 && total && ( + + Entregues: {' '} + {`${deliveredByStudents} de ${total}`} + + )} + {reviewed >= 0 && total && ( + + Corrigidas: {`${reviewed} de ${total}`} + + )} + {!isAssignmentToReview && ( + + Valor: + {scores.map(s => s.value).join(', ')} pts + + )} diff --git a/src/screens/professor/Home/View.js b/src/screens/professor/Home/View.js index c7cb6a2..0651aea 100644 --- a/src/screens/professor/Home/View.js +++ b/src/screens/professor/Home/View.js @@ -1,11 +1,18 @@ import { Grid, Skeleton, Stack } from '@mui/material'; import { Container } from '@mui/system'; +import AssignmentCard from '../../../components/AssignmentCard'; import ClassCard from '../../../components/ClassCard'; import { createArrayFrom1ToN } from '../../../utils/createArrayFrom1ToN'; import styles from './styles'; -function View({ layoutType, classrooms, onClickClassCard }) { - const { container, divider, assignmentsStack } = styles[layoutType]; +function View({ + layoutType, + classrooms, + assignmentsToReview, + onClickClassCard, +}) { + const { container, divider, assignmentsStack, onClickAssignmentCard } = + styles[layoutType]; if (layoutType === 'desktop') { return ( @@ -51,7 +58,6 @@ function View({ layoutType, classrooms, onClickClassCard }) {

Atividades para corrigir

-

Atribuídas

-

Atividade 1

-

Atividade 2

+ {assignmentsToReview === null ? ( + createArrayFrom1ToN(6).map(i => ( + + )) + ) : assignmentsToReview.length !== 0 ? ( + assignmentsToReview.map(assignment => ( + onClickAssignmentCard(assignment.id)} + /> + )) + ) : ( + +

Nenhuma atividade encontrada!

+
+ )}
@@ -105,7 +146,6 @@ function View({ layoutType, classrooms, onClickClassCard }) { )}

Atividades para corrigir

-

Atribuídas

-

Atividade 1

-

Atividade 2

+ {assignmentsToReview === null ? ( + createArrayFrom1ToN(6).map(i => ( + + )) + ) : assignmentsToReview.length !== 0 ? ( + assignmentsToReview.map(assignment => ( + onClickAssignmentCard(assignment.id)} + /> + )) + ) : ( + +

Nenhuma atividade encontrada!

+
+ )}
); diff --git a/src/screens/professor/Home/index.js b/src/screens/professor/Home/index.js index 32580b6..d16c20d 100644 --- a/src/screens/professor/Home/index.js +++ b/src/screens/professor/Home/index.js @@ -11,6 +11,7 @@ function Home() { const layoutType = useLayoutType(); const { userService } = useUser(); const [classrooms, setClassrooms] = useState(null); + const [assignmentsToReview, setAssignmentsToReview] = useState(null); useEffect(() => { async function getClassrooms() { @@ -20,17 +21,29 @@ function Home() { getClassrooms(); }, [userService, userService.fetchClassrooms]); + useEffect(() => { + async function getAssignmentsToReview() { + const result = await userService.fetchAssignmentsToReview(); + setAssignmentsToReview(result.data); + } + getAssignmentsToReview(); + }, [userService, userService.fetchAllAssignments]); + const onClickClassCard = id => { navigate(`/class/${id}`); }; - console.log(classrooms); + const onClickAssignmentCard = id => { + navigate(`/assignment/${id}`); + }; return ( ); } diff --git a/src/services/professor.js b/src/services/professor.js index 9820227..3599f67 100644 --- a/src/services/professor.js +++ b/src/services/professor.js @@ -6,4 +6,7 @@ export default class ProfessorService { } fetchClassrooms = () => ProfessorApi.getClassrooms(this.user.id); + + fetchAssignmentsToReview = () => + ProfessorApi.getAssignmentsToReview(this.user.id); } diff --git a/src/utils/mocks/api.js b/src/utils/mocks/api.js index 55e4889..08009c0 100644 --- a/src/utils/mocks/api.js +++ b/src/utils/mocks/api.js @@ -10,6 +10,7 @@ import { allUpcomingAssignments, allPeople, professorClassrooms, + assignmentsToReview, } from './responses'; const CommonApi = { @@ -128,6 +129,13 @@ const ProfessorApi = { data: professorClassrooms, }; }), + getAssignmentsToReview: userId => + sleep(400).then(() => { + console.log('Getting assignments to review' + userId); + return { + data: assignmentsToReview, + }; + }), }; export { StudentApi, ProfessorApi, CommonApi }; diff --git a/src/utils/mocks/responses.js b/src/utils/mocks/responses.js index 661a166..25eadd3 100644 --- a/src/utils/mocks/responses.js +++ b/src/utils/mocks/responses.js @@ -119,7 +119,7 @@ const professorClassrooms = [ ], }, { - id: '123', + id: '666', name: 'Matemática Discreta', abbreviation: 'MD', color: '#149b00', @@ -344,6 +344,80 @@ const allClassroomAnnouncements = [ }, ]; +const assignmentsToReview = [ + { + id: '0123', + type: 'assessment', + title: + 'Prova 1 - Armazenamento de Dados. Python em CD. Armazenamento Analítico', + dueDate: '2022-07-01 23:59', + scores: [ + { + classroomId: '321', + value: 30, + }, + ], + classrooms: professorClassrooms.filter(c => c.id === '321'), + status: 'OPEN', + deliveredByStudents: 10, + reviewed: 6, + total: 30, + }, + { + id: '0128', + type: 'assessment', + title: + 'Prova 2 - Visualização de Dados. Matemática e Estatística em CD. Análise de Dados', + dueDate: '2022-09-01 23:59', + scores: [ + { + classroomId: '321', + value: 30, + }, + ], + classrooms: professorClassrooms.filter(c => c.id === '321'), + status: 'CLOSED', + deliveredByStudents: 30, + reviewed: 1, + total: 30, + }, + { + id: '0129', + type: 'assessment', + title: 'Lista de Exercícios 1 - Caminhos e circuitos', + dueDate: '2022-09-01 23:59', + scores: [ + { + classroomId: '123', + value: 30, + }, + ], + classrooms: professorClassrooms.filter(c => c.id === '123'), + status: 'CLOSED', + deliveredByStudents: 30, + reviewed: 0, + total: 30, + }, + + { + id: '0130', + type: 'assessment', + title: 'Lista de Exercícios 2 - Tabela verdade', + dueDate: '2022-09-01 23:59', + scores: [ + { + classroomId: '666', + value: 30, + }, + ], + classrooms: professorClassrooms.filter(c => c.id === '666'), + status: 'OPEN', + deliveredByStudents: 0, + reviewed: 0, + total: 30, + }, +]; + const allUpcomingAssignments = [ { id: '5435', @@ -618,4 +692,5 @@ export { authFailure, allUpcomingAssignments, professorClassrooms, + assignmentsToReview, };