Merged develop into feature/ExamGenRework
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useListSearch } from "@/hooks/useListSearch"
|
||||
import { ColumnDef, flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, PaginationState, useReactTable } from "@tanstack/react-table"
|
||||
import clsx from "clsx"
|
||||
import { useState } from "react"
|
||||
import { useEffect, useState } from "react"
|
||||
import { BsArrowDown, BsArrowUp } from "react-icons/bs"
|
||||
import Button from "../Low/Button"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import clsx from "clsx";
|
||||
import {ComponentProps, useEffect, useState} from "react";
|
||||
import ReactSelect, {GroupBase, StylesConfig} from "react-select";
|
||||
import { ComponentProps, useEffect, useState } from "react";
|
||||
import ReactSelect, { GroupBase, StylesConfig } from "react-select";
|
||||
import Option from "@/interfaces/option";
|
||||
|
||||
interface Props {
|
||||
@@ -9,14 +9,23 @@ interface Props {
|
||||
options: Option[];
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
onChange: (value: Option | null) => void;
|
||||
isClearable?: boolean;
|
||||
styles?: StylesConfig<Option, boolean, GroupBase<Option>>;
|
||||
className?: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export default function Select({value, defaultValue, options, placeholder, disabled, onChange, styles, isClearable, label, className}: Props) {
|
||||
interface MultiProps {
|
||||
isMulti: true
|
||||
onChange: (value: Option[] | null) => void
|
||||
}
|
||||
|
||||
interface SingleProps {
|
||||
isMulti?: false
|
||||
onChange: (value: Option | null) => void
|
||||
}
|
||||
|
||||
export default function Select({ value, isMulti, defaultValue, options, placeholder, disabled, onChange, styles, isClearable, label, className }: Props & (MultiProps | SingleProps)) {
|
||||
const [target, setTarget] = useState<HTMLElement>();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -27,14 +36,15 @@ export default function Select({value, defaultValue, options, placeholder, disab
|
||||
<div className="w-full flex flex-col gap-3">
|
||||
{label && <label className="font-normal text-base text-mti-gray-dim">{label}</label>}
|
||||
<ReactSelect
|
||||
isMulti={isMulti}
|
||||
className={
|
||||
styles
|
||||
? undefined
|
||||
: clsx(
|
||||
"placeholder:text-mti-gray-cool border-mti-gray-platinum w-full rounded-full border bg-white px-4 py-4 text-sm font-normal focus:outline-none",
|
||||
disabled && "!bg-mti-gray-platinum/40 !text-mti-gray-dim cursor-not-allowed",
|
||||
className,
|
||||
)
|
||||
"placeholder:text-mti-gray-cool border-mti-gray-platinum w-full rounded-full border bg-white px-4 py-4 text-sm font-normal focus:outline-none",
|
||||
disabled && "!bg-mti-gray-platinum/40 !text-mti-gray-dim cursor-not-allowed",
|
||||
className,
|
||||
)
|
||||
}
|
||||
options={options}
|
||||
value={value}
|
||||
@@ -44,7 +54,7 @@ export default function Select({value, defaultValue, options, placeholder, disab
|
||||
defaultValue={defaultValue}
|
||||
styles={
|
||||
styles || {
|
||||
menuPortal: (base) => ({...base, zIndex: 9999}),
|
||||
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
|
||||
control: (styles) => ({
|
||||
...styles,
|
||||
paddingLeft: "4px",
|
||||
|
||||
@@ -260,9 +260,13 @@ const StatsGridItem: React.FC<StatsGridItemProps> = ({
|
||||
|
||||
<div className="w-full flex flex-col gap-1">
|
||||
<div className={clsx("grid grid-cols-4 gap-2 place-items-start w-full -md:mt-2", examNumber !== undefined && "pr-10")}>
|
||||
{!!assignment &&
|
||||
(assignment.released || assignment.released === undefined) &&
|
||||
aggregatedLevels.map(({ module, level }) => <ModuleBadge key={module} module={module} level={level} />)}
|
||||
{aggregatedLevels.map(({ module, level }) =>
|
||||
<ModuleBadge
|
||||
key={module}
|
||||
module={module}
|
||||
level={(!!assignment && (assignment.released || assignment.released === undefined)) || !assignment ? level : undefined}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{assignment && (
|
||||
|
||||
26
src/components/PracticeModal.tsx
Normal file
26
src/components/PracticeModal.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useState } from "react";
|
||||
import Button from "./Low/Button";
|
||||
import Modal from "./Modal";
|
||||
|
||||
interface Props {
|
||||
open?: boolean
|
||||
}
|
||||
|
||||
export default function PracticeModal({ open }: Props) {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(open || false)
|
||||
|
||||
return (
|
||||
<Modal title="Practice Questions" isOpen={isOpen} onClose={() => setIsOpen(false)}>
|
||||
<div className="py-4 flex flex-col gap-4 items-center">
|
||||
<span className="w-full">
|
||||
To acquaint yourself with the question types in this section, please respond to the practice questions provided.
|
||||
<br />
|
||||
<b>Do note that these questions are for practice purposes only and are not graded.</b>
|
||||
<br />
|
||||
You may choose to skip them if you prefer.
|
||||
</span>
|
||||
<Button onClick={() => setIsOpen(false)} className="w-full max-w-[200px]">Understood</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
@@ -171,16 +171,17 @@ export default function Sidebar({
|
||||
badge={totalAssignedTickets}
|
||||
/>
|
||||
)}
|
||||
{(entitiesAllowGeneration.length > 0 || isAdmin) && (
|
||||
<Nav
|
||||
disabled={disableNavigation}
|
||||
Icon={BsCloudFill}
|
||||
label="Generation"
|
||||
path={path}
|
||||
keyPath="/generation"
|
||||
isMinimized={isMinimized}
|
||||
/>
|
||||
)}
|
||||
{checkAccess(user, ["admin", "developer", "teacher", 'corporate', 'mastercorporate'])
|
||||
&& (entitiesAllowGeneration.length > 0 || isAdmin) && (
|
||||
<Nav
|
||||
disabled={disableNavigation}
|
||||
Icon={BsCloudFill}
|
||||
label="Generation"
|
||||
path={path}
|
||||
keyPath="/generation"
|
||||
isMinimized={isMinimized}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="-xl:flex flex-col gap-3 xl:hidden">
|
||||
<Nav disabled={disableNavigation} Icon={MdSpaceDashboard} label="Dashboard" path={path} keyPath="/" isMinimized />
|
||||
|
||||
@@ -19,7 +19,6 @@ import Select from "react-select";
|
||||
import useUsers from "@/hooks/useUsers";
|
||||
import { USER_TYPE_LABELS } from "@/resources/user";
|
||||
import { CURRENCIES } from "@/resources/paypal";
|
||||
import useCodes from "@/hooks/useCodes";
|
||||
import { checkAccess, getTypesOfUser } from "@/utils/permissions";
|
||||
import { PERMISSIONS } from "@/constants/userPermissions";
|
||||
import { PermissionType } from "@/interfaces/permissions";
|
||||
@@ -119,7 +118,6 @@ const UserCard = ({
|
||||
);
|
||||
const { data: stats } = useFilterRecordsByUser<Stat[]>(user.id);
|
||||
const { users } = useUsers();
|
||||
const { codes } = useCodes(user.id);
|
||||
const { permissions } = usePermissions(loggedInUser.id);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user