Add multilanguage support
This commit is contained in:
parent
f8cbcb2908
commit
fc53bb14a0
15 changed files with 489 additions and 92 deletions
|
@ -3,6 +3,8 @@ import { Stack } from 'expo-router';
|
|||
import { StyleSheet, TextInput, TouchableOpacity } from 'react-native';
|
||||
import { router } from 'expo-router';
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Ionicons from '@expo/vector-icons/Ionicons';
|
||||
|
||||
import { ThemedText } from '@/lib/components/ThemedText';
|
||||
import { ThemedView } from '@/lib/components/ThemedView';
|
||||
|
@ -17,13 +19,14 @@ import { setSession } from '@/lib/store/dataStore';
|
|||
export default function OnboardStartScreen() {
|
||||
const colorScheme = useColorScheme() ?? 'light';
|
||||
const { setToken } = useToken();
|
||||
const { t } = useTranslation();
|
||||
const [ name, setName ] = React.useState( '' );
|
||||
const [ zipcode, setZipcode ] = React.useState( '' );
|
||||
const [ houseNumber, setHouseNumber ] = React.useState( '' );
|
||||
|
||||
const start = () => {
|
||||
if (name === '' || zipcode === '' || houseNumber === '') {
|
||||
Message.error( 'Niet alle gegevens zijn ingevuld!' );
|
||||
Message.error( t( "onboarding.missing-info" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -47,7 +50,7 @@ export default function OnboardStartScreen() {
|
|||
setToken( token );
|
||||
router.replace( "/(tabs)" );
|
||||
|
||||
store.dispatch(setSession(response.session));
|
||||
store.dispatch( setSession( response.session ) );
|
||||
|
||||
Message.success( response.message );
|
||||
}
|
||||
|
@ -59,32 +62,32 @@ export default function OnboardStartScreen() {
|
|||
<Stack.Screen options={{ title: 'Welkom' }}/>
|
||||
<ThemedView style={styles.container}>
|
||||
<ThemedView style={styles.heading}>
|
||||
<ThemedText type="title">Welkom bij </ThemedText>
|
||||
<ThemedText type="title">{t( "onboarding.welcome" )} </ThemedText>
|
||||
<ThemedText type="title" style={{ color: Colors[ colorScheme ].tint }}>Kliko</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.inputContainer}>
|
||||
<ThemedText>Wat is je naam?</ThemedText>
|
||||
<ThemedText>{t( "onboarding.your-name" )}</ThemedText>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
onChangeText={setName}
|
||||
placeholder={'Je naam'}
|
||||
placeholder={t( "onboarding.name" )}
|
||||
value={name}
|
||||
/>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.inputContainer}>
|
||||
<ThemedText>Wat is je postcode en huisnummer?</ThemedText>
|
||||
<ThemedText>{t( "onboarding.your-address" )}</ThemedText>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
onChangeText={setZipcode}
|
||||
placeholder={'Postcode'}
|
||||
placeholder={t( "onboarding.zipcode" )}
|
||||
value={zipcode}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
onChangeText={setHouseNumber}
|
||||
placeholder={'Huisnummer'}
|
||||
placeholder={t( "onboarding.house-number" )}
|
||||
value={houseNumber}
|
||||
keyboardType="numeric"
|
||||
/>
|
||||
|
@ -92,7 +95,10 @@ export default function OnboardStartScreen() {
|
|||
|
||||
|
||||
<TouchableOpacity style={{ ...styles.button, backgroundColor: Colors[ colorScheme ].tint }} onPress={start}>
|
||||
<ThemedText style={{ color: '#fff' }}>Start</ThemedText>
|
||||
<ThemedText style={{ color: Colors.white }}>
|
||||
{t( "onboarding.start" )}
|
||||
</ThemedText>
|
||||
<Ionicons name={"arrow-forward"} size={18} style={styles.buttonIcon}/>
|
||||
</TouchableOpacity>
|
||||
</ThemedView>
|
||||
</>
|
||||
|
@ -129,5 +135,13 @@ const styles = StyleSheet.create( {
|
|||
paddingLeft: 40,
|
||||
paddingRight: 40,
|
||||
marginTop: 30,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
buttonIcon: {
|
||||
marginLeft: 15,
|
||||
paddingTop: 2,
|
||||
color: Colors.white
|
||||
}
|
||||
} );
|
||||
|
|
|
@ -3,6 +3,7 @@ import { SafeAreaView, ScrollView, StyleSheet, Switch, TouchableOpacity, } from
|
|||
import { useNavigation } from '@react-navigation/native';
|
||||
import { DateTimePickerAndroid, DateTimePickerEvent } from '@react-native-community/datetimepicker';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Colors } from '@/lib/constants/Colors';
|
||||
import { useColorScheme } from '@/lib/hooks/useColorScheme';
|
||||
|
@ -19,6 +20,7 @@ export default function CategoryScreen() {
|
|||
const colorScheme = useColorScheme() ?? 'light';
|
||||
const navigation = useNavigation();
|
||||
const { token } = useToken();
|
||||
const { t } = useTranslation();
|
||||
const session = useSelector( (state: any) => state.data.session );
|
||||
|
||||
const [ sessionSet, setSessionSet ] = useState( false );
|
||||
|
@ -34,7 +36,7 @@ export default function CategoryScreen() {
|
|||
// Set page title
|
||||
useEffect( () => {
|
||||
// Set page title
|
||||
navigation.setOptions( { title: ( 'Notificaties' ) } );
|
||||
navigation.setOptions( { title: ( t( "notifications" ) ) } );
|
||||
}, [] );
|
||||
|
||||
// Set session data
|
||||
|
@ -80,8 +82,8 @@ export default function CategoryScreen() {
|
|||
onChange,
|
||||
mode: 'time',
|
||||
is24Hour: true,
|
||||
positiveButton: { label: 'Kies' },
|
||||
negativeButton: { label: 'Sluiten' },
|
||||
positiveButton: { label: t( "choose" ) },
|
||||
negativeButton: { label: t( "close" ) },
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
@ -97,14 +99,14 @@ export default function CategoryScreen() {
|
|||
if (currentEdit === 'dayBefore') {
|
||||
const minDate = new Date( `1970-01-01T16:00` );
|
||||
if (minDate > selectedDate) {
|
||||
Message.error( 'Meldingen voor 16:00 worden niet ondersteund' );
|
||||
Message.error( t( "notifications-before-16-00" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const minDate = new Date( `1970-01-01T09:00` );
|
||||
if (minDate < selectedDate) {
|
||||
Message.error( 'Meldingen na 09:00 worden niet ondersteund' );
|
||||
Message.error( t( "notifications-after-09-00" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -141,7 +143,7 @@ export default function CategoryScreen() {
|
|||
if (response.success) {
|
||||
store.dispatch( setSession( response.session ) );
|
||||
} else {
|
||||
Message.error( 'Er ging iets mis. Probeer het later opnieuw.' );
|
||||
Message.error( t( "something-went-wrong" ) );
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
@ -159,19 +161,19 @@ export default function CategoryScreen() {
|
|||
style={styles.listSwitch}
|
||||
onValueChange={() => toggleDate( 'dayBefore' )}
|
||||
/>
|
||||
<ThemedText type="defaultSemiBold">Dag van te voren</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "day-before" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
{isDayBeforeEnabled ?
|
||||
(
|
||||
<TouchableOpacity style={styles.listEdit} onPress={() => selectTime( 'dayBefore' )}>
|
||||
<ThemedText style={styles.listEditText}>Om {dayBefore}</ThemedText>
|
||||
<ThemedText style={styles.listEditText}>{t( "at" )} {dayBefore}</ThemedText>
|
||||
<ThemedIcon size={18} name="chevron-forward" style={styles.listEditIcon}/>
|
||||
</TouchableOpacity>
|
||||
) :
|
||||
(
|
||||
<ThemedText style={styles.listEdit}>
|
||||
<ThemedText style={styles.listEditText}>Uit</ThemedText>
|
||||
<ThemedText style={styles.listEditText}>{t( "off" )}</ThemedText>
|
||||
</ThemedText>
|
||||
)
|
||||
}
|
||||
|
@ -188,19 +190,19 @@ export default function CategoryScreen() {
|
|||
style={styles.listSwitch}
|
||||
onValueChange={() => toggleDate( 'sameDay' )}
|
||||
/>
|
||||
<ThemedText type="defaultSemiBold">Op de ophaaldag</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "same-day" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
{isSameDayEnabled ?
|
||||
(
|
||||
<TouchableOpacity style={styles.listEdit} onPress={() => selectTime( 'sameDay' )}>
|
||||
<ThemedText style={styles.listEditText}>Om {sameDay}</ThemedText>
|
||||
<ThemedText style={styles.listEditText}>{t( "at" )} {sameDay}</ThemedText>
|
||||
<ThemedIcon size={18} name="chevron-forward" style={styles.listEditIcon}/>
|
||||
</TouchableOpacity>
|
||||
) :
|
||||
(
|
||||
<ThemedView style={styles.listEdit}>
|
||||
<ThemedText style={styles.listEditText}>Uit</ThemedText>
|
||||
<ThemedText style={styles.listEditText}>{t( "off" )}</ThemedText>
|
||||
</ThemedView>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@ import {
|
|||
SafeAreaView,
|
||||
StatusBar,
|
||||
Image,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
TouchableOpacity
|
||||
} from 'react-native';
|
||||
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
|
@ -13,6 +12,7 @@ import { router } from 'expo-router';
|
|||
import type { AutocompleteDropdownRef } from 'react-native-autocomplete-dropdown'
|
||||
import { AutocompleteDropdown } from 'react-native-autocomplete-dropdown';
|
||||
import Modal from "react-native-modal";
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { ThemedText } from '@/lib/components/ThemedText';
|
||||
import { ThemedView } from '@/lib/components/ThemedView';
|
||||
|
@ -25,6 +25,7 @@ import { setViewCategory } from '@/lib/store/dataStore';
|
|||
|
||||
export default function ExploreScreen() {
|
||||
const colorScheme = useColorScheme() ?? 'light';
|
||||
const { t } = useTranslation();
|
||||
const [ categories, setCategories ] = useState( [] );
|
||||
const [ types, setTypes ] = useState( [] );
|
||||
const [ activeCategory, setActiveCategory ] = useState<any | null>( null );
|
||||
|
@ -78,29 +79,29 @@ export default function ExploreScreen() {
|
|||
<ThemedView>
|
||||
<ScrollView style={styles.container}>
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title">Wat moet waar?</ThemedText>
|
||||
<ThemedText type="title">{t( "what-where" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title" style={{ color: Colors[ colorScheme ].tint }}>en waarom?</ThemedText>
|
||||
<ThemedText type="title" style={{ color: Colors[ colorScheme ].tint }}>{t( "what-why" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.searchContainer}>
|
||||
<ThemedText type="defaultSemiBold">Wat wilt u scheiden?</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "what-separate" )}</ThemedText>
|
||||
<AutocompleteDropdown
|
||||
ref={searchRef}
|
||||
controller={controller => {
|
||||
dropdownController.current = controller
|
||||
}}
|
||||
textInputProps={{
|
||||
placeholder: 'Wat wilt u scheiden?',
|
||||
placeholder: t( "what-separate" ),
|
||||
autoCorrect: false,
|
||||
autoCapitalize: 'none',
|
||||
}}
|
||||
clearOnFocus={false}
|
||||
closeOnBlur={false}
|
||||
closeOnSubmit={false}
|
||||
emptyResultText={'Niks gevonden'}
|
||||
emptyResultText={t( "nothing-found" )}
|
||||
onSelectItem={selectItem}
|
||||
dataSet={categories}
|
||||
showClear={false}
|
||||
|
@ -108,7 +109,7 @@ export default function ExploreScreen() {
|
|||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.categoriesContainer}>
|
||||
<ThemedText type="defaultSemiBold">Of kies een categorie:</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "choose-category" )}:</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.listContainer}>
|
||||
|
@ -132,7 +133,7 @@ export default function ExploreScreen() {
|
|||
</ScrollView>
|
||||
</ThemedView>
|
||||
|
||||
<Modal isVisible={activeCategory !== null} useNativeDriverForBackdrop={true}>
|
||||
<Modal isVisible={activeCategory !== null} useNativeDriverForBackdrop={true}>
|
||||
<ThemedView style={{ ...styles.modalView, backgroundColor: Colors[ colorScheme ].background }}>
|
||||
<ThemedText type="subtitle" style={{ marginBottom: 30, textAlign: 'center' }}>{activeCategory?.name}</ThemedText>
|
||||
|
||||
|
@ -146,14 +147,14 @@ export default function ExploreScreen() {
|
|||
}
|
||||
|
||||
<ThemedView style={{ alignItems: 'center' }}>
|
||||
<ThemedText type="defaultSemiBold">Beschrijving:</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "description" )}:</ThemedText>
|
||||
<ThemedText>{activeCategory?.description}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => setActiveCategory( null )}
|
||||
style={{ ...styles.modalClose, backgroundColor: Colors[ colorScheme ].tint }}>
|
||||
<ThemedText style={{ color: '#fff' }}>Sluiten</ThemedText>
|
||||
<ThemedText style={{ color: '#fff' }}>{t( "close" )}</ThemedText>
|
||||
</TouchableOpacity>
|
||||
</ThemedView>
|
||||
</Modal>
|
||||
|
|
|
@ -5,6 +5,7 @@ import CalendarPicker from 'react-native-calendar-picker';
|
|||
import { useIsFocused } from '@react-navigation/core';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { LogLevel, OneSignal } from 'react-native-onesignal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { ThemedText } from '@/lib/components/ThemedText';
|
||||
import { ThemedView } from '@/lib/components/ThemedView';
|
||||
|
@ -19,9 +20,10 @@ import { ThemedIcon } from '@/lib/components/ThemedIcon';
|
|||
export default function HomeScreen() {
|
||||
const colorScheme = useColorScheme() ?? 'light';
|
||||
const isFocused = useIsFocused();
|
||||
const { t } = useTranslation();
|
||||
const session = useSelector( (state: any) => state.data.session );
|
||||
const reloadCalendar = useSelector( (state: any) => state.data.reloadCalendar );
|
||||
const { token, isLoading } = useToken();
|
||||
const { token } = useToken();
|
||||
const [ name, setName ] = useState( ' ' ); // Default empty space to prevent layout shifting
|
||||
const [ dates, setDates ] = useState<any | null>( [] );
|
||||
const [ types, setTypes ] = useState<any | null>( [] );
|
||||
|
@ -68,6 +70,21 @@ export default function HomeScreen() {
|
|||
}
|
||||
}, [ reloadCalendar, isFocused ] );
|
||||
|
||||
const getGreeting = () => {
|
||||
const myDate = new Date();
|
||||
const hours = myDate.getHours();
|
||||
|
||||
if (hours < 12) {
|
||||
return t( "greeting.morning" );
|
||||
} else if (hours >= 12 && hours <= 17) {
|
||||
return t( "greeting.afternoon" );
|
||||
} else if (hours >= 17 && hours <= 24) {
|
||||
return t( "greeting.evening" );
|
||||
}
|
||||
|
||||
return t( "greeting.hello" );
|
||||
}
|
||||
|
||||
// Load calendar data
|
||||
const loadCalendar = () => {
|
||||
Request.post( 'calendar', { token: token } ).then( (response) => {
|
||||
|
@ -116,26 +133,34 @@ export default function HomeScreen() {
|
|||
nextComponent={
|
||||
<ThemedIcon size={28} name="chevron-forward"/>
|
||||
}
|
||||
weekdays={[ "Ma", "Di", "Woe", "Do", "Vrij", "Zat", "Zo" ]}
|
||||
weekdays={[
|
||||
t( "days.mon" ),
|
||||
t( "days.tue" ),
|
||||
t( "days.wed" ),
|
||||
t( "days.thu" ),
|
||||
t( "days.fri" ),
|
||||
t( "days.sat" ),
|
||||
t( "days.sun" ),
|
||||
]}
|
||||
months={[
|
||||
"Januari",
|
||||
"Februari",
|
||||
"Maart",
|
||||
"April",
|
||||
"Mei",
|
||||
"Juni",
|
||||
"Juli",
|
||||
"Augustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"December",
|
||||
t( "months.january" ),
|
||||
t( "months.february" ),
|
||||
t( "months.march" ),
|
||||
t( "months.april" ),
|
||||
t( "months.may" ),
|
||||
t( "months.june" ),
|
||||
t( "months.july" ),
|
||||
t( "months.august" ),
|
||||
t( "months.september" ),
|
||||
t( "months.october" ),
|
||||
t( "months.november" ),
|
||||
t( "months.december" ),
|
||||
]}
|
||||
/>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.legendaContainer}>
|
||||
<ThemedText type='subtitle'>Legenda:</ThemedText>
|
||||
<ThemedText type='subtitle'>{t( "legenda" )}:</ThemedText>
|
||||
<List
|
||||
data={types}
|
||||
viewStyle={styles.legendaList}
|
||||
|
@ -153,21 +178,6 @@ export default function HomeScreen() {
|
|||
);
|
||||
}
|
||||
|
||||
function getGreeting() {
|
||||
const myDate = new Date();
|
||||
const hours = myDate.getHours();
|
||||
|
||||
if (hours < 12) {
|
||||
return 'Goedemorgen';
|
||||
} else if (hours >= 12 && hours <= 17) {
|
||||
return 'Goedemiddag';
|
||||
} else if (hours >= 17 && hours <= 24) {
|
||||
return 'Goedenavond';
|
||||
}
|
||||
|
||||
return 'Hallo';
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create( {
|
||||
container: {
|
||||
padding: 25,
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Image, SafeAreaView, ScrollView, StatusBar, StyleSheet, Switch, View, D
|
|||
import Mapbox, { Callout, Camera, MapView, PointAnnotation } from "@rnmapbox/maps";
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useIsFocused } from '@react-navigation/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
Mapbox.setAccessToken( "pk.eyJ1IjoibWFhcnRlbnZyOTgiLCJhIjoiY2x6ZDFqMGp1MGVyejJrczhqcXpvYm9iYiJ9.XvYcL62dWiJQiFmG6mOoug" );
|
||||
|
||||
|
@ -17,6 +18,7 @@ export default function MapScreen() {
|
|||
const colorScheme = useColorScheme() ?? 'light';
|
||||
const isFocused = useIsFocused();
|
||||
const session = useSelector((state: any) => state.data.session);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [ types, setTypes ] = useState<any>( [] );
|
||||
const [ coordinates, setCoordinates ] = useState<any>( [] );
|
||||
|
@ -85,11 +87,11 @@ export default function MapScreen() {
|
|||
<ThemedView style={styles.container}>
|
||||
<ThemedView>
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title">Afvalcontainers</ThemedText>
|
||||
<ThemedText type="title">{t( "garbage-bins" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title" style={{ color: Colors[ colorScheme ].tint }}>in de buurt</ThemedText>
|
||||
<ThemedText type="title" style={{ color: Colors[ colorScheme ].tint }}>{t( "nearby" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.mapContainer}>
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
SafeAreaView,
|
||||
StatusBar,
|
||||
TouchableOpacity,
|
||||
Alert,
|
||||
Alert, Image,
|
||||
} from 'react-native';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { BottomSheet, BottomSheetRefType } from 'react-native-select-bottom-list';
|
||||
|
||||
|
||||
import { ThemedText } from '@/lib/components/ThemedText';
|
||||
import { ThemedView } from '@/lib/components/ThemedView';
|
||||
|
@ -21,10 +24,12 @@ import CustomModal from '@/lib/components/EditModal';
|
|||
import { store } from '@/lib/store/store';
|
||||
import { setSession, setReloadCalendar } from '@/lib/store/dataStore';
|
||||
import { ThemedIcon } from '@/lib/components/ThemedIcon';
|
||||
import List from '@/lib/components/List';
|
||||
|
||||
export default function SettingsScreen() {
|
||||
const colorScheme = useColorScheme() ?? 'light';
|
||||
const { token, setToken } = useToken();
|
||||
const { t, i18n } = useTranslation();
|
||||
const session = useSelector( (state: any) => state.data.session );
|
||||
const router = useRouter();
|
||||
|
||||
|
@ -39,6 +44,10 @@ export default function SettingsScreen() {
|
|||
const [ city, setCity ] = React.useState( '3' );
|
||||
const [ addressModalVisible, setAddressModalVisible ] = useState( false );
|
||||
|
||||
// Language
|
||||
const [ language, setLanguage ] = useState( 'nl' );
|
||||
const sheetRef = useRef<BottomSheetRefType>( null );
|
||||
|
||||
useEffect( () => {
|
||||
setSessionData( session );
|
||||
}, [ session ] );
|
||||
|
@ -53,6 +62,9 @@ export default function SettingsScreen() {
|
|||
setHouseNumber( session.address.houseNumber );
|
||||
setStreet( session.address.street );
|
||||
setCity( session.address.city );
|
||||
|
||||
// Language
|
||||
setLanguage(session.language);
|
||||
}
|
||||
|
||||
// Handle save settings
|
||||
|
@ -75,6 +87,10 @@ export default function SettingsScreen() {
|
|||
addressChanged = true;
|
||||
}
|
||||
|
||||
if (inputValues.language) {
|
||||
postData[ 'language' ] = inputValues.language;
|
||||
}
|
||||
|
||||
Request.post( 'sessions/update', postData )
|
||||
.then( (response) => {
|
||||
if (response.success) {
|
||||
|
@ -84,32 +100,46 @@ export default function SettingsScreen() {
|
|||
store.dispatch( setSession( response.session ) )
|
||||
store.dispatch( setReloadCalendar( addressChanged ) )
|
||||
|
||||
Message.success( 'Opgeslagen!' )
|
||||
Message.success( t( "saved" ) )
|
||||
} else {
|
||||
Message.error( response.message );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
const openLanguageSelect = () => {
|
||||
sheetRef.current?.open();
|
||||
}
|
||||
|
||||
const changeLanguage = (lang: string) => {
|
||||
sheetRef.current?.close();
|
||||
|
||||
i18n.changeLanguage( lang ).then( () => {
|
||||
setLanguage(lang);
|
||||
|
||||
handleSave( { language: lang } );
|
||||
} );
|
||||
}
|
||||
|
||||
// Remove session data and logout
|
||||
const logout = () => {
|
||||
Alert.alert( 'Uitloggen', 'Weet je het zeker?', [
|
||||
Alert.alert( t( "logout" ), t( "are-you-sure" ), [
|
||||
{
|
||||
text: 'Annuleren',
|
||||
text: t( "cancel" ),
|
||||
style: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'Ja',
|
||||
text: t( "ja" ),
|
||||
onPress: () => {
|
||||
Request.post( 'sessions/delete' ).then( (response) => {
|
||||
if (!response.success) {
|
||||
Message.success( 'Je bent uitgelogd' );
|
||||
Message.success( t( "logged-out" ) );
|
||||
|
||||
setToken( null );
|
||||
|
||||
router.replace( '/(onboarding)/start' );
|
||||
} else {
|
||||
Message.error( 'Er is iets mis gegaan. Probeer het later opnieuw!' )
|
||||
Message.error( t( "something-went-wrong" ) )
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
@ -122,14 +152,14 @@ export default function SettingsScreen() {
|
|||
<ThemedView style={styles.container}>
|
||||
<ScrollView>
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title">Instellingen</ThemedText>
|
||||
<ThemedText type="title">{t( "settings" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.listContainer}>
|
||||
<ThemedView style={styles.listItem}>
|
||||
<ThemedView style={styles.listTitle}>
|
||||
<ThemedIcon name="person-outline" size={20} style={styles.listIcon}/>
|
||||
<ThemedText type="defaultSemiBold">Naam</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "name" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<TouchableOpacity style={styles.listEdit} onPress={() => setNameModalVisible( true )}>
|
||||
|
@ -141,7 +171,7 @@ export default function SettingsScreen() {
|
|||
<ThemedView style={styles.listItem}>
|
||||
<ThemedView style={styles.listTitle}>
|
||||
<ThemedIcon size={20} name="trail-sign-outline" style={styles.listIcon}/>
|
||||
<ThemedText type="defaultSemiBold">Adres</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "address" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<TouchableOpacity style={styles.listEdit} onPress={() => setAddressModalVisible( true )}>
|
||||
|
@ -153,11 +183,23 @@ export default function SettingsScreen() {
|
|||
<ThemedView style={styles.listItem}>
|
||||
<ThemedView style={styles.listTitle}>
|
||||
<ThemedIcon size={20} name="notifications-outline" style={styles.listIcon}/>
|
||||
<ThemedText type="defaultSemiBold">Notificaties</ThemedText>
|
||||
<ThemedText type="defaultSemiBold">{t( "notifications" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<TouchableOpacity style={styles.listEdit} onPress={() => router.push( '/(settings)/notifications' )}>
|
||||
<ThemedText style={styles.listEditText}>Wijzigen</ThemedText>
|
||||
<ThemedText style={styles.listEditText}>{t( "change" )}</ThemedText>
|
||||
<ThemedIcon size={18} name="chevron-forward" style={styles.listEditIcon}/>
|
||||
</TouchableOpacity>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.listItem}>
|
||||
<ThemedView style={styles.listTitle}>
|
||||
<ThemedIcon size={20} name="language-outline" style={styles.listIcon}/>
|
||||
<ThemedText type="defaultSemiBold">{t( "language" )}</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<TouchableOpacity style={styles.listEdit} onPress={openLanguageSelect}>
|
||||
<ThemedText style={styles.listEditText}>{t( "languages." + language )}</ThemedText>
|
||||
<ThemedIcon size={18} name="chevron-forward" style={styles.listEditIcon}/>
|
||||
</TouchableOpacity>
|
||||
</ThemedView>
|
||||
|
@ -166,7 +208,7 @@ export default function SettingsScreen() {
|
|||
<ThemedText>
|
||||
<TouchableOpacity onPress={logout}>
|
||||
<ThemedText type="defaultSemiBold" style={styles.logout}>
|
||||
Uitloggen
|
||||
{t( "logout" )}
|
||||
</ThemedText>
|
||||
</TouchableOpacity>
|
||||
</ThemedText>
|
||||
|
@ -174,39 +216,63 @@ export default function SettingsScreen() {
|
|||
</ThemedView>
|
||||
|
||||
<CustomModal
|
||||
title="Naam wijzigen"
|
||||
title={t( "modal.name.title" )}
|
||||
visible={nameModalVisible}
|
||||
onClose={() => setNameModalVisible( false )}
|
||||
onSave={handleSave}
|
||||
fields={[
|
||||
{
|
||||
name: 'name',
|
||||
placeholder: 'Je naam',
|
||||
placeholder: t( "modal.name.your-name" ),
|
||||
defaultValue: name,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<CustomModal
|
||||
title="Adres wijzigen"
|
||||
title={t( "modal.address.title" )}
|
||||
visible={addressModalVisible}
|
||||
onClose={() => setAddressModalVisible( false )}
|
||||
onSave={handleSave}
|
||||
fields={[
|
||||
{
|
||||
name: 'zipcode',
|
||||
title: 'Postcode',
|
||||
placeholder: 'Je postcode',
|
||||
title: t( "modal.address.zipcode" ),
|
||||
placeholder: t( "modal.address.your-zipcode" ),
|
||||
defaultValue: zipcode,
|
||||
},
|
||||
{
|
||||
name: 'houseNumber',
|
||||
title: 'Huisnummer',
|
||||
placeholder: 'Je huis nummer',
|
||||
title: t( "modal.address.house-number" ),
|
||||
placeholder: t( "modal.address.your-house-number" ),
|
||||
defaultValue: houseNumber,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<BottomSheet ref={sheetRef} presentationStyle={'overFullScreen'}>
|
||||
<ThemedView>
|
||||
<List
|
||||
data={[
|
||||
{
|
||||
name: t( "languages.nl" ),
|
||||
key: "nl",
|
||||
},
|
||||
{
|
||||
name: t( "languages.en" ),
|
||||
key: "en",
|
||||
}
|
||||
]}
|
||||
viewStyle={styles.languagesList}
|
||||
renderItem={(item: any, index: any) => (
|
||||
<TouchableOpacity style={styles.languagesListItem} key={index} onPress={() => changeLanguage( item.key )}>
|
||||
<ThemedText type="defaultSemiBold">{item.name}</ThemedText>
|
||||
<ThemedIcon name={'chevron-forward'} size={18}/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
/>
|
||||
</ThemedView>
|
||||
</BottomSheet>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
@ -262,4 +328,20 @@ const styles = StyleSheet.create( {
|
|||
logout: {
|
||||
color: Colors.red,
|
||||
},
|
||||
languagesList: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: 25,
|
||||
},
|
||||
languagesListItem: {
|
||||
display: 'flex',
|
||||
gap: 8,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingBottom: 15,
|
||||
marginBottom: 15,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: '#f2f2f2',
|
||||
}
|
||||
} );
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { Redirect, router, useRouter } from 'expo-router';
|
||||
import { Redirect, useRouter } from 'expo-router';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { ThemedText } from '@/lib/components/ThemedText';
|
||||
import { ThemedView } from '@/lib/components/ThemedView';
|
||||
|
@ -7,15 +8,17 @@ import { useToken } from '@/lib/context/AppProvider';
|
|||
import { Request } from '@/lib/services/request';
|
||||
import { store } from '@/lib/store/store';
|
||||
import { setSession } from '@/lib/store/dataStore';
|
||||
import '@/lib/localization/i18n';
|
||||
|
||||
|
||||
export default function OnboardStartScreen() {
|
||||
const { token, isLoading } = useToken();
|
||||
const { i18n } = useTranslation();
|
||||
const router = useRouter();
|
||||
|
||||
const loadingScreen = () => (
|
||||
<ThemedView>
|
||||
<ThemedText>Laden...</ThemedText>
|
||||
<ThemedText>Loading...</ThemedText>
|
||||
</ThemedView>
|
||||
);
|
||||
|
||||
|
@ -26,6 +29,9 @@ export default function OnboardStartScreen() {
|
|||
// Save to store
|
||||
store.dispatch(setSession(response.session))
|
||||
|
||||
// Set language
|
||||
i18n.changeLanguage(response.session.language);
|
||||
|
||||
// @ts-ignore
|
||||
router.replace( '/(tabs)' );
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue