Exam generation rework, batch user tables, fastapi endpoint switch
This commit is contained in:
99
src/components/ExamEditor/SectionRenderer/index.tsx
Executable file
99
src/components/ExamEditor/SectionRenderer/index.tsx
Executable file
@@ -0,0 +1,99 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { toast } from 'react-toastify';
|
||||
import ReadingContext from './SectionContext/reading';
|
||||
import SectionExercises from './SectionExercises';
|
||||
import useExamEditorStore from '@/stores/examEditor';
|
||||
import { ModuleState } from '@/stores/examEditor/types';
|
||||
import ListeningContext from './SectionContext/listening';
|
||||
import SectionDropdown from '../Shared/SectionDropdown';
|
||||
|
||||
|
||||
const SectionRenderer: React.FC = () => {
|
||||
const { currentModule, dispatch } = useExamEditorStore();
|
||||
const {
|
||||
focusedSection,
|
||||
expandedSections,
|
||||
sections,
|
||||
sectionLabels,
|
||||
edit,
|
||||
} = useExamEditorStore(state => state.modules[currentModule]);
|
||||
|
||||
const updateModule = useCallback((updates: Partial<ModuleState>) => {
|
||||
dispatch({ type: 'UPDATE_MODULE', payload: { updates } });
|
||||
}, [dispatch]);
|
||||
|
||||
const toggleSection = (sectionId: number) => {
|
||||
if (edit.includes(sectionId)) {
|
||||
toast.info(`Save or discard your changes first!`);
|
||||
} else {
|
||||
if (!expandedSections.includes(sectionId)) {
|
||||
updateModule({ focusedSection: sectionId });
|
||||
}
|
||||
updateModule({
|
||||
expandedSections:
|
||||
expandedSections.includes(sectionId) ?
|
||||
expandedSections.filter(index => index !== sectionId) :
|
||||
[...expandedSections, sectionId]
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const ContextMap: Record<string, React.ComponentType<{ sectionId: number; }>> = {
|
||||
reading: ReadingContext,
|
||||
listening: ListeningContext,
|
||||
};
|
||||
|
||||
const SectionContext = ContextMap[currentModule];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex flex-row'>
|
||||
<div className={clsx(
|
||||
"p-4 rounded-xl w-full",
|
||||
currentModule && `bg-ielts-${currentModule}/20`
|
||||
)}>
|
||||
|
||||
{sections.map((state, sectionIndex) => {
|
||||
const id = state.sectionId;
|
||||
const label = sectionLabels.find((sl) => sl.id == id)?.label;
|
||||
|
||||
return (
|
||||
<div key={id}
|
||||
className={
|
||||
clsx("rounded-xl shadow",
|
||||
sectionIndex !== sections.length - 1 && "mb-4"
|
||||
)}>
|
||||
<SectionDropdown
|
||||
toggleOpen={() => toggleSection(id)}
|
||||
open={expandedSections.includes(id)}
|
||||
title={label}
|
||||
className={clsx(
|
||||
"w-full py-4 px-8 text-lg font-semibold leading-6 text-white",
|
||||
"shadow-lg transform transition-all duration-300 hover:scale-102 hover:rounded-lg",
|
||||
expandedSections.includes(id) ? "rounded-t-lg" : "rounded-lg",
|
||||
focusedSection !== id ?
|
||||
`bg-gradient-to-r from-ielts-${currentModule}/30 to-ielts-${currentModule}/60 hover:from-ielts-${currentModule}/60 hover:to-ielts-${currentModule}` :
|
||||
`bg-ielts-${currentModule}`
|
||||
)}
|
||||
>
|
||||
{expandedSections.includes(id) && (
|
||||
<div
|
||||
className="p-6 bg-white rounded-b-xl shadow-inner border-b"
|
||||
onFocus={() => updateModule({ focusedSection: id })}
|
||||
tabIndex={id + 1}
|
||||
>
|
||||
{currentModule in ContextMap && <SectionContext sectionId={id} />}
|
||||
<SectionExercises sectionId={id} />
|
||||
</div>
|
||||
)}
|
||||
</SectionDropdown>
|
||||
</div>);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionRenderer;
|
||||
Reference in New Issue
Block a user