Files
encoach_frontend/src/components/ExamEditor/SectionRenderer/index.tsx

102 lines
4.5 KiB
TypeScript
Executable File

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';
import LevelContext from './SectionContext/level';
import { Module } from '@/interfaces';
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; module: Module }>> = {
reading: ReadingContext,
listening: ListeningContext,
level: LevelContext,
};
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} module={currentModule} />}
<SectionExercises sectionId={id} />
</div>
)}
</SectionDropdown>
</div>);
})}
</div>
</div>
</>
);
};
export default SectionRenderer;