chore: sort list of children (#151)

* chore: sort list of children

* fix: sortera klasskompisar

* chore: ta bort classmates ur child

De hämtas med en hook i classmates vyn

* chore: uppdatera namnhelpers

Co-authored-by: Rickard Natt och Dag <rickard@hey.com>
This commit is contained in:
Jimmy Jardland 2021-02-19 15:30:48 +01:00 committed by GitHub
parent a191b450c0
commit f0f61217d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 186 additions and 42 deletions

View File

@ -0,0 +1,87 @@
import { useClassmates } from '@skolplattformen/api-hooks'
import React from 'react'
import { render } from '../../utils/testHelpers'
import { ChildProvider } from '../childContext.component'
import { Classmates } from '../classmates.component'
jest.mock('@react-navigation/native')
jest.mock('@skolplattformen/api-hooks')
const defaultClassmates = [
{
className: '2B',
firstname: 'Tyrell',
lastname: 'Eriksson',
guardians: [
{
firstname: 'Margaery',
lastname: 'Eriksson',
},
{
firstname: 'Loras',
lastname: 'Eriksson',
},
],
},
{
className: '2B',
firstname: 'Adam',
lastname: 'Svensson',
guardians: [
{
firstname: 'Eva',
lastname: 'Svensson',
},
],
},
]
const setup = ({ classmates } = { classmates: defaultClassmates }) => {
useClassmates.mockReturnValue({
data: classmates,
})
return render(
<ChildProvider child={{ id: 1 }}>
<Classmates />
</ChildProvider>
)
}
test('gets the classmates for a child from context', () => {
setup()
expect(useClassmates).toHaveBeenCalledWith({ id: 1 })
})
test('renders class name', () => {
const screen = setup()
expect(screen.getByText(/^klass 2b$/i)).toBeTruthy()
})
test('renders class without name', () => {
const screen = setup({
classmates: [],
})
expect(screen.getByText(/^klass$/i)).toBeTruthy()
})
test('renders classmates sorted by first name', () => {
const screen = setup()
expect(screen.getByLabelText('Barn 1')).toContainElement(
screen.getByText(/adam svensson/i)
)
expect(screen.getByLabelText('Barn 2')).toContainElement(
screen.getByText(/tyrell eriksson/i)
)
})
test('renders guardians sorted by first name', () => {
const screen = setup()
expect(screen.getByText(/eva svensson/i)).toBeTruthy()
expect(screen.getByText(/^loras eriksson, margaery eriksson$/i)).toBeTruthy()
})

View File

@ -19,7 +19,7 @@ import Personnummer from 'personnummer'
import AsyncStorage from '@react-native-async-storage/async-storage'
import DateTimePickerModal from 'react-native-modal-datetime-picker'
import moment from 'moment'
import { childName } from '../utils/childHelpers'
import { studentName } from '../utils/peopleHelpers'
const AbsenceSchema = Yup.object().shape({
socialSecurityNumber: Yup.string()
@ -65,7 +65,7 @@ const Absence = ({ route, navigation }) => {
alignment="center"
style={styles.topBar}
title="Anmäl frånvaro"
subtitle={childName(child.name)}
subtitle={studentName(child.name)}
/>
<Divider />
<Layout style={styles.wrap}>

View File

@ -24,7 +24,7 @@ import { ChildProvider, useChild } from './childContext.component'
import { Classmates } from './classmates.component'
import { NewsList } from './newsList.component'
import { NotificationsList } from './notificationsList.component'
import { childName } from '../utils/childHelpers'
import { studentName } from '../utils/peopleHelpers'
const { Navigator, Screen } = createBottomTabNavigator()
@ -72,12 +72,9 @@ const CalendarScreen = () => {
}
const ClassmatesScreen = () => {
const child = useChild()
const { data: classmates } = useClassmates(child)
return (
<Layout>
<Classmates classmates={classmates} />
<Classmates />
</Layout>
)
}
@ -148,7 +145,7 @@ export const Child = ({ route, navigation }) => {
<SafeAreaView style={{ ...styles.wrap, color }}>
<ChildProvider child={child}>
<TopNavigation
title={childName(child.name)}
title={studentName(child.name)}
alignment="center"
accessoryLeft={BackAction}
style={styles.topBar}

View File

@ -10,7 +10,7 @@ import { DateTime } from 'luxon'
import moment from 'moment'
import React, { useEffect } from 'react'
import { StyleSheet, View } from 'react-native'
import { childName } from '../utils/childHelpers'
import { studentName } from '../utils/peopleHelpers'
const NotificationsIcon = (props) => (
<Icon {...props} name="alert-circle-outline" />
@ -71,7 +71,7 @@ export const ChildListItem = ({ navigation, child, color }) => {
<Avatar source={require('../assets/avatar.png')} shape="square" />
</View>
<View style={{ margin: 20, flex: 1 }}>
<Text category="h6">{childName(child.name)}</Text>
<Text category="h6">{studentName(child.name)}</Text>
<Text category="s1">{`${getClassName()}`}</Text>
</View>
</View>

View File

@ -1,30 +1,24 @@
import { useClassmates } from '@skolplattformen/api-hooks'
import { Divider, Icon, List, ListItem, Text } from '@ui-kitten/components'
import React, { useEffect, useState } from 'react'
import React, { useState } from 'react'
import { StyleSheet } from 'react-native'
import { useChild } from './childContext.component'
import { ContactMenu } from './contactMenu.component'
import { fullName, guardians, sortByFirstName } from '../utils/peopleHelpers'
export const Classmates = () => {
const child = useChild()
const { data, status, reload } = useClassmates(child)
const [refreshing, setRefreshing] = useState(status === 'loading')
useEffect(() => {
setRefreshing(status === 'loading')
}, [status])
const refresh = () => reload()
const { data } = useClassmates(child)
const renderItemIcon = (props) => <Icon {...props} name="people-outline" />
const [selected, setSelected] = useState()
const renderItem = ({ item }) => (
const renderItem = ({ item, index }) => (
<ListItem
title={`${item.firstname} ${item.lastname}`}
accessibilityLabel={`Barn ${index + 1}`}
title={fullName(item)}
onPress={() => setSelected(item)}
description={item.guardians
.map((guardian) => `${guardian.firstname} ${guardian.lastname}`)
.join(', ')}
description={guardians(item.guardians)}
accessoryLeft={renderItemIcon}
accessoryRight={(props) =>
ContactMenu({
@ -39,13 +33,12 @@ export const Classmates = () => {
return (
<List
refreshing={refreshing}
style={styles.container}
data={data}
data={sortByFirstName(data)}
ItemSeparatorComponent={Divider}
ListHeaderComponent={
<Text category="h5" style={styles.listHeader}>
Klass {data?.length ? data[0].className : ''}
{data?.length ? `Klass ${data[0].className}` : 'Klass'}
</Text>
}
renderItem={renderItem}

View File

@ -1,15 +0,0 @@
import { childName } from '../childHelpers'
describe('#childName', () => {
test('should remove student from name', () => {
expect(childName('Alan Nilsson (elev)')).toEqual('Alan Nilsson')
})
test('should remove student without spacing from name', () => {
expect(childName('Alan Nilsson(elev)')).toEqual('Alan Nilsson')
})
test('handles undefined name', () => {
expect(childName(undefined)).toBeUndefined()
})
})

View File

@ -0,0 +1,74 @@
import {
fullName,
guardians,
sortByFirstName,
studentName,
} from '../peopleHelpers'
describe('#studentName', () => {
test('should remove student from name', () => {
expect(studentName('Alan Nilsson (elev)')).toEqual('Alan Nilsson')
})
test('should remove student without spacing from name', () => {
expect(studentName('Alan Nilsson(elev)')).toEqual('Alan Nilsson')
})
test('handles undefined name', () => {
expect(studentName(undefined)).toBeUndefined()
})
})
describe('#fullName', () => {
test('should', () => {
expect(
fullName({
firstname: 'Margaery',
lastname: 'Eriksson',
})
).toEqual('Margaery Eriksson')
})
})
describe('#sortByFirstName', () => {
test('sort arrays by first name', () => {
expect(
sortByFirstName([
{
firstname: 'Margaery',
lastname: 'Eriksson',
},
{
firstname: 'Loras',
lastname: 'Eriksson',
},
])
).toEqual([
{
firstname: 'Loras',
lastname: 'Eriksson',
},
{
firstname: 'Margaery',
lastname: 'Eriksson',
},
])
})
})
describe('#guardians', () => {
test('should join a list of guardians sorted by firstname', () => {
expect(
guardians([
{
firstname: 'Margaery',
lastname: 'Eriksson',
},
{
firstname: 'Loras',
lastname: 'Eriksson',
},
])
).toEqual('Loras Eriksson, Margaery Eriksson')
})
})

View File

@ -1 +0,0 @@
export const childName = (name) => name?.replace(/\s?\(\w+\)$/, '')

View File

@ -0,0 +1,9 @@
export const studentName = (name) => name?.replace(/\s?\(\w+\)$/, '')
export const sortByFirstName = (data) =>
data.sort((a, b) => a.firstname.localeCompare(b.firstname))
export const guardians = (data) =>
sortByFirstName(data).map(fullName).join(', ')
export const fullName = (person) => `${person.firstname} ${person.lastname}`