diff --git a/src/config/analytics.ts b/src/config/analytics.ts new file mode 100644 index 0000000..7e4a0c3 --- /dev/null +++ b/src/config/analytics.ts @@ -0,0 +1,5 @@ +export enum Event { + StartTest = 'start_test', + FinishTest = 'finish_test', + SelectAnswer = 'select_answer', +} diff --git a/src/features/QualificationPage/features/TestPage/TestPage.tsx b/src/features/QualificationPage/features/TestPage/TestPage.tsx index 11c05fd..fbb487d 100644 --- a/src/features/QualificationPage/features/TestPage/TestPage.tsx +++ b/src/features/QualificationPage/features/TestPage/TestPage.tsx @@ -41,7 +41,7 @@ const TestPage = ({ questions, suggestions, qualification }: TestPageProps) => { } ${polishPlurals('pytanie', 'pytania', 'pytań', questions.length)}`} /> - + {suggestions.length > 0 && } ); }; diff --git a/src/features/QualificationPage/features/TestPage/components/Test/Navigation.tsx b/src/features/QualificationPage/features/TestPage/components/Test/Navigation.tsx index f6998ef..bca7e86 100644 --- a/src/features/QualificationPage/features/TestPage/components/Test/Navigation.tsx +++ b/src/features/QualificationPage/features/TestPage/components/Test/Navigation.tsx @@ -59,7 +59,7 @@ const Navigation = ({ Zakończ test )} - {isLastQuestion && reviewMode && ( + {reviewMode && ( diff --git a/src/features/QualificationPage/features/TestPage/components/Test/Question.tsx b/src/features/QualificationPage/features/TestPage/components/Test/Question.tsx index 8a65141..588e4de 100644 --- a/src/features/QualificationPage/features/TestPage/components/Test/Question.tsx +++ b/src/features/QualificationPage/features/TestPage/components/Test/Question.tsx @@ -13,7 +13,7 @@ import ImageWrapper from './ImageWrapper'; export interface QuestionProps { question: QuestionT; answer: Answer; - onChangeAnswer: (answer: Answer) => void; + onSelectAnswer: (answer: Answer) => void; reviewMode: boolean; } @@ -22,7 +22,7 @@ const ANSWERS = Object.values(Answer); const Question = ({ question, answer, - onChangeAnswer, + onSelectAnswer, reviewMode, }: QuestionProps) => { const classes = useStyles(); @@ -86,7 +86,7 @@ const Question = ({ : 'outlined' } fullWidth - onClick={() => onChangeAnswer(a)} + onClick={() => onSelectAnswer(a)} color={'primary'} > diff --git a/src/features/QualificationPage/features/TestPage/components/Test/Test.tsx b/src/features/QualificationPage/features/TestPage/components/Test/Test.tsx index 22c9673..4e6eb2c 100644 --- a/src/features/QualificationPage/features/TestPage/components/Test/Test.tsx +++ b/src/features/QualificationPage/features/TestPage/components/Test/Test.tsx @@ -1,26 +1,28 @@ -import { useState, useRef } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { useUpdateEffect } from 'react-use'; import clsx from 'clsx'; import { usePrompt } from 'libs/hooks'; import { Answer, - Qualification, - Question as QuestionT, createClient, + Qualification, Query, + Question as QuestionT, } from 'libs/graphql'; +import { Event } from 'config/analytics'; +import gtag from 'utils/gtag'; import { QUERY_GENERATE_TEST_SIMILAR_QUALIFICATIONS } from '../../queries'; import { QueryGenerateTestSimilarQualificationsArgs } from '../../types'; import { makeStyles } from '@material-ui/core/styles'; import { + AppBar, + Box, Container, Paper, Tab, - Typography, Tabs, - AppBar, - Box, + Typography, } from '@material-ui/core'; import Section from 'common/Section/Section'; import TabPanel from './TabPanel'; @@ -47,6 +49,20 @@ const Test = ({ initialQuestions, qualification }: TestProps) => { const [endedAt, setEndedAt] = useState(new Date()); const classes = useStyles(); usePrompt(!reviewMode); + const analyticsParams = useMemo( + () => ({ + qualificationID: qualification.id.toString(), + questions: questions.length.toString(), + }), + [qualification, questions] + ); + useEffect(() => { + gtag( + 'event', + reviewMode ? Event.FinishTest : Event.StartTest, + analyticsParams + ); + }, [reviewMode, analyticsParams]); useUpdateEffect(() => { if (headingRef.current?.scrollIntoView) { headingRef.current?.scrollIntoView({ @@ -74,6 +90,20 @@ const Test = ({ initialQuestions, qualification }: TestProps) => { setReviewMode(false); }; + const handleSelectAnswer = (index: number, newAnswer: Answer) => { + setSelectedAnswers(answers => + answers.map((oldAnswer, index2) => + index2 === index ? newAnswer : oldAnswer + ) + ); + gtag('event', Event.SelectAnswer, { + qualificationID: analyticsParams.qualificationID, + questionID: questions[index].id.toString(), + answer: newAnswer, + correct: questions[index].correctAnswer === newAnswer ? '1' : '0', + }); + }; + const handleReset = async () => { try { setIsFetching(true); @@ -97,7 +127,6 @@ const Test = ({ initialQuestions, qualification }: TestProps) => { setCurrentTab(currentTab => currentTab + 1); setReviewMode(true); }; - return (
{isFetching && } @@ -150,13 +179,7 @@ const Test = ({ initialQuestions, qualification }: TestProps) => { - setSelectedAnswers(answers => - answers.map((oldAnswer, index2) => - index2 === index ? newAnswer : oldAnswer - ) - ) - } + onSelectAnswer={answer => handleSelectAnswer(index, answer)} reviewMode={reviewMode} /> diff --git a/src/utils/gtag.ts b/src/utils/gtag.ts new file mode 100644 index 0000000..f702ec6 --- /dev/null +++ b/src/utils/gtag.ts @@ -0,0 +1,19 @@ +import { Event } from 'config/analytics'; + +type GTagFN = ( + type: 'event', + event: Event, + params: { [key: string]: string } +) => void; + +interface customWindow extends Window { + gtag: GTagFN; +} + +declare const window: customWindow; + +const gtag: GTagFN = (t, event, params) => { + window.gtag(t, event, params); +}; + +export default gtag;