language system for components

master
Netcup Gituser 2023-12-02 22:37:14 +01:00
parent 34185d8a7e
commit 2c2d661583
157 changed files with 480 additions and 290 deletions

View File

@ -1,6 +1,10 @@
import {ReactNode} from 'react';
import {ScrollView, StyleProp, View, ViewStyle} from 'react-native';
import { useSelector } from 'react-redux';
import {RootState, store} from '@redux/store';
interface MyScreenContainerProps {
children: ReactNode;
style?: StyleProp<ViewStyle>;
@ -12,8 +16,12 @@ export function MyScreenContainer({
style,
scrollView,
}: MyScreenContainerProps) {
const currentTheme = useSelector(
(state: RootState) => state.nonSaveVariables.themeColors,
);
const containerStyle = {
backgroundColor: '#212137',
backgroundColor: currentTheme.backgroundDark400,
flex: 1,
paddingLeft: 20,
paddingRight: 20,

View File

@ -1,7 +1,7 @@
import {AnimationResolver} from '@gluestack-style/animation-resolver';
import {MotionAnimationDriver} from '@gluestack-style/legend-motion-animation-driver';
import {createConfig, createComponents} from '@gluestack-style/react';
import * as componentsTheme from './theme';
import * as componentsTheme from '../theme';
export const gluestackUIConfig = createConfig({
aliases: {
@ -383,7 +383,18 @@ export const gluestackUIConfig = createConfig({
borderLight800: '#404040',
borderLight900: '#262626',
borderLight950: '#171717',
backgroundDark0: '#FCFCFC',
backgroundDark50: '#3e3e88',
backgroundDark100: '#393972',
backgroundDark200: '#32325c',
backgroundDark300: '#2b2b48',
backgroundDark400: '#212137', // primary background
backgroundDark500: '#1c1c2a',
backgroundDark600: '#16161f',
backgroundDark700: '#101015',
backgroundDark800: '#0a0a0b',
backgroundDark900: '#020202',
/*backgroundDark0: '#FCFCFC',
backgroundDark50: '#F5F5F5',
backgroundDark100: '#F1F1F1',
backgroundDark200: '#DBDBDB',
@ -394,7 +405,8 @@ export const gluestackUIConfig = createConfig({
backgroundDark700: '#525252',
backgroundDark800: '#404040',
backgroundDark900: '#262626',
backgroundDark950: '#171717',
backgroundDark950: '#171717',*/
backgroundLight0: '#FCFCFC',
backgroundLight50: '#F5F5F5',
backgroundLight100: '#F1F1F1',

View File

@ -5,67 +5,137 @@ interface LangDetails {
export default interface LangFormat {
details: LangDetails;
curVersion: string;
appName: string;
appNameDesc: string;
startHelper1: string;
navigation: {
home: {
profile: string;
calendar: string;
map: string;
chat: string;
profile: {
tabName: string;
overview: string;
settings: string;
updateUsername: string;
updatePassword: string;
help: string;
about: string;
};
calendar: {
tabName: string;
overview: string;
};
map: {
tabName: string;
overview: string;
};
chats: {
tabName: string;
overview: string;
};
};
};
info: string;
error: string;
success: string;
account: {
registration: {
buttonLogin: string;
buttonSignUp: string;
buttonNext: string;
dividerText: string;
thirdAuthButton: {
google: string;
apple: string;
};
previewLogin: {
title: string;
dontHaveAccount: string;
};
previewSignup: {
title: string;
agreeToTerms: string;
agreeToTermsAnd: string;
alreadyHaveAccount: string;
terms: string;
privacyPolicy: string;
cookieUse: string;
};
login: {
title: string;
wrongEmPw: string;
failed: string;
success: string;
inputPhoneNumberOrAccountName: string;
inputPassword: string;
};
registration: {
registration: string;
info: string;
privacyPolicy: string;
termsOfUse: string;
stepOne: {
title: string;
success: string;
addressExists: string;
addressInvalid: string;
noMailEntered: string;
button: string;
signUpStepUsername: {
title: string;
description: string;
inputUsername: string;
};
signUpStepPhoneNumber: {
title: string;
inputPhoneNumber: string;
};
signUpStepVerifyPhoneNumber: {
title: string;
description: string;
clickableTextResendCode: string;
};
signUpStepPassword: {
title: string;
description: string;
inputPassword: string;
};
signUpStepAccountName: {
title: string;
description: string;
inputAccountName: string;
buttonGetStarted: string;
};
};
profile: {
overview: {
statistics: {
followers: string;
following: string;
visited: string;
};
stepTwo: {
title: string;
verification: string;
resend: [string, string, string];
noCodeEntered: string;
resendError: {[key: number]: string};
verificationError: {[key: number]: string};
button: string;
success: string;
};
settings: {
overview: {
accountData: {
title: string;
accountName: string;
username: string;
phoneNumber: string;
};
changePassword: {
title: string;
password: string;
tapToChange: string;
};
moreInfo: {
title: string;
help: string;
about: string;
logout: string;
};
};
stepFinal: {
verification: string;
userName: string;
accountName: string;
password: string;
passwordRepeat: string;
displayName: string;
accountNameError: {[key: string]: string};
userNameError: {[key: string]: string};
passwordError: {[key: string]: string};
passwordQuality: string;
passwordQualityList: {[key: string]: string};
noAllFieldsEntered: string;
button: string;
registerError: {[key: string]: string};
changeUsername: {
username: string;
info: string;
info2: string;
};
changePassword: {
currentPassword: string;
newPassword: string;
repeatNewPassword: string;
info: string;
info2: string;
};
help: {
reportAProblem: string;
helpCenter: string;
};
about: {
aboutYourAccount: string;
privacyPolicy: string;
termsOfService: string;
openSourceLibraries: string;
};
};
};

View File

@ -5,109 +5,138 @@ export const lang: LangFormat = {
langCode: 'en',
langName: 'English',
},
curVersion: 'Your current version is v${version}.',
appName: 'Click And Join',
appNameDesc: 'an app developed with love by Janex',
startHelper1: 'Your data will be loaded :)',
appName: 'Party App',
navigation: {
home: {
profile: 'My profile',
calendar: 'Calendar',
map: 'Map',
chat: 'Chats',
profile: {
tabName: 'Profile',
overview: 'My profile',
settings: 'Profile Settings',
updateUsername: 'Change username',
updatePassword: 'Change password',
help: 'Help',
about: 'About',
},
calendar: {
tabName: 'Calendar',
overview: 'Calendar',
},
map: {
tabName: 'Map',
overview: 'Map',
},
chats: {
tabName: 'Chats',
overview: 'Chats',
},
},
},
info: 'Info',
error: 'Error',
success: 'Success',
account: {
login: {
title: 'Log in',
wrongEmPw: 'Wrong E-Mail or password',
failed: 'Login failed. Try again or contact support.',
success: 'Successfully logged in!',
registration: {
buttonLogin: 'Login',
buttonSignUp: 'Sign up',
buttonNext: 'Next',
dividerText: 'or',
thirdAuthButton: {
google: 'Sign in with Google',
apple: 'Sign in with Apple',
},
registration: {
registration: 'Registration',
info: 'By registering, you agree to our ${TermsOfUse}. You can find out how we collect and use your data in our ${privacyPolicy}.',
privacyPolicy: 'privacy policy',
termsOfUse: 'Terms of Use',
stepOne: {
title: 'E-Mail',
success: 'A verification has sent to your E-Mail!',
addressExists: 'The E-Mail you entered is already in use.',
addressInvalid: 'The address you entered has an invalid format.',
noMailEntered: 'Please enter your E-Mail',
button: 'Next step',
previewLogin: {
title: 'Time to get to know the next a party',
dontHaveAccount: "Don't have an account?",
},
previewSignup: {
title: 'Find the next party near you',
agreeToTerms: 'By signing up, you agree to our',
agreeToTermsAnd: 'and',
alreadyHaveAccount: 'Already have an account?',
terms: 'Terms',
privacyPolicy: 'Privacy Policy',
cookieUse: 'Cookie Use',
},
login: {
title: 'Welcome back!',
inputPhoneNumberOrAccountName: 'PHONE NUMBER OR ACCOUNT NAME',
inputPassword: 'PASSWORD',
},
signUpStepUsername: {
title: "Let's get started, what's your name?",
description: 'The name will be displayed on your profil overview',
inputUsername: 'Username',
},
signUpStepPhoneNumber: {
title: 'Create your account using your phone number',
inputPhoneNumber: 'PHONE NUMBER',
},
signUpStepVerifyPhoneNumber: {
title: 'We sent you a code',
description: 'Enter the 6-digit code we sent to',
clickableTextResendCode: 'Resend code',
},
signUpStepPassword: {
title: "You'll need a password",
description: 'Make sure its 8 characters or more.',
inputPassword: 'PASSWORD',
},
signUpStepAccountName: {
title: 'Next, create your account name',
description:
'Your account name is unique and is used for friends to find you.',
inputAccountName: 'ACCOUNT NAME',
buttonGetStarted: 'Get Started',
},
},
profile: {
overview: {
statistics: {
followers: 'FOLLOWER',
following: 'FOLLOWING',
visited: 'VISITED',
},
stepTwo: {
title: 'Enter the 6-digit code that we sent you to ${EMail}.',
verification: 'X-X-X-X-X-X',
noCodeEntered: 'Please enter your code',
resend: [
'E-Mail not arrived? You can also resend the verification E-Mail by ${resend}.',
'clicking here',
'E-Mail verification has resent',
],
resendError: {
400: 'Email is already in the registration process by another user!',
401: 'Your device have changed. Please use another E-Mail address.',
429: 'Too many requests in a too small period of time in a row',
},
settings: {
overview: {
accountData: {
title: 'ACCOUNT DATA',
accountName: 'ACCOUNT NAME',
username: 'USERNAME',
phoneNumber: 'PHONE NUMBER',
},
verificationError: {
400: 'Something went wrong please try again :( Restart App maybe required',
401: 'The code you entered does not match with the code we sent you',
422: 'The verification time is expired. Please please try again',
changePassword: {
title: 'PASSWORD',
password: 'PASSWORD',
tapToChange: 'Tap to change',
},
moreInfo: {
title: 'MORE INFO',
help: 'Help',
about: 'About',
logout: 'Logout',
},
button: 'Verify',
success: 'Verification success!',
},
stepFinal: {
verification:
'Your Account has been verified. Now enter your user credentials.',
userName: 'Username',
accountName: 'AccountName',
password: 'Password',
passwordRepeat: 'Repeat password',
displayName: 'Other users will see you like this:',
accountNameError: {
tooLong: 'Too long. Max length are ${maxLength} character.',
tooShort: 'Too short. Min length are ${minLength} character.',
required: 'This field is required',
invalid:
'Account names can only contain letters, numbers, underscores (_) and dots (.)',
exists: 'The account name you entered already exists.',
422: 'This name is already in use :(',
},
userNameError: {
tooLong: 'Too long. Max length are ${maxLength} character.',
tooShort: 'Too short. Min length are ${minLength} character.',
required: 'This field is required',
},
passwordError: {
noMatch: 'Passwords do not match',
tooLong: 'Too long. Max length are ${maxLength} character.',
tooShort: 'Too short. Min length are ${minLength} character.',
required: 'This field is required',
weak: 'Password is too weak',
invalid:
"Passwords must have at least one letter, one number, and one special character. It's for your security. :)",
},
passwordQuality: 'Password quality: ${quality}',
passwordQualityList: {
0: 'Very weak',
1: 'Weak',
2: 'Moderate',
3: 'Strong',
4: 'Very strong',
},
noAllFieldsEntered: 'Please fill all fields',
button: 'Finish registration',
registerError: {
400: 'Sign up process expired please try again',
401: 'User agent and/or IP has changed',
},
changeUsername: {
username: 'USERNAME',
info: 'You can use a-z, 0-9 and underscores.',
info2: 'Minimum length is 3 characters.',
},
changePassword: {
currentPassword: 'CURRENT PASSWORD',
newPassword: 'NEW PASSWORD',
repeatNewPassword: 'REPEAT NEW PASSWORD',
info: 'Make sure its 8 characters or more.',
info2: 'You will be logged out after changing your password.',
},
help: {
reportAProblem: 'Report a problem',
helpCenter: 'Help center',
},
about: {
aboutYourAccount: 'About your account',
privacyPolicy: 'Privacy Policy',
termsOfService: 'Terms of Service',
openSourceLibraries: 'Open source libraries',
},
},
},

View File

@ -4,13 +4,15 @@ import {
BottomTabBarProps,
createBottomTabNavigator,
} from '@react-navigation/bottom-tabs';
import CalendarTab from './tabs/main/CalendarTab';
import ChatsTab from './tabs/main/ChatsTab';
import MapTab from './tabs/main/MapTab';
import CalendarTab, {
CalendarStackNavigatorParamList,
} from './tabs/main/CalendarTab';
import ChatsTab, {ChatsStackNavigatorParamList} from './tabs/main/ChatsTab';
import MapTab, {MapStackNavigatorParamList} from './tabs/main/MapTab';
import ProfileTab, {
ProfileStackNavigatorParamList,
} from './tabs/main/ProfileTab';
import {FadeInView, SlideFromLeftView} from '@helper/animations';
import {FadeInView} from '@helper/animations';
import {Text, TouchableOpacity, View} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import {
@ -19,6 +21,8 @@ import {
} from './registration/registration';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
import {MyIcon} from '@components/MyIcon';
import {useSelector} from 'react-redux';
import {RootState, store as reduxStore} from '@redux/store';
export type RootStackNavigatorParamList = {
Home: NavigatorScreenParams<HomeStackNavigatorParamList>;
@ -29,12 +33,15 @@ export type RootScreenNavigationProp =
NativeStackNavigationProp<RootStackNavigatorParamList>;
export default function Navigation() {
const currentUser =
reduxStore.getState().appVariables.preferences.selectedAccount;
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
initialRouteName="Registration">
initialRouteName={currentUser === 'none' ? 'Registration' : 'Home'}>
<Stack.Screen name="Home" component={HomeStack} />
<Stack.Screen name="Registration" component={RegistrationScreenAnim} />
</Stack.Navigator>
@ -43,13 +50,16 @@ export default function Navigation() {
export type HomeStackNavigatorParamList = {
Profile: NavigatorScreenParams<ProfileStackNavigatorParamList>;
Calendar: NavigatorScreenParams<CalendarStackNavigatorParamList>;
Map: NavigatorScreenParams<MapStackNavigatorParamList>;
Chats: NavigatorScreenParams<ChatsStackNavigatorParamList>;
};
function ProfileTabAnim(props: any) {
return (
<SlideFromLeftView>
<FadeInView>
<ProfileTab {...props} />
</SlideFromLeftView>
</FadeInView>
);
}
@ -71,9 +81,9 @@ function MapTabAnim(props: any) {
function ChatsTabAnim(props: any) {
return (
<SlideFromLeftView>
<FadeInView>
<ChatsTab {...props} />
</SlideFromLeftView>
</FadeInView>
);
}
@ -82,6 +92,17 @@ const tabBarIcons = ['account-circle', 'calendar-month', 'map', 'chat'];
function CustomTabBar(props: BottomTabBarProps) {
const {state, descriptors, navigation} = props;
const lang = useSelector(
(state: RootState) => state.appVariables.lang.navigation.home,
);
const tabNames = [
lang.profile.tabName,
lang.calendar.tabName,
lang.map.tabName,
lang.chats.tabName,
];
return (
<View style={{backgroundColor: '#212137'}}>
<View
@ -92,14 +113,6 @@ function CustomTabBar(props: BottomTabBarProps) {
borderRadius: 20,
}}>
{state.routes.map((route, index) => {
const {options} = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const onPress = () => {
@ -130,8 +143,6 @@ function CustomTabBar(props: BottomTabBarProps) {
<TouchableOpacity
key={route.key}
accessibilityRole="button"
//accessibilityState={isFocused ? ['selected'] : []}
//accessibilityLabel={options.tabBarAccessibilityLabel}
onPress={onPress}
onLongPress={onLongPress}
style={{
@ -158,7 +169,7 @@ function CustomTabBar(props: BottomTabBarProps) {
size={20}
/>
{isFocused && (
<Text style={{color: '#fff'}}>{label.toString()}</Text>
<Text style={{color: '#fff'}}>{tabNames[index]}</Text>
)}
</LinearGradient>
</TouchableOpacity>

View File

@ -20,7 +20,7 @@ import AppleLogo from '@assets/apple-logo.png';
import Logo from '@assets/logo.png';
import {MyDividerWithText} from '@components/MyDivider';
import {MyButton, MyIconButton, MyImageButton} from '@components/MyButton';
import {MyButton, MyImageButton} from '@components/MyButton';
import {MyClickableText} from '@components/MyClickableText';
import {OpenURL} from '@helper/linking';
import {Constants} from '@utils/utils';
@ -28,6 +28,8 @@ import {MyIconInput} from '@components/MyInput';
import {useRef, useState} from 'react';
import {KeyboardAvoidingView} from 'react-native';
import {MyTitle} from '@components/MyTitle';
import {useSelector} from 'react-redux';
import {RootState} from '@redux/store';
export type RegistrationStackNavigatorParamList = {
SignUpPreview: undefined;
@ -113,24 +115,31 @@ function LoginPreview() {
}
function ThirdAuthButtons() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration.thirdAuthButton,
);
return (
<>
<MyImageButton
image={GoogleLogo}
imageStyle={{left: 2, height: 35, width: 35}}
text="Continue with Google"
text={lang.google}
/>
<MyImageButton
image={AppleLogo}
imageStyle={{height: 40, width: 40}}
text="Continue with Apple"
text={lang.apple}
/>
</>
);
}
function RegistrationPreview({type}: {type: 'login' | 'signup'}) {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
return (
@ -146,8 +155,8 @@ function RegistrationPreview({type}: {type: 'login' | 'signup'}) {
<MyTitle
text={
type === 'login'
? 'Time to get to know the next party'
: 'Find the next party near you'
? lang.previewLogin.title
: lang.previewSignup.title
}
/>
</View>
@ -161,11 +170,11 @@ function RegistrationPreview({type}: {type: 'login' | 'signup'}) {
}}>
<ThirdAuthButtons />
<MyDividerWithText text="or" />
<MyDividerWithText text={lang.dividerText} />
<MyButton
type="secondary"
text={type === 'login' ? 'Login' : 'Create account'}
text={type === 'login' ? lang.buttonLogin : lang.buttonSignUp}
style={{marginBottom: 20}}
onPress={() => {
navigation.navigate(
@ -177,23 +186,23 @@ function RegistrationPreview({type}: {type: 'login' | 'signup'}) {
}}
/>
{type === 'login' && (
{type === 'signup' && (
<View style={{flexDirection: 'row', flexWrap: 'wrap'}}>
<Text>By signing up, you agree to our </Text>
<Text>{`${lang.previewSignup.agreeToTerms} `}</Text>
<MyClickableText
text="Terms"
text={lang.previewSignup.terms}
textStyle={{color: '#6030da'}}
onPress={() => OpenURL(Constants.REGISTRATION.TERMS_URL)}
/>
<Text>, </Text>
<MyClickableText
text="Privacy Policy"
text={lang.previewSignup.privacyPolicy}
textStyle={{color: '#6030da'}}
onPress={() => OpenURL(Constants.REGISTRATION.PRIVACY_POLICY_URL)}
/>
<Text> and </Text>
<Text>{` ${lang.previewSignup.agreeToTermsAnd} `}</Text>
<MyClickableText
text="Cookie Use"
text={lang.previewSignup.cookieUse}
textStyle={{color: '#6030da'}}
onPress={() => OpenURL(Constants.REGISTRATION.COOKIE_USE_URL)}
/>
@ -203,13 +212,13 @@ function RegistrationPreview({type}: {type: 'login' | 'signup'}) {
<View style={{flexDirection: 'row'}}>
{type === 'login' ? (
<Text>Don't have an account?</Text>
<Text>{lang.previewLogin.dontHaveAccount}</Text>
) : (
<Text>Have already an account?</Text>
<Text>{lang.previewSignup.alreadyHaveAccount}</Text>
)}
<MyClickableText
text={type === 'login' ? 'Sign up' : 'Login'}
text={type === 'login' ? lang.buttonSignUp : lang.buttonLogin}
textStyle={{left: 2, color: '#931278', fontWeight: 'bold'}}
onPress={() => {
navigation.navigate(
@ -236,6 +245,9 @@ function ContentContainer({children}: {children: React.ReactNode}) {
}
function Login() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
return (
@ -244,19 +256,24 @@ function Login() {
flexDirection: 'column',
}}>
<ContentContainer>
<MyTitle text="Welcome back!" />
<MyTitle text={lang.login.title} />
<View style={{gap: 12}}>
<MyIconInput text="PHONE NUMBER OR ACCOUNT NAME" iconName="person" />
<MyIconInput text="PASSWORD" iconName="lock" secureTextEntry />
<MyIconInput
text={lang.login.inputPhoneNumberOrAccountName}
iconName="person"
/>
<MyIconInput
text={lang.login.inputPassword}
iconName="lock"
secureTextEntry
/>
<MyButton
type="secondary"
text={'Login'}
text={lang.buttonLogin}
style={{marginBottom: 20}}
onPress={() => {
navigation.navigate('Home');
}}
onPress={() => navigateToHome(navigation)}
/>
</View>
</ContentContainer>
@ -265,6 +282,9 @@ function Login() {
}
function SignUpStepUsername() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
return (
@ -273,15 +293,18 @@ function SignUpStepUsername() {
flexDirection: 'column',
}}>
<ContentContainer>
<MyTitle text="Let's get started, what's your name?" />
<Text>The name will be displayed on your profil overview</Text>
<MyTitle text={lang.signUpStepUsername.title} />
<Text>{lang.signUpStepUsername.description}</Text>
<View style={{gap: 12, marginTop: 20}}>
<MyIconInput text="Username" iconName="person" />
<MyIconInput
text={lang.signUpStepUsername.inputUsername}
iconName="person"
/>
<MyButton
type="secondary"
text={'Next'}
text={lang.buttonNext}
style={{marginBottom: 20}}
onPress={() => {
navigation.navigate('Registration', {
@ -296,6 +319,9 @@ function SignUpStepUsername() {
}
function SignUpStepPhoneNumber() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
return (
@ -304,18 +330,18 @@ function SignUpStepPhoneNumber() {
flexDirection: 'column',
}}>
<ContentContainer>
<MyTitle text="Create your account using your phone number" />
<MyTitle text={lang.signUpStepPhoneNumber.title} />
<View style={{gap: 12, marginTop: 20}}>
<MyIconInput
text="Phone"
text={lang.signUpStepPhoneNumber.inputPhoneNumber}
iconName="phone-iphone"
keyboardType="phone-pad"
/>
<MyButton
type="secondary"
text={'Next'}
text={lang.buttonNext}
style={{marginBottom: 20}}
onPress={() => {
navigation.navigate('Registration', {
@ -329,9 +355,7 @@ function SignUpStepPhoneNumber() {
);
}
interface ConfirmationCodeInputProps {
// Zusätzliche Props für das ConfirmationCodeInput-Komponente hier hinzufügen
}
interface ConfirmationCodeInputProps {}
const ConfirmationCodeInput: React.FC<ConfirmationCodeInputProps> = () => {
const [confirmationCode, setConfirmationCode] = useState([
@ -396,6 +420,9 @@ const styles = StyleSheet.create({
});
function SignUpStepVerifyPhoneNumber() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
return (
@ -404,15 +431,15 @@ function SignUpStepVerifyPhoneNumber() {
flexDirection: 'column',
}}>
<ContentContainer>
<MyTitle text="We sent you a code" />
<Text>Enter it below to verify +49 15** ******43 </Text>
<MyTitle text={lang.signUpStepVerifyPhoneNumber.title} />
<Text>{`${lang.signUpStepVerifyPhoneNumber.description} +49 15** ******43`}</Text>
<KeyboardAvoidingView style={{gap: 12, marginTop: 20}}>
<ConfirmationCodeInput />
<MyButton
type="secondary"
text={'Next'}
text={lang.buttonNext}
style={{marginBottom: 2}}
onPress={() => {
navigation.navigate('Registration', {
@ -421,7 +448,9 @@ function SignUpStepVerifyPhoneNumber() {
}}
/>
<View style={{alignItems: 'center'}}>
<MyClickableText text="Resend code" />
<MyClickableText
text={lang.signUpStepVerifyPhoneNumber.clickableTextResendCode}
/>
</View>
</KeyboardAvoidingView>
</ContentContainer>
@ -430,6 +459,9 @@ function SignUpStepVerifyPhoneNumber() {
}
function SignUpStepPassword() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
return (
@ -438,21 +470,25 @@ function SignUpStepPassword() {
flexDirection: 'column',
}}>
<ContentContainer>
<MyTitle text="You'll need a password" />
<Text>Make sure it's 8 characters or more</Text>
<MyTitle text={lang.signUpStepPassword.title} />
<Text>{lang.signUpStepPassword.description}</Text>
<View style={{gap: 12, marginTop: 20}}>
<MyIconInput text="PASSWORD" iconName="lock" secureTextEntry />
<MyIconInput
text={lang.signUpStepPassword.inputPassword}
iconName="lock"
secureTextEntry
/>
<MyButton
type="secondary"
text={'Next'}
text={lang.buttonNext}
style={{marginBottom: 2}}
onPress={() => {
onPress={() =>
navigation.navigate('Registration', {
screen: 'SignUpStepAccountName',
});
}}
})
}
/>
</View>
</ContentContainer>
@ -460,7 +496,18 @@ function SignUpStepPassword() {
);
}
function navigateToHome(navigation: RootScreenNavigationProp) {
navigation.navigate('Home', {screen: 'Map', params: {screen: 'Overview'}});
navigation.reset({
index: 0,
routes: [{name: 'Home'}],
});
}
function SignUpStepAccountName() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.registration,
);
const navigation = useNavigation<RootScreenNavigationProp>();
return (
@ -470,21 +517,20 @@ function SignUpStepAccountName() {
}}>
<ScrollView>
<ContentContainer>
<MyTitle text="Next, create your account name" />
<Text>
Your account name is unique and is used for friends to find you.
</Text>
<MyTitle text={lang.signUpStepAccountName.title} />
<Text>{lang.signUpStepAccountName.description}</Text>
<View style={{gap: 12, marginTop: 20}}>
<MyIconInput text="ACCOUNT NAME" iconName="person" />
<MyIconInput
text={lang.signUpStepAccountName.inputAccountName}
iconName="person"
/>
<MyButton
type="primary"
text={'Get Started'}
text={lang.signUpStepAccountName.buttonGetStarted}
style={{marginBottom: 2}}
onPress={() => {
navigation.navigate('Home');
}}
onPress={() => navigateToHome(navigation)}
/>
</View>
</ContentContainer>

View File

@ -1,5 +1,4 @@
import { MyScreenContainer } from '@components/MyScreenContainer';
import {Center} from '@gluestack-ui/themed/build/components/Center';
import {
createNativeStackNavigator,
NativeStackNavigationProp,
@ -21,7 +20,7 @@ export type CalendarScreenNavigationProp =
NativeStackNavigationProp<CalendarStackNavigatorParamList>;
function CalendarTab() {
const lang = useSelector((state: RootState) => state.appVariables.lang);
const lang = useSelector((state: RootState) => state.appVariables.lang.navigation.home.calendar);
//const navigation = useNavigation<CalendarScreenNavigationProp>();
@ -30,7 +29,7 @@ function CalendarTab() {
<CalendarStack.Screen
name="Overview"
options={{
title: lang.navigation.home.calendar,
title: lang.tabName,
headerShown: true,
}}
component={CalendarScreen}

View File

@ -1,6 +1,4 @@
import { MyScreenContainer } from '@components/MyScreenContainer';
import {Center} from '@gluestack-ui/themed/build/components/Center';
import {useNavigation} from '@react-navigation/native';
import {MyScreenContainer} from '@components/MyScreenContainer';
import {
createNativeStackNavigator,
NativeStackNavigationProp,
@ -22,16 +20,16 @@ export type ChatsScreenNavigationProp =
NativeStackNavigationProp<ChatsStackNavigatorParamList>;
function ChatsTab() {
const lang = useSelector((state: RootState) => state.appVariables.lang);
//const navigation = useNavigation<ChatsScreenNavigationProp>();
const lang = useSelector(
(state: RootState) => state.appVariables.lang.navigation.home.chats,
);
return (
<ChatsStack.Navigator initialRouteName="Overview">
<ChatsStack.Screen
name="Overview"
options={{
title: lang.navigation.home.chat,
title: lang.tabName,
headerShown: true,
}}
component={ChatsScreen}

View File

@ -1,5 +1,4 @@
import { MyScreenContainer } from '@components/MyScreenContainer';
import {Center} from '@gluestack-ui/themed/build/components/Center';
import {
createNativeStackNavigator,
NativeStackNavigationProp,
@ -20,7 +19,7 @@ export type MapScreenNavigationProp =
NativeStackNavigationProp<MapStackNavigatorParamList>;
function MapTab() {
const lang = useSelector((state: RootState) => state.appVariables.lang);
const lang = useSelector((state: RootState) => state.appVariables.lang.navigation.home.map);
//const navigation = useNavigation<MapScreenNavigationProp>();
@ -29,7 +28,7 @@ function MapTab() {
<MapStack.Screen
name="Overview"
options={{
title: lang.navigation.home.map,
title: lang.tabName,
headerShown: true,
}}
component={MapScreen}

View File

@ -13,7 +13,7 @@ import {
UpdateUsername,
} from '@pages/profile/profile';
import {Help} from '@pages/profile/help';
import { About } from '@pages/profile/about';
import {About} from '@pages/profile/about';
export const ProfileTabName = 'Profile';
@ -36,7 +36,9 @@ export type ProfileScreenNavigationProp =
export default function ProfileTab() {
const navigation = useNavigation<ProfileScreenNavigationProp>();
const lang = useSelector((state: RootState) => state.appVariables.lang);
const lang = useSelector(
(state: RootState) => state.appVariables.lang.navigation.home.profile,
);
return (
<ProfileStack.Navigator>
@ -44,10 +46,9 @@ export default function ProfileTab() {
name="Overview"
options={{
animation: 'slide_from_left',
title: lang.navigation.home.profile,
title: lang.overview,
headerShown: true,
headerStyle: {backgroundColor: '#212137'},
headerTitle: '',
headerRight: () => (
<MyIconButton
MyIconProps={{name: 'settings', size: 24}}
@ -62,7 +63,7 @@ export default function ProfileTab() {
name="Settings"
options={{
animation: 'slide_from_right',
title: 'Profile Settings',
title: lang.settings,
headerShown: true,
headerStyle: {backgroundColor: '#212137'},
headerTitleAlign: 'center',
@ -74,7 +75,7 @@ export default function ProfileTab() {
name="UpdateUsername"
options={{
animation: 'slide_from_right',
title: 'Update Username',
title: lang.updateUsername,
headerShown: true,
headerStyle: {backgroundColor: '#212137'},
headerTitleAlign: 'center',
@ -86,7 +87,7 @@ export default function ProfileTab() {
name="UpdatePassword"
options={{
animation: 'slide_from_right',
title: 'Update Password',
title: lang.updatePassword,
headerShown: true,
headerStyle: {backgroundColor: '#212137'},
headerTitleAlign: 'center',
@ -98,7 +99,7 @@ export default function ProfileTab() {
name="Help"
options={{
animation: 'slide_from_right',
title: 'Help',
title: lang.help,
headerShown: true,
headerStyle: {backgroundColor: '#212137'},
headerTitleAlign: 'center',
@ -110,7 +111,7 @@ export default function ProfileTab() {
name="About"
options={{
animation: 'slide_from_right',
title: 'About',
title: lang.about,
headerShown: true,
headerStyle: {backgroundColor: '#212137'},
headerTitleAlign: 'center',

View File

@ -1,15 +1,11 @@
import {Platform, StyleSheet, View, ScrollView} from 'react-native';
import {Center, Heading, Text, Spinner, HStack} from '@gluestack-ui/themed';
import {View} from 'react-native';
import {Center, Heading, Spinner, HStack} from '@gluestack-ui/themed';
import {animated, useSpring} from '@react-spring/native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {useSelector, useDispatch} from 'react-redux';
import {useSelector} from 'react-redux';
import {RootState, store} from '@redux/store';
//import {getBackgroundColor} from '@configs/colors';
import {useEffect} from 'react';
import {initAppData} from '@helper/appData';
import {appStatus} from '@configs/appNonSaveVar';
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
@ -26,7 +22,7 @@ function onAppStart() {
store.dispatch(
appNonSaveVarActions.setAppStatus(appStatus.APP_RUNNING),
);
}, 250);
}, 0);
})
.catch(err => {
console.error("Database Error! Can't start App :(");
@ -80,14 +76,14 @@ function StartHelper() {
if (currentAppStatus === appStatus.APP_RUNNING) return null;
return (
<SafeAreaView style={[{flex: 1, backgroundColor: '#333'}]}>
<SafeAreaView style={[{flex: 1, backgroundColor: '#26263f'}]}>
<Center height={'100%'}>
<AnimationView
style={{
height: 100,
position: 'absolute',
backgroundColor: '#f22',
backgroundColor: '#931278',
borderRadius: 8,
width: motionProps.width,
@ -95,13 +91,10 @@ function StartHelper() {
transform: [{translateX: motionProps.translateX}, {translateY: 5}],
}}
/>
<Heading>{lang.appName}</Heading>
<Heading style={{color: '#fff'}}>{lang.appName}</Heading>
<HStack marginTop={5} justifyContent="center">
<Spinner color="#ff7d4f" accessibilityLabel="Loading posts" />
<Heading color="#ff7d4f" size="md">
{lang.startHelper1}
</Heading>
<Spinner color="#931278" size="large" />
</HStack>
</Center>
</SafeAreaView>

View File

@ -1,15 +1,21 @@
import {MyScreenContainer} from '@components/MyScreenContainer';
import {Item} from './help';
import { useSelector } from 'react-redux';
import { RootState } from '@redux/store';
export function About() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.profile.settings.about,
);
return (
<MyScreenContainer>
<Item icon="person" title="About your account" onPress={() => {}} />
<Item icon="privacy-tip" title="Privacy Policy" onPress={() => {}} />
<Item icon="description" title="Terms and Imprint" onPress={() => {}} />
<Item icon="person" title={lang.aboutYourAccount} onPress={() => {}} />
<Item icon="privacy-tip" title={lang.privacyPolicy} onPress={() => {}} />
<Item icon="description" title={lang.termsOfService} onPress={() => {}} />
<Item
icon="library-books"
title="Open source libraries"
title={lang.openSourceLibraries}
onPress={() => {}}
/>
</MyScreenContainer>

View File

@ -1,13 +1,19 @@
import {MyIcon} from '@components/MyIcon';
import {MyScreenContainer} from '@components/MyScreenContainer';
import { RootState } from '@redux/store';
import {View} from 'react-native';
import {Text, TouchableOpacity} from 'react-native';
import { useSelector } from 'react-redux';
export function Help() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.profile.settings.help,
);
return (
<MyScreenContainer>
<Item icon="bug-report" title="Report a problem" onPress={() => {}} />
<Item icon="contact-support" title="Help Center" onPress={() => {}} />
<Item icon="bug-report" title={lang.reportAProblem} onPress={() => {}} />
<Item icon="contact-support" title={lang.helpCenter} onPress={() => {}} />
</MyScreenContainer>
);
}

View File

@ -1,7 +1,6 @@
import {MyScreenContainer} from '@components/MyScreenContainer';
import {Image, ScrollView, TextInput, TouchableOpacity} from 'react-native';
import {Image, ScrollView, TouchableOpacity} from 'react-native';
import {Text, View} from 'react-native';
import Avatar from '@assets/profile.png';
import {MyTitle} from '@components/MyTitle';
import {MyVerticalDivider} from '@components/MyDivider';
@ -10,10 +9,9 @@ import {useNavigation} from '@react-navigation/native';
import {ProfileScreenNavigationProp} from '@navigation/tabs/main/ProfileTab';
import {MyIconInput} from '@components/MyInput';
import {useEffect, useState} from 'react';
import {
RootScreenNavigationProp,
RootStackNavigatorParamList,
} from '@navigation/navigation';
import {RootScreenNavigationProp} from '@navigation/navigation';
import {useSelector} from 'react-redux';
import {RootState} from '@redux/store';
function UserAvatar() {
return (
@ -26,6 +24,10 @@ function UserAvatar() {
}
export function ProfileOverview() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.profile.overview.statistics,
);
return (
<MyScreenContainer
style={{
@ -38,11 +40,11 @@ export function ProfileOverview() {
<MyTitle text="Max Mustermann" />
<View style={{flexDirection: 'row', gap: 12}}>
<Statistic title="FOLLOWER" value="400.3k" />
<Statistic title={lang.followers} value="400.3k" />
<MyVerticalDivider />
<Statistic title="FOLLOWING" value="40.3k" />
<Statistic title={lang.following} value="40.3k" />
<MyVerticalDivider />
<Statistic title="VISITED" value="2k" />
<Statistic title={lang.visited} value="2k" />
</View>
</MyScreenContainer>
);
@ -81,8 +83,10 @@ function Statistic({value, title}: StatisticProps) {
}
export function ProfileSettings() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.profile.settings.overview,
);
const navigation = useNavigation<ProfileScreenNavigationProp>();
const rootNavigation = useNavigation<RootScreenNavigationProp>();
return (
@ -95,52 +99,52 @@ export function ProfileSettings() {
<UserAvatar />
</View>
<SettingsItemContainer title="ACCOUNT DATA">
<SettingsItemContainer title={lang.accountData.title}>
<SettingsItem
icon="person"
title="ACCOUNT NAME"
title={lang.accountData.accountName}
value="max_mustermann"
/>
<SettingsItem
icon="person"
title="USERNAME"
title={lang.accountData.username}
value="Max Mustermann"
onPress={() => navigation.navigate('UpdateUsername')}
/>
<SettingsItem
icon="phone-iphone"
title="PHONE NUMBER"
title={lang.accountData.phoneNumber}
value="+49 1510 21334143"
/>
</SettingsItemContainer>
<SettingsItemContainer title="CHANGE PASSWORD">
<SettingsItemContainer title={lang.changePassword.title}>
<SettingsItem
icon="lock"
title="PASSWORD"
value="Tap to change"
title={lang.changePassword.password}
value={lang.changePassword.tapToChange}
onPress={() => navigation.navigate('UpdatePassword')}
/>
</SettingsItemContainer>
<SettingsItemContainer title="MORE INFO">
<SettingsItemContainer title={lang.moreInfo.title}>
<SettingsItem
icon="help"
title="Help"
title={lang.moreInfo.help}
onPress={() => navigation.navigate('Help')}
/>
<SettingsItem
icon="info"
title="About"
title={lang.moreInfo.about}
onPress={() => navigation.navigate('About')}
/>
<SettingsItem
icon="logout"
title="Logout"
title={lang.moreInfo.logout}
onPress={() =>
rootNavigation.navigate('Registration', {screen: 'LoginPreview'})
}
@ -195,7 +199,7 @@ function SettingsItem({icon, title, value, onPress}: SettingsItemProps) {
<View>
{value ? (
<>
<Text>{title}</Text>
<Text style={{fontSize: 14}}>{title}</Text>
<Text style={{color: '#fff', fontWeight: 'bold', fontSize: 16}}>
{value}
</Text>
@ -212,10 +216,14 @@ function SettingsItem({icon, title, value, onPress}: SettingsItemProps) {
}
export function UpdateUsername() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.profile.settings,
);
const navigation = useNavigation<ProfileScreenNavigationProp>();
// TODO: get username from current logged in user
const username = 'Max Mustermann';
const navigation = useNavigation<ProfileScreenNavigationProp>();
const [newUsername, setNewUsername] = useState(username);
useEffect(() => {
@ -237,19 +245,22 @@ export function UpdateUsername() {
<MyScreenContainer style={{paddingTop: 20}}>
<MyIconInput
iconName="person"
text="USERNAME"
text={lang.changeUsername.username}
value={newUsername}
onChangeText={text => {
setNewUsername(text);
}}
/>
<Text style={{marginTop: 12}}>You can use a-z, 0-9 and underscores.</Text>
<Text>Minimum length is 5 characters.</Text>
<Text style={{marginTop: 12}}>{lang.changeUsername.info}</Text>
<Text>{lang.changeUsername.info2}</Text>
</MyScreenContainer>
);
}
export function UpdatePassword() {
const lang = useSelector(
(state: RootState) => state.appVariables.lang.profile.settings.changePassword,
);
const navigation = useNavigation<RootScreenNavigationProp>();
const [currentPassword, setCurrentPassword] = useState('');
@ -288,7 +299,7 @@ export function UpdatePassword() {
}}>
<MyIconInput
iconName="lock"
text="CURRENT PASSWORD"
text={lang.currentPassword}
secureTextEntry={true}
value={currentPassword}
onChangeText={text => setCurrentPassword(text)}
@ -296,7 +307,7 @@ export function UpdatePassword() {
/>
<MyIconInput
iconName="lock"
text="NEW PASSWORD"
text={lang.newPassword}
secureTextEntry={true}
value={newPassword}
onChangeText={text => setNewPassword(text)}
@ -304,7 +315,7 @@ export function UpdatePassword() {
/>
<MyIconInput
iconName="lock"
text="REPEAT NEW PASSWORD"
text={lang.repeatNewPassword}
secureTextEntry={true}
value={repeatNewPassword}
onChangeText={text => setRepeatNewPassword(text)}
@ -313,8 +324,9 @@ export function UpdatePassword() {
</View>
<Text style={{marginTop: 12}}>
You will be logged out after changing your password.
{lang.info}
</Text>
<Text>{lang.info2}</Text>
</MyScreenContainer>
);
}

Some files were not shown because too many files have changed in this diff Show More