From 768a1fc0d91bb201febdd197e302860fc2d55bfe Mon Sep 17 00:00:00 2001 From: Suvodip Date: Fri, 2 Aug 2024 18:19:11 +0530 Subject: [PATCH] s1 --- app/components/QuizHeader.jsx | 13 +++ app/routes/quiz._index.tsx | 163 ++++++++++++++++++++++++++++ app/routes/quiz.result.tsx | 168 +++++++++++++++++++++++++++++ app/routes/quiz2.tsx | 130 ---------------------- app/routes/{quiz.tsx => quiz3.tsx} | 2 +- public/assets/custom-radio.css | 24 +++++ tsconfig.json | 2 +- 7 files changed, 370 insertions(+), 132 deletions(-) create mode 100644 app/components/QuizHeader.jsx create mode 100644 app/routes/quiz._index.tsx create mode 100644 app/routes/quiz.result.tsx delete mode 100644 app/routes/quiz2.tsx rename app/routes/{quiz.tsx => quiz3.tsx} (98%) create mode 100644 public/assets/custom-radio.css diff --git a/app/components/QuizHeader.jsx b/app/components/QuizHeader.jsx new file mode 100644 index 0000000..2dd0533 --- /dev/null +++ b/app/components/QuizHeader.jsx @@ -0,0 +1,13 @@ +export default function QuizHeader(){ + return( +
+
+

+
+

Take an AI Generative Quiz

+

Convert any text into an interactive quiz session

+
+
+
+ ) +} \ No newline at end of file diff --git a/app/routes/quiz._index.tsx b/app/routes/quiz._index.tsx new file mode 100644 index 0000000..cd86ab3 --- /dev/null +++ b/app/routes/quiz._index.tsx @@ -0,0 +1,163 @@ +import React, { useState, useEffect } from "react"; +import '../../public/assets/custom-radio.css' +import QuizHeader from '~/components/QuizHeader' + +interface Questiondata { + questionId: number; + questionText: string; + option1: string; + option2: string; + option3: string; + option4: string; + correctAnswer: string; + quizId: string | null; + moduleId: string; +} + +interface Answerdata { + questionId: number; + selectedOption: number; +} + +export default function QuizIndex() { + const [questionData, setQuestionsData] = useState([]); + const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0); + const [selectedOption, setSelectedOption] = useState(null); + const [answers, setAnswers] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [timeLeft, setTimeLeft] = useState(120); // 120 seconds timer + const [newQuizIds, setNewQuizIds] = useState(); + useEffect(() => { + fetch(`https://api.teachertrainingkolkata.in/api/question-list`) + .then(res => { + if (!res.ok) { + throw new Error('Network response was not ok'); + } + return res.json(); + }) + .then(data => { + console.log('Question Data', data); + setQuestionsData(data); + setNewQuizIds(data[0].newQuizId) + setLoading(false); + }) + .catch(error => { + console.error('An error occurred', error); + setError(error); + setLoading(false); + }); + }, []); + + useEffect(() => { + if (timeLeft > 0) { + const timerId = setInterval(() => setTimeLeft(timeLeft - 1), 1000); + return () => clearInterval(timerId); + } else { + handleSubmit(); + } + }, [timeLeft]); + + if (loading) { + return
Loading...
; + } + + if (error) { + return
Error: {error.message}
; + } + + const handleOptionChange = (event: React.ChangeEvent) => { + setSelectedOption(parseInt(event.target.value)); + }; + + const handleNextQuestion = () => { + if (selectedOption !== null) { + const newAnswer = { + questionId: questionData[currentQuestionIndex].questionId, + selectedOption: selectedOption, + quizId: newQuizIds + }; + setAnswers([...answers, newAnswer]); + setSelectedOption(null); + setCurrentQuestionIndex((prevIndex) => (prevIndex + 1) % questionData.length); + console.log([...answers, newAnswer]); + } else { + alert("Please select an option before proceeding to the next question."); + } + }; + + const handleSubmit = () => { + if (selectedOption !== null) { + const newAnswer = { + questionId: questionData[currentQuestionIndex].questionId, + selectedOption: selectedOption, + quizId: newQuizIds + }; + const finalAnswers = [...answers, newAnswer]; + setAnswers(finalAnswers); + console.log('Console Answers ', finalAnswers); + const apiUrl = 'https://api.teachertrainingkolkata.in/api/save-quiz-response'; + fetch(apiUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(finalAnswers) + }) + .then(response => response.json()) + .then(data => { + if(data.success === true){ + console.log('Find Success Message True') + window.location.href = `/quiz/result?id=${newQuizIds}` + } + console.log('Success:', data); + }) + .catch((error) => { + console.error('Error:', error); + }); + } else { + alert("Please select an option before submitting the quiz."); + } + }; + + const currentQuestion = questionData[currentQuestionIndex]; + + return ( +
+ +

Time left: {timeLeft} seconds

+
+
+
+

{`Q${currentQuestion.questionId}. ${currentQuestion.questionText}`}

+
+ + + + +
+
+
+
+
+ {currentQuestionIndex < questionData.length - 1 ? ( + + ) : ( + + )} +
+
+ ); +} diff --git a/app/routes/quiz.result.tsx b/app/routes/quiz.result.tsx new file mode 100644 index 0000000..5e4b8b7 --- /dev/null +++ b/app/routes/quiz.result.tsx @@ -0,0 +1,168 @@ +import React, { useState, useEffect } from "react"; +import QuizHeader from '~/components/QuizHeader'; + +interface ResultData { + totalQuestions: number; + correctAnswers: number; + message: string; + +} +let performersData = [ + { + id: "1", + name: "Eiden", + score: "48/50", + points: "999", + rank: "1", + program: "Graduate Program", + avatar: "/assets/avatar1.png" + }, + { + id: "2", + name: "Jackson", + score: "45/50", + points: "997", + rank: "2", + program: "Graduate Program", + avatar: "/assets/avatar2.png" + }, + { + id: "3", + name: "Emma Aria", + score: "43/50", + points: "994", + rank: "3", + program: "Graduate Program", + avatar: "/assets/avatar3.png" + }, + { + id: "4", + name: "John Doe", + score: "40/50", + points: "990", + rank: "4", + program: "Graduate Program", + avatar: "/assets/avatar4.png" + }, + { + id: "5", + name: "Jane Cooper", + score: "37/50", + points: "987", + rank: "5", + program: "Graduate Program", + avatar: "/assets/avatar5.png" + }, + { + id: "6", + name: "John Doe", + score: "35/50", + points: "982", + rank: "6", + program: "Graduate Program", + avatar: "/assets/avatar6.png" + }, + { + id: "7", + name: "Alice", + score: "33/50", + points: "980", + rank: "7", + program: "Graduate Program", + avatar: "/assets/avatar1.png" + }, + { + id: "8", + name: "Bob", + score: "32/50", + points: "978", + rank: "8", + program: "Graduate Program", + avatar: "/assets/avatar2.png" + }, + { + id: "9", + name: "Charlie", + score: "30/50", + points: "975", + rank: "9", + program: "Graduate Program", + avatar: "/assets/avatar3.png" + }, + { + id: "10", + name: "Diana", + score: "28/50", + points: "972", + rank: "10", + program: "Graduate Program", + avatar: "/assets/avatar4.png" + } +]; +export default function QuizResult(){ + const [resultData, setResultData] = useState(null); + + useEffect(() => { + let urlParams = new URLSearchParams(window.location.search); + let quizIdValue = urlParams.get('id'); + console.log(quizIdValue); + + fetch(`https://api.teachertrainingkolkata.in/api/quizresult-aftersubmit?id=${quizIdValue}`) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + console.log(data.totalQuestions); + setResultData(data); + }) + .catch(error => { + console.error('There was a problem with the fetch operation:', error); + }); + }, []); // Empty dependency array to run only once on mount + + return ( +
+ + +
+ +
+ + {resultData && ( +
+

{`You scored ${resultData.correctAnswers}/${resultData.totalQuestions}`}

+

{resultData.message}

+
+ )} +  Another Quiz +
+

