0% found this document useful (0 votes)
10 views24 pages

New Text Document

Uploaded by

tuannmhe179004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views24 pages

New Text Document

Uploaded by

tuannmhe179004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 24

import { Helmet } from "react-helmet";

import { Breadcrumb, BreadcrumbItem, Card, CardBody, CardSubtitle, CardTitle, Row,


Col, Form, Button, Input, Label, FormGroup, ModalFooter, Modal, ModalHeader,
ModalBody, NavLink, NavItem, Nav, TabContent, TabPane, Table, Alert } from
"reactstrap";
import { useNavigate, useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import React, { useEffect, useMemo, useState } from "react";
import classnames from "classnames";
import CustomButton from "components/CustomButton";
import DataTable from "components/table/DataTable";
import { defaultColumn, useFilters, usePagination, useRowSelect, useTable } from
"react-table";
import SearchColumnFilter from "components/table/SearchColumnFilter";
import SelectColumnFilter from "components/table/SelectColumnFilter";
import { createCourse, fetchCourseBySubjectId, updateCourse, updateCourseStatus }
from "api/CourseApi";
import AddModal from "components/modal/AddModal";
import { adjustStatusChapter, arrangeChapterOrder, createChapter,
getChapterBySubject, updateChapter } from "api/ChapterApi";
import EditModal from "components/modal/EditModal";
import ConfirmModal from "components/modal/ConfirmModal";
import { addDomainToSubject, asignSubjectManager, changeDomainStatus,
changeSubjectStatus, createDomain, fetchDomain, fetchDomainBySubjectId,
fetchSubjectById, updateDomain, updateSubject } from "api/SubjectApi";
import PaginationSection from "components/table/PaginationSection";
import AlertBox from "components/AlertBox";
import { changeQuestionStatus, createQuestion, fetchQuestionBySubjectId,
updateQuestion } from "api/QuestionApi";
import { fetchSettingSemester, fetchSettingTypeList } from "api/SettingApi";
import EditButton from "components/EditButton";
import StatusButton from "components/StatusButton";
import { createTest, exportTemplateQuestion, fetchTestBySubjectId,
importTestQuestionByExcel } from "api/TestApi";
import AddClassModal from "components/modal/AddClassModal";
import { fetchAccount, getAllTeacher } from "api/AccountApi";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import ImportModal from "components/modal/ImportFileModal ";
import EditClassModal from "components/modal/EditClassModal";

const ManagerSubject = () => {


/** General */
const { subjectId } = useParams();
const [subjectData, setSubjectData] = useState(null);
const [activeTab, setActiveTab] = useState('1');
const [error, setError] = useState({});
const [message, setMessage] = useState({});
const navigate = useNavigate();
/** Data */
const [courseData, setCourseData] = useState([]);
const [questionData, setQuestionData] = useState([]);
const [domainData, setDomainData] = useState([]);
const [chapterData, setChapterData] = useState([]);
const [simulationTestData, setSimulationTestData] = useState([]);
const [domainOptions, setDomainOptions] = useState([]);
const [semesterOptions, setSemesterOptions] = useState([]);
/**Loading */
const [editingSubject, setEditingSubject] = useState(false);
const [editingManager, setEditingManager] = useState(false);
const [loading, setLoading] = useState(false);
/** Modal */
/**Chapter Modal */
const [addChapterModal, setAddChapterModal] = useState(false);
const [editChapterModal, setEditChapterModal] = useState(false);
const [editChapterData, setEditChapterData] = useState({});
const [statusChapterModal, setStatusChapterModal] = useState(false);
const [isArrangingChapter, setIsArrangingChapter] = useState(false);
const [chapters, setChapters] = useState(chapterData);
/** Course Modal */
const [addCourseModal, setAddCourseModal] = useState(false);
const [editCourseModal, setEditCourseModal] = useState(false);
const [editCourseData, setEditCourseData] = useState({});
const [statusCourseModal, setStatusCourseModal] = useState(false);
/** Domain Modal */
const [createDomainModal, setCreateDomainModal] = useState(false);
const [editDomainModal, setEditDomainModal] = useState(false);
const [editDomainData, setEditDomainData] = useState({});
const [statusDomainModal, setStatusDomainModal] = useState(false);
const [isDataTable, setIsDataTable] = useState(true);
/** Question Modal */
const [addQuestionModal, setAddQuestionModal] = useState(false);
const [editQuestionModal, setEditQuestionModal] = useState(false);
const [editQuestionData, setEditQuestionData] = useState({});
const [statusQuestionModal, setStatusQuestionModal] = useState(false);
/** Question Modal */
const [addTestModal, setAddTestModal] = useState(false);
const [importTestquestionModal, setImportTestquestionModal] = useState(false);
/** Table */
const [currentRow, setCurrentRow] = useState();
const [expandedQuestionId, setExpandedQuestionId] = useState([]);
const [expandedRows, setExpandedRows] = useState({});
const [confirmModal, setConfirmModal] = useState(false);
/**Pagination */
const [totalElements, setTotalElements] = useState(0);
const [totalPages, setTotalPages] = useState(0);
const [currentPage, setCurrentPages] = useState(0);
const [searchTerm, setSearchTerm] = useState('');
const [sortField, setSortField] = useState('id');
const [descend, setDescend] = useState(false);
const [key, setKey] = useState();
/** New Data */
const [formData, setFormData] = useState({ name: "", code: "", status: false,
departmentName: "Example", description: "", managerName: "", managerPhone: "",
managerCode: "", managerEmail: "" });
const [teacherEmailData, setTeacherEmailData] = useState([]);
const [newTeacherEmail, setNewTeacherEmail] = useState(null);
const [newChapter, setNewChapter] = useState({ title: "", number: 0, content:
"", status: true });
const [newCourse, setNewCourse] = useState({ name: "", description: "", code:
"", semesterSettingId: '', status: true, email: "" });
const [newDomain, setNewDomain] = useState({ name: "", parent: null, status:
true });
const [newTest, setNewTest] = useState({ title: '', timeLimit: '', status: true
});
const [selectedFile, setSelectedFile] = useState(null);
const [currentTestId, setCurrentTestId] = useState(null);
const [filteredEmails, setFilteredEmails] = useState([]);
const toggleConfirmModal = () => {
setConfirmModal(!confirmModal);
};

const handleToggleStatus = async () => {


const response = await changeSubjectStatus(subjectId);
if (response && response.error === true) {
handleApiError("errorAddCourse", response);
} else {
fetchSubjectData();
setConfirmModal(!confirmModal);
}
};

const handleEmailInputChange = (e) => {


const value = e.target.value;
setNewTeacherEmail(value);

if (value) {
const suggestions = teacherEmailData.filter((teacher) =>
teacher.email.toLowerCase().includes(value.toLowerCase())
);
const formattedSuggestions = suggestions.map((teacher) => ({
display: `${teacher.email} (${teacher.code})`,
email: teacher.email,
code: teacher.code,
}));
setFilteredEmails(formattedSuggestions);
} else {
const allSuggestions = teacherEmailData.map((teacher) => ({
display: `${teacher.email} (${teacher.code})`,
email: teacher.email,
code: teacher.code,
}));
setFilteredEmails(allSuggestions);
}
};

const handleEmailSelect = (email) => {


setNewTeacherEmail(email);
setFilteredEmails([]);
};

const handleArrangChapter = async () => {


const sortedChapters = chapters.map((chapter, index) => ({
chapterId: chapter.id,
number: index + 1,
}));
const response = await arrangeChapterOrder({
subjectId: subjectId,
sortedChapter: sortedChapters
});
if (response && response.error === true) {
handleApiError("errorFetchSubject", response);
} else {
fetchChapter();
setIsArrangingChapter(false);
}
}

/** Use Effect */


const fetchSubjectData = async () => {
const response = await fetchSubjectById(subjectId);
if (response && response.error === true) {
handleApiError("errorFetchSubject", response);
} else {
setSubjectData(response.body);
setFormData({
name: response.body.name || "",
code: response.body.code || "",
status: response.body.status || false,
departmentName: response.body.department.departmentName || "",
description: response.body.description || "",
managerCode: response.body.managedBy?.code || "",
managerEmail: response.body.managedBy?.email || "",
managerName: (response.body.managedBy?.firstName || ' ' + ' ' +
response.body.managedBy?.lastName) || "",
managerName: (response.body.managedBy?.firstName &&
response.body.managedBy?.lastName ? (response.body.managedBy.firstName + ' ' +
response.body.managedBy.lastName) : "Unasgined"),
managerPhone: response.body.managedBy?.phone || ""
});
setNewTeacherEmail(response.body.managedBy?.email);
await fetchTeacherEmail();
await fetchSemester();
await fetchChapter();
await fetchCourse();
await fetchDomain();
await fetchQuestion();
await fetchSimulationTest();
}
};

const handleFileChange = (e) => {


setSelectedFile(e.target.files[0]);
};

const handleImport = async () => {


if (selectedFile) {
const response = await importTestQuestionByExcel(currentTestId,
selectedFile);
if (response && response.error === true) {
handleApiError("errorImportQuestion", response);
} else {
setMessage("editTest", "Add question successfully");
fetchSimulationTest();
setImportTestquestionModal();
}
}
};

const handleOnDragEnd = (result) => {


try {
const { destination, source } = result;

if (!destination || destination.index === source.index) {


return;
}

const reorderedChapters = Array.from(chapters);


const [removed] = reorderedChapters.splice(source.index, 1);
reorderedChapters.splice(destination.index, 0, removed);
setChapters(reorderedChapters);
} catch (error) {
console.error("Error during drag and drop:", error);
}
};

const fetchSimulationTest = async () => {


const response = await fetchTestBySubjectId({
subjectId: subjectId,
pageIndex: currentPage,
descend: true,
getAll: true,
sortField: 'id',
searchKey: key
});
if (response && response.error === true) {
handleApiError("errorFetchSimulationTest", response);
} else {
setSimulationTestData(response.body.content);
setTotalElements(response.body.totalElements);
setTotalPages(response.body.totalPages);
}
}

const downloadTemplate = async () => {


try {
const templateUrl = await exportTemplateQuestion();
const a = document.createElement('a');
a.href = templateUrl;
a.download = 'template.xlsx';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(templateUrl);
} catch (error) {
setError({ errorImportQuestion: "Unable to download the template" });
}
};

const fetchQuestion = async () => {


const response = await fetchQuestionBySubjectId({
subjectId: subjectId,
pageIndex: currentPage,
descend: descend,
sortField: sortField,
searchKey: key
});
if (response && response.error === true) {
handleApiError("errorFetchQuestion", response);
} else {
setQuestionData(response.body.content);
setTotalElements(response.body.totalElements);
setTotalPages(response.body.totalPages);
}
}

const fetchTeacherEmail = async () => {


const response = await getAllTeacher();
if (response && response.error === true) {
handleApiError("errorFetchAccount", response);
} else {
setTeacherEmailData(response.body);
}
}

const fetchCourse = async () => {


const response = await fetchCourseBySubjectId(subjectId);
setCourseData(response.body);
}

const fetchChapter = async () => {


const response = await getChapterBySubject({
subjectId: subjectId,
pageIndex: currentPage,
descend: descend,
getAll: true,
sortField: 'number',
searchKey: key
});
setChapterData(response.body.content);
setChapters(response.body.content);
}

const fetchDomain = async () => {


const response = await fetchDomainBySubjectId(subjectId);
setDomainData(response.body);
const domainsMap = {};
response.body.forEach(domain => {
if (!domainsMap[domain.id]) {
domainsMap[domain.id] = {
id: domain.id,
label: domain.name,
parentId: domain.parent ? domain.parent.id : null,
children: []
};
}

if (domain.parent) {
const parentId = domain.parent.id;
if (domainsMap[parentId]) {
domainsMap[parentId].children.push(domainsMap[domain.id]);
}
}
});
const result = Object.values(domainsMap).filter(domain => domain.parentId
=== null);
setDomainOptions(result);
}
const fetchSemester = async () => {
const response = await fetchSettingSemester();
if (response && response.error === true) {
handleApiError("errorFetchSubject", response);
} else {
const sortedSemesters = (response.body?.content || []).sort((a, b) =>
b.id - a.id);
setSemesterOptions(sortedSemesters);
}
};

useEffect(() => {
fetchSubjectData();
}, [subjectId]);

useEffect(() => {
fetchSubjectData();
}, [activeTab, currentPage, sortField, descend, key]);

/** Table Section */


const columns = useMemo(() => {
switch (activeTab) {
case '3':
return [
{ Header: "Id", accessor: "id", width: '60px' },
{ Header: "Name", accessor: "name", start: 'start', Cell:
({ row }) => (row.original.parent ? <span className="ms-3"> -
{row.original.name}</span> : row.original.name) },
{ Header: "Parent Name", accessor: "parent.name", Cell:
({ row }) => (row.original.parent ? row.original.parent.name : '') },
{ Header: "Status", id: "status", accessor: "status", Filter:
SelectColumnFilter, width: '80px' },
{
Header: "Actions", id: "actions",
Cell: ({ row }) => (
<div className="d-flex justify-content-start align-
items-center">
<EditButton btnStyle='btn-outline-info me-2'
icon='bi bi-pencil-square' onClick={() => toggleEditDommainModal(row)} />{' '}
<StatusButton status={row.original.status}
onClick={() => toggleStatusDomainModal(row.original.id)} />
</div>
), width: '80px'
}
];
case '4':
return [
{ Header: "Id", accessor: "id", width: '60px' },
{ Header: "Code", accessor: "code", width: '100px' },
{ Header: "Course name", accessor: "name", start: 'start' },
{ Header: "Teacher", accessor: "teacherCode", width:
'150px', },
{
Header: "Stu.", accessor: "numberOfStudents",
Cell: ({ row }) => (
<span>{row.original.numberOfStudents + 1}</span>
), width: '60px'
},
{ Header: "Semester", accessor: "semester.name", Filter:
SelectColumnFilter, width: '140px' },
{ Header: "Status", accessor: "status", Filter:
SelectColumnFilter, width: '80px' },
{
Header: "Actions", id: "actions",
Cell: ({ row }) => (
<div className="d-flex justify-content-start align-
items-center">
<EditButton btnStyle='btn-outline-info me-2'
icon='bi bi-pencil-square' onClick={() => toggleEditCourseModal(row)} />{' '}
<StatusButton status={row.original.status}
onClick={() => toggleStatusCourseModal(row.original.id)} />

</div>
), width: '80px'
},
];
case '2':
return [
{ Header: "Id", accessor: "id", width: '60px' },
{ Header: "Chapter No.", accessor: "number", width: '60px' },
{ Header: "Title", accessor: "title", start: 'start' },
{ Header: "Content", accessor: "content", start: 'start' },
{ Header: "Status", accessor: "status", Filter:
SelectColumnFilter },
{
Header: "Actions", id: "actions",
Cell: ({ row }) => (
<div className="d-flex justify-content-start align-
items-center">
<EditButton btnStyle='btn-outline-info me-2'
icon='bi bi-pencil-square' onClick={() => toggleEditChapterModal(row)} />{' '}
<StatusButton status={row.original.status}
onClick={() => toggleStatusChapterModal(row.original.id)} />
</div>
), width: '80px'
},
];
default:
return [
{ Header: "Id", accessor: "id", width: '60px' },
{ Header: "Chapter No.", accessor: "number", width: '60px' },
{ Header: "Title", accessor: "title", start: 'start' },
{ Header: "Content", accessor: "content", start: 'start' },
{ Header: "Status", accessor: "status", Filter:
SelectColumnFilter },
{
Header: "Actions", id: "actions",
Cell: ({ row }) => (
<div className="d-flex justify-content-start align-
items-center">
<EditButton btnStyle='btn-outline-info me-2'
icon='bi bi-pencil-square' onClick={() => toggleEditChapterModal(row)} />{' '}
<StatusButton status={row.original.status}
onClick={() => toggleStatusChapterModal(row.original.id)} />

</div>
), width: '80px'
},
];
}
}, [activeTab, expandedQuestionId]);
const tableData = useMemo(() => {
if (activeTab === '6') {
return questionData;
} else if (activeTab === '5') {
return questionData;
} else if (activeTab === '4') {
return courseData;
} else if (activeTab === '3') {
return domainData;
} else {
return chapterData;
}
}, [activeTab, chapterData, courseData, domainData, questionData]);

const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page


} = useTable(
{ columns, data: tableData, defaultColumn: { Filter: SearchColumnFilter },
initialState: { pageSize: 1000000 }, },
useFilters, usePagination, useRowSelect
);

/** Form template */


/** Form Add */
const formAddChapter = [
{ label: 'Title', id: 'title', type: 'text', name: 'title', required:
true },
{ label: 'Content', id: 'content', type: 'text', name: 'content', required:
true },
];

const formAddTest = [
{ label: 'Title', id: 'title', type: 'text', name: 'title', required:
true },
{ label: 'Time Limit (Mins)', id: 'timeLimit', type: 'number', name:
'timeLimit', min: '0', required: true },
];

const formAddCourse = [
{ label: 'Description', id: 'description', type: 'text', name:
'description', required: true },
{ label: 'Class Code', id: 'code', type: 'text', name: 'code', required:
true },
{
label: 'Semester', id: 'semesterSettingId', type: 'select', name:
'semesterSettingId', required: true,
options: Array.isArray(semesterOptions) && semesterOptions.length > 0
? semesterOptions.map(opt => ({ label: opt.name + ' - ' +
opt.value, value: opt.id }))
: []
},
];

const formCreateDomain = [
{ label: 'Name', id: 'name', type: 'text', name: 'name', required: true },
{
label: 'Domain parent', id: 'parent', type: 'select', name: 'parent',
options: Array.isArray(domainData) && domainData.length > 0 ?
domainData
.filter(opt => opt.parent === null && opt.status === true).map(opt
=> ({ label: opt.name, value: opt.id }))
: []
},
];

/** Form Edit */


const formEditChapter = [
{ label: 'Id', id: 'id', type: 'text', name: 'id', required: true,
disabled: true },
{ label: 'Title', id: 'title', type: 'text', name: 'title', required:
true },
{ label: 'Content', id: 'content', type: 'textarea', name: 'content',
required: true },
];

const formEditDomain = [
{ label: 'Id', id: 'id', type: 'text', name: 'id', required: true,
disabled: true },
{ label: 'Name', id: 'name', type: 'text', name: 'name', required: true },
];

const formEditCourse = [
{ label: 'Id', id: 'id', type: 'text', name: 'id', required: true,
disabled: true },
{ label: 'Name', id: 'name', type: 'text', name: 'name', required: true },
{ label: 'Code', id: 'code', type: 'text', name: 'code', required: true },
{
label: 'Semester', id: 'semesterSettingId', type: 'select', name:
'semesterSettingId', required: true,
options: [
...(semesterOptions && semesterOptions.length > 0
? semesterOptions.map(opt => ({ label: opt.name + ' - ' +
opt.value, value: opt.id }))
: []
)
],
},
{ label: 'Description', id: 'description', type: 'textarea', name:
'description' }
];

/**Function */
/** Toggle Modal */
const toggleAddChapterModal = () => { setAddChapterModal(!addChapterModal); }
const toggleAddTestModal = () => { setAddTestModal(!addTestModal); }
// const toggleImportQuestionModal = () => { setImportTestquestionModal(!
importTestquestionModal); }
const toggleImportQuestionModal = (testId) => {
setCurrentTestId(testId); // Lưu testId khi mở modal
setImportTestquestionModal(!importTestquestionModal);
};
const toggleAddCourseModal = () => { setAddCourseModal(!addCourseModal); }
const toggleCreateDommainModal = () => { setCreateDomainModal(!
createDomainModal); }
const toggleAddQuestionModal = () => { setAddQuestionModal(!
addQuestionModal); }
const toggleEditChapterModal = (row) => {
if (row && row.original) {
setEditChapterData(row.original);
}
setEditChapterModal(!editChapterModal);
}
const toggleEditCourseModal = (row) => {

if (row && row.original) {


const teacherEmail = teacherEmailData.find(teacher => teacher.code ===
row.original.teacherCode)?.email || '';
setEditCourseData({
...row.original,
semesterSettingId: row.original.semester?.id,
email: teacherEmail
});
}
setEditCourseModal(!editCourseModal);
}

