Exam generation rework, batch user tables, fastapi endpoint switch
This commit is contained in:
129
src/components/ExamEditor/Exercises/Blanks/DragNDrop.tsx
Normal file
129
src/components/ExamEditor/Exercises/Blanks/DragNDrop.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import { useDraggable, useDroppable } from "@dnd-kit/core";
|
||||
import clsx from "clsx";
|
||||
import { MdClose, MdDelete, MdDragIndicator } from "react-icons/md";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { useEffect, useState } from "react";
|
||||
import ConfirmDeleteBtn from "../../Shared/ConfirmDeleteBtn";
|
||||
|
||||
interface BlankProps {
|
||||
id: number;
|
||||
module: string;
|
||||
variant: "text" | "bank";
|
||||
isSelected?: boolean;
|
||||
isDragging?: boolean;
|
||||
onSelect?: (id: number) => void;
|
||||
onRemove?: (id: number) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export const Blank: React.FC<BlankProps> = ({
|
||||
id,
|
||||
module,
|
||||
variant,
|
||||
isSelected,
|
||||
isDragging,
|
||||
onSelect,
|
||||
onRemove,
|
||||
disabled,
|
||||
}) => {
|
||||
const { attributes, listeners, setNodeRef, transform } = useDraggable({
|
||||
id: `${variant}-blank-${id}`,
|
||||
disabled: disabled || variant !== "text",
|
||||
});
|
||||
|
||||
const style = transform ? {
|
||||
transform: CSS.Translate.toString(transform),
|
||||
transition: 'none',
|
||||
zIndex: 999,
|
||||
position: 'relative' as const,
|
||||
touchAction: 'none',
|
||||
} : {
|
||||
transition: 'transform 0.2s cubic-bezier(0.25, 1, 0.5, 1)',
|
||||
touchAction: 'none',
|
||||
position: 'relative' as const,
|
||||
};
|
||||
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
if (variant === "bank" && !disabled && onSelect) {
|
||||
onSelect(id);
|
||||
}
|
||||
};
|
||||
|
||||
const dragProps = variant === "text" ? {
|
||||
...attributes,
|
||||
...listeners,
|
||||
} : {};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
className={clsx(
|
||||
"group relative inline-flex items-center gap-2 px-2 py-1.5 rounded-lg select-none",
|
||||
"transform-gpu transition-colors duration-150",
|
||||
"hover:ring-2 hover:ring-offset-1 shadow-sm",
|
||||
(
|
||||
isSelected ? (
|
||||
isDragging ?
|
||||
`bg-ielts-${module}/20 bg-ielts-${module} hover:ring-ielts-${module}/50` :
|
||||
`bg-ielts-${module}/20 bg-ielts-${module}/80 hover:ring-ielts-${module}/40`
|
||||
)
|
||||
: `bg-ielts-${module}/20 bg-ielts-${module} hover:ring-ielts-${module}/50`
|
||||
),
|
||||
!disabled && (variant === "text" ? "cursor-grab active:cursor-grabbing" : "cursor-pointer"),
|
||||
disabled && "cursor-default",
|
||||
variant === "bank" && "w-12"
|
||||
)}
|
||||
onClick={variant === "bank" ? handleClick : undefined}
|
||||
{...dragProps}
|
||||
role="button"
|
||||
>
|
||||
{variant === "text" && (
|
||||
<span
|
||||
className={clsx(
|
||||
"text-xl p-1.5 -ml-1 rounded-md",
|
||||
"transition-colors duration-150"
|
||||
)}
|
||||
title="Drag to reorder"
|
||||
>
|
||||
{isSelected ?
|
||||
<MdDragIndicator className="transform scale-125" color="white" /> :
|
||||
<MdDragIndicator className="transform scale-125" color="#898492" />
|
||||
}
|
||||
</span>
|
||||
)}
|
||||
<span className={clsx(
|
||||
"font-semibold px-1 text-mti-gray-taupe",
|
||||
isSelected && !isDragging && "text-white"
|
||||
)}>
|
||||
{id}
|
||||
</span>
|
||||
|
||||
{onRemove && !isDragging && (
|
||||
<ConfirmDeleteBtn
|
||||
onDelete={() => onRemove(id)}
|
||||
size="md"
|
||||
position="top-right"
|
||||
className="-translate-y-2 translate-x-1.5"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const DropZone: React.FC<{ index: number, module: string; }> = ({ index, module }) => {
|
||||
const { setNodeRef, isOver } = useDroppable({
|
||||
id: `drop-${index}`,
|
||||
});
|
||||
|
||||
return (
|
||||
<span
|
||||
ref={setNodeRef}
|
||||
className={clsx(
|
||||
"inline-block h-6 w-4 mx-px transition-all duration-200 select-none",
|
||||
isOver ? `bg-ielts-${module}/20 w-4.5` : `bg-transparent hover:bg-ielts-${module}/20`
|
||||
)}
|
||||
role="presentation"
|
||||
/>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user