Merged develop into feature/ExamGenRework
This commit is contained in:
99
src/components/High/AssignmentCard.tsx
Normal file
99
src/components/High/AssignmentCard.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Session } from "@/hooks/useSessions";
|
||||
import { Assignment } from "@/interfaces/results";
|
||||
import { User } from "@/interfaces/user";
|
||||
import { sortByModuleName } from "@/utils/moduleUtils";
|
||||
import clsx from "clsx";
|
||||
import moment from "moment";
|
||||
import { useRouter } from "next/router";
|
||||
import Button from "../Low/Button";
|
||||
import ModuleBadge from "../ModuleBadge";
|
||||
|
||||
interface Props {
|
||||
assignment: Assignment
|
||||
user: User
|
||||
session?: Session
|
||||
startAssignment: (assignment: Assignment) => void
|
||||
resumeAssignment: (session: Session) => void
|
||||
}
|
||||
|
||||
export default function AssignmentCard({ user, assignment, session, startAssignment, resumeAssignment }: Props) {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"border-mti-gray-anti-flash flex min-w-[350px] flex-col gap-6 rounded-xl border p-4",
|
||||
assignment.results.map((r) => r.user).includes(user.id) && "border-mti-green-light",
|
||||
)}
|
||||
key={assignment.id}>
|
||||
<div className="flex flex-col gap-1">
|
||||
<h3 className="text-mti-black/90 text-xl font-semibold">{assignment.name}</h3>
|
||||
<span className="flex justify-between gap-1 text-lg">
|
||||
<span>{moment(assignment.startDate).format("DD/MM/YY, HH:mm")}</span>
|
||||
<span>-</span>
|
||||
<span>{moment(assignment.endDate).format("DD/MM/YY, HH:mm")}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="-md:mt-2 grid w-fit min-w-[140px] grid-cols-2 grid-rows-2 place-items-center justify-between gap-4">
|
||||
{assignment.exams
|
||||
.filter((e) => e.assignee === user.id)
|
||||
.map((e) => e.module)
|
||||
.sort(sortByModuleName)
|
||||
.map((module) => (
|
||||
<ModuleBadge className="scale-110 w-full" key={module} module={module} />
|
||||
))}
|
||||
</div>
|
||||
{!assignment.results.map((r) => r.user).includes(user.id) && (
|
||||
<>
|
||||
<div
|
||||
className="tooltip flex h-full w-full items-center justify-end pl-8 md:hidden"
|
||||
data-tip="Your screen size is too small to perform an assignment">
|
||||
<Button className="h-full w-full !rounded-xl" variant="outline">
|
||||
Start
|
||||
</Button>
|
||||
</div>
|
||||
{!session && (
|
||||
<div
|
||||
data-tip="You have already started this assignment!"
|
||||
className={clsx(
|
||||
"-md:hidden h-full w-full max-w-[50%] cursor-pointer",
|
||||
!!session && "tooltip",
|
||||
)}>
|
||||
<Button
|
||||
className={clsx("w-full h-full !rounded-xl")}
|
||||
onClick={() => startAssignment(assignment)}
|
||||
variant="outline">
|
||||
Start
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{!!session && (
|
||||
<div
|
||||
className={clsx(
|
||||
"-md:hidden h-full w-full max-w-[50%] cursor-pointer"
|
||||
)}>
|
||||
<Button
|
||||
className={clsx("w-full h-full !rounded-xl")}
|
||||
onClick={() => resumeAssignment(session)}
|
||||
color="green"
|
||||
variant="outline">
|
||||
Resume
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{assignment.results.map((r) => r.user).includes(user.id) && (
|
||||
<Button
|
||||
onClick={() => router.push("/record")}
|
||||
color="green"
|
||||
className="-md:hidden h-full w-full max-w-[50%] !rounded-xl"
|
||||
variant="outline">
|
||||
Submitted
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -13,10 +13,12 @@ export default function SessionCard({
|
||||
session,
|
||||
reload,
|
||||
loadSession,
|
||||
disableDelete = false
|
||||
}: {
|
||||
session: Session;
|
||||
reload: () => void;
|
||||
loadSession: (session: Session) => Promise<void>;
|
||||
disableDelete?: boolean
|
||||
}) {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
@@ -95,7 +97,7 @@ export default function SessionCard({
|
||||
</button>
|
||||
<button
|
||||
onClick={deleteSession}
|
||||
disabled={isLoading}
|
||||
disabled={isLoading || disableDelete}
|
||||
className="bg-mti-red-ultralight w-full hover:bg-mti-red-light rounded-lg p-2 px-4 transition duration-300 ease-in-out hover:text-white disabled:cursor-not-allowed">
|
||||
{!isLoading && "Delete"}
|
||||
{isLoading && (
|
||||
|
||||
@@ -189,10 +189,7 @@ const StatsGridItem: React.FC<StatsGridItemProps> = ({
|
||||
};
|
||||
|
||||
const shouldRenderPDFIcon = () => {
|
||||
if (assignment) {
|
||||
return assignment.released;
|
||||
}
|
||||
|
||||
if (assignment) return assignment.released;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,10 +14,11 @@ interface Props {
|
||||
label: string;
|
||||
tooltip?: string;
|
||||
}[];
|
||||
removeLevel?: boolean
|
||||
children?: ReactElement;
|
||||
}
|
||||
|
||||
export default function ProfileSummary({user, items}: Props) {
|
||||
export default function ProfileSummary({user, items, removeLevel = false}: Props) {
|
||||
return (
|
||||
<section className="w-full flex -md:flex-col gap-4 md:gap-8">
|
||||
<img
|
||||
@@ -30,21 +31,29 @@ export default function ProfileSummary({user, items}: Props) {
|
||||
<div className="flex -md:flex-col justify-between w-full gap-8">
|
||||
<div className="flex flex-col gap-2 py-2">
|
||||
<h1 className="font-bold text-2xl md:text-4xl">{user.name}</h1>
|
||||
<h6 className="font-normal text-base text-mti-gray-taupe">{USER_TYPE_LABELS[user.type]}</h6>
|
||||
<div className="flex items-center gap-2">
|
||||
<h6 className="font-normal text-base text-mti-gray-taupe">{user.email}</h6>
|
||||
<span> - </span>
|
||||
<h6 className="font-normal text-base text-mti-gray-taupe">{USER_TYPE_LABELS[user.type]}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<ProgressBar
|
||||
label={`Level ${calculateAverageLevel(user.levels).toFixed(1)}`}
|
||||
percentage={100}
|
||||
color="purple"
|
||||
className="max-w-xs w-32 md:self-end h-10 -md:hidden"
|
||||
/>
|
||||
{!removeLevel && (
|
||||
<ProgressBar
|
||||
label={`Level ${calculateAverageLevel(user.levels).toFixed(1)}`}
|
||||
percentage={100}
|
||||
color="purple"
|
||||
className="max-w-xs w-32 md:self-end h-10 -md:hidden"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<ProgressBar
|
||||
label=""
|
||||
percentage={Math.round((calculateAverageLevel(user.levels) * 100) / calculateAverageLevel(user.desiredLevels))}
|
||||
color="red"
|
||||
className="w-full h-3 drop-shadow-lg -md:hidden"
|
||||
/>
|
||||
{!removeLevel && (
|
||||
<ProgressBar
|
||||
label=""
|
||||
percentage={Math.round((calculateAverageLevel(user.levels) * 100) / calculateAverageLevel(user.desiredLevels))}
|
||||
color="red"
|
||||
className="w-full h-3 drop-shadow-lg -md:hidden"
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between w-full mt-8 -md:hidden">
|
||||
{items.map((item) => (
|
||||
|
||||
Reference in New Issue
Block a user