137 lines
5.1 KiB
TypeScript
137 lines
5.1 KiB
TypeScript
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 | string[]>;
|
|
files?: Record<string, string>;
|
|
body?: Record<string, any>;
|
|
}
|
|
|
|
export function generate(
|
|
sectionId: number,
|
|
module: Module,
|
|
type: Generating,
|
|
config: GeneratorConfig,
|
|
mapData: (data: any) => Record<string, any>[],
|
|
levelSectionId?: number,
|
|
level: boolean = false
|
|
) {
|
|
const setGenerating = (sectionId: number, generating: Generating, level: boolean, remove?: boolean) => {
|
|
const state = useExamEditorStore.getState();
|
|
const dispatch = state.dispatch;
|
|
let generatingUpdate;
|
|
if (level) {
|
|
if (remove) {
|
|
generatingUpdate = state.modules["level"].sections.find((s) => s.sectionId === levelSectionId)!.levelGenerating.filter(g => g === generating)
|
|
}
|
|
else {
|
|
generatingUpdate = [...state.modules["level"].sections.find((s) => s.sectionId === levelSectionId)!.levelGenerating, generating];
|
|
}
|
|
} else {
|
|
generatingUpdate = generating;
|
|
}
|
|
|
|
dispatch({
|
|
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
payload: { sectionId, module: level ? "level" : module, field: level ? "levelGenerating" : "generating", value: generatingUpdate }
|
|
});
|
|
};
|
|
|
|
const setGeneratedResult = (sectionId: number, generating: Generating, result: Record<string, any>[] | undefined, level: boolean) => {
|
|
const state = useExamEditorStore.getState();
|
|
const dispatch = state.dispatch;
|
|
|
|
let genResults;
|
|
if (level) {
|
|
genResults = [...state.modules["level"].sections.find((s) => s.sectionId === levelSectionId)!.levelGenResults, { generating, result, module }];
|
|
} else {
|
|
genResults = { generating, result, module };
|
|
}
|
|
|
|
dispatch({
|
|
type: "UPDATE_SECTION_SINGLE_FIELD",
|
|
payload: { sectionId: level ? levelSectionId! : sectionId, module: level ? "level" : module, field: level ? "levelGenResults" : "genResult", value: genResults }
|
|
});
|
|
};
|
|
|
|
setGenerating(level ? levelSectionId! : sectionId, type, level);
|
|
|
|
function buildQueryString(params: Record<string, string | string[]>): string {
|
|
const searchParams = new URLSearchParams();
|
|
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (Array.isArray(value)) {
|
|
value.forEach(v => searchParams.append(key, v));
|
|
} else {
|
|
searchParams.append(key, value);
|
|
}
|
|
});
|
|
|
|
return searchParams.toString();
|
|
}
|
|
|
|
const queryString = config.queryParams ? buildQueryString(config.queryParams) : '';
|
|
|
|
const url = `/api/exam/generate/${module}/${sectionId}${queryString ? `?${queryString}` : ''}`;
|
|
|
|
let body = null;
|
|
if (config.files && Object.keys(config.files).length > 0 && config.method === 'POST') {
|
|
const formData = new FormData();
|
|
|
|
const buildForm = async () => {
|
|
await Promise.all(
|
|
Object.entries(config.files ?? {}).map(async ([key, blobUrl]) => {
|
|
const response = await fetch(blobUrl);
|
|
const blob = await response.blob();
|
|
const file = new File([blob], key, { type: blob.type });
|
|
formData.append(key, file);
|
|
})
|
|
);
|
|
|
|
if (config.body) {
|
|
Object.entries(config.body).forEach(([key, value]) => {
|
|
formData.append(key, value as string);
|
|
});
|
|
}
|
|
return formData;
|
|
};
|
|
|
|
buildForm().then(form => {
|
|
body = form;
|
|
|
|
const request = axios.post(url, body, { headers: { 'Content-Type': 'multipart/form-data' } });
|
|
request
|
|
.then((result) => {
|
|
playSound("check");
|
|
setGeneratedResult(level ? levelSectionId! : sectionId, type, mapData(result.data), level);
|
|
})
|
|
.catch((error) => {
|
|
setGenerating(sectionId, undefined, level, true);
|
|
playSound("error");
|
|
toast.error("Something went wrong! Try to generate again.");
|
|
});
|
|
});
|
|
} else {
|
|
body = config.body;
|
|
|
|
const request = config.method === 'POST'
|
|
? axios.post(url, body, { headers: { 'Content-Type': 'application/json' } })
|
|
: axios.get(url);
|
|
|
|
request
|
|
.then((result) => {
|
|
playSound("check");
|
|
setGeneratedResult(level ? levelSectionId! : sectionId, type, mapData(result.data), level);
|
|
})
|
|
.catch((error) => {
|
|
setGenerating(sectionId, undefined, level, true);
|
|
playSound("error");
|
|
toast.error("Something went wrong! Try to generate again.");
|
|
});
|
|
}
|
|
} |