Design refresh with new navigator and colors (#418)
* Refactor design with navigator and colors * remove childList test data * Update React Navigation and related packages * Add `initials` to peopleHelpers * remove unused tests * change initials to first 2 letters of name * update color scheme * add mock for react-native-reanimated * fix absence translation * update design à la modern/rounded * Add headerLargeTitle everywhere
This commit is contained in:
parent
49328b44f9
commit
25f4ebc0f7
|
@ -1,22 +1,21 @@
|
|||
import React from 'react'
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context'
|
||||
import * as eva from '@eva-design/eva'
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import CookieManager from '@react-native-community/cookies'
|
||||
import { ApiProvider } from '@skolplattformen/api-hooks'
|
||||
import init from '@skolplattformen/embedded-api'
|
||||
import { ApplicationProvider, IconRegistry } from '@ui-kitten/components'
|
||||
import { EvaIconsPack } from '@ui-kitten/eva-icons'
|
||||
import * as eva from '@eva-design/eva'
|
||||
import darkTheme from './design/dark.json'
|
||||
import lightTheme from './design/light.json'
|
||||
import { AppNavigator } from './components/navigation.component'
|
||||
import init from '@skolplattformen/embedded-api'
|
||||
import { ApiProvider } from '@skolplattformen/api-hooks'
|
||||
import CookieManager from '@react-native-community/cookies'
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import React from 'react'
|
||||
import { StatusBar } from 'react-native'
|
||||
import { useBackgroundBlur } from './utils/blur'
|
||||
import { LanguageProvider } from './context/language/languageContext'
|
||||
import { translations } from './utils/translation'
|
||||
import { AppearanceProvider, useColorScheme } from 'react-native-appearance'
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context'
|
||||
import { AppNavigator } from './components/navigation.component'
|
||||
import { LanguageProvider } from './context/language/languageContext'
|
||||
import { default as customMapping } from './design/mapping.json'
|
||||
import { darkTheme, lightTheme } from './design/themes'
|
||||
import { useBackgroundBlur } from './utils/blur'
|
||||
import { translations } from './utils/translation'
|
||||
const api = init(fetch, CookieManager)
|
||||
import { default as customMapping } from './design/mapping.json';
|
||||
|
||||
const reporter = __DEV__
|
||||
? {
|
||||
|
@ -45,10 +44,7 @@ export default () => {
|
|||
<ApplicationProvider
|
||||
{...eva}
|
||||
customMapping={customMapping}
|
||||
theme={{
|
||||
...(colorScheme === 'dark' ? eva.dark : eva.light),
|
||||
...(colorScheme === 'dark' ? darkTheme : lightTheme),
|
||||
}}
|
||||
theme={colorScheme === 'dark' ? darkTheme : lightTheme}
|
||||
>
|
||||
<LanguageProvider cache={true} data={translations}>
|
||||
<AppNavigator />
|
||||
|
|
|
@ -37,12 +37,6 @@ beforeEach(() => {
|
|||
AsyncStorage.clear()
|
||||
})
|
||||
|
||||
test('renders title', () => {
|
||||
const screen = setup()
|
||||
|
||||
expect(screen.getByText('Anmäl frånvaro')).toBeTruthy()
|
||||
})
|
||||
|
||||
test('can fill out the form with full day absence', async () => {
|
||||
const screen = setup()
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { useApi, useNewsDetails } from '@skolplattformen/api-hooks'
|
||||
import React from 'react'
|
||||
import { render } from '../../utils/testHelpers'
|
||||
import { NewsItem } from '../newsItem.component'
|
||||
import { fireEvent } from '@testing-library/react-native'
|
||||
import { useNewsDetails, useApi } from '@skolplattformen/api-hooks'
|
||||
|
||||
jest.mock('@skolplattformen/api-hooks')
|
||||
|
||||
|
@ -89,11 +88,3 @@ test('renders an article without modified date if date is invalid', () => {
|
|||
expect(screen.getByText('Publicerad: 15 feb 2021 10:13')).toBeTruthy()
|
||||
expect(screen.queryByText('Uppdaterad: Invalid DateTime')).toBeFalsy()
|
||||
})
|
||||
|
||||
test('handles navigating back to child view', () => {
|
||||
const screen = setup()
|
||||
|
||||
fireEvent.press(screen.getByTestId('topNavBackToChild'))
|
||||
|
||||
expect(navigation.goBack).toHaveBeenCalled()
|
||||
})
|
||||
|
|
|
@ -1,35 +1,29 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { RouteProp, useRoute } from '@react-navigation/native'
|
||||
import {
|
||||
Button,
|
||||
CheckBox,
|
||||
Divider,
|
||||
Input,
|
||||
Layout,
|
||||
StyleService,
|
||||
Text,
|
||||
TopNavigation,
|
||||
TopNavigationAction,
|
||||
useStyleSheet,
|
||||
} from '@ui-kitten/components'
|
||||
import { Formik } from 'formik'
|
||||
import moment from 'moment'
|
||||
import Personnummer from 'personnummer'
|
||||
import React from 'react'
|
||||
import React, { useCallback } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import DateTimePickerModal from 'react-native-modal-datetime-picker'
|
||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||
import * as Yup from 'yup'
|
||||
import { Layout as LayoutStyle, Sizing, Typography } from '../styles'
|
||||
import { SafeAreaView } from '../ui/safeAreaView.component'
|
||||
import { studentName } from '../utils/peopleHelpers'
|
||||
import { useSMS } from '../utils/SMS'
|
||||
import { translate } from '../utils/translation'
|
||||
import { BackIcon, AlertIcon } from './icon.component'
|
||||
import { AlertIcon } from './icon.component'
|
||||
import { RootStackParamList } from './navigation.component'
|
||||
import { SafeAreaViewContainer } from '../ui/safeAreaViewContainer.component'
|
||||
import { NavigationTitle } from './navigationTitle.component'
|
||||
|
||||
type AbsenceNavigationProp = StackNavigationProp<RootStackParamList, 'Absence'>
|
||||
type AbsenceRouteProps = RouteProp<RootStackParamList, 'Absence'>
|
||||
|
||||
interface AbsenceFormValues {
|
||||
|
@ -41,7 +35,21 @@ interface AbsenceFormValues {
|
|||
endTime: moment.Moment
|
||||
}
|
||||
|
||||
const Alert = (props: any) => <AlertIcon {...props} />
|
||||
export const absenceRouteOptions = ({
|
||||
route,
|
||||
}: {
|
||||
route: RouteProp<RootStackParamList, 'Absence'>
|
||||
}): NativeStackNavigationOptions => {
|
||||
const child = route.params.child
|
||||
return {
|
||||
headerCenter: () => (
|
||||
<NavigationTitle
|
||||
title={translate('abscense.title')}
|
||||
subtitle={studentName(child?.name)}
|
||||
/>
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
const Absence = () => {
|
||||
const AbsenceSchema = Yup.object().shape({
|
||||
|
@ -52,7 +60,7 @@ const Absence = () => {
|
|||
),
|
||||
isFullDay: Yup.bool().required(),
|
||||
})
|
||||
const navigation = useNavigation<AbsenceNavigationProp>()
|
||||
|
||||
const route = useRoute<AbsenceRouteProps>()
|
||||
const { sendSMS } = useSMS()
|
||||
const { child } = route.params
|
||||
|
@ -61,6 +69,28 @@ const Absence = () => {
|
|||
const maximumDate = moment().hours(17).minute(0)
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
|
||||
const submit = useCallback(
|
||||
async (values: AbsenceFormValues) => {
|
||||
const ssn = Personnummer.parse(values.socialSecurityNumber).format()
|
||||
|
||||
if (values.isFullDay) {
|
||||
sendSMS(ssn)
|
||||
} else {
|
||||
sendSMS(
|
||||
`${ssn} ${moment(values.startTime).format('HHmm')}-${moment(
|
||||
values.endTime
|
||||
).format('HHmm')}`
|
||||
)
|
||||
}
|
||||
|
||||
await AsyncStorage.setItem(
|
||||
`@childssn.${child.id}`,
|
||||
values.socialSecurityNumber
|
||||
)
|
||||
},
|
||||
[child.id, sendSMS]
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
const getSocialSecurityNumber = async () => {
|
||||
const ssn = await AsyncStorage.getItem(`@childssn.${child.id}`)
|
||||
|
@ -80,210 +110,154 @@ const Absence = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<SafeAreaViewContainer>
|
||||
<TopNavigation
|
||||
accessoryLeft={() => (
|
||||
<TopNavigationAction
|
||||
icon={BackIcon}
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)}
|
||||
alignment="center"
|
||||
style={styles.topBar}
|
||||
title={() => (
|
||||
<Text maxFontSizeMultiplier={1.5} style={styles.topNavigationTitle}>
|
||||
{translate('abscense.title')}
|
||||
</Text>
|
||||
)}
|
||||
subtitle={() => (
|
||||
<Text
|
||||
maxFontSizeMultiplier={1.5}
|
||||
style={styles.topNavigationSubtitle}
|
||||
>
|
||||
{studentName(child.name)}
|
||||
</Text>
|
||||
)}
|
||||
/>
|
||||
<Divider />
|
||||
<Layout style={styles.wrap}>
|
||||
<Formik
|
||||
enableReinitialize
|
||||
validationSchema={AbsenceSchema}
|
||||
initialValues={initialValues}
|
||||
onSubmit={async (values) => {
|
||||
const ssn = Personnummer.parse(
|
||||
values.socialSecurityNumber
|
||||
).format()
|
||||
<Formik
|
||||
enableReinitialize
|
||||
validationSchema={AbsenceSchema}
|
||||
initialValues={initialValues}
|
||||
onSubmit={submit}
|
||||
>
|
||||
{({
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
setFieldValue,
|
||||
values,
|
||||
touched,
|
||||
errors,
|
||||
}) => {
|
||||
const hasError = (field: keyof typeof values) =>
|
||||
errors[field] && touched[field]
|
||||
|
||||
if (values.isFullDay) {
|
||||
sendSMS(ssn)
|
||||
} else {
|
||||
sendSMS(
|
||||
`${ssn} ${moment(values.startTime).format('HHmm')}-${moment(
|
||||
values.endTime
|
||||
).format('HHmm')}`
|
||||
)
|
||||
}
|
||||
|
||||
await AsyncStorage.setItem(
|
||||
`@childssn.${child.id}`,
|
||||
values.socialSecurityNumber
|
||||
)
|
||||
}}
|
||||
>
|
||||
{({
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
setFieldValue,
|
||||
values,
|
||||
touched,
|
||||
errors,
|
||||
}) => {
|
||||
const hasError = (field: keyof typeof values) =>
|
||||
errors[field] && touched[field]
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.field}>
|
||||
<Text style={styles.label}>
|
||||
{translate('general.socialSecurityNumber')}
|
||||
</Text>
|
||||
<Input
|
||||
testID="socialSecurityNumberInput"
|
||||
keyboardType="number-pad"
|
||||
onChangeText={handleChange('socialSecurityNumber')}
|
||||
onBlur={handleBlur('socialSecurityNumber')}
|
||||
status={
|
||||
hasError('socialSecurityNumber') ? 'danger' : 'basic'
|
||||
}
|
||||
value={values.socialSecurityNumber}
|
||||
accessoryRight={
|
||||
errors.socialSecurityNumber ? Alert : undefined
|
||||
}
|
||||
/>
|
||||
{hasError('socialSecurityNumber') && (
|
||||
<Text style={styles.error}>
|
||||
{errors.socialSecurityNumber}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.field}>
|
||||
<CheckBox
|
||||
checked={values.isFullDay}
|
||||
onChange={(checked) =>
|
||||
setFieldValue('isFullDay', checked)
|
||||
}
|
||||
>
|
||||
{translate('abscense.entireDay')}
|
||||
</CheckBox>
|
||||
</View>
|
||||
{!values.isFullDay && (
|
||||
<View style={styles.partOfDay}>
|
||||
<View style={styles.inputHalf}>
|
||||
<Text style={styles.label}>
|
||||
{translate('abscense.startTime')}
|
||||
</Text>
|
||||
<Button
|
||||
status="basic"
|
||||
onPress={() =>
|
||||
setFieldValue('displayStartTimePicker', true)
|
||||
}
|
||||
>
|
||||
{moment(values.startTime).format('LT')}
|
||||
</Button>
|
||||
<DateTimePickerModal
|
||||
cancelTextIOS={translate('general.cancel')}
|
||||
confirmTextIOS={translate('general.confirm')}
|
||||
date={moment(values.startTime).toDate()}
|
||||
isVisible={values.displayStartTimePicker}
|
||||
headerTextIOS={translate(
|
||||
'abscense.selectAbscenseStartTime'
|
||||
)}
|
||||
locale="sv-SE"
|
||||
maximumDate={maximumDate.toDate()}
|
||||
minimumDate={minumumDate.toDate()}
|
||||
minuteInterval={10}
|
||||
mode="time"
|
||||
onConfirm={(date) => {
|
||||
setFieldValue('startTime', date)
|
||||
setFieldValue('displayStartTimePicker', false)
|
||||
}}
|
||||
onCancel={() =>
|
||||
setFieldValue('displayStartTimePicker', false)
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.spacer} />
|
||||
<View style={styles.inputHalf}>
|
||||
<Text style={styles.label}>
|
||||
{translate('abscense.endTime')}
|
||||
</Text>
|
||||
<Button
|
||||
status="basic"
|
||||
onPress={() =>
|
||||
setFieldValue('displayEndTimePicker', true)
|
||||
}
|
||||
>
|
||||
{moment(values.endTime).format('LT')}
|
||||
</Button>
|
||||
<DateTimePickerModal
|
||||
cancelTextIOS={translate('general.cancel')}
|
||||
confirmTextIOS={translate('general.confirm')}
|
||||
date={moment(values.endTime).toDate()}
|
||||
isVisible={values.displayEndTimePicker}
|
||||
headerTextIOS={translate(
|
||||
'abscense.selectAbscenseEndTime'
|
||||
)}
|
||||
// Todo fix this
|
||||
locale="sv-SE"
|
||||
maximumDate={maximumDate.toDate()}
|
||||
minimumDate={minumumDate.toDate()}
|
||||
minuteInterval={10}
|
||||
mode="time"
|
||||
onConfirm={(date) => {
|
||||
setFieldValue('endTime', date)
|
||||
setFieldValue('displayEndTimePicker', false)
|
||||
}}
|
||||
onCancel={() =>
|
||||
setFieldValue('displayEndTimePicker', false)
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
<Button onPress={handleSubmit} status="primary">
|
||||
{translate('general.send')}
|
||||
return (
|
||||
<View style={styles.wrap}>
|
||||
<View style={styles.field}>
|
||||
<Text style={styles.label}>
|
||||
{translate('general.socialSecurityNumber')}
|
||||
</Text>
|
||||
<Input
|
||||
testID="socialSecurityNumberInput"
|
||||
keyboardType="number-pad"
|
||||
onChangeText={handleChange('socialSecurityNumber')}
|
||||
onBlur={handleBlur('socialSecurityNumber')}
|
||||
status={hasError('socialSecurityNumber') ? 'danger' : 'basic'}
|
||||
value={values.socialSecurityNumber}
|
||||
style={styles.input}
|
||||
accessoryRight={
|
||||
hasError('socialSecurityNumber') ? AlertIcon : undefined
|
||||
}
|
||||
/>
|
||||
{hasError('socialSecurityNumber') && (
|
||||
<Text style={styles.error}>{errors.socialSecurityNumber}</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.field}>
|
||||
<CheckBox
|
||||
checked={values.isFullDay}
|
||||
onChange={(checked) => setFieldValue('isFullDay', checked)}
|
||||
>
|
||||
{translate('abscense.entireDay')}
|
||||
</CheckBox>
|
||||
</View>
|
||||
{!values.isFullDay && (
|
||||
<View style={styles.partOfDay}>
|
||||
<View style={styles.inputHalf}>
|
||||
<Text style={styles.label}>
|
||||
{translate('abscense.startTime')}
|
||||
</Text>
|
||||
<Button
|
||||
status="basic"
|
||||
style={styles.pickerButton}
|
||||
onPress={() =>
|
||||
setFieldValue('displayStartTimePicker', true)
|
||||
}
|
||||
>
|
||||
{moment(values.startTime).format('LT')}
|
||||
</Button>
|
||||
<DateTimePickerModal
|
||||
cancelTextIOS={translate('general.cancel')}
|
||||
confirmTextIOS={translate('general.confirm')}
|
||||
date={moment(values.startTime).toDate()}
|
||||
isVisible={values.displayStartTimePicker}
|
||||
headerTextIOS={translate(
|
||||
'abscense.selectAbscenseStartTime'
|
||||
)}
|
||||
locale="sv-SE"
|
||||
maximumDate={maximumDate.toDate()}
|
||||
minimumDate={minumumDate.toDate()}
|
||||
minuteInterval={10}
|
||||
mode="time"
|
||||
onConfirm={(date) => {
|
||||
setFieldValue('startTime', date)
|
||||
setFieldValue('displayStartTimePicker', false)
|
||||
}}
|
||||
onCancel={() =>
|
||||
setFieldValue('displayStartTimePicker', false)
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}}
|
||||
</Formik>
|
||||
</Layout>
|
||||
</SafeAreaViewContainer>
|
||||
</SafeAreaView>
|
||||
<View style={styles.spacer} />
|
||||
<View style={styles.inputHalf}>
|
||||
<Text style={styles.label}>
|
||||
{translate('abscense.endTime')}
|
||||
</Text>
|
||||
<Button
|
||||
status="basic"
|
||||
style={styles.pickerButton}
|
||||
onPress={() => setFieldValue('displayEndTimePicker', true)}
|
||||
>
|
||||
{moment(values.endTime).format('LT')}
|
||||
</Button>
|
||||
<DateTimePickerModal
|
||||
cancelTextIOS={translate('general.cancel')}
|
||||
confirmTextIOS={translate('general.confirm')}
|
||||
date={moment(values.endTime).toDate()}
|
||||
isVisible={values.displayEndTimePicker}
|
||||
headerTextIOS={translate('abscense.selectAbscenseEndTime')}
|
||||
// Todo fix this
|
||||
locale="sv-SE"
|
||||
maximumDate={maximumDate.toDate()}
|
||||
minimumDate={minumumDate.toDate()}
|
||||
minuteInterval={10}
|
||||
mode="time"
|
||||
onConfirm={(date) => {
|
||||
setFieldValue('endTime', date)
|
||||
setFieldValue('displayEndTimePicker', false)
|
||||
}}
|
||||
onCancel={() =>
|
||||
setFieldValue('displayEndTimePicker', false)
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
<Button onPress={handleSubmit} status="primary">
|
||||
{translate('general.send')}
|
||||
</Button>
|
||||
</View>
|
||||
)
|
||||
}}
|
||||
</Formik>
|
||||
)
|
||||
}
|
||||
|
||||
export default Absence
|
||||
|
||||
const themedStyles = StyleService.create({
|
||||
safeArea: {
|
||||
...LayoutStyle.flex.full,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
},
|
||||
topBar: {
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
},
|
||||
wrap: {
|
||||
...LayoutStyle.flex.full,
|
||||
padding: Sizing.t5,
|
||||
padding: Sizing.t4,
|
||||
},
|
||||
field: { marginBottom: Sizing.t4 },
|
||||
partOfDay: { ...LayoutStyle.flex.row, marginBottom: Sizing.t4 },
|
||||
spacer: { width: Sizing.t2 },
|
||||
inputHalf: { ...LayoutStyle.flex.full },
|
||||
input: {
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
},
|
||||
// TODO: Refactor to use mapping.json in eva design
|
||||
pickerButton: {
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
},
|
||||
label: {
|
||||
...Typography.fontSize.xs,
|
||||
...Typography.fontWeight.bold,
|
||||
|
@ -293,11 +267,4 @@ const themedStyles = StyleService.create({
|
|||
error: {
|
||||
color: 'color-primary-600',
|
||||
},
|
||||
topNavigationTitle: {
|
||||
...Typography.fontWeight.semibold,
|
||||
},
|
||||
topNavigationSubtitle: {
|
||||
...Typography.fontWeight.regular,
|
||||
...Typography.fontSize.sm,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,23 +1,30 @@
|
|||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import {
|
||||
Layout,
|
||||
Text,
|
||||
TopNavigation,
|
||||
TopNavigationAction,
|
||||
StyleService,
|
||||
Text,
|
||||
useStyleSheet,
|
||||
useTheme,
|
||||
} from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { Keyboard, TouchableWithoutFeedback, View, Image } from 'react-native'
|
||||
import { Login } from './login.component'
|
||||
import { Layout as LayoutStyle, Sizing, Typography } from '../styles'
|
||||
import { SafeAreaViewContainer } from '../ui/safeAreaViewContainer.component'
|
||||
import { translate, languages } from '../utils/translation'
|
||||
import { GlobeIcon } from './icon.component'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { RootStackParamList } from './navigation.component'
|
||||
import { SafeAreaView } from '../ui/safeAreaView.component'
|
||||
import { KeyboardAvoidingView } from '../ui/keyboardAvoidingView.component'
|
||||
import {
|
||||
Image,
|
||||
ImageStyle,
|
||||
Keyboard,
|
||||
TouchableWithoutFeedback,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { TouchableOpacity } from 'react-native-gesture-handler'
|
||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||
import { LanguageService } from '../services/languageService'
|
||||
import { Layout as LayoutStyle, Sizing, Typography } from '../styles'
|
||||
import { fontSize } from '../styles/typography'
|
||||
import { KeyboardAvoidingView } from '../ui/keyboardAvoidingView.component'
|
||||
import { SafeAreaView } from '../ui/safeAreaView.component'
|
||||
import { SafeAreaViewContainer } from '../ui/safeAreaViewContainer.component'
|
||||
import { languages, translate } from '../utils/translation'
|
||||
import { GlobeIcon } from './icon.component'
|
||||
import { Login } from './login.component'
|
||||
import { RootStackParamList } from './navigation.component'
|
||||
|
||||
const randomWord = () => {
|
||||
const words = translate('auth.words')
|
||||
|
@ -34,8 +41,17 @@ interface AuthProps {
|
|||
navigation: StackNavigationProp<RootStackParamList, 'Login'>
|
||||
}
|
||||
|
||||
export const authRouteOptions = (): NativeStackNavigationOptions => {
|
||||
return {
|
||||
headerShown: false,
|
||||
replaceAnimation: 'push',
|
||||
stackAnimation: 'fade',
|
||||
}
|
||||
}
|
||||
|
||||
export const Auth: React.FC<AuthProps> = ({ navigation }) => {
|
||||
const styles = useStyleSheet(themeStyles)
|
||||
const colors = useTheme()
|
||||
|
||||
const currentLanguage = LanguageService.getLanguageCode()
|
||||
const currentLanguageName = languages.find(
|
||||
|
@ -43,56 +59,66 @@ export const Auth: React.FC<AuthProps> = ({ navigation }) => {
|
|||
)?.languageLocalName
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView>
|
||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
||||
<SafeAreaView>
|
||||
<SafeAreaViewContainer>
|
||||
<TopNavigation
|
||||
alignment="start"
|
||||
subtitle={currentLanguageName}
|
||||
accessoryLeft={() => (
|
||||
<TopNavigationAction
|
||||
accessibilityHint={translate(
|
||||
'auth.a11y_navigate_to_change_language',
|
||||
{
|
||||
defaultValue: 'Navigerar till vyn för att byta språk',
|
||||
}
|
||||
)}
|
||||
accessibilityLabel={translate('auth.a11y_change_language', {
|
||||
defaultValue: 'Byt språk',
|
||||
})}
|
||||
accessible={true}
|
||||
icon={GlobeIcon}
|
||||
onPress={() => navigation.navigate('SetLanguage')}
|
||||
/>
|
||||
<SafeAreaView>
|
||||
<SafeAreaViewContainer>
|
||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
||||
<View style={LayoutStyle.flex.full}>
|
||||
<TouchableOpacity
|
||||
onPress={() => navigation.navigate('SetLanguage')}
|
||||
accessibilityHint={translate(
|
||||
'auth.a11y_navigate_to_change_language',
|
||||
{
|
||||
defaultValue: 'Navigerar till vyn för att byta språk',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
<View style={styles.content}>
|
||||
<Image
|
||||
source={require('../assets/boys.png')}
|
||||
// @ts-expect-error Don't know why this occurs
|
||||
style={styles.image}
|
||||
accessibilityHint={translate('login.a11y_image_two_boys', {
|
||||
defaultValue: 'Bild på två personer som kollar i mobilen',
|
||||
})}
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
accessibilityLabel={translate('auth.a11y_change_language', {
|
||||
defaultValue: 'Byt språk',
|
||||
})}
|
||||
>
|
||||
<View style={styles.language}>
|
||||
<GlobeIcon
|
||||
height={24}
|
||||
width={24}
|
||||
fill={colors['color-primary-500']}
|
||||
/>
|
||||
<Layout style={styles.container}>
|
||||
<Text category="h1" style={styles.header} adjustsFontSizeToFit numberOfLines={2}>
|
||||
{translate('general.title')}
|
||||
</Text>
|
||||
<Login />
|
||||
<Text category="c2" style={styles.subtitle}>
|
||||
{translate('auth.subtitle', {
|
||||
word: randomWord(),
|
||||
})}
|
||||
</Text>
|
||||
</Layout>
|
||||
</View>
|
||||
</SafeAreaViewContainer>
|
||||
</SafeAreaView>
|
||||
</TouchableWithoutFeedback>
|
||||
</KeyboardAvoidingView>
|
||||
<Text style={styles.languageText}>{currentLanguageName}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<KeyboardAvoidingView>
|
||||
<View style={styles.content}>
|
||||
<View style={styles.imageWrapper}>
|
||||
<Image
|
||||
source={require('../assets/boys.png')}
|
||||
style={styles.image as ImageStyle}
|
||||
accessibilityHint={translate('login.a11y_image_two_boys', {
|
||||
defaultValue: 'Bild på två personer som kollar i mobilen',
|
||||
})}
|
||||
resizeMode="contain"
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.container}>
|
||||
<Text
|
||||
category="h1"
|
||||
style={styles.header}
|
||||
adjustsFontSizeToFit
|
||||
numberOfLines={2}
|
||||
>
|
||||
{translate('general.title')}
|
||||
</Text>
|
||||
<Login />
|
||||
<Text category="c2" style={styles.subtitle}>
|
||||
{translate('auth.subtitle', {
|
||||
word: randomWord(),
|
||||
})}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</SafeAreaViewContainer>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -102,9 +128,12 @@ const themeStyles = StyleService.create({
|
|||
...LayoutStyle.crossAxis.flexEnd,
|
||||
padding: Sizing.t6,
|
||||
},
|
||||
imageWrapper: {
|
||||
flex: 1,
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
image: {
|
||||
...Sizing.aspectRatio(1.7, Sizing.Ratio['4:3']),
|
||||
marginLeft: '-17%',
|
||||
...Sizing.aspectRatio(1.5, Sizing.Ratio['4:3']),
|
||||
},
|
||||
content: {
|
||||
...LayoutStyle.flex.full,
|
||||
|
@ -112,12 +141,22 @@ const themeStyles = StyleService.create({
|
|||
header: {
|
||||
width: '60%',
|
||||
marginBottom: Sizing.t5,
|
||||
fontFamily: 'Poppins-Black',
|
||||
fontWeight: '900',
|
||||
},
|
||||
subtitle: {
|
||||
width: '100%',
|
||||
textAlign: 'center',
|
||||
...Typography.fontSize.xs,
|
||||
color: 'color-basic-800',
|
||||
marginTop: Sizing.t5,
|
||||
},
|
||||
language: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingLeft: Sizing.t4,
|
||||
},
|
||||
languageText: {
|
||||
...fontSize.xs,
|
||||
marginLeft: Sizing.t1,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -65,12 +65,12 @@ export const Calendar = () => {
|
|||
|
||||
const themedStyles = StyleService.create({
|
||||
container: {
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
},
|
||||
description: {
|
||||
...Typography.fontSize.xs,
|
||||
color: 'color-basic-600',
|
||||
color: 'text-hint-color',
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,182 +1,126 @@
|
|||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
|
||||
import {
|
||||
BottomTabBarOptions,
|
||||
BottomTabBarProps,
|
||||
createBottomTabNavigator,
|
||||
} from '@react-navigation/bottom-tabs'
|
||||
import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'
|
||||
getFocusedRouteNameFromRoute,
|
||||
RouteProp,
|
||||
useRoute,
|
||||
} from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import {
|
||||
BottomNavigation,
|
||||
BottomNavigationTab,
|
||||
Layout,
|
||||
StyleService,
|
||||
Text,
|
||||
TopNavigation,
|
||||
TopNavigationAction,
|
||||
useStyleSheet,
|
||||
} from '@ui-kitten/components'
|
||||
import { Icon } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { StyleProp, TextProps } from 'react-native'
|
||||
import { studentName } from '../utils/peopleHelpers'
|
||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||
import { defaultStackStyling } from '../design/navigationThemes'
|
||||
import { translate } from '../utils/translation'
|
||||
import { Calendar } from './calendar.component'
|
||||
import { ChildProvider } from './childContext.component'
|
||||
import { Menu } from './menu.component'
|
||||
import {
|
||||
BackIcon,
|
||||
CalendarOutlineIcon,
|
||||
MenuIcon,
|
||||
NewsIcon,
|
||||
NotificationsIcon,
|
||||
} from './icon.component'
|
||||
import { RootStackParamList } from './navigation.component'
|
||||
import { NewsList } from './newsList.component'
|
||||
import { NotificationsList } from './notificationsList.component'
|
||||
import { translate } from '../utils/translation'
|
||||
import { SafeAreaView } from '../ui/safeAreaView.component'
|
||||
import { SafeAreaViewContainer } from '../ui/safeAreaViewContainer.component'
|
||||
import { Typography } from '../styles'
|
||||
|
||||
type ChildNavigationProp = StackNavigationProp<RootStackParamList, 'Child'>
|
||||
type ChildRouteProps = RouteProp<RootStackParamList, 'Child'>
|
||||
|
||||
export type ChildTabParamList = {
|
||||
News: undefined
|
||||
Notifications: undefined
|
||||
Calendar: undefined
|
||||
Menu: undefined
|
||||
}
|
||||
|
||||
interface TabTitleProps {
|
||||
children: string
|
||||
style?: StyleProp<TextProps>
|
||||
}
|
||||
|
||||
const { Navigator, Screen } = createBottomTabNavigator()
|
||||
const { Navigator, Screen } = createBottomTabNavigator<ChildTabParamList>()
|
||||
|
||||
const NewsScreen = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<NewsList />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
const NewsScreen = () => <NewsList />
|
||||
const NotificationsScreen = () => <NotificationsList />
|
||||
const CalendarScreen = () => <Calendar />
|
||||
const MenuScreen = () => <Menu />
|
||||
|
||||
const NotificationsScreen = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<NotificationsList />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
const CalendarScreen = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<Calendar />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
const MenuScreen = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<Menu />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
const TabTitle = ({ style, children }: TabTitleProps) => (
|
||||
<Text
|
||||
maxFontSizeMultiplier={1.5}
|
||||
adjustsFontSizeToFit
|
||||
numberOfLines={1}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
)
|
||||
|
||||
const BottomTabBar = ({
|
||||
navigation,
|
||||
state,
|
||||
}: BottomTabBarProps<BottomTabBarOptions>) => (
|
||||
<BottomNavigation
|
||||
accessibilityRole="menu"
|
||||
selectedIndex={state.index}
|
||||
onSelect={(index) => navigation.navigate(state.routeNames[index])}
|
||||
>
|
||||
<BottomNavigationTab
|
||||
accessibilityRole="menuitem"
|
||||
title={(props) => (
|
||||
<TabTitle {...props}>{translate('navigation.news')}</TabTitle>
|
||||
)}
|
||||
icon={NewsIcon}
|
||||
/>
|
||||
<BottomNavigationTab
|
||||
accessibilityRole="menuitem"
|
||||
title={(props) => (
|
||||
<TabTitle {...props}>{translate('navigation.notifications')}</TabTitle>
|
||||
)}
|
||||
icon={NotificationsIcon}
|
||||
/>
|
||||
<BottomNavigationTab
|
||||
accessibilityRole="menuitem"
|
||||
title={(props) => (
|
||||
<TabTitle {...props}>{translate('navigation.calender')}</TabTitle>
|
||||
)}
|
||||
icon={CalendarOutlineIcon}
|
||||
/>
|
||||
<BottomNavigationTab
|
||||
accessibilityRole="menuitem"
|
||||
title={(props) => (
|
||||
<TabTitle {...props}>{translate('navigation.menu')}</TabTitle>
|
||||
)}
|
||||
icon={MenuIcon}
|
||||
/>
|
||||
</BottomNavigation>
|
||||
)
|
||||
|
||||
const TabNavigator = ({ initialRouteName = 'Nyheter' }) => (
|
||||
const TabNavigator = ({
|
||||
initialRouteName = 'News',
|
||||
}: {
|
||||
initialRouteName: keyof ChildTabParamList
|
||||
}) => (
|
||||
<Navigator
|
||||
initialRouteName={initialRouteName}
|
||||
tabBar={(props) => <BottomTabBar {...props} />}
|
||||
screenOptions={({ route }) => {
|
||||
return {
|
||||
tabBarIcon: ({ focused, color }) => {
|
||||
let iconName = 'news'
|
||||
|
||||
if (route.name === 'News')
|
||||
iconName = focused ? 'book-open' : 'book-open-outline'
|
||||
else if (route.name === 'Notifications')
|
||||
iconName = focused ? 'alert-circle' : 'alert-circle-outline'
|
||||
else if (route.name === 'Calendar')
|
||||
iconName = focused ? 'calendar' : 'calendar-outline'
|
||||
else if (route.name === 'Menu')
|
||||
iconName = focused ? 'clipboard' : 'clipboard-outline'
|
||||
return <Icon name={iconName} fill={color} height={24} width={24} />
|
||||
},
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Screen name={'navigation.news'} component={NewsScreen} />
|
||||
<Screen name={'navigation.notifications'} component={NotificationsScreen} />
|
||||
<Screen name={'navigation.calender'} component={CalendarScreen} />
|
||||
<Screen name={'navigation.menu'} component={MenuScreen} />
|
||||
<Screen
|
||||
name="News"
|
||||
component={NewsScreen}
|
||||
options={{ title: translate('navigation.news') }}
|
||||
/>
|
||||
<Screen
|
||||
name="Notifications"
|
||||
component={NotificationsScreen}
|
||||
options={{ title: translate('navigation.notifications') }}
|
||||
/>
|
||||
<Screen
|
||||
name="Calendar"
|
||||
component={CalendarScreen}
|
||||
options={{ title: translate('navigation.calender') }}
|
||||
/>
|
||||
<Screen
|
||||
name="Menu"
|
||||
component={MenuScreen}
|
||||
options={{ title: translate('navigation.menu') }}
|
||||
/>
|
||||
</Navigator>
|
||||
)
|
||||
|
||||
export const Child = () => {
|
||||
const navigation = useNavigation<ChildNavigationProp>()
|
||||
const route = useRoute<ChildRouteProps>()
|
||||
const { child, initialRouteName } = route.params
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
const getHeaderTitle = (route: any) => {
|
||||
const routeName = getFocusedRouteNameFromRoute(route) ?? 'News'
|
||||
|
||||
const BackAction = () => (
|
||||
<TopNavigationAction icon={BackIcon} onPress={navigateBack} />
|
||||
)
|
||||
|
||||
const navigateBack = () => {
|
||||
navigation.goBack()
|
||||
switch (routeName) {
|
||||
case 'News':
|
||||
return translate('navigation.news')
|
||||
case 'Notifications':
|
||||
return translate('navigation.notifications')
|
||||
case 'Calendar':
|
||||
return translate('navigation.calender')
|
||||
case 'Menu':
|
||||
return translate('navigation.menu')
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<SafeAreaViewContainer>
|
||||
<ChildProvider child={child}>
|
||||
<TopNavigation
|
||||
title={() => (
|
||||
<Text maxFontSizeMultiplier={2} style={styles.topNavigationTitle}>
|
||||
{studentName(child.name)}
|
||||
</Text>
|
||||
)}
|
||||
alignment="center"
|
||||
accessoryLeft={BackAction}
|
||||
/>
|
||||
<TabNavigator initialRouteName={initialRouteName} />
|
||||
</ChildProvider>
|
||||
</SafeAreaViewContainer>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
const themedStyles = StyleService.create({
|
||||
topNavigationTitle: {
|
||||
...Typography.fontWeight.semibold,
|
||||
},
|
||||
})
|
||||
export const childRouteOptions = ({
|
||||
route,
|
||||
}: {
|
||||
route: RouteProp<RootStackParamList, 'Child'>
|
||||
}): NativeStackNavigationOptions => {
|
||||
return {
|
||||
...defaultStackStyling,
|
||||
title: getHeaderTitle(route),
|
||||
}
|
||||
}
|
||||
|
||||
export const Child = () => {
|
||||
const route = useRoute<ChildRouteProps>()
|
||||
const { child, initialRouteName } = route.params
|
||||
|
||||
return (
|
||||
<ChildProvider child={child}>
|
||||
<TabNavigator initialRouteName={initialRouteName as any} />
|
||||
</ChildProvider>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,28 +9,28 @@ import {
|
|||
useSchedule,
|
||||
} from '@skolplattformen/api-hooks'
|
||||
import { Child } from '@skolplattformen/embedded-api'
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Card,
|
||||
IconProps,
|
||||
StyleService,
|
||||
Text,
|
||||
useStyleSheet,
|
||||
useTheme,
|
||||
} from '@ui-kitten/components'
|
||||
import moment from 'moment'
|
||||
import React from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { TouchableOpacity, View } from 'react-native'
|
||||
import { Layout, Sizing } from '../styles'
|
||||
import { studentName } from '../utils/peopleHelpers'
|
||||
import { translate } from '../utils/translation'
|
||||
import {
|
||||
BookOpenIcon,
|
||||
CalendarOutlineIcon,
|
||||
MenuIcon,
|
||||
NewsIcon,
|
||||
ClipboardIcon,
|
||||
NotificationsIcon,
|
||||
} from './icon.component'
|
||||
import { RootStackParamList } from './navigation.component'
|
||||
import { StudentAvatar } from './studentAvatar.component'
|
||||
|
||||
interface ChildListItemProps {
|
||||
child: Child
|
||||
|
@ -40,10 +40,12 @@ type ChildListItemNavigationProp = StackNavigationProp<
|
|||
RootStackParamList,
|
||||
'Children'
|
||||
>
|
||||
|
||||
export const ChildListItem = ({ child, color }: ChildListItemProps) => {
|
||||
// Forces rerender when child.id changes
|
||||
React.useEffect(() => {}, [child.id])
|
||||
|
||||
const colors = useTheme()
|
||||
const navigation = useNavigation<ChildListItemNavigationProp>()
|
||||
const { data: notifications, status: notificationsStatus } = useNotifications(
|
||||
child
|
||||
|
@ -113,181 +115,204 @@ export const ChildListItem = ({ child, color }: ChildListItemProps) => {
|
|||
pending: 'basic',
|
||||
}
|
||||
|
||||
const buttonAppearance: string = 'ghost'
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<View style={styles.itemFooter}>
|
||||
<Button
|
||||
style={styles.item}
|
||||
accessible={true}
|
||||
accessibilityLabel={`${child.name}, ${translate('navigation.news')}`}
|
||||
accessibilityRole="button"
|
||||
size="small"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[newsStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: 'navigation.news',
|
||||
})
|
||||
}
|
||||
accessoryLeft={NewsIcon}
|
||||
>
|
||||
{`${(news || []).length}`}
|
||||
</Button>
|
||||
<Button
|
||||
style={styles.item}
|
||||
accessible={true}
|
||||
accessibilityLabel={`${child.name}, ${translate(
|
||||
'navigation.notifications'
|
||||
)}`}
|
||||
accessibilityRole="button"
|
||||
size="small"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[notificationsStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: 'navigation.notifications',
|
||||
})
|
||||
}
|
||||
accessoryLeft={NotificationsIcon}
|
||||
>
|
||||
{`${(notifications || []).length}`}
|
||||
</Button>
|
||||
<Button
|
||||
style={styles.item}
|
||||
accessible={true}
|
||||
accessibilityLabel={`${child.name}, ${translate(
|
||||
'navigation.calender'
|
||||
)}`}
|
||||
accessibilityRole="button"
|
||||
size="small"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[calendarStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: 'navigation.calender',
|
||||
})
|
||||
}
|
||||
accessoryLeft={CalendarOutlineIcon}
|
||||
>
|
||||
{`${(calendar || []).length}`}
|
||||
</Button>
|
||||
<Button
|
||||
style={styles.item}
|
||||
accessible={true}
|
||||
accessibilityLabel={`${child.name}, ${translate('navigation.menu')}`}
|
||||
accessibilityRole="button"
|
||||
size="small"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[menuStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: 'navigation.menu',
|
||||
})
|
||||
}
|
||||
accessoryLeft={MenuIcon}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
const buttonAppearance = 'basic'
|
||||
|
||||
return (
|
||||
<Card
|
||||
style={styles.card}
|
||||
appearance="filled"
|
||||
status={color}
|
||||
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}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
footer={Footer}
|
||||
<TouchableOpacity
|
||||
onPress={() => navigation.navigate('Child', { child, color })}
|
||||
>
|
||||
{scheduleAndCalendarThisWeek.slice(0, 3).map((calendarItem, i) => (
|
||||
<Text category="p1" key={i}>
|
||||
{`${calendarItem.title} (${displayDate(calendarItem.startDate)})`}
|
||||
</Text>
|
||||
))}
|
||||
{notificationsThisWeek.slice(0, 3).map((notification, i) => (
|
||||
<Text category="p1" key={i}>
|
||||
{translate('notifications.notificationTitle', {
|
||||
message: notification.message,
|
||||
dateCreated: displayDate(notification.dateCreated),
|
||||
})}
|
||||
</Text>
|
||||
))}
|
||||
{newsThisWeek.slice(0, 3).map((newsItem, i) => (
|
||||
<Text category="p1" key={i}>
|
||||
{translate('news.notificationTitle', {
|
||||
header: newsItem.header,
|
||||
published: displayDate(newsItem.published),
|
||||
})}
|
||||
</Text>
|
||||
))}
|
||||
{scheduleAndCalendarThisWeek.length ||
|
||||
notificationsThisWeek.length ||
|
||||
newsThisWeek.length ? null : (
|
||||
<Text category="p1" style={styles.noNewNewsItemsText}>
|
||||
{translate('news.noNewNewsItemsThisWeek')}
|
||||
</Text>
|
||||
)}
|
||||
<View style={styles.itemFooterAbsence}>
|
||||
<Button
|
||||
accessible={true}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={`${child.name}, ${translate('abscense.title')}`}
|
||||
size="small"
|
||||
status="primary"
|
||||
onPress={() => navigation.navigate('Absence', { child })}
|
||||
>
|
||||
{translate('abscense.title')}
|
||||
</Button>
|
||||
<View style={styles.card}>
|
||||
<View style={styles.cardHeader}>
|
||||
<View style={styles.cardHeaderLeft}>
|
||||
<StudentAvatar name={studentName(child.name)} color={color} />
|
||||
<View style={styles.cardHeaderText}>
|
||||
<Text category="h6">{studentName(child.name)}</Text>
|
||||
{className ? <Text category="s1">{className}</Text> : null}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
{scheduleAndCalendarThisWeek.slice(0, 3).map((calendarItem, i) => (
|
||||
<Text category="p1" key={i}>
|
||||
{`${calendarItem.title} (${displayDate(calendarItem.startDate)})`}
|
||||
</Text>
|
||||
))}
|
||||
{notificationsThisWeek.slice(0, 3).map((notification, i) => (
|
||||
<Text category="p1" key={i}>
|
||||
{translate('notifications.notificationTitle', {
|
||||
message: notification.message,
|
||||
dateCreated: displayDate(notification.dateCreated),
|
||||
})}
|
||||
</Text>
|
||||
))}
|
||||
{newsThisWeek.slice(0, 3).map((newsItem, i) => (
|
||||
<Text category="p1" key={i}>
|
||||
{translate('news.notificationTitle', {
|
||||
header: newsItem.header,
|
||||
published: displayDate(newsItem.published),
|
||||
})}
|
||||
</Text>
|
||||
))}
|
||||
{scheduleAndCalendarThisWeek.length ||
|
||||
notificationsThisWeek.length ||
|
||||
newsThisWeek.length ? null : (
|
||||
<Text category="p1" style={styles.noNewNewsItemsText}>
|
||||
{translate('news.noNewNewsItemsThisWeek')}
|
||||
</Text>
|
||||
)}
|
||||
<View style={styles.itemFooterAbsence}>
|
||||
<Button
|
||||
accessible
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={`${child.name}, ${translate('abscense.title')}`}
|
||||
size="small"
|
||||
status="primary"
|
||||
onPress={() => navigation.navigate('Absence', { child })}
|
||||
>
|
||||
{translate('abscense.title')}
|
||||
</Button>
|
||||
</View>
|
||||
<View style={styles.itemFooter}>
|
||||
<Button
|
||||
style={styles.item}
|
||||
size="small"
|
||||
accessible={true}
|
||||
accessibilityLabel={`${child.name}, ${translate(
|
||||
'navigation.news'
|
||||
)}`}
|
||||
accessibilityRole="button"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[newsStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: translate('navigation.news'),
|
||||
})
|
||||
}
|
||||
accessoryLeft={createFooterIcon(
|
||||
BookOpenIcon,
|
||||
colors['color-basic-text']
|
||||
)}
|
||||
>
|
||||
{`${(news || []).length}`}
|
||||
</Button>
|
||||
<Button
|
||||
style={styles.item}
|
||||
size="small"
|
||||
accessible={true}
|
||||
accessibilityLabel={`${child.name}, ${translate(
|
||||
'navigation.notifications'
|
||||
)}`}
|
||||
accessibilityRole="button"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[notificationsStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: translate('navigation.notifications'),
|
||||
})
|
||||
}
|
||||
accessoryLeft={createFooterIcon(
|
||||
NotificationsIcon,
|
||||
colors['color-basic-text']
|
||||
)}
|
||||
>
|
||||
{`${(notifications || []).length}`}
|
||||
</Button>
|
||||
<Button
|
||||
style={styles.item}
|
||||
size="small"
|
||||
accessible={true}
|
||||
accessibilityLabel={`${child.name}, ${translate(
|
||||
'navigation.calender'
|
||||
)}`}
|
||||
accessibilityRole="button"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[calendarStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: translate('navigation.calender'),
|
||||
})
|
||||
}
|
||||
accessoryLeft={createFooterIcon(
|
||||
CalendarOutlineIcon,
|
||||
colors['color-basic-text']
|
||||
)}
|
||||
>
|
||||
{`${(calendar || []).length}`}
|
||||
</Button>
|
||||
<Button
|
||||
style={styles.item}
|
||||
size="small"
|
||||
accessible
|
||||
accessibilityLabel={`${child.name}, ${translate(
|
||||
'navigation.menu'
|
||||
)}`}
|
||||
accessibilityRole="button"
|
||||
appearance={buttonAppearance}
|
||||
status={statusColors[menuStatus]}
|
||||
onPress={() =>
|
||||
navigation.navigate('Child', {
|
||||
child,
|
||||
color,
|
||||
initialRouteName: translate('navigation.menu'),
|
||||
})
|
||||
}
|
||||
accessoryLeft={createFooterIcon(
|
||||
ClipboardIcon,
|
||||
colors['color-basic-text']
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Card>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
const createFooterIcon = (Icon: typeof BookOpenIcon, color: string) => (
|
||||
props: IconProps
|
||||
) => {
|
||||
return <Icon {...props} fill={color} />
|
||||
}
|
||||
|
||||
const themeStyles = StyleService.create({
|
||||
card: {
|
||||
marginBottom: Sizing.t5,
|
||||
borderRadius: 25,
|
||||
padding: Sizing.t5,
|
||||
marginBottom: Sizing.t4,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
},
|
||||
cardHeader: {
|
||||
...Layout.flex.row,
|
||||
...Layout.mainAxis.center,
|
||||
...Layout.crossAxis.spaceBetween,
|
||||
marginBottom: Sizing.t4,
|
||||
},
|
||||
cardHeaderLeft: {
|
||||
...Layout.flex.row,
|
||||
...Layout.mainAxis.center,
|
||||
flex: 1,
|
||||
},
|
||||
cardHeaderText: {
|
||||
marginHorizontal: Sizing.t4,
|
||||
flex: 1,
|
||||
},
|
||||
cardAvatar: { margin: Sizing.t5, marginRight: 0 },
|
||||
cardHeaderText: { margin: Sizing.t5, flex: 1 },
|
||||
itemFooter: {
|
||||
...Layout.flex.row,
|
||||
...Layout.crossAxis.evenly,
|
||||
paddingVertical: Sizing.t2,
|
||||
borderRadius: 5,
|
||||
margin: 0,
|
||||
marginTop: Sizing.t4,
|
||||
},
|
||||
itemFooterAbsence: {
|
||||
...Layout.mainAxis.flexStart,
|
||||
marginTop: Sizing.t4,
|
||||
},
|
||||
item: {
|
||||
paddingHorizontal: 0,
|
||||
},
|
||||
noNewNewsItemsText: {
|
||||
color: 'color-basic-600',
|
||||
marginRight: 12,
|
||||
paddingHorizontal: 2,
|
||||
paddingVertical: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
noNewNewsItemsText: {},
|
||||
})
|
||||
|
|
|
@ -1,28 +1,27 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
|
||||
import { useNavigation } from '@react-navigation/core'
|
||||
import { useApi, useChildList } from '@skolplattformen/api-hooks'
|
||||
import { Child } from '@skolplattformen/embedded-api'
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
Layout,
|
||||
List,
|
||||
Spinner,
|
||||
StyleService,
|
||||
Text,
|
||||
TopNavigation,
|
||||
TopNavigationAction,
|
||||
useTheme,
|
||||
useStyleSheet,
|
||||
} from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import React, { useCallback, useEffect, useMemo } from 'react'
|
||||
import {
|
||||
Image,
|
||||
ListRenderItemInfo,
|
||||
StyleSheet,
|
||||
View,
|
||||
ImageStyle,
|
||||
Linking,
|
||||
ListRenderItemInfo,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||
import ActionSheet from 'rn-actionsheet-module'
|
||||
import { defaultStackStyling } from '../design/navigationThemes'
|
||||
import { Colors, Layout as LayoutStyle, Sizing, Typography } from '../styles'
|
||||
import { translate } from '../utils/translation'
|
||||
import { ChildListItem } from './childListItem.component'
|
||||
|
@ -30,25 +29,43 @@ import { SettingsIcon } from './icon.component'
|
|||
|
||||
const colors = ['primary', 'success', 'info', 'warning', 'danger']
|
||||
|
||||
export const childenRouteOptions = (): NativeStackNavigationOptions => {
|
||||
return {
|
||||
...defaultStackStyling,
|
||||
title: translate('children.title'),
|
||||
headerLargeTitle: true,
|
||||
headerLargeTitleHideShadow: true,
|
||||
}
|
||||
}
|
||||
|
||||
export const Children = () => {
|
||||
const settingsOptions = [
|
||||
translate('general.logout'),
|
||||
translate('general.cancel'),
|
||||
]
|
||||
const theme = useTheme()
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
|
||||
const navigation = useNavigation()
|
||||
|
||||
const { api } = useApi()
|
||||
const { data: childList, status, reload } = useChildList()
|
||||
const insets = useSafeAreaInsets()
|
||||
const handleSettingSelection = (index: number) => {
|
||||
switch (index) {
|
||||
case 0:
|
||||
logout()
|
||||
break
|
||||
}
|
||||
let { data: childList, status, reload } = useChildList()
|
||||
const reloadChildren = () => {
|
||||
reload()
|
||||
}
|
||||
|
||||
const settings = () => {
|
||||
const logout = useCallback(() => {
|
||||
api.logout()
|
||||
AsyncStorage.clear()
|
||||
}, [api])
|
||||
|
||||
const settingsOptions = useMemo(() => {
|
||||
return [translate('general.logout'), translate('general.cancel')]
|
||||
}, [])
|
||||
|
||||
const handleSettingSelection = useCallback(
|
||||
(index: number) => {
|
||||
if (index === 0) logout()
|
||||
},
|
||||
[logout]
|
||||
)
|
||||
|
||||
const settings = useCallback(() => {
|
||||
const options = {
|
||||
cancelButtonIndex: 1,
|
||||
title: translate('general.settings'),
|
||||
|
@ -58,126 +75,93 @@ export const Children = () => {
|
|||
}
|
||||
|
||||
ActionSheet(options, handleSettingSelection)
|
||||
}
|
||||
}, [handleSettingSelection, settingsOptions])
|
||||
|
||||
const reloadChildren = () => {
|
||||
reload()
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
api.logout()
|
||||
AsyncStorage.clear()
|
||||
}
|
||||
useEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerRight: () => {
|
||||
return <TopNavigationAction icon={SettingsIcon} onPress={settings} />
|
||||
},
|
||||
})
|
||||
}, [navigation, settings])
|
||||
|
||||
// We need to skip safe area view here, due to the reason that it's adding a white border
|
||||
// when this view is actually lightgrey. Taking the padding top value from the use inset hook.
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
...styles.topContainer,
|
||||
paddingTop: insets.top,
|
||||
},
|
||||
{ backgroundColor: theme['background-basic-color-1'] },
|
||||
]}
|
||||
>
|
||||
<>
|
||||
{status === 'loaded' ? (
|
||||
<>
|
||||
<TopNavigation
|
||||
title={() => (
|
||||
<Text
|
||||
maxFontSizeMultiplier={2.5}
|
||||
style={styles.topNavigationTitle}
|
||||
<>
|
||||
{status === 'loaded' ? (
|
||||
<List
|
||||
contentContainerStyle={styles.childListContainer}
|
||||
data={childList}
|
||||
style={styles.childList}
|
||||
ListEmptyComponent={
|
||||
<View style={styles.emptyState}>
|
||||
<Text category="h2">{translate('children.noKids_title')}</Text>
|
||||
<Text style={styles.emptyStateDescription}>
|
||||
{translate('children.noKids_description')}
|
||||
</Text>
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
source={require('../assets/children.png')}
|
||||
style={styles.emptyStateImage as ImageStyle}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
renderItem={({ item: child, index }: ListRenderItemInfo<Child>) => (
|
||||
<ChildListItem
|
||||
child={child}
|
||||
color={colors[index % colors.length]}
|
||||
key={child.id}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.loading}>
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
source={require('../assets/girls.png')}
|
||||
style={styles.loadingImage as ImageStyle}
|
||||
/>
|
||||
{status === 'error' ? (
|
||||
<View style={styles.errorMessage}>
|
||||
<Text category="h5">
|
||||
{translate('children.loadingErrorHeading')}
|
||||
</Text>
|
||||
<Text style={{ fontSize: Sizing.t4 }}>
|
||||
{translate('children.loadingErrorInformationText')}
|
||||
</Text>
|
||||
<View style={styles.errorButtons}>
|
||||
<Button status="success" onPress={() => reloadChildren()}>
|
||||
{translate('children.tryAgain')}
|
||||
</Button>
|
||||
<Button
|
||||
status="basic"
|
||||
onPress={() =>
|
||||
Linking.openURL('https://skolplattformen.org/status')
|
||||
}
|
||||
>
|
||||
{translate('children.title')}
|
||||
</Text>
|
||||
)}
|
||||
alignment="center"
|
||||
accessoryRight={() => (
|
||||
<TopNavigationAction icon={SettingsIcon} onPress={settings} />
|
||||
)}
|
||||
/>
|
||||
<Divider />
|
||||
<List
|
||||
contentContainerStyle={styles.childListContainer}
|
||||
data={childList}
|
||||
style={styles.childList}
|
||||
ListEmptyComponent={
|
||||
<View style={styles.emptyState}>
|
||||
<Text category="h2">
|
||||
{translate('children.noKids_title')}
|
||||
</Text>
|
||||
<Text style={styles.emptyStateDescription}>
|
||||
{translate('children.noKids_description')}
|
||||
</Text>
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
source={require('../assets/children.png')}
|
||||
style={styles.emptyStateImage}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
renderItem={({
|
||||
item: child,
|
||||
index,
|
||||
}: ListRenderItemInfo<Child>) => (
|
||||
<ChildListItem
|
||||
child={child}
|
||||
color={colors[index % colors.length]}
|
||||
key={child.id}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Layout style={styles.loading}>
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
source={require('../assets/girls.png')}
|
||||
style={styles.loadingImage}
|
||||
/>
|
||||
{status === 'error' ? (
|
||||
<View style={styles.errorMessage}>
|
||||
<Text category="h5">
|
||||
{translate('children.loadingErrorHeading')}
|
||||
</Text>
|
||||
<Text style={{ fontSize: Sizing.t5 }}>
|
||||
{translate('children.loadingErrorInformationText')}
|
||||
</Text>
|
||||
<View style={styles.errorButtons}>
|
||||
<Button status="success" onPress={() => reloadChildren()}>
|
||||
{translate('children.tryAgain')}
|
||||
</Button>
|
||||
<Button
|
||||
status="basic"
|
||||
onPress={() =>
|
||||
Linking.openURL('https://skolplattformen.org/status')
|
||||
}
|
||||
>
|
||||
{translate('children.viewStatus')}
|
||||
</Button>
|
||||
<Button onPress={() => logout()}>
|
||||
{translate('general.logout')}
|
||||
</Button>
|
||||
</View>
|
||||
{translate('children.viewStatus')}
|
||||
</Button>
|
||||
<Button onPress={() => logout()}>
|
||||
{translate('general.logout')}
|
||||
</Button>
|
||||
</View>
|
||||
) : (
|
||||
<View style={styles.loadingMessage}>
|
||||
<Spinner size="large" status="warning" />
|
||||
<Text category="h1" style={styles.loadingText}>
|
||||
{translate('general.loading')}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</Layout>
|
||||
)}
|
||||
</>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View style={styles.loadingMessage}>
|
||||
<Spinner size="large" status="primary" />
|
||||
<Text category="h1" style={styles.loadingText}>
|
||||
{translate('general.loading')}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
const themedStyles = StyleService.create({
|
||||
topContainer: {
|
||||
...LayoutStyle.flex.full,
|
||||
paddingBottom: 0,
|
||||
|
@ -216,7 +200,8 @@ const styles = StyleSheet.create({
|
|||
...LayoutStyle.flex.full,
|
||||
},
|
||||
childListContainer: {
|
||||
padding: Sizing.t5,
|
||||
paddingVertical: Sizing.t4,
|
||||
paddingHorizontal: Sizing.t3,
|
||||
},
|
||||
emptyState: {
|
||||
...LayoutStyle.center,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { Icon } from '@ui-kitten/components'
|
||||
import { Icon, IconProps } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
|
||||
const uiIcon = (name: string) => (props: any) => <Icon {...props} name={name} />
|
||||
const uiIcon = (name: string) => (props: IconProps) => (
|
||||
<Icon {...props} name={name} />
|
||||
)
|
||||
|
||||
export const AlertIcon = uiIcon('alert-circle-outline')
|
||||
export const BackIcon = uiIcon('arrow-back')
|
||||
|
@ -26,3 +28,4 @@ export const SearchIcon = uiIcon('search-outline')
|
|||
export const BookOpenIcon = uiIcon('book-open-outline')
|
||||
export const GlobeIcon = uiIcon('globe-outline')
|
||||
export const ExternalLinkIcon = uiIcon('external-link-outline')
|
||||
export const ClipboardIcon = uiIcon('clipboard-outline')
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
import { StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { ActivityIndicator, View, StyleSheet } from 'react-native'
|
||||
import { ActivityIndicator, View } from 'react-native'
|
||||
|
||||
export const LoadingComponent = () => (
|
||||
<View style={[styles.container, styles.horizontal]}>
|
||||
<ActivityIndicator size="large" />
|
||||
</View>
|
||||
)
|
||||
export const LoadingComponent = () => {
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
return (
|
||||
<View style={[styles.container, styles.horizontal]}>
|
||||
<ActivityIndicator size="large" />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const themedStyles = StyleService.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
},
|
||||
horizontal: {
|
||||
flexDirection: 'row',
|
||||
|
|
|
@ -32,10 +32,11 @@ import {
|
|||
SelectIcon,
|
||||
} from './icon.component'
|
||||
|
||||
const BankId = (style) => (
|
||||
const BankId = () => (
|
||||
<Image
|
||||
style={themedStyles.icon}
|
||||
source={require('../assets/bankid_low_rgb.png')}
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -60,7 +61,9 @@ export const Login = () => {
|
|||
translate('auth.bankid.OpenOnThisDevice'),
|
||||
translate('auth.bankid.OpenOnAnotherDevice'),
|
||||
translate('auth.loginAsTestUser'),
|
||||
translate('general.cancel'),
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
if (loginMethodIndex !== parseInt(cachedLoginMethodIndex, 10)) {
|
||||
setCachedLoginMethodIndex(loginMethodIndex.toString())
|
||||
|
@ -180,7 +183,7 @@ export const Login = () => {
|
|||
placeholder={translate('auth.placeholder_SocialSecurityNumber')}
|
||||
/>
|
||||
)}
|
||||
<ButtonGroup style={styles.loginButtonGroup} status="info">
|
||||
<ButtonGroup style={styles.loginButtonGroup} status="primary">
|
||||
<Button
|
||||
accessible={true}
|
||||
onPress={() => startLogin(socialSecurityNumber)}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import { useMenu } from '@skolplattformen/api-hooks'
|
||||
import { MenuItem } from '@skolplattformen/embedded-api'
|
||||
import { List, Text } from '@ui-kitten/components'
|
||||
import {
|
||||
Divider,
|
||||
List,
|
||||
StyleService,
|
||||
Text,
|
||||
useStyleSheet,
|
||||
} from '@ui-kitten/components'
|
||||
import 'moment/locale/sv'
|
||||
import React from 'react'
|
||||
import { Image, ListRenderItemInfo, StyleSheet, View } from 'react-native'
|
||||
import { Sizing, Layout as LayoutStyle, Typography } from '../styles'
|
||||
import { Image, ImageStyle, ListRenderItemInfo, View } from 'react-native'
|
||||
import { Layout as LayoutStyle, Sizing, Typography } from '../styles'
|
||||
import { translate } from '../utils/translation'
|
||||
import { useChild } from './childContext.component'
|
||||
import { MenuListItem } from './menuListItem.component'
|
||||
|
||||
export const Menu = () => {
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
const child = useChild()
|
||||
const { data } = useMenu(child)
|
||||
|
||||
|
@ -17,6 +24,7 @@ export const Menu = () => {
|
|||
<List
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
data={data}
|
||||
ItemSeparatorComponent={Divider}
|
||||
ListEmptyComponent={
|
||||
<View style={styles.emptyState}>
|
||||
<Text category="h4">{translate('menu.emptyHeadline')}</Text>
|
||||
|
@ -26,7 +34,7 @@ export const Menu = () => {
|
|||
<Image
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
source={require('../assets/children.png')}
|
||||
style={styles.emptyStateImage}
|
||||
style={styles.emptyStateImage as ImageStyle}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
|
@ -38,23 +46,26 @@ export const Menu = () => {
|
|||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
const themedStyles = StyleService.create({
|
||||
container: {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
padding: Sizing.t3,
|
||||
},
|
||||
contentContainer: {
|
||||
padding: Sizing.t3,
|
||||
paddingHorizontal: Sizing.t5,
|
||||
paddingVertical: Sizing.t2,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
borderRadius: 25,
|
||||
},
|
||||
emptyState: {
|
||||
...LayoutStyle.center,
|
||||
...LayoutStyle.flex.full,
|
||||
paddingHorizontal: Sizing.t5,
|
||||
paddingTop: 25,
|
||||
},
|
||||
emptyStateDescription: {
|
||||
...Typography.align.center,
|
||||
lineHeight: 21,
|
||||
paddingHorizontal: Sizing.t3,
|
||||
marginTop: Sizing.t3,
|
||||
},
|
||||
emptyStateImage: {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Text, Card, StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
import { MenuItem } from '@skolplattformen/embedded-api'
|
||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { MenuItem } from '@skolplattformen/embedded-api'
|
||||
import { Sizing, Typography } from '../styles'
|
||||
|
||||
interface MenuListItemProps {
|
||||
|
@ -12,16 +12,8 @@ export const MenuListItem = ({ item }: MenuListItemProps) => {
|
|||
const styles = useStyleSheet(themedStyles)
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Card
|
||||
header={(props) => (
|
||||
<View {...props}>
|
||||
<Text style={styles.title}>{item.title}</Text>
|
||||
</View>
|
||||
)}
|
||||
style={styles.contentContainer}
|
||||
>
|
||||
<Text category="p1">{item.description}</Text>
|
||||
</Card>
|
||||
<Text style={styles.title}>{item.title}</Text>
|
||||
<Text category="p1">{item.description}</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
@ -29,10 +21,7 @@ export const MenuListItem = ({ item }: MenuListItemProps) => {
|
|||
const themedStyles = StyleService.create({
|
||||
container: {
|
||||
width: '100%',
|
||||
},
|
||||
contentContainer: {
|
||||
marginBottom: Sizing.t2,
|
||||
justifyContent: 'flex-start',
|
||||
paddingVertical: Sizing.t3,
|
||||
},
|
||||
topContainer: {
|
||||
margin: Sizing.t1,
|
||||
|
@ -41,6 +30,6 @@ const themedStyles = StyleService.create({
|
|||
},
|
||||
title: {
|
||||
...Typography.header,
|
||||
color: 'color-basic-800',
|
||||
marginBottom: Sizing.t1,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -88,7 +88,7 @@ export const ModalWebView = ({
|
|||
const themedStyles = StyleService.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
},
|
||||
headerWrapper: {
|
||||
marginTop: Sizing.t1,
|
||||
|
@ -96,7 +96,7 @@ const themedStyles = StyleService.create({
|
|||
borderRadius: 2,
|
||||
borderColor: 'basic-color-200',
|
||||
borderBottomWidth: 1,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
},
|
||||
backdrop: {
|
||||
backgroundColor: 'color-basic-transparent-600',
|
||||
|
@ -111,7 +111,7 @@ const themedStyles = StyleService.create({
|
|||
...Layout.mainAxis.center,
|
||||
paddingHorizontal: Sizing.t3,
|
||||
paddingVertical: Sizing.t1,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
},
|
||||
shareIcon: {
|
||||
width: 24,
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
import { useApi } from '@skolplattformen/api-hooks'
|
||||
import { NavigationContainer } from '@react-navigation/native'
|
||||
import { createStackNavigator } from '@react-navigation/stack'
|
||||
import React, { useEffect } from 'react'
|
||||
import { StatusBar } from 'react-native'
|
||||
import { schema } from '../app.json'
|
||||
import Absence from './absence.component'
|
||||
import { Child } from './child.component'
|
||||
import { Children } from './children.component'
|
||||
import { Auth } from './auth.component'
|
||||
import { SetLanguage } from './setLanguage.component'
|
||||
import { NewsItem } from './newsItem.component'
|
||||
import { useApi } from '@skolplattformen/api-hooks'
|
||||
import {
|
||||
Child as ChildType,
|
||||
NewsItem as NewsItemType,
|
||||
} from '@skolplattformen/embedded-api'
|
||||
import { useTheme } from '@ui-kitten/components'
|
||||
import React, { useEffect } from 'react'
|
||||
import { StatusBar, useColorScheme } from 'react-native'
|
||||
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
||||
import { schema } from '../app.json'
|
||||
import {
|
||||
darkNavigationTheme,
|
||||
lightNavigationTheme,
|
||||
} from '../design/navigationThemes'
|
||||
import { useAppState } from '../hooks/useAppState'
|
||||
import Absence, { absenceRouteOptions } from './absence.component'
|
||||
import { Auth, authRouteOptions } from './auth.component'
|
||||
import { Child, childRouteOptions } from './child.component'
|
||||
import { childenRouteOptions, Children } from './children.component'
|
||||
import { NewsItem, newsItemRouteOptions } from './newsItem.component'
|
||||
import { SetLanguage, setLanguageRouteOptions } from './setLanguage.component'
|
||||
|
||||
export type RootStackParamList = {
|
||||
Login: undefined
|
||||
|
@ -29,7 +34,7 @@ export type RootStackParamList = {
|
|||
SetLanguage: undefined
|
||||
}
|
||||
|
||||
const { Navigator, Screen } = createStackNavigator()
|
||||
const { Navigator, Screen } = createNativeStackNavigator<RootStackParamList>()
|
||||
|
||||
const linking = {
|
||||
prefixes: [schema],
|
||||
|
@ -43,6 +48,9 @@ const linking = {
|
|||
export const AppNavigator = () => {
|
||||
const { isLoggedIn, api } = useApi()
|
||||
|
||||
const colorScheme = useColorScheme()
|
||||
const colors = useTheme()
|
||||
|
||||
const currentAppState = useAppState()
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -59,20 +67,56 @@ export const AppNavigator = () => {
|
|||
}, [currentAppState, isLoggedIn, api])
|
||||
|
||||
return (
|
||||
<NavigationContainer linking={linking}>
|
||||
<NavigationContainer
|
||||
linking={linking}
|
||||
theme={
|
||||
colorScheme === 'dark' ? darkNavigationTheme : lightNavigationTheme
|
||||
}
|
||||
>
|
||||
<StatusBar />
|
||||
<Navigator headerMode="none">
|
||||
<Navigator
|
||||
screenOptions={() => ({
|
||||
headerLargeTitle: true,
|
||||
headerLargeTitleHideShadow: true,
|
||||
headerStyle: {
|
||||
backgroundColor: colors['background-basic-color-2'],
|
||||
},
|
||||
headerLargeTitleStyle: {
|
||||
fontFamily: 'Poppins-ExtraBold',
|
||||
},
|
||||
})}
|
||||
>
|
||||
{isLoggedIn ? (
|
||||
<>
|
||||
<Screen name="Children" component={Children} />
|
||||
<Screen name="Child" component={Child} />
|
||||
<Screen name="NewsItem" component={NewsItem} />
|
||||
<Screen name="Absence" component={Absence} />
|
||||
<Screen
|
||||
name="Children"
|
||||
component={Children}
|
||||
options={childenRouteOptions}
|
||||
/>
|
||||
<Screen
|
||||
name="Child"
|
||||
component={Child}
|
||||
options={childRouteOptions}
|
||||
/>
|
||||
<Screen
|
||||
name="NewsItem"
|
||||
component={NewsItem}
|
||||
options={newsItemRouteOptions}
|
||||
/>
|
||||
<Screen
|
||||
name="Absence"
|
||||
component={Absence}
|
||||
options={absenceRouteOptions}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Screen name="Login" component={Auth} />
|
||||
<Screen name="SetLanguage" component={SetLanguage} />
|
||||
<Screen name="Login" component={Auth} options={authRouteOptions} />
|
||||
<Screen
|
||||
name="SetLanguage"
|
||||
component={SetLanguage}
|
||||
options={setLanguageRouteOptions}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Navigator>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { Text } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { Layout } from '../styles'
|
||||
import { fontSize } from '../styles/typography'
|
||||
|
||||
interface NavigationTitleProps {
|
||||
title?: string
|
||||
subtitle?: string
|
||||
}
|
||||
/**
|
||||
* Navigation Title with a smaller subtitle.
|
||||
*/
|
||||
export const NavigationTitle = ({ title, subtitle }: NavigationTitleProps) => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>{title}</Text>
|
||||
<Text style={styles.subtitle}>{subtitle}</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
...Layout.center,
|
||||
},
|
||||
title: {
|
||||
...fontSize.base,
|
||||
fontWeight: '500',
|
||||
},
|
||||
subtitle: { ...fontSize.xs },
|
||||
})
|
|
@ -1,26 +1,18 @@
|
|||
import { RouteProp } from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { useNewsDetails } from '@skolplattformen/api-hooks'
|
||||
import {
|
||||
Divider,
|
||||
Text,
|
||||
TopNavigation,
|
||||
TopNavigationAction,
|
||||
StyleService,
|
||||
useStyleSheet,
|
||||
} from '@ui-kitten/components'
|
||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/sv'
|
||||
import React from 'react'
|
||||
import { ScrollView, View } from 'react-native'
|
||||
import { Colors, Layout, Sizing, Typography } from '../styles'
|
||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||
import { defaultStackStyling } from '../design/navigationThemes'
|
||||
import { Layout, Sizing, Typography } from '../styles'
|
||||
import { translate } from '../utils/translation'
|
||||
import { BackIcon } from './icon.component'
|
||||
import { Image } from './image.component'
|
||||
import { Markdown } from './markdown.component'
|
||||
import { RootStackParamList } from './navigation.component'
|
||||
import { SafeAreaViewContainer } from '../ui/safeAreaViewContainer.component'
|
||||
import { SafeAreaView } from '../ui/safeAreaView.component'
|
||||
|
||||
interface NewsItemProps {
|
||||
navigation: StackNavigationProp<RootStackParamList, 'NewsItem'>
|
||||
|
@ -32,111 +24,90 @@ const displayDate = (date: string | undefined) => moment(date).format('lll')
|
|||
const dateIsValid = (date: string | undefined) =>
|
||||
moment(date, moment.ISO_8601).isValid()
|
||||
|
||||
export const NewsItem = ({ navigation, route }: NewsItemProps) => {
|
||||
export const newsItemRouteOptions = ({
|
||||
route,
|
||||
}: {
|
||||
route: RouteProp<RootStackParamList, 'NewsItem'>
|
||||
}): NativeStackNavigationOptions => {
|
||||
const newsItem = route.params.newsItem
|
||||
|
||||
return {
|
||||
...defaultStackStyling,
|
||||
title: newsItem.header,
|
||||
headerLargeTitle: true,
|
||||
headerStyle: {
|
||||
// TODO: This color must come from theme for dark mode
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const NewsItem = ({ route }: NewsItemProps) => {
|
||||
const { newsItem, child } = route.params
|
||||
const { data } = useNewsDetails(child, newsItem)
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
const stylesMarkdown = useStyleSheet(themedStylesMarkdown)
|
||||
|
||||
const navigateBack = () => {
|
||||
navigation.goBack()
|
||||
}
|
||||
|
||||
const BackAction = () => (
|
||||
<TopNavigationAction
|
||||
testID="topNavBackToChild"
|
||||
accessibilityHint={translate('news.backToChild')}
|
||||
icon={BackIcon}
|
||||
onPress={navigateBack}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<SafeAreaViewContainer>
|
||||
<TopNavigation
|
||||
title={() => (
|
||||
<Text maxFontSizeMultiplier={1.5} style={styles.topNavigationTitle}>
|
||||
{translate('news.title')}
|
||||
</Text>
|
||||
)}
|
||||
alignment="center"
|
||||
accessoryLeft={BackAction}
|
||||
/>
|
||||
<Divider />
|
||||
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.article}
|
||||
style={styles.scrollView}
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.article}
|
||||
style={styles.scrollView}
|
||||
>
|
||||
{dateIsValid(newsItem.published) && (
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
style={[styles.subtitle, styles.published]}
|
||||
>
|
||||
<Text maxFontSizeMultiplier={2} style={styles.title}>
|
||||
{newsItem.header}
|
||||
</Text>
|
||||
{dateIsValid(newsItem.published) && (
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
style={[styles.subtitle, styles.published]}
|
||||
>
|
||||
<Text style={styles.strong}>{translate('news.published')}:</Text>{' '}
|
||||
{displayDate(newsItem.published)}
|
||||
</Text>
|
||||
)}
|
||||
{dateIsValid(newsItem.modified) && (
|
||||
<Text maxFontSizeMultiplier={2} style={styles.subtitle}>
|
||||
<Text style={styles.strong}>{translate('news.updated')}:</Text>{' '}
|
||||
{displayDate(newsItem.modified)}
|
||||
</Text>
|
||||
)}
|
||||
<View style={styles.body}>
|
||||
<Markdown style={stylesMarkdown}>{data.body}</Markdown>
|
||||
{newsItem.fullImageUrl && (
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
src={newsItem.fullImageUrl}
|
||||
// @ts-expect-error Fix later on
|
||||
style={styles.image}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaViewContainer>
|
||||
</SafeAreaView>
|
||||
<Text style={styles.strong}>{translate('news.published')}:</Text>{' '}
|
||||
{displayDate(newsItem.published)}
|
||||
</Text>
|
||||
)}
|
||||
{dateIsValid(newsItem.modified) && (
|
||||
<Text maxFontSizeMultiplier={2} style={styles.subtitle}>
|
||||
<Text style={styles.strong}>{translate('news.updated')}:</Text>{' '}
|
||||
{displayDate(newsItem.modified)}
|
||||
</Text>
|
||||
)}
|
||||
<View style={styles.body}>
|
||||
<Markdown style={stylesMarkdown}>{data.body}</Markdown>
|
||||
{newsItem.fullImageUrl && (
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
src={newsItem.fullImageUrl}
|
||||
// @ts-expect-error Fix later on
|
||||
style={styles.image}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
)
|
||||
}
|
||||
|
||||
const themedStylesMarkdown = StyleService.create({
|
||||
body: {
|
||||
...Typography.fontSize.base,
|
||||
color: 'color-basic-800',
|
||||
color: 'text-basic-color',
|
||||
lineHeight: 26,
|
||||
},
|
||||
heading1: {
|
||||
...Typography.fontSize.xl,
|
||||
color: 'color-basic-600',
|
||||
color: 'text-basic-color',
|
||||
},
|
||||
heading2: {
|
||||
...Typography.fontSize.lg,
|
||||
color: 'color-basic-800',
|
||||
color: 'text-basic-color',
|
||||
},
|
||||
code_block: {
|
||||
color: 'color-basic-800',
|
||||
color: 'text-basic-color',
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
borderColor: 'color-basic-400',
|
||||
},
|
||||
})
|
||||
|
||||
const themedStyles = StyleService.create({
|
||||
safeArea: {
|
||||
...Layout.flex.full,
|
||||
backgroundColor: Colors.neutral.white,
|
||||
},
|
||||
topContainer: {
|
||||
...Layout.flex.row,
|
||||
...Layout.crossAxis.spaceBetween,
|
||||
},
|
||||
article: {
|
||||
padding: Sizing.t5,
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
},
|
||||
scrollView: {
|
||||
...Layout.flex.full,
|
||||
|
@ -145,6 +116,7 @@ const themedStyles = StyleService.create({
|
|||
width: '100%',
|
||||
minHeight: 300,
|
||||
marginTop: Sizing.t4,
|
||||
borderRadius: 15,
|
||||
},
|
||||
title: {
|
||||
...Typography.fontWeight.bold,
|
||||
|
@ -153,12 +125,12 @@ const themedStyles = StyleService.create({
|
|||
},
|
||||
subtitle: {
|
||||
...Typography.fontSize.xs,
|
||||
color: 'color-basic-600',
|
||||
color: 'text-hint-color',
|
||||
},
|
||||
strong: {
|
||||
...Typography.fontSize.xs,
|
||||
...Typography.fontWeight.bold,
|
||||
color: 'color-basic-600',
|
||||
color: 'text-hint-color',
|
||||
},
|
||||
published: {
|
||||
marginBottom: Sizing.t1,
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import React, { useState, useMemo } from 'react'
|
||||
import { useNews } from '@skolplattformen/api-hooks'
|
||||
import { List, Input } from '@ui-kitten/components'
|
||||
import { StyleSheet, TouchableWithoutFeedback } from 'react-native'
|
||||
import { Input, List, StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { TouchableOpacity, View } from 'react-native'
|
||||
import { Sizing } from '../styles'
|
||||
import { useChild } from './childContext.component'
|
||||
import { NewsListItem } from './newsListItem.component'
|
||||
import { translate } from '../utils/translation'
|
||||
import {
|
||||
useNewsListSearchResults,
|
||||
renderSearchResultPreview,
|
||||
useNewsListSearchResults,
|
||||
} from '../utils/search'
|
||||
import { SearchIcon, CloseOutlineIcon } from './icon.component'
|
||||
import { translate } from '../utils/translation'
|
||||
import { useChild } from './childContext.component'
|
||||
import { CloseOutlineIcon, SearchIcon } from './icon.component'
|
||||
import { NewsListItem } from './newsListItem.component'
|
||||
|
||||
export const NewsList = () => {
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
const child = useChild()
|
||||
const { data } = useNews(child)
|
||||
|
||||
|
@ -33,14 +34,19 @@ export const NewsList = () => {
|
|||
accessoryLeft={SearchIcon}
|
||||
onChangeText={setSearchQuery}
|
||||
value={searchQuery}
|
||||
accessoryRight={(props) => (
|
||||
<TouchableWithoutFeedback onPress={() => setSearchQuery('')}>
|
||||
<CloseOutlineIcon {...props} />
|
||||
</TouchableWithoutFeedback>
|
||||
)}
|
||||
style={styles.search}
|
||||
accessoryRight={(props) =>
|
||||
searchQuery.length > 0 ? (
|
||||
<TouchableOpacity onPress={() => setSearchQuery('')}>
|
||||
<CloseOutlineIcon {...props} />
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
<View />
|
||||
)
|
||||
}
|
||||
/>
|
||||
),
|
||||
[searchQuery]
|
||||
[searchQuery, styles.search]
|
||||
)
|
||||
|
||||
if (searchQuery) {
|
||||
|
@ -72,12 +78,18 @@ export const NewsList = () => {
|
|||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
const themedStyles = StyleService.create({
|
||||
container: {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
},
|
||||
contentContainer: {
|
||||
padding: Sizing.t3,
|
||||
paddingVertical: Sizing.t3,
|
||||
paddingHorizontal: Sizing.t3,
|
||||
},
|
||||
search: {
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
borderRadius: 40,
|
||||
marginBottom: Sizing.t2,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { useNavigation } from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { NewsItem } from '@skolplattformen/embedded-api'
|
||||
import React, { ReactNode } from 'react'
|
||||
import { StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
import moment from 'moment'
|
||||
import React, { ReactNode } from 'react'
|
||||
import { Dimensions, Text, View } from 'react-native'
|
||||
import { TouchableOpacity } from 'react-native-gesture-handler'
|
||||
import { Layout, Sizing, Typography } from '../styles'
|
||||
import { useChild } from './childContext.component'
|
||||
import { Image } from './image.component'
|
||||
import { RootStackParamList } from './navigation.component'
|
||||
import { StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
|
||||
interface NewsListItemProps {
|
||||
item: NewsItem
|
||||
|
@ -66,15 +66,11 @@ const themedStyles = StyleService.create({
|
|||
card: {
|
||||
...Layout.flex.full,
|
||||
...Layout.flex.row,
|
||||
|
||||
borderRadius: 2,
|
||||
|
||||
borderWidth: 1,
|
||||
padding: Sizing.t5,
|
||||
marginBottom: Sizing.t2,
|
||||
|
||||
borderRadius: 15,
|
||||
paddingVertical: Sizing.t4,
|
||||
paddingHorizontal: Sizing.t4,
|
||||
marginBottom: Sizing.t3,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
borderColor: 'border-basic-color-3',
|
||||
},
|
||||
text: {
|
||||
...Layout.flex.full,
|
||||
|
@ -86,7 +82,6 @@ const themedStyles = StyleService.create({
|
|||
},
|
||||
subtitle: {
|
||||
...Typography.fontSize.xs,
|
||||
|
||||
marginBottom: Sizing.t2,
|
||||
color: 'text-hint-color',
|
||||
},
|
||||
|
@ -95,9 +90,9 @@ const themedStyles = StyleService.create({
|
|||
color: 'text-basic-color',
|
||||
},
|
||||
image: {
|
||||
borderRadius: 3,
|
||||
width: 80,
|
||||
height: 80,
|
||||
marginRight: Sizing.t5,
|
||||
borderRadius: 50,
|
||||
width: 50,
|
||||
height: 50,
|
||||
marginRight: Sizing.t3,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Notification as NotificationType } from '@skolplattformen/embedded-api'
|
||||
import { Card, StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||
import moment from 'moment'
|
||||
import React from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { TouchableOpacity, View } from 'react-native'
|
||||
import { Layout, Sizing, Typography } from '../styles'
|
||||
import { ModalWebView } from './modalWebView.component'
|
||||
import moment from 'moment'
|
||||
|
||||
interface NotificationProps {
|
||||
item: NotificationType
|
||||
|
@ -26,11 +26,9 @@ export const Notification = ({ item }: NotificationProps) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
style={styles.card}
|
||||
onPress={open}
|
||||
header={(headerProps) => (
|
||||
<View {...headerProps}>
|
||||
<TouchableOpacity onPress={open}>
|
||||
<View style={styles.card}>
|
||||
<View>
|
||||
<Text style={styles.title}>{item.sender}</Text>
|
||||
<Text style={styles.subtitle}>
|
||||
{item.category ? item.category : ''}
|
||||
|
@ -38,10 +36,9 @@ export const Notification = ({ item }: NotificationProps) => {
|
|||
{displayDate ? displayDate : ''}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
>
|
||||
<Text>{item.message}</Text>
|
||||
</Card>
|
||||
<Text>{item.message}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
{isOpen && (
|
||||
<ModalWebView
|
||||
url={item.url}
|
||||
|
@ -56,13 +53,11 @@ export const Notification = ({ item }: NotificationProps) => {
|
|||
const themedStyles = StyleService.create({
|
||||
card: {
|
||||
...Layout.flex.full,
|
||||
borderRadius: 2,
|
||||
|
||||
borderWidth: 1,
|
||||
marginBottom: Sizing.t2,
|
||||
|
||||
borderRadius: 15,
|
||||
paddingVertical: Sizing.t4,
|
||||
paddingHorizontal: Sizing.t4,
|
||||
marginBottom: Sizing.t3,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
borderColor: 'border-basic-color-3',
|
||||
},
|
||||
title: {
|
||||
...Typography.header,
|
||||
|
@ -71,5 +66,6 @@ const themedStyles = StyleService.create({
|
|||
subtitle: {
|
||||
...Typography.fontSize.xs,
|
||||
color: 'text-hint-color',
|
||||
marginBottom: Sizing.t2,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import { useNotifications } from '@skolplattformen/api-hooks'
|
||||
import { List } from '@ui-kitten/components'
|
||||
import { List, StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { StyleSheet } from 'react-native'
|
||||
import { Sizing } from '../styles'
|
||||
import { useChild } from './childContext.component'
|
||||
import { Notification } from './notification.component'
|
||||
|
||||
export const NotificationsList = () => {
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
const child = useChild()
|
||||
const { data } = useNotifications(child)
|
||||
|
||||
return (
|
||||
<List
|
||||
style={styles.container}
|
||||
|
@ -21,12 +22,13 @@ export const NotificationsList = () => {
|
|||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
const themedStyles = StyleService.create({
|
||||
container: {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
},
|
||||
contentContainer: {
|
||||
padding: Sizing.t3,
|
||||
paddingHorizontal: Sizing.t3,
|
||||
paddingVertical: Sizing.t3,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,26 +1,32 @@
|
|||
import { useNavigation } from '@react-navigation/native'
|
||||
import {
|
||||
Layout,
|
||||
Text,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
TopNavigationAction,
|
||||
TopNavigation,
|
||||
StyleService,
|
||||
Text,
|
||||
useStyleSheet,
|
||||
useTheme,
|
||||
} from '@ui-kitten/components'
|
||||
import React, { useState } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { View } from 'react-native'
|
||||
import { ScrollView, TouchableOpacity } from 'react-native-gesture-handler'
|
||||
import RNRestart from 'react-native-restart'
|
||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||
import { useLanguage } from '../hooks/useLanguage'
|
||||
import { isRTL, LanguageService } from '../services/languageService'
|
||||
import { Layout as LayoutStyle, Sizing } from '../styles'
|
||||
import { translate, languages } from '../utils/translation'
|
||||
import { BackIcon } from './icon.component'
|
||||
import { SafeAreaViewContainer } from '../ui/safeAreaViewContainer.component'
|
||||
import RNRestart from 'react-native-restart'
|
||||
import { SafeAreaView } from '../ui/safeAreaView.component'
|
||||
import { fontSize } from '../styles/typography'
|
||||
import { languages, translate } from '../utils/translation'
|
||||
import { CheckIcon } from './icon.component'
|
||||
|
||||
export const setLanguageRouteOptions = (): NativeStackNavigationOptions => ({
|
||||
title: translate('language.changeLanguage'),
|
||||
})
|
||||
|
||||
export const SetLanguage = () => {
|
||||
const navigation = useNavigation()
|
||||
const styles = useStyleSheet(themedStyles)
|
||||
const colors = useTheme()
|
||||
|
||||
const currentLanguage = LanguageService.getLanguageCode()
|
||||
|
||||
|
@ -56,76 +62,63 @@ export const SetLanguage = () => {
|
|||
const activeLanguages = languages.filter((language) => language.active)
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<SafeAreaViewContainer>
|
||||
<TopNavigation
|
||||
accessoryLeft={() => (
|
||||
<TopNavigationAction icon={BackIcon} onPress={() => goBack()} />
|
||||
)}
|
||||
alignment="center"
|
||||
title={translate('language.changeLanguage')}
|
||||
/>
|
||||
|
||||
<View style={styles.content}>
|
||||
<ScrollView>
|
||||
<Layout style={styles.container}>
|
||||
<View style={styles.languageList}>
|
||||
{activeLanguages.map((language) => (
|
||||
<TouchableOpacity
|
||||
key={language.langCode}
|
||||
style={styles.languageButton}
|
||||
onPress={() => setSelectedLanguage(language.langCode)}
|
||||
>
|
||||
<Text style={styles.check}>
|
||||
{isSelected(language.langCode) ? '✓' : ''}
|
||||
</Text>
|
||||
<Text>{language.languageName}</Text>
|
||||
<Text style={styles.languageButtonSubtitle}>
|
||||
{language.languageLocalName}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</Layout>
|
||||
</ScrollView>
|
||||
|
||||
<ButtonGroup style={styles.buttonGroup}>
|
||||
<Button
|
||||
onPress={() => saveLanguage()}
|
||||
appearance="ghost"
|
||||
status="primary"
|
||||
disabled={currentLanguage === selectedLanguage}
|
||||
style={styles.button}
|
||||
size="medium"
|
||||
<View style={styles.content}>
|
||||
<ScrollView>
|
||||
<View style={styles.languageList}>
|
||||
{activeLanguages.map((language) => (
|
||||
<TouchableOpacity
|
||||
key={language.langCode}
|
||||
style={styles.languageButton}
|
||||
onPress={() => setSelectedLanguage(language.langCode)}
|
||||
>
|
||||
{translate('language.changeLanguageButton')}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
<View>
|
||||
<Text style={styles.languageButtonTitle}>
|
||||
{language.languageLocalName}
|
||||
</Text>
|
||||
<Text style={styles.languageButtonSubtitle}>
|
||||
{language.languageName}
|
||||
</Text>
|
||||
</View>
|
||||
{isSelected(language.langCode) ? (
|
||||
<CheckIcon
|
||||
height={24}
|
||||
width={24}
|
||||
fill={colors['color-success-600']}
|
||||
/>
|
||||
) : null}
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</SafeAreaViewContainer>
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
|
||||
<ButtonGroup style={styles.buttonGroup}>
|
||||
<Button
|
||||
onPress={() => saveLanguage()}
|
||||
appearance="ghost"
|
||||
status="primary"
|
||||
disabled={currentLanguage === selectedLanguage}
|
||||
style={styles.button}
|
||||
size="medium"
|
||||
>
|
||||
{translate('language.changeLanguageButton')}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
const themedStyles = StyleService.create({
|
||||
languageList: {
|
||||
flex: 1,
|
||||
alignSelf: 'stretch',
|
||||
flexDirection: 'column',
|
||||
marginTop: 40,
|
||||
marginTop: 8,
|
||||
},
|
||||
icon: {
|
||||
width: 30,
|
||||
height: 30,
|
||||
},
|
||||
check: {
|
||||
position: 'absolute',
|
||||
left: -20,
|
||||
color: 'green',
|
||||
},
|
||||
container: {
|
||||
...LayoutStyle.mainAxis.center,
|
||||
...LayoutStyle.crossAxis.flexEnd,
|
||||
padding: Sizing.t5,
|
||||
},
|
||||
content: {
|
||||
|
@ -141,8 +134,15 @@ const styles = StyleSheet.create({
|
|||
languageButton: {
|
||||
minHeight: 45,
|
||||
marginBottom: 10,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
},
|
||||
languageButtonTitle: {
|
||||
...fontSize.lg,
|
||||
},
|
||||
languageButtonSubtitle: {
|
||||
...fontSize.sm,
|
||||
opacity: 0.4,
|
||||
},
|
||||
button: { ...LayoutStyle.flex.full },
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import { Text, useTheme } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { fontSize } from '../styles/typography'
|
||||
import { initials } from '../utils/peopleHelpers'
|
||||
|
||||
export type StudentAvatarProps = {
|
||||
name?: string
|
||||
color: string
|
||||
}
|
||||
|
||||
export const StudentAvatar = ({ name, color }: StudentAvatarProps) => {
|
||||
const colors = useTheme()
|
||||
const bgColor = colors[`color-${color}-100`]
|
||||
const textColor = colors[`color-${color}-900`]
|
||||
|
||||
return (
|
||||
<View style={{ ...styles.container, backgroundColor: bgColor }}>
|
||||
<Text style={{ ...styles.text, color: textColor }}>{initials(name)}</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
height: 44,
|
||||
width: 44,
|
||||
borderRadius: 300,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
text: {
|
||||
...fontSize.lg,
|
||||
fontFamily: 'Poppins-Medium',
|
||||
fontWeight: '500',
|
||||
},
|
||||
})
|
|
@ -1,22 +1,22 @@
|
|||
import { useMenu, useTimetable } from '@skolplattformen/api-hooks'
|
||||
import { Child, MenuItem, TimetableEntry } from '@skolplattformen/embedded-api'
|
||||
import {
|
||||
List,
|
||||
ListItem,
|
||||
ViewPager,
|
||||
Text,
|
||||
TabBar,
|
||||
Tab,
|
||||
StyleService,
|
||||
Tab,
|
||||
TabBar,
|
||||
Text,
|
||||
useStyleSheet,
|
||||
ViewPager,
|
||||
} from '@ui-kitten/components'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import moment from 'moment'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { useMenu, useTimetable } from '@skolplattformen/api-hooks'
|
||||
import { TimetableEntry, Child, MenuItem } from '@skolplattformen/embedded-api'
|
||||
import { LanguageService } from '../services/languageService'
|
||||
import { Sizing, Typography } from '../styles'
|
||||
import { translate } from '../utils/translation'
|
||||
import { TransitionView } from './transitionView.component'
|
||||
import { Typography, Sizing } from '../styles'
|
||||
|
||||
interface WeekProps {
|
||||
child: Child
|
||||
|
@ -174,7 +174,7 @@ export const Week = ({ child }: WeekProps) => {
|
|||
|
||||
const themedStyles = StyleService.create({
|
||||
view: {
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
},
|
||||
part: {
|
||||
backgroundColor: 'transparent',
|
||||
|
@ -186,7 +186,7 @@ const themedStyles = StyleService.create({
|
|||
},
|
||||
item: {
|
||||
height: 45,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
paddingHorizontal: 0,
|
||||
borderRadius: 2,
|
||||
margin: 2,
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
{
|
||||
"color-primary-100": "#FDD3D4",
|
||||
"color-primary-200": "#FBA7B3",
|
||||
"color-primary-300": "#F47A97",
|
||||
"color-primary-400": "#E95789",
|
||||
"color-primary-500": "#DB2575",
|
||||
"color-primary-600": "#BC1B72",
|
||||
"color-primary-700": "#9D126B",
|
||||
"color-primary-800": "#7F0B60",
|
||||
"color-primary-900": "#690759",
|
||||
"color-primary-50": "#FFECF9",
|
||||
"color-primary-100": "#FEC9EF",
|
||||
"color-primary-200": "#FD82DA",
|
||||
"color-primary-300": "#FB3CC6",
|
||||
"color-primary-400": "#EC04AB",
|
||||
"color-primary-500": "#A60378",
|
||||
"color-primary-600": "#880262",
|
||||
"color-primary-700": "#6A024D",
|
||||
"color-primary-800": "#4C0137",
|
||||
"color-primary-900": "#2E0121",
|
||||
"color-primary-transparent-100": "rgba(219, 37, 117, 0.08)",
|
||||
"color-primary-transparent-200": "rgba(219, 37, 117, 0.16)",
|
||||
"color-primary-transparent-300": "rgba(219, 37, 117, 0.24)",
|
||||
|
@ -44,15 +45,6 @@
|
|||
"color-info-transparent-400": "rgba(24, 75, 186, 0.32)",
|
||||
"color-info-transparent-500": "rgba(24, 75, 186, 0.4)",
|
||||
"color-info-transparent-600": "rgba(24, 75, 186, 0.48)",
|
||||
"color-warning-100": "#FCF1CA",
|
||||
"color-warning-200": "#F9E097",
|
||||
"color-warning-300": "#EFC662",
|
||||
"color-warning-400": "#E0A93B",
|
||||
"color-warning-500": "#CC8204",
|
||||
"color-warning-600": "#AF6902",
|
||||
"color-warning-700": "#925202",
|
||||
"color-warning-800": "#763D01",
|
||||
"color-warning-900": "#612F00",
|
||||
"color-warning-transparent-100": "rgba(204, 130, 4, 0.08)",
|
||||
"color-warning-transparent-200": "rgba(204, 130, 4, 0.16)",
|
||||
"color-warning-transparent-300": "rgba(204, 130, 4, 0.24)",
|
||||
|
@ -74,14 +66,12 @@
|
|||
"color-danger-transparent-400": "rgba(186, 50, 127, 0.32)",
|
||||
"color-danger-transparent-500": "rgba(186, 50, 127, 0.4)",
|
||||
"color-danger-transparent-600": "rgba(186, 50, 127, 0.48)",
|
||||
"background-basic-color-1": "#2E3137",
|
||||
"background-basic-color-2": "#202225",
|
||||
"background-basic-color-1": "#150A12",
|
||||
"background-basic-color-2": "#030200",
|
||||
"color-control-default": "#E5E7EB",
|
||||
/* text colors */
|
||||
"color-basic-800": "#DCDDDE",
|
||||
"color-basic-600": "#DCDDDE",
|
||||
"color-basic-500": "#8E9297",
|
||||
/* basic button colors */
|
||||
"color-basic-300": "#202020",
|
||||
"color-basic-400": "gray"
|
||||
"color-basic-default": "$color-primary-800",
|
||||
"color-basic-focus": "$color-primary-700",
|
||||
"color-basic-hover": "$color-primary-700",
|
||||
"color-basic-active": "$color-primary-700",
|
||||
"color-basic-text": "$color-primary-100"
|
||||
}
|
||||
|
|
|
@ -1,81 +1,86 @@
|
|||
{
|
||||
"color-primary-100": "#FDD3D4",
|
||||
"color-primary-200": "#FBA7B3",
|
||||
"color-primary-300": "#F47A97",
|
||||
"color-primary-400": "#E95789",
|
||||
"color-primary-500": "#DB2575",
|
||||
"color-primary-600": "#BC1B72",
|
||||
"color-primary-700": "#9D126B",
|
||||
"color-primary-800": "#7F0B60",
|
||||
"color-primary-900": "#690759",
|
||||
"color-primary-50": "#FFECF9",
|
||||
"color-primary-100": "#FEC9EF",
|
||||
"color-primary-200": "#FD82DA",
|
||||
"color-primary-300": "#FB3CC6",
|
||||
"color-primary-400": "#EC04AB",
|
||||
"color-primary-500": "#A60378",
|
||||
"color-primary-600": "#880262",
|
||||
"color-primary-700": "#6A024D",
|
||||
"color-primary-800": "#4C0137",
|
||||
"color-primary-900": "#2E0121",
|
||||
"color-primary-transparent-100": "rgba(219, 37, 117, 0.08)",
|
||||
"color-primary-transparent-200": "rgba(219, 37, 117, 0.16)",
|
||||
"color-primary-transparent-300": "rgba(219, 37, 117, 0.24)",
|
||||
"color-primary-transparent-400": "rgba(219, 37, 117, 0.32)",
|
||||
"color-primary-transparent-500": "rgba(219, 37, 117, 0.4)",
|
||||
"color-primary-transparent-600": "rgba(219, 37, 117, 0.48)",
|
||||
"color-success-100": "#DEF8D1",
|
||||
"color-success-200": "#B8F2A6",
|
||||
"color-success-300": "#82D973",
|
||||
"color-success-400": "#50B44A",
|
||||
"color-success-500": "#1C821F",
|
||||
"color-success-600": "#146F1F",
|
||||
"color-success-700": "#0E5D1E",
|
||||
"color-success-800": "#084B1C",
|
||||
"color-success-900": "#053E1B",
|
||||
"color-success-transparent-100": "rgba(28, 130, 31, 0.08)",
|
||||
"color-success-transparent-200": "rgba(28, 130, 31, 0.16)",
|
||||
"color-success-transparent-300": "rgba(28, 130, 31, 0.24)",
|
||||
"color-success-transparent-400": "rgba(28, 130, 31, 0.32)",
|
||||
"color-success-transparent-500": "rgba(28, 130, 31, 0.4)",
|
||||
"color-success-transparent-600": "rgba(28, 130, 31, 0.48)",
|
||||
"color-info-100": "#CFE3FB",
|
||||
"color-info-200": "#A1C5F8",
|
||||
"color-info-300": "#6F9EEA",
|
||||
"color-info-400": "#4A7AD5",
|
||||
"color-info-500": "#184BBA",
|
||||
"color-info-600": "#11399F",
|
||||
"color-info-700": "#0C2A85",
|
||||
"color-info-800": "#071D6B",
|
||||
"color-info-900": "#041459",
|
||||
"color-info-transparent-100": "rgba(24, 75, 186, 0.08)",
|
||||
"color-info-transparent-200": "rgba(24, 75, 186, 0.16)",
|
||||
"color-info-transparent-300": "rgba(24, 75, 186, 0.24)",
|
||||
"color-info-transparent-400": "rgba(24, 75, 186, 0.32)",
|
||||
"color-info-transparent-500": "rgba(24, 75, 186, 0.4)",
|
||||
"color-info-transparent-600": "rgba(24, 75, 186, 0.48)",
|
||||
"color-warning-100": "#FCEDC9",
|
||||
"color-warning-200": "#F9D696",
|
||||
"color-warning-300": "#EDB55F",
|
||||
"color-warning-400": "#DC9338",
|
||||
"color-warning-500": "#C66401",
|
||||
"color-warning-600": "#AA4D00",
|
||||
"color-warning-700": "#8E3900",
|
||||
"color-warning-800": "#722800",
|
||||
"color-warning-900": "#5F1C00",
|
||||
"color-warning-transparent-100": "rgba(198, 100, 1, 0.08)",
|
||||
"color-warning-transparent-200": "rgba(198, 100, 1, 0.16)",
|
||||
"color-warning-transparent-300": "rgba(198, 100, 1, 0.24)",
|
||||
"color-warning-transparent-400": "rgba(198, 100, 1, 0.32)",
|
||||
"color-warning-transparent-500": "rgba(198, 100, 1, 0.4)",
|
||||
"color-warning-transparent-600": "rgba(198, 100, 1, 0.48)",
|
||||
"color-danger-100": "#F9D6D0",
|
||||
"color-danger-200": "#F4A7A3",
|
||||
"color-danger-300": "#DE6F73",
|
||||
"color-danger-400": "#BE4757",
|
||||
"color-danger-500": "#931935",
|
||||
"color-danger-600": "#7E1235",
|
||||
"color-danger-700": "#690C33",
|
||||
"color-danger-800": "#55072F",
|
||||
"color-danger-900": "#46042D",
|
||||
"color-danger-transparent-100": "rgba(147, 25, 53, 0.08)",
|
||||
"color-danger-transparent-200": "rgba(147, 25, 53, 0.16)",
|
||||
"color-danger-transparent-300": "rgba(147, 25, 53, 0.24)",
|
||||
"color-danger-transparent-400": "rgba(147, 25, 53, 0.32)",
|
||||
"color-danger-transparent-500": "rgba(147, 25, 53, 0.4)",
|
||||
"color-danger-transparent-600": "rgba(147, 25, 53, 0.48)",
|
||||
"color-basic-800": "#1F2937",
|
||||
"color-basic-600": "#4B5563",
|
||||
"color-basic-500": "#6B7280",
|
||||
"color-basic-400": "#E4E9F2"
|
||||
"color-success-100": "#EEFACF",
|
||||
"color-success-200": "#DAF6A1",
|
||||
"color-success-300": "#B8E36F",
|
||||
"color-success-400": "#93C948",
|
||||
"color-success-500": "#64A518",
|
||||
"color-success-600": "#4E8D11",
|
||||
"color-success-700": "#3B760C",
|
||||
"color-success-800": "#2A5F07",
|
||||
"color-success-900": "#1E4F04",
|
||||
"color-success-transparent-100": "rgba(100, 165, 24, 0.08)",
|
||||
"color-success-transparent-200": "rgba(100, 165, 24, 0.16)",
|
||||
"color-success-transparent-300": "rgba(100, 165, 24, 0.24)",
|
||||
"color-success-transparent-400": "rgba(100, 165, 24, 0.32)",
|
||||
"color-success-transparent-500": "rgba(100, 165, 24, 0.4)",
|
||||
"color-success-transparent-600": "rgba(100, 165, 24, 0.48)",
|
||||
"color-info-100": "#C6EEF8",
|
||||
"color-info-200": "#90D9F1",
|
||||
"color-info-300": "#55AED5",
|
||||
"color-info-400": "#2B7DAC",
|
||||
"color-info-500": "#004475",
|
||||
"color-info-600": "#003464",
|
||||
"color-info-700": "#002754",
|
||||
"color-info-800": "#001B43",
|
||||
"color-info-900": "#001338",
|
||||
"color-info-transparent-100": "rgba(0, 68, 117, 0.08)",
|
||||
"color-info-transparent-200": "rgba(0, 68, 117, 0.16)",
|
||||
"color-info-transparent-300": "rgba(0, 68, 117, 0.24)",
|
||||
"color-info-transparent-400": "rgba(0, 68, 117, 0.32)",
|
||||
"color-info-transparent-500": "rgba(0, 68, 117, 0.4)",
|
||||
"color-info-transparent-600": "rgba(0, 68, 117, 0.48)",
|
||||
"color-warning-100": "#FCF1CA",
|
||||
"color-warning-200": "#F9E097",
|
||||
"color-warning-300": "#EFC662",
|
||||
"color-warning-400": "#E0A93B",
|
||||
"color-warning-500": "#CC8204",
|
||||
"color-warning-600": "#AF6902",
|
||||
"color-warning-700": "#925202",
|
||||
"color-warning-800": "#763D01",
|
||||
"color-warning-900": "#612F00",
|
||||
"color-warning-transparent-100": "rgba(204, 130, 4, 0.08)",
|
||||
"color-warning-transparent-200": "rgba(204, 130, 4, 0.16)",
|
||||
"color-warning-transparent-300": "rgba(204, 130, 4, 0.24)",
|
||||
"color-warning-transparent-400": "rgba(204, 130, 4, 0.32)",
|
||||
"color-warning-transparent-500": "rgba(204, 130, 4, 0.4)",
|
||||
"color-warning-transparent-600": "rgba(204, 130, 4, 0.48)",
|
||||
"color-danger-100": "#FBD6DC",
|
||||
"color-danger-200": "#F8AFC2",
|
||||
"color-danger-300": "#EA83A9",
|
||||
"color-danger-400": "#D56097",
|
||||
"color-danger-500": "#BA327F",
|
||||
"color-danger-600": "#9F2476",
|
||||
"color-danger-700": "#85196C",
|
||||
"color-danger-800": "#6B0F5F",
|
||||
"color-danger-900": "#590956",
|
||||
"color-danger-transparent-100": "rgba(186, 50, 127, 0.08)",
|
||||
"color-danger-transparent-200": "rgba(186, 50, 127, 0.16)",
|
||||
"color-danger-transparent-300": "rgba(186, 50, 127, 0.24)",
|
||||
"color-danger-transparent-400": "rgba(186, 50, 127, 0.32)",
|
||||
"color-danger-transparent-500": "rgba(186, 50, 127, 0.4)",
|
||||
"color-danger-transparent-600": "rgba(186, 50, 127, 0.48)",
|
||||
"background-basic-color-1": "#fff",
|
||||
"background-basic-color-2": "$color-basic-200",
|
||||
"text-hint-color": "#4B5466",
|
||||
"color-basic-default": "$color-primary-50",
|
||||
"color-basic-focus": "$color-primary-100",
|
||||
"color-basic-hover": "$color-primary-100",
|
||||
"color-basic-active": "$color-primary-100",
|
||||
"color-basic-text": "$color-primary-800"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"strict": {
|
||||
"text-font-family": "Poppins"
|
||||
"text-font-family": "Poppins",
|
||||
"border-radius": 10
|
||||
},
|
||||
"components": {
|
||||
"Button": {
|
||||
|
@ -10,12 +11,13 @@
|
|||
"mapping": {},
|
||||
"variantGroups": {
|
||||
"status": {
|
||||
"primary": {
|
||||
"basic": {
|
||||
"textColor": "$color-basic-text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import { DarkTheme, DefaultTheme, Theme } from '@react-navigation/native'
|
||||
import { NativeStackNavigationOptions } from 'react-native-screens/native-stack'
|
||||
import { darkTheme, lightTheme } from './themes'
|
||||
|
||||
export const darkNavigationTheme: Theme = {
|
||||
...DarkTheme,
|
||||
colors: {
|
||||
...DarkTheme.colors,
|
||||
background: darkTheme['background-basic-color-2'],
|
||||
border: darkTheme['background-basic-color-1'],
|
||||
card: darkTheme['background-basic-color-1'],
|
||||
primary: darkTheme['color-primary-400'],
|
||||
text: '#ddd',
|
||||
},
|
||||
}
|
||||
|
||||
export const lightNavigationTheme: Theme = {
|
||||
...DefaultTheme,
|
||||
colors: {
|
||||
...DefaultTheme.colors,
|
||||
background: lightTheme['background-basic-color-2'],
|
||||
border: lightTheme['background-basic-color-1'],
|
||||
card: lightTheme['background-basic-color-1'],
|
||||
primary: lightTheme['color-primary-500'],
|
||||
},
|
||||
}
|
||||
|
||||
export const defaultStackStyling: NativeStackNavigationOptions = {
|
||||
headerTitleStyle: {
|
||||
fontFamily: 'Poppins-Medium',
|
||||
},
|
||||
headerBackTitleStyle: {
|
||||
fontFamily: 'Poppins-Regular',
|
||||
},
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import * as eva from '@eva-design/eva'
|
||||
import darkJsonTheme from './dark.json'
|
||||
import lightJsonTheme from './light.json'
|
||||
|
||||
export const darkTheme = {
|
||||
...eva.dark,
|
||||
...darkJsonTheme,
|
||||
}
|
||||
export const lightTheme = {
|
||||
...eva.light,
|
||||
...lightJsonTheme,
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
/**
|
||||
* @format
|
||||
*/
|
||||
|
||||
import 'react-native-gesture-handler'
|
||||
import { AppRegistry } from 'react-native'
|
||||
import App from './App'
|
||||
import { name as appName } from './app.json'
|
||||
|
||||
|
||||
AppRegistry.registerComponent(appName, () => App)
|
||||
|
|
|
@ -351,7 +351,7 @@ PODS:
|
|||
- React
|
||||
- RNCAsyncStorage (1.15.2):
|
||||
- React-Core
|
||||
- RNCMaskedView (0.1.10):
|
||||
- RNCMaskedView (0.1.11):
|
||||
- React
|
||||
- RNDateTimePicker (3.4.3):
|
||||
- React-Core
|
||||
|
@ -359,8 +359,38 @@ PODS:
|
|||
- React-Core
|
||||
- RNLocalize (2.0.3):
|
||||
- React-Core
|
||||
- RNScreens (2.18.1):
|
||||
- RNReanimated (2.2.0):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
- glog
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React
|
||||
- React-callinvoker
|
||||
- React-Core
|
||||
- React-Core/DevSupport
|
||||
- React-Core/RCTWebSocket
|
||||
- React-CoreModules
|
||||
- React-cxxreact
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- React-jsinspector
|
||||
- React-RCTActionSheet
|
||||
- React-RCTAnimation
|
||||
- React-RCTBlob
|
||||
- React-RCTImage
|
||||
- React-RCTLinking
|
||||
- React-RCTNetwork
|
||||
- React-RCTSettings
|
||||
- React-RCTText
|
||||
- React-RCTVibration
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNScreens (3.3.0):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- RNSVG (12.1.0):
|
||||
- React
|
||||
- Toast (4.0.0)
|
||||
|
@ -433,6 +463,7 @@ DEPENDENCIES:
|
|||
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNLocalize (from `../node_modules/react-native-localize`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||
- RNScreens (from `../node_modules/react-native-screens`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
@ -535,6 +566,8 @@ EXTERNAL SOURCES:
|
|||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNLocalize:
|
||||
:path: "../node_modules/react-native-localize"
|
||||
RNReanimated:
|
||||
:path: "../node_modules/react-native-reanimated"
|
||||
RNScreens:
|
||||
:path: "../node_modules/react-native-screens"
|
||||
RNSVG:
|
||||
|
@ -547,7 +580,7 @@ SPEC CHECKSUMS:
|
|||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
|
||||
FBLazyVector: 7b423f9e248eae65987838148c36eec1dbfe0b53
|
||||
FBReactNativeSpec: 313b66e17294041415f72c26996e9670a9f07a59
|
||||
FBReactNativeSpec: f792ea65d58b0e9219f7d4b52d887ee1141647ff
|
||||
Flipper: d3da1aa199aad94455ae725e9f3aa43f3ec17021
|
||||
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
|
||||
Flipper-Folly: 755929a4f851b2fb2c347d533a23f191b008554c
|
||||
|
@ -591,11 +624,12 @@ SPEC CHECKSUMS:
|
|||
ReactCommon: bedc99ed4dae329c4fcf128d0c31b9115e5365ca
|
||||
RNCalendarEvents: 7e65eb4a94f53c1744d1e275f7fafcfaa619f7a3
|
||||
RNCAsyncStorage: 9b7605e899f9acb2fba33e87952c529731265453
|
||||
RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
|
||||
RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489
|
||||
RNDateTimePicker: d943800c936fb01c352fcfb70439550d2cb57092
|
||||
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
|
||||
RNLocalize: 99e59cad311ca1b6872b1764514009416ccba03d
|
||||
RNScreens: f7ad633b2e0190b77b6a7aab7f914fad6f198d8d
|
||||
RNReanimated: 9c13c86454bfd54dab7505c1a054470bfecd2563
|
||||
RNScreens: bf59f17fbf001f1025243eeed5f19419d3c11ef2
|
||||
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
|
||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||
Yoga: a7de31c64fe738607e7a3803e3f591a4b1df7393
|
||||
|
|
|
@ -8,36 +8,36 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
00E356F31AD99517003FC87E /* appTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* appTests.m */; };
|
||||
04B5A89762F9430A902416B4 /* Poppins-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3CBFE8DBE8994C1FAF939519 /* Poppins-MediumItalic.ttf */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
230E5925A9044F679B2F7C39 /* Poppins-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7AF5677EA52D44EE97668E7A /* Poppins-Medium.ttf */; };
|
||||
2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
2DC4DBF14540481ABF14857A /* Poppins-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9A9C27037F0F4AF2A4CBAE78 /* Poppins-ExtraBold.ttf */; };
|
||||
2DCD954D1E0B4F2C00145EB5 /* appTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* appTests.m */; };
|
||||
417D579C3DC24A9684D24EDD /* Poppins-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 00FDE4C2522044DAAD866D5F /* Poppins-BlackItalic.ttf */; };
|
||||
41DE97CF96674977BC052462 /* Poppins-SemiBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A9CB7679337840D3BD256A13 /* Poppins-SemiBoldItalic.ttf */; };
|
||||
4E01D1C8DD5749C8953D3BE5 /* Poppins-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 661AE05493ED4FE780C32EF6 /* Poppins-Bold.ttf */; };
|
||||
4F931CB3182F40F580F357FF /* Poppins-ThinItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E251C7BB03F74441B4357419 /* Poppins-ThinItalic.ttf */; };
|
||||
50AAEBD19BD24B129801C393 /* Poppins-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 977D264ECA05485EA89A2F13 /* Poppins-Italic.ttf */; };
|
||||
5257E7B8420740A2862BEEB0 /* Poppins-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8E2BDC4163F1467E94E5D34C /* Poppins-BoldItalic.ttf */; };
|
||||
6D069850985349ABB76BDD0A /* Poppins-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B1A304CF782943E19F93DFD6 /* Poppins-Black.ttf */; };
|
||||
71436C48CDF348BE904103E9 /* Poppins-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 231B760691854EBCA7ECD80E /* Poppins-Light.ttf */; };
|
||||
7B94D8768C6340958F2EEFFD /* Poppins-ExtraLight.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C9AC377D6B7744ECBBEA0A8A /* Poppins-ExtraLight.ttf */; };
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||
836E1F3164D8497F8C51847A /* Poppins-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7CEBAD12E8E5471AA962262A /* Poppins-LightItalic.ttf */; };
|
||||
8F8E6DB2A0AB4DF3A5ED51E7 /* Poppins-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 920F53F06E0B433DB798AC45 /* Poppins-SemiBold.ttf */; };
|
||||
9FA2A398A0264369AD50123F /* Poppins-ExtraBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9F1539AF1544412D9662D264 /* Poppins-ExtraBoldItalic.ttf */; };
|
||||
9FC2C87C76F74B609BA3709E /* Poppins-ExtraLightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9420B3EA5C884AFFADCAFB4C /* Poppins-ExtraLightItalic.ttf */; };
|
||||
9FDEB3BC9BEB0D9B20C40FFA /* libPods-app-appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 198E5E1047B7B7C1FE9480E3 /* libPods-app-appTests.a */; };
|
||||
A74B9EB17CB0D9069DBDEC11 /* libPods-app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A849643D470B360BB9710A2 /* libPods-app.a */; };
|
||||
B9CA13426DF0582117265C94 /* libPods-app-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 209E1A9D464732CA3D5436BA /* libPods-app-tvOS.a */; };
|
||||
F8EEF49F61D796445B439296 /* libPods-app-tvOSTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD654FF33034F72E23F45E0 /* libPods-app-tvOSTests.a */; };
|
||||
6D069850985349ABB76BDD0A /* Poppins-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B1A304CF782943E19F93DFD6 /* Poppins-Black.ttf */; };
|
||||
417D579C3DC24A9684D24EDD /* Poppins-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 00FDE4C2522044DAAD866D5F /* Poppins-BlackItalic.ttf */; };
|
||||
4E01D1C8DD5749C8953D3BE5 /* Poppins-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 661AE05493ED4FE780C32EF6 /* Poppins-Bold.ttf */; };
|
||||
5257E7B8420740A2862BEEB0 /* Poppins-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8E2BDC4163F1467E94E5D34C /* Poppins-BoldItalic.ttf */; };
|
||||
2DC4DBF14540481ABF14857A /* Poppins-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9A9C27037F0F4AF2A4CBAE78 /* Poppins-ExtraBold.ttf */; };
|
||||
9FA2A398A0264369AD50123F /* Poppins-ExtraBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9F1539AF1544412D9662D264 /* Poppins-ExtraBoldItalic.ttf */; };
|
||||
7B94D8768C6340958F2EEFFD /* Poppins-ExtraLight.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C9AC377D6B7744ECBBEA0A8A /* Poppins-ExtraLight.ttf */; };
|
||||
9FC2C87C76F74B609BA3709E /* Poppins-ExtraLightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9420B3EA5C884AFFADCAFB4C /* Poppins-ExtraLightItalic.ttf */; };
|
||||
50AAEBD19BD24B129801C393 /* Poppins-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 977D264ECA05485EA89A2F13 /* Poppins-Italic.ttf */; };
|
||||
71436C48CDF348BE904103E9 /* Poppins-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 231B760691854EBCA7ECD80E /* Poppins-Light.ttf */; };
|
||||
836E1F3164D8497F8C51847A /* Poppins-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7CEBAD12E8E5471AA962262A /* Poppins-LightItalic.ttf */; };
|
||||
230E5925A9044F679B2F7C39 /* Poppins-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7AF5677EA52D44EE97668E7A /* Poppins-Medium.ttf */; };
|
||||
04B5A89762F9430A902416B4 /* Poppins-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3CBFE8DBE8994C1FAF939519 /* Poppins-MediumItalic.ttf */; };
|
||||
BB34E03413EB4CDFA59766B1 /* Poppins-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EB6EB5293E4C48098CBD53C2 /* Poppins-Regular.ttf */; };
|
||||
8F8E6DB2A0AB4DF3A5ED51E7 /* Poppins-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 920F53F06E0B433DB798AC45 /* Poppins-SemiBold.ttf */; };
|
||||
41DE97CF96674977BC052462 /* Poppins-SemiBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A9CB7679337840D3BD256A13 /* Poppins-SemiBoldItalic.ttf */; };
|
||||
AC5E863985C04D72B5806B58 /* Poppins-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 02B78F6C72354B2D8171239D /* Poppins-Thin.ttf */; };
|
||||
4F931CB3182F40F580F357FF /* Poppins-ThinItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E251C7BB03F74441B4357419 /* Poppins-ThinItalic.ttf */; };
|
||||
B9CA13426DF0582117265C94 /* libPods-app-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 209E1A9D464732CA3D5436BA /* libPods-app-tvOS.a */; };
|
||||
BB34E03413EB4CDFA59766B1 /* Poppins-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EB6EB5293E4C48098CBD53C2 /* Poppins-Regular.ttf */; };
|
||||
F8EEF49F61D796445B439296 /* libPods-app-tvOSTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD654FF33034F72E23F45E0 /* libPods-app-tvOSTests.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -62,6 +62,8 @@
|
|||
00E356EE1AD99517003FC87E /* appTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = appTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
00E356F21AD99517003FC87E /* appTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = appTests.m; sourceTree = "<group>"; };
|
||||
00FDE4C2522044DAAD866D5F /* Poppins-BlackItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-BlackItalic.ttf"; path = "../assets/fonts/Poppins-BlackItalic.ttf"; sourceTree = "<group>"; };
|
||||
02B78F6C72354B2D8171239D /* Poppins-Thin.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-Thin.ttf"; path = "../assets/fonts/Poppins-Thin.ttf"; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = app.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = app/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = app/AppDelegate.m; sourceTree = "<group>"; };
|
||||
|
@ -71,38 +73,36 @@
|
|||
198E5E1047B7B7C1FE9480E3 /* libPods-app-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1A849643D470B360BB9710A2 /* libPods-app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
209E1A9D464732CA3D5436BA /* libPods-app-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
231B760691854EBCA7ECD80E /* Poppins-Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-Light.ttf"; path = "../assets/fonts/Poppins-Light.ttf"; sourceTree = "<group>"; };
|
||||
2D02E47B1E0B4A5D006451C7 /* app-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "app-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2D02E4901E0B4A5D006451C7 /* app-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "app-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3CBFE8DBE8994C1FAF939519 /* Poppins-MediumItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-MediumItalic.ttf"; path = "../assets/fonts/Poppins-MediumItalic.ttf"; sourceTree = "<group>"; };
|
||||
4F9213F90B49965FDCF003FA /* Pods-app-appTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.release.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
55AC07BDE5542A03F6AD2FE2 /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = "<group>"; };
|
||||
64A4BC0C882E097B17B89CAB /* Pods-app-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-tvOSTests.debug.xcconfig"; path = "Target Support Files/Pods-app-tvOSTests/Pods-app-tvOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
661AE05493ED4FE780C32EF6 /* Poppins-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-Bold.ttf"; path = "../assets/fonts/Poppins-Bold.ttf"; sourceTree = "<group>"; };
|
||||
78E0CED54136BD6995951328 /* Pods-app-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-tvOS.release.xcconfig"; path = "Target Support Files/Pods-app-tvOS/Pods-app-tvOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
7AF5677EA52D44EE97668E7A /* Poppins-Medium.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-Medium.ttf"; path = "../assets/fonts/Poppins-Medium.ttf"; sourceTree = "<group>"; };
|
||||
7CEBAD12E8E5471AA962262A /* Poppins-LightItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-LightItalic.ttf"; path = "../assets/fonts/Poppins-LightItalic.ttf"; sourceTree = "<group>"; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = app/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
866817BF8B562CD61F42398B /* Pods-app-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-app-tvOSTests/Pods-app-tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
8E2BDC4163F1467E94E5D34C /* Poppins-BoldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-BoldItalic.ttf"; path = "../assets/fonts/Poppins-BoldItalic.ttf"; sourceTree = "<group>"; };
|
||||
920F53F06E0B433DB798AC45 /* Poppins-SemiBold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-SemiBold.ttf"; path = "../assets/fonts/Poppins-SemiBold.ttf"; sourceTree = "<group>"; };
|
||||
9420B3EA5C884AFFADCAFB4C /* Poppins-ExtraLightItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-ExtraLightItalic.ttf"; path = "../assets/fonts/Poppins-ExtraLightItalic.ttf"; sourceTree = "<group>"; };
|
||||
977D264ECA05485EA89A2F13 /* Poppins-Italic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-Italic.ttf"; path = "../assets/fonts/Poppins-Italic.ttf"; sourceTree = "<group>"; };
|
||||
9A9C27037F0F4AF2A4CBAE78 /* Poppins-ExtraBold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-ExtraBold.ttf"; path = "../assets/fonts/Poppins-ExtraBold.ttf"; sourceTree = "<group>"; };
|
||||
9F1539AF1544412D9662D264 /* Poppins-ExtraBoldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-ExtraBoldItalic.ttf"; path = "../assets/fonts/Poppins-ExtraBoldItalic.ttf"; sourceTree = "<group>"; };
|
||||
A9CB7679337840D3BD256A13 /* Poppins-SemiBoldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-SemiBoldItalic.ttf"; path = "../assets/fonts/Poppins-SemiBoldItalic.ttf"; sourceTree = "<group>"; };
|
||||
AB8B9EC2CC8BC79836F11661 /* Pods-app-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-app-tvOS/Pods-app-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B1A304CF782943E19F93DFD6 /* Poppins-Black.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-Black.ttf"; path = "../assets/fonts/Poppins-Black.ttf"; sourceTree = "<group>"; };
|
||||
C9AC377D6B7744ECBBEA0A8A /* Poppins-ExtraLight.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-ExtraLight.ttf"; path = "../assets/fonts/Poppins-ExtraLight.ttf"; sourceTree = "<group>"; };
|
||||
D9ABD588946E114F0E0A649D /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
DAD654FF33034F72E23F45E0 /* libPods-app-tvOSTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-tvOSTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DE49AE0B25BD2EF3496BCE37 /* Pods-app-appTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.debug.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
E251C7BB03F74441B4357419 /* Poppins-ThinItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-ThinItalic.ttf"; path = "../assets/fonts/Poppins-ThinItalic.ttf"; sourceTree = "<group>"; };
|
||||
EB6EB5293E4C48098CBD53C2 /* Poppins-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Poppins-Regular.ttf"; path = "../assets/fonts/Poppins-Regular.ttf"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
|
||||
B1A304CF782943E19F93DFD6 /* Poppins-Black.ttf */ = {isa = PBXFileReference; name = "Poppins-Black.ttf"; path = "../assets/fonts/Poppins-Black.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
00FDE4C2522044DAAD866D5F /* Poppins-BlackItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-BlackItalic.ttf"; path = "../assets/fonts/Poppins-BlackItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
661AE05493ED4FE780C32EF6 /* Poppins-Bold.ttf */ = {isa = PBXFileReference; name = "Poppins-Bold.ttf"; path = "../assets/fonts/Poppins-Bold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
8E2BDC4163F1467E94E5D34C /* Poppins-BoldItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-BoldItalic.ttf"; path = "../assets/fonts/Poppins-BoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
9A9C27037F0F4AF2A4CBAE78 /* Poppins-ExtraBold.ttf */ = {isa = PBXFileReference; name = "Poppins-ExtraBold.ttf"; path = "../assets/fonts/Poppins-ExtraBold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
9F1539AF1544412D9662D264 /* Poppins-ExtraBoldItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-ExtraBoldItalic.ttf"; path = "../assets/fonts/Poppins-ExtraBoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
C9AC377D6B7744ECBBEA0A8A /* Poppins-ExtraLight.ttf */ = {isa = PBXFileReference; name = "Poppins-ExtraLight.ttf"; path = "../assets/fonts/Poppins-ExtraLight.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
9420B3EA5C884AFFADCAFB4C /* Poppins-ExtraLightItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-ExtraLightItalic.ttf"; path = "../assets/fonts/Poppins-ExtraLightItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
977D264ECA05485EA89A2F13 /* Poppins-Italic.ttf */ = {isa = PBXFileReference; name = "Poppins-Italic.ttf"; path = "../assets/fonts/Poppins-Italic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
231B760691854EBCA7ECD80E /* Poppins-Light.ttf */ = {isa = PBXFileReference; name = "Poppins-Light.ttf"; path = "../assets/fonts/Poppins-Light.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
7CEBAD12E8E5471AA962262A /* Poppins-LightItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-LightItalic.ttf"; path = "../assets/fonts/Poppins-LightItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
7AF5677EA52D44EE97668E7A /* Poppins-Medium.ttf */ = {isa = PBXFileReference; name = "Poppins-Medium.ttf"; path = "../assets/fonts/Poppins-Medium.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
3CBFE8DBE8994C1FAF939519 /* Poppins-MediumItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-MediumItalic.ttf"; path = "../assets/fonts/Poppins-MediumItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
EB6EB5293E4C48098CBD53C2 /* Poppins-Regular.ttf */ = {isa = PBXFileReference; name = "Poppins-Regular.ttf"; path = "../assets/fonts/Poppins-Regular.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
920F53F06E0B433DB798AC45 /* Poppins-SemiBold.ttf */ = {isa = PBXFileReference; name = "Poppins-SemiBold.ttf"; path = "../assets/fonts/Poppins-SemiBold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
A9CB7679337840D3BD256A13 /* Poppins-SemiBoldItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-SemiBoldItalic.ttf"; path = "../assets/fonts/Poppins-SemiBoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
02B78F6C72354B2D8171239D /* Poppins-Thin.ttf */ = {isa = PBXFileReference; name = "Poppins-Thin.ttf"; path = "../assets/fonts/Poppins-Thin.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
E251C7BB03F74441B4357419 /* Poppins-ThinItalic.ttf */ = {isa = PBXFileReference; name = "Poppins-ThinItalic.ttf"; path = "../assets/fonts/Poppins-ThinItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -235,7 +235,7 @@
|
|||
sourceTree = "<group>";
|
||||
};
|
||||
86DE8D5EB35F4504B427A63A /* Resources */ = {
|
||||
isa = "PBXGroup";
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1A304CF782943E19F93DFD6 /* Poppins-Black.ttf */,
|
||||
00FDE4C2522044DAAD866D5F /* Poppins-BlackItalic.ttf */,
|
||||
|
@ -257,8 +257,8 @@
|
|||
E251C7BB03F74441B4357419 /* Poppins-ThinItalic.ttf */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
path = "";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
|
@ -975,7 +975,7 @@
|
|||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
|
@ -1036,7 +1036,7 @@
|
|||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"@react-native-community/blur": "3.6.0",
|
||||
"@react-native-community/cookies": "5.0.1",
|
||||
"@react-native-community/datetimepicker": "3.4.3",
|
||||
"@react-native-community/masked-view": "0.1.10",
|
||||
"@react-native-community/masked-view": "^0.1.11",
|
||||
"@react-navigation/bottom-tabs": "5.11.9",
|
||||
"@react-navigation/native": "5.9.4",
|
||||
"@react-navigation/stack": "5.14.4",
|
||||
|
@ -47,13 +47,14 @@
|
|||
"react-native-appearance": "^0.3.4",
|
||||
"react-native-calendar-events": "2.2.0",
|
||||
"react-native-fix-image": "2.1.0",
|
||||
"react-native-gesture-handler": "1.10.3",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-localize": "^2.0.2",
|
||||
"react-native-markdown-display": "7.0.0-alpha.2",
|
||||
"react-native-modal-datetime-picker": "9.2.0",
|
||||
"react-native-reanimated": "^2.2.0",
|
||||
"react-native-restart": "^0.0.22",
|
||||
"react-native-safe-area-context": "3.2.0",
|
||||
"react-native-screens": "2.18.1",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.3.0",
|
||||
"react-native-simple-toast": "1.1.3",
|
||||
"react-native-svg": "12.1.0",
|
||||
"react-native-svg-transformer": "0.14.3",
|
||||
|
@ -70,8 +71,8 @@
|
|||
"@babel/runtime": "^7.13.10",
|
||||
"@react-native-community/eslint-config": "^2.0.0",
|
||||
"@testing-library/jest-native": "^4.0.1",
|
||||
"@testing-library/react-hooks": "^5.1.1",
|
||||
"@testing-library/react-native": "7.1.0",
|
||||
"@testing-library/react-hooks": "^7.0.0",
|
||||
"@testing-library/react-native": "7.2.0",
|
||||
"@types/i18n-js": "^3.8.0",
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/jsuri": "^1.3.30",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'react-native-gesture-handler/jestSetup'
|
||||
import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock'
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/sv'
|
||||
import 'react-native-gesture-handler/jestSetup'
|
||||
|
||||
moment.locale('sv')
|
||||
|
||||
|
@ -9,3 +9,13 @@ jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage)
|
|||
|
||||
// Silence useNativeDriver error
|
||||
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
|
||||
|
||||
jest.mock('react-native-reanimated', () => {
|
||||
const Reanimated = require('react-native-reanimated/mock')
|
||||
|
||||
// The mock for `call` immediately calls the callback which is incorrect
|
||||
// So we override it with a no-op
|
||||
Reanimated.default.call = () => {}
|
||||
|
||||
return Reanimated
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { SafeAreaView as RNSafeAreaView, ViewProps } from 'react-native'
|
||||
import { ViewProps } from 'react-native'
|
||||
import { SafeAreaView as RNSafeAreaView } from 'react-native-safe-area-context'
|
||||
import { Layout } from '../styles'
|
||||
|
||||
export const SafeAreaView: React.FC<ViewProps> = ({ children }) => {
|
||||
|
@ -12,6 +13,6 @@ export const SafeAreaView: React.FC<ViewProps> = ({ children }) => {
|
|||
const themedStyles = StyleService.create({
|
||||
safeArea: {
|
||||
...Layout.flex.full,
|
||||
backgroundColor: 'background-basic-color-1',
|
||||
backgroundColor: 'background-basic-color-2',
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
fullName,
|
||||
guardians,
|
||||
initials,
|
||||
sortByFirstName,
|
||||
studentName,
|
||||
} from '../peopleHelpers'
|
||||
|
@ -72,3 +73,13 @@ describe('#guardians', () => {
|
|||
).toEqual('Loras Eriksson, Margaery Eriksson')
|
||||
})
|
||||
})
|
||||
describe('#initials', () => {
|
||||
test('should extract initials from name', () => {
|
||||
expect(initials('Namn Namnsson')).toEqual('Na')
|
||||
expect(initials('Nisse Namnsson')).toEqual('Ni')
|
||||
})
|
||||
|
||||
test('handles undefined name', () => {
|
||||
expect(initials(undefined)).toBeUndefined()
|
||||
})
|
||||
})
|
|
@ -1,9 +0,0 @@
|
|||
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}`
|
|
@ -0,0 +1,16 @@
|
|||
import { Guardian } from '@skolplattformen/embedded-api'
|
||||
|
||||
export const studentName = (name?: string) => name?.replace(/\s?\(\w+\)$/, '')
|
||||
|
||||
export const sortByFirstName = (data: Guardian[]) =>
|
||||
data.sort((a, b) => a.firstname.localeCompare(b.firstname))
|
||||
|
||||
export const guardians = (data: Guardian[]) =>
|
||||
sortByFirstName(data).map(fullName).join(', ')
|
||||
|
||||
export const fullName = (person: Guardian) =>
|
||||
`${person.firstname} ${person.lastname}`
|
||||
|
||||
export const initials = (name?: string) => {
|
||||
return name?.slice(0, 2)
|
||||
}
|
|
@ -173,6 +173,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af"
|
||||
integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==
|
||||
|
||||
"@babel/helper-plugin-utils@^7.14.5":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9"
|
||||
integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==
|
||||
|
||||
"@babel/helper-remap-async-to-generator@^7.13.0":
|
||||
version "7.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz#376a760d9f7b4b2077a9dd05aa9c3927cadb2209"
|
||||
|
@ -546,6 +551,13 @@
|
|||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.12.13"
|
||||
|
||||
"@babel/plugin-transform-object-assign@^7.10.4":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.14.5.tgz#62537d54b6d85de04f4df48bfdba2eebff17b760"
|
||||
integrity sha512-lvhjk4UN9xJJYB1mI5KC0/o1D5EcJXdbhVe+4fSk08D6ZN+iuAIs7LJC+71h8av9Ew4+uRq9452v9R93SFmQlQ==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
|
||||
"@babel/plugin-transform-object-super@^7.0.0":
|
||||
version "7.12.13"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.13.tgz#b4416a2d63b8f7be314f3d349bd55a9c1b5171f7"
|
||||
|
@ -1360,10 +1372,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.1.0.tgz#e42b1bef12d2415411519fd528e64b593b1363dc"
|
||||
integrity sha512-W/J0fNYVO01tioHjvYWQ9m6RgndVtbElzYozBq1ZPrHO/iCzlqoySHl4gO/fpCl9QEFjvJfjPgtPMTMlsoq5DQ==
|
||||
|
||||
"@react-native-community/masked-view@0.1.10":
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/@react-native-community/masked-view/-/masked-view-0.1.10.tgz#5dda643e19e587793bc2034dd9bf7398ad43d401"
|
||||
integrity sha512-rk4sWFsmtOw8oyx8SD3KSvawwaK7gRBSEIy2TAwURyGt+3TizssXP1r8nx3zY+R7v2vYYHXZ+k2/GULAT/bcaQ==
|
||||
"@react-native-community/masked-view@^0.1.11":
|
||||
version "0.1.11"
|
||||
resolved "https://registry.yarnpkg.com/@react-native-community/masked-view/-/masked-view-0.1.11.tgz#2f4c6e10bee0786abff4604e39a37ded6f3980ce"
|
||||
integrity sha512-rQfMIGSR/1r/SyN87+VD8xHHzDYeHaJq6elOSCAD+0iLagXkSI2pfA0LmSXP21uw5i3em7GkkRjfJ8wpqWXZNw==
|
||||
|
||||
"@react-native/assets@1.0.0":
|
||||
version "1.0.0"
|
||||
|
@ -1583,22 +1595,21 @@
|
|||
ramda "^0.26.1"
|
||||
redent "^2.0.0"
|
||||
|
||||
"@testing-library/react-hooks@^5.1.1":
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-5.1.2.tgz#36e359d992bb652a9885c6fa9aa394639cbe8dd3"
|
||||
integrity sha512-jwhtDYZ5gQUIX8cmVCVdtwNvuF5EiCOWjokRlTV+o/V0GdtRZDykUllL1OXq5PS4+J33wGLNQeeWzEHcWrH7tg==
|
||||
"@testing-library/react-hooks@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-7.0.0.tgz#dd6d37a7e018f147a3b9153137f10e013be8472b"
|
||||
integrity sha512-WFBGH8DWdIGGBHt6PBtQPe2v4Kbj9vQ1sQ9qLBTmwn1PNggngint4MTE/IiWCYhPbyTW3oc/7X62DObMn/AjQQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@types/react" ">=16.9.0"
|
||||
"@types/react-dom" ">=16.9.0"
|
||||
"@types/react-test-renderer" ">=16.9.0"
|
||||
filter-console "^0.1.1"
|
||||
react-error-boundary "^3.1.0"
|
||||
|
||||
"@testing-library/react-native@7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-7.1.0.tgz#6b168aac21522c8a5175461b350336fd79612ac9"
|
||||
integrity sha512-ljVM9KZqG7BT/NFN6CHzdF6MNmM28+k7MEybFJ7FW1wVrhpiY4+hU9ypZ+hboO+MG3KpE2aFBzP4od3gu+Zzdg==
|
||||
"@testing-library/react-native@7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-7.2.0.tgz#e5ec5b0974e4e5f525f8057563417d1e9f820d96"
|
||||
integrity sha512-rDKzJjAAeGgyoJT0gFQiMsIL09chdWcwZyYx6WZHMgm2c5NDqY52hUuyTkzhqddMYWmSRklFphSg7B2HX+246Q==
|
||||
dependencies:
|
||||
pretty-format "^26.0.1"
|
||||
|
||||
|
@ -4007,11 +4018,6 @@ fill-range@^7.0.1:
|
|||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
filter-console@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/filter-console/-/filter-console-0.1.1.tgz#6242be28982bba7415bcc6db74a79f4a294fa67c"
|
||||
integrity sha512-zrXoV1Uaz52DqPs+qEwNJWJFAWZpYJ47UNmpN9q4j+/EYsz85uV0DC9k8tRND5kYmoVzL0W+Y75q4Rg8sRJCdg==
|
||||
|
||||
filter-obj@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
|
||||
|
@ -6671,7 +6677,7 @@ mkdirp@^0.5.1, mkdirp@~0.5.1:
|
|||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mockdate@^3.0.5:
|
||||
mockdate@^3.0.2, mockdate@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/mockdate/-/mockdate-3.0.5.tgz#789be686deb3149e7df2b663d2bc4392bc3284fb"
|
||||
integrity sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==
|
||||
|
@ -7594,7 +7600,7 @@ react-native-fix-image@2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/react-native-fix-image/-/react-native-fix-image-2.1.0.tgz#a4677b91529be926544775faf736df6af8c4743c"
|
||||
integrity sha512-qn4xItNSKfwlSkMHgxH9cusUQuk5Lhag9aHqL9ESxnCDUDwqS6rsWuOYt/JlncaKhsCc9cANFomCLlY8+Ffuaw==
|
||||
|
||||
react-native-gesture-handler@1.10.3:
|
||||
react-native-gesture-handler@^1.10.3:
|
||||
version "1.10.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.10.3.tgz#942bbf2963bbf49fa79593600ee9d7b5dab3cfc0"
|
||||
integrity sha512-cBGMi1IEsIVMgoox4RvMx7V2r6bNKw0uR1Mu1o7NbuHS6BRSVLq0dP34l2ecnPlC+jpWd3le6Yg1nrdCjby2Mw==
|
||||
|
@ -7632,20 +7638,30 @@ react-native-modal-datetime-picker@9.2.0:
|
|||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-native-reanimated@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.2.0.tgz#a6412c56b4e591d1f00fac949f62d0c72c357c78"
|
||||
integrity sha512-lOJDd+5w1gY6DHGXG2jD1dsjzQmXQ2699HUc3IztvI2WP4zUT+UAA+zSG+5JiBS5DUnTL8YhhkmUQmr1KNGO5w==
|
||||
dependencies:
|
||||
"@babel/plugin-transform-object-assign" "^7.10.4"
|
||||
fbjs "^3.0.0"
|
||||
mockdate "^3.0.2"
|
||||
string-hash-64 "^1.0.3"
|
||||
|
||||
react-native-restart@^0.0.22:
|
||||
version "0.0.22"
|
||||
resolved "https://registry.yarnpkg.com/react-native-restart/-/react-native-restart-0.0.22.tgz#81fcb7f31e35951d85410c68b9556acf3ab88705"
|
||||
integrity sha512-XwCqAMAKsO8yCM3xACPFKvkDQZe41lcavOuO0gUEu803IuTLtciualCq/qs83ryRDCDh1jkXYRqFjsGjLMCN3Q==
|
||||
|
||||
react-native-safe-area-context@3.2.0:
|
||||
react-native-safe-area-context@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-3.2.0.tgz#06113c6b208f982d68ab5c3cebd199ca93db6941"
|
||||
integrity sha512-k2Nty4PwSnrg9HwrYeeE+EYqViYJoOFwEy9LxL5RIRfoqxAq/uQXNGwpUg2/u4gnKpBbEPa9eRh15KKMe/VHkA==
|
||||
|
||||
react-native-screens@2.18.1:
|
||||
version "2.18.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-2.18.1.tgz#47b9991c6f762d00d0ed3233e5283d523e859885"
|
||||
integrity sha512-r5WZLpmx2hHjC1RgMdPq5YpSU9tEhBpUaZ5M1SUtNIONyiLqQVxabhRCINdebIk4depJiIl7yw2Q85zJyeX6fw==
|
||||
react-native-screens@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.3.0.tgz#d4464a96620b85d09e46bd6865b5f48456c244f0"
|
||||
integrity sha512-ni11jC6I9cFVXdLIDwkgafDHw/STXUNzkR5Fx3w8Wikdzi8gfTEan2kiOm7aS42d2F/LXddZ6i74Z2em0L6LPQ==
|
||||
|
||||
react-native-simple-toast@1.1.3:
|
||||
version "1.1.3"
|
||||
|
@ -8596,6 +8612,11 @@ strict-uri-encode@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
|
||||
|
||||
string-hash-64@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322"
|
||||
integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==
|
||||
|
||||
string-length@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837"
|
||||
|
|
Loading…
Reference in New Issue