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

Updated in handling async loading and updated layout and colors and illustrations #14

Merged
merged 11 commits into from
Dec 23, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default () => {
return (
<>
<IconRegistry icons={EvaIconsPack}/>
<ApplicationProvider {...eva} theme={{...eva.light, ...customization}}>
<ApplicationProvider {...eva} theme={{...eva.light, ...customization}} >
<AppNavigator />
</ApplicationProvider>
</>
Expand Down
Binary file modified packages/app/assets/avatar.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/assets/boys.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/app/assets/children.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/assets/girls.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/app/assets/man.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 1 addition & 4 deletions packages/app/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
production: {
plugins: ["transform-remove-console"]
}
presets: ['module:metro-react-native-babel-preset']
};
27 changes: 16 additions & 11 deletions packages/app/components/calendar.component.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { Divider, List, ListItem, Icon, Text} from '@ui-kitten/components';
import { StyleSheet, Image, View } from 'react-native';
import { Divider, List, ListItem, Icon, Text, Layout} from '@ui-kitten/components';
import moment from 'moment'
import 'moment/locale/sv' // without this line it didn't work
moment.locale('sv')

export const Calendar = ({calendar}) => {

const parseMoment = (date) => moment(date, 'YYYY-MM-DD hh:mm')

const renderItemIcon = (startDate, endDate) =>
(props) => <Icon {...props} fill={parseMoment(startDate).isBefore() && parseMoment(endDate).isAfter() ? '#33f' : '#333'} name={parseMoment(endDate || startDate).isBefore() ? 'calendar' : 'calendar-outline'}/>
(props) => <Icon {...props} fill={moment(startDate).isBefore() && moment(endDate).isAfter() ? '#33f' : '#333'} name={moment(endDate || startDate).isBefore() ? 'calendar' : 'calendar-outline'}/>

const renderItem = ({ item }) => (
<ListItem
title={`${item.title}`}
description={`${moment(item.startDate).calendar()}`}
description={`${moment(item.startDate).locale('sv').calendar()}`}
accessoryLeft={renderItemIcon(item.startDate, item.endDate)}
/>
);


return (
)

return (!calendar?.length ?
<View style={{flex: 1}}>
<Image source={require('../assets/girls.png')} style={{height: 200, width: '100%'}}></Image>
<Text category="h5">Det ser lite tomt ut i kalendern</Text>
</View>
:
<List
style={styles.container}
data={calendar.sort((a, b) => b.startDate < a.startDate)}
ItemSeparatorComponent={Divider}
renderItem={renderItem}
/>
);
};
)
}

