diff --git a/frontend/frontend/src/assets/logo_UGent_EN_RGB_2400_color-on-white.png b/frontend/frontend/public/assets/logo_UGent_EN_RGB_2400_color-on-white.png similarity index 100% rename from frontend/frontend/src/assets/logo_UGent_EN_RGB_2400_color-on-white.png rename to frontend/frontend/public/assets/logo_UGent_EN_RGB_2400_color-on-white.png diff --git a/frontend/frontend/src/assets/logo_UGent_EN_RGB_2400_color.png b/frontend/frontend/public/assets/logo_UGent_EN_RGB_2400_color.png similarity index 100% rename from frontend/frontend/src/assets/logo_UGent_EN_RGB_2400_color.png rename to frontend/frontend/public/assets/logo_UGent_EN_RGB_2400_color.png diff --git a/frontend/frontend/src/assets/logo_UGent_EN_RGB_2400_white.png b/frontend/frontend/public/assets/logo_UGent_EN_RGB_2400_white.png similarity index 100% rename from frontend/frontend/src/assets/logo_UGent_EN_RGB_2400_white.png rename to frontend/frontend/public/assets/logo_UGent_EN_RGB_2400_white.png diff --git a/frontend/frontend/src/assets/logo_UGent_NL_RGB_2400_kleur-op-wit.png b/frontend/frontend/public/assets/logo_UGent_NL_RGB_2400_kleur-op-wit.png similarity index 100% rename from frontend/frontend/src/assets/logo_UGent_NL_RGB_2400_kleur-op-wit.png rename to frontend/frontend/public/assets/logo_UGent_NL_RGB_2400_kleur-op-wit.png diff --git a/frontend/frontend/src/assets/logo_UGent_NL_RGB_2400_kleur.png b/frontend/frontend/public/assets/logo_UGent_NL_RGB_2400_kleur.png similarity index 100% rename from frontend/frontend/src/assets/logo_UGent_NL_RGB_2400_kleur.png rename to frontend/frontend/public/assets/logo_UGent_NL_RGB_2400_kleur.png diff --git a/frontend/frontend/src/assets/logo_UGent_NL_RGB_2400_wit.png b/frontend/frontend/public/assets/logo_UGent_NL_RGB_2400_wit.png similarity index 100% rename from frontend/frontend/src/assets/logo_UGent_NL_RGB_2400_wit.png rename to frontend/frontend/public/assets/logo_UGent_NL_RGB_2400_wit.png diff --git a/frontend/frontend/src/assets/react.svg b/frontend/frontend/public/assets/react.svg similarity index 100% rename from frontend/frontend/src/assets/react.svg rename to frontend/frontend/public/assets/react.svg diff --git a/frontend/frontend/src/assets/ufo-logo-3375276369.png b/frontend/frontend/public/assets/ufo-logo-3375276369.png similarity index 100% rename from frontend/frontend/src/assets/ufo-logo-3375276369.png rename to frontend/frontend/public/assets/ufo-logo-3375276369.png diff --git a/frontend/frontend/src/components/AssignmentListItemSubjectsPage.tsx b/frontend/frontend/src/components/AssignmentListItemSubjectsPage.tsx new file mode 100644 index 00000000..6ad833a0 --- /dev/null +++ b/frontend/frontend/src/components/AssignmentListItemSubjectsPage.tsx @@ -0,0 +1,62 @@ +import {ListItem, ListItemButton, ListItemText, Divider} from "@mui/material"; +import {useNavigate} from "react-router-dom"; +import {t} from "i18next"; +interface AssignmentListItemSubjectsPageProps { + key: string; + projectName: string; + dueDate?: Date; + submissions: number; + score: number; + isStudent: boolean; +} + +/* +* This component is used to display a single assignment in the list of assignments +* @param key: string - the key of the assignment +* @param projectName: string - the name of the project +* @param dueDate: Date - the due date of the project +* @param submissions: number - number of submissions for the project +* @param score: number - assigned score on the project +* @param isStudent: boolean - if the user is a student or a teacher +*/ + +export function AssignmentListItemSubjectsPage({key,projectName, dueDate, submissions, score, isStudent}:AssignmentListItemSubjectsPageProps) { + const navigate = useNavigate(); + const handleProjectClick = () => { + console.log("Project clicked"); + navigate(`/${key}`) + } + + return ( + <> + + + {isStudent? + <> + + + + + + : + <> + + + + + } + + + + + ); +} \ No newline at end of file diff --git a/frontend/frontend/src/components/StudentScoreListItem.tsx b/frontend/frontend/src/components/StudentScoreListItem.tsx new file mode 100644 index 00000000..74d6bccd --- /dev/null +++ b/frontend/frontend/src/components/StudentScoreListItem.tsx @@ -0,0 +1,50 @@ +import {ListItem, ListItemText, Divider, TextField, IconButton} from "@mui/material"; +import DownloadIcon from '@mui/icons-material/Download'; +import {t} from "i18next"; + +interface StudentScoreListItemProps { + key: string; + studentName: string; + submissionFiles: string[]; +} + +/* +* This component is used to display a single assignment in the list of assignments +* @param key: string - the key of the studentOnProject +* @param studentName: string - the name of the student +* @param submissionFiles: string[] - a list of all files submitted by this student +*/ + +export function StudentScoreListItem({key, studentName, submissionFiles}:StudentScoreListItemProps) { + return ( + <> + + + <> + + + + + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/frontend/frontend/src/i18n/config.ts b/frontend/frontend/src/i18n/config.ts index 8a1313cb..7b0c659f 100644 --- a/frontend/frontend/src/i18n/config.ts +++ b/frontend/frontend/src/i18n/config.ts @@ -3,8 +3,8 @@ import i18n from "i18next"; import LanguageDetector from "i18next-browser-languagedetector"; const english = { - logo: "./src/assets/logo_UGent_EN_RGB_2400_white.png", - logo_blue: "./src/assets/logo_UGent_EN_RGB_2400_color.png", + logo: "/assets/logo_UGent_EN_RGB_2400_white.png", + logo_blue: "/assets/logo_UGent_EN_RGB_2400_color.png", login: "Log in with your UGent account", back: "Back", current_courses: "Current courses", @@ -12,10 +12,16 @@ const english = { students: "Students: ", no_deadline: "No deadline", add_admin: "Add admin", + submission: "Submission", + error: "Something went wrong.", + assignment: "Assignment:", + filename: "Submitted file:", + restrictions: "Restrictions:", + current_projects: "Current projects", }; const dutch = { - logo: "./src/assets/logo_UGent_NL_RGB_2400_wit.png", - logo_blue: "./src/assets/logo_UGent_NL_RGB_2400_kleur.png", + logo: "/assets/logo_UGent_NL_RGB_2400_wit.png", + logo_blue: "/assets/logo_UGent_NL_RGB_2400_kleur.png", login: "Log in met je UGent account", back: "Terug", current_courses: "Huidige vakken", @@ -23,6 +29,12 @@ const dutch = { students: "Studenten: ", no_deadline: "Geen deadline", add_admin: "Voeg admin toe", + submission: "Indiening", + error: "Er is iets misgegaan.", + assignment: "Opgave:", + filename: "Ingediend bestand:", + restrictions: "Restricties:", + current_projects: "Huidige projecten", }; i18n.use(initReactI18next).use(LanguageDetector).init({ diff --git a/frontend/frontend/src/main.tsx b/frontend/frontend/src/main.tsx index 54ff44ee..9141dcd8 100644 --- a/frontend/frontend/src/main.tsx +++ b/frontend/frontend/src/main.tsx @@ -8,17 +8,22 @@ import ErrorPage from "./pages/ErrorPage.tsx"; import {MainPage} from "./pages/mainPage/MainPage.tsx"; import {Helmet, HelmetProvider} from "react-helmet-async"; + +import { SubjectsStudentPage } from "./pages/subjectsPage/SubjectsStudentPage.tsx"; +import { SubjectsTeacherPage } from "./pages/subjectsPage/SubjectsTeacherPage.tsx"; +import { ProjectScoresPage } from "./pages/scoresPage/ProjectScoresPage.tsx"; import { SubjectsStudentPage } from "./pages/subjects_page/SubjectsStudentPage.tsx"; import { AssignmentStudentPage } from "./pages/assignmentPage/assignmentStudentPage"; import { AssignmentTeacherPage } from "./pages/assignmentPage/assignmentTeacherPage.tsx"; import { GroupsPage } from "./pages/groupsPage/groupsPage.tsx"; import {SubjectsStudentPage} from "./pages/subjects_page/SubjectsStudentPage.tsx"; - import {LocalizationProvider} from "@mui/x-date-pickers"; import {AdapterDayjs} from '@mui/x-date-pickers/AdapterDayjs/AdapterDayjs'; +import {SubmissionPage} from "./pages/submissionPage/SubmissionPage.tsx"; import {SimpleRequestsPage} from "./pages/simpleRequestsPage/SimpleRequestsPage.tsx"; + const router = createBrowserRouter([ { path: "/", @@ -26,10 +31,19 @@ const router = createBrowserRouter([ errorElement: , }, { - path: "/subjects_student", + path: "/subjects_student/:courseId", element: , }, { + + path: "/subjects_teacher/:courseId", + element: , + }, + { + path: "/scores", + element: , + }, + path: "/assignment_student", element: , }, @@ -47,6 +61,11 @@ const router = createBrowserRouter([ }, { + + path: "/submission/:project", + element: , + }, + { path: "/test_requests", element: , } diff --git a/frontend/frontend/src/pages/ErrorPage.tsx b/frontend/frontend/src/pages/ErrorPage.tsx index 6afd2b0f..0efc778b 100644 --- a/frontend/frontend/src/pages/ErrorPage.tsx +++ b/frontend/frontend/src/pages/ErrorPage.tsx @@ -1,18 +1,122 @@ -import { useRouteError } from "react-router-dom"; +import {isRouteErrorResponse, useRouteError} from "react-router-dom"; +import {Box, Typography} from "@mui/material"; +import {t} from "i18next"; -//TODO:: fix a decent error page export default function ErrorPage() { const error = useRouteError(); console.error(error); + let errorMessage: string; + + if (isRouteErrorResponse(error)) { + // error is type `ErrorResponse` + errorMessage = error.error?.message || error.statusText; + } else if (error instanceof Error) { + errorMessage = error.message; + } else if (typeof error === 'string') { + errorMessage = error; + } else { + console.error(error); + errorMessage = 'Unknown error'; + } return ( -
-

Oops!

-

Sorry, an unexpected error has occurred.

-

- error -

-
+ <> + + + + + + + + {t("error")} + + + {errorMessage} + + + + + + ); } \ No newline at end of file diff --git a/frontend/frontend/src/pages/SubjectsPage/ArchivedProjectsView.tsx b/frontend/frontend/src/pages/SubjectsPage/ArchivedProjectsView.tsx new file mode 100644 index 00000000..0f4cded8 --- /dev/null +++ b/frontend/frontend/src/pages/SubjectsPage/ArchivedProjectsView.tsx @@ -0,0 +1,7 @@ +export function ArchivedProjectsView() { + return ( + <> + + + ); +} \ No newline at end of file diff --git a/frontend/frontend/src/pages/SubjectsPage/ProjectsView.tsx b/frontend/frontend/src/pages/SubjectsPage/ProjectsView.tsx new file mode 100644 index 00000000..70266f32 --- /dev/null +++ b/frontend/frontend/src/pages/SubjectsPage/ProjectsView.tsx @@ -0,0 +1,101 @@ +import {Box, Typography} from "@mui/material"; +import List from '@mui/material/List'; +import {AssignmentListItemSubjectsPage} from "../../components/AssignmentListItemSubjectsPage.tsx"; + +interface ProjectsViewProps { + courseId: string; + isStudent: boolean; +} + +interface Course { + id: string; + name: string; + teacher: string; + students: string[]; + //list of assignment ids + assignments: string[]; + archived: boolean; +} + +interface Assignment { + id: string; + name: string; + deadline?: Date; + submissions: number; + score: number; +} + +export function ProjectsView({courseId, isStudent}: ProjectsViewProps) { + const course = getCourse(courseId); + const assignments = course.assignments.map((assignmentId) => getAssignment(assignmentId)); + + return ( + <> + + {isStudent? + <> + Project + Deadline + Submissions + Score + + : + <> + Project + Deadline + Edit + + } + + + + + + {assignments.map((assignment) => ( + + ))} + + + + + + ); +} + +//TODO: use api to get data, for now use mock data +function getCourse(courseId: string): Course { + return { + id: courseId, + name: "courseName", + teacher: "teacher", + students: ["student1", "student2"], + archived: false, + assignments: ["assignment1", "assignment2", "assignment3", "assignment4", "assignment5", "assignment6", "assignment7", "assignment8", "assignment9"] + } +} + +function getAssignment(assignmentId: string): Assignment { + return { + id: assignmentId, + name: "assignmentName", + deadline: new Date(2022, 11, 17), + submissions: 2, + score: 10 + } +} \ No newline at end of file diff --git a/frontend/frontend/src/pages/SubjectsPage/SubjectsStudentPage.tsx b/frontend/frontend/src/pages/SubjectsPage/SubjectsStudentPage.tsx new file mode 100644 index 00000000..512c33a7 --- /dev/null +++ b/frontend/frontend/src/pages/SubjectsPage/SubjectsStudentPage.tsx @@ -0,0 +1,22 @@ +import { Header } from "../../components/Header"; +import { Box, Stack } from "@mui/material"; +import TabSwitcher from "../../components/TabSwitcher.tsx"; +import {ArchivedProjectsView} from "./ArchivedProjectsView.tsx"; +import {ProjectsView} from "./ProjectsView.tsx"; +import { useParams } from "react-router-dom"; + +export function SubjectsStudentPage() { + let { courseId } = useParams(); + courseId = String(courseId); + return ( + <> + +
+ + ,]}/> + + + + ); +} \ No newline at end of file diff --git a/frontend/frontend/src/pages/SubjectsPage/SubjectsTeacherPage.tsx b/frontend/frontend/src/pages/SubjectsPage/SubjectsTeacherPage.tsx new file mode 100644 index 00000000..1858afe4 --- /dev/null +++ b/frontend/frontend/src/pages/SubjectsPage/SubjectsTeacherPage.tsx @@ -0,0 +1,22 @@ +import { Header } from "../../components/Header"; +import { Box, Stack } from "@mui/material"; +import TabSwitcher from "../../components/TabSwitcher.tsx"; +import {ArchivedProjectsView} from "./ArchivedProjectsView.tsx"; +import {ProjectsView} from "./ProjectsView.tsx"; +import { useParams } from "react-router-dom"; + +export function SubjectsTeacherPage() { + let { courseId } = useParams(); + courseId = String(courseId); + return ( + <> + +
+ + ,]}/> + + + + ); +} \ No newline at end of file diff --git a/frontend/frontend/src/pages/loginPage/LoginPage.tsx b/frontend/frontend/src/pages/loginPage/LoginPage.tsx index e4aa5bfa..72d3c320 100644 --- a/frontend/frontend/src/pages/loginPage/LoginPage.tsx +++ b/frontend/frontend/src/pages/loginPage/LoginPage.tsx @@ -1,5 +1,5 @@ -import { Box, Button, Typography } from "@mui/material"; -import { t } from "i18next"; +import {Box, Button, Typography} from "@mui/material"; +import {t} from "i18next"; import {useNavigate} from "react-router-dom"; /* @@ -16,106 +16,106 @@ export function LoginPage() { //navigate("main") //relative path, so it will redirect to localhost:3000/login/main } - return ( - <> - - - - + return ( + <> - - Naam Platform - - - - - - - - - ); + + + + + + Naam Platform + + + + + + + + + ); } diff --git a/frontend/frontend/src/pages/scoresPage/ProjectScoresPage.tsx b/frontend/frontend/src/pages/scoresPage/ProjectScoresPage.tsx new file mode 100644 index 00000000..d8ba97fe --- /dev/null +++ b/frontend/frontend/src/pages/scoresPage/ProjectScoresPage.tsx @@ -0,0 +1,30 @@ +import { Header } from "../../components/Header"; +import { Box, Button, Stack } from "@mui/material"; +import { useParams } from "react-router-dom"; +import { StudentsView } from "./StudentsView.tsx"; +import SaveIcon from '@mui/icons-material/Save'; +import CloseIcon from '@mui/icons-material/Close'; + +export function ProjectScoresPage() { + let { projectId } = useParams(); + projectId = String(projectId); + return ( + <> + +
+ + + + + + + + + + + + {t("restrictions")} + + + { + submission.restrictions.map((restriction, index) => { + return ( + <> + + {restriction.name} + {restriction.artifact && + } + {restriction.value} + + + + ); + }) + } + + + + + + + ); +} \ No newline at end of file