mirror of
https://github.com/samkaraca/lazuri-doviguram.git
synced 2026-04-29 17:59:51 +00:00
slight improvements in activity ui
This commit is contained in:
parent
c959753077
commit
1254ff3b80
@ -5,7 +5,7 @@ $board-item-height: 1.8rem;
|
||||
.exercise-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 2.5rem;
|
||||
row-gap: 3rem;
|
||||
}
|
||||
|
||||
.board-items-board {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { DndContext } from "@dnd-kit/core";
|
||||
import { ReactNode, useEffect } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import { BoardItemsBoard } from "./draggables_board";
|
||||
import styles from "./styles.module.scss";
|
||||
import IDraggable from "@/lib/utils/dnd_setting/draggable";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
.exercise-body {
|
||||
padding-inline: 9%;
|
||||
padding-block: 4rem;
|
||||
margin-inline: 9%;
|
||||
margin-block: 4rem;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { WrapperDndContext } from "@/core/components/dnd/wrapper_dnd_context";
|
||||
import { Droppable } from "@/core/components/dnd/droppable";
|
||||
import activityStyles from "../../activity.module.scss";
|
||||
import { Draggable } from "@/core/components/dnd/draggable";
|
||||
import useViewModelContext from "../../view_model";
|
||||
import IFillInBlanksExercise from "@/lib/exercise/fill_in_blanks_exercise/fill_in_blanks_exercise";
|
||||
@ -19,45 +18,53 @@ export function DragIntoBlanksExercise() {
|
||||
if (!dndBoard || !replies) return null;
|
||||
|
||||
return (
|
||||
<article>
|
||||
<div className={activityStyles["exercise-body"]}>
|
||||
<WrapperDndContext
|
||||
disabled={isSolved}
|
||||
board={dndBoard}
|
||||
startDragging={handleStartDragging}
|
||||
stopDragging={handleStopDragging}
|
||||
>
|
||||
<section aria-label="sorular">
|
||||
<ol className={`simple composite-question-list`}>
|
||||
{(activityData.exercise as IFillInBlanksExercise).template.map(
|
||||
(item, index) => {
|
||||
return (
|
||||
<li key={index}>
|
||||
<section aria-label="soru içeriği">
|
||||
{item.atoms.map((piece) => {
|
||||
const { id, type } = piece;
|
||||
if (type === "text") {
|
||||
return (
|
||||
<p
|
||||
key={id}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: piece.value,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (type === "blank") {
|
||||
const reply = ExerciseServices.getReply(
|
||||
id,
|
||||
replies
|
||||
);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
<WrapperDndContext
|
||||
disabled={isSolved}
|
||||
board={dndBoard}
|
||||
startDragging={handleStartDragging}
|
||||
stopDragging={handleStopDragging}
|
||||
>
|
||||
<section aria-label="sorular">
|
||||
<ol className={`simple composite-question-list`}>
|
||||
{(activityData.exercise as IFillInBlanksExercise).template.map(
|
||||
(item, index) => {
|
||||
return (
|
||||
<li key={index}>
|
||||
<section aria-label="soru içeriği">
|
||||
{item.atoms.map((piece) => {
|
||||
const { id, type } = piece;
|
||||
if (type === "text") {
|
||||
return (
|
||||
<p
|
||||
key={id}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: piece.value,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (type === "blank") {
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
|
||||
return (
|
||||
<Droppable
|
||||
return (
|
||||
<Droppable
|
||||
status={
|
||||
isSolved
|
||||
? isCorrect
|
||||
? "success"
|
||||
: "error"
|
||||
: "neutral"
|
||||
}
|
||||
disabled={isSolved}
|
||||
key={id}
|
||||
blankId={id}
|
||||
>
|
||||
{reply?.value && reply?.id && (
|
||||
<Draggable
|
||||
status={
|
||||
isSolved
|
||||
? isCorrect
|
||||
@ -66,38 +73,23 @@ export function DragIntoBlanksExercise() {
|
||||
: "neutral"
|
||||
}
|
||||
disabled={isSolved}
|
||||
key={id}
|
||||
blankId={id}
|
||||
>
|
||||
{reply?.value && reply?.id && (
|
||||
<Draggable
|
||||
status={
|
||||
isSolved
|
||||
? isCorrect
|
||||
? "success"
|
||||
: "error"
|
||||
: "neutral"
|
||||
}
|
||||
disabled={isSolved}
|
||||
item={{
|
||||
id: reply.id,
|
||||
value: reply.value,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Droppable>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
</section>
|
||||
</WrapperDndContext>
|
||||
</div>
|
||||
</article>
|
||||
item={{
|
||||
id: reply.id,
|
||||
value: reply.value,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Droppable>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
</section>
|
||||
</WrapperDndContext>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ReactNode } from "react";
|
||||
import useViewModelContext from "../view_model";
|
||||
import { DragIntoBlanksExercise } from "./drag_into_blanks_exercise";
|
||||
import { ActivityBody } from "./layout/activity_body";
|
||||
@ -6,6 +7,7 @@ import { MultipleChoiceExercise } from "./multiple_choice_exercise";
|
||||
import { PairTextsWithImagesExercise } from "./pair_texts_with_images_exercise";
|
||||
import { TrueFalseExercise } from "./true_false_exercise";
|
||||
import { TypeInBlanksExercise } from "./type_in_blanks_exercise";
|
||||
import activityStyles from "../activity.module.scss";
|
||||
|
||||
export function View() {
|
||||
return (
|
||||
@ -20,26 +22,29 @@ export function View() {
|
||||
export function Exercise() {
|
||||
const { activityData } = useViewModelContext()!;
|
||||
const { type } = activityData;
|
||||
let exercise: ReactNode = null;
|
||||
|
||||
if (type === "true-false") {
|
||||
return <TrueFalseExercise />;
|
||||
exercise = <TrueFalseExercise />;
|
||||
}
|
||||
|
||||
if (type === "drag-into-blanks") {
|
||||
return <DragIntoBlanksExercise />;
|
||||
exercise = <DragIntoBlanksExercise />;
|
||||
}
|
||||
|
||||
if (type === "multiple-choice") {
|
||||
return <MultipleChoiceExercise />;
|
||||
exercise = <MultipleChoiceExercise />;
|
||||
}
|
||||
|
||||
if (type === "pair-texts-with-images") {
|
||||
return <PairTextsWithImagesExercise />;
|
||||
exercise = <PairTextsWithImagesExercise />;
|
||||
}
|
||||
|
||||
if (type === "type-in-blanks") {
|
||||
return <TypeInBlanksExercise />;
|
||||
exercise = <TypeInBlanksExercise />;
|
||||
}
|
||||
|
||||
return null;
|
||||
return (
|
||||
<article className={activityStyles["exercise-body"]}>{exercise}</article>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { ReactNode } from "react";
|
||||
import YouTube from "react-youtube";
|
||||
import getYouTubeID from "get-youtube-id";
|
||||
import styles from "./styles.module.scss";
|
||||
@ -10,50 +9,48 @@ export function ActivityBody() {
|
||||
activityData;
|
||||
|
||||
return (
|
||||
<section className={styles["container"]} aria-label="aktivite">
|
||||
<>
|
||||
<header className={styles["header"]}>
|
||||
<h2 className={styles["title"]}>{title}</h2>
|
||||
</header>
|
||||
<div className={styles["main"]}>
|
||||
{youtubeVideoUrl && (
|
||||
<div className={styles["yt-container-container"]}>
|
||||
<YouTube
|
||||
iframeClassName={styles["yt-iframe"]}
|
||||
className={styles["yt-container"]}
|
||||
opts={{ width: "100%", height: "100%" }}
|
||||
videoId={getYouTubeID(youtubeVideoUrl) ?? undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{explanation && (
|
||||
<div className={styles["explanation"]}>
|
||||
<h3 className={styles["text"]}>{explanation}</h3>
|
||||
<div className={styles["line"]} />
|
||||
</div>
|
||||
)}
|
||||
<div className={styles["content"]}>
|
||||
{image && (
|
||||
<img
|
||||
className={styles["image"]}
|
||||
alt="Aktivite ek fotoğraf"
|
||||
src={`${process.env.NEXT_PUBLIC_AWS_CLOUDFRONT_IMAGE_BASE_URL}/${image}`}
|
||||
/>
|
||||
)}
|
||||
{textContent && (
|
||||
<p
|
||||
className={styles["text-content"]}
|
||||
dangerouslySetInnerHTML={{ __html: textContent }}
|
||||
/>
|
||||
)}
|
||||
{audio && (
|
||||
<audio
|
||||
className={styles["audio"]}
|
||||
controls
|
||||
src={`${process.env.NEXT_PUBLIC_AWS_CLOUDFRONT_AUDIO_BASE_URL}/${audio}`}
|
||||
/>
|
||||
)}
|
||||
{explanation && (
|
||||
<div className={styles["explanation"]}>
|
||||
<h3 className={styles["text"]}>{explanation}</h3>
|
||||
<div className={styles["line"]} />
|
||||
</div>
|
||||
)}
|
||||
{youtubeVideoUrl && (
|
||||
<div className={styles["yt-container-container"]}>
|
||||
<YouTube
|
||||
iframeClassName={styles["yt-iframe"]}
|
||||
className={styles["yt-container"]}
|
||||
opts={{ width: "100%", height: "100%" }}
|
||||
videoId={getYouTubeID(youtubeVideoUrl) ?? undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles["content"]}>
|
||||
{image && (
|
||||
<img
|
||||
className={styles["image"]}
|
||||
alt="Aktivite ek fotoğraf"
|
||||
src={`${process.env.NEXT_PUBLIC_AWS_CLOUDFRONT_IMAGE_BASE_URL}/${image}`}
|
||||
/>
|
||||
)}
|
||||
{textContent && (
|
||||
<p
|
||||
className={styles["text-content"]}
|
||||
dangerouslySetInnerHTML={{ __html: textContent }}
|
||||
/>
|
||||
)}
|
||||
{audio && (
|
||||
<audio
|
||||
className={styles["audio"]}
|
||||
controls
|
||||
src={`${process.env.NEXT_PUBLIC_AWS_CLOUDFRONT_AUDIO_BASE_URL}/${audio}`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 3rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
@ -17,63 +16,65 @@
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
div.explanation {
|
||||
width: fit-content;
|
||||
font-size: 1.4rem;
|
||||
padding-inline: 9%;
|
||||
div.explanation {
|
||||
margin-block: 3rem;
|
||||
width: fit-content;
|
||||
font-size: 1.4rem;
|
||||
padding-inline: 9%;
|
||||
|
||||
div.line {
|
||||
margin-top: 1rem;
|
||||
background-color: black;
|
||||
height: 0.3rem;
|
||||
width: 35%;
|
||||
div.line {
|
||||
margin-top: 1rem;
|
||||
background-color: black;
|
||||
height: 0.3rem;
|
||||
width: 35%;
|
||||
}
|
||||
}
|
||||
|
||||
.yt-container-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-block: 3rem;
|
||||
margin-top: 4rem;
|
||||
|
||||
.yt-container {
|
||||
margin: 0;
|
||||
height: 20rem;
|
||||
width: 75%;
|
||||
|
||||
.yt-iframe {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.yt-container-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.content:not(:empty) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 2rem;
|
||||
margin-block: 3rem;
|
||||
padding-inline: 12.5%;
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
background-color: #ccc;
|
||||
|
||||
.yt-container {
|
||||
margin: 0;
|
||||
height: 20rem;
|
||||
width: 75%;
|
||||
|
||||
.yt-iframe {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
max-height: 18rem;
|
||||
object-fit: contain;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.content:not(:empty) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 1.5rem;
|
||||
margin-top: 2.5rem;
|
||||
padding-inline: 12.5%;
|
||||
.audio {
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
max-height: 18rem;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.audio {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-content {
|
||||
margin: 0;
|
||||
}
|
||||
.text-content {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-inline: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
margin-inline: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import IMultipleChoiceExercise from "@/lib/exercise/multiple_choice_exercise/multiple_choice_exercise";
|
||||
import activityStyles from "../../activity.module.scss";
|
||||
import useViewModelContext from "../../view_model";
|
||||
import * as ExerciseServices from "@/lib/exercise/exercise_services";
|
||||
|
||||
@ -10,62 +9,52 @@ export function MultipleChoiceExercise() {
|
||||
if (!replies) return null;
|
||||
|
||||
return (
|
||||
<article>
|
||||
<div className={activityStyles["exercise-body"]}>
|
||||
<ol className={`simple multiple-choice`}>
|
||||
{(activityData.exercise as IMultipleChoiceExercise).template.map(
|
||||
({ id, questionText, choices }, index) => {
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
<ol className={`simple multiple-choice`}>
|
||||
{(activityData.exercise as IMultipleChoiceExercise).template.map(
|
||||
({ id, questionText, choices }, index) => {
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
|
||||
return (
|
||||
<li
|
||||
key={id}
|
||||
className={`${
|
||||
isSolved ? (isCorrect ? "success" : "error") : ""
|
||||
}`}
|
||||
>
|
||||
<section aria-label="soru">
|
||||
<p dangerouslySetInnerHTML={{ __html: questionText }} />
|
||||
<div className={"choices"}>
|
||||
{choices.map((choice, i) => {
|
||||
return (
|
||||
<div key={`${choice}-${i}`} className={"choice"}>
|
||||
<input
|
||||
disabled={isSolved}
|
||||
onChange={() =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(
|
||||
id,
|
||||
i.toString(),
|
||||
replies
|
||||
)
|
||||
)
|
||||
}
|
||||
checked={reply && reply.value === i.toString()}
|
||||
type="radio"
|
||||
id={`choice-${index}-${i}`}
|
||||
name={`choice-${index}`}
|
||||
/>
|
||||
<label
|
||||
htmlFor={`choice-${index}-${i}`}
|
||||
dangerouslySetInnerHTML={{ __html: choice }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
</div>
|
||||
</article>
|
||||
return (
|
||||
<li
|
||||
key={id}
|
||||
className={`${isSolved ? (isCorrect ? "success" : "error") : ""}`}
|
||||
>
|
||||
<section aria-label="soru">
|
||||
<p dangerouslySetInnerHTML={{ __html: questionText }} />
|
||||
<div className={"choices"}>
|
||||
{choices.map((choice, i) => {
|
||||
return (
|
||||
<div key={`${choice}-${i}`} className={"choice"}>
|
||||
<input
|
||||
disabled={isSolved}
|
||||
onChange={() =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(id, i.toString(), replies)
|
||||
)
|
||||
}
|
||||
checked={reply && reply.value === i.toString()}
|
||||
type="radio"
|
||||
id={`choice-${index}-${i}`}
|
||||
name={`choice-${index}`}
|
||||
/>
|
||||
<label
|
||||
htmlFor={`choice-${index}-${i}`}
|
||||
dangerouslySetInnerHTML={{ __html: choice }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import styles from "./styles.module.scss";
|
||||
import activityStyles from "../../activity.module.scss";
|
||||
import { Droppable } from "@/core/components/dnd/droppable";
|
||||
import { WrapperDndContext } from "@/core/components/dnd/wrapper_dnd_context";
|
||||
import { Draggable } from "@/core/components/dnd/draggable";
|
||||
@ -20,36 +19,40 @@ export function PairTextsWithImagesExercise() {
|
||||
if (!replies || !dndBoard) return null;
|
||||
|
||||
return (
|
||||
<article>
|
||||
<div className={activityStyles["exercise-body"]}>
|
||||
<WrapperDndContext
|
||||
disabled={isSolved}
|
||||
board={dndBoard}
|
||||
startDragging={handleStartDragging}
|
||||
stopDragging={handleStopDragging}
|
||||
>
|
||||
<section
|
||||
aria-label="soru kartları"
|
||||
className={styles["question-cards"]}
|
||||
>
|
||||
{(activityData.exercise as IQAExercise).template.map(
|
||||
({ id, questionText }) => {
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
<WrapperDndContext
|
||||
disabled={isSolved}
|
||||
board={dndBoard}
|
||||
startDragging={handleStartDragging}
|
||||
stopDragging={handleStopDragging}
|
||||
>
|
||||
<section aria-label="soru kartları" className={styles["question-cards"]}>
|
||||
{(activityData.exercise as IQAExercise).template.map(
|
||||
({ id, questionText }) => {
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={`simple-card`} key={id}>
|
||||
<img
|
||||
alt="soru fotoğrafı"
|
||||
src={`${process.env.NEXT_PUBLIC_AWS_CLOUDFRONT_IMAGE_BASE_URL}/${questionText}`}
|
||||
/>
|
||||
{
|
||||
<Droppable
|
||||
className="full-width"
|
||||
return (
|
||||
<div className={`simple-card`} key={id}>
|
||||
<img
|
||||
alt="soru fotoğrafı"
|
||||
src={`${process.env.NEXT_PUBLIC_AWS_CLOUDFRONT_IMAGE_BASE_URL}/${questionText}`}
|
||||
/>
|
||||
{
|
||||
<Droppable
|
||||
className="full-width"
|
||||
status={
|
||||
isSolved ? (isCorrect ? "success" : "error") : "neutral"
|
||||
}
|
||||
disabled={isSolved}
|
||||
key={id}
|
||||
blankId={id}
|
||||
>
|
||||
{reply?.value && reply?.id && (
|
||||
<Draggable
|
||||
status={
|
||||
isSolved
|
||||
? isCorrect
|
||||
@ -57,34 +60,19 @@ export function PairTextsWithImagesExercise() {
|
||||
: "error"
|
||||
: "neutral"
|
||||
}
|
||||
styleChip={{ width: "100%" }}
|
||||
styleContainer={{ width: "100%" }}
|
||||
disabled={isSolved}
|
||||
key={id}
|
||||
blankId={id}
|
||||
>
|
||||
{reply?.value && reply?.id && (
|
||||
<Draggable
|
||||
status={
|
||||
isSolved
|
||||
? isCorrect
|
||||
? "success"
|
||||
: "error"
|
||||
: "neutral"
|
||||
}
|
||||
styleChip={{ width: "100%" }}
|
||||
styleContainer={{ width: "100%" }}
|
||||
disabled={isSolved}
|
||||
item={{ id: reply.id, value: reply.value }}
|
||||
/>
|
||||
)}
|
||||
</Droppable>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</section>
|
||||
</WrapperDndContext>
|
||||
</div>
|
||||
</article>
|
||||
item={{ id: reply.id, value: reply.value }}
|
||||
/>
|
||||
)}
|
||||
</Droppable>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</section>
|
||||
</WrapperDndContext>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import styles from "./styles.module.scss";
|
||||
import activityStyles from "../../activity.module.scss";
|
||||
import useViewModelContext from "../../view_model";
|
||||
import * as ExerciseServices from "@/lib/exercise/exercise_services";
|
||||
import IQAExercise from "@/lib/exercise/qa_exercise/qa_exercise";
|
||||
@ -11,72 +10,67 @@ export function TrueFalseExercise() {
|
||||
if (!replies) return null;
|
||||
|
||||
return (
|
||||
<section
|
||||
className={styles["container"]}
|
||||
aria-label="doğru yanlış egzersizi"
|
||||
>
|
||||
<div className={activityStyles["exercise-body"]}>
|
||||
<header>
|
||||
<span>Doğru</span>
|
||||
<span>Yanlış</span>
|
||||
</header>
|
||||
<ol className={`simple ${styles["questions"]}`}>
|
||||
{(activityData.exercise as IQAExercise).template.map(
|
||||
({ id, questionText }) => {
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
<div className={`${styles["container"]}`}>
|
||||
<header>
|
||||
<span>Doğru</span>
|
||||
<span>Yanlış</span>
|
||||
</header>
|
||||
<ol className={`simple ${styles["questions"]}`}>
|
||||
{(activityData.exercise as IQAExercise).template.map(
|
||||
({ id, questionText }) => {
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
|
||||
return (
|
||||
<li
|
||||
className={`${
|
||||
isSolved ? styles[isCorrect ? "success" : "error"] : ""
|
||||
}`}
|
||||
key={id}
|
||||
>
|
||||
<section aria-label="soru">
|
||||
<p
|
||||
className={styles["question"]}
|
||||
dangerouslySetInnerHTML={{ __html: questionText }}
|
||||
/>
|
||||
<div className={styles["radio-buttons"]}>
|
||||
<div className={styles["radio-button"]}>
|
||||
<input
|
||||
type="radio"
|
||||
name={`true-false-${id}`}
|
||||
disabled={isSolved}
|
||||
checked={reply && reply.value === "true"}
|
||||
onChange={() =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(id, "true", replies)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["radio-button"]}>
|
||||
<input
|
||||
type="radio"
|
||||
name={`true-false-${id}`}
|
||||
disabled={isSolved}
|
||||
checked={reply && reply.value === "false"}
|
||||
onChange={() =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(id, "false", replies)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
return (
|
||||
<li
|
||||
className={`${
|
||||
isSolved ? styles[isCorrect ? "success" : "error"] : ""
|
||||
}`}
|
||||
key={id}
|
||||
>
|
||||
<section aria-label="soru">
|
||||
<p
|
||||
className={styles["question"]}
|
||||
dangerouslySetInnerHTML={{ __html: questionText }}
|
||||
/>
|
||||
<div className={styles["radio-buttons"]}>
|
||||
<div className={styles["radio-button"]}>
|
||||
<input
|
||||
type="radio"
|
||||
name={`true-false-${id}`}
|
||||
disabled={isSolved}
|
||||
checked={reply && reply.value === "true"}
|
||||
onChange={() =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(id, "true", replies)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
<div className={styles["radio-button"]}>
|
||||
<input
|
||||
type="radio"
|
||||
name={`true-false-${id}`}
|
||||
disabled={isSolved}
|
||||
checked={reply && reply.value === "false"}
|
||||
onChange={() =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(id, "false", replies)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import IFillInBlanksExercise from "@/lib/exercise/fill_in_blanks_exercise/fill_in_blanks_exercise";
|
||||
import activityStyles from "../../activity.module.scss";
|
||||
import useViewModelContext from "../../view_model";
|
||||
import * as ExerciseServices from "@/lib/exercise/exercise_services";
|
||||
|
||||
@ -10,62 +9,54 @@ export function TypeInBlanksExercise() {
|
||||
if (!replies) return null;
|
||||
|
||||
return (
|
||||
<article>
|
||||
<div className={activityStyles["exercise-body"]}>
|
||||
<ol className={`simple composite-question-list`}>
|
||||
{(activityData.exercise as IFillInBlanksExercise).template.map(
|
||||
(item, index) => {
|
||||
return (
|
||||
<li key={index}>
|
||||
<section aria-label="soru">
|
||||
{item.atoms.map((piece) => {
|
||||
const { id, type } = piece;
|
||||
<ol className={`simple composite-question-list`}>
|
||||
{(activityData.exercise as IFillInBlanksExercise).template.map(
|
||||
(item, index) => {
|
||||
return (
|
||||
<li key={index}>
|
||||
<section aria-label="soru">
|
||||
{item.atoms.map((piece) => {
|
||||
const { id, type } = piece;
|
||||
|
||||
if (type === "text") {
|
||||
return (
|
||||
<p
|
||||
key={id}
|
||||
dangerouslySetInnerHTML={{ __html: piece.value }}
|
||||
/>
|
||||
);
|
||||
if (type === "text") {
|
||||
return (
|
||||
<p
|
||||
key={id}
|
||||
dangerouslySetInnerHTML={{ __html: piece.value }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
style={{ width: "10rem" }}
|
||||
className={`basic ${
|
||||
isSolved ? (isCorrect ? "success" : "error") : ""
|
||||
}`}
|
||||
key={id}
|
||||
disabled={isSolved}
|
||||
value={reply?.value ?? ""}
|
||||
onChange={(e) =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(id, e.target.value, replies)
|
||||
)
|
||||
}
|
||||
|
||||
const reply = ExerciseServices.getReply(id, replies);
|
||||
const isCorrect = ExerciseServices.checkReply(
|
||||
id,
|
||||
activityData.exercise,
|
||||
replies
|
||||
);
|
||||
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
style={{ width: "10rem" }}
|
||||
className={`basic ${
|
||||
isSolved ? (isCorrect ? "success" : "error") : ""
|
||||
}`}
|
||||
key={id}
|
||||
disabled={isSolved}
|
||||
value={reply?.value ?? ""}
|
||||
onChange={(e) =>
|
||||
setReplies(
|
||||
ExerciseServices.reply(
|
||||
id,
|
||||
e.target.value,
|
||||
replies
|
||||
)
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
</div>
|
||||
</article>
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user