mirror of
https://github.com/samkaraca/lazuri-doviguram.git
synced 2026-04-29 17:59:51 +00:00
some buggy parts of the exercises fixed.
This commit is contained in:
parent
f1a1c7cdda
commit
89cca4620a
@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { DragIntoBlanksExercise } from "./drag_into_blanks_exercise";
|
||||
import { Layout } from "./layout";
|
||||
import { MultipleChoiceExercise } from "./multiple_choice_exercise";
|
||||
@ -13,7 +13,13 @@ import {
|
||||
TrueFalseQuestion,
|
||||
} from "@/core/models/entities/question";
|
||||
|
||||
export function Activity({ activity }: { activity: IActivity<any> }) {
|
||||
export function Activity({
|
||||
activity,
|
||||
closeActivity,
|
||||
}: {
|
||||
activity: IActivity<any>;
|
||||
closeActivity: VoidFunction;
|
||||
}) {
|
||||
const {
|
||||
title,
|
||||
textContent,
|
||||
@ -24,16 +30,16 @@ export function Activity({ activity }: { activity: IActivity<any> }) {
|
||||
activityType,
|
||||
questions,
|
||||
} = activity;
|
||||
|
||||
const [isFormLocked, setIsFormLocked] = useState(false);
|
||||
const [replies, setReplies] = useState<any[]>(
|
||||
new Array(questions.length).fill(undefined)
|
||||
);
|
||||
const [replies, setReplies] = useState<any[]>([]);
|
||||
|
||||
useEffect(() => setReplies([]), [activityType]);
|
||||
|
||||
const handleFinishClick = () => {
|
||||
setIsFormLocked(true);
|
||||
};
|
||||
const handleReattemptClick = () => {
|
||||
setReplies(new Array(questions.length).fill(undefined));
|
||||
setReplies([]);
|
||||
setIsFormLocked(false);
|
||||
};
|
||||
|
||||
@ -48,6 +54,7 @@ export function Activity({ activity }: { activity: IActivity<any> }) {
|
||||
isFormLocked={isFormLocked}
|
||||
handleReattemptClick={handleReattemptClick}
|
||||
handleFinishClick={handleFinishClick}
|
||||
closeActivity={closeActivity}
|
||||
>
|
||||
{activityType === "true-false" ? (
|
||||
<TrueFalseExercise
|
||||
|
||||
@ -15,6 +15,7 @@ export function Layout({
|
||||
handleFinishClick,
|
||||
isFormLocked,
|
||||
handleReattemptClick,
|
||||
closeActivity,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
title: Activity<any>["title"];
|
||||
@ -24,8 +25,9 @@ export function Layout({
|
||||
image: Activity<any>["image"];
|
||||
youtubeVideoUrl: Activity<any>["youtubeVideoUrl"];
|
||||
isFormLocked: boolean;
|
||||
handleReattemptClick: () => void;
|
||||
handleFinishClick: () => void;
|
||||
handleReattemptClick: VoidFunction;
|
||||
handleFinishClick: VoidFunction;
|
||||
closeActivity: VoidFunction;
|
||||
}) {
|
||||
return (
|
||||
<section className={styles["container"]} aria-label="aktivite">
|
||||
@ -79,7 +81,7 @@ export function Layout({
|
||||
<button className="simple" onClick={handleReattemptClick}>
|
||||
Tekrar Çöz
|
||||
</button>
|
||||
<button className="simple" onClick={() => {}}>
|
||||
<button className="simple" onClick={closeActivity}>
|
||||
Bitir
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import { MultipleChoiceQuestion } from "@/core/models/entities/question";
|
||||
import styles from "./styles.module.scss";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import { Dispatch, SetStateAction, useState } from "react";
|
||||
|
||||
export function MultipleChoiceExercise({
|
||||
replies,
|
||||
setReplies,
|
||||
isFormLocked,
|
||||
exercise,
|
||||
replies,
|
||||
setReplies,
|
||||
}: {
|
||||
replies: number[];
|
||||
setReplies: Dispatch<SetStateAction<number[]>>;
|
||||
isFormLocked: boolean;
|
||||
exercise: MultipleChoiceQuestion[];
|
||||
replies: number[];
|
||||
setReplies: Dispatch<SetStateAction<number[]>>;
|
||||
}) {
|
||||
return (
|
||||
<ol className={`simple multiple-choice`}>
|
||||
@ -36,13 +36,14 @@ export function MultipleChoiceExercise({
|
||||
<div key={`${choice}-${i}`} className={"choice"}>
|
||||
<input
|
||||
disabled={isFormLocked}
|
||||
onClick={() =>
|
||||
onChange={() =>
|
||||
setReplies((prev) => {
|
||||
const newReplies = [...prev];
|
||||
newReplies[index] = i;
|
||||
return newReplies;
|
||||
})
|
||||
}
|
||||
checked={replies[index] === i}
|
||||
type="radio"
|
||||
id={`choice-${index}-${i}`}
|
||||
name={`choice-${index}`}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import styles from "./styles.module.scss";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import { Dispatch, SetStateAction, useState } from "react";
|
||||
import { TrueFalseQuestion } from "@/core/models/entities/question";
|
||||
|
||||
export function TrueFalseExercise({
|
||||
replies,
|
||||
setReplies,
|
||||
exercise,
|
||||
isFormLocked,
|
||||
replies,
|
||||
setReplies,
|
||||
}: {
|
||||
replies: boolean[];
|
||||
setReplies: Dispatch<SetStateAction<boolean[]>>;
|
||||
isFormLocked: boolean;
|
||||
exercise: TrueFalseQuestion[];
|
||||
replies: boolean[];
|
||||
setReplies: Dispatch<SetStateAction<boolean[]>>;
|
||||
}) {
|
||||
return (
|
||||
<section
|
||||
@ -45,13 +45,13 @@ export function TrueFalseExercise({
|
||||
name={`true-false-${i}`}
|
||||
disabled={isFormLocked}
|
||||
checked={reply === true}
|
||||
onClick={() =>
|
||||
onChange={() => {
|
||||
setReplies((prev) => {
|
||||
const newReplies = [...prev];
|
||||
newReplies[i] = true;
|
||||
return newReplies;
|
||||
})
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["radio-button"]}>
|
||||
@ -60,13 +60,13 @@ export function TrueFalseExercise({
|
||||
name={`true-false-${i}`}
|
||||
disabled={isFormLocked}
|
||||
checked={reply === false}
|
||||
onClick={() =>
|
||||
onChange={() => {
|
||||
setReplies((prev) => {
|
||||
const newReplies = [...prev];
|
||||
newReplies[i] = false;
|
||||
return newReplies;
|
||||
})
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { IViewModel } from "@/features/activity_editor/model/view_model";
|
||||
import styles from "./styles.module.scss";
|
||||
import { Dispatch, SetStateAction, useRef, useState } from "react";
|
||||
import { Dispatch, SetStateAction, useEffect, useRef, useState } from "react";
|
||||
import { FillInBlanksQuestion } from "@/core/models/entities/question";
|
||||
|
||||
export function TypeInBlanksExercise({
|
||||
@ -9,8 +7,8 @@ export function TypeInBlanksExercise({
|
||||
isFormLocked,
|
||||
exercise,
|
||||
}: {
|
||||
replies: { [index: number]: string }[];
|
||||
setReplies: Dispatch<SetStateAction<{ [index: number]: string }[]>>;
|
||||
replies: Map<string, string>[];
|
||||
setReplies: Dispatch<SetStateAction<Map<string, string>[]>>;
|
||||
isFormLocked: boolean;
|
||||
exercise: FillInBlanksQuestion[];
|
||||
}) {
|
||||
@ -25,7 +23,10 @@ export function TypeInBlanksExercise({
|
||||
return <p key={pieceKey}>{pieceValue}</p>;
|
||||
}
|
||||
|
||||
const reply = replies[index][i];
|
||||
const replyMap = replies[index] as
|
||||
| Map<string, string>
|
||||
| undefined;
|
||||
const reply = replyMap?.get(pieceKey);
|
||||
const isCorrect =
|
||||
reply !== undefined && reply !== null
|
||||
? item.check(pieceKey, reply)
|
||||
@ -34,16 +35,21 @@ export function TypeInBlanksExercise({
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
style={{ width: "10rem" }}
|
||||
className={`basic ${
|
||||
isFormLocked ? (isCorrect ? "success" : "error") : ""
|
||||
}`}
|
||||
key={pieceKey}
|
||||
disabled={isFormLocked}
|
||||
value={replies[index][i]}
|
||||
value={replyMap?.get(pieceKey) ?? ""}
|
||||
onChange={(e) => {
|
||||
setReplies((prev) => {
|
||||
const newReplies = [...prev];
|
||||
newReplies[index][i] = e.target.value;
|
||||
const newReplyMap = new Map(
|
||||
newReplies[index] ?? new Map()
|
||||
);
|
||||
newReplyMap.set(pieceKey, e.target.value);
|
||||
newReplies[index] = newReplyMap;
|
||||
return newReplies;
|
||||
});
|
||||
}}
|
||||
|
||||
@ -2,10 +2,10 @@ import { Paper } from "@mui/material";
|
||||
import TrueOrFalseExercise from "./true_or_false_exercise";
|
||||
import FillOrDragExercise from "./type_or_drag_exercise";
|
||||
import useViewModelContext from "@/features/activity_editor/view_model";
|
||||
import { MultipleChoiceExerciseForm } from "../multiple_choice_exercise_form";
|
||||
import { PairTextsWithImagesExerciseForm } from "../pair_texts_with_images_exercise_form";
|
||||
import { MultipleChoiceExerciseForm } from "./multiple_choice_exercise_form";
|
||||
import { PairTextsWithImagesExerciseForm } from "./pair_texts_with_images_exercise_form";
|
||||
|
||||
export default function Activity() {
|
||||
export default function ExerciseEditor() {
|
||||
const { activityType } = useViewModelContext()!;
|
||||
|
||||
return (
|
||||
@ -6,12 +6,12 @@ import {
|
||||
PhotoLibraryOutlined,
|
||||
} from "@mui/icons-material";
|
||||
import { useState } from "react";
|
||||
import useViewModelContext from "@/features/activity_editor/view_model";
|
||||
import { nanoid } from "nanoid";
|
||||
import { SimpleQuestion } from "@/core/models/entities/question";
|
||||
import { Fab } from "@mui/material";
|
||||
import { AltEditDialog } from "@/features/edit_dialog/index.alt";
|
||||
import { Testable } from "@/core/models/entities/testable";
|
||||
import useViewModelContext from "@/features/activity_editor/view_model";
|
||||
|
||||
interface ImageCard {
|
||||
question: string;
|
||||
@ -1,12 +1,12 @@
|
||||
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material";
|
||||
import styles from "../styles.module.scss";
|
||||
import useViewModelContext from "../../view_model";
|
||||
import Activity from "./activity";
|
||||
import { Activity as IActivity } from "@/core/models/entities/learning_unit";
|
||||
import { MediaTester } from "@/core/components/media_tester";
|
||||
import YouTube from "react-youtube";
|
||||
import { NextImageContainer } from "@/core/components/next_image_container";
|
||||
import getYouTubeID from "get-youtube-id";
|
||||
import ExerciseEditor from "./exercise_editor";
|
||||
|
||||
const activityTypeMap = {
|
||||
"true-false": "Doğru yanlış",
|
||||
@ -155,7 +155,7 @@ export default function EditorForm() {
|
||||
placeholder="ses.mp3"
|
||||
/>
|
||||
</section>
|
||||
<Activity />
|
||||
<ExerciseEditor />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -5,10 +5,7 @@ import { Activity } from "@/features/activity";
|
||||
import useViewModelContext from "../view_model";
|
||||
import { useMemo } from "react";
|
||||
import { Activity as IActivity } from "@/core/models/entities/learning_unit";
|
||||
import {
|
||||
FillInBlanksQuestion,
|
||||
TrueFalseQuestion,
|
||||
} from "@/core/models/entities/question";
|
||||
import { FillInBlanksQuestion } from "@/core/models/entities/question";
|
||||
import { ExerciseConverter } from "../services/exercise_converter";
|
||||
|
||||
export default function View() {
|
||||
@ -79,7 +76,7 @@ export default function View() {
|
||||
<div className={styles["content"]}>
|
||||
<EditorForm />
|
||||
<div className={styles["simple-container"]}>
|
||||
<Activity activity={activity} />
|
||||
<Activity closeActivity={() => {}} activity={activity} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,6 @@ import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||
import {
|
||||
DeleteOutline,
|
||||
DesignServices,
|
||||
RssFeed,
|
||||
WarningAmber,
|
||||
} from "@mui/icons-material";
|
||||
import { useAdminViewModelContext } from "../theme_page/view_model/context_providers/admin_view_model";
|
||||
@ -24,8 +23,7 @@ export function ThemeSideBar({
|
||||
// context state
|
||||
const { themeTitle, themeExplanation, themeImage, themeYoutubeVideoUrl } =
|
||||
useBaseViewModelContext()!;
|
||||
const { saveTheme, deleteTheme, publishChanges } =
|
||||
useAdminViewModelContext()!;
|
||||
const { saveTheme, deleteTheme } = useAdminViewModelContext()!;
|
||||
|
||||
// component state
|
||||
const [modified, setModified] = useState(false);
|
||||
@ -98,10 +96,6 @@ export function ThemeSideBar({
|
||||
>
|
||||
<header>
|
||||
<h3>Tema Editörü</h3>
|
||||
<button onClick={publishChanges} className="simple">
|
||||
<span>Değişiklikleri Yayınla</span>
|
||||
<RssFeed />
|
||||
</button>
|
||||
</header>
|
||||
<div className={"main"}>
|
||||
{modified && (
|
||||
|
||||
@ -14,7 +14,7 @@ export function AppBar({ home }: { home: "/admin" | "/" }) {
|
||||
<img src="/header-logo.png" alt="" />
|
||||
</Link>
|
||||
<nav>
|
||||
<a className="simple" href="#">
|
||||
<a className="simple" href={`${home}#temalar`}>
|
||||
Temalar
|
||||
</a>
|
||||
<a
|
||||
|
||||
@ -13,7 +13,7 @@ export function ThemesSection({
|
||||
createNewThemeButton?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<article className={styles["themes"]}>
|
||||
<article id="temalar" className={styles["themes"]}>
|
||||
<div>
|
||||
<h4>Temel Lazca</h4>
|
||||
<section aria-label="temalar">
|
||||
|
||||
@ -37,5 +37,4 @@ export interface AdminViewModel {
|
||||
youtubeVideoUrl: string;
|
||||
}) => Promise<void>;
|
||||
deleteTheme: () => Promise<void>;
|
||||
publishChanges: () => Promise<void>;
|
||||
}
|
||||
|
||||
@ -21,7 +21,9 @@ export default function ActivityDialog({
|
||||
maxWidth="md"
|
||||
scroll="body"
|
||||
>
|
||||
{activeActivity && <Activity activity={activeActivity} />}
|
||||
{activeActivity && (
|
||||
<Activity closeActivity={closeActivity} activity={activeActivity} />
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
@ -10,7 +10,9 @@ import { TabBar } from "./tab_bar";
|
||||
import { ReactNode } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const ActivityDialog = dynamic(() => import("./activity_dialog"));
|
||||
const ActivityDialog = dynamic(() => import("./activity_dialog"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
export function View({
|
||||
home,
|
||||
|
||||
@ -322,34 +322,6 @@ export function useAdminViewModel(): AdminViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
const publishChanges = async () => {
|
||||
setStalling(true);
|
||||
const resObj = await fetch(`/api/admin/temalar/${themeId}`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ type: "publishChanges" }),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const res = (await resObj.json()) as StatusResponse;
|
||||
setStalling(false);
|
||||
|
||||
if (res.status === "error") {
|
||||
setSnackbar({
|
||||
severity: res.status,
|
||||
message: res.message,
|
||||
visible: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setSnackbar({
|
||||
severity: res.status,
|
||||
message: res.message,
|
||||
visible: true,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
stalling,
|
||||
snackbar,
|
||||
@ -364,6 +336,5 @@ export function useAdminViewModel(): AdminViewModel {
|
||||
// theme actions
|
||||
saveTheme,
|
||||
deleteTheme,
|
||||
publishChanges,
|
||||
};
|
||||
}
|
||||
|
||||
@ -4,18 +4,14 @@ import { Theme } from "@/core/models/entities/learning_unit";
|
||||
import TP from "@/features/theme_page";
|
||||
|
||||
export default function ThemePage({ themeData }: { themeData: Theme }) {
|
||||
console.debug("ThemePage---", Date.now());
|
||||
|
||||
return <TP home="/" theme={Theme.from(themeData)} />;
|
||||
}
|
||||
|
||||
export async function getStaticProps(context: GetServerSidePropsContext) {
|
||||
console.debug("getStaticProps---", Date.now());
|
||||
console.log("/temalar/[theme] -> getStaticProps");
|
||||
const path = context.params as unknown as { theme: string };
|
||||
const themeRepository = new ThemeReposityImplementation();
|
||||
console.debug("getStaticProps-1--", Date.now());
|
||||
const themeData = await themeRepository.getThemeData(path.theme);
|
||||
console.debug("getStaticProps-2--", Date.now());
|
||||
|
||||
return {
|
||||
props: {
|
||||
@ -26,11 +22,8 @@ export async function getStaticProps(context: GetServerSidePropsContext) {
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
console.debug("getStaticPaths---", Date.now());
|
||||
const themeRepository = new ThemeReposityImplementation();
|
||||
console.debug("getStaticPaths-1--", Date.now());
|
||||
const result = await themeRepository.getThemeIds();
|
||||
console.debug("getStaticPaths-2--", Date.now());
|
||||
|
||||
if (result.status === "success" && result.data) {
|
||||
const themePaths = result.data.map((item) => ({ params: { theme: item } }));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user