const toggleEditDommainModal = (row) => {


if (row && row.original) {
setEditDomainData({
...row.original,
parent: row.original.name
});
}
setEditDomainModal(!editDomainModal);
}

const toggleStatusCourseModal = (id) => {


setCurrentRow(id);
setStatusCourseModal(!statusCourseModal);
}
const toggleStatusChapterModal = (id) => {
setCurrentRow(id);
setStatusChapterModal(!statusChapterModal);
}
const toggleStatusDomainModal = (id) => {
setCurrentRow(id);
setStatusDomainModal(!statusDomainModal);
}
const toggleRow = (id) => {
setExpandedRows(prevState => ({
...prevState,
[id]: !prevState[id],
}));
};

const renderChildDomains = (parentId) => {


const childDomains = domainData.filter(domain => domain.parent &&
domain.parent.id === parentId);

return childDomains.length ? (
<span>
{childDomains.map((child) => (
<div key={child.id} className="row mx-1 mb-2">
<span className="col-1 border-end px-2 text-
end">{child.id}</span>
<span className="col-6 border-end px-2">{child.name}</span>
<span className={`col-2 px-2 ${child.status ? 'text-
success' : 'text-danger'}`}>
{child.status ? 'Active' : 'Inactive'}
</span>
</div>
))}
</span>
) : (
<span className="ms-2 text-muted fs-6">{'( No child domain )'}</span>
);
};

