@modhamanish/rn-mm-template 1.0.1 → 1.0.3

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 (32) hide show
  1. package/MMTemplate/App.tsx +15 -2
  2. package/MMTemplate/package.json +3 -0
  3. package/MMTemplate/src/components/AppText.tsx +125 -0
  4. package/MMTemplate/src/components/CustomToast.tsx +8 -6
  5. package/MMTemplate/src/components/FeatureItem.tsx +11 -8
  6. package/MMTemplate/src/components/InfoCard.tsx +10 -6
  7. package/MMTemplate/src/components/LanguageSwitcher.tsx +8 -7
  8. package/MMTemplate/src/components/TextInput.tsx +214 -23
  9. package/MMTemplate/src/components/ThemeSwitcher.tsx +12 -7
  10. package/MMTemplate/src/context/ThemeContext.tsx +15 -1
  11. package/MMTemplate/src/locales/en.json +19 -2
  12. package/MMTemplate/src/locales/hi.json +19 -2
  13. package/MMTemplate/src/navigation/AppStack.tsx +2 -0
  14. package/MMTemplate/src/navigation/MainTab.tsx +15 -4
  15. package/MMTemplate/src/navigation/routes.ts +2 -0
  16. package/MMTemplate/src/screens/AddNoteScreen.tsx +155 -0
  17. package/MMTemplate/src/screens/HomeScreen.tsx +60 -33
  18. package/MMTemplate/src/screens/LoginScreen.tsx +67 -25
  19. package/MMTemplate/src/screens/NoteScreen.tsx +241 -0
  20. package/MMTemplate/src/screens/ProfileScreen.tsx +26 -25
  21. package/MMTemplate/src/screens/SettingsScreen.tsx +17 -16
  22. package/MMTemplate/src/screens/WelcomeScreen.tsx +23 -23
  23. package/MMTemplate/src/services/axiosInstance.ts +41 -0
  24. package/MMTemplate/src/services/note.query.ts +40 -0
  25. package/MMTemplate/src/services/queryKeys.ts +4 -0
  26. package/MMTemplate/src/types/components.types.ts +47 -1
  27. package/MMTemplate/src/types/navigation.types.ts +2 -0
  28. package/MMTemplate/src/types/services.types.ts +6 -0
  29. package/MMTemplate/src/utils/storageHelper.ts +2 -0
  30. package/MMTemplate/src/utils/validationSchemas.ts +6 -0
  31. package/README.md +1 -1
  32. package/package.json +1 -1
@@ -1,10 +1,4 @@
1
- import {
2
- StyleSheet,
3
- Text,
4
- TouchableOpacity,
5
- View,
6
- Linking,
7
- } from 'react-native';
1
+ import { StyleSheet, TouchableOpacity, View, Linking } from 'react-native';
8
2
  import React, { FC, useEffect } from 'react';
9
3
  import { useTranslation } from 'react-i18next';
10
4
  import { ThemeContextType, useTheme } from '../context/ThemeContext';
@@ -21,6 +15,7 @@ import { mobileScreenHeight, mobileScreenWidth } from '../utils/utilsHelper';
21
15
  import FullScreenContainer from '../components/FullScreenContainer';
22
16
  import { navigate } from '../utils/navigationUtils';
23
17
  import Routes from '../navigation/routes';
18
+ import AppText from '../components/AppText';
24
19
 
