import Layout from "@/components/High/Layout"; import Button from "@/components/Low/Button"; import Checkbox from "@/components/Low/Checkbox"; import Input from "@/components/Low/Input"; 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 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 { requestUser } from "@/utils/api"; import {getEntitiesWithRoles} from "@/utils/entities.be"; import {getGroups, getGroupsByEntities} from "@/utils/groups.be"; import {checkAccess} 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 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 ReactDatePicker from "react-datepicker"; 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}) => { const user = await requestUser(req, res) if (!user) return redirect("/login") if (!checkAccess(user, ["admin", "developer", "corporate", "teacher", "mastercorporate"])) return redirect("/") const entityIDS = mapBy(user.entities, "id") || []; const users = await (checkAccess(user, ["developer", "admin"]) ? getUsers() : getEntitiesUsers(entityIDS)); const entities = await (checkAccess(user, ["developer", "admin"]) ? getEntitiesWithRoles() : getEntitiesWithRoles(entityIDS)); const groups = await (checkAccess(user, ["developer", "admin"]) ? getGroups() : getGroupsByEntities(entityIDS)); return {props: serialize({user, users, entities, groups})}; }, sessionOptions); interface Props { assignment: Assignment; groups: Group[]; user: User; users: User[]; entities: EntityWithRoles[]; } const SIZE = 9; export default function AssignmentsPage({user, users, groups, entities}: Props) { const [selectedModules, setSelectedModules] = useState([]); const [assignees, setAssignees] = useState([]); const [teachers, setTeachers] = useState([...(user.type === "teacher" ? [user.id] : [])]); const [entity, setEntity] = useState(entities[0]?.id); const [name, setName] = useState( generate({ minLength: 6, maxLength: 8, min: 2, max: 3, join: " ", formatter: capitalize, }), ); const [isLoading, setIsLoading] = useState(false); const [startDate, setStartDate] = useState(moment().add(1, "hour").toDate()); const [endDate, setEndDate] = useState(moment().hours(23).minutes(59).add(8, "day").toDate()); const [variant, setVariant] = useState("full"); const [instructorGender, setInstructorGender] = useState("varied"); const [generateMultiple, setGenerateMultiple] = useState(false); const [released, setReleased] = useState(false); const [autoStart, setAutostart] = useState(false); const [autoStartDate, setAutoStartDate] = useState(new Date()); const [useRandomExams, setUseRandomExams] = useState(true); const [examIDs, setExamIDs] = useState<{id: string; module: Module}[]>([]); const {exams} = useExams(); const router = useRouter(); const classrooms = useMemo(() => groups.filter((e) => e.entity === entity), [entity, groups]); 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 {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))); }, [selectedModules]); useEffect(() => { setAssignees([]); setTeachers([]); }, [entity]); const toggleModule = (module: Module) => { const modules = selectedModules.filter((x) => x !== module); setSelectedModules((prev) => (prev.includes(module) ? modules : [...modules, module])); }; const toggleAssignee = (user: User) => { setAssignees((prev) => (prev.includes(user.id) ? prev.filter((a) => a !== user.id) : [...prev, user.id])); }; const toggleTeacher = (user: User) => { setTeachers((prev) => (prev.includes(user.id) ? prev.filter((a) => a !== user.id) : [...prev, user.id])); }; const createAssignment = () => { setIsLoading(true); axios .post(`/api/assignments`, { assignees, name, startDate, examIDs: !useRandomExams ? examIDs : undefined, endDate, selectedModules, generateMultiple, entity, teachers, variant, instructorGender, released, autoStart, autoStartDate, }) .then((result) => { toast.success(`The assignment "${name}" has been created successfully!`); router.push(`/assignments/${result.data.id}`); }) .catch((e) => { console.log(e); toast.error("Something went wrong, please try again later!"); }) .finally(() => setIsLoading(false)); }; return ( <> Create Assignment | EnCoach

Create Assignment

toggleModule("reading") : undefined} className={clsx( "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", selectedModules.includes("reading") ? "border-mti-purple-light" : "border-mti-gray-platinum", )}>
Reading {!selectedModules.includes("reading") && !selectedModules.includes("level") && (
)} {selectedModules.includes("level") && } {selectedModules.includes("reading") && }
toggleModule("listening") : undefined} className={clsx( "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", selectedModules.includes("listening") ? "border-mti-purple-light" : "border-mti-gray-platinum", )}>
Listening {!selectedModules.includes("listening") && !selectedModules.includes("level") && (
)} {selectedModules.includes("level") && } {selectedModules.includes("listening") && }
toggleModule("level") : undefined } className={clsx( "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", selectedModules.includes("level") ? "border-mti-purple-light" : "border-mti-gray-platinum", )}>
Level {!selectedModules.includes("level") && selectedModules.length === 0 && (
)} {!selectedModules.includes("level") && selectedModules.length > 0 && } {selectedModules.includes("level") && }
toggleModule("writing") : undefined} className={clsx( "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", selectedModules.includes("writing") ? "border-mti-purple-light" : "border-mti-gray-platinum", )}>
Writing {!selectedModules.includes("writing") && !selectedModules.includes("level") && (
)} {selectedModules.includes("level") && } {selectedModules.includes("writing") && }
toggleModule("speaking") : undefined} className={clsx( "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", selectedModules.includes("speaking") ? "border-mti-purple-light" : "border-mti-gray-platinum", )}>
Speaking {!selectedModules.includes("speaking") && !selectedModules.includes("level") && (
)} {selectedModules.includes("level") && } {selectedModules.includes("speaking") && }
setName(e)} defaultValue={name} label="Assignment Name" required /> (value ? setInstructorGender(value.value as InstructorGender) : null)} disabled={!selectedModules.includes("speaking")} options={[ {value: "male", label: "Male"}, {value: "female", label: "Female"}, {value: "varied", label: "Varied"}, ]} />
)} {selectedModules.length > 0 && (
Random Exams {!useRandomExams && (
{selectedModules.map((module) => (