Exam generation rework, batch user tables, fastapi endpoint switch
This commit is contained in:
118
src/components/ExamEditor/Shared/ConfirmDeleteBtn.tsx
Normal file
118
src/components/ExamEditor/Shared/ConfirmDeleteBtn.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { MdClose, MdDelete } from 'react-icons/md';
|
||||
import clsx from 'clsx';
|
||||
|
||||
interface ConfirmDeleteBtnProps {
|
||||
onDelete: () => void;
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ConfirmDeleteBtn: React.FC<ConfirmDeleteBtnProps> = ({
|
||||
onDelete,
|
||||
size = 'sm',
|
||||
position = 'top-right',
|
||||
className
|
||||
}) => {
|
||||
const [showConfirm, setShowConfirm] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = () => setShowConfirm(false);
|
||||
if (showConfirm) {
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
return () => document.removeEventListener('click', handleClickOutside);
|
||||
}
|
||||
}, [showConfirm]);
|
||||
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setShowConfirm(true);
|
||||
};
|
||||
|
||||
const handleConfirm = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
onDelete();
|
||||
setShowConfirm(false);
|
||||
};
|
||||
|
||||
const handleCancel = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setShowConfirm(false);
|
||||
};
|
||||
|
||||
const sizeClasses = {
|
||||
sm: 'p-0.5',
|
||||
md: 'p-1',
|
||||
lg: 'p-1.5'
|
||||
};
|
||||
|
||||
const iconSizes = {
|
||||
sm: 14,
|
||||
md: 16,
|
||||
lg: 18
|
||||
};
|
||||
|
||||
const positionClasses = {
|
||||
'top-right': '-right-1 -top-1',
|
||||
'top-left': '-left-1 -top-1',
|
||||
'bottom-right': '-right-1 -bottom-1',
|
||||
'bottom-left': '-left-1 -bottom-1'
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"absolute",
|
||||
positionClasses[position],
|
||||
"z-10",
|
||||
className
|
||||
)}
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
{!showConfirm && (
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className={clsx(
|
||||
sizeClasses[size],
|
||||
"rounded-full",
|
||||
"bg-white/90 shadow-sm",
|
||||
"text-gray-400 hover:text-red-600",
|
||||
"transition-all duration-150",
|
||||
"opacity-0 group-hover:opacity-100",
|
||||
"hover:scale-110"
|
||||
)}
|
||||
title="Remove"
|
||||
>
|
||||
<MdClose size={iconSizes[size]} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{showConfirm && (
|
||||
<div className={clsx(
|
||||
"flex items-center gap-1",
|
||||
"bg-white rounded-lg shadow-lg",
|
||||
sizeClasses[size]
|
||||
)}>
|
||||
<button
|
||||
onClick={handleConfirm}
|
||||
className="p-1 rounded-md bg-red-50 text-red-600 hover:bg-red-100 transition-colors"
|
||||
title="Confirm remove"
|
||||
>
|
||||
<MdDelete size={iconSizes[size]} />
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCancel}
|
||||
className="p-1 rounded-md bg-gray-50 text-gray-600 hover:bg-gray-100 transition-colors"
|
||||
title="Cancel"
|
||||
>
|
||||
<MdClose size={iconSizes[size]} />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmDeleteBtn;
|
||||
|
||||
Reference in New Issue
Block a user