Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Courses now converts deadlines from string to Date right after fetch #295

Merged
merged 5 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions frontend/src/components/Courses/CourseDetailTeacher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
} from "@mui/material";
import { ChangeEvent, useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Course, Project, apiHost, getIdFromLink, getNearestFutureDate, getUserName, appHost } from "./CourseUtils";
import { Course, Project, apiHost, getIdFromLink, getNearestFutureDate, getUserName, appHost, ProjectDetail } from "./CourseUtils";

Check failure on line 21 in frontend/src/components/Courses/CourseDetailTeacher.tsx

View workflow job for this annotation

GitHub Actions / Frontend-tests

'Project' is defined but never used
import { Link, useNavigate, NavigateFunction, useLoaderData } from "react-router-dom";
import { Title } from "../Header/Title";
import ClearIcon from '@mui/icons-material/Clear';
Expand Down Expand Up @@ -103,10 +103,11 @@

const courseDetail = useLoaderData() as { //TODO CATCH ERROR
Vucis marked this conversation as resolved.
Show resolved Hide resolved
course: Course ,
projects:Project[] ,
projects:ProjectDetail[] ,
admins: UserUid[],
students: UserUid[]
};

const { course, projects, admins, students } = courseDetail;
const { t } = useTranslation('translation', { keyPrefix: 'courseDetailTeacher' });
const { i18n } = useTranslation();
Expand Down Expand Up @@ -179,7 +180,7 @@
* @param projects - The array of projects.
* @returns Either a place holder for no projects or a grid of cards describing the projects.
*/
function EmptyOrNotProjects({projects}: {projects: Project[]}): JSX.Element {
function EmptyOrNotProjects({projects}: {projects: ProjectDetail[]}): JSX.Element {
const { t } = useTranslation('translation', { keyPrefix: 'courseDetailTeacher' });
if(projects === undefined || projects.length === 0){
return (
Expand All @@ -199,7 +200,7 @@
{getNearestFutureDate(project.deadlines) &&
(
<Typography variant="body1">
{`${t('deadline')}: ${getNearestFutureDate(project.deadlines)?.toLocaleDateString()}`}
{`${t('deadline')}: ${getNearestFutureDate(project.deadlines)?.[1].toLocaleDateString()}`}
</Typography>
)}
</CardContent>
Expand Down
39 changes: 32 additions & 7 deletions frontend/src/components/Courses/CourseUtilComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import {
Course,
Project,
ProjectDetail,
apiHost,
getIdFromLink,
getNearestFutureDate,
Expand Down Expand Up @@ -100,7 +101,7 @@ export function SideScrollableCourses({
const [teacherNameFilter, setTeacherNameFilter] = useState(
initialTeacherNameFilter
);
const [projects, setProjects] = useState<{ [courseId: string]: Project[] }>(
const [projects, setProjects] = useState<{ [courseId: string]: ProjectDetail[] }>(
{}
);

Expand Down Expand Up @@ -159,10 +160,33 @@ export function SideScrollableCourses({
);

const projectResults = await Promise.all(projectPromises);
const projectsMap: { [courseId: string]: Project[] } = {};
const projectsMap: { [courseId: string]: ProjectDetail[] } = {};

projectResults.forEach((result, index) => {
projectsMap[getIdFromLink(courses[index].course_id)] = result.data;
const detailProjectPromises = result.data.map(async (item: Project) => {
const projectRes = await authenticatedFetch(item.project_id);
if (projectRes.status !== 200) {
throw new Response("Failed to fetch project data", {
status: projectRes.status,
});
}
const projectJson = await projectRes.json();
const projectData = projectJson.data;
const project: ProjectDetail = {
...item,
deadlines: projectData.deadlines.map(
([description, dateString]: [string, string]) => [
description,
new Date(dateString),
]
),
};
return project;
});
Promise.all(detailProjectPromises).then((projects) => {
projectsMap[getIdFromLink(courses[index].course_id)] = projects;
setProjects({ ...projectsMap });
});
});

setProjects(projectsMap);
Expand Down Expand Up @@ -216,7 +240,7 @@ function EmptyOrNotFilteredCourses({
projects,
}: {
filteredCourses: Course[];
projects: { [courseId: string]: Project[] };
projects: { [courseId: string]: ProjectDetail[] };
}): JSX.Element {
const { t } = useTranslation("translation", {
keyPrefix: "courseDetailTeacher",
Expand Down Expand Up @@ -286,7 +310,7 @@ function EmptyOrNotProjects({
projects,
noProjectsText,
}: {
projects: Project[];
projects: ProjectDetail[];
noProjectsText: string;
}): JSX.Element {
if (projects === undefined || projects.length === 0) {
Expand All @@ -305,10 +329,11 @@ function EmptyOrNotProjects({
{projects.slice(0, 3).map((project) => {
let timeLeft = "";
if (project.deadlines != undefined) {
const deadlineDate = getNearestFutureDate(project.deadlines);
if (deadlineDate == null) {
const deadline = getNearestFutureDate(project.deadlines);
if (deadline == null) {
return <></>;
}
const deadlineDate = deadline[1];
const diffTime = Math.abs(deadlineDate.getTime() - now.getTime());
const diffHours = Math.ceil(diffTime / (1000 * 60 * 60));
const diffDays = Math.ceil(diffHours * 24);
Expand Down
38 changes: 31 additions & 7 deletions frontend/src/components/Courses/CourseUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ export interface Course {
export interface Project {
title: string;
project_id: string;
deadlines: string[][];
}

export interface ProjectDetail {
title: string;
project_id: string;
deadlines: [string, Date][];
AronBuzogany marked this conversation as resolved.
Show resolved Hide resolved
}

export const apiHost = import.meta.env.VITE_APP_API_HOST;
Expand Down Expand Up @@ -84,11 +89,9 @@ export function getIdFromLink(link: string): string {
* @param dates - Array of dates
* @returns The nearest future date
*/
export function getNearestFutureDate(dates: string[][]): Date | null {
export function getNearestFutureDate(dates: [string, Date][]): [string, Date] | null {
const now = new Date();
const futureDates = dates
.map((date) => new Date(date[1]))
.filter((date) => date > now);
const futureDates = dates.filter((date) => date[1] > now);
if (futureDates.length === 0) return null;
return futureDates.reduce((nearest, current) =>
current < nearest ? current : nearest
Expand Down Expand Up @@ -125,7 +128,28 @@ const dataLoaderCourse = async (courseId: string) => {

const dataLoaderProjects = async (courseId: string) => {
const params = new URLSearchParams({ course_id: courseId });
return fetchData(`projects`, params);
const uri = `${apiHost}/projects?${params}`;

const res = await authenticatedFetch(uri);
if (res.status !== 200) {
throw new Response("Failed to fetch data", { status: res.status });
}
const jsonResult = await res.json();
const projects: ProjectDetail[] = jsonResult.data.map(async (item: Project) => {
const projectRes = await authenticatedFetch(item.project_id);
if (projectRes.status !== 200) {
throw new Response("Failed to fetch project data", { status: projectRes.status });
}
const projectJson = await projectRes.json();
const projectData = projectJson.data;
const project: ProjectDetail = {
...item,
deadlines: projectData.deadlines.map(([description, dateString]: [string, string]) => [description, new Date(dateString)])
};
return project;
});

return Promise.all(projects);
};

const dataLoaderAdmins = async (courseId: string) => {
Expand All @@ -145,10 +169,10 @@ export const dataLoaderCourseDetail = async ({
if (!courseId) {
throw new Error("Course ID is undefined.");
}

const course = await dataLoaderCourse(courseId);
const projects = await dataLoaderProjects(courseId);
const admins = await dataLoaderAdmins(courseId);
const students = await dataLoaderStudents(courseId);

return { course, projects, admins, students };
};
Loading