@@ -12,7 +12,7 @@ | |||
font-size: 1.2rem; | |||
font-weight: 700; | |||
color: white; | |||
background-color: var(--teal); | |||
background-color: var(--red); | |||
margin: 0 auto; | |||
display: block; | |||
border: none; | |||
@@ -3,33 +3,100 @@ import styles from './Revise.module.scss'; | |||
import { Question } from "./question/Question"; | |||
import { Summary } from "./summary/Summary"; | |||
import { recollectionQuestions } from "../../services/recollectionquestions"; | |||
import { MongoShelfWord } from "../../shared/models/shelf"; | |||
interface WordWithShelfId extends MongoShelfWord { | |||
shelfId: string | |||
} | |||
import { recollectionQuestions, updateRecollectionQuestion } from "../../services/recollectionquestions"; | |||
import { MobileShelf } from "../../shared/models/shelf"; | |||
import { MobileUser } from "../../shared/models/user"; | |||
export const Revise: React.FC = () => { | |||
const [progressState, setProgressState] = useState<'INTRO' | 'QUESTION' | 'END'>('QUESTION'); | |||
const [questions, setQuestions] = useState<Array<WordWithShelfId>>([]); | |||
const [questions, setQuestions] = useState<Array<any>>([]); | |||
const [answeredQuestions, setAnsweredQuestion] = useState<Array<{ | |||
wordId: string, | |||
hasRecalled: boolean | |||
}>>([]); | |||
const [currentQuestion, setCurrentQuestion] = useState<number>(0); | |||
useEffect(() => { | |||
recollectionQuestions().then((response: any) => { | |||
setQuestions(response.data); | |||
let questions: Array<any> = response.data; | |||
const curatedQuestions: Array<any> = []; | |||
let allShelves: Array<MobileShelf> = []; | |||
const userProfile: MobileUser = JSON.parse(localStorage.getItem('userProfile') || ""); | |||
userProfile.categories.forEach(category => { | |||
category.shelves?.forEach((shelf) => { | |||
allShelves.push(shelf); | |||
}); | |||
}); | |||
questions.forEach((question) => { | |||
let index = allShelves.findIndex(shelf => shelf._id === question.shelfId); | |||
if (index !== undefined) { | |||
const word = allShelves[index].words?.find(word => word.word._id === question.word)?.word; | |||
if (word !== undefined) { | |||
curatedQuestions.push({ | |||
...question, | |||
word: word | |||
}) | |||
} | |||
} | |||
}); | |||
setQuestions(curatedQuestions); | |||
if (curatedQuestions.length === 0) { | |||
setProgressState('END'); | |||
} | |||
}, (e) => { | |||
window.alert("Failed to get questions"); | |||
console.log(e); | |||
}); | |||
}, []); | |||
return <section className={styles.revisePage}> | |||
{ progressState === 'QUESTION' && <div> | |||
<Question /> | |||
{ questions.map((question, index) => { | |||
return currentQuestion === index && <Question key={index} totalQuestions={questions.length} questionNumber={currentQuestion} | |||
word={question.word} | |||
selectOption={(flag) => { | |||
let temp = answeredQuestions; | |||
temp.push({ | |||
wordId: question.word._id, | |||
hasRecalled: flag, | |||
}); | |||
setAnsweredQuestion(temp); | |||
console.log(question) | |||
setTimeout(() => { | |||
if (currentQuestion < questions.length - 1) { | |||
setCurrentQuestion(currentQuestion + 1); | |||
} else { | |||
setProgressState('END'); | |||
} | |||
updateRecollectionQuestion(question.shelfId, question.word._id, flag); | |||
}, 200); | |||
}} /> | |||
}) } | |||
<button className={styles.finishButton} onClick={() => setProgressState('END')}> | |||
Finish | |||
Done | |||
</button> | |||
</div> } | |||
@@ -33,7 +33,7 @@ | |||
p { | |||
font-size: 1.2rem; | |||
font-weight: 500; | |||
color: var(--black); | |||
color: var(--grey); | |||
} | |||
.checkmark { | |||
@@ -1,43 +1,33 @@ | |||
import React from "react"; | |||
import React, { useState } from "react"; | |||
import styles from './Options.module.scss'; | |||
import { ReactComponent as CheckCircleIcon } from '../../../assets/icons/check.svg'; | |||
export const Options: React.FC = () => { | |||
return <ul className={styles.optionsHolder}> | |||
<li className={styles.active}> | |||
<p> | |||
Argentina & Leo Messi | |||
</p> | |||
<div className={styles.checkmark}> | |||
<CheckCircleIcon /> | |||
</div> | |||
</li> | |||
<li> | |||
<p> | |||
Brazil & Neymar | |||
</p> | |||
<div className={styles.checkmark}> | |||
</div> | |||
</li> | |||
type OwnProps = { | |||
options: Array<{ | |||
text: string, | |||
function:() => void, | |||
}> | |||
} | |||
<li> | |||
<p> | |||
Chile & Sanchez | |||
</p> | |||
<div className={styles.checkmark}> | |||
</div> | |||
</li> | |||
export const Options: React.FC<OwnProps> = (props) => { | |||
const [selectedOption, setSelectedOption] = useState<{ | |||
text: string, | |||
function:() => void, | |||
} | undefined>(); | |||
<li> | |||
<p> | |||
Mexico & Chicharito | |||
</p> | |||
<div className={styles.checkmark}> | |||
</div> | |||
</li> | |||
</ul>; | |||
return <ul className={styles.optionsHolder}> | |||
{ props.options.map((option, index) => { | |||
return <li key={index} className={selectedOption === option ? styles.active : ''} onClick={() => { | |||
option.function(); | |||
setSelectedOption(option); | |||
}}> | |||
<p> | |||
{ option.text } | |||
</p> | |||
{ selectedOption === option && <div className={styles.checkmark} > | |||
<CheckCircleIcon /> | |||
</div> } | |||
</li> | |||
}) } | |||
</ul>; | |||
} |
@@ -1,7 +1,7 @@ | |||
$common-width: calc(100% - 4rem); | |||
.questionHolder { | |||
height: calc(100vh - 8rem); | |||
height: calc(100vh - 6rem); | |||
padding-top: 2rem; | |||
overflow: auto; | |||
} | |||
@@ -76,4 +76,52 @@ $common-width: calc(100% - 4rem); | |||
.answerTypes { | |||
width: #{$common-width}; | |||
margin: 0 auto 2rem; | |||
} | |||
.meaning { | |||
width: $common-width; | |||
margin: 0 auto 2rem; | |||
list-style: none; | |||
position: relative; | |||
&::before { | |||
content: ''; | |||
left: 0; | |||
top: 0; | |||
width: 100%; | |||
height: 100%; | |||
background-color: var(--lighter-grey); | |||
position: absolute; | |||
border-radius: 5px; | |||
opacity: 0.95; | |||
transition: opacity 0.5s; | |||
} | |||
&.unblock { | |||
&::before { | |||
opacity: 0; | |||
} | |||
} | |||
li { | |||
margin-bottom: 1rem; | |||
} | |||
p { | |||
font-size: 14px; | |||
color: var(--light-grey); | |||
span { | |||
vertical-align: middle; | |||
} | |||
} | |||
} | |||
.caption { | |||
font-size: 14px; | |||
color: var(--light-grey); | |||
font-style: italic; | |||
width: $common-width; | |||
margin: 0 auto 2rem; | |||
} |
@@ -1,22 +1,48 @@ | |||
import React from "react"; | |||
import React, { useState } from "react"; | |||
import styles from './Question.module.scss'; | |||
import { ReactComponent as TimeIcon } from '../../../assets/icons/timer.svg'; | |||
import { Options } from "../options/Options"; | |||
import { Word } from "../../../shared/models/word"; | |||
type OwnProps = { | |||
questionNumber: number, | |||
totalQuestions: number, | |||
word: Word, | |||
selectOption: (hasRecalled: boolean) => void, | |||
} | |||
export const Question: React.FC<OwnProps> = (props) => { | |||
const [isMeaningShown, setShowMeaning] = useState<boolean>(false); | |||
export const Question: React.FC = () => { | |||
return <section className={styles.questionHolder}> | |||
<div className={styles.progressBarHolder}> | |||
<span className={styles.progressBar} style={{width: '60%'}}></span> | |||
<span className={styles.text}> 30 </span> | |||
<TimeIcon /> | |||
<span className={styles.progressBar} style={{width: (props.questionNumber / props.totalQuestions * 100) + '%'}}></span> | |||
{/* <span className={styles.text}> 30 </span> | |||
<TimeIcon /> */} | |||
</div> | |||
<h3 className={styles.questionCount}> Question 10/<span>10</span> </h3> | |||
<h3 className={styles.questionCount}> Question {props.questionNumber + 1} / <span> { props.totalQuestions } </span> </h3> | |||
<h3 className={styles.question}> Do you recall this word? <br /> <strong> { props.word.name } </strong> </h3> | |||
<ol className={styles.meaning + ' ' + (isMeaningShown ? styles.unblock : '')} | |||
onClick={() => setShowMeaning(true)}> | |||
{ props.word.grammaticalDetails.map((detail, index) => { | |||
return <li key={index}> | |||
<p> <span> - </span> { detail.description } </p> | |||
</li> | |||
}) } | |||
</ol> | |||
<h3 className={styles.question}> Who won Copa America 2021 and who was the Captian? </h3> | |||
{ !isMeaningShown && <p className={styles.caption}> Tap on the blocked section to see the meaning </p> } | |||
<section className={styles.answerTypes}> | |||
<Options /> | |||
<Options options={[{ | |||
text: 'Yes', | |||
function: () => props.selectOption(true) | |||
}, { | |||
text: 'No', | |||
function: () => props.selectOption(false) | |||
}]} /> | |||
</section> | |||
</section> | |||
} |