react-native-boiler-plate-vijay 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/package.json +32 -0
  4. package/template/.husky/pre-commit +1 -0
  5. package/template/Gemfile +16 -0
  6. package/template/README.md +272 -0
  7. package/template/__tests__/App.test.tsx +13 -0
  8. package/template/_eslintrc.js +4 -0
  9. package/template/_gitignore +71 -0
  10. package/template/_prettierrc.js +7 -0
  11. package/template/_watchmanconfig +1 -0
  12. package/template/android/app/build.gradle +119 -0
  13. package/template/android/app/debug.keystore +0 -0
  14. package/template/android/app/proguard-rules.pro +10 -0
  15. package/template/android/app/src/main/AndroidManifest.xml +28 -0
  16. package/template/android/app/src/main/assets/custom/index.ts +12 -0
  17. package/template/android/app/src/main/assets/fonts/Poppins-Black.ttf +0 -0
  18. package/template/android/app/src/main/assets/fonts/Poppins-Bold.ttf +0 -0
  19. package/template/android/app/src/main/assets/fonts/Poppins-ExtraBold.ttf +0 -0
  20. package/template/android/app/src/main/assets/fonts/Poppins-ExtraLight.ttf +0 -0
  21. package/template/android/app/src/main/assets/fonts/Poppins-Italic.ttf +0 -0
  22. package/template/android/app/src/main/assets/fonts/Poppins-Light.ttf +0 -0
  23. package/template/android/app/src/main/assets/fonts/Poppins-Medium.ttf +0 -0
  24. package/template/android/app/src/main/assets/fonts/Poppins-Regular.ttf +0 -0
  25. package/template/android/app/src/main/assets/fonts/Poppins-SemiBold.ttf +0 -0
  26. package/template/android/app/src/main/assets/fonts/Poppins-Thin.ttf +0 -0
  27. package/template/android/app/src/main/java/com/helloworld/MainActivity.kt +29 -0
  28. package/template/android/app/src/main/java/com/helloworld/MainApplication.kt +27 -0
  29. package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  30. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  31. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  32. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  33. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  34. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  35. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  36. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  37. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  38. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  39. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  40. package/template/android/app/src/main/res/values/strings.xml +3 -0
  41. package/template/android/app/src/main/res/values/styles.xml +9 -0
  42. package/template/android/build.gradle +31 -0
  43. package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  44. package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  45. package/template/android/gradle.properties +44 -0
  46. package/template/android/gradlew +251 -0
  47. package/template/android/gradlew.bat +99 -0
  48. package/template/android/settings.gradle +6 -0
  49. package/template/app.json +4 -0
  50. package/template/babel.config.js +38 -0
  51. package/template/index.js +9 -0
  52. package/template/ios/.xcode.env +11 -0
  53. package/template/ios/HelloWorld/AppDelegate.swift +48 -0
  54. package/template/ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  55. package/template/ios/HelloWorld/Images.xcassets/Contents.json +6 -0
  56. package/template/ios/HelloWorld/Info.plist +73 -0
  57. package/template/ios/HelloWorld/LaunchScreen.storyboard +47 -0
  58. package/template/ios/HelloWorld/PrivacyInfo.xcprivacy +45 -0
  59. package/template/ios/HelloWorld.xcodeproj/project.pbxproj +547 -0
  60. package/template/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme +88 -0
  61. package/template/ios/HelloWorld.xcworkspace/contents.xcworkspacedata +10 -0
  62. package/template/ios/Podfile +34 -0
  63. package/template/jest.config.js +3 -0
  64. package/template/metro.config.js +24 -0
  65. package/template/package.json +83 -0
  66. package/template/react-native.config.js +3 -0
  67. package/template/src/api/axiosInstance.ts +75 -0
  68. package/template/src/api/index.ts +13 -0
  69. package/template/src/appRedux/index.ts +32 -0
  70. package/template/src/appRedux/modules/LoaderSlice.ts +23 -0
  71. package/template/src/appRedux/modules/ProfileSlice.ts +56 -0
  72. package/template/src/assets/fonts/Poppins-Black.ttf +0 -0
  73. package/template/src/assets/fonts/Poppins-Bold.ttf +0 -0
  74. package/template/src/assets/fonts/Poppins-ExtraBold.ttf +0 -0
  75. package/template/src/assets/fonts/Poppins-ExtraLight.ttf +0 -0
  76. package/template/src/assets/fonts/Poppins-Italic.ttf +0 -0
  77. package/template/src/assets/fonts/Poppins-Light.ttf +0 -0
  78. package/template/src/assets/fonts/Poppins-Medium.ttf +0 -0
  79. package/template/src/assets/fonts/Poppins-Regular.ttf +0 -0
  80. package/template/src/assets/fonts/Poppins-SemiBold.ttf +0 -0
  81. package/template/src/assets/fonts/Poppins-Thin.ttf +0 -0
  82. package/template/src/assets/fonts/index.ts +12 -0
  83. package/template/src/assets/images/IC_Home_Active.svg +3 -0
  84. package/template/src/assets/images/IC_Home_UnActive.svg +4 -0
  85. package/template/src/assets/images/IC_Setting_Active.svg +3 -0
  86. package/template/src/assets/images/IC_Setting_UnActive.svg +3 -0
  87. package/template/src/assets/images/index.ts +11 -0
  88. package/template/src/assets/index.ts +1 -0
  89. package/template/src/common/asyncServices.ts +41 -0
  90. package/template/src/common/constant.ts +18 -0
  91. package/template/src/common/helperFunctions.ts +70 -0
  92. package/template/src/common/index.ts +3 -0
  93. package/template/src/components/NoInternetModalPopUp.tsx +71 -0
  94. package/template/src/components/PrimaryButton.tsx +74 -0
  95. package/template/src/components/PrimaryFlashMessage.tsx +122 -0
  96. package/template/src/components/PrimaryLoader.tsx +37 -0
  97. package/template/src/components/PrimaryScrollView.tsx +97 -0
  98. package/template/src/components/PrimaryText.tsx +25 -0
  99. package/template/src/components/index.ts +15 -0
  100. package/template/src/hooks/index.ts +0 -0
  101. package/template/src/i18n/en.json +30 -0
  102. package/template/src/i18n/es.json +30 -0
  103. package/template/src/i18n/i18n.ts +37 -0
  104. package/template/src/i18n/index.ts +4 -0
  105. package/template/src/index.tsx +25 -0
  106. package/template/src/navigation/AppStack.tsx +22 -0
  107. package/template/src/navigation/AuthStack.tsx +12 -0
  108. package/template/src/navigation/MainNavigation.tsx +35 -0
  109. package/template/src/navigation/RootNavigationRef.ts +46 -0
  110. package/template/src/navigation/TabNavigator.tsx +65 -0
  111. package/template/src/navigation/index.ts +5 -0
  112. package/template/src/screens/Home/index.tsx +51 -0
  113. package/template/src/screens/Login/index.tsx +48 -0
  114. package/template/src/screens/ModalScreen/index.tsx +56 -0
  115. package/template/src/screens/Profile/index.tsx +68 -0
  116. package/template/src/screens/index.ts +5 -0
  117. package/template/src/services/index.ts +0 -0
  118. package/template/src/static/index.ts +0 -0
  119. package/template/src/theme/colors.ts +7 -0
  120. package/template/src/theme/dimensions.ts +35 -0
  121. package/template/src/theme/index.ts +3 -0
  122. package/template/src/theme/styles.ts +7 -0
  123. package/template/src/types/declarations.d.ts +6 -0
  124. package/template/src/types/index.ts +64 -0
  125. package/template/tsconfig.json +27 -0
  126. package/template.config.js +10 -0
