new-react-native-boilerplate 0.0.0-stage → 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.
- package/LICENSE +21 -0
- package/README.md +314 -2
- package/package.json +49 -4
- package/run.sh +36 -0
- package/setup.js +141 -0
- package/template/.bundle/config +2 -0
- package/template/.editorconfig +14 -0
- package/template/.eslintrc.js +49 -0
- package/template/.husky/commit-msg +4 -0
- package/template/.husky/pre-commit +1 -0
- package/template/.prettierrc.js +6 -0
- package/template/.watchmanconfig +1 -0
- package/template/Gemfile +17 -0
- package/template/Gemfile.lock +114 -0
- package/template/README.md +103 -0
- package/template/__tests__/App.test.tsx +13 -0
- package/template/__tests__/CustomTextInput.test.jsx +29 -0
- package/template/android/app/build.gradle +119 -0
- package/template/android/app/debug.keystore +0 -0
- package/template/android/app/proguard-rules.pro +10 -0
- package/template/android/app/src/main/AndroidManifest.xml +27 -0
- package/template/android/app/src/main/assets/fonts/Poppins-Bold.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/Poppins-Medium.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/Poppins-Regular.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/Poppins-SemiBold.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/futura_book.otf +0 -0
- package/template/android/app/src/main/assets/fonts/futura_medium.otf +0 -0
- package/template/android/app/src/main/java/com/boilerplatereactnative/MainActivity.kt +22 -0
- package/template/android/app/src/main/java/com/boilerplatereactnative/MainApplication.kt +27 -0
- package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/values/strings.xml +3 -0
- package/template/android/app/src/main/res/values/styles.xml +9 -0
- package/template/android/build.gradle +21 -0
- package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/template/android/gradle.properties +49 -0
- package/template/android/gradlew +248 -0
- package/template/android/gradlew.bat +98 -0
- package/template/android/link-assets-manifest.json +29 -0
- package/template/android/settings.gradle +6 -0
- package/template/app.json +4 -0
- package/template/babel.config.js +43 -0
- package/template/eslint.config.mjs +175 -0
- package/template/index.d.ts +1 -0
- package/template/index.js +10 -0
- package/template/ios/.xcode.env +11 -0
- package/template/ios/BoilerPlateReactNative/AppDelegate.swift +11 -0
- package/template/ios/BoilerPlateReactNative/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/template/ios/BoilerPlateReactNative/Images.xcassets/Contents.json +6 -0
- package/template/ios/BoilerPlateReactNative/Info.plist +102 -0
- package/template/ios/BoilerPlateReactNative/LaunchScreen.storyboard +47 -0
- package/template/ios/BoilerPlateReactNative/PrivacyInfo.xcprivacy +37 -0
- package/template/ios/BoilerPlateReactNative/SceneDelegate.swift +54 -0
- package/template/ios/BoilerPlateReactNative.xcodeproj/project.pbxproj +531 -0
- package/template/ios/BoilerPlateReactNative.xcodeproj/xcshareddata/xcschemes/BoilerPlateReactNative.xcscheme +88 -0
- package/template/ios/BoilerPlateReactNative.xcworkspace/contents.xcworkspacedata +10 -0
- package/template/ios/BoilerPlateReactNative.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/template/ios/Podfile +34 -0
- package/template/ios/Podfile.lock +2552 -0
- package/template/ios/link-assets-manifest.json +29 -0
- package/template/jest.config.js +13 -0
- package/template/jest.setup.js +30 -0
- package/template/metro.config.js +15 -0
- package/template/package.json +88 -0
- package/template/plugins/compile-js/_prompts.js +6 -0
- package/template/plugins/compile-js/index.js +9 -0
- package/template/plugins/compile-js/plugin.js +103 -0
- package/template/plugins/compile-js/tsconfig.build.json +20 -0
- package/template/plugins/index.js +46 -0
- package/template/plugins/printSuccess/_prompts.js +1 -0
- package/template/plugins/printSuccess/index.js +9 -0
- package/template/plugins/printSuccess/plugin.js +40 -0
- package/template/react-native.config.js +7 -0
- package/template/src/App.tsx +27 -0
- package/template/src/assets/fonts/Poppins-Bold.ttf +0 -0
- package/template/src/assets/fonts/Poppins-Medium.ttf +0 -0
- package/template/src/assets/fonts/Poppins-Regular.ttf +0 -0
- package/template/src/assets/fonts/Poppins-SemiBold.ttf +0 -0
- package/template/src/assets/fonts/futura_book.otf +0 -0
- package/template/src/assets/fonts/futura_medium.otf +0 -0
- package/template/src/assets/images/check.png +0 -0
- package/template/src/assets/images/check@2x.png +0 -0
- package/template/src/assets/images/check@3x.png +0 -0
- package/template/src/assets/images/email.png +0 -0
- package/template/src/assets/images/email@2x.png +0 -0
- package/template/src/assets/images/email@3x.png +0 -0
- package/template/src/assets/images/icBack.png +0 -0
- package/template/src/assets/images/icBack@2x.png +0 -0
- package/template/src/assets/images/icBack@3x.png +0 -0
- package/template/src/assets/images/icClose.png +0 -0
- package/template/src/assets/images/icClose@2x.png +0 -0
- package/template/src/assets/images/icClose@3x.png +0 -0
- package/template/src/assets/images/icComment.png +0 -0
- package/template/src/assets/images/icComment@2x.png +0 -0
- package/template/src/assets/images/icComment@3x.png +0 -0
- package/template/src/assets/images/icLike.png +0 -0
- package/template/src/assets/images/icLike@2x.png +0 -0
- package/template/src/assets/images/icLike@3x.png +0 -0
- package/template/src/assets/images/icSearch.png +0 -0
- package/template/src/assets/images/icSearch@2x.png +0 -0
- package/template/src/assets/images/icSearch@3x.png +0 -0
- package/template/src/assets/images/icSetting.png +0 -0
- package/template/src/assets/images/icSetting@2x.png +0 -0
- package/template/src/assets/images/icSetting@3x.png +0 -0
- package/template/src/assets/images/icShare.png +0 -0
- package/template/src/assets/images/icShare@2x.png +0 -0
- package/template/src/assets/images/icShare@3x.png +0 -0
- package/template/src/assets/images/line.png +0 -0
- package/template/src/assets/images/line@2x.png +0 -0
- package/template/src/assets/images/line@3x.png +0 -0
- package/template/src/assets/images/lock.png +0 -0
- package/template/src/assets/images/lock@2x.png +0 -0
- package/template/src/assets/images/lock@3x.png +0 -0
- package/template/src/assets/images/notification.png +0 -0
- package/template/src/assets/images/notification@2x.png +0 -0
- package/template/src/assets/images/notification@3x.png +0 -0
- package/template/src/assets/images/oct_dark.png +0 -0
- package/template/src/assets/images/oct_light.png +0 -0
- package/template/src/assets/images/onboard.png +0 -0
- package/template/src/assets/images/password_hide.png +0 -0
- package/template/src/assets/images/password_hide@2x.png +0 -0
- package/template/src/assets/images/password_hide@3x.png +0 -0
- package/template/src/assets/images/password_show.png +0 -0
- package/template/src/assets/images/password_show@2x.png +0 -0
- package/template/src/assets/images/password_show@3x.png +0 -0
- package/template/src/assets/images/right_arrow.png +0 -0
- package/template/src/assets/images/right_arrow@2x.png +0 -0
- package/template/src/assets/images/right_arrow@3x.png +0 -0
- package/template/src/assets/images/star.png +0 -0
- package/template/src/assets/images/star@2x.png +0 -0
- package/template/src/assets/images/star@3x.png +0 -0
- package/template/src/assets/images/uncheck.png +0 -0
- package/template/src/assets/images/uncheck@2x.png +0 -0
- package/template/src/assets/images/uncheck@3x.png +0 -0
- package/template/src/assets/images/user.png +0 -0
- package/template/src/assets/images/user@2x.png +0 -0
- package/template/src/assets/images/user@3x.png +0 -0
- package/template/src/components/atoms/ButtonContainer.tsx +52 -0
- package/template/src/components/atoms/ImageContainer.tsx +10 -0
- package/template/src/components/atoms/RemoteImage.tsx +8 -0
- package/template/src/components/atoms/RoundImageBorder.tsx +35 -0
- package/template/src/components/atoms/TextContainer.tsx +38 -0
- package/template/src/components/atoms/WrapperContainer.tsx +43 -0
- package/template/src/components/atoms/index.ts +6 -0
- package/template/src/components/molecules/AuthHeader.tsx +55 -0
- package/template/src/components/molecules/CustomTextInput.tsx +102 -0
- package/template/src/components/molecules/EmptyComp.tsx +16 -0
- package/template/src/components/molecules/ErrorComp.tsx +25 -0
- package/template/src/components/molecules/FooterView.tsx +41 -0
- package/template/src/components/molecules/HeaderComp.tsx +51 -0
- package/template/src/components/molecules/HomeHeader.tsx +63 -0
- package/template/src/components/molecules/HomeListHeader.tsx +48 -0
- package/template/src/components/molecules/HomeListItems.tsx +86 -0
- package/template/src/components/molecules/Loader.tsx +25 -0
- package/template/src/components/molecules/ModalSheet.tsx +146 -0
- package/template/src/components/molecules/RememberMe.tsx +58 -0
- package/template/src/components/molecules/SearchBar.tsx +46 -0
- package/template/src/components/molecules/index.ts +12 -0
- package/template/src/constants/apiConstant.ts +12 -0
- package/template/src/constants/fontFamily.ts +8 -0
- package/template/src/constants/imagePath.ts +25 -0
- package/template/src/constants/index.ts +3 -0
- package/template/src/constants/storageKeys.ts +5 -0
- package/template/src/models/ApiErrorResponse.ts +19 -0
- package/template/src/models/HomeData.ts +17 -0
- package/template/src/models/User.ts +11 -0
- package/template/src/navigations/AuthStack.tsx +20 -0
- package/template/src/navigations/MainStack.tsx +19 -0
- package/template/src/navigations/Routes.tsx +22 -0
- package/template/src/navigations/navigationProps.ts +8 -0
- package/template/src/redux/hooks.ts +10 -0
- package/template/src/redux/reducers/auth.ts +43 -0
- package/template/src/redux/reducers/common.ts +24 -0
- package/template/src/redux/reducers/index.ts +31 -0
- package/template/src/redux/reducers/product.ts +37 -0
- package/template/src/redux/reducers/settings.ts +55 -0
- package/template/src/redux/store.ts +19 -0
- package/template/src/redux/types.ts +6 -0
- package/template/src/screens/Home/Home.tsx +65 -0
- package/template/src/screens/Login/Login.tsx +35 -0
- package/template/src/screens/Login/components/LoginForm.tsx +88 -0
- package/template/src/screens/Login/hooks/useLogin.ts +38 -0
- package/template/src/screens/Login/styles.ts +17 -0
- package/template/src/screens/Login/types.ts +10 -0
- package/template/src/screens/Onboarding/Onboarding.tsx +87 -0
- package/template/src/screens/Onboarding/styles.ts +25 -0
- package/template/src/screens/PostDetails/PostDetails.tsx +168 -0
- package/template/src/screens/PostDetails/styles.ts +82 -0
- package/template/src/screens/Signup/Signup.tsx +32 -0
- package/template/src/screens/Signup/components/SignupForm.tsx +113 -0
- package/template/src/screens/Signup/hooks/useSignup.ts +38 -0
- package/template/src/screens/Signup/styles.ts +18 -0
- package/template/src/screens/Signup/type.ts +12 -0
- package/template/src/screens/index.ts +5 -0
- package/template/src/services/apiService.ts +144 -0
- package/template/src/services/authService.ts +79 -0
- package/template/src/services/productService.ts +45 -0
- package/template/src/services/statusHandler.ts +17 -0
- package/template/src/styles/breakpoints.ts +11 -0
- package/template/src/styles/themes.ts +45 -0
- package/template/src/styles/unistyles.ts +25 -0
- package/template/src/translations/ar.json +47 -0
- package/template/src/translations/en.json +47 -0
- package/template/src/translations/fr.json +47 -0
- package/template/src/translations/index.ts +32 -0
- package/template/src/typings/env.d.ts +5 -0
- package/template/src/typings/global.d.ts +3 -0
- package/template/src/utils/handleLocalStorage.ts +31 -0
- package/template/src/utils/i18nHelpers.ts +20 -0
- package/template/src/utils/index.ts +66 -0
- package/template/src/utils/scaling.ts +13 -0
- package/template/src/utils/themeHelpers.ts +10 -0
- package/template/src/utils/validationForm.ts +23 -0
- package/template/src/utils/validations.ts +69 -0
- package/template/tsconfig.json +22 -0
- package/template/yarn.lock +7728 -0
- package/template.config.js +6 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import { TextContainer } from "@components/atoms";
|
|
4
|
+
import RemoteImage from "@components/atoms/RemoteImage";
|
|
5
|
+
import fontFamily from "@constants/fontFamily";
|
|
6
|
+
import type { ProductsData } from "@models/HomeData";
|
|
7
|
+
import type { HomeStackParamList } from "@navigations/MainStack";
|
|
8
|
+
import type { NavigationProp } from "@react-navigation/native";
|
|
9
|
+
import { moderateScale, scale, verticalScale } from "@utils/scaling";
|
|
10
|
+
import React, { memo } from "react";
|
|
11
|
+
import { Pressable, View } from "react-native";
|
|
12
|
+
import { createStyleSheet, useStyles } from "react-native-unistyles";
|
|
13
|
+
|
|
14
|
+
const stylesheet = createStyleSheet((theme) => ({
|
|
15
|
+
container: {
|
|
16
|
+
alignItems: "center",
|
|
17
|
+
flexDirection: "row",
|
|
18
|
+
marginHorizontal: moderateScale(16),
|
|
19
|
+
},
|
|
20
|
+
flexRow: {
|
|
21
|
+
alignItems: "center",
|
|
22
|
+
flexDirection: "row",
|
|
23
|
+
justifyContent: "space-between",
|
|
24
|
+
},
|
|
25
|
+
imageStyle: {
|
|
26
|
+
borderRadius: moderateScale(10),
|
|
27
|
+
height: moderateScale(20),
|
|
28
|
+
marginRight: moderateScale(4),
|
|
29
|
+
width: moderateScale(20),
|
|
30
|
+
},
|
|
31
|
+
profileImage: {
|
|
32
|
+
backgroundColor: theme.colors.grey,
|
|
33
|
+
borderRadius: moderateScale(24),
|
|
34
|
+
height: moderateScale(134),
|
|
35
|
+
marginRight: moderateScale(16),
|
|
36
|
+
width: moderateScale(134),
|
|
37
|
+
},
|
|
38
|
+
textStyle: {
|
|
39
|
+
color: theme.colors.opacity50,
|
|
40
|
+
fontSize: scale(12),
|
|
41
|
+
},
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
interface HomeListItemsProps {
|
|
45
|
+
item: ProductsData;
|
|
46
|
+
navigation: NavigationProp<HomeStackParamList>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const HomeListItems: React.FC<HomeListItemsProps> = memo(({ item, navigation }) => {
|
|
50
|
+
const { styles } = useStyles(stylesheet);
|
|
51
|
+
return (
|
|
52
|
+
<Pressable
|
|
53
|
+
onPress={() => navigation.navigate("PostDetails", { productId: item.id })}
|
|
54
|
+
style={styles.container}
|
|
55
|
+
>
|
|
56
|
+
<RemoteImage source={{ uri: item.thumbnail }} style={styles.profileImage} />
|
|
57
|
+
|
|
58
|
+
<View style={{ flex: 1 }}>
|
|
59
|
+
<TextContainer isDynamicText style={{ fontSize: scale(12) }} text={item.title} />
|
|
60
|
+
<TextContainer
|
|
61
|
+
isDynamicText
|
|
62
|
+
numberOfLines={2}
|
|
63
|
+
style={{
|
|
64
|
+
fontFamily: fontFamily.medium,
|
|
65
|
+
marginVertical: verticalScale(6),
|
|
66
|
+
}}
|
|
67
|
+
text={item.description}
|
|
68
|
+
/>
|
|
69
|
+
<View style={styles.flexRow}>
|
|
70
|
+
<View style={{ alignItems: "center", flex: 1, flexDirection: "row" }}>
|
|
71
|
+
<RemoteImage
|
|
72
|
+
source={{
|
|
73
|
+
uri: "https://www.profilebakery.com/wp-content/uploads/2023/03/AI-Profile-Picture.jpg",
|
|
74
|
+
}}
|
|
75
|
+
style={styles.imageStyle}
|
|
76
|
+
/>
|
|
77
|
+
<TextContainer isDynamicText style={styles.textStyle} text="Regulators" />
|
|
78
|
+
</View>
|
|
79
|
+
<TextContainer isDynamicText style={styles.textStyle} text="June 14 2023" />
|
|
80
|
+
</View>
|
|
81
|
+
</View>
|
|
82
|
+
</Pressable>
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export default HomeListItems;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { WrapperContainer } from "@components/atoms";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { ActivityIndicator, View } from "react-native";
|
|
4
|
+
import { createStyleSheet, useStyles } from "react-native-unistyles";
|
|
5
|
+
|
|
6
|
+
const stylesheet = createStyleSheet(() => ({
|
|
7
|
+
container: {
|
|
8
|
+
alignItems: "center",
|
|
9
|
+
flex: 1,
|
|
10
|
+
justifyContent: "center",
|
|
11
|
+
},
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
const Loader = (): React.JSX.Element => {
|
|
15
|
+
const { styles } = useStyles(stylesheet);
|
|
16
|
+
return (
|
|
17
|
+
<WrapperContainer isSafeAreaView={false}>
|
|
18
|
+
<View style={styles.container}>
|
|
19
|
+
<ActivityIndicator size="large" />
|
|
20
|
+
</View>
|
|
21
|
+
</WrapperContainer>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default React.memo(Loader);
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import {ImageContainer, TextContainer} from '@components/atoms';
|
|
2
|
+
import fontFamily from '@constants/fontFamily';
|
|
3
|
+
import imagePath from '@constants/imagePath';
|
|
4
|
+
import {useDispatch, useSelector} from '@redux/hooks';
|
|
5
|
+
import types from '@redux/types';
|
|
6
|
+
import changeLanguage from '@utils/i18nHelpers';
|
|
7
|
+
import {moderateScale, verticalScale} from '@utils/scaling';
|
|
8
|
+
import changeTheme from '@utils/themeHelpers';
|
|
9
|
+
import type {ReactNode} from 'react';
|
|
10
|
+
import React, { forwardRef, useImperativeHandle, useState} from 'react';
|
|
11
|
+
import type { ModalProps} from 'react-native';
|
|
12
|
+
import {Modal, Pressable, Switch, View} from 'react-native';
|
|
13
|
+
import {createStyleSheet, UnistylesRuntime, useStyles} from 'react-native-unistyles';
|
|
14
|
+
import {storage} from 'src/services/apiService';
|
|
15
|
+
|
|
16
|
+
const stylesheet = createStyleSheet(theme => ({
|
|
17
|
+
container: {
|
|
18
|
+
backgroundColor: theme.colors.background,
|
|
19
|
+
borderTopLeftRadius: moderateScale(24),
|
|
20
|
+
borderTopRightRadius: moderateScale(24),
|
|
21
|
+
elevation: 5,
|
|
22
|
+
marginTop: 'auto',
|
|
23
|
+
minHeight: '25%',
|
|
24
|
+
paddingHorizontal: moderateScale(16),
|
|
25
|
+
paddingVertical: moderateScale(8),
|
|
26
|
+
shadowColor: theme.colors.background,
|
|
27
|
+
shadowOffset: {
|
|
28
|
+
height: 2,
|
|
29
|
+
width: 0,
|
|
30
|
+
},
|
|
31
|
+
shadowOpacity: 0.25,
|
|
32
|
+
shadowRadius: 3.84,
|
|
33
|
+
},
|
|
34
|
+
headerView: {
|
|
35
|
+
flexDirection: 'row',
|
|
36
|
+
justifyContent: 'space-between',
|
|
37
|
+
},
|
|
38
|
+
horizontalLine: {
|
|
39
|
+
alignSelf: 'center',
|
|
40
|
+
backgroundColor: theme.colors.opacity50,
|
|
41
|
+
borderRadius: moderateScale(8),
|
|
42
|
+
height: moderateScale(6),
|
|
43
|
+
width: moderateScale(80),
|
|
44
|
+
},
|
|
45
|
+
logoutText: {
|
|
46
|
+
color: theme.colors.danger,
|
|
47
|
+
fontFamily: fontFamily.semiBold,
|
|
48
|
+
},
|
|
49
|
+
modalView: {
|
|
50
|
+
flexDirection: 'row',
|
|
51
|
+
justifyContent: 'space-between',
|
|
52
|
+
marginTop: verticalScale(8),
|
|
53
|
+
},
|
|
54
|
+
textStyle: (isSelected: boolean) => ({
|
|
55
|
+
color: isSelected ? theme.colors.danger : theme.colors.typography,
|
|
56
|
+
fontFamily: isSelected ? fontFamily.semiBold : fontFamily.regular,
|
|
57
|
+
}),
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
interface ModalSheetProps extends ModalProps {
|
|
61
|
+
children?: ReactNode;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ModalSheetRef {
|
|
65
|
+
toggleSheet: () => void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const ModalSheet = forwardRef<ModalSheetRef, ModalSheetProps>((props, ref) => {
|
|
69
|
+
const [isVisible, setVisible] = useState(false);
|
|
70
|
+
const {defaultLanguage, languages} = useSelector(state => state.settings);
|
|
71
|
+
|
|
72
|
+
const isDarkMode = UnistylesRuntime.themeName === 'dark';
|
|
73
|
+
const dispatch = useDispatch();
|
|
74
|
+
const {styles} = useStyles(stylesheet);
|
|
75
|
+
|
|
76
|
+
useImperativeHandle(ref, () => ({
|
|
77
|
+
toggleSheet: () => {
|
|
78
|
+
setVisible(!isVisible);
|
|
79
|
+
},
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
const onPressLogout = () => {
|
|
83
|
+
setVisible(!isVisible);
|
|
84
|
+
setTimeout(() => {
|
|
85
|
+
// need time to close modal
|
|
86
|
+
storage.clearAll();
|
|
87
|
+
dispatch({type: types.CLEAR_REDUX_STATE});
|
|
88
|
+
}, 800);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<Modal animationType="slide" transparent visible={isVisible} {...props}>
|
|
93
|
+
<View style={styles.container}>
|
|
94
|
+
<View style={styles.headerView}>
|
|
95
|
+
<View />
|
|
96
|
+
<View style={styles.horizontalLine} />
|
|
97
|
+
<Pressable onPress={() => setVisible(!isVisible)}>
|
|
98
|
+
<ImageContainer source={imagePath.icClose} />
|
|
99
|
+
</Pressable>
|
|
100
|
+
</View>
|
|
101
|
+
<>
|
|
102
|
+
<View style={styles.modalView}>
|
|
103
|
+
<View>
|
|
104
|
+
<TextContainer
|
|
105
|
+
style={{
|
|
106
|
+
fontFamily: fontFamily.semiBold,
|
|
107
|
+
}}
|
|
108
|
+
text="CHANGE_LANGUAGE"
|
|
109
|
+
/>
|
|
110
|
+
{languages.map(val => (
|
|
111
|
+
<Pressable
|
|
112
|
+
key={String(val.sortName)}
|
|
113
|
+
onPress={() => changeLanguage(val)}
|
|
114
|
+
style={{
|
|
115
|
+
marginTop: verticalScale(8),
|
|
116
|
+
}}>
|
|
117
|
+
<TextContainer
|
|
118
|
+
isDynamicText
|
|
119
|
+
style={styles.textStyle(defaultLanguage.sortName === val.sortName)}
|
|
120
|
+
text={val.name}
|
|
121
|
+
/>
|
|
122
|
+
</Pressable>
|
|
123
|
+
))}
|
|
124
|
+
</View>
|
|
125
|
+
<View>
|
|
126
|
+
<TextContainer style={{fontFamily: fontFamily.semiBold}} text="CHANGE_THEME" />
|
|
127
|
+
<Switch
|
|
128
|
+
onChange={() => changeTheme(isDarkMode ? 'light' : 'dark')}
|
|
129
|
+
style={{
|
|
130
|
+
alignSelf: 'flex-end',
|
|
131
|
+
marginVertical: verticalScale(8),
|
|
132
|
+
}}
|
|
133
|
+
value={isDarkMode}
|
|
134
|
+
/>
|
|
135
|
+
</View>
|
|
136
|
+
</View>
|
|
137
|
+
<Pressable style={{alignSelf: 'center', marginVertical: verticalScale(16)}}>
|
|
138
|
+
<TextContainer onPress={onPressLogout} style={styles.logoutText} text="LOGOUT" />
|
|
139
|
+
</Pressable>
|
|
140
|
+
</>
|
|
141
|
+
</View>
|
|
142
|
+
</Modal>
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
export default React.memo(ModalSheet);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ImageContainer, TextContainer } from "@components/atoms";
|
|
2
|
+
import fontFamily from "@constants/fontFamily";
|
|
3
|
+
import imagePath from "@constants/imagePath";
|
|
4
|
+
import { moderateScale, scale, verticalScale } from "@utils/scaling";
|
|
5
|
+
import React, { useState } from "react";
|
|
6
|
+
import type { PropsWithChildren } from "react";
|
|
7
|
+
import { Pressable, View } from "react-native";
|
|
8
|
+
import { createStyleSheet, useStyles } from "react-native-unistyles";
|
|
9
|
+
|
|
10
|
+
const stylesheet = createStyleSheet(() => ({
|
|
11
|
+
flexRow: {
|
|
12
|
+
alignItems: "center",
|
|
13
|
+
flexDirection: "row",
|
|
14
|
+
justifyContent: "space-between",
|
|
15
|
+
marginBottom: verticalScale(24),
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
headerStyle: {
|
|
19
|
+
alignItems: "center",
|
|
20
|
+
flexDirection: "row",
|
|
21
|
+
marginBottom: verticalScale(32),
|
|
22
|
+
},
|
|
23
|
+
textStyle: {
|
|
24
|
+
fontFamily: fontFamily.medium,
|
|
25
|
+
fontSize: scale(12),
|
|
26
|
+
opacity: 0.6,
|
|
27
|
+
},
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
type SectionProps = PropsWithChildren<{
|
|
31
|
+
onPressForgot: () => void;
|
|
32
|
+
}>;
|
|
33
|
+
|
|
34
|
+
const RememberMe = ({ onPressForgot }: SectionProps): React.JSX.Element => {
|
|
35
|
+
const [rememberMe, setRememberMe] = useState<boolean>(false);
|
|
36
|
+
const { styles } = useStyles(stylesheet);
|
|
37
|
+
return (
|
|
38
|
+
<View style={styles.flexRow}>
|
|
39
|
+
<Pressable
|
|
40
|
+
onPress={() => setRememberMe(!rememberMe)}
|
|
41
|
+
style={{ alignItems: "center", flexDirection: "row" }}
|
|
42
|
+
>
|
|
43
|
+
<ImageContainer
|
|
44
|
+
resizeMode="contain"
|
|
45
|
+
source={rememberMe ? imagePath.icCheck : imagePath.icUnchek}
|
|
46
|
+
style={{
|
|
47
|
+
height: moderateScale(14),
|
|
48
|
+
marginRight: moderateScale(12),
|
|
49
|
+
width: moderateScale(14),
|
|
50
|
+
}}
|
|
51
|
+
/>
|
|
52
|
+
<TextContainer style={styles.textStyle} text="REMEBER_ME" />
|
|
53
|
+
</Pressable>
|
|
54
|
+
<TextContainer onPress={onPressForgot} style={styles.textStyle} text="FORGOT_PASSWORD" />
|
|
55
|
+
</View>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
export default React.memo(RememberMe);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ImageContainer, TextContainer } from "@components/atoms";
|
|
2
|
+
import fontFamily from "@constants/fontFamily";
|
|
3
|
+
import imagePath from "@constants/imagePath";
|
|
4
|
+
import { moderateScale, scale } from "@utils/scaling";
|
|
5
|
+
import type { PropsWithChildren } from "react";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import type { TextStyle, ViewStyle } from "react-native";
|
|
8
|
+
import { View } from "react-native";
|
|
9
|
+
import { createStyleSheet, useStyles } from "react-native-unistyles";
|
|
10
|
+
|
|
11
|
+
const stylesheet = createStyleSheet((theme) => ({
|
|
12
|
+
container: {
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
borderColor: theme.colors.opacity50,
|
|
15
|
+
borderRadius: moderateScale(36),
|
|
16
|
+
borderWidth: moderateScale(1.2),
|
|
17
|
+
flexDirection: "row",
|
|
18
|
+
height: moderateScale(56),
|
|
19
|
+
paddingHorizontal: moderateScale(12),
|
|
20
|
+
},
|
|
21
|
+
titleStyle: {
|
|
22
|
+
color: theme.colors.opacity50,
|
|
23
|
+
fontFamily: fontFamily.regular,
|
|
24
|
+
fontSize: scale(14),
|
|
25
|
+
marginLeft: moderateScale(16),
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
28
|
+
|
|
29
|
+
type SectionProps = PropsWithChildren<{
|
|
30
|
+
style?: ViewStyle;
|
|
31
|
+
textStyle?: TextStyle;
|
|
32
|
+
title: string;
|
|
33
|
+
}>;
|
|
34
|
+
|
|
35
|
+
const SearchBar = ({ style, textStyle, title }: SectionProps): React.JSX.Element => {
|
|
36
|
+
const { styles } = useStyles(stylesheet);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<View style={[styles.container, style]}>
|
|
40
|
+
<ImageContainer source={imagePath.icSearch} />
|
|
41
|
+
<TextContainer style={[styles.titleStyle, textStyle]} text={title} />
|
|
42
|
+
</View>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default React.memo(SearchBar);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default as AuthHeader } from "./AuthHeader";
|
|
2
|
+
export { default as CustomTextInput } from "./CustomTextInput";
|
|
3
|
+
export { default as EmptyComp } from "./EmptyComp";
|
|
4
|
+
export { default as ErrorComp } from "./ErrorComp";
|
|
5
|
+
export { default as FooterView } from "./FooterView";
|
|
6
|
+
export { default as HeaderComp } from "./HeaderComp";
|
|
7
|
+
export { default as HomeHeader } from "./HomeHeader";
|
|
8
|
+
export { default as HomeListItems } from "./HomeListItems";
|
|
9
|
+
export { default as Loader } from "./Loader";
|
|
10
|
+
export { default as ModalSheet } from "./ModalSheet";
|
|
11
|
+
export { default as RememberMe } from "./RememberMe";
|
|
12
|
+
export { default as SearchBar } from "./SearchBar";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-require-imports -- require() is the idiomatic way to load static image assets in React Native */
|
|
2
|
+
export default {
|
|
3
|
+
icBack: require("@assets/images/icBack.png"),
|
|
4
|
+
icCheck: require("@assets/images/check.png"),
|
|
5
|
+
icClose: require("@assets/images/icClose.png"),
|
|
6
|
+
icComment: require("@assets/images/icComment.png"),
|
|
7
|
+
icDarkOct: require("@assets/images/oct_dark.png"),
|
|
8
|
+
icEmail: require("@assets/images/email.png"),
|
|
9
|
+
icLightOct: require("@assets/images/oct_light.png"),
|
|
10
|
+
icLike: require("@assets/images/icLike.png"),
|
|
11
|
+
icLine: require("@assets/images/line.png"),
|
|
12
|
+
icLock: require("@assets/images/lock.png"),
|
|
13
|
+
icNotification: require("@assets/images/notification.png"),
|
|
14
|
+
icOnboard: require("@assets/images/onboard.png"),
|
|
15
|
+
icPassword: require("@assets/images/password_hide.png"),
|
|
16
|
+
|
|
17
|
+
icPasswordShow: require("@assets/images/password_show.png"),
|
|
18
|
+
icRightArrow: require("@assets/images/right_arrow.png"),
|
|
19
|
+
icSearch: require("@assets/images/icSearch.png"),
|
|
20
|
+
icSetting: require("@assets/images/icSetting.png"),
|
|
21
|
+
icShare: require("@assets/images/icShare.png"),
|
|
22
|
+
icStar: require("@assets/images/star.png"),
|
|
23
|
+
icUnchek: require("@assets/images/uncheck.png"),
|
|
24
|
+
icUser: require("@assets/images/user.png"),
|
|
25
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AxiosError } from "axios";
|
|
2
|
+
|
|
3
|
+
type ResponseStatus = {
|
|
4
|
+
data: {
|
|
5
|
+
error: string;
|
|
6
|
+
status: boolean;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export interface ApiErrorResponse {
|
|
11
|
+
error?: Error;
|
|
12
|
+
message?: string;
|
|
13
|
+
response?: ResponseStatus;
|
|
14
|
+
status?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ExtendedApiErrorResponse extends ApiErrorResponse {
|
|
18
|
+
axiosError?: AxiosError;
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ProductsData {
|
|
2
|
+
brand: string;
|
|
3
|
+
category: string;
|
|
4
|
+
description: string;
|
|
5
|
+
discountPercentage: number;
|
|
6
|
+
id: number;
|
|
7
|
+
images: [];
|
|
8
|
+
price: number;
|
|
9
|
+
rating: number;
|
|
10
|
+
stock: number;
|
|
11
|
+
thumbnail: string | undefined;
|
|
12
|
+
title: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface HomeData extends ProductsData {
|
|
16
|
+
products: Array<HomeData>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {createNativeStackNavigator} from '@react-navigation/native-stack';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import * as Screens from '../screens';
|
|
4
|
+
|
|
5
|
+
export type AuthStackParamList = {
|
|
6
|
+
Login: undefined;
|
|
7
|
+
Onboarding: undefined;
|
|
8
|
+
Signup: undefined;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const Stack = createNativeStackNavigator<AuthStackParamList>();
|
|
12
|
+
const AuthStack = () => (
|
|
13
|
+
<>
|
|
14
|
+
<Stack.Screen component={Screens.Onboarding} name="Onboarding" />
|
|
15
|
+
<Stack.Screen component={Screens.Login} name="Login" />
|
|
16
|
+
<Stack.Screen component={Screens.Signup} name="Signup" />
|
|
17
|
+
</>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export default AuthStack;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import * as Screens from "../screens";
|
|
4
|
+
|
|
5
|
+
export type HomeStackParamList = {
|
|
6
|
+
Home: undefined;
|
|
7
|
+
PostDetails: { productId: number };
|
|
8
|
+
Settings: undefined;
|
|
9
|
+
};
|
|
10
|
+
const Stack = createNativeStackNavigator<HomeStackParamList>();
|
|
11
|
+
|
|
12
|
+
const MainStack = () => (
|
|
13
|
+
<>
|
|
14
|
+
<Stack.Screen component={Screens.Home} name="Home" />
|
|
15
|
+
<Stack.Screen component={Screens.PostDetails} name="PostDetails" />
|
|
16
|
+
</>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export default MainStack;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {RootState} from '@redux/store';
|
|
2
|
+
import {NavigationContainer} from '@react-navigation/native';
|
|
3
|
+
import {createNativeStackNavigator} from '@react-navigation/native-stack';
|
|
4
|
+
import {useSelector} from '@redux/hooks';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import AuthStack from './AuthStack';
|
|
7
|
+
import MainStack from './MainStack';
|
|
8
|
+
|
|
9
|
+
const Stack = createNativeStackNavigator();
|
|
10
|
+
|
|
11
|
+
const Routes = () => {
|
|
12
|
+
const {userData} = useSelector((state: RootState) => state.auth);
|
|
13
|
+
return (
|
|
14
|
+
<NavigationContainer>
|
|
15
|
+
<Stack.Navigator screenOptions={{headerShown: false}}>
|
|
16
|
+
{userData?.accessToken ? MainStack() : AuthStack()}
|
|
17
|
+
</Stack.Navigator>
|
|
18
|
+
</NavigationContainer>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default Routes;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
import type { AppDispatch, RootState } from "./store";
|
|
3
|
+
|
|
4
|
+
import type { TypedUseSelectorHook } from "react-redux";
|
|
5
|
+
import { useDispatch as useReduxDispatch, useSelector as useReduxSelector } from "react-redux";
|
|
6
|
+
|
|
7
|
+
// Type safe hooks
|
|
8
|
+
export const useSelector: TypedUseSelectorHook<RootState> = useReduxSelector;
|
|
9
|
+
|
|
10
|
+
export const useDispatch: () => AppDispatch = useReduxDispatch;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
import type { User } from "@models/User";
|
|
3
|
+
import type { PayloadAction } from "@reduxjs/toolkit";
|
|
4
|
+
import { createSlice } from "@reduxjs/toolkit";
|
|
5
|
+
|
|
6
|
+
export interface AuthState {
|
|
7
|
+
error: Error | null;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
userData: User;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const initialState: AuthState = {
|
|
13
|
+
error: null,
|
|
14
|
+
isLoading: false,
|
|
15
|
+
userData: {
|
|
16
|
+
accessToken: "",
|
|
17
|
+
email: "",
|
|
18
|
+
firstName: "",
|
|
19
|
+
gender: "",
|
|
20
|
+
id: 0,
|
|
21
|
+
image: "",
|
|
22
|
+
lastName: "",
|
|
23
|
+
refreshToken: "",
|
|
24
|
+
username: ""
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const authSlice = createSlice({
|
|
29
|
+
initialState,
|
|
30
|
+
name: "auth",
|
|
31
|
+
reducers: {
|
|
32
|
+
hasError: (state, action: PayloadAction<Error>) => {
|
|
33
|
+
state.error = action.payload;
|
|
34
|
+
},
|
|
35
|
+
saveUserData: (state, action: PayloadAction<User>) => {
|
|
36
|
+
state.userData = action.payload;
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const { hasError, saveUserData } = authSlice.actions;
|
|
42
|
+
|
|
43
|
+
export default authSlice.reducer;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PayloadAction } from "@reduxjs/toolkit";
|
|
2
|
+
import { createSlice } from "@reduxjs/toolkit";
|
|
3
|
+
|
|
4
|
+
export interface CommonState {
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const initialState: CommonState = {
|
|
9
|
+
isLoading: false,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const commonSlice = createSlice({
|
|
13
|
+
initialState,
|
|
14
|
+
name: "common",
|
|
15
|
+
reducers: {
|
|
16
|
+
setLoading: (state, action: PayloadAction<boolean>) => {
|
|
17
|
+
state.isLoading = action.payload;
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const { setLoading } = commonSlice.actions;
|
|
23
|
+
|
|
24
|
+
export default commonSlice.reducer;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { UnknownAction } from "@reduxjs/toolkit";
|
|
2
|
+
import { combineReducers } from "@reduxjs/toolkit";
|
|
3
|
+
import types from "../types";
|
|
4
|
+
import type { AuthState } from "./auth";
|
|
5
|
+
import auth from "./auth";
|
|
6
|
+
import type { CommonState } from "./common";
|
|
7
|
+
import common from "./common";
|
|
8
|
+
import type { ProductState } from "./product";
|
|
9
|
+
import product from "./product";
|
|
10
|
+
import type { SettingsState } from "./settings";
|
|
11
|
+
import settings from "./settings";
|
|
12
|
+
|
|
13
|
+
export interface RootState {
|
|
14
|
+
auth: AuthState;
|
|
15
|
+
common: CommonState;
|
|
16
|
+
product: ProductState;
|
|
17
|
+
settings: SettingsState; // Update with the type of settings state
|
|
18
|
+
}
|
|
19
|
+
const appReducer = combineReducers({
|
|
20
|
+
auth,
|
|
21
|
+
common,
|
|
22
|
+
product,
|
|
23
|
+
settings
|
|
24
|
+
});
|
|
25
|
+
const rootReducer = (state: RootState | undefined, action: UnknownAction) => {
|
|
26
|
+
if (action.type === types.CLEAR_REDUX_STATE) {
|
|
27
|
+
state = undefined;
|
|
28
|
+
}
|
|
29
|
+
return appReducer(state, action);
|
|
30
|
+
};
|
|
31
|
+
export default rootReducer;
|