25
20
  const WelcomeScreen: FC = () => {
26
21
  const theme = useTheme();
@@ -83,14 +78,20 @@ const WelcomeScreen: FC = () => {
83
78
  </View>
84
79
 
85
80
  <Animated.View style={[styles.contentContainer, { opacity }]}>
86
- <Text style={styles.titleText}>
87
- <Text style={styles.titleBoldText}>{t('welcome.titleBold')}</Text>
81
+ <AppText style={styles.titleText}>
82
+ <AppText variant="bold" size="xxlarge" style={styles.titleBoldText}>
83
+ {t('welcome.titleBold')}
84
+ </AppText>
88
85
  {t('welcome.titleText')}
89
- </Text>
90
- <Text style={styles.matchBoldText}>{t('welcome.appName')}</Text>
86
+ </AppText>
87
+ <AppText variant="h1" size={36} style={styles.matchBoldText}>
88
+ {t('welcome.appName')}
89
+ </AppText>
91
90
 
92
91
  <Animated.View style={[styles.infoContainer, animatedContentStyle]}>
93
- <Text style={styles.subtitleText}>{t('welcome.subtitle')}</Text>
92
+ <AppText variant="body1" style={styles.subtitleText}>
93
+ {t('welcome.subtitle')}
94
+ </AppText>
94
95
  </Animated.View>
95
96
 
96
97
  <FullScreenContainer
@@ -103,9 +104,13 @@ const WelcomeScreen: FC = () => {
103
104
  style={styles.githubButton}
104
105
  activeOpacity={0.8}
105
106
  >
106
- <Text style={styles.githubButtonText}>
107
+ <AppText
108
+ variant="semiBold"
109
+ size={15}
110
+ style={styles.githubButtonText}
111
+ >
107
112
  📦 {t('welcome.githubButton')}
108
- </Text>
113
+ </AppText>
109
114
  </TouchableOpacity>
110
115
 
111
116
  <TouchableOpacity
@@ -113,7 +118,9 @@ const WelcomeScreen: FC = () => {
113
118
  style={styles.button}
114
119
  activeOpacity={0.8}
115
120
  >
116
- <Text style={styles.buttonText}>{t('welcome.loginButton')}</Text>
121
+ <AppText variant="bold" size={18} style={styles.buttonText}>
122
+ {t('welcome.loginButton')}
123
+ </AppText>
117
124
  </TouchableOpacity>
118
125
  </FullScreenContainer>
119
126
  </Animated.View>
@@ -150,13 +157,11 @@ const getStyles = ({ colors }: ThemeContextType) =>
150
157
  fontSize: 32,
151
158
  },
152
159
  titleBoldText: {
153
- fontWeight: '700',
160
+ color: colors.white,
154
161
  },
155
162
  matchBoldText: {
156
163
  color: colors.white,
157
- fontWeight: '800',
158
164
  textAlign: 'center',
159
- fontSize: 36,
160
165
  marginTop: 4,
161
166
  },
162
167
  infoContainer: {
@@ -165,7 +170,6 @@ const getStyles = ({ colors }: ThemeContextType) =>
165
170
  },
166
171
  subtitleText: {
167
172
  color: colors.white + 'CC',
168
- fontSize: 16,
169
173
  textAlign: 'center',
170
174
  lineHeight: 24,
171
175
  },
@@ -190,8 +194,6 @@ const getStyles = ({ colors }: ThemeContextType) =>
190
194
  },
191
195
  githubButtonText: {
192
196
  color: colors.white,
193
- fontSize: 15,
194
- fontWeight: '600',
195
197
  },
196
198
  button: {
197
199
  alignSelf: 'center',
@@ -208,8 +210,6 @@ const getStyles = ({ colors }: ThemeContextType) =>
208
210
  },
209
211
  buttonText: {
210
212
  color: colors.textColor,
211
- fontSize: 18,
212
213
  textAlign: 'center',
213
- fontWeight: '700',
214
214
  },
215
215
  });
@@ -0,0 +1,41 @@
1
+ import { Platform } from 'react-native';
2
+ import axios, { AxiosResponse, AxiosRequestConfig } from 'axios';
3
+ import Routes from '../navigation/routes';
4
+ import storageHelper from '../utils/storageHelper';
5
+ import { resetAndNavigate } from '../utils/navigationUtils';
6
+
7
+ const axiosInstance = axios.create({
8
+ baseURL: 'https://user-driven-mock-api-generator-serv.vercel.app/man',
9
+ });
10
+
11
+ const ResponseInterceptor = (response: AxiosResponse) => {
12
+ return response;
13
+ };
14
+
15
+ const RequestInterceptor = (config: AxiosRequestConfig | any) => {
16
+ const token = storageHelper.getItem(storageHelper.STORAGE_KEYS.AUTH_TOKEN);
17
+ config.headers.device = Platform.OS;
18
+
19
+ if (token) {
20
+ config.headers.Authorization = `Bearer ${token}`;
21
+ }
22
+ return config;
23
+ };
24
+
25
+ axiosInstance.interceptors.request.use(RequestInterceptor);
26
+
27
+ axiosInstance.interceptors.response.use(ResponseInterceptor, error => {
28
+ if (error.response) {
29
+ if (error.response.status === 403) {
30
+ // Unauthorized
31
+ resetAndNavigate(Routes.AuthStack);
32
+ }
33
+ return Promise.reject(error);
34
+ } else if (error.request) {
35
+ return Promise.reject(error);
36
+ } else {
37
+ return Promise.reject(error);
38
+ }
39
+ });
40
+
41
+ export { axiosInstance };
@@ -0,0 +1,40 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
2
+ import { QUERY_KEY } from './queryKeys';
3
+ import { axiosInstance } from './axiosInstance';
4
+ import { GetNotesResponse, Note } from '../types/services.types';
5
+ import Toast from 'react-native-toast-message';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { goBack } from '../utils/navigationUtils';
8
+
9
+ export const useGetNotesQuery = () => {
10
+ return useQuery({
11
+ queryKey: [QUERY_KEY.GET_NOTES],
12
+ queryFn: async () => {
13
+ const response = await axiosInstance.get<GetNotesResponse>('/notes');
14
+ if (response.status === 200) {
15
+ return response.data;
16
+ }
17
+ throw new Error('Something went wrong');
18
+ },
19
+ });
20
+ };
21
+
22
+ export const useAddNoteMutation = () => {
23
+ const queryClient = useQueryClient();
24
+ const { t } = useTranslation();
25
+ return useMutation({
26
+ mutationFn: async (note: Omit<Note, 'id'>) => {
27
+ const response = await axiosInstance.post<Note>('/notes', note);
28
+ return response.data;
29
+ },
30
+ onSuccess: () => {
31
+ queryClient.invalidateQueries({ queryKey: [QUERY_KEY.GET_NOTES] });
32
+ Toast.show({
33
+ type: 'success',
34
+ text1: t('common.success'),
35
+ text2: t('common.noteCreated'),
36
+ });
37
+ goBack();
38
+ },
39
+ });
40
+ };
@@ -0,0 +1,4 @@
1
+ export enum QUERY_KEY {
2
+ GET_NOTES = 'GET-NOTES',
3
+ CREATE_NOTE = 'CREATE-NOTE',
4
+ }
@@ -1,7 +1,53 @@
1
1
  import { ReactNode } from 'react';
