Merge branch 'develop' into master-corporate

This commit is contained in:
Joao Ramos
2024-07-20 12:38:52 +01:00
13 changed files with 2293 additions and 1185 deletions

View File

@@ -0,0 +1,84 @@
import { FillBlanksExercise } from "@/interfaces/exam";
import React from "react";
import Input from "@/components/Low/Input";
interface Props {
exercise: FillBlanksExercise;
updateExercise: (data: any) => void;
}
const FillBlanksEdit = (props: Props) => {
const { exercise, updateExercise } = props;
return (
<>
<Input
type="text"
label="Prompt"
name="prompt"
required
value={exercise.prompt}
onChange={(value) =>
updateExercise({
prompt: value,
})
}
/>
<Input
type="text"
label="Text"
name="text"
required
value={exercise.text}
onChange={(value) =>
updateExercise({
text: value,
})
}
/>
<h1>Solutions</h1>
<div className="w-full flex flex-wrap -mx-2">
{exercise.solutions.map((solution, index) => (
<div key={solution.id} className="flex sm:w-1/2 lg:w-1/4 px-2">
<Input
type="text"
label={`Solution ${index + 1}`}
name="solution"
required
value={solution.solution}
onChange={(value) =>
updateExercise({
solutions: exercise.solutions.map((sol) =>
sol.id === solution.id ? { ...sol, solution: value } : sol
),
})
}
/>
</div>
))}
</div>
<h1>Words</h1>
<div className="w-full flex flex-wrap -mx-2">
{exercise.words.map((word, index) => (
<div key={index} className="flex sm:w-1/2 lg:w-1/4 px-2">
<Input
type="text"
label={`Word ${index + 1}`}
name="word"
required
value={word}
onChange={(value) =>
updateExercise({
words: exercise.words.map((sol, idx) =>
index === idx ? value : sol
),
})
}
/>
</div>
))}
</div>
</>
);
};
export default FillBlanksEdit;

View File

@@ -0,0 +1,7 @@
import React from "react";
const InteractiveSpeakingEdit = () => {
return null;
};
export default InteractiveSpeakingEdit;

View File

@@ -0,0 +1,130 @@
import React from "react";
import { MatchSentencesExercise } from "@/interfaces/exam";
import Input from "@/components/Low/Input";
import Select from "@/components/Low/Select";
interface Props {
exercise: MatchSentencesExercise;
updateExercise: (data: any) => void;
}
const MatchSentencesEdit = (props: Props) => {
const { exercise, updateExercise } = props;
const selectOptions = exercise.options.map((option) => ({
value: option.id,
label: option.id,
}));
return (
<>
<Input
type="text"
label="Prompt"
name="prompt"
required
value={exercise.prompt}
onChange={(value) =>
updateExercise({
prompt: value,
})
}
/>
<h1>Solutions</h1>
<div className="w-full flex flex-wrap -mx-2">
{exercise.sentences.map((sentence, index) => (
<div key={sentence.id} className="flex flex-col w-full px-2">
<div className="flex w-full">
<Input
type="text"
label={`Sentence ${index + 1}`}
name="sentence"
required
value={sentence.sentence}
onChange={(value) =>
updateExercise({
sentences: exercise.sentences.map((iSol) =>
iSol.id === sentence.id
? {
...iSol,
sentence: value,
}
: iSol
),
})
}
className="px-2"
/>
<div className="w-48 flex items-end px-2">
<Select
value={selectOptions.find(
(o) => o.value === sentence.solution
)}
options={selectOptions}
onChange={(value) => {
updateExercise({
sentences: exercise.sentences.map((iSol) =>
iSol.id === sentence.id
? {
...iSol,
solution: value?.value,
}
: iSol
),
});
}}
/>
</div>
</div>
</div>
))}
<h1>Options</h1>
<div className="w-full flex flex-wrap -mx-2">
{exercise.options.map((option, index) => (
<div key={option.id} className="flex flex-col w-full px-2">
<div className="flex w-full">
<Input
type="text"
label={`Option ${index + 1}`}
name="option"
required
value={option.sentence}
onChange={(value) =>
updateExercise({
options: exercise.options.map((iSol) =>
iSol.id === option.id
? {
...iSol,
sentence: value,
}
: iSol
),
})
}
className="px-2"
/>
<div className="w-48 flex items-end px-2">
<Select
value={{
value: option.id,
label: option.id,
}}
options={[
{
value: option.id,
label: option.id,
},
]}
disabled
onChange={() => {}}
/>
</div>
</div>
</div>
))}
</div>
</div>
</>
);
};
export default MatchSentencesEdit;

View File

