new-react-native-boilerplate 0.0.0-stage → 1.0.1

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 (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +329 -2
  3. package/package.json +49 -4
  4. package/run.sh +36 -0
  5. package/setup.js +141 -0
  6. package/template/.bundle/config +2 -0
  7. package/template/.editorconfig +14 -0
  8. package/template/.eslintrc.js +49 -0
  9. package/template/.husky/commit-msg +4 -0
  10. package/template/.husky/pre-commit +1 -0
  11. package/template/.prettierrc.js +6 -0
  12. package/template/.watchmanconfig +1 -0
  13. package/template/Gemfile +17 -0
  14. package/template/Gemfile.lock +114 -0
  15. package/template/README.md +101 -0
  16. package/template/__tests__/App.test.tsx +13 -0
  17. package/template/__tests__/CustomTextInput.test.jsx +29 -0
  18. package/template/android/app/build.gradle +119 -0
  19. package/template/android/app/debug.keystore +0 -0
  20. package/template/android/app/proguard-rules.pro +10 -0
  21. package/template/android/app/src/main/AndroidManifest.xml +27 -0
  22. package/template/android/app/src/main/assets/fonts/Poppins-Bold.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/futura_book.otf +0 -0
  27. package/template/android/app/src/main/assets/fonts/futura_medium.otf +0 -0
  28. package/template/android/app/src/main/java/com/boilerplatereactnative/MainActivity.kt +22 -0
  29. package/template/android/app/src/main/java/com/boilerplatereactnative/MainApplication.kt +27 -0
  30. package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  31. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  32. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  33. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  34. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  35. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  36. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  37. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  38. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  39. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  40. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  41. package/template/android/app/src/main/res/values/strings.xml +3 -0
  42. package/template/android/app/src/main/res/values/styles.xml +9 -0
  43. package/template/android/build.gradle +21 -0
  44. package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  45. package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  46. package/template/android/gradle.properties +49 -0
  47. package/template/android/gradlew +248 -0
  48. package/template/android/gradlew.bat +98 -0
  49. package/template/android/link-assets-manifest.json +29 -0
  50. package/template/android/settings.gradle +6 -0
  51. package/template/app.json +4 -0
  52. package/template/babel.config.js +43 -0
  53. package/template/eslint.config.mjs +175 -0
  54. package/template/index.d.ts +1 -0
  55. package/template/index.js +10 -0
  56. package/template/ios/.xcode.env +11 -0
  57. package/template/ios/BoilerPlateReactNative/AppDelegate.swift +11 -0
  58. package/template/ios/BoilerPlateReactNative/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  59. package/template/ios/BoilerPlateReactNative/Images.xcassets/Contents.json +6 -0
  60. package/template/ios/BoilerPlateReactNative/Info.plist +102 -0
  61. package/template/ios/BoilerPlateReactNative/LaunchScreen.storyboard +47 -0
  62. package/template/ios/BoilerPlateReactNative/PrivacyInfo.xcprivacy +37 -0
  63. package/template/ios/BoilerPlateReactNative/SceneDelegate.swift +54 -0
  64. package/template/ios/BoilerPlateReactNative.xcodeproj/project.pbxproj +531 -0
  65. package/template/ios/BoilerPlateReactNative.xcodeproj/xcshareddata/xcschemes/BoilerPlateReactNative.xcscheme +88 -0
  66. package/template/ios/BoilerPlateReactNative.xcworkspace/contents.xcworkspacedata +10 -0
  67. package/template/ios/BoilerPlateReactNative.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  68. package/template/ios/Podfile +34 -0
  69. package/template/ios/Podfile.lock +2552 -0
  70. package/template/ios/link-assets-manifest.json +29 -0
  71. package/template/jest.config.js +13 -0
  72. package/template/jest.setup.js +30 -0
  73. package/template/metro.config.js +15 -0
  74. package/template/package.json +88 -0
  75. package/template/plugins/compile-js/_prompts.js +6 -0
  76. package/template/plugins/compile-js/index.js +9 -0
  77. package/template/plugins/compile-js/plugin.js +103 -0
  78. package/template/plugins/compile-js/tsconfig.build.json +20 -0
  79. package/template/plugins/index.js +46 -0
  80. package/template/plugins/printSuccess/_prompts.js +1 -0
  81. package/template/plugins/printSuccess/index.js +9 -0
  82. package/template/plugins/printSuccess/plugin.js +40 -0
  83. package/template/react-native.config.js +7 -0
  84. package/template/src/App.tsx +27 -0
  85. package/template/src/assets/fonts/Poppins-Bold.ttf +0 -0
  86. package/template/src/assets/fonts/Poppins-Medium.ttf +0 -0
  87. package/template/src/assets/fonts/Poppins-Regular.ttf +0 -0
  88. package/template/src/assets/fonts/Poppins-SemiBold.ttf +0 -0
  89. package/template/src/assets/fonts/futura_book.otf +0 -0
  90. package/template/src/assets/fonts/futura_medium.otf +0 -0
  91. package/template/src/assets/images/check.png +0 -0
  92. package/template/src/assets/images/check@2x.png +0 -0
  93. package/template/src/assets/images/check@3x.png +0 -0
  94. package/template/src/assets/images/email.png +0 -0
  95. package/template/src/assets/images/email@2x.png +0 -0
  96. package/template/src/assets/images/email@3x.png +0 -0
  97. package/template/src/assets/images/icBack.png +0 -0
  98. package/template/src/assets/images/icBack@2x.png +0 -0
  99. package/template/src/assets/images/icBack@3x.png +0 -0
  100. package/template/src/assets/images/icClose.png +0 -0
  101. package/template/src/assets/images/icClose@2x.png +0 -0
  102. package/template/src/assets/images/icClose@3x.png +0 -0
  103. package/template/src/assets/images/icComment.png +0 -0
  104. package/template/src/assets/images/icComment@2x.png +0 -0
  105. package/template/src/assets/images/icComment@3x.png +0 -0
  106. package/template/src/assets/images/icLike.png +0 -0
  107. package/template/src/assets/images/icLike@2x.png +0 -0
  108. package/template/src/assets/images/icLike@3x.png +0 -0
  109. package/template/src/assets/images/icSearch.png +0 -0
  110. package/template/src/assets/images/icSearch@2x.png +0 -0
  111. package/template/src/assets/images/icSearch@3x.png +0 -0
  112. package/template/src/assets/images/icSetting.png +0 -0
  113. package/template/src/assets/images/icSetting@2x.png +0 -0
  114. package/template/src/assets/images/icSetting@3x.png +0 -0
  115. package/template/src/assets/images/icShare.png +0 -0
  116. package/template/src/assets/images/icShare@2x.png +0 -0
  117. package/template/src/assets/images/icShare@3x.png +0 -0
  118. package/template/src/assets/images/line.png +0 -0
  119. package/template/src/assets/images/line@2x.png +0 -0
  120. package/template/src/assets/images/line@3x.png +0 -0
  121. package/template/src/assets/images/lock.png +0 -0
  122. package/template/src/assets/images/lock@2x.png +0 -0
  123. package/template/src/assets/images/lock@3x.png +0 -0
  124. package/template/src/assets/images/notification.png +0 -0
  125. package/template/src/assets/images/notification@2x.png +0 -0
  126. package/template/src/assets/images/notification@3x.png +0 -0
  127. package/template/src/assets/images/oct_dark.png +0 -0
  128. package/template/src/assets/images/oct_light.png +0 -0
  129. package/template/src/assets/images/onboard.png +0 -0
  130. package/template/src/assets/images/password_hide.png +0 -0
  131. package/template/src/assets/images/password_hide@2x.png +0 -0
  132. package/template/src/assets/images/password_hide@3x.png +0 -0
  133. package/template/src/assets/images/password_show.png +0 -0
  134. package/template/src/assets/images/password_show@2x.png +0 -0
  135. package/template/src/assets/images/password_show@3x.png +0 -0
  136. package/template/src/assets/images/right_arrow.png +0 -0
  137. package/template/src/assets/images/right_arrow@2x.png +0 -0
  138. package/template/src/assets/images/right_arrow@3x.png +0 -0
  139. package/template/src/assets/images/star.png +0 -0
  140. package/template/src/assets/images/star@2x.png +0 -0
  141. package/template/src/assets/images/star@3x.png +0 -0
  142. package/template/src/assets/images/uncheck.png +0 -0
  143. package/template/src/assets/images/uncheck@2x.png +0 -0
  144. package/template/src/assets/images/uncheck@3x.png +0 -0
  145. package/template/src/assets/images/user.png +0 -0
  146. package/template/src/assets/images/user@2x.png +0 -0
  147. package/template/src/assets/images/user@3x.png +0 -0
  148. package/template/src/components/atoms/ButtonContainer.tsx +52 -0
  149. package/template/src/components/atoms/ImageContainer.tsx +10 -0
  150. package/template/src/components/atoms/RemoteImage.tsx +8 -0
  151. package/template/src/components/atoms/RoundImageBorder.tsx +35 -0
  152. package/template/src/components/atoms/TextContainer.tsx +38 -0
  153. package/template/src/components/atoms/WrapperContainer.tsx +43 -0
  154. package/template/src/components/atoms/index.ts +6 -0
  155. package/template/src/components/molecules/AuthHeader.tsx +55 -0
  156. package/template/src/components/molecules/CustomTextInput.tsx +102 -0
  157. package/template/src/components/molecules/EmptyComp.tsx +16 -0
  158. package/template/src/components/molecules/ErrorComp.tsx +25 -0
  159. package/template/src/components/molecules/FooterView.tsx +41 -0
  160. package/template/src/components/molecules/HeaderComp.tsx +51 -0
  161. package/template/src/components/molecules/HomeHeader.tsx +63 -0
  162. package/template/src/components/molecules/HomeListHeader.tsx +48 -0
  163. package/template/src/components/molecules/HomeListItems.tsx +86 -0
  164. package/template/src/components/molecules/Loader.tsx +25 -0
  165. package/template/src/components/molecules/ModalSheet.tsx +146 -0
  166. package/template/src/components/molecules/RememberMe.tsx +58 -0
  167. package/template/src/components/molecules/SearchBar.tsx +46 -0
  168. package/template/src/components/molecules/index.ts +12 -0
  169. package/template/src/constants/apiConstant.ts +12 -0
  170. package/template/src/constants/fontFamily.ts +8 -0
  171. package/template/src/constants/imagePath.ts +25 -0
  172. package/template/src/constants/index.ts +3 -0
  173. package/template/src/constants/storageKeys.ts +5 -0
  174. package/template/src/models/ApiErrorResponse.ts +19 -0
  175. package/template/src/models/HomeData.ts +17 -0
  176. package/template/src/models/User.ts +11 -0
  177. package/template/src/navigations/AuthStack.tsx +20 -0
  178. package/template/src/navigations/MainStack.tsx +19 -0
  179. package/template/src/navigations/Routes.tsx +22 -0
  180. package/template/src/navigations/navigationProps.ts +8 -0
  181. package/template/src/redux/hooks.ts +10 -0
  182. package/template/src/redux/reducers/auth.ts +43 -0
  183. package/template/src/redux/reducers/common.ts +24 -0
  184. package/template/src/redux/reducers/index.ts +31 -0
  185. package/template/src/redux/reducers/product.ts +37 -0
  186. package/template/src/redux/reducers/settings.ts +55 -0
  187. package/template/src/redux/store.ts +19 -0
  188. package/template/src/redux/types.ts +6 -0
  189. package/template/src/screens/Home/Home.tsx +65 -0
  190. package/template/src/screens/Login/Login.tsx +35 -0
  191. package/template/src/screens/Login/components/LoginForm.tsx +88 -0
  192. package/template/src/screens/Login/hooks/useLogin.ts +38 -0
  193. package/template/src/screens/Login/styles.ts +17 -0
  194. package/template/src/screens/Login/types.ts +10 -0
  195. package/template/src/screens/Onboarding/Onboarding.tsx +87 -0
  196. package/template/src/screens/Onboarding/styles.ts +25 -0
  197. package/template/src/screens/PostDetails/PostDetails.tsx +168 -0
  198. package/template/src/screens/PostDetails/styles.ts +82 -0
  199. package/template/src/screens/Signup/Signup.tsx +32 -0
  200. package/template/src/screens/Signup/components/SignupForm.tsx +113 -0
  201. package/template/src/screens/Signup/hooks/useSignup.ts +38 -0
  202. package/template/src/screens/Signup/styles.ts +18 -0
  203. package/template/src/screens/Signup/type.ts +12 -0
  204. package/template/src/screens/index.ts +5 -0
  205. package/template/src/services/apiService.ts +144 -0
  206. package/template/src/services/authService.ts +79 -0
  207. package/template/src/services/productService.ts +45 -0
  208. package/template/src/services/statusHandler.ts +17 -0
  209. package/template/src/styles/breakpoints.ts +11 -0
  210. package/template/src/styles/themes.ts +45 -0
  211. package/template/src/styles/unistyles.ts +25 -0
  212. package/template/src/translations/ar.json +47 -0
  213. package/template/src/translations/en.json +47 -0
  214. package/template/src/translations/fr.json +47 -0
  215. package/template/src/translations/index.ts +32 -0
  216. package/template/src/typings/env.d.ts +5 -0
  217. package/template/src/typings/global.d.ts +3 -0
  218. package/template/src/utils/handleLocalStorage.ts +31 -0
  219. package/template/src/utils/i18nHelpers.ts +20 -0
  220. package/template/src/utils/index.ts +66 -0
  221. package/template/src/utils/scaling.ts +13 -0
  222. package/template/src/utils/themeHelpers.ts +10 -0
  223. package/template/src/utils/validationForm.ts +23 -0
  224. package/template/src/utils/validations.ts +69 -0
  225. package/template/tsconfig.json +22 -0
  226. package/template/yarn.lock +7728 -0
  227. package/template.config.js +6 -0
@@ -0,0 +1,37 @@
1
+ import type { HomeData, ProductsData } from "@models/HomeData";
2
+ import type { PayloadAction } from "@reduxjs/toolkit";
3
+ import { createSlice } from "@reduxjs/toolkit";
4
+
5
+ export interface ProductState {
6
+ error: Error | null;
7
+ isLoading: boolean;
8
+ productDetail: null | ProductsData,
9
+ productList: Array<HomeData>,
10
+ }
11
+
12
+ const initialState: ProductState = {
13
+ error: null,
14
+ isLoading: false,
15
+ productDetail: null,
16
+ productList: [],
17
+ };
18
+
19
+ const productSlice = createSlice({
20
+ initialState,
21
+ name: "auth",
22
+ reducers: {
23
+ hasError: (state, action: PayloadAction<Error>) => {
24
+ state.error = action.payload;
25
+ },
26
+ setProductDetail: (state, action: PayloadAction<ProductsData>) => {
27
+ state.productDetail = action.payload;
28
+ },
29
+ setProducts: (state, action: PayloadAction<Array<HomeData>>) => {
30
+ state.productList = action.payload;
31
+ },
32
+ },
33
+ });
34
+
35
+ export const { hasError, setProductDetail, setProducts } = productSlice.actions;
36
+
37
+ export default productSlice.reducer;
@@ -0,0 +1,55 @@
1
+ /* eslint-disable no-console */
2
+ import { createSlice } from "@reduxjs/toolkit";
3
+ import type { PayloadAction } from "@reduxjs/toolkit";
4
+ import type { UnistylesThemes } from "react-native-unistyles";
5
+
6
+ export interface LanguageInterface {
7
+ name: string;
8
+ sortName: string;
9
+ }
10
+
11
+ export interface ThemeInterface {
12
+ myTheme: keyof UnistylesThemes;
13
+ }
14
+
15
+ export interface SettingsState {
16
+ defaultLanguage: LanguageInterface;
17
+ defaultTheme: ThemeInterface;
18
+ languages: Array<LanguageInterface>;
19
+ }
20
+
21
+ const supportedLanguages: Array<LanguageInterface> = [
22
+ { name: "English", sortName: "en" },
23
+ { name: "Arabic", sortName: "ar" },
24
+ { name: "French", sortName: "fr" },
25
+ ];
26
+
27
+ const initialState: SettingsState = {
28
+ defaultLanguage: supportedLanguages[0],
29
+ defaultTheme: { myTheme: "light" },
30
+ languages: supportedLanguages,
31
+ };
32
+
33
+ const settingSlice = createSlice({
34
+ initialState,
35
+ name: "settings",
36
+ reducers: {
37
+ saveDefaultLanguage: (state, action: PayloadAction<LanguageInterface>) => {
38
+ const languageExists = state.languages.some(
39
+ (lang) => lang.sortName === action.payload.sortName,
40
+ );
41
+ if (languageExists) {
42
+ state.defaultLanguage = action.payload;
43
+ } else {
44
+ console.error("Language not found in the list.");
45
+ }
46
+ },
47
+ saveDefaultTheme: (state, action: PayloadAction<ThemeInterface>) => {
48
+ state.defaultTheme = action.payload;
49
+ },
50
+ },
51
+ });
52
+
53
+ export const { saveDefaultLanguage, saveDefaultTheme } = settingSlice.actions;
54
+
55
+ export default settingSlice.reducer;
@@ -0,0 +1,19 @@
1
+
2
+ import type { Action, ThunkAction} from "@reduxjs/toolkit";
3
+ import { configureStore } from "@reduxjs/toolkit";
4
+ import reducer from "./reducers";
5
+
6
+ const store = configureStore({
7
+ middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false }),
8
+ reducer,
9
+ });
10
+ export default store;
11
+
12
+ export type RootState = ReturnType<typeof store.getState>;
13
+ export type AppDispatch = typeof store.dispatch;
14
+ export type AppThunk<ReturnType = void> = ThunkAction<
15
+ ReturnType,
16
+ RootState,
17
+ unknown,
18
+ Action<string>
19
+ >;
@@ -0,0 +1,6 @@
1
+
2
+ export default {
3
+ CLEAR_REDUX_STATE: "CLEAR_REDUX_STATE",
4
+ IS_FIRST_TIME: "IS_FIRST_TIME",
5
+ IS_SKIP: "IS_SKIP",
6
+ };
@@ -0,0 +1,65 @@
1
+ import {WrapperContainer} from '@components/atoms';
2
+ import EmptyComp from '@components/molecules/EmptyComp';
3
+ import HomeHeader from '@components/molecules/HomeHeader';
4
+ import HomeListHeader from '@components/molecules/HomeListHeader';
5
+ import HomeListItems from '@components/molecules/HomeListItems';
6
+ import type {ModalSheetRef} from '@components/molecules/ModalSheet';
7
+ import ModalSheet from '@components/molecules/ModalSheet';
8
+ import constants from '@constants/index';
9
+ import type {HomeStackParamList} from '@navigations/MainStack';
10
+ import type {NavigationProp} from '@react-navigation/native';
11
+ import { useNavigation} from '@react-navigation/native';
12
+ import {useDispatch, useSelector} from '@redux/hooks';
13
+ import {moderateScale} from '@utils/scaling';
14
+ import React, {useCallback, useEffect, useRef} from 'react';
15
+ import {FlatList, View} from 'react-native';
16
+ import {getProduct} from 'src/services/productService';
17
+
18
+ const ItemSeparatorComponent = (): React.JSX.Element => (
19
+ <View style={{height: moderateScale(20)}} />
20
+ );
21
+
22
+ const Home = (): React.JSX.Element => {
23
+ // Navigation state variables
24
+ const navigation = useNavigation<NavigationProp<HomeStackParamList>>();
25
+ const modalSheetRef = useRef<ModalSheetRef>(null);
26
+
27
+ // Redux global variables
28
+ const dispatch = useDispatch();
29
+ const isLoading = useSelector(state => state.common.isLoading);
30
+ const productList = useSelector(state => state.product.productList);
31
+
32
+ // Callbacks
33
+ const handleToggleSheet = useCallback(() => {
34
+ if (modalSheetRef.current) {
35
+ modalSheetRef.current.toggleSheet();
36
+ }
37
+ }, []);
38
+
39
+ // Effects
40
+ useEffect(() => {
41
+ dispatch(getProduct(constants.DATA_LIMIT));
42
+ }, [dispatch]);
43
+
44
+ // Renders
45
+ return (
46
+ <WrapperContainer>
47
+ <View style={{marginHorizontal: moderateScale(20)}}>
48
+ <HomeHeader onPress={handleToggleSheet} title="BLOGS_POT" />
49
+ </View>
50
+ <FlatList
51
+ data={productList}
52
+ ItemSeparatorComponent={ItemSeparatorComponent}
53
+ keyExtractor={(item, index) => String(item?.id || index)}
54
+ ListEmptyComponent={<EmptyComp isError={true} isLoading={isLoading} />}
55
+ ListHeaderComponent={<HomeListHeader />}
56
+ renderItem={props => <HomeListItems {...props} navigation={navigation} />}
57
+ />
58
+
59
+ {/* Bottom Modal Sheet */}
60
+ <ModalSheet ref={modalSheetRef} />
61
+ </WrapperContainer>
62
+ );
63
+ };
64
+
65
+ export default Home;
@@ -0,0 +1,35 @@
1
+ import {WrapperContainer} from '@components/atoms';
2
+ import {AuthHeader, FooterView} from '@components/molecules';
3
+ import React from 'react';
4
+ import {Keyboard, TouchableWithoutFeedback, View} from 'react-native';
5
+ import {useStyles} from 'react-native-unistyles';
6
+ import LoginForm from './components/LoginForm';
7
+ import useLogin from './hooks/useLogin';
8
+ import stylesheet from './styles';
9
+
10
+ const Login = (): React.JSX.Element => {
11
+ // Login hidden action and effect implementation from the screen
12
+ const {onSignupPress} = useLogin();
13
+
14
+ // Stylesheet declaration
15
+ const {styles} = useStyles(stylesheet);
16
+
17
+ return (
18
+ <WrapperContainer>
19
+ <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
20
+ <View style={styles.container}>
21
+ <View>
22
+ <AuthHeader
23
+ description="WELCOME_BACK_PLEASE_ENTER_YOUR_DETAILS"
24
+ title="LOG_IN_TO_YOUR_ACCOUNT"
25
+ />
26
+ <LoginForm />
27
+ </View>
28
+ <FooterView linkPress={onSignupPress} linkText="SIGNUP" simpleText="DONT_HAVE_ACCOUNT" />
29
+ </View>
30
+ </TouchableWithoutFeedback>
31
+ </WrapperContainer>
32
+ );
33
+ };
34
+
35
+ export default Login;
@@ -0,0 +1,88 @@
1
+ import {ButtonContainer} from '@components/atoms';
2
+ import {CustomTextInput, RememberMe} from '@components/molecules';
3
+ import imagePath from '@constants/imagePath';
4
+ import {useDispatch, useSelector} from '@redux/hooks';
5
+ import {alertFunction} from '@utils/index';
6
+ import {verticalScale} from '@utils/scaling';
7
+ import validationForm from '@utils/validationForm';
8
+ import {Formik} from 'formik';
9
+ import React, {Fragment, useCallback, useRef, useState} from 'react';
10
+ import type {TextInputInstance} from 'react-native';
11
+ import {Keyboard} from 'react-native';
12
+ import {login} from 'src/services/authService';
13
+
14
+ const LoginForm = (): React.JSX.Element => {
15
+ // Reference variables
16
+ const loginFormRef = useRef(null);
17
+ const passwordInputRef = useRef<null | TextInputInstance>(null);
18
+
19
+ // Redux variables
20
+ const dispatch = useDispatch();
21
+ const isLoading = useSelector(state => state.common.isLoading);
22
+
23
+ // Local state declaration
24
+ const [secureTextEntry, setSecureTextEntry] = useState(true);
25
+
26
+ // Login button callback
27
+ const onLogin = useCallback(({password, username}: {password: string; username: string;}) => {
28
+ dispatch(login({password, username}));
29
+ }, [dispatch]);
30
+
31
+ return (
32
+ <Formik
33
+ initialValues={{
34
+ password: 'emilyspass',
35
+ username: 'emilys',
36
+ }}
37
+ innerRef={loginFormRef}
38
+ onSubmit={onLogin}
39
+ validationSchema={validationForm.login}>
40
+ {({...params}) => {
41
+ return (
42
+ <Fragment>
43
+ <CustomTextInput
44
+ autoCapitalize="none"
45
+ autoCorrect={false}
46
+ error={params.touched.username ? params.errors.username : null}
47
+ id="username"
48
+ label="USERNAME"
49
+ leftImage={imagePath.icUser}
50
+ onBlur={params.handleBlur('username')}
51
+ onChangeText={params.handleChange('username')}
52
+ onSubmitEditing={() => passwordInputRef.current?.focus()}
53
+ placeholder="ENTER_YOUR_USERNAME"
54
+ returnKeyType="next"
55
+ style={{marginBottom: verticalScale(16)}}
56
+ value={params.values.username}
57
+ />
58
+ <CustomTextInput
59
+ error={params.touched.password ? params.errors.password : null}
60
+ id="password"
61
+ label="PASSWORD"
62
+ leftImage={imagePath.icLock}
63
+ onBlur={params.handleBlur('password')}
64
+ onChangeText={params.handleChange('password')}
65
+ onPressRight={() => setSecureTextEntry(!secureTextEntry)}
66
+ onSubmitEditing={() => Keyboard.dismiss()}
67
+ placeholder="ENTER_YOUR_PASSWORD"
68
+ ref={passwordInputRef}
69
+ returnKeyType="done"
70
+ rightImage={secureTextEntry ? imagePath.icPassword : imagePath.icPasswordShow}
71
+ secureTextEntry={secureTextEntry}
72
+ style={{marginBottom: verticalScale(30)}}
73
+ value={params.values.password}
74
+ />
75
+ <RememberMe onPressForgot={() => alertFunction('Password', 'Forgot Password')} />
76
+ <ButtonContainer
77
+ isLoading={isLoading}
78
+ label="LOG_IN"
79
+ onPress={() => params.handleSubmit()}
80
+ />
81
+ </Fragment>
82
+ );
83
+ }}
84
+ </Formik>
85
+ );
86
+ };
87
+
88
+ export default LoginForm;
@@ -0,0 +1,38 @@
1
+ import type { AuthStackParamList } from '@navigations/AuthStack';
2
+ import type { NavigationProp} from '@react-navigation/native';
3
+ import { useNavigation } from '@react-navigation/native';
4
+ import { useDispatch, useSelector } from '@redux/hooks';
5
+ import { hasError } from '@redux/reducers/auth';
6
+ import { alertFunction } from '@utils/index';
7
+ import { useCallback, useEffect } from 'react';
8
+ import { Platform, ToastAndroid } from 'react-native';
9
+
10
+ // Custom Login hook
11
+ const useLogin = () => {
12
+ //Navigation variable declaration
13
+ const navigation = useNavigation<NavigationProp<AuthStackParamList>>();
14
+
15
+ // Redux variables
16
+ const dispatch = useDispatch();
17
+ const error = useSelector(state => state.auth.error);
18
+
19
+ const onSignupPress = useCallback(() => {
20
+ navigation.navigate('Signup');
21
+ }, [navigation]);
22
+
23
+ // Effects
24
+ useEffect(() => {
25
+ if (error?.message) {
26
+ if (Platform.OS === 'android') {
27
+ ToastAndroid.show(error.message, ToastAndroid.SHORT);
28
+ } else {
29
+ alertFunction(error.message, '');
30
+ }
31
+ dispatch(hasError(new Error('')));
32
+ }
33
+ }, [dispatch, error]);
34
+
35
+ return {onSignupPress};
36
+ };
37
+
38
+ export default useLogin;
@@ -0,0 +1,17 @@
1
+ import { moderateScale } from "@utils/scaling";
2
+ import { createStyleSheet } from "react-native-unistyles";
3
+
4
+ const stylesheet = createStyleSheet(() => ({
5
+ bottomView: {
6
+ alignItems: 'center',
7
+ alignSelf: 'center',
8
+ flexDirection: 'row',
9
+ },
10
+ container: {
11
+ flex: 1,
12
+ justifyContent: 'space-between',
13
+ marginHorizontal: moderateScale(16),
14
+ },
15
+ }));
16
+
17
+ export default stylesheet;
@@ -0,0 +1,10 @@
1
+ import type { User } from "@models/User";
2
+
3
+ export interface LoginRequestData {
4
+ password: string;
5
+ username: string;
6
+ }
7
+
8
+ export default interface LoginResponse {
9
+ data: User;
10
+ }
@@ -0,0 +1,87 @@
1
+ import {TextContainer, WrapperContainer} from '@components/atoms';
2
+ import fontFamily from '@constants/fontFamily';
3
+ import type {AuthStackParamList} from '@navigations/AuthStack';
4
+ import type {NavigationProp} from '@react-navigation/native';
5
+ import {useNavigation} from '@react-navigation/native';
6
+ import {height, moderateScale, scale, verticalScale, width} from '@utils/scaling';
7
+ import React, {useRef, useState} from 'react';
8
+ import type {NativeScrollEvent, NativeSyntheticEvent, ScrollViewInstance} from 'react-native';
9
+ import {Image, ScrollView, View} from 'react-native';
10
+ import {useStyles} from 'react-native-unistyles';
11
+ import stylesheet from './styles';
12
+
13
+ const onBoardData = [{id: 1}, {id: 2}, {id: 3}];
14
+
15
+ const Onboarding = (): React.JSX.Element => {
16
+ const navigation = useNavigation<NavigationProp<AuthStackParamList>>();
17
+ const [index, setIndex] = useState<number>(0);
18
+ const {styles} = useStyles(stylesheet);
19
+ const scrollRef = useRef<null | ScrollViewInstance>(null);
20
+
21
+ const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
22
+ const newIndex = Number((event.nativeEvent.contentOffset.x / (width - 20)).toFixed(0));
23
+ setIndex(newIndex);
24
+ };
25
+
26
+ return (
27
+ <WrapperContainer>
28
+ <View style={styles.container}>
29
+ <ScrollView
30
+ horizontal
31
+ onMomentumScrollEnd={handleScroll}
32
+ pagingEnabled
33
+ ref={scrollRef}
34
+ showsHorizontalScrollIndicator={false}>
35
+ {onBoardData.map(val => (
36
+ <View
37
+ key={String(val.id)}
38
+ style={{
39
+ paddingHorizontal: moderateScale(16),
40
+ width,
41
+ }}>
42
+ <Image
43
+ resizeMode="contain"
44
+ source={{
45
+ uri: 'https://img.freepik.com/free-vector/onboarding-concept-illustration_114360-1085.jpg',
46
+ }}
47
+ style={{
48
+ height: height / 2.1,
49
+ width: '100%',
50
+ }}
51
+ />
52
+ <TextContainer
53
+ isDynamicText
54
+ style={{
55
+ fontSize: scale(32),
56
+ lineHeight: scale(42),
57
+ marginVertical: verticalScale(16),
58
+ }}
59
+ text="Connect people around the world"
60
+ />
61
+ <TextContainer
62
+ isDynamicText
63
+ style={{
64
+ fontFamily: fontFamily.regular,
65
+ fontSize: scale(14),
66
+ }}
67
+ text="Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content."
68
+ />
69
+ </View>
70
+ ))}
71
+ </ScrollView>
72
+ <View style={styles.flexView}>
73
+ <View style={{alignItems: 'center', flexDirection: 'row'}}>
74
+ {onBoardData.map((val, i) => (
75
+ <View key={String(val.id)} style={styles.dotStyle(i === index)} />
76
+ ))}
77
+ </View>
78
+ <View>
79
+ <TextContainer onPress={() => navigation.navigate('Login')} text="SKIP" />
80
+ </View>
81
+ </View>
82
+ </View>
83
+ </WrapperContainer>
84
+ );
85
+ };
86
+
87
+ export default Onboarding;
@@ -0,0 +1,25 @@
1
+ import { moderateScale, verticalScale } from "@utils/scaling";
2
+ import { createStyleSheet } from "react-native-unistyles";
3
+
4
+ const stylesheet = createStyleSheet((theme) => ({
5
+ container: {
6
+ flex: 1,
7
+ justifyContent: "space-between",
8
+ marginVertical: verticalScale(16),
9
+ },
10
+ dotStyle: (isSelected: boolean) => ({
11
+ backgroundColor: isSelected ? theme.colors.darkwhite : theme.colors.grey,
12
+ borderRadius: moderateScale(4),
13
+ height: moderateScale(6),
14
+ marginRight: moderateScale(8),
15
+ width: moderateScale(6),
16
+ }),
17
+ flexView: {
18
+ alignItems: "center",
19
+ flexDirection: "row",
20
+ justifyContent: "space-between",
21
+ marginHorizontal: moderateScale(16),
22
+ },
23
+ }));
24
+
25
+ export default stylesheet;
@@ -0,0 +1,168 @@
1
+ import {ButtonContainer, ImageContainer, TextContainer, WrapperContainer} from '@components/atoms';
2
+ import ErrorComp from '@components/molecules/ErrorComp';
3
+ import HeaderComp from '@components/molecules/HeaderComp';
4
+ import Loader from '@components/molecules/Loader';
5
+ import fontFamily from '@constants/fontFamily';
6
+ import imagePath from '@constants/imagePath';
7
+ import {ProductsData} from '@models/HomeData';
8
+ import type {HomeStackParamList} from '@navigations/MainStack';
9
+ import type {RouteProp} from '@react-navigation/native';
10
+ import {moderateScale, scale, width} from '@utils/scaling';
11
+ import React, {useEffect} from 'react';
12
+ import {ImageBackground, SafeAreaView, ScrollView, View} from 'react-native';
13
+ import {UnistylesRuntime, useStyles} from 'react-native-unistyles';
14
+ import stylesheet from './styles';
15
+ import {useDispatch, useSelector} from '@redux/hooks';
16
+ import {getProductDetails} from 'src/services/productService';
17
+
18
+ type PostDetailsRouteProp = RouteProp<HomeStackParamList, 'PostDetails'>;
19
+
20
+ type Props = {
21
+ route: PostDetailsRouteProp;
22
+ };
23
+
24
+ const PostDetails: React.FC<Props> = ({route}): React.JSX.Element => {
25
+ // Redux global variables
26
+ const dispatch = useDispatch();
27
+ const isLoading = useSelector(state => state.common.isLoading);
28
+ const {error, productDetail} = useSelector(state => state.product);
29
+
30
+ // Styles variables
31
+ const {styles} = useStyles(stylesheet);
32
+ const {theme} = useStyles();
33
+ const isDarkMode = UnistylesRuntime.themeName === 'dark';
34
+
35
+ // Effects
36
+ useEffect(() => {
37
+ dispatch(getProductDetails(route.params?.productId));
38
+ }, [dispatch, route.params?.productId]);
39
+
40
+ // Rendering handled
41
+ if (isLoading) {
42
+ return <Loader />;
43
+ }
44
+ if (error) {
45
+ return <ErrorComp />;
46
+ }
47
+
48
+ return (
49
+ <WrapperContainer isSafeAreaView={false}>
50
+ <ScrollView
51
+ style={{
52
+ backgroundColor: theme.colors.background,
53
+ overflow: 'visible',
54
+ }}>
55
+ <ImageBackground
56
+ resizeMode="stretch"
57
+ source={{uri: productDetail?.thumbnail}}
58
+ style={styles.imageStyle}>
59
+ <SafeAreaView>
60
+ <HeaderComp />
61
+ </SafeAreaView>
62
+
63
+ <View>
64
+ <TextContainer
65
+ isDynamicText
66
+ style={{
67
+ color: theme.colors.white,
68
+ fontFamily: fontFamily.semiBold,
69
+ fontSize: scale(24),
70
+ }}
71
+ text={productDetail?.description || ''}
72
+ />
73
+ <TextContainer
74
+ isDynamicText
75
+ style={{
76
+ color: theme.colors.white,
77
+ fontSize: scale(14),
78
+ }}
79
+ text={productDetail?.description || ''}
80
+ />
81
+ </View>
82
+ </ImageBackground>
83
+
84
+ <View style={[styles.containerView, {backgroundColor: theme.colors.background}]}>
85
+ <View
86
+ style={{
87
+ ...styles.headerLine,
88
+ backgroundColor: theme.colors.opacity50,
89
+ }}
90
+ />
91
+
92
+ <View style={styles.rectangleBox}>
93
+ <View style={{width: width / 2}}>
94
+ <TextContainer style={styles.followUs} text="FOLLOW_US" />
95
+ <TextContainer
96
+ isDynamicText
97
+ style={{color: theme.colors.white}}
98
+ text="Over 35k Happy Customers"
99
+ />
100
+ </View>
101
+ <ButtonContainer
102
+ label="FOLLOW"
103
+ style={styles.btnStyle}
104
+ textStyle={styles.btnTextStyle}
105
+ />
106
+ </View>
107
+
108
+ <View style={styles.likeCommentView}>
109
+ <View style={styles.flexView}>
110
+ <ImageContainer
111
+ source={imagePath.icLike}
112
+ style={{marginRight: moderateScale(8), resizeMode: 'contain'}}
113
+ />
114
+ <TextContainer isDynamicText style={{fontSize: scale(12)}} text="25.3k LIKES" />
115
+ </View>
116
+ <View style={{...styles.flexView, flex: 0.4}}>
117
+ <ImageContainer
118
+ source={imagePath.icComment}
119
+ style={{marginRight: moderateScale(8), resizeMode: 'contain'}}
120
+ />
121
+ <TextContainer isDynamicText style={{fontSize: scale(12)}} text="2.1k COMMENTS" />
122
+ </View>
123
+
124
+ <ButtonContainer
125
+ label="ADD_COMMENTS"
126
+ style={{
127
+ ...styles.btnStyle,
128
+ backgroundColor: isDarkMode ? theme.colors.white : theme.colors.black,
129
+ paddingHorizontal: moderateScale(10),
130
+ }}
131
+ textStyle={{
132
+ ...styles.btnTextStyle,
133
+ color: isDarkMode ? theme.colors.black : theme.colors.white,
134
+ fontSize: scale(10),
135
+ }}
136
+ />
137
+ </View>
138
+
139
+ <View
140
+ style={{
141
+ ...styles.headerLine,
142
+ backgroundColor: theme.colors.grey,
143
+ height: moderateScale(1),
144
+ width: '100%',
145
+ }}
146
+ />
147
+
148
+ <TextContainer
149
+ isDynamicText
150
+ style={{color: theme.colors.blue}}
151
+ text={productDetail?.brand || ''}
152
+ />
153
+ <TextContainer
154
+ isDynamicText
155
+ style={styles.headerTextStyle}
156
+ text={productDetail?.title || ''}
157
+ />
158
+ <TextContainer
159
+ isDynamicText
160
+ style={styles.descTextStyle}
161
+ text={productDetail?.description || ''}
162
+ />
163
+ </View>
164
+ </ScrollView>
165
+ </WrapperContainer>
166
+ );
167
+ };
168
+ export default PostDetails;