diff --git a/src/History.js b/src/History.js
index 9925f00..968224c 100644
--- a/src/History.js
+++ b/src/History.js
@@ -3,8 +3,10 @@ import { HomeRounded as HomeRoundedIcon, QuestionAnswerRounded as QuestionAnswer
import NavBar from "./NavBar";
import Button from "./Button";
import Footer from "./Footer";
+import LineChart from "./LineChart";
import { Link } from 'react-router-dom';
import "./css/History.css";
+import "./css/Chart.css";
export default class History extends Component {
constructor(props) {
@@ -37,14 +39,26 @@ export default class History extends Component {
componentDidMount() {
document.title = "History | Parandum";
+
+ const userSets = this.state.db
+ .collection("sets")
+ .where("owner", "==", this.state.user.uid)
+ .orderBy("title", "asc")
+ .get();
this.state.db.collection("progress")
.where("uid", "==", this.state.user.uid)
.orderBy("start_time", "desc")
.get()
- .then((querySnapshot) => {
+ .then(async (querySnapshot) => {
let complete = [];
let incomplete = [];
+ let totalCorrect = 0;
+ let totalIncorrect = 0;
+ let totalMarks = 0;
+ let totalTime = 0;
+ let totalPercentage = 0;
+ let userMarkHistory = [];
querySnapshot.docs.map((doc) => {
const data = doc.data();
@@ -52,14 +66,24 @@ export default class History extends Component {
id: doc.id,
setTitle: data.set_title,
switchLanguage: data.switch_language,
- percentage: (data.progress / data.questions.length * 100).toFixed(2),
- mark: (data.progress > 0 ? data.correct.length / data.progress * 100 : 0).toFixed(2),
+ percentageProgress: (data.progress / data.questions.length * 100).toFixed(2),
+ grade: (data.progress > 0 ? data.correct.length / data.progress * 100 : 0).toFixed(2),
mode: data.mode,
correct: data.correct.length,
progress: data.progress,
};
+ totalCorrect += data.correct.length;
+ totalIncorrect += data.incorrect.length;
+ totalMarks += data.progress;
+
if (data.duration !== null) {
+ totalPercentage += (data.correct.length / data.questions.length * 100);
+ totalTime += data.duration;
+ userMarkHistory.push({
+ x: new Date(data.start_time),
+ y: (data.correct.length / data.questions.length * 100),
+ });
return complete.push(pushData);
} else {
return incomplete.push(pushData);
@@ -69,6 +93,14 @@ export default class History extends Component {
this.setState({
progressHistoryComplete: complete,
progressHistoryIncomplete: incomplete,
+ totalCorrect: totalCorrect,
+ totalIncorrect: totalIncorrect,
+ totalMarks: totalMarks,
+ totalTime: totalTime,
+ totalPercentage: totalPercentage,
+ totalCompleteTests: complete.length,
+ userMarkHistory: userMarkHistory,
+ personalSetsCount: (await userSets).docs.length,
});
}).catch((error) => {
console.log(`Couldn't retrieve progress history: ${error}`);
@@ -93,6 +125,18 @@ export default class History extends Component {
});
}
+ msToTime = (time) => {
+ const localeData = {
+ minimumIntegerDigits: 2,
+ useGrouping: false,
+ };
+ const seconds = Math.floor((time / 1000) % 60).toLocaleString("en-GB", localeData);
+ const minutes = Math.floor((time / 1000 / 60) % 60).toLocaleString("en-GB", localeData);
+ const hours = Math.floor(time / 1000 / 60 / 60).toLocaleString("en-GB", localeData);
+
+ return `${hours}:${minutes}:${seconds}`;
+ }
+
render() {
return (
@@ -100,97 +144,132 @@ export default class History extends Component {
History
- {
- this.state.progressHistoryComplete.length > 0 || this.state.progressHistoryIncomplete.length > 0
- ?
- <>
- {
- this.state.progressHistoryIncomplete.length > 0 &&
-
-
Incomplete
-
-
Set
- Progress
- Mark
- Grade
- Mode
-
- {
- this.state.progressHistoryIncomplete.map((progressItem) =>
-
-
- {progressItem.setTitle}
- {
- progressItem.switchLanguage &&
-
- }
-
-
{progressItem.percentage}%
-
{progressItem.correct}/{progressItem.progress}
-
{progressItem.mark}%
-
- {
- progressItem.mode === "questions"
- ?
-
- :
-
- }
-
-
this.deleteProgress(progressItem.id)}
- icon={ }
- >
-
- )
- }
+
+
+
+
{this.state.totalCorrect}
+
correct
+
+
{this.state.totalIncorrect}
+
incorrect
+
+
+
{`${(this.state.totalPercentage / this.state.totalCompleteTests).toFixed(2)}%`}
+
average
+
+
+
{this.msToTime(this.state.totalTime)}
+
total time
+
+
+
{this.state.totalCompleteTests}
+
tests completed
+
+
+
{this.state.personalSetsCount}
+
personal set{ this.state.personalSetsCount > 1 && "s"}
+
+
+
+ { this.state.userMarkHistory && this.state.userMarkHistory.length > 1 &&
+
}
+
{
- this.state.progressHistoryComplete.length > 0 &&
-
-
Completed
+ this.state.progressHistoryComplete.length > 0 || this.state.progressHistoryIncomplete.length > 0
+ ?
-
Set
- Progress
- Mark
- Grade
- Mode
-
- {
- this.state.progressHistoryComplete.map((progressItem) =>
-
-
- {progressItem.setTitle}
- {
- progressItem.switchLanguage &&
-
- }
-
-
{progressItem.percentage}%
-
{progressItem.correct}/{progressItem.progress}
-
{progressItem.mark}%
+ {
+ this.state.progressHistoryIncomplete.length > 0 &&
+
+
Incomplete
+
+
Set
+ Progress
+ Mark
+ Grade
+ Mode
+
{
- progressItem.mode === "questions"
- ?
-
- :
-
+ this.state.progressHistoryIncomplete.map((progressItem) =>
+
+
+ {progressItem.setTitle}
+ {
+ progressItem.switchLanguage &&
+
+ }
+
+
{progressItem.percentageProgress}%
+
{progressItem.correct}/{progressItem.progress}
+
{progressItem.grade}%
+
+ {
+ progressItem.mode === "questions"
+ ?
+
+ :
+
+ }
+
+
this.deleteProgress(progressItem.id)}
+ icon={ }
+ >
+
+ )
}
- )
- }
-
+ }
+ {
+ this.state.progressHistoryComplete.length > 0 &&
+
+
Completed
+
+
Set
+ Progress
+ Mark
+ Grade
+ Mode
+
+ {
+ this.state.progressHistoryComplete.map((progressItem) =>
+
+
+ {progressItem.setTitle}
+ {
+ progressItem.switchLanguage &&
+
+ }
+
+
{progressItem.percentageProgress}%
+
{progressItem.correct}/{progressItem.progress}
+
{progressItem.grade}%
+ {
+ progressItem.mode === "questions"
+ ?
+
+ :
+
+ }
+
+ )
+ }
+
+ }
+
+ :
+
+
You haven't done any tests yet.
+
}
- >
- :
-
You haven't done any tests yet.
- }
+
diff --git a/src/LineChart.js b/src/LineChart.js
new file mode 100644
index 0000000..068dd4c
--- /dev/null
+++ b/src/LineChart.js
@@ -0,0 +1,91 @@
+import React from 'react';
+import Chart from "react-apexcharts";
+
+export default function LineChart (props) {
+ const options = {
+ xaxis: {
+ type: "datetime",
+ },
+ yaxis: {
+ min: 0,
+ max: 100,
+ labels: {
+ formatter: (value) => `${value.toFixed(0)}%`
+ },
+ tickAmount: 5,
+ },
+ chart: {
+ foreColor:
+ getComputedStyle(
+ document.querySelector("#root > div")
+ ).getPropertyValue("--text-color")
+ .trim(),
+ toolbar: {
+ show: false,
+ },
+ fontFamily: "Hind, sans-serif",
+ offsetX: -15,
+ zoom: {
+ enabled: false,
+ },
+ },
+ colors: [
+ getComputedStyle(
+ document.querySelector("#root > div")
+ ).getPropertyValue("--primary-color")
+ .trim()
+ ],
+ tooltip: {
+ theme: "dark",
+ x: {
+ show: false,
+ },
+ y: {
+ show: false,
+ },
+ },
+ stroke: {
+ width: 3,
+ },
+ grid: {
+ borderColor: getComputedStyle(
+ document.querySelector("#root > div")
+ ).getPropertyValue("--overlay-color")
+ .trim(),
+ xaxis: {
+ lines: {
+ show: true
+ }
+ },
+ },
+ markers: {
+ size: 1
+ },
+ responsive: [{
+ breakpoint: 600,
+ options: {
+ chart: {
+ height: "200px",
+ },
+ },
+ }],
+ };
+ const series = [
+ {
+ name: "",
+ data: props.data,
+ }
+ ];
+
+ return (
+ <>
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/src/Progress.js b/src/Progress.js
index 68e9420..04ff357 100644
--- a/src/Progress.js
+++ b/src/Progress.js
@@ -7,9 +7,11 @@ import LinkButton from "./LinkButton";
import Error404 from "./Error404";
import SettingsContent from "./SettingsContent";
import Footer from "./Footer";
+import LineChart from './LineChart';
import "./css/PopUp.css";
import "./css/Progress.css";
+import "./css/Chart.css";
export default withRouter(class Progress extends React.Component {
constructor(props) {
@@ -60,6 +62,7 @@ export default withRouter(class Progress extends React.Component {
themeInput: this.props.theme,
setIds: [],
attemptNumber: 1,
+ attemptHistory: {},
};
let isMounted = true;
@@ -145,6 +148,12 @@ export default withRouter(class Progress extends React.Component {
.get()
.then((querySnapshot) => {
newState.attemptNumber = querySnapshot.docs.map((doc) => doc.id).indexOf(this.props.match.params.progressId) + 1;
+ if (newState.attemptNumber > 1)
+ newState.attemptHistory = querySnapshot.docs.filter((doc) => doc.data().duration !== null)
+ .map((doc) => ({
+ x: new Date(doc.data().start_time),
+ y: (doc.data().correct.length / doc.data().questions.length * 100),
+ }));
}));
if (incorrectAnswers.length > 0) {
@@ -182,6 +191,11 @@ export default withRouter(class Progress extends React.Component {
this.setState(newState, () => {
if (!setDone) this.answerInput.focus()
});
+
+ this.props.logEvent("select_content", {
+ content_type: "progress",
+ item_id: this.props.match.params.progressId,
+ });
}
componentWillUnmount() {
@@ -310,8 +324,13 @@ export default withRouter(class Progress extends React.Component {
.orderBy("start_time")
.get()
.then((querySnapshot) => {
- console.log(querySnapshot);
newState.attemptNumber = querySnapshot.docs.map((doc) => doc.id).indexOf(this.props.match.params.progressId) + 1;
+ if (newState.attemptNumber > 1)
+ newState.attemptHistory = querySnapshot.docs.filter((doc) => doc.data().duration !== null)
+ .map((doc) => ({
+ x: new Date(doc.data().start_time),
+ y: (doc.data().correct.length / doc.data().questions.length * 100),
+ }));
}));
}
@@ -517,8 +536,14 @@ export default withRouter(class Progress extends React.Component {
>
}
- {/* TODO: provide the attempt number -- .get() where array-contains-all array of setIds from original sets? would mean a new field in db and adjusting cloud fns again */}
-
+
+ {this.state.attemptNumber > 1 &&
+ <>
+ History
+
+ >
+ }
+