commit
46e122913f
5
src/config/analytics.ts
Normal file
5
src/config/analytics.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export enum Event {
|
||||||
|
StartTest = 'start_test',
|
||||||
|
FinishTest = 'finish_test',
|
||||||
|
SelectAnswer = 'select_answer',
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ const TestPage = ({ questions, suggestions, qualification }: TestPageProps) => {
|
||||||
} ${polishPlurals('pytanie', 'pytania', 'pytań', questions.length)}`}
|
} ${polishPlurals('pytanie', 'pytania', 'pytań', questions.length)}`}
|
||||||
/>
|
/>
|
||||||
<Test initialQuestions={questions} qualification={qualification} />
|
<Test initialQuestions={questions} qualification={qualification} />
|
||||||
<Suggestions suggestions={suggestions} />
|
{suggestions.length > 0 && <Suggestions suggestions={suggestions} />}
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,7 +59,7 @@ const Navigation = ({
|
||||||
Zakończ test
|
Zakończ test
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{isLastQuestion && reviewMode && (
|
{reviewMode && (
|
||||||
<Button startIcon={<RefreshIcon />} onClick={onReset}>
|
<Button startIcon={<RefreshIcon />} onClick={onReset}>
|
||||||
Rozpocznij od nowa
|
Rozpocznij od nowa
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -13,7 +13,7 @@ import ImageWrapper from './ImageWrapper';
|
||||||
export interface QuestionProps {
|
export interface QuestionProps {
|
||||||
question: QuestionT;
|
question: QuestionT;
|
||||||
answer: Answer;
|
answer: Answer;
|
||||||
onChangeAnswer: (answer: Answer) => void;
|
onSelectAnswer: (answer: Answer) => void;
|
||||||
reviewMode: boolean;
|
reviewMode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ const ANSWERS = Object.values(Answer);
|
||||||
const Question = ({
|
const Question = ({
|
||||||
question,
|
question,
|
||||||
answer,
|
answer,
|
||||||
onChangeAnswer,
|
onSelectAnswer,
|
||||||
reviewMode,
|
reviewMode,
|
||||||
}: QuestionProps) => {
|
}: QuestionProps) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
@ -86,7 +86,7 @@ const Question = ({
|
||||||
: 'outlined'
|
: 'outlined'
|
||||||
}
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
onClick={() => onChangeAnswer(a)}
|
onClick={() => onSelectAnswer(a)}
|
||||||
color={'primary'}
|
color={'primary'}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
import { useState, useRef } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useUpdateEffect } from 'react-use';
|
import { useUpdateEffect } from 'react-use';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { usePrompt } from 'libs/hooks';
|
import { usePrompt } from 'libs/hooks';
|
||||||
import {
|
import {
|
||||||
Answer,
|
Answer,
|
||||||
Qualification,
|
|
||||||
Question as QuestionT,
|
|
||||||
createClient,
|
createClient,
|
||||||
|
Qualification,
|
||||||
Query,
|
Query,
|
||||||
|
Question as QuestionT,
|
||||||
} from 'libs/graphql';
|
} from 'libs/graphql';
|
||||||
|
import { Event } from 'config/analytics';
|
||||||
|
import gtag from 'utils/gtag';
|
||||||
import { QUERY_GENERATE_TEST_SIMILAR_QUALIFICATIONS } from '../../queries';
|
import { QUERY_GENERATE_TEST_SIMILAR_QUALIFICATIONS } from '../../queries';
|
||||||
import { QueryGenerateTestSimilarQualificationsArgs } from '../../types';
|
import { QueryGenerateTestSimilarQualificationsArgs } from '../../types';
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
import {
|
import {
|
||||||
|
AppBar,
|
||||||
|
Box,
|
||||||
Container,
|
Container,
|
||||||
Paper,
|
Paper,
|
||||||
Tab,
|
Tab,
|
||||||
Typography,
|
|
||||||
Tabs,
|
Tabs,
|
||||||
AppBar,
|
Typography,
|
||||||
Box,
|
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import Section from 'common/Section/Section';
|
import Section from 'common/Section/Section';
|
||||||
import TabPanel from './TabPanel';
|
import TabPanel from './TabPanel';
|
||||||
|
@ -47,6 +49,20 @@ const Test = ({ initialQuestions, qualification }: TestProps) => {
|
||||||
const [endedAt, setEndedAt] = useState(new Date());
|
const [endedAt, setEndedAt] = useState(new Date());
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
usePrompt(!reviewMode);
|
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(() => {
|
useUpdateEffect(() => {
|
||||||
if (headingRef.current?.scrollIntoView) {
|
if (headingRef.current?.scrollIntoView) {
|
||||||
headingRef.current?.scrollIntoView({
|
headingRef.current?.scrollIntoView({
|
||||||
|
@ -74,6 +90,20 @@ const Test = ({ initialQuestions, qualification }: TestProps) => {
|
||||||
setReviewMode(false);
|
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 () => {
|
const handleReset = async () => {
|
||||||
try {
|
try {
|
||||||
setIsFetching(true);
|
setIsFetching(true);
|
||||||
|
@ -97,7 +127,6 @@ const Test = ({ initialQuestions, qualification }: TestProps) => {
|
||||||
setCurrentTab(currentTab => currentTab + 1);
|
setCurrentTab(currentTab => currentTab + 1);
|
||||||
setReviewMode(true);
|
setReviewMode(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section>
|
<Section>
|
||||||
{isFetching && <FixedSpinner />}
|
{isFetching && <FixedSpinner />}
|
||||||
|
@ -150,13 +179,7 @@ const Test = ({ initialQuestions, qualification }: TestProps) => {
|
||||||
<Question
|
<Question
|
||||||
question={question}
|
question={question}
|
||||||
answer={selectedAnswers[index]}
|
answer={selectedAnswers[index]}
|
||||||
onChangeAnswer={newAnswer =>
|
onSelectAnswer={answer => handleSelectAnswer(index, answer)}
|
||||||
setSelectedAnswers(answers =>
|
|
||||||
answers.map((oldAnswer, index2) =>
|
|
||||||
index2 === index ? newAnswer : oldAnswer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
reviewMode={reviewMode}
|
reviewMode={reviewMode}
|
||||||
/>
|
/>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
19
src/utils/gtag.ts
Normal file
19
src/utils/gtag.ts
Normal file
|
@ -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;
|
Reference in New Issue
Block a user