Top Performers of this Quiz

+
+ { + performersData.map((data) => ( +
+
+

# {data.id}

+ +
+

{data.name}

+

{data.program}

+
+
+
+ +

{data.score}

+
+
+ )) + } + + +
+
+
+ ) +} \ No newline at end of file diff --git a/app/routes/quiz2.tsx b/app/routes/quiz2.tsx deleted file mode 100644 index 3d684a4..0000000 --- a/app/routes/quiz2.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import React, { useState, useEffect } from "react"; - -interface Questiondata { - questionId: number; - questionText: string; - option1: string; - option2: string; - option3: string; - option4: string; - correctAnswer: string; - quizId: string | null; - moduleId: string; -} - -interface Answerdata { - questionId: number; - selectedOption: string; -} - -export default function QuizIndex() { - const [questionData, setQuestionsData] = useState([]); - const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0); - const [selectedOption, setSelectedOption] = useState(''); - const [answers, setAnswers] = useState([]); - const [loading, setLoading] = useState(true); // Set to true initially to show loading - const [error, setError] = useState(null); - - useEffect(() => { - fetch(`https://api.teachertrainingkolkata.in/api/question-list`) - .then(res => { - if (!res.ok) { - throw new Error('Network response was not ok'); - } - return res.json(); - }) - .then(data => { - console.log('Question Data', data); - setQuestionsData(data); - setLoading(false); - }) - .catch(error => { - console.error('An error occurred', error); - setError(error); - setLoading(false); - }); - }, []); - - if (loading) { - return
Loading...
; - } - - if (error) { - return
Error: {error.message}
; - } - - const handleOptionChange = (event: React.ChangeEvent) => { - setSelectedOption(event.target.value); - }; - - const handleNextQuestion = () => { - setAnswers([...answers, { - questionId: questionData[currentQuestionIndex].questionId, - selectedOption: selectedOption - }]); - console.log(answers); - setSelectedOption(''); - setCurrentQuestionIndex((prevIndex) => (prevIndex + 1) % questionData.length); - }; - - const currentQuestion = questionData[currentQuestionIndex]; - - return ( -
-
-
-
-

#{currentQuestion.questionId} {currentQuestion.questionText}

-
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
- -
-
-
- ); -} diff --git a/app/routes/quiz.tsx b/app/routes/quiz3.tsx similarity index 98% rename from app/routes/quiz.tsx rename to app/routes/quiz3.tsx index c1c3c92..97c52f0 100644 --- a/app/routes/quiz.tsx +++ b/app/routes/quiz3.tsx @@ -226,7 +226,7 @@ console.log('Question Data 04',questionsData)
- {/*

{`Q${currentQuestion.id}. ${currentQuestion.question}`}

*/} +

{`Q${currentQuestion.id}. ${currentQuestion.question}`}

{/*
{currentQuestion.options.map((option, index) => (
diff --git a/public/assets/custom-radio.css b/public/assets/custom-radio.css new file mode 100644 index 0000000..83dff01 --- /dev/null +++ b/public/assets/custom-radio.css @@ -0,0 +1,24 @@ +.custom-radio { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 29.47px; + height: 29.47px; + border: 2px solid #ccc; + border-radius: 50%; + position: relative; +} + +/* Create the inner circle for checked state */ +.custom-radio:checked::before { + content: ''; + display: block; + width: 12.74px; + height: 12.74px; + background-color: #000; + border-radius: 50%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 9d87dd3..6b89a44 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "**/.server/**/*.tsx", "**/.client/**/*.ts", "**/.client/**/*.tsx" - ], +, "app/routes/quiz._index.tsx" ], "compilerOptions": { "lib": ["DOM", "DOM.Iterable", "ES2022"], "types": ["@remix-run/node", "vite/client"],