diff --git a/assets/images/arrow-right-circle-icon-white.svg b/assets/images/arrow-right-circle-icon-white.svg
new file mode 100644
index 000000000..325e7bf9e
--- /dev/null
+++ b/assets/images/arrow-right-circle-icon-white.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/images/index.ts b/assets/images/index.ts
index c34ae8570..7aae81044 100644
--- a/assets/images/index.ts
+++ b/assets/images/index.ts
@@ -1,6 +1,7 @@
import AddCircleIcon from './add-circle-icon.svg'
import ArrowLeftCircleIconBlue from './arrow-left-circle-icon-blue.svg'
import ArrowLeftCircleIconWhite from './arrow-left-circle-icon-white.svg'
+import ArrowRightCircleIconWhite from './arrow-right-circle-icon-white.svg'
import ArrowRightIcon from './arrow-right-icon.svg'
import BannerGreen from './banner-green.png'
import BannerRed from './banner-red.png'
@@ -55,6 +56,7 @@ export {
ArrowLeftCircleIconBlue,
ArrowLeftCircleIconWhite,
ArrowRightIcon,
+ ArrowRightCircleIconWhite,
BannerGreen,
BannerRed,
BannerYellow,
diff --git a/src/constants/data.ts b/src/constants/data.ts
index 1740e99d0..c44a371bb 100644
--- a/src/constants/data.ts
+++ b/src/constants/data.ts
@@ -3,6 +3,7 @@ import { SvgProps } from 'react-native-svg'
import { CheckCloseCircleIcon, CheckCircleIcon, CloseCircleIcon } from '../../assets/images'
import { RoutesParams } from '../navigation/NavigationTypes'
+import { Document } from './endpoints'
import labels from './labels.json'
export const ExerciseKeys = {
@@ -61,6 +62,11 @@ export interface NextExercise {
exerciseKey: number
}
+export type NextExerciseData = NextExercise & {
+ documents: Document[]
+ title: string
+}
+
export const BUTTONS_THEME = {
outlined: 'outlined',
contained: 'contained',
diff --git a/src/constants/endpoints.ts b/src/constants/endpoints.ts
index a8b50c551..3c7a3b92d 100644
--- a/src/constants/endpoints.ts
+++ b/src/constants/endpoints.ts
@@ -40,6 +40,7 @@ export const ENDPOINTS = {
disciplinesByGroup: 'disciplines_by_group',
groupInfo: 'group_info',
trainingSet: 'training_set',
+ trainingSets: 'training_sets',
documents: 'documents/:id'
}
diff --git a/src/constants/labels.json b/src/constants/labels.json
index a5d1746aa..36c8d93dd 100644
--- a/src/constants/labels.json
+++ b/src/constants/labels.json
@@ -10,7 +10,8 @@
"haveFun": "Viel Spaß beim Lernen",
"progressDescription": "Modulen erledigt",
"start": "Beginnen",
- "continue": "Weitermachen",
+ "continue": "Fortsetzen",
+ "viewModules": "Module ansehen",
"addCustomDiscipline": "Bereich hinzufügen",
"customDisciplineSection": "Individueller Lernbereich",
"customDisciplineExplanation": "Hier kannst du eigene Lernbereiche hinzufügen",
diff --git a/src/hooks/useLoadNextExercise.ts b/src/hooks/useLoadNextExercise.ts
new file mode 100644
index 000000000..5664962c0
--- /dev/null
+++ b/src/hooks/useLoadNextExercise.ts
@@ -0,0 +1,22 @@
+import { NextExerciseData } from '../constants/data'
+import { Discipline } from '../constants/endpoints'
+import { getNextExercise, loadTrainingsSet } from '../services/helpers'
+import { formatDiscipline } from './helpers'
+import useLoadAsync, { Return } from './useLoadAsync'
+import { loadDocuments } from './useLoadDocuments'
+
+export const loadNextExercise = async (profession: Discipline): Promise => {
+ const nextExercise = await getNextExercise(profession)
+ const trainingSet = await loadTrainingsSet(nextExercise.disciplineId)
+ const documents = await loadDocuments({ disciplineId: nextExercise.disciplineId })
+ return {
+ documents,
+ title: formatDiscipline(trainingSet, { parent: null }).title,
+ exerciseKey: nextExercise.exerciseKey,
+ disciplineId: nextExercise.disciplineId
+ }
+}
+
+const useLoadNextExercise = (loadData: Discipline): Return => useLoadAsync(loadNextExercise, loadData)
+
+export default useLoadNextExercise
diff --git a/src/hooks/useReadNextExercise.ts b/src/hooks/useReadNextExercise.ts
index ebbe3db45..1ed1c3ef2 100644
--- a/src/hooks/useReadNextExercise.ts
+++ b/src/hooks/useReadNextExercise.ts
@@ -3,7 +3,6 @@ import { Discipline } from '../constants/endpoints'
import { getNextExercise } from '../services/helpers'
import useLoadAsync, { Return } from './useLoadAsync'
-const useReadNextExercise = (profession: Discipline | null): Return =>
- useLoadAsync(getNextExercise, profession)
+const useReadNextExercise = (profession: Discipline): Return => useLoadAsync(getNextExercise, profession)
export default useReadNextExercise
diff --git a/src/routes/home/HomeScreen.tsx b/src/routes/home/HomeScreen.tsx
index 90ea1e567..e2a391930 100644
--- a/src/routes/home/HomeScreen.tsx
+++ b/src/routes/home/HomeScreen.tsx
@@ -1,4 +1,4 @@
-import { useFocusEffect } from '@react-navigation/native'
+import { CommonActions, useFocusEffect } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import React from 'react'
import { View } from 'react-native'
@@ -6,6 +6,8 @@ import styled from 'styled-components/native'
import { ContentSecondary } from '../../components/text/Content'
import { Heading } from '../../components/text/Heading'
+import { EXERCISES, NextExerciseData } from '../../constants/data'
+import { Discipline } from '../../constants/endpoints'
import labels from '../../constants/labels.json'
import useReadCustomDisciplines from '../../hooks/useReadCustomDisciplines'
import useReadSelectedProfessions from '../../hooks/useReadSelectedProfessions'
@@ -48,16 +50,38 @@ const HomeScreen = ({ navigation }: HomeScreenProps): JSX.Element => {
navigation.navigate('AddCustomDiscipline')
}
+ const navigateToDiscipline = (discipline: Discipline): void => {
+ navigation.navigate('DisciplineSelection', {
+ discipline
+ })
+ }
+
+ const navigateToNextExercise = (nextExerciseData: NextExerciseData) => {
+ const { exerciseKey, disciplineId, title: disciplineTitle, documents } = nextExerciseData
+ navigation.navigate(EXERCISES[exerciseKey].screen, {
+ disciplineId,
+ disciplineTitle,
+ documents,
+ closeExerciseAction: CommonActions.navigate('Home')
+ })
+ }
+
const customDisciplineItems = customDisciplines?.map(customDiscipline => (
))
const selectedProfessionItems = selectedProfessions?.map(profession => (
-
+
))
return (
diff --git a/src/routes/home/__tests__/HomeScreen.spec.tsx b/src/routes/home/__tests__/HomeScreen.spec.tsx
index 6be6d3c9a..810de26e6 100644
--- a/src/routes/home/__tests__/HomeScreen.spec.tsx
+++ b/src/routes/home/__tests__/HomeScreen.spec.tsx
@@ -6,6 +6,7 @@ import labels from '../../../constants/labels.json'
import { useLoadDiscipline } from '../../../hooks/useLoadDiscipline'
import { useLoadDisciplines } from '../../../hooks/useLoadDisciplines'
import useReadCustomDisciplines from '../../../hooks/useReadCustomDisciplines'
+import useReadProgress from '../../../hooks/useReadProgress'
import useReadSelectedProfessions from '../../../hooks/useReadSelectedProfessions'
import AsyncStorageService from '../../../services/AsyncStorage'
import createNavigationMock from '../../../testing/createNavigationPropMock'
@@ -15,8 +16,10 @@ import { mockDisciplines } from '../../../testing/mockDiscipline'
import render from '../../../testing/render'
import HomeScreen from '../HomeScreen'
+jest.mock('../../../services/helpers')
jest.mock('@react-navigation/native')
jest.mock('../../../hooks/useReadCustomDisciplines')
+jest.mock('../../../hooks/useReadProgress')
jest.mock('../../../hooks/useReadSelectedProfessions')
jest.mock('../../../hooks/useLoadDisciplines')
jest.mock('../../../hooks/useLoadDiscipline')
@@ -34,7 +37,7 @@ describe('HomeScreen', () => {
mocked(useLoadDiscipline)
.mockReturnValueOnce(getReturnOf(mockDisciplines()[0]))
.mockReturnValueOnce(getReturnOf(mockDisciplines()[1]))
-
+ mocked(useReadProgress).mockReturnValue(getReturnOf(0))
const { getByText } = render()
const firstDiscipline = getByText('First Discipline')
const secondDiscipline = getByText('Second Discipline')
@@ -42,8 +45,6 @@ describe('HomeScreen', () => {
expect(secondDiscipline).toBeDefined()
})
- // TODO LUN-328 add test for navigate to child disciplines
-
it('should show custom discipline', async () => {
await AsyncStorageService.setCustomDisciplines(['test'])
mocked(useLoadDisciplines).mockReturnValueOnce(getReturnOf(mockDisciplines()))
diff --git a/src/routes/home/components/Card.tsx b/src/routes/home/components/Card.tsx
index 80b4ccd4d..14de0d690 100644
--- a/src/routes/home/components/Card.tsx
+++ b/src/routes/home/components/Card.tsx
@@ -16,7 +16,7 @@ const Box = styled.Pressable`
justify-content: space-between;
margin: ${props => props.theme.spacings.sm};
padding: 0 ${props => props.theme.spacings.sm};
- height: ${hp('28%')}px;
+ min-height: ${hp('28%')}px;
`
const BoxHeading = styled.View`
diff --git a/src/routes/home/components/CustomDisciplineDetails.tsx b/src/routes/home/components/CustomDisciplineDetails.tsx
index 07d44f3a8..5456467f0 100644
--- a/src/routes/home/components/CustomDisciplineDetails.tsx
+++ b/src/routes/home/components/CustomDisciplineDetails.tsx
@@ -1,5 +1,3 @@
-import { useNavigation } from '@react-navigation/native'
-import { StackNavigationProp } from '@react-navigation/stack'
import React from 'react'
import styled from 'styled-components/native'
@@ -7,7 +5,6 @@ import Button from '../../../components/Button'
import { BUTTONS_THEME } from '../../../constants/data'
import { Discipline } from '../../../constants/endpoints'
import labels from '../../../constants/labels.json'
-import { RoutesParams } from '../../../navigation/NavigationTypes'
import { childrenLabel } from '../../../services/helpers'
import { ButtonContainer, NumberText, UnitText } from './DisciplineCard'
@@ -20,28 +17,23 @@ const TextContainer = styled.View`
interface PropsType {
discipline: Discipline
+ navigateToDiscipline: (discipline: Discipline) => void
}
-const CustomDisciplineDetails = ({ discipline }: PropsType): JSX.Element => {
- const navigation = useNavigation>()
-
- const navigate = (): void => {
- navigation.navigate('DisciplineSelection', {
- discipline
- })
- }
-
- return (
- <>
-
- {discipline.numberOfChildren}
- {childrenLabel(discipline)}
-
-
-
-
- >
- )
-}
+const CustomDisciplineDetails = ({ discipline, navigateToDiscipline }: PropsType): JSX.Element => (
+ <>
+
+ {discipline.numberOfChildren}
+ {childrenLabel(discipline)}
+
+
+
+ >
+)
export default CustomDisciplineDetails
diff --git a/src/routes/home/components/DisciplineCard.tsx b/src/routes/home/components/DisciplineCard.tsx
index 78203f7f0..19abe1f13 100644
--- a/src/routes/home/components/DisciplineCard.tsx
+++ b/src/routes/home/components/DisciplineCard.tsx
@@ -6,8 +6,8 @@ import ErrorMessage from '../../../components/ErrorMessage'
import Loading from '../../../components/Loading'
import { ContentSecondary, ContentSecondaryLight } from '../../../components/text/Content'
import { Subheading } from '../../../components/text/Subheading'
-import { BUTTONS_THEME } from '../../../constants/data'
-import { ForbiddenError } from '../../../constants/endpoints'
+import { BUTTONS_THEME, NextExerciseData } from '../../../constants/data'
+import { Discipline, ForbiddenError } from '../../../constants/endpoints'
import labels from '../../../constants/labels.json'
import { isTypeLoadProtected } from '../../../hooks/helpers'
import { RequestParams, useLoadDiscipline } from '../../../hooks/useLoadDiscipline'
@@ -40,9 +40,16 @@ export const ButtonContainer = styled.View`
interface PropsType {
identifier: RequestParams
refresh?: () => void
+ navigateToDiscipline: (discipline: Discipline) => void
+ navigateToNextExercise?: (nextExerciseData: NextExerciseData) => void
}
-const DisciplineCard = ({ identifier, refresh: refreshHome }: PropsType): JSX.Element => {
+const DisciplineCard = ({
+ identifier,
+ refresh: refreshHome,
+ navigateToDiscipline,
+ navigateToNextExercise
+}: PropsType): JSX.Element => {
const { data: discipline, loading, error, refresh } = useLoadDiscipline(identifier)
if (loading) {
@@ -79,11 +86,17 @@ const DisciplineCard = ({ identifier, refresh: refreshHome }: PropsType): JSX.El
}
return (
-
+ navigateToDiscipline(discipline)}>
{isTypeLoadProtected(identifier) ? (
-
+
) : (
-
+ navigateToNextExercise && (
+
+ )
)}
)
diff --git a/src/routes/home/components/NextExerciseCard.tsx b/src/routes/home/components/NextExerciseCard.tsx
new file mode 100644
index 000000000..7b9c64edb
--- /dev/null
+++ b/src/routes/home/components/NextExerciseCard.tsx
@@ -0,0 +1,79 @@
+import React, { ReactElement } from 'react'
+import { Pressable, TouchableOpacity } from 'react-native'
+import { widthPercentageToDP as wp } from 'react-native-responsive-screen'
+import styled from 'styled-components/native'
+
+import { ArrowRightCircleIconWhite } from '../../../../assets/images'
+import { ContentTextLight } from '../../../components/text/Content'
+import { SubheadingPrimary, SubheadingText } from '../../../components/text/Subheading'
+
+const Container = styled.View`
+ flex-direction: row;
+ background-color: ${props => props.theme.colors.background};
+ padding: ${props => props.theme.spacings.sm};
+ margin: ${props => props.theme.spacings.sm} 0;
+ shadow-color: ${props => props.theme.colors.shadow};
+ elevation: 8;
+ shadow-radius: 1px;
+ shadow-offset: 1px 1px;
+ shadow-opacity: 0.5;
+`
+
+const ExerciseDetail = styled.View`
+ padding: 0 ${props => props.theme.spacings.sm};
+ align-self: center;
+`
+
+const ActionContainer = styled.View`
+ padding-top: ${props => props.theme.spacings.xs};
+ flex-direction: row;
+ align-items: flex-start;
+`
+
+const Label = styled(SubheadingPrimary)`
+ letter-spacing: ${props => props.theme.fonts.capsLetterSpacing};
+ text-transform: uppercase;
+ padding-right: ${props => props.theme.spacings.xs};
+ align-self: center;
+`
+
+const Thumbnail = styled.Image`
+ height: ${wp('19%')}px;
+ width: ${wp('18%')}px;
+ align-self: center;
+`
+
+const Heading = styled(SubheadingText)`
+ font-size: ${props => props.theme.fonts.smallFontSize};
+`
+const Subheading = styled(ContentTextLight)`
+ font-size: ${props => props.theme.fonts.smallFontSize};
+`
+
+interface PropsType {
+ thumbnail: string
+ heading: string
+ subheading: string
+ buttonLabel: string
+ onPress: () => void
+}
+
+const NextExerciseCard = ({ thumbnail, onPress, heading, subheading, buttonLabel }: PropsType): ReactElement => (
+
+
+
+
+ {heading}
+ {subheading}
+
+
+
+
+
+
+
+
+
+)
+
+export default NextExerciseCard
diff --git a/src/routes/home/components/ProfessionDetails.tsx b/src/routes/home/components/ProfessionDetails.tsx
index 02ae41cda..a0662355b 100644
--- a/src/routes/home/components/ProfessionDetails.tsx
+++ b/src/routes/home/components/ProfessionDetails.tsx
@@ -1,22 +1,18 @@
-import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native'
-import { StackNavigationProp } from '@react-navigation/stack'
-import React, { ReactElement, useEffect, useState } from 'react'
-import { Pressable } from 'react-native'
+import { useFocusEffect } from '@react-navigation/native'
+import React, { ReactElement } from 'react'
import * as Progress from 'react-native-progress'
import styled from 'styled-components/native'
import Button from '../../../components/Button'
-import { BUTTONS_THEME, EXERCISES } from '../../../constants/data'
-import { Discipline, Document } from '../../../constants/endpoints'
+import { BUTTONS_THEME, EXERCISES, NextExerciseData } from '../../../constants/data'
+import { Discipline } from '../../../constants/endpoints'
import labels from '../../../constants/labels.json'
import theme from '../../../constants/theme'
-import { loadDocuments } from '../../../hooks/useLoadDocuments'
-import useReadNextExercise from '../../../hooks/useReadNextExercise'
+import useLoadNextExercise from '../../../hooks/useLoadNextExercise'
import useReadProgress from '../../../hooks/useReadProgress'
-import { RoutesParams } from '../../../navigation/NavigationTypes'
import { childrenLabel } from '../../../services/helpers'
-import { reportError } from '../../../services/sentry'
import { ButtonContainer, NumberText, UnitText } from './DisciplineCard'
+import NextExerciseCard from './NextExerciseCard'
const ProgressContainer = styled.View`
display: flex;
@@ -27,40 +23,31 @@ const ProgressContainer = styled.View`
interface PropsType {
discipline: Discipline
+ navigateToDiscipline: (discipline: Discipline) => void
+ navigateToNextExercise: (nextExerciseData: NextExerciseData) => void
}
-const ProfessionDetails = ({ discipline }: PropsType): ReactElement => {
- const { data: nextExercise, refresh: refreshNextExercise } = useReadNextExercise(discipline)
+const ProfessionDetails = ({
+ discipline,
+ navigateToDiscipline,
+ navigateToNextExercise
+}: PropsType): ReactElement | null => {
const { data: progress, refresh: refreshProgress } = useReadProgress(discipline)
+ const { data: nextExerciseData, refresh: refreshNextExercise } = useLoadNextExercise(discipline)
const moduleAlreadyStarted = progress !== null && progress !== 0
- const [documents, setDocuments] = useState(null)
- const navigation = useNavigation>()
useFocusEffect(refreshProgress)
useFocusEffect(refreshNextExercise)
- useEffect(() => {
- if (nextExercise) {
- loadDocuments({ disciplineId: nextExercise.disciplineId }).then(setDocuments).catch(reportError)
- }
- }, [nextExercise])
-
- const navigate = () => {
- if (documents !== null && nextExercise !== null) {
- navigation.navigate(EXERCISES[nextExercise.exerciseKey].screen, {
- disciplineId: nextExercise.disciplineId,
- disciplineTitle: '', // TODO set discipline title correct LUN-320
- documents,
- closeExerciseAction: CommonActions.navigate('Home')
- })
- }
+ if (!nextExerciseData) {
+ return null
}
- const navigateToDisciplines = () => navigation.navigate('DisciplineSelection', { discipline }) // TODO remove in LUN-328
+ const { documents, title, exerciseKey } = nextExerciseData
return (
-
+ <>
{
)}
{moduleAlreadyStarted ? labels.home.progressDescription : childrenLabel(discipline)}
+ navigateToNextExercise(nextExerciseData)}
+ heading={EXERCISES[exerciseKey].title}
+ buttonLabel={labels.home.continue}
+ subheading={title}
+ />
-
+ >
)
}
diff --git a/src/routes/home/components/__tests__/CustomDisciplineDetails.spec.tsx b/src/routes/home/components/__tests__/CustomDisciplineDetails.spec.tsx
index 2511d9049..7ca00c12e 100644
--- a/src/routes/home/components/__tests__/CustomDisciplineDetails.spec.tsx
+++ b/src/routes/home/components/__tests__/CustomDisciplineDetails.spec.tsx
@@ -6,26 +6,16 @@ import { mockDisciplines } from '../../../../testing/mockDiscipline'
import render from '../../../../testing/render'
import CustomDisciplineDetails from '../CustomDisciplineDetails'
-const mockedNavigate = jest.fn()
-
-jest.mock('@react-navigation/native', () => {
- const actualNav = jest.requireActual('@react-navigation/native')
- return {
- ...actualNav,
- useNavigation: () => ({
- navigate: mockedNavigate
- })
- }
-})
+const navigateToDiscipline = jest.fn()
describe('CustomDisciplineDetails', () => {
- it('should navigate on button click', () => {
+ it('should handle button click', () => {
const discipline = mockDisciplines(false)[0]
- const { getByText } = render()
+ const { getByText } = render(
+
+ )
const button = getByText(labels.home.start)
fireEvent.press(button)
- expect(mockedNavigate).toHaveBeenCalledWith('DisciplineSelection', {
- discipline
- })
+ expect(navigateToDiscipline).toHaveBeenCalledWith(discipline)
})
})
diff --git a/src/routes/home/components/__tests__/DisciplineCard.spec.tsx b/src/routes/home/components/__tests__/DisciplineCard.spec.tsx
index 30d6d8cc1..08eee8c2d 100644
--- a/src/routes/home/components/__tests__/DisciplineCard.spec.tsx
+++ b/src/routes/home/components/__tests__/DisciplineCard.spec.tsx
@@ -1,4 +1,3 @@
-import { NavigationContainer } from '@react-navigation/native'
import { RenderAPI } from '@testing-library/react-native'
import React from 'react'
@@ -13,25 +12,23 @@ import {
import render from '../../../../testing/render'
import DisciplineCard from '../DisciplineCard'
+jest.mock('@react-navigation/native')
jest.useFakeTimers()
+const navigateToDiscipline = jest.fn()
+
describe('DisciplineCard', () => {
beforeEach(() => {
jest.clearAllMocks()
})
const renderDisciplineCard = (): RenderAPI =>
- render(
-
-
-
- )
+ render()
it('should show discipline card', async () => {
mockUseLoadAsyncWithData(mockDisciplines()[0])
- const { getByText, findByText, getByTestId } = renderDisciplineCard()
+ const { getByText, findByText } = renderDisciplineCard()
expect(getByText(mockDisciplines()[0].title)).toBeDefined()
- expect(getByTestId('progress-circle')).toBeDefined()
await expect(findByText(labels.home.continue)).toBeDefined()
})
@@ -50,9 +47,7 @@ describe('DisciplineCard', () => {
it('should display forbidden error', async () => {
mockUseLoadAsyncWithError(ForbiddenError)
const { getByText } = render(
-
-
-
+
)
expect(getByText(`${labels.home.errorLoadCustomDiscipline} abc`)).toBeDefined()
expect(getByText(labels.home.deleteModal.confirm)).toBeDefined()
diff --git a/src/routes/home/components/__tests__/ProfessionDetails.spec.tsx b/src/routes/home/components/__tests__/ProfessionDetails.spec.tsx
new file mode 100644
index 000000000..0c2adef3f
--- /dev/null
+++ b/src/routes/home/components/__tests__/ProfessionDetails.spec.tsx
@@ -0,0 +1,56 @@
+import { fireEvent, RenderAPI } from '@testing-library/react-native'
+import { mocked } from 'jest-mock'
+import React from 'react'
+
+import { NextExerciseData } from '../../../../constants/data'
+import labels from '../../../../constants/labels.json'
+import useLoadNextExercise from '../../../../hooks/useLoadNextExercise'
+import useReadProgress from '../../../../hooks/useReadProgress'
+import DocumentBuilder from '../../../../testing/DocumentBuilder'
+import { getReturnOf } from '../../../../testing/helper'
+import { mockDisciplines } from '../../../../testing/mockDiscipline'
+import render from '../../../../testing/render'
+import ProfessionDetails from '../ProfessionDetails'
+
+const navigateToDiscipline = jest.fn()
+const navigateToExercise = jest.fn()
+jest.mock('../../../../services/helpers')
+jest.mock('../../../../hooks/useReadProgress')
+jest.mock('../../../../hooks/useLoadNextExercise')
+jest.mock('@react-navigation/native')
+
+const nextExerciseData: NextExerciseData = {
+ documents: new DocumentBuilder(1).build(),
+ title: 'Exercise Test',
+ exerciseKey: 1,
+ disciplineId: 1
+}
+
+describe('ProfessionDetails', () => {
+ const renderProfessionDetails = (): RenderAPI =>
+ render(
+
+ )
+
+ it('should show next exercise details on the card', () => {
+ mocked(useReadProgress).mockReturnValue(getReturnOf(0))
+ mocked(useLoadNextExercise).mockReturnValue(getReturnOf(nextExerciseData))
+ const { getByText, findByText, getByTestId } = renderProfessionDetails()
+ expect(getByText(nextExerciseData.title)).toBeDefined()
+ expect(getByTestId('progress-circle')).toBeDefined()
+ expect(findByText(labels.home.continue)).toBeDefined()
+ })
+
+ it('should navigate to NextExercise', () => {
+ mocked(useReadProgress).mockReturnValue(getReturnOf(0))
+ mocked(useLoadNextExercise).mockReturnValue(getReturnOf(nextExerciseData))
+ const { getByText } = renderProfessionDetails()
+ const button = getByText(labels.home.continue)
+ fireEvent.press(button)
+ expect(navigateToExercise).toHaveBeenCalledWith(nextExerciseData)
+ })
+})
diff --git a/src/services/__tests__/helpers.spec.tsx b/src/services/__tests__/helpers.spec.tsx
index d482d825c..36c62290c 100644
--- a/src/services/__tests__/helpers.spec.tsx
+++ b/src/services/__tests__/helpers.spec.tsx
@@ -23,13 +23,7 @@ describe('helpers', () => {
}
describe('getNextExercise', () => {
- const getNextExerciseWithCheck = async (): Promise => {
- const e = await getNextExercise(profession)
- if (!e) {
- throw Error('NextExerciseData is undefined')
- }
- return e
- }
+ const getNextExerciseWithCheck = async (): Promise => getNextExercise(profession)
it('should open first exercise, if no exercise was finished yet', async () => {
mocked(loadDisciplines).mockReturnValueOnce(Promise.resolve(mockDisciplines(true)))
diff --git a/src/services/helpers.ts b/src/services/helpers.ts
index 3632be722..d550d2bcc 100644
--- a/src/services/helpers.ts
+++ b/src/services/helpers.ts
@@ -1,9 +1,11 @@
import { Article, EXERCISES, NextExercise, Progress } from '../constants/data'
-import { AlternativeWord, Discipline, Document } from '../constants/endpoints'
+import { AlternativeWord, Discipline, Document, ENDPOINTS } from '../constants/endpoints'
import labels from '../constants/labels.json'
import { COLORS } from '../constants/theme/colors'
+import { ServerResponseDiscipline } from '../hooks/helpers'
import { loadDisciplines } from '../hooks/useLoadDisciplines'
import AsyncStorage from './AsyncStorage'
+import { getFromEndpoint } from './axios'
export const stringifyDocument = ({ article, word }: Document | AlternativeWord): string => `${article.value} ${word}`
@@ -75,10 +77,7 @@ export const getDoneExercises = (disciplineId: number): Promise =>
disciplineId: the leaf discipline which needs to be done next
exerciseKey: exerciseKey of the next exercise which needs to be done
*/
-export const getNextExercise = async (profession: Discipline | null): Promise => {
- if (!profession) {
- return null
- }
+export const getNextExercise = async (profession: Discipline): Promise => {
const disciplines = await loadDisciplines({ parent: profession }) // TODO LUN-316 leaf disciplines must be loaded, also if nested
if (disciplines.length <= 0) {
throw new Error(`No Disciplines for id ${profession.id}`)
@@ -87,12 +86,19 @@ export const getNextExercise = async (profession: Discipline | null): Promise getDoneExercisesByProgress(discipline.id, progress) < EXERCISES.length
)
+
if (!firstUnfinishedDiscipline) {
- return { disciplineId: disciplines[0].id, exerciseKey: 0 } // TODO LUN-319 show success that every exercise is done
+ return {
+ disciplineId: disciplines[0].id,
+ exerciseKey: 0
+ } // TODO LUN-319 show success that every exercise is done
}
const disciplineProgress = progress[firstUnfinishedDiscipline.id]
if (!disciplineProgress) {
- return { disciplineId: firstUnfinishedDiscipline.id, exerciseKey: 0 }
+ return {
+ disciplineId: firstUnfinishedDiscipline.id,
+ exerciseKey: 0
+ }
}
const nextExerciseKey = EXERCISES.find(exercise => disciplineProgress[exercise.key] === undefined)
return {
@@ -113,3 +119,9 @@ export const getProgress = async (profession: Discipline | null): Promise => {
+ const trainingSetUrl = `${ENDPOINTS.trainingSets}/${disciplineId}`
+ const trainingSet = await getFromEndpoint(trainingSetUrl)
+ return trainingSet
+}