diff --git a/src/components/High/AssignmentCard.tsx b/src/components/High/AssignmentCard.tsx
index d7427e5f..49812254 100644
--- a/src/components/High/AssignmentCard.tsx
+++ b/src/components/High/AssignmentCard.tsx
@@ -1,6 +1,7 @@
import { Session } from "@/hooks/useSessions";
import { Assignment } from "@/interfaces/results";
import { User } from "@/interfaces/user";
+import { activeAssignmentFilter, futureAssignmentFilter } from "@/utils/assignments";
import { sortByModuleName } from "@/utils/moduleUtils";
import clsx from "clsx";
import moment from "moment";
@@ -44,7 +45,16 @@ export default function AssignmentCard({ user, assignment, session, startAssignm
))}
- {!assignment.results.map((r) => r.user).includes(user.id) && (
+ {futureAssignmentFilter(assignment) && (
+
+ )}
+ {activeAssignmentFilter(assignment) && !assignment.results.map((r) => r.user).includes(user.id) && (
<>
Submitted
diff --git a/src/dashboards/AssignmentCreator.tsx b/src/dashboards/AssignmentCreator.tsx
index c3bdd792..89c58598 100644
--- a/src/dashboards/AssignmentCreator.tsx
+++ b/src/dashboards/AssignmentCreator.tsx
@@ -1,27 +1,27 @@
import Input from "@/components/Low/Input";
import Modal from "@/components/Modal";
-import {Module} from "@/interfaces";
+import { Module } from "@/interfaces";
import clsx from "clsx";
-import {useEffect, useMemo, useState} from "react";
-import {BsBook, BsCheckCircle, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle} from "react-icons/bs";
-import {generate} from "random-words";
-import {capitalize} from "lodash";
+import { useEffect, useMemo, useState } from "react";
+import { BsBook, BsCheckCircle, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle } from "react-icons/bs";
+import { generate } from "random-words";
+import { capitalize } from "lodash";
import useUsers from "@/hooks/useUsers";
-import {Group, User} from "@/interfaces/user";
+import { Group, User } from "@/interfaces/user";
import ProgressBar from "@/components/Low/ProgressBar";
-import {calculateAverageLevel} from "@/utils/score";
+import { calculateAverageLevel } from "@/utils/score";
import Button from "@/components/Low/Button";
import ReactDatePicker from "react-datepicker";
import moment from "moment";
import axios from "axios";
-import {getExam} from "@/utils/exams";
-import {toast} from "react-toastify";
-import {Assignment} from "@/interfaces/results";
+import { getExam } from "@/utils/exams";
+import { toast } from "react-toastify";
+import { Assignment } from "@/interfaces/results";
import Checkbox from "@/components/Low/Checkbox";
-import {InstructorGender, Variant} from "@/interfaces/exam";
+import { InstructorGender, Variant } from "@/interfaces/exam";
import Select from "@/components/Low/Select";
import useExams from "@/hooks/useExams";
-import {useListSearch} from "@/hooks/useListSearch";
+import { useListSearch } from "@/hooks/useListSearch";
interface Props {
isCreating: boolean;
@@ -34,7 +34,7 @@ interface Props {
const SIZE = 12;
-export default function AssignmentCreator({isCreating, assignment, user, groups, users, cancelCreation}: Props) {
+export default function AssignmentCreator({ isCreating, assignment, user, groups, users, cancelCreation }: Props) {
const [studentsPage, setStudentsPage] = useState(0);
const [teachersPage, setTeachersPage] = useState(0);
@@ -43,14 +43,14 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
const [teachers, setTeachers] = useState(!!assignment ? assignment.teachers || [] : [...(user.type === "teacher" ? [user.id] : [])]);
const [name, setName] = useState(
assignment?.name ||
- generate({
- minLength: 6,
- maxLength: 8,
- min: 2,
- max: 3,
- join: " ",
- formatter: capitalize,
- }),
+ generate({
+ minLength: 6,
+ maxLength: 8,
+ min: 2,
+ max: 3,
+ join: " ",
+ formatter: capitalize,
+ }),
);
const [isLoading, setIsLoading] = useState(false);
const [startDate, setStartDate] = useState(assignment ? moment(assignment.startDate).toDate() : moment().add(1, "hour").toDate());
@@ -65,18 +65,17 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
const [released, setReleased] = useState(assignment?.released || false);
const [autoStart, setAutostart] = useState(assignment?.autoStart || false);
- const [autoStartDate, setAutoStartDate] = useState(assignment ? moment(assignment.autoStartDate).toDate() : new Date());
const [useRandomExams, setUseRandomExams] = useState(true);
- const [examIDs, setExamIDs] = useState<{id: string; module: Module}[]>([]);
+ const [examIDs, setExamIDs] = useState<{ id: string; module: Module }[]>([]);
- const {exams} = useExams();
+ const { exams } = useExams();
const userStudents = useMemo(() => users.filter((x) => x.type === "student"), [users]);
const userTeachers = useMemo(() => users.filter((x) => x.type === "teacher"), [users]);
- const {rows: filteredStudentsRows, renderSearch: renderStudentSearch, text: studentText} = useListSearch([["name"], ["email"]], userStudents);
- const {rows: filteredTeachersRows, renderSearch: renderTeacherSearch, text: teacherText} = useListSearch([["name"], ["email"]], userTeachers);
+ const { rows: filteredStudentsRows, renderSearch: renderStudentSearch, text: studentText } = useListSearch([["name"], ["email"]], userStudents);
+ const { rows: filteredTeachersRows, renderSearch: renderTeacherSearch, text: teacherText } = useListSearch([["name"], ["email"]], userTeachers);
useEffect(() => setStudentsPage(0), [studentText]);
const studentRows = useMemo(
@@ -131,7 +130,6 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
instructorGender,
released,
autoStart,
- autoStartDate,
})
.then(() => {
toast.success(`The assignment "${name}" has been ${assignment ? "updated" : "created"} successfully!`);
@@ -306,24 +304,6 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
onChange={(date) => setEndDate(date)}
/>
- {autoStart && (
-
-
- moment(date).isSameOrAfter(new Date())}
- dateFormat="dd/MM/yyyy HH:mm"
- selected={autoStartDate}
- showTimeSelect
- onChange={(date) => setAutoStartDate(date)}
- />
-
- )}
{selectedModules.includes("speaking") && (
@@ -337,9 +317,9 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
onChange={(value) => (value ? setInstructorGender(value.value as InstructorGender) : null)}
disabled={!selectedModules.includes("speaking") || !!assignment}
options={[
- {value: "male", label: "Male"},
- {value: "female", label: "Female"},
- {value: "varied", label: "Varied"},
+ { value: "male", label: "Male" },
+ { value: "female", label: "Female" },
+ { value: "varied", label: "Varied" },
]}
/>
@@ -362,12 +342,12 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
}}
onChange={(value) =>
value
- ? setExamIDs((prev) => [...prev.filter((x) => x.module !== module), {id: value.value!, module}])
+ ? setExamIDs((prev) => [...prev.filter((x) => x.module !== module), { id: value.value!, module }])
: setExamIDs((prev) => prev.filter((x) => x.module !== module))
}
options={exams
.filter((x) => !x.isDiagnostic && x.module === module)
- .map((x) => ({value: x.id, label: x.id}))}
+ .map((x) => ({ value: x.id, label: x.id }))}
/>
))}
@@ -394,7 +374,7 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
"transition duration-300 ease-in-out",
users.filter((u) => g.participants.includes(u.id)).every((u) => assignees.includes(u.id)) &&
- "!bg-mti-purple-light !text-white",
+ "!bg-mti-purple-light !text-white",
)}>
{g.name}
@@ -475,7 +455,7 @@ export default function AssignmentCreator({isCreating, assignment, user, groups,
"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
"transition duration-300 ease-in-out",
users.filter((u) => g.participants.includes(u.id)).every((u) => teachers.includes(u.id)) &&
- "!bg-mti-purple-light !text-white",
+ "!bg-mti-purple-light !text-white",
)}>
{g.name}
diff --git a/src/interfaces/results.ts b/src/interfaces/results.ts
index cd9ff373..58832a4f 100644
--- a/src/interfaces/results.ts
+++ b/src/interfaces/results.ts
@@ -1,8 +1,8 @@
-import {Module} from "@/interfaces";
-import {InstructorGender} from "./exam";
-import {Stat} from "./user";
+import { Module } from "@/interfaces";
+import { InstructorGender } from "./exam";
+import { Stat } from "./user";
-export type UserResults = {[key in Module]: ModuleResult};
+export type UserResults = { [key in Module]: ModuleResult };
interface ModuleResult {
exams: string[];
@@ -22,7 +22,7 @@ export interface Assignment {
assigner: string;
assignees: string[];
results: AssignmentResult[];
- exams: {id: string; module: Module; assignee: string}[];
+ exams: { id: string; module: Module; assignee: string }[];
instructorGender?: InstructorGender;
startDate: Date;
endDate: Date;
@@ -32,9 +32,8 @@ export interface Assignment {
// unless start is active, the assignment is not visible to the assignees
// start date now works as a limit time to start the exam
start?: boolean;
- autoStartDate?: Date;
autoStart?: boolean;
entity?: string;
}
-export type AssignmentWithCorporateId = Assignment & {corporateId: string};
+export type AssignmentWithCorporateId = Assignment & { corporateId: string };
diff --git a/src/pages/assignments/creator/[id].tsx b/src/pages/assignments/creator/[id].tsx
index 4f3e8bca..0f8dcdf1 100644
--- a/src/pages/assignments/creator/[id].tsx
+++ b/src/pages/assignments/creator/[id].tsx
@@ -6,43 +6,43 @@ import ProgressBar from "@/components/Low/ProgressBar";
import Select from "@/components/Low/Select";
import Separator from "@/components/Low/Separator";
import useExams from "@/hooks/useExams";
-import {useListSearch} from "@/hooks/useListSearch";
+import { useListSearch } from "@/hooks/useListSearch";
import usePagination from "@/hooks/usePagination";
-import {Module} from "@/interfaces";
-import {EntityWithRoles} from "@/interfaces/entity";
-import {InstructorGender, Variant} from "@/interfaces/exam";
-import {Assignment} from "@/interfaces/results";
-import {Group, User} from "@/interfaces/user";
-import {sessionOptions} from "@/lib/session";
-import {mapBy, redirect, serialize} from "@/utils";
+import { Module } from "@/interfaces";
+import { EntityWithRoles } from "@/interfaces/entity";
+import { InstructorGender, Variant } from "@/interfaces/exam";
+import { Assignment } from "@/interfaces/results";
+import { Group, User } from "@/interfaces/user";
+import { sessionOptions } from "@/lib/session";
+import { mapBy, redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
-import {getAssignment} from "@/utils/assignments.be";
-import {getEntitiesWithRoles} from "@/utils/entities.be";
-import {getGroups, getGroupsByEntities} from "@/utils/groups.be";
-import {checkAccess, doesEntityAllow, findAllowedEntities} from "@/utils/permissions";
-import {calculateAverageLevel} from "@/utils/score";
-import {getEntitiesUsers, getUsers} from "@/utils/users.be";
+import { getAssignment } from "@/utils/assignments.be";
+import { getEntitiesWithRoles } from "@/utils/entities.be";
+import { getGroups, getGroupsByEntities } from "@/utils/groups.be";
+import { checkAccess, doesEntityAllow, findAllowedEntities } from "@/utils/permissions";
+import { calculateAverageLevel } from "@/utils/score";
+import { getEntitiesUsers, getUsers } from "@/utils/users.be";
import axios from "axios";
import clsx from "clsx";
-import {withIronSessionSsr} from "iron-session/next";
-import {capitalize} from "lodash";
+import { withIronSessionSsr } from "iron-session/next";
+import { capitalize } from "lodash";
import moment from "moment";
import Head from "next/head";
import Link from "next/link";
-import {useRouter} from "next/router";
-import {generate} from "random-words";
-import {useEffect, useMemo, useState} from "react";
+import { useRouter } from "next/router";
+import { generate } from "random-words";
+import { useEffect, useMemo, useState } from "react";
import ReactDatePicker from "react-datepicker";
-import {BsBook, BsCheckCircle, BsChevronLeft, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle} from "react-icons/bs";
-import {toast} from "react-toastify";
+import { BsBook, BsCheckCircle, BsChevronLeft, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle } from "react-icons/bs";
+import { toast } from "react-toastify";
-export const getServerSideProps = withIronSessionSsr(async ({req, res, params}) => {
+export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }) => {
const user = await requestUser(req, res)
if (!user) return redirect("/login")
res.setHeader("Cache-Control", "public, s-maxage=10, stale-while-revalidate=59");
- const {id} = params as {id: string};
+ const { id } = params as { id: string };
const entityIDS = mapBy(user.entities, "id") || [];
const assignment = await getAssignment(id);
@@ -59,7 +59,7 @@ export const getServerSideProps = withIronSessionSsr(async ({req, res, params})
const users = await (checkAccess(user, ["developer", "admin"]) ? getUsers() : getEntitiesUsers(mapBy(allowedEntities, 'id')));
const groups = await (checkAccess(user, ["developer", "admin"]) ? getGroups() : getGroupsByEntities(mapBy(allowedEntities, 'id')));
- return {props: serialize({user, users, entities: allowedEntities, assignment, groups})};
+ return { props: serialize({ user, users, entities: allowedEntities, assignment, groups }) };
}, sessionOptions);
interface Props {
@@ -72,7 +72,7 @@ interface Props {
const SIZE = 9;
-export default function AssignmentsPage({assignment, user, users, entities, groups}: Props) {
+export default function AssignmentsPage({ assignment, user, users, entities, groups }: Props) {
const [selectedModules, setSelectedModules] = useState(assignment.exams.map((e) => e.module));
const [assignees, setAssignees] = useState(assignment.assignees);
const [teachers, setTeachers] = useState(assignment.teachers || []);
@@ -90,12 +90,11 @@ export default function AssignmentsPage({assignment, user, users, entities, grou
const [released, setReleased] = useState(assignment.released || false);
const [autoStart, setAutostart] = useState(assignment.autoStart || false);
- const [autoStartDate, setAutoStartDate] = useState(moment(assignment.autoStartDate).toDate());
const [useRandomExams, setUseRandomExams] = useState(true);
- const [examIDs, setExamIDs] = useState<{id: string; module: Module}[]>([]);
+ const [examIDs, setExamIDs] = useState<{ id: string; module: Module }[]>([]);
- const {exams} = useExams();
+ const { exams } = useExams();
const router = useRouter();
const classrooms = useMemo(() => groups.filter((e) => e.entity === entity), [entity, groups]);
@@ -103,11 +102,11 @@ export default function AssignmentsPage({assignment, user, users, entities, grou
const userStudents = useMemo(() => users.filter((x) => x.type === "student"), [users]);
const userTeachers = useMemo(() => users.filter((x) => x.type === "teacher"), [users]);
- const {rows: filteredStudentsRows, renderSearch: renderStudentSearch} = useListSearch([["name"], ["email"]], userStudents);
- const {rows: filteredTeachersRows, renderSearch: renderTeacherSearch} = useListSearch([["name"], ["email"]], userTeachers);
+ const { rows: filteredStudentsRows, renderSearch: renderStudentSearch } = useListSearch([["name"], ["email"]], userStudents);
+ const { rows: filteredTeachersRows, renderSearch: renderTeacherSearch } = useListSearch([["name"], ["email"]], userTeachers);
- const {items: studentRows, renderMinimal: renderStudentPagination} = usePagination(filteredStudentsRows, SIZE);
- const {items: teacherRows, renderMinimal: renderTeacherPagination} = usePagination(filteredTeachersRows, SIZE);
+ const { items: studentRows, renderMinimal: renderStudentPagination } = usePagination(filteredStudentsRows, SIZE);
+ const { items: teacherRows, renderMinimal: renderTeacherPagination } = usePagination(filteredTeachersRows, SIZE);
useEffect(() => {
setExamIDs((prev) => prev.filter((x) => selectedModules.includes(x.module)));
@@ -148,7 +147,6 @@ export default function AssignmentsPage({assignment, user, users, entities, grou
instructorGender,
released,
autoStart,
- autoStartDate,
})
.then(() => {
toast.success(`The assignment "${name}" has been updated successfully!`);
@@ -316,9 +314,9 @@ export default function AssignmentsPage({assignment, user, users, entities, grou
setName(e)} defaultValue={name} label="Assignment Name" required />