Skip to content

Commit

Permalink
Merge pull request #370 from digitalfabrik/LUN-407-add-evaluation-of-…
Browse files Browse the repository at this point in the history
…levels

LUN-407: Add evaluation of levels
  • Loading branch information
charludo authored Oct 5, 2022
2 parents f94c575 + 953fb4d commit 5f91401
Show file tree
Hide file tree
Showing 18 changed files with 240 additions and 118 deletions.
6 changes: 4 additions & 2 deletions assets/images/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ import StarCircleIconGrey from './star-circle-icon-grey.svg'
import StarIconGreyFilled from './star-icon-grey-filled.svg'
import StarIconGrey from './star-icon-grey.svg'
import StarIconWhite from './star-icon-white.svg'
import ThumbsDownIcon from './thumbs-down.svg'
import ThumbsUpIcon from './thumbs-up.svg'
import TrashIconWhite from './trash-bin-icon-white.svg'
import TrashIcon from './trash-bin-icon.svg'
import TrophyIcon from './trophy-icon.svg'
import VolumeUpCircleIcon from './volume-up-circle-icon.svg'

export {
Expand Down Expand Up @@ -134,6 +135,7 @@ export {
StarIconWhite,
TrashIcon,
TrashIconWhite,
TrophyIcon,
VolumeUpCircleIcon,
ThumbsUpIcon,
ThumbsDownIcon,
}
7 changes: 7 additions & 0 deletions assets/images/thumbs-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions assets/images/thumbs-up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 0 additions & 36 deletions assets/images/trophy-icon.svg

This file was deleted.

6 changes: 6 additions & 0 deletions release-notes/unreleased/LUN-407-add-evaluation-of-levels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
issue_key: LUN-407
show_in_stores: true
platforms:
- android
- ios
de: Zeige Feedback zu bereits abgeschlossenen Leveln
2 changes: 1 addition & 1 deletion src/components/ErrorMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const ErrorMessage = ({ error, refresh, contained }: ErrorMessageProps): JSX.Ele

return (
<NetworkErrorWrapper>
<RoundedBackground color={theme.colors.networkErrorBackground} height='67%'>
<RoundedBackground color={theme.colors.lightGreyBackground} height='67%'>
<Container>
{error.message === NetworkError && (
<IconStyle>
Expand Down
58 changes: 58 additions & 0 deletions src/components/FeedbackBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { ReactElement } from 'react'
import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-native-responsive-screen'
import styled from 'styled-components/native'

import { ThumbsDownIcon, ThumbsUpIcon } from '../../assets/images'
import { EXERCISE_FEEDBACK } from '../constants/data'
import { getLabels } from '../services/helpers'
import { ContentSecondaryLight } from './text/Content'

const BadgeContainer = styled.View`
display: flex;
flex-flow: row nowrap;
padding: ${props => props.theme.spacings.xxs} ${props => props.theme.spacings.sm};
background-color: ${props => props.theme.colors.lightGreyBackground};
width: 100%;
`
const BadgeText = styled(ContentSecondaryLight)`
font-style: italic;
margin-left: ${props => props.theme.spacings.xs};
align-self: center;
`

const BadgeIcon = styled.View`
height: ${hp('3.5%')}px;
max-height: ${wp('5%')}px;
`

interface FeedbackBadgeProps {
feedback: EXERCISE_FEEDBACK
}

const FeedbackBadge = ({ feedback }: FeedbackBadgeProps): ReactElement | null => {
const { positive, negative } = { ...getLabels().exercises.feedback }
if (feedback === EXERCISE_FEEDBACK.POSITIVE) {
return (
<BadgeContainer testID='positive-badge'>
<BadgeIcon>
<ThumbsUpIcon height='100%' />
</BadgeIcon>
<BadgeText>{positive}</BadgeText>
</BadgeContainer>
)
}

if (feedback === EXERCISE_FEEDBACK.NEGATIVE) {
return (
<BadgeContainer testID='negative-badge'>
<BadgeIcon>
<ThumbsDownIcon height='100%' />
</BadgeIcon>
<BadgeText>{negative}</BadgeText>
</BadgeContainer>
)
}

return null
}
export default FeedbackBadge
65 changes: 51 additions & 14 deletions src/components/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,59 @@ import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-nat
import styled, { useTheme } from 'styled-components/native'

import { ChevronRight } from '../../assets/images'
import { EXERCISE_FEEDBACK } from '../constants/data'
import FeedbackBadge from './FeedbackBadge'
import { ContentSecondaryLight } from './text/Content'

export const GenericListItemContainer = styled.Pressable`
margin-bottom: ${props => props.theme.spacings.xxs};
align-self: center;
flex-direction: row;
justify-content: space-between;
align-items: center;
border-radius: 2px;
`

const Container = styled(GenericListItemContainer)<{ pressed: boolean; disabled: boolean }>`
const Container = styled(GenericListItemContainer)<{
pressed: boolean
disabled: boolean
feedback: EXERCISE_FEEDBACK
}>`
min-height: ${hp('12%')}px;
justify-content: center;
flex-direction: column;
border-top-width: 1px;
border-top-color: ${prop => (prop.pressed ? prop.theme.colors.primary : prop.theme.colors.disabled)};
border-right-width: 1px;
border-right-color: ${prop => (prop.pressed ? prop.theme.colors.primary : prop.theme.colors.disabled)};
border-bottom-width: 1px;
border-bottom-color: ${prop => (prop.pressed ? prop.theme.colors.primary : prop.theme.colors.disabled)};
border-left-color: ${props => {
if (props.feedback === EXERCISE_FEEDBACK.POSITIVE) {
return props.theme.colors.correct
}
if (props.feedback === EXERCISE_FEEDBACK.NEGATIVE) {
return props.theme.colors.incorrect
}
if (props.pressed) {
return props.theme.colors.primary
}
return props.theme.colors.disabled
}};
border-left-radius: 0;
border-left-width: ${props => (props.feedback !== EXERCISE_FEEDBACK.NONE ? '4px' : '1px')};
background-color: ${prop => {
if (prop.disabled) {
return prop.theme.colors.disabled
}
return prop.pressed ? prop.theme.colors.primary : prop.theme.colors.backgroundAccent
}};
border: 1px solid ${prop => (prop.pressed ? prop.theme.colors.primary : prop.theme.colors.disabled)};
`

const ContentContainer = styled.View<{ pressed: boolean; disabled: boolean }>`
display: flex;
flex-direction: row;
padding: ${props =>
`${props.theme.spacings.sm} ${props.theme.spacings.xs} ${props.theme.spacings.sm} ${props.theme.spacings.sm}`};
align-items: center;
`

const Title = styled.Text<{ pressed: boolean }>`
Expand Down Expand Up @@ -87,6 +118,7 @@ interface ListItemProps {
hideRightChildren?: boolean
arrowDisabled?: boolean
disabled?: boolean
feedback?: EXERCISE_FEEDBACK
}

const ListItem = ({
Expand All @@ -100,6 +132,7 @@ const ListItem = ({
hideRightChildren = false,
arrowDisabled = false,
disabled = false,
feedback = EXERCISE_FEEDBACK.NONE,
}: ListItemProps): ReactElement => {
const [pressInY, setPressInY] = useState<number | null>(null)
const [pressed, setPressed] = useState<boolean>(false)
Expand Down Expand Up @@ -160,17 +193,21 @@ const ListItem = ({
onLongPress={() => updatePressed(true)}
pressed={pressed}
delayLongPress={200}
feedback={feedback}
testID='list-item'>
{iconToRender}
<FlexContainer>
{titleToRender}
<DescriptionContainer>
{badgeLabel && <BadgeLabel pressed={pressed}>{badgeLabel}</BadgeLabel>}
{description && description.length > 0 && <Description pressed={pressed}>{description}</Description>}
</DescriptionContainer>
{children}
</FlexContainer>
{rightChildrenToRender}
<FeedbackBadge feedback={feedback} />
<ContentContainer pressed={pressed} disabled={disabled}>
{iconToRender}
<FlexContainer>
{titleToRender}
<DescriptionContainer>
{badgeLabel && <BadgeLabel pressed={pressed}>{badgeLabel}</BadgeLabel>}
{description && description.length > 0 && <Description pressed={pressed}>{description}</Description>}
</DescriptionContainer>
{children}
</FlexContainer>
{rightChildrenToRender}
</ContentContainer>
</Container>
)
}
Expand Down
29 changes: 0 additions & 29 deletions src/components/Trophy.tsx

This file was deleted.

38 changes: 38 additions & 0 deletions src/components/__tests__/FeedbackBadge.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { waitFor } from '@testing-library/react-native'
import React from 'react'

import { SCORE_THRESHOLD_POSITIVE_FEEDBACK, EXERCISE_FEEDBACK } from '../../constants/data'
import { getLabels } from '../../services/helpers'
import render from '../../testing/render'
import FeedbackBadge from '../FeedbackBadge'

describe('FeedbackBadge', () => {
beforeEach(() => {
jest.clearAllMocks()
})

const renderFeedbackBadge = (feedback: EXERCISE_FEEDBACK) => render(<FeedbackBadge feedback={feedback} />)

it('should not show badge for no feedback', async () => {
const { queryByTestId } = renderFeedbackBadge(EXERCISE_FEEDBACK.NONE)

await waitFor(() => expect(queryByTestId('positive-badge')).toBeNull())
await waitFor(() => expect(queryByTestId('negative-badge')).toBeNull())
})

it('should show badge for positive feedback', async () => {
const { queryByText, queryByTestId } = renderFeedbackBadge(EXERCISE_FEEDBACK.POSITIVE)

await waitFor(() => expect(queryByTestId('negative-badge')).toBeNull())
await waitFor(() => expect(queryByTestId('positive-badge')).not.toBeNull())
await waitFor(() => expect(queryByText(getLabels().exercises.feedback.positive)).not.toBeNull())
})

it('should show badge for negative feedback', async () => {
const { queryByText, queryByTestId } = renderFeedbackBadge(EXERCISE_FEEDBACK.NEGATIVE)

await waitFor(() => expect(queryByTestId('positive-badge')).toBeNull())
await waitFor(() => expect(queryByTestId('negative-badge')).not.toBeNull())
await waitFor(() => expect(queryByText(getLabels().exercises.feedback.negative)).not.toBeNull())
})
})
1 change: 1 addition & 0 deletions src/components/__tests__/ListItem.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { COLORS } from '../../constants/theme/colors'
import render from '../../testing/render'
import ListItem from '../ListItem'

jest.mock('@react-navigation/native')
describe('ListItem', () => {
const onPress = jest.fn()
const description = 'Wörter'
Expand Down
25 changes: 0 additions & 25 deletions src/components/__tests__/Trophy.spec.tsx

This file was deleted.

6 changes: 6 additions & 0 deletions src/constants/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,9 @@ export const numberOfMaxRetries = 3

export const SCORE_THRESHOLD_POSITIVE_FEEDBACK = 4
export const SCORE_THRESHOLD_UNLOCK = 2

export const enum EXERCISE_FEEDBACK {
POSITIVE,
NONE,
NEGATIVE,
}
4 changes: 4 additions & 0 deletions src/constants/labels.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@
"cancelModal": {
"cancelAsk": "Möchtest du diese Übung wirklich beenden?",
"cancel": "Beenden"
},
"feedback": {
"positive": "Weiter so, das war super!",
"negative": "Das geht besser. Probier es nochmal."
}
},
"results": {
Expand Down
2 changes: 1 addition & 1 deletion src/constants/theme/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const COLORS = {
articleFeminine: '#faa7a7',
articleMasculine: '#8cc8f3',
link: 'blue',
networkErrorBackground: '#e0e4ed',
lightGreyBackground: '#e0e4ed',
}

export type Color = typeof COLORS[keyof typeof COLORS]
Loading

0 comments on commit 5f91401

Please sign in to comment.