347 lines
12 KiB
TypeScript
347 lines
12 KiB
TypeScript
import React, { useEffect, useRef, useState } from 'react';
|
|
import {
|
|
StyleSheet,
|
|
ScrollView,
|
|
SafeAreaView,
|
|
StatusBar,
|
|
TouchableOpacity,
|
|
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';
|
|
import { Colors } from '@/lib/constants/Colors';
|
|
import { useColorScheme } from '@/lib/hooks/useColorScheme';
|
|
import { useToken } from '@/lib/context/AppProvider';
|
|
import { Message } from '@/lib/services/message';
|
|
import { Request } from '@/lib/services/request';
|
|
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();
|
|
|
|
// Name
|
|
const [ name, setName ] = useState( '' );
|
|
const [ nameModalVisible, setNameModalVisible ] = useState( false );
|
|
|
|
// Address
|
|
const [ zipcode, setZipcode ] = React.useState( '6715GA' );
|
|
const [ houseNumber, setHouseNumber ] = React.useState( '3' );
|
|
const [ street, setStreet ] = React.useState( '3' );
|
|
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 ] );
|
|
|
|
// Set session data in view
|
|
const setSessionData = (session: any) => {
|
|
// Name
|
|
setName( session.name );
|
|
|
|
// Address
|
|
setZipcode( session.address.zipcode );
|
|
setHouseNumber( session.address.houseNumber );
|
|
setStreet( session.address.street );
|
|
setCity( session.address.city );
|
|
|
|
// Language
|
|
setLanguage(session.language);
|
|
}
|
|
|
|
// Handle save settings
|
|
const handleSave = (inputValues: Record<string, string>) => {
|
|
let postData: any = { token: token };
|
|
|
|
if (inputValues.name) {
|
|
postData[ 'name' ] = inputValues.name;
|
|
}
|
|
|
|
let addressChanged = false;
|
|
|
|
if (inputValues.zipcode) {
|
|
postData[ 'zipcode' ] = inputValues.zipcode;
|
|
addressChanged = true;
|
|
}
|
|
|
|
if (inputValues.houseNumber) {
|
|
postData[ 'houseNumber' ] = inputValues.houseNumber;
|
|
addressChanged = true;
|
|
}
|
|
|
|
if (inputValues.language) {
|
|
postData[ 'language' ] = inputValues.language;
|
|
}
|
|
|
|
Request.post( 'sessions/update', postData )
|
|
.then( (response) => {
|
|
if (response.success) {
|
|
setSessionData( response.session );
|
|
|
|
// Save to store
|
|
store.dispatch( setSession( response.session ) )
|
|
store.dispatch( setReloadCalendar( addressChanged ) )
|
|
|
|
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( t( "logout" ), t( "are-you-sure" ), [
|
|
{
|
|
text: t( "cancel" ),
|
|
style: 'cancel',
|
|
},
|
|
{
|
|
text: t( "ja" ),
|
|
onPress: () => {
|
|
Request.post( 'sessions/delete' ).then( (response) => {
|
|
if (!response.success) {
|
|
Message.success( t( "logged-out" ) );
|
|
|
|
setToken( null );
|
|
|
|
router.replace( '/(onboarding)/start' );
|
|
} else {
|
|
Message.error( t( "something-went-wrong" ) )
|
|
}
|
|
} )
|
|
}
|
|
},
|
|
] );
|
|
}
|
|
|
|
return (
|
|
<SafeAreaView style={{ flex: 1, backgroundColor: Colors[ colorScheme ].background }}>
|
|
<ThemedView style={styles.container}>
|
|
<ScrollView>
|
|
<ThemedView style={styles.titleContainer}>
|
|
<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">{t( "name" )}</ThemedText>
|
|
</ThemedView>
|
|
|
|
<TouchableOpacity style={styles.listEdit} onPress={() => setNameModalVisible( true )}>
|
|
<ThemedText style={styles.listEditText}>{name}</ThemedText>
|
|
<ThemedIcon size={18} name="chevron-forward" style={styles.listEditIcon}/>
|
|
</TouchableOpacity>
|
|
</ThemedView>
|
|
|
|
<ThemedView style={styles.listItem}>
|
|
<ThemedView style={styles.listTitle}>
|
|
<ThemedIcon size={20} name="trail-sign-outline" style={styles.listIcon}/>
|
|
<ThemedText type="defaultSemiBold">{t( "address" )}</ThemedText>
|
|
</ThemedView>
|
|
|
|
<TouchableOpacity style={styles.listEdit} onPress={() => setAddressModalVisible( true )}>
|
|
<ThemedText style={styles.listEditText}>{street} {houseNumber}. {city}</ThemedText>
|
|
<ThemedIcon size={18} name="chevron-forward" style={styles.listEditIcon}/>
|
|
</TouchableOpacity>
|
|
</ThemedView>
|
|
|
|
<ThemedView style={styles.listItem}>
|
|
<ThemedView style={styles.listTitle}>
|
|
<ThemedIcon size={20} name="notifications-outline" style={styles.listIcon}/>
|
|
<ThemedText type="defaultSemiBold">{t( "notifications" )}</ThemedText>
|
|
</ThemedView>
|
|
|
|
<TouchableOpacity style={styles.listEdit} onPress={() => router.push( '/(settings)/notifications' )}>
|
|
<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>
|
|
</ThemedView>
|
|
|
|
<ThemedText>
|
|
<TouchableOpacity onPress={logout}>
|
|
<ThemedText type="defaultSemiBold" style={styles.logout}>
|
|
{t( "logout" )}
|
|
</ThemedText>
|
|
</TouchableOpacity>
|
|
</ThemedText>
|
|
</ScrollView>
|
|
</ThemedView>
|
|
|
|
<CustomModal
|
|
title={t( "modal.name.title" )}
|
|
visible={nameModalVisible}
|
|
onClose={() => setNameModalVisible( false )}
|
|
onSave={handleSave}
|
|
fields={[
|
|
{
|
|
name: 'name',
|
|
placeholder: t( "modal.name.your-name" ),
|
|
defaultValue: name,
|
|
},
|
|
]}
|
|
/>
|
|
|
|
<CustomModal
|
|
title={t( "modal.address.title" )}
|
|
visible={addressModalVisible}
|
|
onClose={() => setAddressModalVisible( false )}
|
|
onSave={handleSave}
|
|
fields={[
|
|
{
|
|
name: 'zipcode',
|
|
title: t( "modal.address.zipcode" ),
|
|
placeholder: t( "modal.address.your-zipcode" ),
|
|
defaultValue: zipcode,
|
|
},
|
|
{
|
|
name: 'houseNumber',
|
|
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>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create( {
|
|
container: {
|
|
padding: 25,
|
|
marginTop: StatusBar.currentHeight,
|
|
},
|
|
titleContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 8,
|
|
paddingBottom: 8,
|
|
},
|
|
listContainer: {
|
|
marginTop: 30,
|
|
paddingBottom: 10
|
|
},
|
|
listItem: {
|
|
flex: 1,
|
|
display: 'flex',
|
|
gap: 8,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
paddingBottom: 20,
|
|
marginBottom: 20,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: '#f2f2f2',
|
|
},
|
|
listIcon: {
|
|
marginRight: 15,
|
|
},
|
|
listTitle: {
|
|
flex: 1,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
},
|
|
listEdit: {
|
|
flex: 1,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'flex-end',
|
|
textAlign: 'right',
|
|
},
|
|
listEditText: {
|
|
fontWeight: '300',
|
|
},
|
|
listEditIcon: {
|
|
marginLeft: 10,
|
|
},
|
|
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',
|
|
}
|
|
} );
|