|
@ -14,7 +14,7 @@ export default () => {
|
|||
return (
|
||||
<>
|
||||
<IconRegistry icons={EvaIconsPack}/>
|
||||
<ApplicationProvider {...eva} theme={{...eva.light, ...customization}}>
|
||||
<ApplicationProvider {...eva} theme={{...eva.light, ...customization}} >
|
||||
<AppNavigator />
|
||||
</ApplicationProvider>
|
||||
</>
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
<entry key="imagePath" value="/private/var/folders/ry/0xbqnmj96xx4x4pzt83lvpy40000gn/T/ic_android_black_24dp.xml" />
|
||||
</map>
|
||||
</option>
|
||||
|
@ -79,7 +80,7 @@
|
|||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
<entry key="imagePath" value="$USER_HOME$/Downloads/Skolplattformen logo.svg" />
|
||||
<entry key="imagePath" value="$USER_HOME$/Downloads/SpAppIcons/playstore.png" />
|
||||
<entry key="scalingPercent" value="70" />
|
||||
</map>
|
||||
</option>
|
||||
|
@ -113,7 +114,8 @@
|
|||
<option name="values">
|
||||
<map>
|
||||
<entry key="backgroundAssetType" value="COLOR" />
|
||||
<entry key="backgroundColor" value="006ec5" />
|
||||
<entry key="backgroundColor" value="f5f5f6" />
|
||||
<entry key="legacyIconShape" value="CIRCLE" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
|
|
|
@ -96,7 +96,7 @@ def enableSeparateBuildPerCPUArchitecture = false
|
|||
/**
|
||||
* Run Proguard to shrink the Java bytecode in release builds.
|
||||
*/
|
||||
def enableProguardInReleaseBuilds = false
|
||||
def enableProguardInReleaseBuilds = true
|
||||
|
||||
/**
|
||||
* The preferred build flavor of JavaScriptCore.
|
||||
|
@ -132,8 +132,8 @@ android {
|
|||
applicationId "se.kolplattformen.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 15
|
||||
versionName "0.0.1"
|
||||
versionCode 20
|
||||
versionName "0.0.2"
|
||||
}
|
||||
splits {
|
||||
abi {
|
||||
|
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 399 KiB |
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 15 KiB |
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#006EC5</color>
|
||||
<color name="ic_launcher_background">#F5F5F6</color>
|
||||
</resources>
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 569 KiB |
Before Width: | Height: | Size: 351 KiB After Width: | Height: | Size: 349 KiB |
After Width: | Height: | Size: 396 KiB |
Before Width: | Height: | Size: 422 KiB After Width: | Height: | Size: 537 KiB |
|
@ -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']
|
||||
};
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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'
|
||||
|
@ -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'/>
|
||||
|
@ -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} />
|
||||
)
|
||||
|
@ -37,10 +45,36 @@ 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} />
|
||||
|
@ -48,27 +82,17 @@ export const Child = ({route, navigation}) => {
|
|||
</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>
|
||||
|
@ -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)',
|
||||
},
|
||||
})
|
|
@ -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' />
|
||||
|
@ -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 }) => {
|
||||
|
||||
|
||||
|
||||
|
@ -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'>
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { useEffect } from 'react'
|
||||
import { Platform } from 'react-native'
|
||||
import { SafeAreaView, StyleSheet, Image, Linking, KeyboardAvoidingView, View } from 'react-native'
|
||||
import { SafeAreaView, StyleSheet, Image, Linking, KeyboardAvoidingView, TouchableOpacity, View } from 'react-native'
|
||||
import { Button, Icon, Modal, Card, Text, ImageBackground, Divider, Layout, TopNavigation, Input } from '@ui-kitten/components'
|
||||
import Personnummer from 'personnummer'
|
||||
import useAsyncStorage from '@rnhooks/async-storage'
|
||||
import {useAsyncStorage} from 'use-async-storage'
|
||||
import { ScrollView } from 'react-native-gesture-handler'
|
||||
import {api} from '../lib/backend'
|
||||
|
||||
|
@ -17,21 +17,11 @@ export const Login = ({ navigation, route }) => {
|
|||
const [argument, setArgument] = React.useState('öppna')
|
||||
const [error, setError] = React.useState(null)
|
||||
const [hasBankId, setHasBankId] = React.useState(false)
|
||||
const [socialSecurityNumber, setSocialSecurityNumber, clearSocialSecurityNumber] = useAsyncStorage('@socialSecurityNumber')
|
||||
const [socialSecurityNumber, setSocialSecurityNumber] = useAsyncStorage('@socialSecurityNumber')
|
||||
const [cookie, setCookie, clearCookie] = useAsyncStorage('@cookie')
|
||||
|
||||
useEffect(() => {
|
||||
setValid(Personnummer.valid(socialSecurityNumber))
|
||||
const url = Platform.OS == 'ios' ? 'https://app.bankid.com/' : 'bankid:///'
|
||||
setHasBankId(Linking.canOpenURL(url))
|
||||
if (route.params?.error) setError(route.params.error)
|
||||
console.log('effect')
|
||||
if (cookie) {
|
||||
console.log('cookie', cookie)
|
||||
api.setSessionCookie(cookie)
|
||||
setLoggedIn(true)
|
||||
navigateToChildren()
|
||||
}
|
||||
}, [socialSecurityNumber, cookie])
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -88,9 +78,9 @@ export const Login = ({ navigation, route }) => {
|
|||
loginStatus.on("ERROR", () => setError('Inloggningen misslyckades, försök igen!') && setVisible(false))
|
||||
loginStatus.on("OK", async () => {
|
||||
setLoggedIn(true)
|
||||
navigateToChildren()
|
||||
const session = api.getSessionCookie()
|
||||
setCookie(session)
|
||||
navigateToChildren()
|
||||
setVisible(false)
|
||||
})
|
||||
}
|
||||
|
@ -107,8 +97,8 @@ export const Login = ({ navigation, route }) => {
|
|||
<TopNavigation title={`Skolplattformen.org - det ${argument} alternativet`} alignment='center'/>
|
||||
{loggedIn ? <Layout style={{ flex: 1, justifyContent: 'center', alignItems: 'center'}}>
|
||||
|
||||
<Image source={require('../assets/man.png')} style={{maxHeight: 300, width: '100%' }}></Image>
|
||||
<View style={{ margin: 30, justifyContent: 'flex-start', alignItems: 'flex-start', flex: 1}}>
|
||||
<Image source={require('../assets/man.png')} style={{maxHeight: 300, width: '100%', borderBottomWidth:1 }}></Image>
|
||||
<View style={{ marginTop: 80, justifyContent: 'flex-start', alignItems: 'flex-start', flex: 1}}>
|
||||
<Text category="h4">{socialSecurityNumber}</Text>
|
||||
<Text>{error ? error : 'Hurra, du är inloggad!'}</Text>
|
||||
<Button
|
||||
|
@ -129,25 +119,30 @@ export const Login = ({ navigation, route }) => {
|
|||
</View>
|
||||
</Layout>
|
||||
: <KeyboardAvoidingView>
|
||||
<Layout style={{ flex: 1 }}>
|
||||
<Image source={require('../assets/children.png')} style={{height: 270, width: '100%'}}></Image>
|
||||
<View style={{ flex: 1, justifyContent: 'flex-start', alignItems: 'flex-start', paddingHorizontal: 20}}>
|
||||
<Text category="h3">Vårdnadshavare</Text>
|
||||
<Layout style={{ flex: 1 }}>
|
||||
{
|
||||
// hidden easter egg, just touch the image to login without bankId if you still have a valid token
|
||||
}
|
||||
<TouchableOpacity onPress={navigateToChildren} style={{height: 320}}>
|
||||
<Image source={require('../assets/boys.png')} style={{height: 320, marginTop: -20, marginLeft: -10, width: '110%'}}></Image>
|
||||
</TouchableOpacity>
|
||||
<View style={{ flex: 1, justifyContent: 'flex-start', alignItems: 'flex-start', paddingHorizontal: 20}}>
|
||||
<Input label='Personnummer' autoFocus={true} value={socialSecurityNumber}
|
||||
style={{minHeight:70}}
|
||||
accessoryLeft = {PersonIcon}
|
||||
caption={error && error.message || ''}
|
||||
onChangeText = {text => handleInput(text)}
|
||||
placeholder="Ditt personnr (10 eller 12 siffror)"/>
|
||||
<Button onPress={startLogin} style={{width: "100%"}}
|
||||
appearence='ghost'
|
||||
disabled={!valid}
|
||||
status='primary'
|
||||
accessoryRight={SecureIcon}
|
||||
size='medium'>
|
||||
Öppna BankID
|
||||
</Button>
|
||||
</View>
|
||||
style={{minHeight:70}}
|
||||
accessoryLeft = {PersonIcon}
|
||||
keyboardType='numeric'
|
||||
caption={error && error.message || ''}
|
||||
onChangeText = {text => handleInput(text)}
|
||||
placeholder="Ditt personnr (10 eller 12 siffror)"/>
|
||||
<Button onPress={startLogin} style={{width: "100%"}}
|
||||
appearence='ghost'
|
||||
disabled={!valid}
|
||||
status='primary'
|
||||
accessoryRight={SecureIcon}
|
||||
size='medium'>
|
||||
Öppna BankID
|
||||
</Button>
|
||||
</View>
|
||||
</Layout>
|
||||
</KeyboardAvoidingView>
|
||||
}
|
||||
|
@ -157,7 +152,7 @@ export const Login = ({ navigation, route }) => {
|
|||
backdropStyle={styles.backdrop}
|
||||
onBackdropPress={() => setVisible(false)}>
|
||||
<Card disabled={true}>
|
||||
{hasBankId ? <Text style={{margin: 10}}>Öppnar BankID. Växla tillbaka till hit sen.</Text> : <Text style={{margin: 10}}>Väntar på BankID...</Text>}
|
||||
{hasBankId ? <Text style={{margin: 10}}>Öppnar BankID. Växla tillbaka hit sen.</Text> : <Text style={{margin: 10}}>Väntar på BankID...</Text>}
|
||||
|
||||
<Button
|
||||
visible={!loggedIn}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React from 'react'
|
||||
import { StatusBar} from 'react-native'
|
||||
import { NavigationContainer } from '@react-navigation/native'
|
||||
import { createStackNavigator } from '@react-navigation/stack'
|
||||
import useAsyncStorage from '@rnhooks/async-storage'
|
||||
import { Login } from './login.component'
|
||||
import { Children } from './children.component'
|
||||
import { Child } from './child.component'
|
||||
import { NewsItem } from './newsItem.component'
|
||||
import { Provider } from 'use-http'
|
||||
|
||||
const { Navigator, Screen } = createStackNavigator()
|
||||
|
||||
|
@ -20,22 +19,7 @@ const HomeNavigator = () => (
|
|||
)
|
||||
|
||||
export const AppNavigator = () => {
|
||||
const [jwt, setJwt, clearJwt] = useAsyncStorage('@jwt')
|
||||
const options = {
|
||||
interceptors: {
|
||||
request: async ({ options, url, path, route }) => {
|
||||
console.log('requesting', url, path, route, options)
|
||||
return options
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
authorization: 'Bearer ' + jwt,
|
||||
}
|
||||
}
|
||||
return <NavigationContainer>
|
||||
<Provider url='https://api.skolplattformen.org' options={options}>
|
||||
<HomeNavigator/>
|
||||
</Provider>
|
||||
<HomeNavigator/>
|
||||
</NavigationContainer>
|
||||
}
|
||||
|
|
|
@ -23,8 +23,23 @@ export const NewsItem = ({ navigation, route }) => {
|
|||
<Text category='h3'>
|
||||
{newsItem.header}
|
||||
</Text>
|
||||
<Image source={{ uri: `https://etjanst.stockholm.se/Vardnadshavare/inloggad2/NewsBanner?url=${newsItem.imageUrl}`}} style={{width: '100%', minHeight: 300}}></Image>
|
||||
</View>
|
||||
)
|
||||
|
||||
const rules = {
|
||||
image: (
|
||||
node,
|
||||
children,
|
||||
parent,
|
||||
styles,
|
||||
allowedImageHandlers,
|
||||
defaultImageHandler,
|
||||
) => {
|
||||
const {src, alt} = node.attributes;
|
||||
return <Image source={{uri : `https://elevstockholm.sharepoint.com${src}`}} style={{width: '100%', minHeight: 300}}></Image>
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: '#fff' }} >
|
||||
|
@ -34,7 +49,7 @@ export const NewsItem = ({ navigation, route }) => {
|
|||
<Layout style={styles.topContainer} level='1'>
|
||||
<ScrollView>
|
||||
<Card style={styles.card} header={headerProps => renderItemHeader(headerProps, newsItem)}>
|
||||
<Markdown style={{ body: {color: 'black'}, heading1: {color: 'black'} }}>
|
||||
<Markdown rules={rules} style={{ body: {color: 'black', fontSize: 17, lineHeight: 23}, heading1: {color: 'black'} }}>
|
||||
{decodeURIComponent(newsItem.body)}
|
||||
</Markdown>
|
||||
</Card>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { SafeAreaView, StyleSheet, View, Image } from 'react-native'
|
||||
import { Card, List, Text, Layout } from '@ui-kitten/components'
|
||||
import { Image } from 'react-native-svg'
|
||||
import { NavigationContainer } from '@react-navigation/native'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
|
||||
|
@ -21,28 +20,27 @@ export const NewsList = ({news}) => {
|
|||
style={styles.card}
|
||||
onPress={() => navigation.navigate('NewsItem', {newsItem: info.item})}
|
||||
header={headerProps => renderItemHeader(headerProps, info)}>
|
||||
<Image source={{ uri: `https://etjanst.stockholm.se/Vardnadshavare/inloggad2/NewsBanner?url=${info.item.imageUrl}`}} style={{height: 300}}></Image>
|
||||
</Card>
|
||||
)
|
||||
|
||||
return (
|
||||
<Layout style={styles.topContainer} level='1'>
|
||||
<List
|
||||
style={styles.container}
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
data={news}
|
||||
renderItem={renderItem} />
|
||||
</Layout>
|
||||
<List
|
||||
style={styles.container}
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
data={news}
|
||||
renderItem={renderItem} />
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
topContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
card: {
|
||||
flex: 1,
|
||||
margin: 2,
|
||||
},
|
||||
contentContainer: {
|
||||
paddingRight: 10,
|
||||
paddingBottom: 330
|
||||
}
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"strict": {
|
||||
"border-radius": 50
|
||||
},
|
||||
"components": {
|
||||
"Button": {
|
||||
"meta": {},
|
||||
"appearances": {
|
||||
"filled": {
|
||||
"mapping": {},
|
||||
"variantGroups": {
|
||||
"status": {
|
||||
"primary": {
|
||||
"backgroundColor": "blue"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -291,7 +291,7 @@
|
|||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
DevelopmentTeam = BSE2J6442R;
|
||||
DevelopmentTeam = 59292HY5Q8;
|
||||
LastSwiftMigration = 1120;
|
||||
};
|
||||
2D02E47A1E0B4A5D006451C7 = {
|
||||
|
@ -629,8 +629,8 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 15;
|
||||
DEVELOPMENT_TEAM = BSE2J6442R;
|
||||
CURRENT_PROJECT_VERSION = 20;
|
||||
DEVELOPMENT_TEAM = 59292HY5Q8;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
|
@ -638,7 +638,7 @@
|
|||
);
|
||||
INFOPLIST_FILE = Skolplattformen/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 0.0.1;
|
||||
MARKETING_VERSION = 0.0.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
@ -658,11 +658,11 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 15;
|
||||
DEVELOPMENT_TEAM = BSE2J6442R;
|
||||
CURRENT_PROJECT_VERSION = 20;
|
||||
DEVELOPMENT_TEAM = 59292HY5Q8;
|
||||
INFOPLIST_FILE = Skolplattformen/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 0.0.1;
|
||||
MARKETING_VERSION = 0.0.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
|
|
@ -13,29 +13,28 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_launcher-playstore" id="AD3-Uy-RPP">
|
||||
<rect key="frame" x="49.156626506024054" y="235" width="291.00000000000011" height="270.00000000000006"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Skolplattformen" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="0.0" y="100" width="390" height="43"/>
|
||||
<rect key="frame" x="60.666666666666657" y="100" width="268.66666666666674" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" red="0.99999552970000005" green="1" blue="0.99607855079999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="appstore" id="bMh-M1-Kl4">
|
||||
<rect key="frame" x="45" y="192" width="300" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.019342456009999998" green="0.42363536359999998" blue="0.74905878309999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="tintColor" red="0.99999552970000005" green="1" blue="0.99607855079999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<constraints>
|
||||
<constraint firstItem="AD3-Uy-RPP" firstAttribute="top" secondItem="kId-c2-rCX" secondAttribute="bottom" constant="92" id="Enz-w3-qGu"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kId-c2-rCX" secondAttribute="trailing" id="bHX-Nr-atg"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="e34-cY-Leb"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="100" id="msO-ON-KBD"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="ddS-XM-xPo"/>
|
||||
<constraint firstItem="bMh-M1-Kl4" firstAttribute="top" secondItem="kId-c2-rCX" secondAttribute="bottom" constant="49" id="juP-om-veb"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<point key="canvasLocation" x="546.15384615384619" y="454.9763033175355"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="ic_launcher-playstore" width="512" height="512"/>
|
||||
<image name="appstore" width="1024" height="1024"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 505 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 725 B After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1022 B After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 13 KiB |
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_launcher-playstore.png",
|
||||
"filename" : "appstore.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
BIN
packages/app/ios/Skolplattformen/Images.xcassets/appstore.imageset/appstore.png
vendored
Normal file
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 30 KiB |
|
@ -5,7 +5,7 @@
|
|||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$kolplattformen</string>
|
||||
<string>Skolplattformen</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
@ -48,8 +48,6 @@
|
|||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
import moment from 'moment'
|
||||
import init from "@skolplattformen/embedded-api"
|
||||
export const api = init(fetch) // keep a static version of this object so we can keep the session alive
|
||||
|
||||
export const loadChildrenDetails = async (children, what = {news: true}) => await Promise.all(children.map(async child => ({
|
||||
...child,
|
||||
news: !what.news ? child.news : await api.getNews(child).catch(err => [{err}]),
|
||||
calendar: !what.calendar ? child.calendar : await api.getCalendar(child).catch(err => [{err}]),
|
||||
notifications: !what.notifications ? child.notifications : await api.getNotifications(child).catch(err => [{err}]),
|
||||
schedule: !what.schedule ? child.schedule : await api.getSchedule(child, moment().startOf('day'), moment().add(7,'days').endOf('day')).catch(err => [{err}]),
|
||||
classmates: !what.classmates ? child.classmates : await api.getClassmates(child).catch(err => [{err}]),
|
||||
menu: !what.menu ? child.menu : await api.getMenu(child).catch(err => [{err}]),
|
||||
})))
|
||||
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
"@react-navigation/material-top-tabs": "^5.3.10",
|
||||
"@react-navigation/native": "^5.8.10",
|
||||
"@react-navigation/stack": "^5.12.8",
|
||||
"@rnhooks/async-storage": "0.0.1",
|
||||
"@skolplattformen/embedded-api": "^0.9.0",
|
||||
"@ui-kitten/components": "5.0.0",
|
||||
"@ui-kitten/eva-icons": "5.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"faker": "^5.1.0",
|
||||
"personnummer": "^3.1.1",
|
||||
"react": "16.11.0",
|
||||
"react-native": "0.62.2",
|
||||
|
@ -36,7 +36,7 @@
|
|||
"react-native-svg": "^12.1.0",
|
||||
"react-native-svg-transformer": "^0.14.3",
|
||||
"react-native-tab-view": "^2.15.2",
|
||||
"use-http": "^1.0.16"
|
||||
"use-async-storage": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.2",
|
||||
|
|