const toggleExpandRow = (id) => {


setExpandedQuestionId((prev) =>
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
);
};

/** Handle Function */


const handleApiError = (apiName, errorData) => {
setError((prevErrors) => ({
...prevErrors,
[apiName]: errorData
}));
console.log('Api Error: ', error);
};

const handleChangeSubjectData = (e) => {


const { name, value, type, checked } = e.target;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
};

const handleEditSubject = async () => {


if (editingSubject) {
setError({});
setMessage({});
const updateData = {
id: subjectId,
departmentId: subjectData.department.id,
...formData,
};
const response = await updateSubject(updateData);
if (response && response.error === true) {
handleApiError("errorEditSubject", response);
} else {
fetchSubjectData();
setEditingSubject(!editingSubject);
setMessage({ editSubject: 'Update successfully!' });
}
}
};

const handleEditManager = async () => {


if (editingManager) {
setError({});
setMessage({});
const updateManager = {
subjectId: subjectId,
teacherEmail: newTeacherEmail
};
console.log(updateManager);
const response = await asignSubjectManager(updateManager);
if (response && response.error === true) {
handleApiError("errEditMng", response);
} else {
fetchSubjectData();
setEditingManager(!editingManager);
setMessage({ msgAddMng: 'Asign successfully!' });
}
}
};

