skolplattformen-backup/packages/app/components/childListItem.component.tsx

258 lines
7.1 KiB
TypeScript
Raw Normal View History

import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import {
useCalendar,
useMenu,
useNews,
useNotifications,
useSchedule,
} from '@skolplattformen/api-hooks'
2021-03-26 08:38:15 +00:00
import { Child } from '@skolplattformen/embedded-api'
2021-02-20 08:38:08 +00:00
import { Avatar, Button, Card, Text } from '@ui-kitten/components'
import moment from 'moment'
2021-02-20 08:38:08 +00:00
import React from 'react'
2021-03-26 09:44:46 +00:00
import { StyleSheet, View } from 'react-native'
import { Colors, Layout, Sizing } from '../styles'
import { studentName } from '../utils/peopleHelpers'
2021-04-13 15:03:14 +00:00
import { translate } from '../utils/translation'
2021-02-20 08:38:08 +00:00
import {
CalendarOutlineIcon,
MenuIcon,
2021-02-20 08:38:08 +00:00
NewsIcon,
NotificationsIcon,
} from './icon.component'
2021-03-26 08:38:15 +00:00
import { RootStackParamList } from './navigation.component'
2021-01-04 21:40:54 +00:00
2021-03-26 08:38:15 +00:00
interface ChildListItemProps {
child: Child
color: string
}
type ChildListItemNavigationProp = StackNavigationProp<
RootStackParamList,
'Children'
>
export const ChildListItem = ({ child, color }: ChildListItemProps) => {
2021-02-14 20:06:23 +00:00
// Forces rerender when child.id changes
2021-02-20 08:38:08 +00:00
React.useEffect(() => {}, [child.id])
2021-02-14 20:06:23 +00:00
const navigation = useNavigation<ChildListItemNavigationProp>()
const { data: notifications, status: notificationsStatus } = useNotifications(
child
)
const { data: news, status: newsStatus } = useNews(child)
const { data: calendar, status: calendarStatus } = useCalendar(child)
const { data: schedule } = useSchedule(
child,
moment().toISOString(),
moment().add(7, 'days').toISOString()
)
const { status: menuStatus } = useMenu(child)
2021-01-04 21:40:54 +00:00
const notificationsThisWeek = notifications.filter(({ dateCreated }) =>
2021-04-01 11:41:36 +00:00
dateCreated ? moment(dateCreated).isSame(moment(), 'week') : false
)
const newsThisWeek = news.filter(({ published }) =>
published ? moment(published).isSame(moment(), 'week') : false
)
const scheduleAndCalendarThisWeek = [
...(calendar ?? []),
...(schedule ?? []),
2021-04-01 11:41:36 +00:00
].filter(({ startDate }) =>
startDate
? moment(startDate).isBetween(
moment().startOf('day'),
moment().add(7, 'days')
)
: false
2021-04-01 11:41:36 +00:00
)
const displayDate = (date: moment.MomentInput) => {
return moment(date).fromNow()
}
const getClassName = () => {
// Taken from Skolverket
// https://www.skolverket.se/skolutveckling/anordna-och-administrera-utbildning/administrera-utbildning/skoltermer-pa-engelska
const abbrevations = {
G: translate('abbrevations.upperSecondarySchool'),
GR: translate('abbrevations.compulsorySchool'),
F: translate('abbrevations.leisureTimeCentre'),
FS: translate('abbrevations.preSchool'),
}
return child.status
? child.status
.split(';')
.map((status) => {
const statusAsAbbreviation = status as keyof typeof abbrevations
return abbrevations[statusAsAbbreviation] || status
})
.join(', ')
: null
}
const className = getClassName()
const Footer = () => (
<View style={styles.itemFooter}>
<Button
style={[styles.item, styles[newsStatus]]}
status="control"
size="small"
onPress={() =>
navigation.navigate('Child', {
child,
color,
2021-04-14 08:11:49 +00:00
initialRouteName: translate('navigation.news'),
})
}
accessoryLeft={NewsIcon}
>
{`${(news || []).length}`}
</Button>
<Button
style={[styles.item, styles[notificationsStatus]]}
status="control"
size="small"
onPress={() =>
navigation.navigate('Child', {
child,
color,
2021-04-14 08:11:49 +00:00
initialRouteName: translate('navigation.notifications'),
})
}
accessoryLeft={NotificationsIcon}
>
{`${(notifications || []).length}`}
</Button>
<Button
style={[styles.item, styles[calendarStatus]]}
status="control"
size="small"
onPress={() =>
navigation.navigate('Child', {
child,
color,
2021-04-14 08:11:49 +00:00
initialRouteName: translate('navigation.calender'),
})
}
accessoryLeft={CalendarOutlineIcon}
>
{`${(calendar || []).length}`}
</Button>
<Button
style={[styles.item, styles[menuStatus]]}
status="control"
size="small"
onPress={() =>
navigation.navigate('Child', {
child,
color,
2021-04-14 08:15:59 +00:00
initialRouteName: translate('navigation.menu'),
})
}
accessoryLeft={MenuIcon}
/>
</View>
2021-01-04 21:40:54 +00:00
)
return (
<Card
style={styles.card}
appearance="filled"
2021-01-04 21:40:54 +00:00
status={color}
2021-03-26 08:38:15 +00:00
header={(props) => (
<View {...props} style={styles.cardHeader}>
<View style={styles.cardAvatar}>
<Avatar source={require('../assets/avatar.png')} shape="square" />
</View>
<View style={styles.cardHeaderText}>
<Text category="h6">{studentName(child.name)}</Text>
{className ? <Text category="s1">{className}</Text> : null}
2021-03-26 08:38:15 +00:00
</View>
</View>
)}
2021-01-04 21:40:54 +00:00
footer={Footer}
onPress={() => navigation.navigate('Child', { child, color })}
>
{scheduleAndCalendarThisWeek.slice(0, 3).map((calendarItem, i) => (
<Text appearance="hint" category="c1" key={i}>
{`${calendarItem.title} (${displayDate(calendarItem.startDate)})`}
</Text>
))}
{notificationsThisWeek.slice(0, 3).map((notification, i) => (
<Text appearance="hint" category="c1" key={i}>
{translate('notifications.notificationTitle', {
message: notification.message,
dateCreated: displayDate(notification.dateCreated),
})}
</Text>
))}
{newsThisWeek.slice(0, 3).map((newsItem, i) => (
<Text appearance="hint" category="c1" key={i}>
{translate('news.notificationTitle', {
header: newsItem.header,
published: displayDate(newsItem.published),
})}
</Text>
))}
{scheduleAndCalendarThisWeek.length ||
notificationsThisWeek.length ||
newsThisWeek.length ? null : (
<Text appearance="hint" category="c1">
{translate('news.noNewNewsItemsThisWeek')}
</Text>
)}
<View style={styles.itemFooterAbsence}>
<Button
size="small"
onPress={() => navigation.navigate('Absence', { child })}
>
2021-04-13 15:03:14 +00:00
{translate('abscense.title')}
</Button>
</View>
2021-01-04 21:40:54 +00:00
</Card>
)
}
const styles = StyleSheet.create({
card: {
marginBottom: Sizing.t5,
2021-01-04 21:40:54 +00:00
},
cardHeader: {
...Layout.flex.row,
...Layout.mainAxis.center,
},
cardAvatar: { margin: Sizing.t5, marginRight: 0 },
cardHeaderText: { margin: Sizing.t5, flex: 1 },
2021-01-04 21:40:54 +00:00
itemFooter: {
...Layout.flex.row,
...Layout.crossAxis.evenly,
paddingVertical: Sizing.t2,
2021-01-05 11:27:38 +00:00
borderRadius: 5,
margin: 0,
2021-01-05 11:27:38 +00:00
},
itemFooterAbsence: {
...Layout.mainAxis.flexStart,
marginTop: Sizing.t4,
},
item: {
2021-01-05 11:27:38 +00:00
paddingHorizontal: 0,
},
loaded: {
color: Colors.neutral.black,
2021-01-04 21:40:54 +00:00
},
2021-01-05 11:27:38 +00:00
loading: {
color: '#555',
},
error: {
color: '#500',
},
2021-03-26 08:38:15 +00:00
pending: {},
2021-01-04 21:40:54 +00:00
})