@@ -0,0 +1,74 @@
1
+ import React, {FC} from 'react';
2
+ import {
3
+ ActivityIndicator,
4
+ StyleProp,
5
+ StyleSheet,
6
+ TextStyle,
7
+ TouchableOpacity,
8
+ TouchableOpacityProps,
9
+ } from 'react-native';
10
+ import {colors, perfectSize} from '@theme';
11
+ import PrimaryText from './PrimaryText';
12
+ import {fonts} from '@fonts';
13
+
14
+ interface PrimaryButtonProps extends TouchableOpacityProps {
15
+ label: string;
16
+ labelStyle?: StyleProp<TextStyle>;
17
+ loading?: boolean;
18
+ }
19
+
20
+ const PrimaryButton: FC<PrimaryButtonProps> = ({
21
+ label,
22
+ labelStyle,
23
+ loading = false,
24
+ disabled,
25
+ style,
26
+ ...rest
27
+ }) => {
28
+ const isDisabled = disabled || loading;
29
+
30
+ return (
31
+ <TouchableOpacity
32
+ style={[styles.container, style]}
33
+ activeOpacity={0.6}
34
+ disabled={isDisabled}
35
+ {...rest}>
36
+ <PrimaryText
37
+ style={[
38
+ styles.label,
39
+ labelStyle,
40
+ loading && {
41
+ opacity: 0,
42
+ },
43
+ ]}>
44
+ {label}
45
+ </PrimaryText>
46
+
47
+ {loading && (
48
+ <ActivityIndicator
49
+ color={colors.white}
50
+ size={'small'}
51
+ style={{position: 'absolute'}}
52
+ />
53
+ )}
54
+ </TouchableOpacity>
55
+ );
56
+ };
57
+
58
+ export default PrimaryButton;
59
+
60
+ const styles = StyleSheet.create({
61
+ container: {
62
+ height: perfectSize(40),
63
+ alignItems: 'center',
64
+ justifyContent: 'center',
65
+ borderRadius: perfectSize(8),
66
+ backgroundColor: colors.primary,
67
+ paddingHorizontal: perfectSize(20),
68
+ },
69
+ label: {
70
+ fontSize: perfectSize(14),
71
+ fontFamily: fonts.semiBold,
72
+ color: colors.white,
73
+ },
74
+ });
@@ -0,0 +1,122 @@
1
+ import React, {FC, forwardRef} from 'react';
2
+ import {View, StyleSheet, Animated} from 'react-native';
3
+ import FlashMessage, {FlashMessageProps} from 'react-native-flash-message';
4
+ import {colors, perfectSize} from '@theme';
5
+ import {useSafeAreaInsets} from 'react-native-safe-area-context';
6
+ import {prettyPrint} from '@common';
7
+ import PrimaryText from './PrimaryText';
8
+ import {fonts} from '@fonts';
9
+
10
+ const TYPE_CONFIG: Record<string, {bg: string; accent: string; icon: string}> =
11
+ {
12
+ success: {bg: '#1A2E22', accent: '#34C759', icon: '✓'},
13
+ danger: {bg: '#2E1A1A', accent: '#FF3B30', icon: '✕'},
14
+ warning: {bg: '#2E2A1A', accent: '#FF9500', icon: '⚠'},
15
+ info: {bg: '#1A1E2E', accent: '#007AFF', icon: 'ℹ'},
16
+ default: {bg: '#1C1C1E', accent: '#8E8E93', icon: '•'},
17
+ };
18
+
19
+ const FlashMessageComponent: FC<{message: any}> = ({message}) => {
20
+ prettyPrint({message});
21
+ const type = message?.type ?? 'default';
22
+ const {bg, accent, icon} = TYPE_CONFIG[type] ?? TYPE_CONFIG.default;
23
+ const {top, bottom} = useSafeAreaInsets();
24
+ return (
25
+ <Animated.View
26
+ style={[
27
+ styles.container,
28
+ {
29
+ marginTop: top + perfectSize(12),
30
+ marginBottom: bottom + perfectSize(12),
31
+ backgroundColor: bg,
32
+ opacity: message?.animationValue ?? 1,
33
+ },
34
+ ]}>
35
+ <View style={[styles.accent, {backgroundColor: accent}]} />
36
+ <View style={[styles.iconWrap, {backgroundColor: accent + '30'}]}>
37
+ <PrimaryText style={[styles.icon, {color: accent}]}>{icon}</PrimaryText>
38
+ </View>
39
+ <View style={styles.textWrap}>
40
+ {!!message?.message && (
41
+ <PrimaryText style={styles.title}>{message.message}</PrimaryText>
42
+ )}
43
+ {!!message?.description && (
44
+ <PrimaryText style={styles.description}>
45
+ {message.description}
46
+ </PrimaryText>
47
+ )}
48
+ </View>
49
+ </Animated.View>
50
+ );
51
+ };
52
+
53
+ const PrimaryFlashMessage = forwardRef<
54
+ FlashMessage,
55
+ Partial<FlashMessageProps>
56
+ >((props, ref) => (
57
+ <FlashMessage
58
+ ref={ref}
59
+ position="top"
60
+ duration={3000}
61
+ MessageComponent={FlashMessageComponent}
62
+ transitionConfig={animationValue => ({
63
+ transform: [],
64
+ opacity: animationValue.interpolate({
65
+ inputRange: [0, 1],
66
+ outputRange: [0, 1],
67
+ }),
68
+ })}
69
+ {...props}
70
+ />
71
+ ));
72
+
73
+ export default PrimaryFlashMessage;
74
+
75
+ const styles = StyleSheet.create({
76
+ container: {
77
+ flexDirection: 'row',
78
+ alignItems: 'center',
79
+ marginHorizontal: perfectSize(16),
80
+ marginTop: perfectSize(12),
81
+ borderRadius: perfectSize(16),
82
+ paddingVertical: perfectSize(14),
83
+ paddingRight: perfectSize(16),
84
+ overflow: 'hidden',
85
+ shadowColor: colors.black,
86
+ shadowOffset: {width: 0, height: perfectSize(6)},
87
+ shadowOpacity: 0.3,
88
+ shadowRadius: perfectSize(10),
89
+ },
90
+ accent: {
91
+ width: perfectSize(4),
92
+ alignSelf: 'stretch',
93
+ borderRadius: perfectSize(4),
94
+ marginRight: perfectSize(12),
95
+ },
96
+ iconWrap: {
97
+ width: perfectSize(36),
98
+ height: perfectSize(36),
99
+ borderRadius: perfectSize(10),
100
+ justifyContent: 'center',
101
+ alignItems: 'center',
102
+ marginRight: perfectSize(12),
103
+ },
104
+ icon: {
105
+ fontSize: perfectSize(16),
106
+ fontWeight: '700',
107
+ },
108
+ textWrap: {
109
+ flex: 1,
110
+ },
111
+ title: {
112
+ color: colors.white,
113
+ fontSize: perfectSize(14),
114
+ fontFamily: fonts.semiBold,
115
+ },
116
+ description: {
117
+ color: '#AEAEB2',
118
+ fontSize: perfectSize(12),
119
+ fontFamily: fonts.primary,
120
+ marginTop: perfectSize(2),
121
+ },
122
+ });
@@ -0,0 +1,37 @@
1
+ import React, {FC} from 'react';
2
+ import {ActivityIndicator, StyleSheet, View} from 'react-native';
3
+ import {colors, perfectSize} from '@theme';
4
+ import {useAppSelector} from '@appRedux';
5
+
6
+ interface PrimaryLoaderProps {
7
+ isLocalLoading?: boolean;
8
+ }
9
+
10
+ const PrimaryLoader: FC<PrimaryLoaderProps> = ({isLocalLoading = false}) => {
11
+ const {isLoading} = useAppSelector(state => state.loader);
12
+ const isVisible = isLocalLoading ?? isLoading;
13
+ return isVisible ? (
14
+ <View style={[styles.container, StyleSheet.absoluteFill]}>
15
+ <View style={styles.whiteBox}>
16
+ <ActivityIndicator color={colors.primary} size={perfectSize(40)} />
17
+ </View>
18
+ </View>
19
+ ) : null;
20
+ };
21
+
22
+ const styles = StyleSheet.create({
23
+ container: {
24
+ alignItems: 'center',
25
+ justifyContent: 'center',
26
+ backgroundColor: colors.black60,
27
+ },
28
+ whiteBox: {
29
+ aspectRatio: 1,
30
+ backgroundColor: colors.white,
31
+ height: perfectSize(80),
32
+ alignItems: 'center',
33
+ justifyContent: 'center',
34
+ borderRadius: perfectSize(5),
35
+ },
36
+ });
37
+ export default PrimaryLoader;
@@ -0,0 +1,97 @@
1
+ import {perfectSize} from '@theme';
2
+ import React, {
3
+ ReactNode,
4
+ useState,
5
+ useEffect,
6
+ useRef,
7
+ forwardRef,
8
+ useImperativeHandle,
9
+ } from 'react';
10
+ import {Keyboard, Platform, TextInput, ScrollViewProps} from 'react-native';
11
+ import {ScrollView} from 'react-native-gesture-handler';
12
+
13
+ interface PrimaryScrollViewProps extends ScrollViewProps {
14
+ children?: ReactNode;
15
+ }
16
+
17
+ export interface PrimaryScrollViewHandle {
18
+ scrollTo: (options: {y: number; animated?: boolean}) => void;
19
+ scrollToEnd: (options: {animated?: boolean}) => void;
20
+ }
21
+
22
+ const PrimaryScrollView = forwardRef<
23
+ PrimaryScrollViewHandle,
24
+ PrimaryScrollViewProps
25
+ >(({children, contentContainerStyle, ...rest}, ref) => {
26
+ const [keyboardHeight, setKeyboardHeight] = useState(0);
27
+ const scrollViewRef = useRef<ScrollView>(null);
28
+
29
+ useEffect(() => {
30
+ const showSub = Keyboard.addListener(
31
+ Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow',
32
+ e => {
33
+ setKeyboardHeight(e.endCoordinates.height);
34
+
35
+ // Auto-scroll logic: scroll to the focused input field
36
+ setTimeout(() => {
37
+ const currentlyFocusedInput = TextInput.State.currentlyFocusedInput();
38
+ if (currentlyFocusedInput && scrollViewRef.current) {
39
+ currentlyFocusedInput.measureLayout(
40
+ scrollViewRef.current as any,
41
+ (x, y, width, height) => {
42
+ // Scroll so the input top sits with breathing room above it.
43
+ // Adjust the padding value (height - perfectSize(12)) to control the gap above the focused input.
44
+ scrollViewRef.current?.scrollTo({
45
+ y: Math.max(0, y - height - perfectSize(12)),
46
+ animated: true,
47
+ });
48
+ },
49
+ () => {},
50
+ );
51
+ }
52
+ }, 100);
53
+ },
54
+ );
55
+
56
+ const hideSub = Keyboard.addListener(
57
+ Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide',
58
+ () => {
59
+ setKeyboardHeight(0);
60
+ },
61
+ );
62
+
63
+ return () => {
64
+ showSub.remove();
65
+ hideSub.remove();
66
+ };
67
+ }, []);
68
+
69
+ useImperativeHandle(ref, () => ({
70
+ scrollTo: options => scrollViewRef.current?.scrollTo(options),
71
+ scrollToEnd: options => scrollViewRef.current?.scrollToEnd(options),
72
+ }));
73
+
74
+ return (
75
+ <ScrollView
76
+ showsHorizontalScrollIndicator={false}
77
+ showsVerticalScrollIndicator={false}
78
+ keyboardShouldPersistTaps={'handled'}
79
+ ref={scrollViewRef}
80
+ contentContainerStyle={[
81
+ contentContainerStyle,
82
+ keyboardHeight > 0
83
+ ? {
84
+ paddingBottom: keyboardHeight,
85
+ justifyContent: 'flex-start',
86
+ }
87
+ : undefined,
88
+ ]}
89
+ {...rest}>
90
+ {children}
91
+ </ScrollView>
92
+ );
93
+ });
94
+
95
+ PrimaryScrollView.displayName = 'PrimaryScrollView';
96
+
97
+ export default PrimaryScrollView;
@@ -0,0 +1,25 @@
1
+ import React, {FC} from 'react';
2
+ import {StyleSheet, Text, TextProps} from 'react-native';
3
+ import {colors, perfectSize} from '@theme';
4
+ import {fonts} from '@assets';
5
+
6
+ interface PrimaryTextProps extends TextProps {}
7
+
8
+ const PrimaryText: FC<PrimaryTextProps> = ({style, children, ...props}) => {
9
+ return (
10
+ <Text style={[styles.text, style]} {...props}>
11
+ {children}
12
+ </Text>
13
+ );
14
+ };
15
+
16
+ export default PrimaryText;
17
+
18
+ const styles = StyleSheet.create({
19
+ text: {
20
+ includeFontPadding: false,
21
+ color: colors.black,
22
+ fontFamily: fonts.primary,
23
+ fontSize: perfectSize(16),
24
+ },
25
+ });
@@ -0,0 +1,15 @@
1
+ import PrimaryLoader from './PrimaryLoader';
2
+ import PrimaryFlashMessage from './PrimaryFlashMessage';
3
+ import PrimaryButton from './PrimaryButton';
4
+ import PrimaryText from './PrimaryText';
5
+ import NoInternetModalPopUp from './NoInternetModalPopUp';
6
+ import PrimaryScrollView from './PrimaryScrollView';
7
+
8
+ export {
9
+ PrimaryLoader,
10
+ PrimaryFlashMessage,
11
+ PrimaryButton,
12
+ PrimaryText,
13
+ PrimaryScrollView,
14
+ NoInternetModalPopUp,
15
+ };
File without changes
@@ -0,0 +1,30 @@
1
+ {
2
+ "loginScreen": {
3
+ "loginScreen": "LogIn Screen",
4
+ "login": "Login",
5
+ "showErrorMessage": "Show Error Message"
6
+ },
7
+ "modalScreen": {
8
+ "modalScreen": "Modal Screen",
9
+ "modalDescription": "This is a modal screen. Tap outside to dismiss."
10
+ },
11
+ "homeScreen": {
12
+ "homeScreen": "Home Screen",
13
+ "openModalScreen": "Open Modal Screen",
14
+ "showSuccessMessage": "Show Success Message"
15
+ },
16
+ "profileScreen": {
17
+ "profileScreen": "Profile Screen",
18
+ "logout": "Logout",
19
+ "changeLanguage": "Change Language",
20
+ "cancel": "Cancel"
21
+ },
22
+ "validations": {
23
+ "testError": "This is error message",
24
+ "testSuccess": "This is success message"
25
+ },
26
+ "languages": {
27
+ "en": "English",
28
+ "es": "Spanish"
29
+ }
30
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "loginScreen": {
3
+ "loginScreen": "Pantalla de Inicio de Sesión",
4
+ "login": "Iniciar sesión",
5
+ "showErrorMessage": "Mostrar mensaje de error"
6
+ },
7
+ "modalScreen": {
8
+ "modalScreen": "Pantalla Modal",
9
+ "modalDescription": "Esta es una pantalla modal. Toque afuera para cerrarla."
10
+ },
11
+ "homeScreen": {
12
+ "homeScreen": "Pantalla de Inicio",
13
+ "openModalScreen": "Abrir pantalla modal",
14
+ "showSuccessMessage": "Mostrar mensaje de éxito"
15
+ },
16
+ "profileScreen": {
17
+ "profileScreen": "Pantalla de Perfil",
18
+ "logout": "Cerrar sesión",
19
+ "changeLanguage": "Cambiar idioma",
20
+ "cancel": "Cancelar"
21
+ },
22
+ "validations": {
23
+ "testError": "Este es un mensaje de error",
24
+ "testSuccess": "Este es un mensaje de éxito"
25
+ },
26
+ "languages": {
27
+ "en": "Inglés",
28
+ "es": "Español"
29
+ }
30
+ }
@@ -0,0 +1,37 @@
1
+ import i18n from 'i18next';
2
+ import {initReactI18next} from 'react-i18next';
3
+ import en from './en.json';
4
+ import es from './es.json';
5
+ import moment from 'moment';
6
+
7
+ require('moment/locale/es');
8
+
9
+ import {ASYNC_KEY, setAsyncData} from '@common';
10
+
11
+ i18n.use(initReactI18next).init({
12
+ compatibilityJSON: 'v4',
13
+ resources: {
14
+ en: {translation: en},
15
+ es: {translation: es},
16
+ },
17
+ lng: 'en',
18
+ fallbackLng: 'en',
19
+ interpolation: {
20
+ escapeValue: false,
21
+ },
22
+ });
23
+
24
+ // Set moment locale based on i18n language
25
+ i18n.on('languageChanged', lng => {
26
+ moment.locale(lng);
27
+ });
28
+
29
+ // Set initial moment locale
30
+ moment.locale(i18n.language);
31
+
32
+ export const onChangeLanguage = async (lang: string) => {
33
+ await i18n.changeLanguage(lang);
34
+ await setAsyncData(ASYNC_KEY.LANGUAGE, lang);
35
+ };
36
+
37
+ export default i18n;
@@ -0,0 +1,4 @@
1
+ import i18n from './i18n';
2
+
3
+ export * from './i18n';
4
+ export {i18n};
@@ -0,0 +1,25 @@
1
+ import React, {FC} from 'react';
2
+ import {MainNavigation} from '@navigation';
3
+ import {GestureHandlerRootView} from 'react-native-gesture-handler';
4
+ import {SafeAreaProvider} from 'react-native-safe-area-context';
5
+ import {CommonStyles} from '@theme';
6
+ import {PrimaryLoader, PrimaryFlashMessage} from '@components';
7
+ import {Provider} from 'react-redux';
8
+ import store from '@appRedux';
9
+ import './i18n/i18n';
10
+
11
+ const App: FC = () => {
12
+ return (
13
+ <Provider store={store}>
14
+ <GestureHandlerRootView style={CommonStyles.flex1}>
15
+ <SafeAreaProvider>
16
+ <MainNavigation />
17
+ <PrimaryLoader />
18
+ <PrimaryFlashMessage />
19
+ </SafeAreaProvider>
20
+ </GestureHandlerRootView>
21
+ </Provider>
22
+ );
23
+ };
24
+
25
+ export default App;
@@ -0,0 +1,22 @@
1
+ import React, {FC} from 'react';
2
+ import {createNativeStackNavigator} from '@react-navigation/native-stack';
3
+ import {AppStackParamList} from '@types';
4
+ import {TabNavigation} from '@navigation';
5
+ import {ModalScreen} from '@screens';
6
+
7
+ const Stack = createNativeStackNavigator<AppStackParamList>();
8
+
9
+ export const AppStack: FC = () => (
10
+ <Stack.Navigator screenOptions={{headerShown: false, headerShadowVisible: false}}>
11
+ <Stack.Screen name="TabNavigation" component={TabNavigation} />
12
+ <Stack.Group
13
+ screenOptions={{
14
+ headerShown: false,
15
+ presentation: 'transparentModal',
16
+ gestureEnabled: true,
17
+ animation: 'slide_from_bottom',
18
+ }}>
19
+ <Stack.Screen name="ModalScreen" component={ModalScreen} />
20
+ </Stack.Group>
21
+ </Stack.Navigator>
22
+ );
@@ -0,0 +1,12 @@
1
+ import React, {FC} from 'react';
2
+ import {createNativeStackNavigator} from '@react-navigation/native-stack';
3
+ import {AuthStackParamList} from '@types';
4
+ import {LogIn} from '@screens';
5
+
6
+ const Stack = createNativeStackNavigator<AuthStackParamList>();
7
+
8
+ export const AuthStack: FC = () => (
9
+ <Stack.Navigator screenOptions={{headerShown: false}}>
10
+ <Stack.Screen name="LogIn" component={LogIn} />
11
+ </Stack.Navigator>
12
+ );
@@ -0,0 +1,35 @@
1
+ import React, {FC, useEffect, useState} from 'react';
2
+ import {NavigationContainer} from '@react-navigation/native';
3
+ import {dispatch, setLanguage, setUserData, useAppSelector} from '@appRedux';
4
+ import {ASYNC_KEY, getAsyncData} from '@common';
5
+ import {NoInternetModalPopUp, PrimaryLoader} from '@components';
6
+ import {AuthStack, AppStack, navigationRef} from '@navigation';
7
+
8
+ export const MainNavigation: FC = () => {
9
+ const {isLogIn} = useAppSelector(state => state.profile);
10
+ const [isLoading, setIsLoading] = useState<boolean>(true);
11
+
12
+ useEffect(() => {
13
+ getUser();
14
+ }, []);
15
+
16
+ const getUser = async () => {
17
+ const user = await getAsyncData(ASYNC_KEY.USER);
18
+ const language = await getAsyncData(ASYNC_KEY.LANGUAGE);
19
+ if (user) {
20
+ dispatch(setUserData(user));
21
+ }
22
+ if (language) {
23
+ dispatch(setLanguage(language));
24
+ }
25
+ setIsLoading(false);
26
+ };
27
+
28
+ return (
29
+ <NavigationContainer ref={navigationRef}>
30
+ {!isLoading && (isLogIn ? <AppStack /> : <AuthStack />)}
31
+ <PrimaryLoader isLocalLoading={isLoading} />
32
+ <NoInternetModalPopUp />
33
+ </NavigationContainer>
34
+ );
35
+ };
@@ -0,0 +1,46 @@
1
+ import {
2
+ createNavigationContainerRef,
3
+ NavigationAction,
4
+ PartialState,
5
+ NavigationState,
6
+ } from '@react-navigation/native';
7
+ import {AuthStackParamList, AppStackParamList} from '@types';
8
+
9
+ export type RootStackParamList = AuthStackParamList & AppStackParamList;
10
+
11
+ export const navigationRef = createNavigationContainerRef<RootStackParamList>();
12
+
13
+ export function navigate(
14
+ name: keyof RootStackParamList,
15
+ params?: RootStackParamList[keyof RootStackParamList],
16
+ ) {
17
+ if (navigationRef.isReady()) {
18
+ navigationRef.navigate(name as any, params as any);
19
+ }
20
+ }
21
+
22
+ export function goBack() {
23
+ if (navigationRef.isReady() && navigationRef.canGoBack()) {
24
+ navigationRef.goBack();
25
+ }
26
+ }
27
+
28
+ export function getCurrentRoute() {
29
+ if (navigationRef.isReady()) {
30
+ return navigationRef.getCurrentRoute()?.name;
31
+ }
32
+ }
33
+
34
+ export function resetRoot(
35
+ state?: PartialState<NavigationState> | NavigationState,
36
+ ) {
37
+ if (navigationRef.isReady()) {
38
+ navigationRef.resetRoot(state);
39
+ }
40
+ }
41
+
42
+ export function dispatch(action: NavigationAction) {
43
+ if (navigationRef.isReady()) {
44
+ navigationRef.dispatch(action);
45
+ }
46
+ }
@@ -0,0 +1,65 @@
1
+ import React, {FC} from 'react';
2
+ import {StyleSheet, View} from 'react-native';
3
+ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
4
+ import {AppStackScreenProps, TabScreenRouteProp} from '@types';
5
+ import {colors, perfectSize} from '@theme';
6
+ import {Home, Profile} from '@screens';
7
+ import {
8
+ IC_Home_Active,
9
+ IC_Home_UnActive,
10
+ IC_Setting_Active,
11
+ IC_Setting_UnActive,
12
+ } from '@images';
13
+
14
+ const Tabs = createBottomTabNavigator<TabScreenRouteProp>();
15
+
16
+ export const TabNavigation: FC<AppStackScreenProps<'TabNavigation'>> = () => {
17
+ const renderTabItem = (
18
+ focused: boolean,
19
+ TabFocusedIcon: any,
20
+ TabUnFocusedIcon: any,
21
+ ) => {
22
+ return focused ? (
23
+ <TabFocusedIcon height={perfectSize(24)} width={perfectSize(24)} />
24
+ ) : (
25
+ <TabUnFocusedIcon height={perfectSize(24)} width={perfectSize(24)} />
26
+ );
27
+ };
28
+
29
+ return (
30
+ <View style={styles.container}>
31
+ <Tabs.Navigator
32
+ id="TabNavigator"
33
+ screenOptions={{
34
+ headerShadowVisible: false,
35
+ headerShown: false,
36
+ }}>
37
+ <Tabs.Screen
38
+ name={'Home'}
39
+ component={Home}
40
+ options={{
41
+ tabBarLabel: () => false,
42
+ tabBarIcon: ({focused}) =>
43
+ renderTabItem(focused, IC_Home_Active, IC_Home_UnActive),
44
+ }}
45
+ />
46
+ <Tabs.Screen
47
+ name={'Profile'}
48
+ component={Profile}
49
+ options={{
50
+ tabBarLabel: () => false,
51
+ tabBarIcon: ({focused}) =>
52
+ renderTabItem(focused, IC_Setting_Active, IC_Setting_UnActive),
53
+ }}
54
+ />
55
+ </Tabs.Navigator>
56
+ </View>
57
+ );
58
+ };
59
+
60
+ const styles = StyleSheet.create({
61
+ container: {
62
+ flex: 1,
63
+ backgroundColor: colors.white,
64
+ },
65
+ });