@modhamanish/rn-mm-template 1.0.2 → 1.0.4
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/MMTemplate/App.tsx +15 -2
- package/MMTemplate/README.md +53 -0
- package/MMTemplate/package.json +5 -2
- package/MMTemplate/src/components/AppText.tsx +125 -0
- package/MMTemplate/src/components/CustomToast.tsx +8 -6
- package/MMTemplate/src/components/FeatureItem.tsx +11 -8
- package/MMTemplate/src/components/InfoCard.tsx +10 -6
- package/MMTemplate/src/components/LanguageSwitcher.tsx +8 -7
- package/MMTemplate/src/components/TextInput.tsx +214 -23
- package/MMTemplate/src/components/ThemeSwitcher.tsx +12 -7
- package/MMTemplate/src/locales/en.json +19 -2
- package/MMTemplate/src/locales/hi.json +19 -2
- package/MMTemplate/src/navigation/AppStack.tsx +2 -0
- package/MMTemplate/src/navigation/MainTab.tsx +15 -4
- package/MMTemplate/src/navigation/routes.ts +2 -0
- package/MMTemplate/src/screens/AddNoteScreen.tsx +155 -0
- package/MMTemplate/src/screens/HomeScreen.tsx +60 -33
- package/MMTemplate/src/screens/LoginScreen.tsx +67 -25
- package/MMTemplate/src/screens/NoteScreen.tsx +241 -0
- package/MMTemplate/src/screens/ProfileScreen.tsx +26 -25
- package/MMTemplate/src/screens/SettingsScreen.tsx +17 -16
- package/MMTemplate/src/screens/WelcomeScreen.tsx +23 -23
- package/MMTemplate/src/services/axiosInstance.ts +41 -0
- package/MMTemplate/src/services/note.query.ts +40 -0
- package/MMTemplate/src/services/queryKeys.ts +4 -0
- package/MMTemplate/src/types/components.types.ts +47 -1
- package/MMTemplate/src/types/navigation.types.ts +2 -0
- package/MMTemplate/src/types/services.types.ts +6 -0
- package/MMTemplate/src/utils/storageHelper.ts +1 -0
- package/MMTemplate/src/utils/validationSchemas.ts +6 -0
- package/README.md +34 -0
- package/package.json +1 -1
package/MMTemplate/App.tsx
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
3
|
+
import { KeyboardProvider } from 'react-native-keyboard-controller';
|
|
4
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
5
|
+
|
|
3
6
|
import { ThemeProvider } from './src/context/ThemeContext';
|
|
4
7
|
import AppNavigator from './src/navigation/AppNavigator';
|
|
5
|
-
import { KeyboardProvider } from 'react-native-keyboard-controller';
|
|
6
8
|
|
|
7
9
|
import Toast, { ToastConfigParams } from 'react-native-toast-message';
|
|
8
10
|
import { CustomToast } from './src/components/CustomToast';
|
|
9
11
|
import { AuthProvider } from './src/context/AuthContext';
|
|
10
12
|
import './src/utils/i18n';
|
|
11
13
|
|
|
14
|
+
const queryClient = new QueryClient({
|
|
15
|
+
defaultOptions: {
|
|
16
|
+
queries: {
|
|
17
|
+
refetchOnWindowFocus: false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
12
22
|
const toastConfig = {
|
|
13
23
|
error: ({
|
|
14
24
|
text1,
|
|
@@ -23,13 +33,16 @@ const toastConfig = {
|
|
|
23
33
|
onPress?: () => void;
|
|
24
34
|
}>) => <CustomToast text1={text1} onPress={props?.onPress} type="success" />,
|
|
25
35
|
};
|
|
36
|
+
|
|
26
37
|
const App = () => {
|
|
27
38
|
return (
|
|
28
39
|
<KeyboardProvider>
|
|
29
40
|
<SafeAreaProvider>
|
|
30
41
|
<ThemeProvider>
|
|
31
42
|
<AuthProvider>
|
|
32
|
-
<
|
|
43
|
+
<QueryClientProvider client={queryClient}>
|
|
44
|
+
<AppNavigator />
|
|
45
|
+
</QueryClientProvider>
|
|
33
46
|
</AuthProvider>
|
|
34
47
|
</ThemeProvider>
|
|
35
48
|
<Toast config={toastConfig} />
|
package/MMTemplate/README.md
CHANGED
|
@@ -33,11 +33,64 @@ src/
|
|
|
33
33
|
├── mock/ # Mock data for testing and development
|
|
34
34
|
├── navigation/ # Navigation configuration (Stacks, Stacks, etc.)
|
|
35
35
|
├── screens/ # Screen components (Views)
|
|
36
|
+
├── services/ # Data fetching and API services (React Query)
|
|
36
37
|
├── theme/ # Theme configuration (Colors, Typography, Spacing)
|
|
37
38
|
├── types/ # Global TypeScript types and interfaces
|
|
38
39
|
└── utils/ # Helper functions and utilities
|
|
39
40
|
```
|
|
40
41
|
|
|
42
|
+
### Key Files & Directories
|
|
43
|
+
|
|
44
|
+
| Directory / File | Path | Description |
|
|
45
|
+
| :--- | :--- | :--- |
|
|
46
|
+
| **`assets/`** | `src/assets/` | Stores static assets such as images, fonts, and icons. |
|
|
47
|
+
| **`components/`** | `src/components/` | Contains reusable UI components used throughout the application. |
|
|
48
|
+
| **`context/`** | `src/context/` | Holds React Context definitions for global state management. |
|
|
49
|
+
| **`locales/`** | `src/locales/` | Contains translation files for internationalization. |
|
|
50
|
+
| **`mock/`** | `src/mock/` | Stores mock data used for development and testing. |
|
|
51
|
+
| **`navigation/`** | `src/navigation/` | Contains all navigation-related configuration. |
|
|
52
|
+
| **`screens/`** | `src/screens/` | Contains all the screen components (pages) of the application. |
|
|
53
|
+
| **`services/`** | `src/services/` | Data fetching layer using **React Query** and **Axios**. |
|
|
54
|
+
| **`theme/`** | `src/theme/` | Centralized theme configuration (e.g., Colors, Typography). |
|
|
55
|
+
| **`types/`** | `src/types/` | Stores TypeScript type definitions and interfaces. |
|
|
56
|
+
| **`utils/`** | `src/utils/` | Contains utility functions and helper classes. |
|
|
57
|
+
|
|
58
|
+
Navigation automatically switches between these stacks based on the `user` state in `AuthContext`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 🚀 Data Fetching (React Query)
|
|
63
|
+
|
|
64
|
+
MMTemplate uses **TanStack Query (React Query) v5** for server state management and **Axios** for API requests.
|
|
65
|
+
|
|
66
|
+
### 1. Services Structure
|
|
67
|
+
- **`axiosInstance.ts`**: Configured Axios instance with base URL and interceptors.
|
|
68
|
+
- **`queryKeys.ts`**: Centralized keys for consistency and easy invalidation.
|
|
69
|
+
- **`*.query.ts`**: Feature-specific hooks for fetching and mutating data.
|
|
70
|
+
|
|
71
|
+
### 2. Usage Example
|
|
72
|
+
To fetch data, use a query hook defined in `src/services`:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { useGetNotesQuery } from '../services/note.query';
|
|
76
|
+
|
|
77
|
+
const { data, isLoading, error } = useGetNotesQuery();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
To update data, use a mutation hook:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { useAddNoteMutation } from '../services/note.query';
|
|
84
|
+
|
|
85
|
+
const { mutate, isPending } = useAddNoteMutation();
|
|
86
|
+
const handleSave = () => mutate({ title: 'New Note', content: '...' });
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 3. Global Configuration
|
|
90
|
+
The `QueryClient` is pre-configured in `App.tsx` with optimized defaults (e.g., `refetchOnWindowFocus: false`).
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
41
94
|
## 🛠 Prerequisites
|
|
42
95
|
|
|
43
96
|
Before you begin, ensure you have the following installed on your machine:
|
package/MMTemplate/package.json
CHANGED
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
"@react-navigation/bottom-tabs": "^7.9.0",
|
|
15
15
|
"@react-navigation/native": "^7.1.26",
|
|
16
16
|
"@react-navigation/native-stack": "^7.9.0",
|
|
17
|
+
"@tanstack/react-query": "^5.90.20",
|
|
18
|
+
"axios": "^1.13.4",
|
|
17
19
|
"formik": "^2.4.9",
|
|
18
20
|
"i18next": "^25.7.3",
|
|
19
21
|
"react": "19.2.0",
|
|
20
22
|
"react-i18next": "^16.5.1",
|
|
21
23
|
"react-native": "0.83.1",
|
|
22
24
|
"react-native-keyboard-controller": "^1.20.3",
|
|
23
|
-
"react-native-mmkv": "^4.1.
|
|
24
|
-
"react-native-nitro-modules": "^0.
|
|
25
|
+
"react-native-mmkv": "^4.1.2",
|
|
26
|
+
"react-native-nitro-modules": "^0.33.9",
|
|
25
27
|
"react-native-reanimated": "^4.2.1",
|
|
26
28
|
"react-native-safe-area-context": "^5.6.2",
|
|
27
29
|
"react-native-screens": "^4.19.0",
|
|
@@ -40,6 +42,7 @@
|
|
|
40
42
|
"@react-native/eslint-config": "0.83.1",
|
|
41
43
|
"@react-native/metro-config": "0.83.1",
|
|
42
44
|
"@react-native/typescript-config": "0.83.1",
|
|
45
|
+
"@tanstack/eslint-plugin-query": "^5.91.4",
|
|
43
46
|
"@types/jest": "^29.5.13",
|
|
44
47
|
"@types/react": "^19.2.0",
|
|
45
48
|
"@types/react-test-renderer": "^19.1.0",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React, { FC, memo } from 'react';
|
|
2
|
+
import { Text, TextStyle } from 'react-native';
|
|
3
|
+
import { useTheme } from '../context/ThemeContext';
|
|
4
|
+
import { AppTextProps, AppTextSize } from '../types/components.types';
|
|
5
|
+
|
|
6
|
+
const FONTS: Record<string, string> | undefined = {
|
|
7
|
+
// Define custom font families here. If empty or undefined, the component will use default system fonts with font weights.
|
|
8
|
+
// extraBold: 'Poppins-ExtraBold',
|
|
9
|
+
// bold: 'Poppins-Bold',
|
|
10
|
+
// semiBold: 'Poppins-SemiBold',
|
|
11
|
+
// medium: 'Poppins-Medium',
|
|
12
|
+
// light: 'Poppins-Light',
|
|
13
|
+
// regular: 'Poppins-Regular',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const SIZES: Record<string, number> = {
|
|
17
|
+
xxsmall: 8,
|
|
18
|
+
xsmall: 10,
|
|
19
|
+
small: 12,
|
|
20
|
+
normal: 14,
|
|
21
|
+
body: 16,
|
|
22
|
+
large: 20,
|
|
23
|
+
xlarge: 24,
|
|
24
|
+
xxlarge: 32,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const AppText: FC<AppTextProps> = ({
|
|
28
|
+
children,
|
|
29
|
+
size = 'normal',
|
|
30
|
+
variant = 'regular',
|
|
31
|
+
color,
|
|
32
|
+
fontFamily,
|
|
33
|
+
transform,
|
|
34
|
+
style,
|
|
35
|
+
...props
|
|
36
|
+
}) => {
|
|
37
|
+
const { colors } = useTheme();
|
|
38
|
+
|
|
39
|
+
const getFontSize = (s: AppTextSize): number => {
|
|
40
|
+
if (typeof s === 'number') return s;
|
|
41
|
+
return SIZES[s as string] || SIZES.normal;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getTransform = (t?: string): any => {
|
|
45
|
+
if (!t) return undefined;
|
|
46
|
+
switch (t) {
|
|
47
|
+
case 'capital':
|
|
48
|
+
case 'uppercase':
|
|
49
|
+
return 'uppercase';
|
|
50
|
+
case 'small':
|
|
51
|
+
case 'lowercase':
|
|
52
|
+
return 'lowercase';
|
|
53
|
+
case 'first char capital':
|
|
54
|
+
case 'capitalize':
|
|
55
|
+
return 'capitalize';
|
|
56
|
+
default:
|
|
57
|
+
return t;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const getVariantStyle = (v: string): TextStyle => {
|
|
62
|
+
const hasFonts = !!FONTS && Object.keys(FONTS).length > 0;
|
|
63
|
+
switch (v) {
|
|
64
|
+
case 'h1':
|
|
65
|
+
return hasFonts
|
|
66
|
+
? { fontSize: 32, fontFamily: FONTS.extraBold }
|
|
67
|
+
: { fontSize: 32, fontWeight: '800' };
|
|
68
|
+
case 'h2':
|
|
69
|
+
return hasFonts
|
|
70
|
+
? { fontSize: 24, fontFamily: FONTS.bold }
|
|
71
|
+
: { fontSize: 24, fontWeight: '700' };
|
|
72
|
+
case 'h3':
|
|
73
|
+
return hasFonts
|
|
74
|
+
? { fontSize: 20, fontFamily: FONTS.bold }
|
|
75
|
+
: { fontSize: 20, fontWeight: '700' };
|
|
76
|
+
case 'body1':
|
|
77
|
+
return hasFonts
|
|
78
|
+
? { fontSize: 16, fontFamily: FONTS.regular }
|
|
79
|
+
: { fontSize: 16, fontWeight: '400' };
|
|
80
|
+
case 'body2':
|
|
81
|
+
return hasFonts
|
|
82
|
+
? { fontSize: 14, fontFamily: FONTS.regular }
|
|
83
|
+
: { fontSize: 14, fontWeight: '400' };
|
|
84
|
+
case 'bold':
|
|
85
|
+
return hasFonts ? { fontFamily: FONTS.bold } : { fontWeight: '700' };
|
|
86
|
+
case 'semiBold':
|
|
87
|
+
return hasFonts
|
|
88
|
+
? { fontFamily: FONTS.semiBold }
|
|
89
|
+
: { fontWeight: '600' };
|
|
90
|
+
case 'medium':
|
|
91
|
+
return hasFonts ? { fontFamily: FONTS.medium } : { fontWeight: '500' };
|
|
92
|
+
case 'light':
|
|
93
|
+
return hasFonts ? { fontFamily: FONTS.light } : { fontWeight: '300' };
|
|
94
|
+
case 'regular':
|
|
95
|
+
return hasFonts ? { fontFamily: FONTS.regular } : { fontWeight: '400' };
|
|
96
|
+
default:
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const variantStyle = getVariantStyle(variant);
|
|
102
|
+
|
|
103
|
+
// If prop fontFamily is provided, it should override variant's fontFamily
|
|
104
|
+
// And we should still prevent variant's fontWeight (if any) from conflicting with it.
|
|
105
|
+
if (fontFamily && variantStyle.fontWeight) {
|
|
106
|
+
delete variantStyle.fontWeight;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const combinedStyles: TextStyle = {
|
|
110
|
+
fontSize: getFontSize(size),
|
|
111
|
+
color: color || colors.textColor,
|
|
112
|
+
textTransform: getTransform(transform),
|
|
113
|
+
...variantStyle,
|
|
114
|
+
...(fontFamily ? { fontFamily } : {}),
|
|
115
|
+
...(style as object),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<Text style={combinedStyles} allowFontScaling={false} {...props}>
|
|
120
|
+
{children}
|
|
121
|
+
</Text>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default memo(AppText);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { StyleSheet,
|
|
2
|
+
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import AppText from './AppText';
|
|
3
4
|
|
|
4
5
|
type CustomToastProps = {
|
|
5
6
|
text1?: string;
|
|
@@ -12,10 +13,14 @@ export const CustomToast = ({ text1, onPress, type }: CustomToastProps) => {
|
|
|
12
13
|
|
|
13
14
|
return (
|
|
14
15
|
<View style={[styles.container, { backgroundColor }]}>
|
|
15
|
-
<
|
|
16
|
+
<AppText variant="medium" style={styles.text}>
|
|
17
|
+
{text1}
|
|
18
|
+
</AppText>
|
|
16
19
|
{onPress && (
|
|
17
20
|
<TouchableOpacity onPress={onPress}>
|
|
18
|
-
<
|
|
21
|
+
<AppText variant="semiBold" size="body" style={styles.buttonText}>
|
|
22
|
+
OK
|
|
23
|
+
</AppText>
|
|
19
24
|
</TouchableOpacity>
|
|
20
25
|
)}
|
|
21
26
|
</View>
|
|
@@ -36,11 +41,8 @@ const styles = StyleSheet.create({
|
|
|
36
41
|
text: {
|
|
37
42
|
flex: 1,
|
|
38
43
|
color: 'white',
|
|
39
|
-
fontWeight: '500',
|
|
40
44
|
},
|
|
41
45
|
buttonText: {
|
|
42
46
|
color: 'white',
|
|
43
|
-
fontSize: 16,
|
|
44
|
-
fontWeight: '600',
|
|
45
47
|
},
|
|
46
48
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, StyleSheet } from 'react-native';
|
|
3
|
+
import AppText from './AppText';
|
|
3
4
|
import { useTheme } from '../context/ThemeContext';
|
|
4
5
|
import { ThemeType } from '../theme/Colors';
|
|
5
6
|
|
|
@@ -19,10 +20,16 @@ const FeatureItem: React.FC<FeatureItemProps> = ({
|
|
|
19
20
|
|
|
20
21
|
return (
|
|
21
22
|
<View style={styles.container}>
|
|
22
|
-
<
|
|
23
|
+
<AppText size="large" style={styles.icon}>
|
|
24
|
+
{icon}
|
|
25
|
+
</AppText>
|
|
23
26
|
<View style={styles.textContainer}>
|
|
24
|
-
<
|
|
25
|
-
|
|
27
|
+
<AppText variant="semiBold" size={15} style={styles.title}>
|
|
28
|
+
{title}
|
|
29
|
+
</AppText>
|
|
30
|
+
<AppText size={13} style={styles.description}>
|
|
31
|
+
{description}
|
|
32
|
+
</AppText>
|
|
26
33
|
</View>
|
|
27
34
|
</View>
|
|
28
35
|
);
|
|
@@ -38,7 +45,6 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
38
45
|
marginBottom: 12,
|
|
39
46
|
},
|
|
40
47
|
icon: {
|
|
41
|
-
fontSize: 20,
|
|
42
48
|
marginRight: 12,
|
|
43
49
|
marginTop: 2,
|
|
44
50
|
},
|
|
@@ -46,13 +52,10 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
46
52
|
flex: 1,
|
|
47
53
|
},
|
|
48
54
|
title: {
|
|
49
|
-
fontSize: 15,
|
|
50
|
-
fontWeight: '600',
|
|
51
55
|
color: colors.textColor,
|
|
52
56
|
marginBottom: 2,
|
|
53
57
|
},
|
|
54
58
|
description: {
|
|
55
|
-
fontSize: 13,
|
|
56
59
|
color: colors.textColor + 'CC',
|
|
57
60
|
lineHeight: 18,
|
|
58
61
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, StyleSheet } from 'react-native';
|
|
3
|
+
import AppText from './AppText';
|
|
3
4
|
import { useTheme } from '../context/ThemeContext';
|
|
4
5
|
import { ThemeType } from '../theme/Colors';
|
|
5
6
|
|
|
@@ -16,8 +17,14 @@ const InfoCard: React.FC<InfoCardProps> = ({ title, children, icon }) => {
|
|
|
16
17
|
return (
|
|
17
18
|
<View style={styles.card}>
|
|
18
19
|
<View style={styles.header}>
|
|
19
|
-
{icon &&
|
|
20
|
-
|
|
20
|
+
{icon && (
|
|
21
|
+
<AppText size="xlarge" style={styles.icon}>
|
|
22
|
+
{icon}
|
|
23
|
+
</AppText>
|
|
24
|
+
)}
|
|
25
|
+
<AppText variant="bold" size={18} style={styles.title}>
|
|
26
|
+
{title}
|
|
27
|
+
</AppText>
|
|
21
28
|
</View>
|
|
22
29
|
<View style={styles.content}>{children}</View>
|
|
23
30
|
</View>
|
|
@@ -47,12 +54,9 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
47
54
|
marginBottom: 12,
|
|
48
55
|
},
|
|
49
56
|
icon: {
|
|
50
|
-
fontSize: 24,
|
|
51
57
|
marginRight: 8,
|
|
52
58
|
},
|
|
53
59
|
title: {
|
|
54
|
-
fontSize: 18,
|
|
55
|
-
fontWeight: '700',
|
|
56
60
|
color: colors.primary,
|
|
57
61
|
},
|
|
58
62
|
content: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
+
import AppText from './AppText';
|
|
3
4
|
import { useTranslation } from 'react-i18next';
|
|
4
5
|
import { useTheme } from '../context/ThemeContext';
|
|
5
6
|
import { ThemeType } from '../theme/Colors';
|
|
@@ -21,27 +22,29 @@ const LanguageSwitcher = () => {
|
|
|
21
22
|
style={[styles.button, i18n.language === 'en' && styles.activeButton]}
|
|
22
23
|
onPress={() => changeLanguage('en')}
|
|
23
24
|
>
|
|
24
|
-
<
|
|
25
|
+
<AppText
|
|
26
|
+
variant="semiBold"
|
|
25
27
|
style={[
|
|
26
28
|
styles.buttonText,
|
|
27
29
|
i18n.language === 'en' && styles.activeButtonText,
|
|
28
30
|
]}
|
|
29
31
|
>
|
|
30
32
|
🇬🇧 English
|
|
31
|
-
</
|
|
33
|
+
</AppText>
|
|
32
34
|
</TouchableOpacity>
|
|
33
35
|
<TouchableOpacity
|
|
34
36
|
style={[styles.button, i18n.language === 'hi' && styles.activeButton]}
|
|
35
37
|
onPress={() => changeLanguage('hi')}
|
|
36
38
|
>
|
|
37
|
-
<
|
|
39
|
+
<AppText
|
|
40
|
+
variant="semiBold"
|
|
38
41
|
style={[
|
|
39
42
|
styles.buttonText,
|
|
40
43
|
i18n.language === 'hi' && styles.activeButtonText,
|
|
41
44
|
]}
|
|
42
45
|
>
|
|
43
46
|
🇮🇳 हिंदी
|
|
44
|
-
</
|
|
47
|
+
</AppText>
|
|
45
48
|
</TouchableOpacity>
|
|
46
49
|
</View>
|
|
47
50
|
);
|
|
@@ -70,8 +73,6 @@ const getStyles = ({ colors }: ThemeType) =>
|
|
|
70
73
|
backgroundColor: colors.primary,
|
|
71
74
|
},
|
|
72
75
|
buttonText: {
|
|
73
|
-
fontSize: 14,
|
|
74
|
-
fontWeight: '600',
|
|
75
76
|
color: colors.primary,
|
|
76
77
|
},
|
|
77
78
|
activeButtonText: {
|