Exam generation rework, batch user tables, fastapi endpoint switch

This commit is contained in:
Carlos-Mesquita
2024-11-04 23:29:14 +00:00
parent a2bc997e8f
commit 15c9c4d4bd
148 changed files with 11348 additions and 3901 deletions

View File

@@ -0,0 +1,67 @@
import useExamEditorStore from '@/stores/examEditor';
import ExamEditorStore from '@/stores/examEditor/types';
import { useCallback, useState } from 'react';
interface Props {
sectionId: number;
mode?: "delete" | "edit";
editing?: boolean;
setEditing?: React.Dispatch<React.SetStateAction<boolean>>;
onSave?: () => void;
onDiscard?: () => void;
onMode?: () => void;
}
const useSectionEdit = ({
sectionId,
editing: externalEditing = false,
setEditing: externalSetEditing,
onSave,
onDiscard,
onMode
}: Props) => {
const { dispatch } = useExamEditorStore();
const [internalEditing, setInternalEditing] = useState<boolean>(externalEditing);
const editing = externalSetEditing !== undefined ? externalEditing : internalEditing;
const setEditing = externalSetEditing !== undefined ? externalSetEditing : setInternalEditing;
const updateRoot = useCallback((updates: Partial<ExamEditorStore>) => {
dispatch({ type: 'UPDATE_ROOT', payload: { updates } });
}, [dispatch]);
const handleEdit = useCallback(() => {
setEditing(true);
}, [sectionId, setEditing, updateRoot]);
const handleSave = useCallback(() => {
if (onSave) {
onSave();
} else {
setEditing(false);
}
}, [setEditing, updateRoot, onSave, sectionId]);
const handleDiscard = useCallback(() => {
setEditing(false);
onDiscard?.();
}, [setEditing, updateRoot, onDiscard, sectionId]);
const modeHandle = useCallback(() => {
setEditing(!editing);
onMode?.();
}, [setEditing, editing, updateRoot, onMode, sectionId]);
return {
editing,
setEditing,
handleEdit,
handleSave,
handleDiscard,
modeHandle,
};
};
export default useSectionEdit;

View File

@@ -0,0 +1,81 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import useExamEditorStore from "@/stores/examEditor";
import { Module } from "@/interfaces";
import { debounce } from "lodash";
import { SectionSettings } from "@/stores/examEditor/types";
// Since all the other components have a local state
// that then gets updated all at once, if the keydowns
// aren't here aren't throttled things can get messy
const useSettingsState = <T extends SectionSettings>(
module: Module,
sectionId: number,
) => {
const globalSettings = useExamEditorStore((state) => {
const settings = state.modules[module].sections.find(
(section) => section.sectionId === sectionId
)?.settings;
return settings as T;
});
const dispatch = useExamEditorStore((state) => state.dispatch);
const [localSettings, setLocalSettings] = useState<T>(() =>
globalSettings || {} as T
);
const pendingUpdatesRef = useRef<Partial<T>>({});
useEffect(() => {
if (globalSettings) {
setLocalSettings(globalSettings);
}
}, [globalSettings]);
const debouncedUpdateGlobal = useMemo(() => {
const debouncedFn = debounce(() => {
if (Object.keys(pendingUpdatesRef.current).length > 0) {
dispatch({
type: 'UPDATE_SECTION_SETTINGS',
payload: { sectionId, update: pendingUpdatesRef.current}
});
pendingUpdatesRef.current = {};
}
}, 1000);
return debouncedFn;
}, [dispatch, sectionId]);
useEffect(() => {
return () => {
if (Object.keys(pendingUpdatesRef.current).length > 0) {
dispatch({
type: 'UPDATE_SECTION_SETTINGS',
payload: {sectionId, update: pendingUpdatesRef.current}
});
}
};
}, [dispatch, module, sectionId]);
const updateLocalAndScheduleGlobal = useCallback((updates: Partial<T>) => {
setLocalSettings(prev => ({
...prev,
...updates
}));
pendingUpdatesRef.current = {
...pendingUpdatesRef.current,
...updates
};
debouncedUpdateGlobal();
}, [debouncedUpdateGlobal]);
return {
localSettings,
updateLocalAndScheduleGlobal
};
};
export default useSettingsState;