refactor: use types for props, not interfaces + update enum values + remove unnecessary useCallbacks from List.tsx

This commit is contained in:
Dawid Wysokiński 2021-11-01 17:17:38 +01:00
parent 1b673d1333
commit 66b72dcb77
Signed by: Kichiyaki
GPG Key ID: EF14026D247EB867
29 changed files with 149 additions and 139 deletions

View File

@ -5,27 +5,28 @@ import buildURL from 'utils/buildURL';
import { Linking, StyleSheet } from 'react-native'; import { Linking, StyleSheet } from 'react-native';
import { ActionSheet, Icon, NativeBase } from 'native-base'; import { ActionSheet, Icon, NativeBase } from 'native-base';
export interface MenuProps
extends Omit<NativeBase.Icon, 'onPress' | 'type' | 'name'> {}
const OPTIONS = ['Strona internetowa', 'Kontakt', 'Anuluj']; const OPTIONS = ['Strona internetowa', 'Kontakt', 'Anuluj'];
const WEBSITE_OPT_INDEX = 0; enum OptionIndex {
const CONTACT_OPT_INDEX = 1; WEBSITE,
const CANCEL_OPT_INDEX = OPTIONS.length - 1; CONTACT,
CANCEL,
}
export type MenuProps = Omit<NativeBase.Icon, 'onPress' | 'type' | 'name'>;
const Menu = ({ style, ...rest }: MenuProps) => { const Menu = ({ style, ...rest }: MenuProps) => {
const showMenu = () => { const showMenu = () => {
ActionSheet.show( ActionSheet.show(
{ {
options: OPTIONS, options: OPTIONS,
cancelButtonIndex: CANCEL_OPT_INDEX, cancelButtonIndex: OptionIndex.CANCEL,
}, },
index => { index => {
switch (index) { switch (index) {
case WEBSITE_OPT_INDEX: case OptionIndex.WEBSITE:
Linking.openURL(WEBSITE); Linking.openURL(WEBSITE);
break; break;
case CONTACT_OPT_INDEX: case OptionIndex.CONTACT:
Linking.openURL(buildURL('email', EMAIL)); Linking.openURL(buildURL('email', EMAIL));
break; break;
} }

View File

@ -1,7 +1,7 @@
export enum Event { export enum Event {
SaveQualification = 'save_qualification', SAVE_QUALIFICATION = 'save_qualification',
UnSaveQualification = 'unsave_qualification', UNSAVE_QUALIFICATION = 'unsave_qualification',
StartTest = 'start_test', START_TEST = 'start_test',
FinishTest = 'finish_test', FINISH_TEST = 'finish_test',
SelectAnswer = 'select_answer', SELECT_ANSWER = 'select_answer',
} }

View File

@ -1,6 +1,6 @@
export enum Screen { export enum Screen {
Home = 'HomeScreen', HOME = 'HomeScreen',
Test = 'TestScreen', TEST = 'TestScreen',
} }
export type TestScreenParams = { export type TestScreenParams = {
@ -9,6 +9,6 @@ export type TestScreenParams = {
}; };
export type AppStackParamList = { export type AppStackParamList = {
[Screen.Home]: undefined; [Screen.HOME]: undefined;
[Screen.Test]: TestScreenParams; [Screen.TEST]: TestScreenParams;
}; };

View File

@ -15,17 +15,20 @@ export const createClient = (
cache: new InMemoryCache(), cache: new InMemoryCache(),
link: ApolloLink.from([ link: ApolloLink.from([
onError(({ graphQLErrors, networkError }) => { onError(({ graphQLErrors, networkError }) => {
if (__DEV__) { if (!__DEV__) {
if (graphQLErrors) { return;
graphQLErrors.forEach(({ message, locations, path }) => }
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`, if (graphQLErrors) {
), graphQLErrors.forEach(({ message, locations, path }) =>
); console.log(
} `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
if (networkError) { ),
console.log(`[Network error]: ${networkError}`); );
} }
if (networkError) {
console.log(`[Network error]: ${networkError}`);
} }
}), }),
new HttpLink({ new HttpLink({

View File

@ -66,7 +66,7 @@ export default (variables /* : * */ = variable) => {
}, },
}, },
backgroundColor: backgroundColor:
Platform.OS === OS.Android ? variables.footerDefaultBg : undefined, Platform.OS === OS.ANDROID ? variables.footerDefaultBg : undefined,
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
flex: 1, flex: 1,

View File

@ -47,9 +47,9 @@ export default (variables /* : * */ = variable) => {
shadowOffset: null, shadowOffset: null,
shadowRadius: null, shadowRadius: null,
shadowOpacity: null, shadowOpacity: null,
paddingTop: platform === OS.Android ? StatusBar.currentHeight : undefined, paddingTop: platform === OS.ANDROID ? StatusBar.currentHeight : undefined,
height: height:
platform === OS.Android platform === OS.ANDROID
? variables.toolbarHeight + (StatusBar.currentHeight ?? 0) ? variables.toolbarHeight + (StatusBar.currentHeight ?? 0)
: variables.toolbarHeight, : variables.toolbarHeight,
}, },

View File

@ -97,7 +97,7 @@ export default (variables /* : * */ = variable) => {
paddingTop: paddingTop:
platform === OS.IOS ? variables.listItemPadding + 25 : undefined, platform === OS.IOS ? variables.listItemPadding + 25 : undefined,
paddingBottom: paddingBottom:
platform === OS.Android ? variables.listItemPadding + 20 : undefined, platform === OS.ANDROID ? variables.listItemPadding + 20 : undefined,
flexDirection: 'row', flexDirection: 'row',
borderColor: variables.listBorderColor, borderColor: variables.listBorderColor,
'NativeBase.Text': { 'NativeBase.Text': {

View File

@ -12,8 +12,8 @@ export default (variables /* : * */ = variable) => {
justifyContent: 'center', justifyContent: 'center',
'.scrollable': { '.scrollable': {
paddingHorizontal: 20, paddingHorizontal: 20,
flex: platform === OS.Android ? 0 : 1, flex: platform === OS.ANDROID ? 0 : 1,
minWidth: platform === OS.Android ? undefined : 60, minWidth: platform === OS.ANDROID ? undefined : 60,
}, },
'NativeBase.Text': { 'NativeBase.Text': {
color: variables.topTabBarTextColor, color: variables.topTabBarTextColor,

View File

@ -211,6 +211,6 @@ export type Variables = {
}; };
export enum OS { export enum OS {
Android = 'android', ANDROID = 'android',
IOS = 'ios', IOS = 'ios',
} }

View File

@ -1,19 +1,15 @@
import React, { useCallback, useState } from 'react'; import React, { PropsWithChildren, useCallback, useState } from 'react';
import { useEffectOnce, useUpdateEffect } from 'react-use'; import { useEffectOnce, useUpdateEffect } from 'react-use';
import { useAsyncStorage } from '@react-native-async-storage/async-storage'; import { useAsyncStorage } from '@react-native-async-storage/async-storage';
import analytics from '@react-native-firebase/analytics'; import analytics from '@react-native-firebase/analytics';
import { context as Context } from './context'; import { context as Context } from './context';
import { Event } from 'config/analytics'; import { Event } from 'config/analytics';
export interface SavedQualificationsProviderProps {
children?: React.ReactNode;
}
const ASYNC_STORAGE_KEY = 'saved_qualifications'; const ASYNC_STORAGE_KEY = 'saved_qualifications';
export const SavedQualificationsProvider = ({ export const SavedQualificationsProvider = ({
children, children,
}: SavedQualificationsProviderProps) => { }: PropsWithChildren<{}>) => {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [savedQualifications, setSavedQualifications] = useState<number[]>([]); const [savedQualifications, setSavedQualifications] = useState<number[]>([]);
const asyncStorage = useAsyncStorage(ASYNC_STORAGE_KEY); const asyncStorage = useAsyncStorage(ASYNC_STORAGE_KEY);
@ -54,7 +50,7 @@ export const SavedQualificationsProvider = ({
); );
analytics().logEvent( analytics().logEvent(
save ? Event.SaveQualification : Event.UnSaveQualification, save ? Event.SAVE_QUALIFICATION : Event.UNSAVE_QUALIFICATION,
{ {
id: id.toString(), id: id.toString(),
}, },

View File

@ -1,5 +1,5 @@
import 'react-native-gesture-handler'; import 'react-native-gesture-handler';
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useMemo, useRef } from 'react';
import { ApolloProvider } from '@apollo/client'; import { ApolloProvider } from '@apollo/client';
import RNBootSplash from 'react-native-bootsplash'; import RNBootSplash from 'react-native-bootsplash';
import { Root, StyleProvider } from 'native-base'; import { Root, StyleProvider } from 'native-base';
@ -18,8 +18,12 @@ const BaseApp = () => {
}; };
const App = () => { const App = () => {
const theme = useRef(createTheme(variables)).current; const theme = useMemo(() => {
const client = useRef(createClient(API_URI)).current; return createTheme(variables);
}, []);
const client = useMemo(() => {
return createClient(API_URI);
}, []);
return ( return (
<ApolloProvider client={client}> <ApolloProvider client={client}>

View File

@ -7,7 +7,7 @@ import Professions from './components/Professions/Professions';
const HomeScreen = () => { const HomeScreen = () => {
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const [mode, setMode] = useState(Mode.All); const [mode, setMode] = useState(Mode.ALL);
return ( return (
<Container> <Container>

View File

@ -5,9 +5,9 @@ import { Keyboard, StyleSheet, TextInput } from 'react-native';
import { Icon, Input, Item, Header as NBHeader, View } from 'native-base'; import { Icon, Input, Item, Header as NBHeader, View } from 'native-base';
import Menu from 'common/Menu/Menu'; import Menu from 'common/Menu/Menu';
export interface HeaderProps { export type HeaderProps = {
onSearch?: (search: string) => void; onSearch?: (search: string) => void;
} };
const Header = ({ onSearch }: HeaderProps) => { const Header = ({ onSearch }: HeaderProps) => {
const inputRef = useRef<Input>(null); const inputRef = useRef<Input>(null);

View File

@ -2,28 +2,28 @@ import React from 'react';
import { Button, Segment, Text } from 'native-base'; import { Button, Segment, Text } from 'native-base';
export enum Mode { export enum Mode {
All, ALL,
Saved, SAVED,
} }
export interface ModeSelectorProps { export type ModeSelectorProps = {
mode: Mode; mode: Mode;
onChangeMode: (mode: Mode) => void; onChangeMode: (mode: Mode) => void;
} };
const ModeSelector = ({ mode, onChangeMode }: ModeSelectorProps) => { const ModeSelector = ({ mode, onChangeMode }: ModeSelectorProps) => {
return ( return (
<Segment> <Segment>
<Button <Button
first first
onPress={() => onChangeMode(Mode.All)} onPress={() => onChangeMode(Mode.ALL)}
active={mode === Mode.All} active={mode === Mode.ALL}
> >
<Text allowFontScaling={false}>Wszystkie</Text> <Text allowFontScaling={false}>Wszystkie</Text>
</Button> </Button>
<Button <Button
onPress={() => onChangeMode(Mode.Saved)} onPress={() => onChangeMode(Mode.SAVED)}
active={mode === Mode.Saved} active={mode === Mode.SAVED}
> >
<Text allowFontScaling={false}>Zapisane</Text> <Text allowFontScaling={false}>Zapisane</Text>
</Button> </Button>

View File

@ -1,4 +1,4 @@
import React, { forwardRef, useCallback } from 'react'; import React, { forwardRef } from 'react';
import { import {
FlatList, FlatList,
@ -11,24 +11,20 @@ import ListEmpty from './ListEmpty';
import ListLoading from './ListLoading'; import ListLoading from './ListLoading';
export type Item = ListItemProps; export type Item = ListItemProps;
export interface ListProps export type ListProps = {
extends Pick<
FlatListProps<Item>,
'refreshing' | 'onRefresh' | 'contentContainerStyle'
> {
items: Item[]; items: Item[];
loading?: boolean; loading?: boolean;
} } & Pick<
FlatListProps<Item>,
'refreshing' | 'onRefresh' | 'contentContainerStyle'
>;
const noop = () => {}; const noop = () => {};
const keyExtractor = (item: ListItemProps) => item.id!;
const renderItem = ({ item }: { item: Item }) => <ListItem {...item} />;
const MyList = forwardRef<FlatList<Item>, ListProps>( const List = forwardRef<FlatList<Item>, ListProps>(
({ items, refreshing, onRefresh, loading, ...rest }: ListProps, ref) => { ({ items, refreshing, onRefresh, loading, ...rest }: ListProps, ref) => {
const renderItem = useCallback(({ item }: { item: Item }) => {
return <ListItem {...item} />;
}, []);
const keyExtractor = useCallback(item => item.id, []);
return ( return (
<FlatList <FlatList
data={items} data={items}
@ -61,4 +57,4 @@ const styles = StyleSheet.create({
}, },
}); });
export default MyList; export default List;

View File

@ -1,12 +1,11 @@
import React, { Fragment, useMemo, memo } from 'react'; import React, { Fragment, useMemo, memo } from 'react';
import { Icon, Left, ListItem, NativeBase, Right, Text } from 'native-base'; import { Icon, Left, ListItem, NativeBase, Right, Text } from 'native-base';
export interface ListItemProps export type ListItemProps = {
extends Pick<NativeBase.ListItem, 'itemDivider' | 'itemHeader'> {
onPress?: (id: string) => void; onPress?: (id: string) => void;
id?: string; id?: string;
text: string; text: string;
} } & Pick<NativeBase.ListItem, 'itemDivider' | 'itemHeader'>;
const MyListItem = ({ const MyListItem = ({
onPress, onPress,

View File

@ -4,25 +4,27 @@ import { Alert, Linking } from 'react-native';
import buildURL from 'utils/buildURL'; import buildURL from 'utils/buildURL';
import { EMAIL } from 'config/app'; import { EMAIL } from 'config/app';
export interface NetworkConnectionAlertProps { export type NetworkConnectionAlertProps = {
error?: ApolloError; error?: ApolloError;
} };
const NetworkConnectionAlert = ({ error }: NetworkConnectionAlertProps) => { const NetworkConnectionAlert = ({ error }: NetworkConnectionAlertProps) => {
useUpdateEffect(() => { useUpdateEffect(() => {
if (error && error.networkError) { if (!error || !error.networkError) {
Alert.alert( return;
'Problem z połączeniem',
'Prosimy o sprawdzenie połączenia z internetem / spróbowanie ponownie później. Przepraszamy za utrudnienia.',
[
{
text: 'Zgłoś problem',
onPress: () => Linking.openURL(buildURL('email', EMAIL)),
},
{ text: 'OK' },
],
);
} }
Alert.alert(
'Problem z połączeniem',
'Prosimy o sprawdzenie połączenia z internetem / spróbowanie ponownie później. Przepraszamy za utrudnienia.',
[
{
text: 'Zgłoś problem',
onPress: () => Linking.openURL(buildURL('email', EMAIL)),
},
{ text: 'OK' },
],
);
}, [error]); }, [error]);
return null; return null;

View File

@ -11,10 +11,10 @@ import List, { Item } from './List/List';
import QualificationModal from './QualificationModal'; import QualificationModal from './QualificationModal';
import NetworkConnectionAlert from './NetworkConnectionAlert'; import NetworkConnectionAlert from './NetworkConnectionAlert';
export interface ProfessionsProps { export type ProfessionsProps = {
mode: Mode; mode: Mode;
search: string; search: string;
} };
const ID_SEPARATOR = '.'; const ID_SEPARATOR = '.';
const getQualificationAndProfessionID = (str: string): [number, number] => { const getQualificationAndProfessionID = (str: string): [number, number] => {
@ -44,16 +44,21 @@ const Professions = ({ mode, search }: ProfessionsProps) => {
const [professionID, qualificationID] = getQualificationAndProfessionID( const [professionID, qualificationID] = getQualificationAndProfessionID(
id, id,
); );
const profession = professions.find(p => p.id === professionID); const profession = professions.find(p => p.id === professionID);
if (profession) { if (!profession) {
const qualification = profession.qualifications.find( return;
q => q.id === qualificationID,
);
if (qualification) {
setSelectedQualification(qualification);
setIsModalVisible(true);
}
} }
const qualification = profession.qualifications.find(
q => q.id === qualificationID,
);
if (!qualification) {
return;
}
setSelectedQualification(qualification);
setIsModalVisible(true);
}, },
[setIsModalVisible, setSelectedQualification, professions], [setIsModalVisible, setSelectedQualification, professions],
); );
@ -62,7 +67,9 @@ const Professions = ({ mode, search }: ProfessionsProps) => {
if (professionsLoading) { if (professionsLoading) {
return; return;
} }
let items: Item[] = []; let items: Item[] = [];
professions.forEach(profession => { professions.forEach(profession => {
const qualifications = profession.qualifications const qualifications = profession.qualifications
.filter( .filter(
@ -70,7 +77,7 @@ const Professions = ({ mode, search }: ProfessionsProps) => {
(!search || (!search ||
qualification.name.toLowerCase().includes(search) || qualification.name.toLowerCase().includes(search) ||
qualification.code.toLowerCase().includes(search)) && qualification.code.toLowerCase().includes(search)) &&
(mode === Mode.All || isSaved(qualification.id)), (mode === Mode.ALL || isSaved(qualification.id)),
) )
.map( .map(
(qualification): Item => { (qualification): Item => {
@ -83,18 +90,21 @@ const Professions = ({ mode, search }: ProfessionsProps) => {
}; };
}, },
); );
if (qualifications.length > 0) {
items = [ if (qualifications.length === 0) {
...items, return;
{
text: profession.name,
itemHeader: true,
itemDivider: true,
id: 'P' + profession.id,
} as Item,
...qualifications,
];
} }
items = [
...items,
{
text: profession.name,
itemHeader: true,
itemDivider: true,
id: 'P' + profession.id,
} as Item,
...qualifications,
];
}); });
setListItems(items); setListItems(items);

View File

@ -19,10 +19,9 @@ import {
} from 'native-base'; } from 'native-base';
import Modal, { ModalProps } from 'common/Modal/Modal'; import Modal, { ModalProps } from 'common/Modal/Modal';
export interface QualificationModalProps export type QualificationModalProps = {
extends Pick<ModalProps, 'visible' | 'onPressBackdrop'> {
qualification: Maybe<Qualification>; qualification: Maybe<Qualification>;
} } & Pick<ModalProps, 'visible' | 'onPressBackdrop'>;
const QualificationModal = ({ const QualificationModal = ({
qualification, qualification,
@ -81,7 +80,7 @@ const QualificationModal = ({
if (onPressBackdrop) { if (onPressBackdrop) {
onPressBackdrop(); onPressBackdrop();
} }
navigation.navigate(Screen.Test, { navigation.navigate(Screen.TEST, {
qualificationID: qualification?.id ?? 0, qualificationID: qualification?.id ?? 0,
limit: question, limit: question,
}); });

View File

@ -15,8 +15,8 @@ const AppStack = createStackNavigator<AppStackParamList>();
const AppScreens = () => ( const AppScreens = () => (
<AppStack.Navigator screenOptions={{ headerShown: false }}> <AppStack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name={Screen.Home} component={HomeScreen} /> <Stack.Screen name={Screen.HOME} component={HomeScreen} />
<Stack.Screen name={Screen.Test} component={TestScreen} /> <Stack.Screen name={Screen.TEST} component={TestScreen} />
</AppStack.Navigator> </AppStack.Navigator>
); );

View File

@ -15,9 +15,9 @@ import Suggestions from './components/Suggestions/Suggestions';
import Test from './components/Test/Test'; import Test from './components/Test/Test';
import Content from './components/Content/Content'; import Content from './components/Content/Content';
export interface TestScreenProps { export type TestScreenProps = {
route: RouteProp<AppStackParamList, Screen.Test>; route: RouteProp<AppStackParamList, Screen.TEST>;
} };
type QueryGenerateTestSimilarQualificationsQualificationArgs = { type QueryGenerateTestSimilarQualificationsQualificationArgs = {
limitTest: Scalars['Int']; limitTest: Scalars['Int'];

View File

@ -2,10 +2,10 @@ import React from 'react';
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { Content as ContentNB, NativeBase } from 'native-base'; import { Content as ContentNB, NativeBase } from 'native-base';
export interface ContentProps { export type ContentProps = {
children?: React.ReactNode; children?: React.ReactNode;
contentContainerStyle?: NativeBase.Content['contentContainerStyle']; contentContainerStyle?: NativeBase.Content['contentContainerStyle'];
} };
const Content = ({ children, contentContainerStyle }: ContentProps) => { const Content = ({ children, contentContainerStyle }: ContentProps) => {
return ( return (

View File

@ -12,9 +12,9 @@ import {
} from 'native-base'; } from 'native-base';
import Menu from 'common/Menu/Menu'; import Menu from 'common/Menu/Menu';
export interface HeaderProps { export type HeaderProps = {
title: string; title: string;
} };
const Header = ({ title }: HeaderProps) => { const Header = ({ title }: HeaderProps) => {
const navigation = useNavigation(); const navigation = useNavigation();

View File

@ -9,9 +9,9 @@ import { StyleSheet } from 'react-native';
import { H1, View, H3, Card, CardItem, Text, Button, Body } from 'native-base'; import { H1, View, H3, Card, CardItem, Text, Button, Body } from 'native-base';
import Content from '../Content/Content'; import Content from '../Content/Content';
export interface SuggestionsProps { export type SuggestionsProps = {
qualifications: Qualification[]; qualifications: Qualification[];
} };
const Suggestions = ({ qualifications }: SuggestionsProps) => { const Suggestions = ({ qualifications }: SuggestionsProps) => {
const navigation = useNavigation(); const navigation = useNavigation();
@ -51,7 +51,7 @@ const Suggestions = ({ qualifications }: SuggestionsProps) => {
<Button <Button
key={question} key={question}
onPress={() => { onPress={() => {
navigation.navigate(Screen.Test, { navigation.navigate(Screen.TEST, {
qualificationID: qualification.id, qualificationID: qualification.id,
limit: question, limit: question,
}); });

View File

@ -9,12 +9,12 @@ export enum AlertVariant {
Warning = 'warning', Warning = 'warning',
} }
export interface AlertProps extends Pick<NativeBase.View, 'style'> { export type AlertProps = {
variant?: AlertVariant; variant?: AlertVariant;
title: React.ReactNode; title: React.ReactNode;
description?: React.ReactNode; description?: React.ReactNode;
actions?: React.ReactNode; actions?: React.ReactNode;
} } & Pick<NativeBase.View, 'style'>;
const Alert = ({ const Alert = ({
variant = AlertVariant.Info, variant = AlertVariant.Info,

View File

@ -9,9 +9,9 @@ import {
} from 'react-native'; } from 'react-native';
import { H3 } from 'native-base'; import { H3 } from 'native-base';
export interface ImageProps extends Pick<RNImageProps, 'style'> { export type ImageProps = {
path: string; path: string;
} } & Pick<RNImageProps, 'style'>;
const MyImage = ({ path, style }: ImageProps) => { const MyImage = ({ path, style }: ImageProps) => {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);

View File

@ -10,12 +10,12 @@ import Content from '../Content/Content';
import Image from './Image'; import Image from './Image';
import Alert, { AlertVariant } from './Alert'; import Alert, { AlertVariant } from './Alert';
export interface QuestionProps { export type QuestionProps = {
question: QuestionT; question: QuestionT;
reviewMode: boolean; reviewMode: boolean;
selectedAnswer: Answer; selectedAnswer: Answer;
selectAnswer: (a: Answer) => void; selectAnswer: (a: Answer) => void;
} };
const ANSWERS = Object.values(Answer); const ANSWERS = Object.values(Answer);

View File

@ -8,14 +8,14 @@ import { Button, H1, H3, Text, View } from 'native-base';
import Content from '../Content/Content'; import Content from '../Content/Content';
import Alert from './Alert'; import Alert from './Alert';
export interface SummaryTabProps { export type SummaryTabProps = {
reviewMode: boolean; reviewMode: boolean;
answers: Answer[]; answers: Answer[];
questions: Question[]; questions: Question[];
finishTest: () => void; finishTest: () => void;
resetTest: () => void; resetTest: () => void;
qualificationID: number; qualificationID: number;
} };
const SummaryTab = ({ const SummaryTab = ({
reviewMode, reviewMode,

View File

@ -7,11 +7,11 @@ import { ScrollableTab, Tab, Tabs } from 'native-base';
import Question from './Question'; import Question from './Question';
import SummaryTab from './SummaryTab'; import SummaryTab from './SummaryTab';
export interface TestProps { export type TestProps = {
questions: QuestionT[]; questions: QuestionT[];
onReset: () => void; onReset: () => void;
qualification: Qualification; qualification: Qualification;
} };
const Test = ({ questions, onReset, qualification }: TestProps) => { const Test = ({ questions, onReset, qualification }: TestProps) => {
const [reviewMode, setReviewMode] = useState(false); const [reviewMode, setReviewMode] = useState(false);
@ -28,7 +28,7 @@ const Test = ({ questions, onReset, qualification }: TestProps) => {
); );
useEffect(() => { useEffect(() => {
analytics().logEvent(Event.StartTest, analyticsParams); analytics().logEvent(Event.START_TEST, analyticsParams);
}, [analyticsParams]); }, [analyticsParams]);
const handleSelectAnswer = (index: number, answer: Answer) => { const handleSelectAnswer = (index: number, answer: Answer) => {
@ -40,7 +40,7 @@ const Test = ({ questions, onReset, qualification }: TestProps) => {
index === index2 ? answer : otherAnswer, index === index2 ? answer : otherAnswer,
), ),
); );
analytics().logEvent(Event.SelectAnswer, { analytics().logEvent(Event.SELECT_ANSWER, {
qualificationID: analyticsParams.qualificationID, qualificationID: analyticsParams.qualificationID,
questionID: questions[index].id.toString(), questionID: questions[index].id.toString(),
answer, answer,
@ -50,7 +50,7 @@ const Test = ({ questions, onReset, qualification }: TestProps) => {
const handleFinishTest = () => { const handleFinishTest = () => {
setReviewMode(true); setReviewMode(true);
analytics().logEvent(Event.FinishTest, analyticsParams); analytics().logEvent(Event.FINISH_TEST, analyticsParams);
}; };
return ( return (