const handleAddChapter = async (e) => {


e.preventDefault();
setError({});
setMessage({});
const response = await createChapter({
title: newChapter.title,
content: newChapter.content,
status: true,
subjectId: subjectId
});
if (response && response.error === true) {
handleApiError("errAddChapter", response);
} else {
fetchSubjectData();
setMessage({ msgAddChapter: 'Added new Chapter!' });
toggleAddChapterModal();
}
};

const handleAddTest = async (e) => {


e.preventDefault();
setError({});
setMessage({});
const response = await createTest({
title: newTest.title,
timeLimit: newTest.timeLimit,
status: true,
subjectId: subjectId
});
if (response && response.error === true) {
handleApiError("errorAddtest", response);
} else {
fetchSubjectData();
setMessage({ editTest: 'Added new Chapter!' });
// toggleAddTestModal();
}
};

const handleEditChapter = async (e) => {


e.preventDefault();
setError({});
setMessage({});
const updateData = {
subjectId: subjectId,
...editChapterData,
};
const response = await updateChapter(updateData);
if (response && response.error === true) {
handleApiError("errEditChapter", response);
} else {
fetchSubjectData();
setMessage({ msgAddChapter: 'Chapter ID: ' + response.body.id + '
Updated successfully!' });
toggleEditChapterModal();
}
};

const handleChapterStatus = async (id) => {


setError({});
setMessage({});
await adjustStatusChapter(id);
fetchSubjectData();
setMessage({ editChapter: 'Chapter ID: ' + id + ' Changed status
successfully!' });
setStatusChapterModal(!statusChapterModal);
};

const handleAddCourse = async (e) => {


e.preventDefault();
setError({});
setMessage({});
const response = await createCourse({
name: newCourse.name,
description: newCourse.description,
code: newCourse.code,
email: newCourse.email,
subjectId: subjectId,
semesterSettingId: newCourse.semesterSettingId
});
if (response && response.error === true) {
handleApiError("errorAddCourse", response);
} else {
fetchCourse();
setMessage({ editCourse: 'Create new class' + response.body.name + '
successfully!' });
// toggleAddCourseModal();
}
};

const handleEditCourse = async (e) => {


e.preventDefault();
setError({});
setMessage({});
const updateData = {
subjectId: subjectId,
...editCourseData,
};

const response = await updateCourse(updateData);


if (response && response.error === true) {
handleApiError("errorEditCourse", response);
} else {
fetchCourse();
setMessage({ editCourse: 'Class ID: ' + editCourseData.id + ' Updated
successfully!' });
toggleEditCourseModal();
}
};

const handleCourseStatus = async (id) => {


setError({});
setMessage({});
await updateCourseStatus(id);
fetchCourse();
setMessage({ editCourse: 'Class ID: ' + id + ' Changed status
successfully!' });
setStatusCourseModal(!statusCourseModal);
};

const handleCreateDomain = async (e) => {


e.preventDefault();
const newData = {
...newDomain,
subjectId: subjectId
};
const response = await createDomain(newData);
if (response && response.error === true) {
handleApiError("errorAddDomain", response);
} else {
fetchDomain();
setMessage({ msgAddDomain: 'Create new domain successfully!' });
toggleCreateDommainModal();
}
};

const handleEditDomain = async (e) => {


e.preventDefault();
setError({});
setMessage({});
const updateData = {
...editDomainData,
};
const response = await updateDomain(updateData);
if (response && response.error === true) {
handleApiError("errorEditDomain", response);
} else {
fetchDomain();
setMessage({ msgAddDomain: 'Domain ID: ' + editDomainData.id + '
updated successfully!' });
toggleEditDommainModal();
}
};

const handleDomainStatus = async (id) => {


const response = await changeDomainStatus(id);
fetchDomain();

setStatusDomainModal(!statusDomainModal);
};

const [statusQuestionTemplateModal, setStatusQuestionTemplateModal] =


useState(false);
const toggleTab = (tab) => {
if (activeTab !== tab) {
setActiveTab(tab);
}
};

return (
<div>
<Helmet>
<title>{subjectData && subjectData.code}</title>
</Helmet>
<Breadcrumb>
<BreadcrumbItem>
<Link to="/department">Department</Link>
</BreadcrumbItem>
<BreadcrumbItem>
<Link to={`/department/${subjectData &&
subjectData.department.id}`}>{subjectData &&
subjectData.department.departmentName}</Link>
</BreadcrumbItem>
<BreadcrumbItem active>{subjectData &&
subjectData.name}</BreadcrumbItem>
</Breadcrumb>
<Row>
<Col sm="12" lg="8" xl="8" xxl="8">
<Card>
<CardBody>
<CardTitle tag="h3" className="fw-bold">{subjectData &&
`${subjectData.name} - ${subjectData.code}`}</CardTitle>
</CardBody>
</Card>
</Col>
<Col sm="12" lg="4" xl="4" xxl="4">
<Card>
<CardBody>
<CardTitle tag="h4"
className="fw-bold">Resources</CardTitle>

<CustomButton btnStyle='btn-outline-primary'
title='Questions and terms' onClick={() => navigate(`/question-bank/${subjectId}`)}
type='button' icon='bi bi-arrow-right' />
</CardBody>
</Card>
</Col>
</Row>
{/* <Row> */}
{/* <Col sm="12" lg="9" xl="8" xxl="7" className='mb-3'> */}
<Nav tabs className="border-none">
<NavItem>
<NavLink className={classnames({ active: activeTab === '1',
'bg-white': activeTab === '1' })}
onClick={() => { toggleTab('1'); }} style={{ borderLeft:
'none', borderBottom: 'none' }}>
General
</NavLink>
</NavItem>
<NavItem>
<NavLink className={classnames({ active: activeTab === '2',
'bg-white': activeTab === '2' })}
onClick={() => { toggleTab('2'); }} style={{ borderBottom:
'none' }}>
Chapters
</NavLink>
</NavItem>
<NavItem>
<NavLink className={classnames({ active: activeTab === '3',
'bg-white': activeTab === '3' })}
onClick={() => { toggleTab('3'); }} style={{ borderBottom:
'none' }}>
Domains
</NavLink>
</NavItem>
<NavItem>
<NavLink className={classnames({ active: activeTab === '4',
'bg-white': activeTab === '4' })}
onClick={() => { toggleTab('4'); }} style={{ borderBottom:
'none' }}>
Classes
</NavLink>
</NavItem>
<NavItem>
<NavLink className={classnames({ active: activeTab === '6',
'bg-white': activeTab === '6' })}
onClick={() => { toggleTab('6'); }} style={{ borderBottom:
'none' }}>
Exams
</NavLink>
</NavItem>
</Nav>
<TabContent activeTab={activeTab} className="bg-white px-3 pt-1 pb-3">
<TabPane tabId="1">
<CardTitle tag="h6" className="border-bottom d-flex py-2 px-3
justify-content-between align-items-center" >
<div>
<i className="bi-book me-2"></i>
<span className="fs-5">Subject Infomation</span>
</div>
</CardTitle>
<AlertBox message={message.editSubject} />
<Row >

</Row>
<CardBody className="p-2">
<Row>
<Col>
<Form onSubmit={(e) => { e.preventDefault();
handleEditSubject(); }}>
<FormGroup>
<Label for="name">
<strong>Name: </strong>
<span hidden={editingSubject}>
{formData.name} </span>
<span hidden={!editingSubject}
className="text-danger"> * </span>
</Label>
<Input type="text" name="name" id="name"
placeholder="Enter subject name"
value={formData.name}
onChange={handleChangeSubjectData}
hidden={!editingSubject} disabled={!
editingSubject} required />
</FormGroup>
<FormGroup>
<Label for="code">
<strong>Code: </strong>
<span hidden={editingSubject}>
{formData.code} </span>
<span hidden={!editingSubject}
className="text-danger"> * </span>
</Label>
<Input type="text" name="code" id="code"
placeholder="Enter subject code"
value={formData.code}
onChange={handleChangeSubjectData} hidden={!editingSubject} disabled={!
editingSubject} required />
</FormGroup>
<div hidden={editingSubject} className="d-flex
justify-content-start mb-3">
<strong hidden={editingSubject}>Status:
</strong>
<span className={formData.status ? "text-
success ms-2" : "text-danger ms-2"} hidden={editingSubject}>
{formData ? (formData.status ? "Active"
: "Inactive") : "Loading..."}
</span>
<span className="ms-4"
hidden={editingSubject}>
<StatusButton status={formData.status}
onClick={toggleConfirmModal} />
</span>
</div>
<FormGroup>
<Label for="departmentName">
<strong>Department: </strong>
<span hidden={editingSubject}>
{formData.departmentName} </span>
</Label>
<Input type="text" name="departmentName"
id="departmentName" placeholder="Enter department"
value={formData.departmentName}
onChange={handleChangeSubjectData} hidden={!editingSubject} disabled />
</FormGroup>
<FormGroup>
<Label for="description">
<strong>Description: </strong>
<span hidden={editingSubject}>
{formData.description} </span>
</Label>
<Input type="textarea" name="description"
id="description" placeholder="Enter description"
value={formData.description}
onChange={handleChangeSubjectData} hidden={!editingSubject} disabled={!
editingSubject} />
</FormGroup>
<AlertBox error={true}
message={error.errorEditSubject} />
{!editingSubject && <CustomButton
btnStyle='btn-outline-primary' icon='bi bi-pencil-square' title='Edit subject
information' onClick={() => setEditingSubject(true)} />}
{editingSubject && <CustomButton btnStyle='btn-
primary' icon='bi bi-pencil-square' type='submit' title='Save' />}
</Form>
</Col>
</Row>
</CardBody>
<ConfirmModal isOpen={confirmModal} toggle={toggleConfirmModal}
handleConfirm={() => handleToggleStatus(currentRow)} message="Confirm changing this
status?" />

</TabPane>
<TabPane tabId="2">
<CardTitle tag="h6" className="border-bottom d-flex py-2 px-3
justify-content-between align-items-center" >
<div>
<i className="bi bi-archive me-2"></i>
<span className="fs-5">Chapter</span>
</div>
<div className="pagination d-flex align-items-center
position-relative">
<span className="d-flex align-items-center">
<CustomButton type='button' btnStyle='btn-outline-
primary' icon='bi bi-plus' title='New chapter'
onClick={toggleAddChapterModal}></CustomButton>
</span>
</div>
</CardTitle>

{isArrangingChapter ? (
<DragDropContext onDragEnd={handleOnDragEnd}>
<div className="d-flex justify-content-between my-2">
<div className="ms-2 mb-1 fs-5"> Total <strong>
{chapterData.length} </strong> chapters</div>
<div>
<CustomButton type='button' btnStyle='btn-
primary' title='Save' onClick={() => handleArrangChapter()} />
<CustomButton type='button' btnStyle='btn-
outline-secondary' title='Cancel' onClick={() => { setIsArrangingChapter(!
isArrangingChapter); fetchChapter() }} />
</div>

</div>
<Droppable droppableId="chapterList">
{(provided) => (
<div {...provided.droppableProps}
ref={provided.innerRef}>
{chapters && chapters.length > 0 ? (
chapters.map((chapter, index) => (
<Draggable key={chapter.id}
draggableId={chapter.id.toString()} index={index}>
{(provided) => (
<div className="border py-1
px-3 mb-2 rounded" ref={provided.innerRef} {...provided.draggableProps}
{...provided.dragHandleProps} style={{ ...provided.draggableProps.style }}>
<div className="row">
<div
className="col-1 d-flex align-items-center">
<div
className="fw-bold fs-5 text-primary" style={{ whiteSpace: "nowrap" }}>#{index +
1}</div>
</div>
<div
className="col-10 border-start" style={{ whiteSpace: "nowrap", overflow: "hidden",
textOverflow: "ellipsis" }}>
<div
className="fs-5"><span className="fw-bold"> Chapter {chapter.number}:</span>
{chapter.title}<span className="text-muted"> {'( ID: ' + chapter.id + '
)'}</span><span className={chapter.status ? "text-success ms-2" : "text-danger ms-
2"}>{chapter.status ? "( Active )" : "( Inactive )"}</span></div>
<div
className="text-muted ms-3" style={{ whiteSpace: "nowrap", overflow: "hidden",
textOverflow: "ellipsis" }}>{chapter.content || "(Chapter content empty)"}</div>
</div>
<div
className="col-1 d-flex align-items-center">
<i
className="bi bi-arrows-expand fs-5 text-primary" style={{ transform: "scale(1)",
cursor: "pointer", transition: "transform 0.3s ease, color 0.3s ease" }}
onMouseEnter={(e) => { e.target.style.transform = "scale(1.5)"; }}
onMouseLeave={(e) => { e.target.style.transform = "scale(1)"; }}></i>
</div>
</div>
</div>
)}
</Draggable>
))
) : (
<div className="text-center text-
muted">No chapters available.</div>
)}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>

) : (
<CardBody>
<div className="d-flex justify-content-between my-2">
<div className="ms-2 mb-1 fs-5"> Total <strong>
{chapterData.length} </strong> chapters</div>
<CustomButton type='button' btnStyle='btn-outline-
primary' icon='bi bi-arrows-expand' title='Arange' onClick={() =>
setIsArrangingChapter(!isArrangingChapter)}></CustomButton>
</div>
<AlertBox message={message.msgAddChapter} />
<DataTable getTableProps={getTableProps}
getTableBodyProps={getTableBodyProps} headerGroups={headerGroups} page={page}
prepareRow={prepareRow} columns={columns} />
<AddModal toggle={toggleAddChapterModal}
isOpen={addChapterModal} formData={newChapter} setFormData={setNewChapter}
modalTitle='Create new chapter' formFields={formAddChapter}
handleAdd={handleAddChapter} error={error.errAddChapter} />
<EditModal title='Edit chapter'
toggle={toggleEditChapterModal} isOpen={editChapterModal}
editData={editChapterData} setEditData={setEditChapterData}
handleEdit={handleEditChapter} errors={error.errEditChapter} setErrors={setError}
formFields={formEditChapter} />
<ConfirmModal isOpen={statusChapterModal}
toggle={toggleStatusChapterModal} handleConfirm={() =>
handleChapterStatus(currentRow)} message="Confirm changing this status?" />
</CardBody>
)}
</TabPane>
<TabPane tabId="3">
<CardTitle tag="h6" className="border-bottom d-flex py-2 px-3
justify-content-between align-items-center">
<div>
<i className="bi bi-clipboard me-2"></i>
<span className="fs-5">Domain</span>
</div>
<div className="pagination d-flex align-items-center
position-relative">
<span className="d-flex align-items-center">
<CustomButton type='button' btnStyle='btn-outline-
primary' icon='bi bi-plus' title='Create new domain'
onClick={toggleCreateDommainModal}></CustomButton>
</span>
</div>
</CardTitle>
<CardBody>
<div className="d-flex justify-content-between my-2">
<div className="ms-2 mb-1 fs-5">Total
<strong>{domainData.length}</strong> domains</div>
<CustomButton type="button" btnStyle="btn-outline-info"
icon="bi bi-toggle-on" title={isDataTable ? 'Edit Table' : 'Data Table'}
onClick={() => setIsDataTable(!isDataTable)} />
</div>
<AlertBox message={message.msgAddDomain} />
{!isDataTable ? (
<DataTable getTableProps={getTableProps}
getTableBodyProps={getTableBodyProps} headerGroups={headerGroups} page={page}
prepareRow={prepareRow} columns={columns} />
) : (
<Table bordered >
<thead>
<tr >
<th style={{ backgroundColor:
'inherit' }}>ID</th>
<th style={{ backgroundColor:
'inherit' }}>Parent Domain</th>
<th style={{ backgroundColor:
'inherit' }}>Status</th>
</tr>
</thead>
<tbody>
{domainData.filter(domain => !
domain.parent).map((domain) => (
<React.Fragment key={domain.id}>
<tr>
<td style={{ width: '60px',
backgroundColor: 'inherit' }}>{domain.id}</td>
<td onClick={() =>
toggleRow(domain.id)} style={{ cursor: 'pointer', backgroundColor: 'inherit' }}>
{expandedRows[domain.id] ? <i
className="bi bi-chevron-down"></i> : <i className="bi bi-chevron-right"></i>}
{domain.name}
</td>
<td className={domain.status ?
'text-success' : 'text-danger'} style={{ width: '120px', backgroundColor: 'inherit'
}}>
{domain.status ? 'Active' :
'Inactive'}
</td>
</tr>
{expandedRows[domain.id] && (
<tr>
<td style={{ backgroundColor:
'inherit' }}> </td>
<td style={{ backgroundColor:
'inherit' }}> {renderChildDomains(domain.id)} </td>
<td style={{ backgroundColor:
'inherit' }}> </td>
</tr>
)}
</React.Fragment>
))}
</tbody>
</Table>
)}
</CardBody>
<AddModal toggle={toggleCreateDommainModal}
isOpen={createDomainModal} formData={newDomain} setFormData={setNewDomain}
modalTitle='Create new domain for this course' formFields={formCreateDomain}
handleAdd={handleCreateDomain} error={error.errorAddDomain} />
<EditModal title='Change domain data' isOpen={editDomainModal}
toggle={toggleEditDommainModal} editData={editDomainData}
setEditData={setEditDomainData} handleEdit={handleEditDomain}
errors={error.errorEditDomain} setErrors={setError} formFields={formEditDomain} />
<ConfirmModal isOpen={statusDomainModal}
toggle={toggleStatusDomainModal} handleConfirm={() =>
handleDomainStatus(currentRow)} message="Confirm changing this status?" />
</TabPane>
<TabPane tabId="4">
<CardTitle tag="h6" className="border-bottom d-flex py-2 px-3
justify-content-between align-items-center" >
<div>
<i className="bi bi-laptop me-2"></i>
<span className="fs-5">Class</span>
</div>
<div className="pagination d-flex align-items-center
position-relative">
<span className="d-flex align-items-center">
<CustomButton type='button' btnStyle='btn-outline-
primary' icon='bi bi-plus' title='Create new class'
onClick={toggleAddCourseModal}></CustomButton>
</span>
</div>
</CardTitle>
<CardBody>
<div className="d-flex justify-content-between my-2">
<div className="ms-2 mb-1 fs-5"> Total <strong>
{courseData.length} </strong> classes</div>
</div>
<AlertBox message={message.editCourse} />
<DataTable getTableProps={getTableProps}
getTableBodyProps={getTableBodyProps}
headerGroups={headerGroups} page={page}
prepareRow={prepareRow} columns={columns} />

{/* <PaginationSection currentPage={currentPage}


setCurrentPages={setCurrentPages} totalPages={totalPages} /> */}

<AddClassModal emailList={teacherEmailData}
subjectName={subjectData?.name} toggle={toggleAddCourseModal}
isOpen={addCourseModal} formData={newCourse} setFormData={setNewCourse}
modalTitle='Create new class' formFields={formAddCourse}
handleAdd={handleAddCourse} error={error.errorAddCourse} />
<EditClassModal emailList={teacherEmailData} title='Change
course data' isOpen={editCourseModal} toggle={toggleEditCourseModal}
editData={editCourseData} setEditData={setEditCourseData}
handleEdit={handleEditCourse} errors={error.errorEditCourse} setErrors={setError}
formFields={formEditCourse} />
<ConfirmModal isOpen={statusCourseModal}
toggle={toggleStatusCourseModal} handleConfirm={() =>
handleCourseStatus(currentRow)} message="Confirm changing this status?" />
</CardBody>
</TabPane>
<TabPane tabId="6">
<CardTitle tag="h6" className="border-bottom d-flex py-2 px-3
justify-content-between align-items-center" >
<div>
<i className="bi bi-lightbulb me-2"></i>
<span className="fs-5"> Simulation Exam </span>
</div>
<div className="pagination d-flex align-items-center
position-relative">
<span className="d-flex align-items-center">
<CustomButton type='button' btnStyle='btn-outline-
primary' icon='bi bi-plus' title='Create new Exam'
onClick={toggleAddTestModal}></CustomButton>
</span>
</div>
</CardTitle>
<CardBody>
<div className="d-flex justify-content-between my-2">
<div className="ms-2 mb-1 fs-5"> Total <strong>
{simulationTestData.length} </strong> Exams</div>
</div>
{message.editTest && <AlertBox
message={message.editTest} />}
{simulationTestData.length > 0 ? (
simulationTestData.map((test, index) => (
<div className="border p-3 mb-2 border rounded
border-bottom d-flex justify-content-between" key={index}>
<div className="">
<h3>{test.title || test.description ||
'Test number ' + (index + 1)}</h3>
<div>
<div className="fs-5 mb-1">ID:
{test.id} </div>
<span className="fs-5 mx-1 badge bg-
primary">{test.numOfQuestions} questions</span>
<span className="fs-5 mx-1 badge bg-
info"><i className="bi bi-clock"></i> {test.timeLimit} Mins</span>
{test.numOfQuestions === 0 ? <span
className="fs-5 mx-1 badge bg-dark">Invalid</span> : <span className="fs-5 mx-1
badge bg-success">Valid</span>}

</div>
</div>
<div>
<div className="mb-2">
{test.numOfQuestions > 0 &&
<CustomButton btnStyle='btn-outline-primary' icon='bi bi-play-circle' title='Start
this exam' onClick={() => navigate(`/test-practice/${test.id}`)} />}
<CustomButton btnStyle='btn-outline-
success' icon='bi bi-file-earmark' title='Import Questions' onClick={() =>
toggleImportQuestionModal(test.id)} />
</div>
<div className="d-flex float-end">
<EditButton btnStyle='btn-outline-info'
icon='bi bi-pencil-square' />
<StatusButton status={test.status} />
</div>
</div>
</div>
))
) : (<p> No Exam available. </p>)}
{/* <PaginationSection currentPage={currentPage}
setCurrentPages={setCurrentPages} totalPages={totalPages} /> */}

<AddModal toggle={toggleAddTestModal} isOpen={addTestModal}


formData={newTest} setFormData={setNewTest} modalTitle='Create new question'
formFields={formAddTest} handleAdd={handleAddTest} error={error.errorAddTest} />
<ImportModal downloadTemplate={downloadTemplate}
handleFileChange={handleFileChange} handleImportTerms={handleImport}
error={error.errorImportQuestion}
selectedFile={selectedFile}
toggle={toggleImportQuestionModal} isOpen={importTestquestionModal} />
</CardBody>
</TabPane>
</TabContent>
</div >
);
};

export default ManagerSubject;

You might also like