130 lines
3.8 KiB
TypeScript
130 lines
3.8 KiB
TypeScript
import React from 'react';
|
|
import { Module } from "@/interfaces";
|
|
import useExamEditorStore from "@/stores/examEditor";
|
|
import Dropdown from "./SettingsDropdown";
|
|
import { LevelSectionSettings } from "@/stores/examEditor/types";
|
|
import { LevelPart } from '@/interfaces/exam';
|
|
|
|
interface Props {
|
|
module: Module;
|
|
sectionId: number;
|
|
localSettings: LevelSectionSettings;
|
|
updateLocalAndScheduleGlobal: (updates: Partial<LevelSectionSettings>, schedule?: boolean) => void;
|
|
}
|
|
|
|
const SectionPicker: React.FC<Props> = ({
|
|
module,
|
|
sectionId,
|
|
localSettings,
|
|
updateLocalAndScheduleGlobal
|
|
}) => {
|
|
const { dispatch } = useExamEditorStore();
|
|
const [selectedValue, setSelectedValue] = React.useState<number | undefined>(undefined);
|
|
|
|
const sectionState = useExamEditorStore(state =>
|
|
state.modules["level"].sections.find((s) => s.sectionId === sectionId)
|
|
);
|
|
|
|
const state = sectionState?.state as LevelPart;
|
|
|
|
if (sectionState === undefined) return null;
|
|
|
|
const { readingSection, listeningSection } = sectionState;
|
|
const currentValue = selectedValue ?? (module === "reading" ? readingSection : listeningSection);
|
|
const options = module === "reading" ? [1, 2, 3] : [1, 2, 3, 4];
|
|
const openPicker = module === "reading" ? "isReadingPickerOpen" : "isListeningPickerOpen";
|
|
|
|
const handleSectionChange = (value: number) => {
|
|
const newValue = currentValue === value ? undefined : value;
|
|
setSelectedValue(newValue);
|
|
let update = {};
|
|
if (module === "listening") {
|
|
if (state.audio?.source) {
|
|
URL.revokeObjectURL(state.audio.source)
|
|
}
|
|
update = {
|
|
audio: undefined,
|
|
script: undefined,
|
|
}
|
|
}
|
|
|
|
dispatch({
|
|
type: "UPDATE_SECTION_STATE",
|
|
payload: {
|
|
sectionId,
|
|
module: "level",
|
|
update: {
|
|
...state,
|
|
...update
|
|
}
|
|
}
|
|
})
|
|
|
|
setTimeout(() => {
|
|
dispatch({
|
|
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
payload: {
|
|
sectionId,
|
|
module: "level",
|
|
field: module === "reading" ? "readingSection" : "listeningSection",
|
|
value: newValue
|
|
}
|
|
});
|
|
}, 500);
|
|
};
|
|
|
|
const getTitle = () => {
|
|
const section = module === "reading" ? "Passage" : "Section";
|
|
if (!currentValue) return `Choose a ${section}`;
|
|
return `${section} ${currentValue}`;
|
|
};
|
|
|
|
return (
|
|
<Dropdown
|
|
title={getTitle()}
|
|
module={module}
|
|
open={localSettings[openPicker]}
|
|
setIsOpen={(isOpen: boolean) =>
|
|
updateLocalAndScheduleGlobal({ [openPicker]: isOpen }, false)
|
|
}
|
|
contentWrapperClassName={`pt-6 px-4 bg-gray-200 rounded-b-lg shadow-md transition-all duration-300 ease-in-out border border-ielts-${module}`}
|
|
>
|
|
<div className="space-y-2 pt-3 pb-3 px-2 border border-gray-200 rounded-lg shadow-inner">
|
|
{options.map((num) => (
|
|
<label
|
|
key={num}
|
|
className={`
|
|
flex items-center space-x-3 font-semibold cursor-pointer p-2 rounded
|
|
transition-colors duration-200
|
|
${currentValue === num
|
|
? `bg-ielts-${module}/90 text-white`
|
|
: `hover:bg-ielts-${module}/70 text-gray-700`}
|
|
`}
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
handleSectionChange(num);
|
|
}}
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
checked={currentValue === num}
|
|
onChange={() => { }}
|
|
className={`
|
|
h-5 w-5 cursor-pointer
|
|
accent-ielts-${module}
|
|
`}
|
|
/>
|
|
<div className="flex items-center space-x-2">
|
|
<span>
|
|
{module === "reading" ? `Passage ${num}` : `Section ${num}`}
|
|
</span>
|
|
</div>
|
|
</label>
|
|
))}
|
|
</div>
|
|
</Dropdown>
|
|
);
|
|
};
|
|
|
|
export default SectionPicker;
|