const styles = StyleSheet.create({
container: {
Expand Down
61 changes: 44 additions & 17 deletions packages/app/components/child.component.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { StyleSheet } from 'react-native';
import { TabBar, TopNavigation, TopNavigationAction, Tab, TabView, Layout, Text, Divider, Icon } from '@ui-kitten/components'
import { TabBar, TopNavigation, TopNavigationAction, Tab, TabView, OverflowMenu, MenuItem, Layout, Text, Divider, Icon } from '@ui-kitten/components'
import { NewsList } from './newsList.component'
import { Calendar } from './calendar.component'
import { Classmates } from './classmates.component'
Expand All @@ -10,6 +10,7 @@ import moment from 'moment'
export const Child = ({route, navigation}) => {
const [selectedIndex, setSelectedIndex] = React.useState(0)
const { child, color } = route.params;
const [menuVisible, setMenuVisible] = React.useState(false);

const NewsIcon = (props) => (
<Icon {...props} name='activity-outline'/>
Expand All @@ -22,13 +23,20 @@ export const Child = ({route, navigation}) => {
<Icon {...props} name='people-outline'/>
)

const EditIcon = (props) => (
<Icon {...props} name='edit'/>
)
const SettingsIcon = (props) => (
<Icon {...props} name='options-2-outline'/>
)

const BackIcon = (props) => (
<Icon {...props} name='arrow-back' />
)

const MenuIcon = (props) => (
<Icon {...props} name='more-vertical'/>
)

const BackAction = () => (
<TopNavigationAction icon={BackIcon} onPress={navigateBack} />
)
Expand All @@ -37,38 +45,54 @@ export const Child = ({route, navigation}) => {
navigation.goBack()
}



const toggleMenu = () => {
setMenuVisible(!menuVisible);
}

const renderMenuAction = () => (
<TopNavigationAction icon={MenuIcon} onPress={toggleMenu}/>
)

const renderRightActions = () => (
<React.Fragment>
<OverflowMenu
anchor={renderMenuAction}
visible={menuVisible}
backdropStyle={styles.backdrop}
onBackdropPress={toggleMenu}>
<MenuItem accessoryLeft={SettingsIcon} title='Anmäl frånvaro'/>
</OverflowMenu>
</React.Fragment>
);

return (
<SafeAreaView style={{ flex: 1 }} style={{...styles.topBar, color: color}}>
<TopNavigation title={ child.name} alignment='center' accessoryLeft={BackAction} style={{...styles.topBar, color: color}}/>
<TabView selectedIndex={selectedIndex} tabBarStyle={{color}} indicatorStyle={{backgroundColor: color, color}} onSelect={index => setSelectedIndex(index)}>
<TopNavigation title={ child.name}
alignment='center'
accessoryLeft={BackAction}
accessoryRight={renderRightActions}
style={styles.topBar}/>
<TabView selectedIndex={selectedIndex} onSelect={index => setSelectedIndex(index)}>
<Tab title="Nyheter" icon={NewsIcon}>
<Layout style={styles.tabContainer}>
<NewsList news={child.news} />
</Layout>
</Tab>
<Tab title="Schema" icon={CalendarIcon}>
<Layout style={styles.tabContainer}>
<Calendar calendar={[...child.calendar, ...child.schedule].filter(a => moment(a.startDate).isAfter(moment().startOf('day')) ) }></Calendar>
<Calendar calendar={[...child.calendar, ...child.schedule].filter(a => moment(a.startDate, 'YYYY-MM-DD hh:mm').isAfter(moment().startOf('day')) ) }></Calendar>
</Layout>
</Tab>
<Tab title="Klassen" icon={ClassIcon}>
<Layout style={styles.tabContainer}>
<Text category='h5'>
Klass {child.classmates.length ? child.classmates[0].className : ''}
Klass {child.classmates?.length ? child.classmates[0].className : ''}
</Text>
<Classmates classmates={child.classmates}/>
</Layout>
</Tab>
<Tab title="Inställningar" icon={SettingsIcon}>
<Layout style={styles.tabContainer}>
<Text category='h5'>
Inställningar
</Text>
<Text category='c2'>
Här kommer du kunna sjukanmäla och göra andra bra grejer...
</Text>
</Layout>
</Tab>
</TabView>

</SafeAreaView>
Expand All @@ -83,8 +107,11 @@ const styles = StyleSheet.create({
tabContainer: {
alignItems: 'flex-start',
justifyContent: 'flex-start',
paddingTop: 5,
paddingTop: 10,
paddingLeft: 10,
flexDirection: 'column'
},
backdrop: {
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
})
82 changes: 38 additions & 44 deletions packages/app/components/children.component.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React, {useState, useMemo, useCallback, useEffect } from 'react'
import { StyleSheet, View, Image } from 'react-native'
import { SafeAreaView } from 'react-native'
import useFetch from 'use-http'
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 '@rnhooks/async-storage'
import {api} from '../lib/backend'
import {useAsyncStorage} from 'use-async-storage'
import {api, loadChildrenDetails} from '../lib/backend'

const colors = ['#F2FDD3', '#CEFEF1', '#FEF2DC', '#FEE2E3', '#CB4D93']
const colors = ['primary', 'success', 'info', 'warning', 'danger']

const BackIcon = (props) => (
<Icon {...props} name='arrow-back' />
Expand All @@ -27,46 +26,34 @@ const PeopleIcon = (style) => (
)

export const Children = ({navigation}) => {
const [savedChildren, setSavedChildren, clearSavedChildren] = useAsyncStorage('@children', '[]')
const [children, setChildren] = useState(JSON.parse(savedChildren) || [])
const [children, setChildren] = useAsyncStorage('@children', [])

useEffect(() => {
const load = async () => {
try {
const children = await api.getChildren()

if (!children.length) {
const childrenList = children?.length || await api.getChildren()
if (!childrenList?.length) {
console.log('no children found')
return navigation.navigate('Login', {error: 'Hittar inga barn med det personnumret'})
}
console.log('got children', children)
//setChildren(children)

//TODO: lazy load these
const fullChildren = await Promise.all(children.map(async child => ({
...child,
news: await api.getNews(child),
calendar: await api.getCalendar(child),
classmates: await api.getClassmates(child),
schedule: await api.getSchedule(child, moment().startOf('day'), moment().add(7,'days').endOf('day')),
menu: await api.getMenu(child),
notifications: await api.getNotifications(child),
})))
console.log('full', fullChildren)

// 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)
setSavedChildren(JSON.stringify(savedChildren))

} catch (err) {
console.log('err', err)
navigation.navigate('Login', {error: 'Fel uppstod, försök igen'})
}
}
load()
}, [])
if (api.isLoggedIn) load()
}, [api.isLoggedIn])

return <ChildrenView navigation={navigation} children={children}></ChildrenView>
}


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



Expand All @@ -88,9 +75,9 @@ export const ChildrenView = ({ navigation, children }) => {
)

const Header = (props, info, i) => (
<View {...props} style={{flexDirection: 'row', backgroundColor: colors[i % colors.length]}}>
<View {...props} style={{flexDirection: 'row'}}>
<View style={{margin: 20}}>
<Avatar source={require('../assets/avatar.png')} />
<Avatar source={require('../assets/avatar.png')} shape="square" />
</View>
<View style={{margin: 20}}>
<Text category='h6'>
Expand All @@ -117,7 +104,7 @@ export const ChildrenView = ({ navigation, children }) => {
status='control'
size='small'
accessoryLeft={CalendarIcon}>
{`${(info.item.notifications || []).filter(c => moment(c.startDate).isSame('day') ).length} idag`}
{`${(info.item.notifications || []).filter(c => moment(c.startDate, 'YYYY-MM-DD hh:mm').isSame('day') ).length} idag`}
</Button>
<Button
style={styles.iconButton}
Expand All @@ -130,36 +117,43 @@ export const ChildrenView = ({ navigation, children }) => {
)

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

{([...info.item.calendar, ...info.item.schedule].filter(a => moment(a.startDate).isSame('day'))).map((calendarItem, i) => <Text appearance='hint' category='c1' key={i}>
{`${calendarItem.title}`}
</Text>
{([...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: '#fff' }}>
<TopNavigation title='Dina barn' alignment='center' accessoryLeft={BackAction} />
<SafeAreaView style={{ flex: 1, backgroundColor: 'transparent'}}>
<TopNavigation title='Dina barn' alignment='center' accessoryLeft={BackAction} />
<Divider/>
<Layout style={{ flex: 1 }} level='1'>
{children.length ? <List
style={styles.container}
contentContainerStyle={styles.contentContainer}
data={children}
renderItem={renderItem} />
{children?.length ? <Layout style={{ flex: 1, justifyContent: 'space-between' }}>
<List
style={styles.container}
contentContainerStyle={styles.contentContainer}
data={children}
renderItem={renderItem} />
</Layout>
: <Layout style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Image source={require('../assets/undraw_teaching_f1cm.png')} style={{height: 400, width: '100%'}}></Image>
<Image source={require('../assets/girls.png')} style={{height: 400, width: '100%'}}></Image>
<View style={{flexDirection: 'row'}}>
<Spinner size='large'/>
<Spinner size='large' status="warning"/>
<Text category='h1' style={{marginLeft: 10, marginTop: -7}}>Laddar...</Text>
</View>
</Layout>}

</Layout>
</SafeAreaView>
)
Expand Down