@@ -0,0 +1,137 @@
import React from "react";
import Input from "@/components/Low/Input";
import {
MultipleChoiceExercise,
MultipleChoiceQuestion,
} from "@/interfaces/exam";
import Select from "@/components/Low/Select";
interface Props {
exercise: MultipleChoiceExercise;
updateExercise: (data: any) => void;
}
const variantOptions = [
{ value: "text", label: "Text", key: "text" },
{ value: "image", label: "Image", key: "src" },
];
const MultipleChoiceEdit = (props: Props) => {
const { exercise, updateExercise } = props;
return (
<>
<h1>Questions</h1>
<div className="w-full flex-no-wrap -mx-2">
{exercise.questions.map((question: MultipleChoiceQuestion, index) => {
const variantValue = variantOptions.find(
(o) => o.value === question.variant
);
const solutionsOptions = question.options.map((option) => ({
value: option.id,
label: option.id,
}));
const solutionValue = solutionsOptions.find(
(o) => o.value === question.solution
);
return (
<div key={question.id} className="flex w-full px-2 flex-col">
<span>Question ID: {question.id}</span>
<Input
type="text"
label="Prompt"
name="prompt"
required
value={question.prompt}
onChange={(value) =>
updateExercise({
questions: exercise.questions.map((sol) =>
sol.id === question.id ? { ...sol, prompt: value } : sol
),
})
}
/>
<div className="flex w-full">
<div className="w-48 flex items-end px-2">
<Select
value={solutionValue}
options={solutionsOptions}
onChange={(value) => {
updateExercise({
questions: exercise.questions.map((sol) =>
sol.id === question.id
? { ...sol, solution: value?.value }
: sol
),
});
}}
/>
</div>
<div className="w-48 flex items-end px-2">
<Select
value={variantValue}
options={variantOptions}
onChange={(value) => {
updateExercise({
questions: exercise.questions.map((sol) =>
sol.id === question.id
? { ...sol, variant: value?.value }
: sol
),
});
}}
/>
</div>
</div>
<div className="flex w-full flex-wrap -mx-2">
{question.options.map((option) => (
<div
key={option.id}
className="flex sm:w-1/2 lg:w-1/4 px-2 px-2"
>
<Input
type="text"
label={`Option ${option.id}`}
name="option"
required
value={option.text}
onChange={(value) =>
updateExercise({
questions: exercise.questions.map((sol) =>
sol.id === question.id
? {
...sol,
options: sol.options.map((opt) => {
if (
opt.id === option.id &&
variantValue?.key
) {
return {
...opt,
[variantValue.key]: value,
};
}
return opt;
}),
}
: sol
),
})
}
/>
</div>
))}
</div>
</div>
);
})}
</div>
</>
);
};
export default MultipleChoiceEdit;

View File

@@ -0,0 +1,7 @@
import React from 'react';
const SpeakingEdit = () => {
return null;
}
export default SpeakingEdit;

View File

@@ -0,0 +1,71 @@
import React from "react";
import { TrueFalseExercise } from "@/interfaces/exam";
import Input from "@/components/Low/Input";
import Select from "@/components/Low/Select";
interface Props {
exercise: TrueFalseExercise;
updateExercise: (data: any) => void;
}
const options = [
{ value: "true", label: "True" },
{ value: "false", label: "False" },
{ value: "not_given", label: "Not Given" },
];
const TrueFalseEdit = (props: Props) => {
const { exercise, updateExercise } = props;
return (
<>
<Input
type="text"
label="Prompt"
name="prompt"
required
value={exercise.prompt}
onChange={(value) =>
updateExercise({
prompt: value,
})
}
/>
<h1>Questions</h1>
<div className="w-full flex-no-wrap -mx-2">
{exercise.questions.map((question, index) => (
<div key={question.id} className="flex w-full px-2">
<Input
type="text"
label={`Question ${index + 1}`}
name="question"
required
value={question.prompt}
onChange={(value) =>
updateExercise({
questions: exercise.questions.map((sol) =>
sol.id === question.id ? { ...sol, prompt: value } : sol
),
})
}
/>
<div className="w-48 flex items-end px-2">
<Select
value={options.find((o) => o.value === question.solution)}
options={options}
onChange={(value) => {
updateExercise({
questions: exercise.questions.map((sol) =>
sol.id === question.id ? { ...sol, solution: value?.value } : sol
),
});
}}
className="h-18"
/>
</div>
</div>
))}
</div>
</>
);
};
export default TrueFalseEdit;

View File

@@ -0,0 +1,94 @@
import React from "react";
import Input from "@/components/Low/Input";
import { WriteBlanksExercise } from "@/interfaces/exam";
interface Props {
exercise: WriteBlanksExercise;
updateExercise: (data: any) => void;
}
const WriteBlankEdits = (props: Props) => {
const { exercise, updateExercise } = props;
return (
<>
<Input
type="text"
label="Prompt"
name="prompt"
required
value={exercise.prompt}
onChange={(value) =>
updateExercise({
prompt: value,
})
}
/>
<Input
type="text"
label="Text"
name="text"
required
value={exercise.text}
onChange={(value) =>
updateExercise({
text: value,
})
}
/>
<Input
type="text"
label="Max Words"
name="number"
required
value={exercise.maxWords}
onChange={(value) =>
updateExercise({
maxWords: Number(value),
})
}
/>
<h1>Solutions</h1>
<div className="w-full flex flex-wrap -mx-2">
{exercise.solutions.map((solution) => (
<div key={solution.id} className="flex flex-col w-full px-2">
<span>Solution ID: {solution.id}</span>
{/* TODO: Consider adding an add and delete button */}
<div className="flex flex-wrap">
{solution.solution.map((sol, solIndex) => (
<Input
key={`${sol}-${solIndex}`}
type="text"
label={`Solution ${solIndex + 1}`}
name="solution"
required
value={sol}
onChange={(value) =>
updateExercise({
solutions: exercise.solutions.map((iSol) =>
iSol.id === solution.id
? {
...iSol,
solution: iSol.solution.map((iiSol, iiIndex) => {
if (iiIndex === solIndex) {
return value;
}
return iiSol;
}),
}
: iSol
),
})
}
className="sm:w-1/2 lg:w-1/4 px-2"
/>
))}
</div>
</div>
))}
</div>
</>
);
};
export default WriteBlankEdits;

View File

@@ -0,0 +1,7 @@
import React from 'react';
const WritingEdit = () => {
return null;
}
export default WritingEdit;