Files
encoach_frontend/src/components/ExamEditor/Shared/Header.tsx
Carlos-Mesquita ccbbf30058 ENCOA-311
2025-01-13 01:18:19 +00:00

162 lines
8.0 KiB
TypeScript

import { Module } from "@/interfaces";
import clsx from "clsx";
import { ReactNode, useEffect, useState } from "react";
import { MdDelete, MdEdit, MdEditOff, MdRefresh, MdSave, MdSignalCellularAlt } from "react-icons/md";
import { HiOutlineClipboardCheck, HiOutlineClipboardList } from "react-icons/hi";
import { Difficulty } from "@/interfaces/exam";
import Option from "@/interfaces/option";
import ReactSelect, { components } from "react-select";
interface Props {
title: string;
description: string;
editing: boolean;
difficulty?: Difficulty;
saveDifficulty?: (diff: Difficulty) => void;
module?: Module;
handleSave: () => void;
handleDiscard: () => void;
handleDelete?: () => void;
handlePractice?: () => void;
handleEdit?: () => void;
isEvaluationEnabled?: boolean;
children?: ReactNode;
}
const Header: React.FC<Props> = ({
title, description, editing, difficulty, saveDifficulty, isEvaluationEnabled, handleSave, handleDiscard, handleDelete, handleEdit, handlePractice, children, module
}) => {
const DIFFICULTIES: Difficulty[] = ["A1", "A2", "B1", "B2", "C1", "C2"];
const difficultyOptions: Option[] = DIFFICULTIES.map(level => ({
label: level,
value: level
}));
return (
<div className="flex flex-col md:flex-row items-start md:items-center mb-6 text-sm">
<div>
<h1 className="text-2xl font-bold text-gray-800">{title}</h1>
<p className="text-gray-600 mt-1">{description}</p>
</div>
<div className="flex w-[50%] ml-auto justify-end flex-wrap gap-2">
<div className="flex flex-wrap gap-2 justify-end">
<button
onClick={handleSave}
disabled={!editing}
className={
clsx("px-3 py-2 rounded-lg flex items-center gap-1 transition-all duration-200 min-w-[90px] justify-center",
editing ? 'bg-green-500 text-white hover:bg-green-600' : 'bg-gray-100 text-gray-400 cursor-not-allowed'
)}
>
<MdSave size={18} />
Save
</button>
<button
onClick={handleDiscard}
disabled={!editing}
className={clsx(
"px-3 py-2 rounded-lg flex items-center gap-1 transition-all duration-200 min-w-[90px] justify-center",
editing ? 'bg-gray-500 text-white hover:bg-gray-600' : 'bg-gray-100 text-gray-400 cursor-not-allowed'
)}
>
<MdRefresh size={18} />
Discard
</button>
{handleEdit && (
<button
onClick={handleEdit}
className={`px-3 py-2 bg-ielts-${module}/80 text-white hover:bg-ielts-${module} rounded-lg transition-all duration-200 flex items-center gap-1 min-w-[90px] justify-center`}
>
{editing ? <MdEditOff size={18} /> : <MdEdit size={18} />}
Edit
</button>
)}
{handlePractice &&
<button
onClick={handlePractice}
className={clsx(
"px-3 py-2 rounded-lg flex items-center gap-1 transition-all duration-200 min-w-[90px] justify-center",
isEvaluationEnabled
? 'bg-amber-500 text-white hover:bg-amber-600'
: 'bg-gray-200 text-gray-600 hover:bg-gray-300'
)}
>
{isEvaluationEnabled ? <HiOutlineClipboardCheck size={18} /> : <HiOutlineClipboardList size={18} />}
{isEvaluationEnabled ? 'Graded' : 'Practice'}
</button>
}
{handleDelete && (
<button
onClick={handleDelete}
className="px-3 py-2 bg-white border border-red-500 text-red-500 hover:bg-red-50 rounded-lg transition-all duration-200 flex items-center gap-1 min-w-[90px] justify-center"
>
<MdDelete size={18} />
Delete
</button>
)}
{difficulty !== undefined && (
<div className="w-[92px]">
<ReactSelect
options={difficultyOptions}
value={difficultyOptions.find(opt => opt.value === difficulty)}
onChange={(value) => saveDifficulty!(value!.value as Difficulty)}
menuPortalTarget={document?.body}
components={{
IndicatorSeparator: null,
ValueContainer: ({ children, ...props }) => (
<components.ValueContainer {...props}>
<div className="flex flex-row gap-2 items-center pl-0.5">
<MdSignalCellularAlt size={14} className="text-gray-600" />
{children}
</div>
</components.ValueContainer>
)
}}
styles={{
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
control: (styles) => ({
...styles,
minHeight: '40px',
border: '1px solid #e5e7eb',
borderRadius: '0.5rem',
boxShadow: 'none',
backgroundColor: '#f3f4f6',
cursor: 'pointer',
'&:hover': {
border: '1px solid #e5e7eb',
}
}),
valueContainer: (styles) => ({
...styles,
padding: '0 8px',
display: 'flex',
alignItems: 'center'
}),
input: (styles) => ({
...styles,
margin: '0',
padding: '0'
}),
dropdownIndicator: (styles) => ({
...styles,
padding: '8px'
}),
option: (styles, state) => ({
...styles,
backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
color: state.isFocused ? "black" : styles.color,
}),
}}
className="text-sm"
/>
</div>
)}
{children}
</div>
</div>
</div>
);
}
export default Header;