114 lines
3.8 KiB
TypeScript
114 lines
3.8 KiB
TypeScript
import {Session} from "@/hooks/useSessions";
|
|
import useExamStore from "@/stores/examStore";
|
|
import {sortByModuleName} from "@/utils/moduleUtils";
|
|
import axios from "axios";
|
|
import clsx from "clsx";
|
|
import {capitalize} from "lodash";
|
|
import moment from "moment";
|
|
import {useState} from "react";
|
|
import {BsArrowRepeat, BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs";
|
|
import {toast} from "react-toastify";
|
|
|
|
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);
|
|
|
|
const deleteSession = async () => {
|
|
if (!confirm("Are you sure you want to delete this session?")) return;
|
|
|
|
setIsLoading(true);
|
|
await axios
|
|
.delete(`/api/sessions/${session.sessionId}`)
|
|
.then(() => {
|
|
toast.success(`Successfully delete session "${session.sessionId}"`);
|
|
})
|
|
.catch((e) => {
|
|
console.log(e);
|
|
toast.error("Something went wrong, please try again later");
|
|
})
|
|
.finally(() => {
|
|
reload();
|
|
setIsLoading(false);
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="border-mti-gray-anti-flash flex w-64 flex-col justify-between gap-3 rounded-xl border p-4 text-black">
|
|
<div className="flex flex-col gap-3">
|
|
<span className="flex gap-1">
|
|
<b>ID:</b>
|
|
{session.sessionId}
|
|
</span>
|
|
<span className="flex gap-1">
|
|
<b>Date:</b>
|
|
{moment(session.date).format("DD/MM/YYYY - HH:mm")}
|
|
</span>
|
|
{session.assignment && (
|
|
<span className="flex flex-col gap-0">
|
|
<b>Assignment:</b>
|
|
{session.assignment.name}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<div className="flex flex-col gap-3">
|
|
<div className="flex w-full items-center justify-between">
|
|
<div className="-md:mt-2 grid w-full grid-cols-4 place-items-center justify-center gap-2">
|
|
{session.selectedModules.sort(sortByModuleName).map((module) => (
|
|
<div
|
|
key={module}
|
|
data-tip={capitalize(module)}
|
|
className={clsx(
|
|
"-md:px-4 tooltip flex w-fit items-center gap-2 rounded-xl py-2 text-white md:px-2 xl:px-4",
|
|
module === "reading" && "bg-ielts-reading",
|
|
module === "listening" && "bg-ielts-listening",
|
|
module === "writing" && "bg-ielts-writing",
|
|
module === "speaking" && "bg-ielts-speaking",
|
|
module === "level" && "bg-ielts-level",
|
|
)}>
|
|
{module === "reading" && <BsBook className="h-4 w-4" />}
|
|
{module === "listening" && <BsHeadphones className="h-4 w-4" />}
|
|
{module === "writing" && <BsPen className="h-4 w-4" />}
|
|
{module === "speaking" && <BsMegaphone className="h-4 w-4" />}
|
|
{module === "level" && <BsClipboard className="h-4 w-4" />}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-2 w-full">
|
|
<button
|
|
onClick={async () => await loadSession(session)}
|
|
disabled={isLoading}
|
|
className="bg-mti-green-ultralight w-full hover:bg-mti-green-light rounded-lg p-2 px-4 transition duration-300 ease-in-out hover:text-white disabled:cursor-not-allowed">
|
|
{!isLoading && "Resume"}
|
|
{isLoading && (
|
|
<div className="flex items-center justify-center">
|
|
<BsArrowRepeat className="animate-spin text-white" size={25} />
|
|
</div>
|
|
)}
|
|
</button>
|
|
<button
|
|
onClick={deleteSession}
|
|
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 && (
|
|
<div className="flex items-center justify-center">
|
|
<BsArrowRepeat className="animate-spin text-white" size={25} />
|
|
</div>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|