Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/generators + minor fixes #16

Merged
merged 3 commits into from
Dec 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions packages/api/lib/backend.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const moment = require('moment')
const h2m = require('h2m')
const {htmlDecode} = require('js-htmlencode')
const { htmlDecode } = require('js-htmlencode')
const urls = require('./urls')

const { fetchJson, fetchText, fetchRaw } = require('./fetch')
Expand All @@ -16,7 +16,7 @@ const login = async (socialSecurityNumber) => {
return token
}

const waitForToken = async ({order}, tries = 60) => {
const waitForToken = async ({ order }, tries = 60) => {
if (!tries) return Promise.reject('Timeout')
const status = await fetchText(urls.checkStatus(order))
if (status === 'OK') {
Expand All @@ -25,18 +25,18 @@ const waitForToken = async ({order}, tries = 60) => {
} else {
await pause(1000)
console.log('retry', tries)
return await waitForToken({order}, tries--)
return await waitForToken({ order }, tries--)
}
}

const getChildren = async (cookie) => {
const children = await fetchJson(urls.children, cookie)
return children
.map(({name, id, sdsId, status, schoolId}) =>
({name, id, sdsId, status, schoolId}))
.map(({ name, id, sdsId, status, schoolId }) =>
({ name, id, sdsId, status, schoolId }))
}

const getNews = async(childId, cookie) => {
const getNews = async (childId, cookie) => {
const news = await fetchJson(urls.news(childId), cookie)
return news
.newsItems
Expand All @@ -60,7 +60,7 @@ const getNews = async(childId, cookie) => {
const getCalendar = async (childId, cookie) => {
const url = urls.calendar(childId)
const calendar = await fetchJson(url, cookie)

return calendar
.map(({
title,
Expand All @@ -84,7 +84,7 @@ const getCalendar = async (childId, cookie) => {
const getNotifications = async (childId, cookie) => {
const url = urls.notifications(childId)
const notifications = await fetchJson(url, cookie)

return notifications
.map(({
notificationMessage: {
Expand Down Expand Up @@ -124,7 +124,7 @@ const getSchedule = async (childId, cookie) => {
const to = moment().add(7, 'days').format('YYYY-MM-DD')
const url = urls.schedule(childId, from, to)
const schedule = await fetchJson(url, cookie)

return schedule
.map(({
title,
Expand All @@ -150,7 +150,7 @@ const getSchedule = async (childId, cookie) => {
const getClassmates = async (childId, cookie) => {
const url = urls.classmates(childId)
const classmates = await fetchJson(url, cookie)

return classmates
.map(({
sisId,
Expand Down Expand Up @@ -191,10 +191,10 @@ const getChildById = async (childId, cookie) => {
menu,
schedule
] = [
await getNews(childId, cookie),
await getCalendar(childId, cookie),
await getNotifications(child.sdsId, cookie),
await getMenu(child.id, cookie),
await getNews(childId, cookie),
await getCalendar(childId, cookie),
await getNotifications(child.sdsId, cookie),
await getMenu(child.id, cookie),
await getSchedule(child.id, cookie)
]

Expand All @@ -220,4 +220,4 @@ module.exports = {
getSchedule,
getClassmates,
download
}
}
135 changes: 74 additions & 61 deletions packages/app/components/children.component.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, {useState, useMemo, useCallback, useEffect } from 'react'
import { StyleSheet, View, Image } from 'react-native'
import { SafeAreaView } from 'react-native'
import React, { useEffect } from 'react'
import { StyleSheet, View, Image, SafeAreaView } from 'react-native'

import moment from 'moment'
import { Divider, Button, Icon, Layout, Text, TopNavigation, TopNavigationAction, List, Card, Avatar, Spinner } from '@ui-kitten/components'
// import children from '../output.json'
import {useAsyncStorage} from 'use-async-storage'
import {api, loadChildrenDetails} from '../lib/backend'
import { useAsyncStorage } from 'use-async-storage'
import { api, fillChild } from '../lib/backend'

const colors = ['primary', 'success', 'info', 'warning', 'danger']

Expand All @@ -25,38 +25,41 @@ const PeopleIcon = (style) => (
<Icon {...style} name='people-outline' />
)

export const Children = ({navigation}) => {
export const Children = ({ navigation }) => {
const [children, setChildren] = useAsyncStorage('@children', [])

const [cookie] = useAsyncStorage('@cookie')
useEffect(() => {
const load = async () => {
try {
const childrenList = children?.length || await api.getChildren()
const childrenList = (children?.length && children) || await api.getChildren()
if (!childrenList?.length) {
console.log('no children found')
return navigation.navigate('Login', {error: 'Hittar inga barn med det personnumret'})
console.log('no children found', await api.getChildren())
return navigation.navigate('Login', { error: 'Hittar inga barn för det personnumret' })
}

// Update the list with all details we get the most often updated info first
const fullChildren = await loadChildrenDetails(childrenList, {calendar: true, schedule: true, news: true, menu:true, notifications: true, classmates: true})
setChildren(fullChildren)

childrenList.forEach(async (child, i) => {
let result
let updatedChild // keep a reference to the latest updated information so we don't patch an old object
const iter = fillChild(child)
while (!result?.done) {
result = await iter.next() // get updated values for every updated property
if (result.done) break
const updated = await result.value
childrenList[i] = updatedChild = { ...updatedChild, ...updated }
await setChildren(childrenList) // update after each new information we get. Might be too much?
}
})
} catch (err) {
console.log('err', err)
navigation.navigate('Login', {error: 'Fel uppstod, försök igen'})
navigation.navigate('Login', { error: 'Fel uppstod, försök igen' })
}
}
if (api.isLoggedIn) load()
}, [api.isLoggedIn])

return <ChildrenView navigation={navigation} children={children}></ChildrenView>
if (cookie) load()
}, [cookie])
return <ChildrenView navigation={navigation} childList={children} />
}


export const ChildrenView = ({ navigation, children, eva }) => {



export const ChildrenView = ({ navigation, childList, eva }) => {
const abbrevations = {
G: 'Gymnasiet', // ? i'm guessing here
GR: 'Grundskolan',
Expand All @@ -67,19 +70,19 @@ export const ChildrenView = ({ navigation, children, eva }) => {
}

const navigateChild = (child, color) => {
navigation.navigate('Child', {child, color})
navigation.navigate('Child', { child, color })
}

const BackAction = () => (
<TopNavigationAction icon={BackIcon} onPress={navigateBack} />
)

const Header = (props, info, i) => (
<View {...props} style={{flexDirection: 'row'}}>
<View style={{margin: 20}}>
<Avatar source={require('../assets/avatar.png')} shape="square" />
<View {...props} style={{ flexDirection: 'row' }}>
<View style={{ margin: 20 }}>
<Avatar source={require('../assets/avatar.png')} shape='square' />
</View>
<View style={{margin: 20}}>
<View style={{ margin: 20 }}>
<Text category='h6'>
{info.item.name?.split('(')[0]}
</Text>
Expand All @@ -96,63 +99,73 @@ export const ChildrenView = ({ navigation, children, eva }) => {
style={styles.iconButton}
status='control'
size='small'
accessoryLeft={NotificationIcon}>
accessoryLeft={NotificationIcon}
>
{`${(info.item.news || []).length}`} nyheter
</Button>
<Button
style={styles.iconButton}
status='control'
size='small'
accessoryLeft={CalendarIcon}>
{`${(info.item.notifications || []).filter(c => moment(c.startDate, 'YYYY-MM-DD hh:mm').isSame('day') ).length} idag`}
accessoryLeft={CalendarIcon}
>
{`${(info.item.notifications || []).filter(c => moment(c.startDate, 'YYYY-MM-DD hh:mm').isSame('day')).length} idag`}
</Button>
<Button
style={styles.iconButton}
status='control'
size='small'
accessoryLeft={PeopleIcon}>
accessoryLeft={PeopleIcon}
>
{`${(info.item.classmates || []).length} elever`}
</Button>
</View>
)

const renderItem = (info) => {
const color = colors[info.index % colors.length]
return <Card
style={{...styles.card}}
appearance="filled"
status={color}
header={headerProps => Header(headerProps, info, info.index)}
footer={footerProps => Footer(footerProps, info)}
onPress={() => navigateChild(info.item, color)}>

{([...info.item.calendar, ...info.item.schedule].filter(a => moment(a.startDate, 'YYYY-MM-DD hh:mm').isSame('day'))).map((calendarItem, i) =>
<Text appearance='hint' category='c1' key={i}>
{`${calendarItem.title}`}
</Text>
)}
</Card>
return (
<Card
style={{ ...styles.card }}
appearance='filled'
status={color}
header={headerProps => Header(headerProps, info, info.index)}
footer={footerProps => Footer(footerProps, info)}
onPress={() => navigateChild(info.item, color)}
>

{([...info.item.calendar ?? [], ...info.item.schedule ?? []].filter(a => moment(a.startDate, 'YYYY-MM-DD hh:mm').isSame('day'))).map((calendarItem, i) =>
<Text appearance='hint' category='c1' key={i}>
{`${calendarItem.title}`}
</Text>
)}
</Card>
)
}

return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'transparent'}}>
<TopNavigation title='Dina barn' alignment='center' accessoryLeft={BackAction} />
<Divider/>
<SafeAreaView style={{ flex: 1, backgroundColor: 'transparent' }}>
<TopNavigation title='Dina barn' alignment='center' accessoryLeft={BackAction} />
<Divider />
<Layout style={{ flex: 1 }} level='1'>
{children?.length ? <Layout style={{ flex: 1, justifyContent: 'space-between' }}>
{
childList?.length
? <Layout style={{ flex: 1, justifyContent: 'space-between' }}>
<List
style={styles.container}
contentContainerStyle={styles.contentContainer}
data={children}
renderItem={renderItem} />
style={styles.container}
contentContainerStyle={styles.contentContainer}
data={childList}
renderItem={renderItem}
/>
</Layout>
: <Layout style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Image source={require('../assets/girls.png')} style={{height: 400, width: '100%'}}></Image>
<View style={{flexDirection: 'row'}}>
<Spinner size='large' status="warning"/>
<Text category='h1' style={{marginLeft: 10, marginTop: -7}}>Laddar...</Text>
</View>
</Layout>}
<Image source={require('../assets/girls.png')} style={{ height: 400, width: '100%' }} />
<View style={{ flexDirection: 'row' }}>
<Spinner size='large' status='warning' />
<Text category='h1' style={{ marginLeft: 10, marginTop: -7 }}>Laddar...</Text>
</View>
</Layout>
}

</Layout>
</SafeAreaView>
Expand Down
29 changes: 15 additions & 14 deletions packages/app/components/classmates.component.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { Divider, List, ListItem, Icon, Text, Button} from '@ui-kitten/components';
import { ContactMenu } from './contactMenu.component';
import React from 'react'
import { StyleSheet } from 'react-native'
import { Divider, List, ListItem, Icon } from '@ui-kitten/components'
import { ContactMenu } from './contactMenu.component'

export const Classmates = ({classmates}) => {

const renderItemIcon = (props) => <Icon {...props} name={'people-outline'}/>
export const Classmates = ({ classmates }) => {
const renderItemIcon = (props) => <Icon {...props} name='people-outline' />
const [selected, setSelected] = React.useState()

const renderItem = ({ item }) => (
<ListItem
title={`${item.firstname} ${item.lastname}`}
onPress={() => setSelected(item)}
description={item.guardians.map(guardian => `${guardian.firstname} ${guardian.lastname}`).join(', ')}
accessoryLeft={renderItemIcon}
accessoryRight={(props) => ContactMenu({...props, contact: item})}
accessoryRight={(props) => ContactMenu({ ...props, contact: item, selected: item === selected, setSelected })}
/>
);
)

return (
<List
Expand All @@ -23,11 +24,11 @@ export const Classmates = ({classmates}) => {
ItemSeparatorComponent={Divider}
renderItem={renderItem}
/>
);
};
)
}

const styles = StyleSheet.create({
container: {
width: "100%",
},
});
width: '100%'
}
})
Loading