2
- import { StatusBarStyle, StyleProp, ViewStyle } from 'react-native';
2
+ import {
3
+ StatusBarStyle,
4
+ StyleProp,
5
+ TextProps,
6
+ TextStyle,
7
+ ViewStyle,
8
+ } from 'react-native';
3
9
  import { Edges } from 'react-native-safe-area-context';
4
10
 
11
+ export type AppTextSize =
12
+ | 'xxsmall' // 8
13
+ | 'xsmall' // 10
14
+ | 'small' // 12
15
+ | 'normal' // 14
16
+ | 'body' // 16
17
+ | 'large' // 20
18
+ | 'xlarge' // 24
19
+ | 'xxlarge' // 32
20
+ | number;
21
+
22
+ export type AppTextVariant =
23
+ | 'h1'
24
+ | 'h2'
25
+ | 'h3'
26
+ | 'body1'
27
+ | 'body2'
28
+ | 'caption'
29
+ | 'bold'
30
+ | 'semiBold'
31
+ | 'medium'
32
+ | 'regular'
33
+ | 'light';
34
+
35
+ export type AppTextTransform =
36
+ | 'uppercase'
37
+ | 'lowercase'
38
+ | 'capitalize'
39
+ | 'none';
40
+
41
+ export type AppTextProps = TextProps & {
42
+ children?: ReactNode;
43
+ size?: AppTextSize;
44
+ variant?: AppTextVariant;
45
+ color?: string;
46
+ fontFamily?: string;
47
+ transform?: AppTextTransform;
48
+ style?: StyleProp<TextStyle>;
49
+ };
50
+
5
51
  export type FullScreenContainerProps = {
6
52
  children: ReactNode;
7
53
  style?: StyleProp<ViewStyle>;
@@ -13,6 +13,7 @@ export type RootStackParamList = {
13
13
 
14
14
  export type MainTabParamList = {
15
15
  [Routes.HomeScreen]: undefined;
16
+ [Routes.NoteScreen]: undefined;
16
17
  [Routes.ProfileScreen]: undefined;
17
18
  };
18
19
 
@@ -24,6 +25,7 @@ export type AuthStackParamList = {
24
25
  export type AppStackParamList = {
25
26
  [Routes.MainTab]: undefined;
26
27
  [Routes.SettingsScreen]: undefined;
28
+ [Routes.AddNoteScreen]: undefined;
27
29
  };
28
30
 
29
31
  export type ParamsType = RootStackParamList &
@@ -0,0 +1,6 @@
1
+ export type Note = {
2
+ id: string;
3
+ title: string;
4
+ description: string;
5
+ };
6
+ export type GetNotesResponse = Note[];
@@ -5,6 +5,8 @@ export const storage = createMMKV();
5
5
  enum STORAGE_KEYS {
6
6
  USER = 'user',
7
7
  LANGUAGE = 'language',
8
+ THEME = 'theme',
9
+ AUTH_TOKEN = 'auth_token',
8
10
  }
9
11
 
10
12
  const saveItem = (key: STORAGE_KEYS, value: string) => {
@@ -56,3 +56,9 @@ export const ProfileUpdateSchema = Yup.object().shape({
56
56
  .matches(/^[0-9]{10}$/, 'Phone number must be 10 digits')
57
57
  .optional(),
58
58
  });
59
+
60
+ // Note Validation Schema
61
+ export const NoteSchema = Yup.object().shape({
62
+ title: Yup.string().required('Title is required'),
63
+ description: Yup.string().required('Description is required'),
64
+ });
package/README.md CHANGED
@@ -7,7 +7,7 @@ Welcome to **MMTemplate**! This is a robust and modern React Native template bui
7
7
  To initialize a new project using this template, run the following command:
8
8
 
9
9
  ```bash
10
- npx @react-native-community/cli@latest init AwesomeProject --template https://github.com/modhamanish/mm-template
10
+ npx @react-native-community/cli@latest init AwesomeProject --template @modhamanish/rn-mm-template
11
11
  ```
12
12
 
13
13
  Replace `AwesomeProject` with your desired project name.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modhamanish/rn-mm-template",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A robust and modern React Native template built with TypeScript, designed to jumpstart your mobile application development.",
5
5
  "repository": "https://github.com/modhamanish/mm-template.git",
6
6
  "author": "Manish Modha",