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,61 @@
import axios from "axios";
import { playSound } from "@/utils/sound";
import { toast } from "react-toastify";
import { Generating } from "@/stores/examEditor/types";
import useExamEditorStore from "@/stores/examEditor";
import { Module } from "@/interfaces";
interface GeneratorConfig {
method: 'GET' | 'POST';
queryParams?: Record<string, string>;
body?: Record<string, any>;
}
export function generate(
sectionId: number,
module: Module,
type: "context" | "exercises",
config: GeneratorConfig,
mapData: (data: any) => Record<string, any>[]
) {
const dispatch = useExamEditorStore.getState().dispatch;
const setGenerating = (sectionId: number, generating: Generating) => {
dispatch({
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: { sectionId, module, field: "generating", value: generating }
});
};
const setGeneratedExercises = (sectionId: number, exercises: Record<string, any>[] | undefined) => {
dispatch({
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: { sectionId, module, field: "genResult", value: exercises }
});
};
setGenerating(sectionId, type);
const queryString = config.queryParams
? new URLSearchParams(config.queryParams).toString()
: '';
const url = `/api/exam/generate/${module}/${sectionId}${queryString ? `?${queryString}` : ''}`;
const request = config.method === 'POST'
? axios.post(url, config.body)
: axios.get(url);
request
.then((result) => {
playSound("check");
setGeneratedExercises(sectionId, mapData(result.data));
})
.catch((error) => {
playSound("error");
toast.error("Something went wrong! Try to generate again.");
})
.finally(() => {
setGenerating(sectionId, undefined);
});
}

View File

@@ -0,0 +1,41 @@
import { Module } from "@/interfaces";
import useExamEditorStore from "@/stores/examEditor";
import { Generating } from "@/stores/examEditor/types";
import clsx from "clsx";
import { BsArrowRepeat } from "react-icons/bs";
import { GiBrain } from "react-icons/gi";
interface Props {
module: Module;
sectionId: number;
genType: Generating;
generateFnc: (sectionId: number) => void
}
const GenerateBtn: React.FC<Props> = ({module, sectionId, genType, generateFnc}) => {
const {generating} = useExamEditorStore((store) => store.modules[module].sections.find((s)=> s.sectionId == sectionId))!;
const loading = generating && generating === genType;
return (
<button
key={`section-${sectionId}`}
className={clsx(
"flex items-center w-[140px] justify-center px-4 py-2 text-white rounded-xl transition-colors duration-300 text-lg",
`bg-ielts-${module}/70 border border-ielts-${module} hover:bg-ielts-${module}`
)}
onClick={loading ? () => { } : () => generateFnc(sectionId)}
>
{loading ? (
<div key={`section-${sectionId}`} className="flex items-center justify-center">
<BsArrowRepeat className="text-white animate-spin" size={25} />
</div>
) : (
<div key={`section-${sectionId}`} className="flex flex-row">
<GiBrain className="mr-2" size={24} />
<span>Generate</span>
</div>
)}
</button>
);
}
export default GenerateBtn;

View File

@@ -0,0 +1,33 @@
import Dropdown from "@/components/Dropdown";
import clsx from "clsx";
import { ReactNode } from "react";
interface Props {
module: string;
title: string;
open: boolean;
disabled?: boolean;
setIsOpen: (isOpen: boolean) => void;
children: ReactNode;
}
const SettingsDropdown: React.FC<Props> = ({ module, title, open, setIsOpen, children, disabled = false }) => {
return (
<Dropdown
title={title}
className={clsx(
"w-full font-semibold flex justify-between items-center p-4 bg-gradient-to-r border text-white shadow-md transition-all duration-300 disabled:cursor-not-allowed",
`bg-ielts-${module}/70 border border-ielts-${module} hover:bg-ielts-${module} disabled:bg-ielts-${module}/30`,
open ? "rounded-t-lg" : "rounded-lg"
)}
contentWrapperClassName="pt-6 px-2 bg-white rounded-b-lg shadow-md transition-all duration-300 ease-in-out"
open={open}
setIsOpen={setIsOpen}
disabled={disabled}
>
{children}
</Dropdown>
);
}
export default SettingsDropdown;