import React, { useCallback, useRef, useState } from "react"; import Dropdown from "../Shared/SettingsDropdown"; import Input from "@/components/Low/Input"; import { generate } from "../Shared/Generate"; import GenerateBtn from "../Shared/GenerateBtn"; import { LevelSectionSettings, WritingSectionSettings } from "@/stores/examEditor/types"; import useExamEditorStore from "@/stores/examEditor"; import { Difficulty, WritingExercise } from "@/interfaces/exam"; import clsx from "clsx"; import { FaFileUpload } from "react-icons/fa"; import ReactSelect, { components } from "react-select"; import Option from "@/interfaces/option" import { MdSignalCellularAlt } from "react-icons/md"; import { capitalize } from "lodash"; interface Props { localSettings: WritingSectionSettings | LevelSectionSettings; updateLocalAndScheduleGlobal: (updates: Partial, schedule?: boolean) => void; currentSection?: WritingExercise; level?: boolean; } const WritingComponents: React.FC = ({ localSettings, updateLocalAndScheduleGlobal, level }) => { const { currentModule, dispatch } = useExamEditorStore(); const { difficulty, focusedSection, type, academic_url } = useExamEditorStore((store) => store.modules["writing"]); const randomDiff = difficulty.length === 1 ? capitalize(difficulty[0]) : difficulty.length == 0 ? "Random" : `Selected (${difficulty.sort().map(dif => capitalize(dif)).join(", ")})` as Difficulty; const DIFFICULTIES = difficulty.length === 1 ? ["A1", "A2", "B1", "B2", "C1", "C2", "Random"] : ["A1", "A2", "B1", "B2", "C1", "C2", randomDiff, "Random"]; const difficultyOptions: Option[] = DIFFICULTIES.map(level => ({ label: level, value: level })); const [specificDiff, setSpecificDiff] = useState(randomDiff); const generatePassage = useCallback((sectionId: number) => { if (type === "academic" && academic_url !== undefined && sectionId == 1) { generate( sectionId, currentModule, "writing", { method: 'POST', queryParams: { difficulty: specificDiff.length == 2 ? [specificDiff] : difficulty, type: type! }, files: { file: academic_url!, } }, (data: any) => [{ prompt: data.question, difficulty: data.difficulty }] ) } else { generate( sectionId, currentModule, "writing", { method: 'GET', queryParams: { difficulty: specificDiff.length == 2 ? [specificDiff] : difficulty, type: type!, ...(localSettings.writingTopic && { topic: localSettings.writingTopic }) } }, (data: any) => [{ prompt: data.question, difficulty: data.difficulty }] ); } }, [type, academic_url, currentModule, specificDiff, difficulty, localSettings.writingTopic]); const onTopicChange = useCallback((writingTopic: string) => { updateLocalAndScheduleGlobal({ writingTopic }); }, [updateLocalAndScheduleGlobal]); const fileInputRef = useRef(null); const triggerFileInput = () => { fileInputRef.current?.click(); }; const handleFileUpload = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { const blobUrl = URL.createObjectURL(file); if (academic_url !== undefined) { URL.revokeObjectURL(academic_url); } dispatch({ type: "UPDATE_MODULE", payload: { updates: { academic_url: blobUrl } } }); } }; return ( <> {type === "academic" && focusedSection === 1 && updateLocalAndScheduleGlobal({ isImageUploadOpen: isOpen }, false)} contentWrapperClassName={level ? `border border-ielts-writing` : ''} >
opt.value === specificDiff)} onChange={(value) => setSpecificDiff(value!.value as Difficulty)} menuPortalTarget={document?.body} components={{ IndicatorSeparator: null, ValueContainer: ({ children, ...props }) => (
{children}
) }} styles={{ menuPortal: (base) => ({ ...base, zIndex: 9999 }), control: (styles) => ({ ...styles, minHeight: '50px', border: '1px solid #e5e7eb', borderRadius: '0.5rem', boxShadow: 'none', backgroundColor: 'white', 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" />
Upload a graph, chart or diagram
} { (type !== "academic" || (type === "academic" && focusedSection == 2)) && updateLocalAndScheduleGlobal({ isWritingTopicOpen: isOpen }, false)} contentWrapperClassName={level ? `border border-ielts-writing` : ''} >
opt.value === specificDiff)} onChange={(value) => setSpecificDiff(value!.value as Difficulty)} menuPortalTarget={document?.body} components={{ IndicatorSeparator: null, ValueContainer: ({ children, ...props }) => (
{children}
) }} styles={{ menuPortal: (base) => ({ ...base, zIndex: 9999 }), control: (styles) => ({ ...styles, minHeight: '50px', border: '1px solid #e5e7eb', borderRadius: '0.5rem', boxShadow: 'none', backgroundColor: 'white', 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" />
} ); }; export default WritingComponents;