@modhamanish/rn-mm-template 1.0.4 → 1.0.5

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 (48) hide show
  1. package/MMTemplate/.eslintrc.js +95 -1
  2. package/MMTemplate/.husky/pre-commit +2 -0
  3. package/MMTemplate/.prettierrc.js +2 -0
  4. package/MMTemplate/App.tsx +27 -21
  5. package/MMTemplate/README.md +76 -35
  6. package/MMTemplate/__tests__/App.test.tsx +5 -3
  7. package/MMTemplate/babel.config.js +24 -1
  8. package/MMTemplate/index.js +1 -0
  9. package/MMTemplate/package.json +22 -2
  10. package/MMTemplate/src/components/AnimationView.tsx +54 -69
  11. package/MMTemplate/src/components/AppText.tsx +7 -4
  12. package/MMTemplate/src/components/CustomAlert.tsx +203 -0
  13. package/MMTemplate/src/components/CustomToast.tsx +2 -1
  14. package/MMTemplate/src/components/ErrorBoundaryFallback.tsx +127 -0
  15. package/MMTemplate/src/components/FeatureItem.tsx +8 -6
  16. package/MMTemplate/src/components/FullScreenContainer.tsx +9 -7
  17. package/MMTemplate/src/components/InfoCard.tsx +8 -6
  18. package/MMTemplate/src/components/LanguageSwitcher.tsx +8 -6
  19. package/MMTemplate/src/components/TextInput.tsx +25 -15
  20. package/MMTemplate/src/components/ThemeSwitcher.tsx +4 -3
  21. package/MMTemplate/src/context/AuthContext.tsx +5 -4
  22. package/MMTemplate/src/context/ThemeContext.tsx +10 -19
  23. package/MMTemplate/src/locales/en.json +4 -1
  24. package/MMTemplate/src/locales/hi.json +4 -1
  25. package/MMTemplate/src/navigation/AppNavigator.tsx +7 -8
  26. package/MMTemplate/src/navigation/AppStack.tsx +6 -6
  27. package/MMTemplate/src/navigation/AuthCheck.tsx +11 -10
  28. package/MMTemplate/src/navigation/AuthStack.tsx +6 -4
  29. package/MMTemplate/src/navigation/MainTab.tsx +19 -13
  30. package/MMTemplate/src/screens/AddNoteScreen.tsx +20 -14
  31. package/MMTemplate/src/screens/HomeScreen.tsx +21 -15
  32. package/MMTemplate/src/screens/LoginScreen.tsx +21 -18
  33. package/MMTemplate/src/screens/NoteScreen.tsx +18 -16
  34. package/MMTemplate/src/screens/ProfileScreen.tsx +16 -13
  35. package/MMTemplate/src/screens/SettingsScreen.tsx +14 -11
  36. package/MMTemplate/src/screens/WelcomeScreen.tsx +19 -13
  37. package/MMTemplate/src/services/axiosInstance.ts +7 -5
  38. package/MMTemplate/src/services/note.query.ts +7 -5
  39. package/MMTemplate/src/theme/{Colors.ts → colors.ts} +6 -0
  40. package/MMTemplate/src/types/components.types.ts +38 -0
  41. package/MMTemplate/src/types/navigation.types.ts +1 -1
  42. package/MMTemplate/src/utils/i18n.ts +8 -6
  43. package/MMTemplate/src/utils/navigationUtils.ts +2 -1
  44. package/MMTemplate/src/utils/storageHelper.ts +8 -8
  45. package/MMTemplate/src/utils/utilsHelper.ts +1 -0
  46. package/MMTemplate/tsconfig.json +27 -0
  47. package/README.md +3 -1
  48. package/package.json +1 -1
@@ -1,7 +1,8 @@
1
1
  import React, { FC, memo } from 'react';
2
2
  import { Text, TextStyle } from 'react-native';
3
- import { useTheme } from '../context/ThemeContext';
4
- import { AppTextProps, AppTextSize } from '../types/components.types';
3
+
4
+ import { AppTextProps, AppTextSize } from '@app-types/components.types';
5
+ import { useTheme } from '@context/ThemeContext';
5
6
 
6
7
  const FONTS: Record<string, string> | undefined = {
7
8
  // Define custom font families here. If empty or undefined, the component will use default system fonts with font weights.
@@ -41,7 +42,9 @@ const AppText: FC<AppTextProps> = ({
41
42
  return SIZES[s as string] || SIZES.normal;
42
43
  };
43
44
 
44
- const getTransform = (t?: string): any => {
45
+ const getTransform = (
46
+ t?: string,
47
+ ): 'uppercase' | 'lowercase' | 'capitalize' | undefined => {
45
48
  if (!t) return undefined;
46
49
  switch (t) {
47
50
  case 'capital':
@@ -54,7 +57,7 @@ const AppText: FC<AppTextProps> = ({
54
57
  case 'capitalize':
55
58
  return 'capitalize';
56
59
  default:
57
- return t;
60
+ return undefined;
58
61
  }
59
62
  };
60
63
 
@@ -0,0 +1,203 @@
1
+ import React, { FC, memo, useState, useMemo } from 'react';
2
+ import { Modal, StyleSheet, TouchableOpacity, View } from 'react-native';
3
+
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import AppText from '@components/AppText';
7
+ import { useTheme } from '@src/context/ThemeContext';
8
+ import { ThemeType } from '@src/theme/colors';
9
+ import { AlertOptionsProps } from '@src/types/components.types';
10
+ import { hexWithOpacity } from '@src/utils/utilsHelper';
11
+
12
+ let externalShow: ((opts: AlertOptionsProps) => void) | null = null;
13
+
14
+ const CustomAlert: FC = () => {
15
+ const [stack, setStack] = useState<AlertOptionsProps[]>([]);
16
+ const { t } = useTranslation();
17
+ const theme = useTheme();
18
+ const { colors } = theme;
19
+ const styles = useMemo(() => getStyles(theme), [theme]);
20
+
21
+ const show = (opts: AlertOptionsProps) => {
22
+ const item: AlertOptionsProps = {
23
+ title: opts.title || '',
24
+ message: opts.message || '',
25
+ onConfirm: opts.onConfirm,
26
+ onCancel: opts.onCancel,
27
+ onClose: opts.onClose,
28
+ confirmText: opts.confirmText || t('common.ok'),
29
+ cancelText: opts.cancelText || t('common.cancel'),
30
+ boxStyle: opts.boxStyle,
31
+ titleStyle: opts.titleStyle,
32
+ messageStyle: opts.messageStyle,
33
+ confirmButtonStyle: opts.confirmButtonStyle,
34
+ cancelButtonStyle: opts.cancelButtonStyle,
35
+ confirmTextStyle: opts.confirmTextStyle,
36
+ cancelTextStyle: opts.cancelTextStyle,
37
+ isCancellable: opts.isCancellable || false,
38
+ isError: opts.isError || false,
39
+ };
40
+
41
+ setStack(prev => [...prev, item]);
42
+ };
43
+
44
+ const hideTop = () => {
45
+ setStack(prev => prev.slice(0, -1));
46
+ };
47
+
48
+ externalShow = show;
49
+
50
+ if (stack.length === 0) {
51
+ return null;
52
+ }
53
+
54
+ const item = stack[stack.length - 1];
55
+
56
+ return (
57
+ <Modal visible transparent animationType="fade">
58
+ <TouchableOpacity
59
+ style={styles.overlay}
60
+ activeOpacity={1}
61
+ onPress={() => {
62
+ if (item.isCancellable || (!item.onCancel && !item.onConfirm)) {
63
+ hideTop();
64
+ item.onClose && item.onClose();
65
+ }
66
+ }}
67
+ >
68
+ <TouchableOpacity
69
+ activeOpacity={1}
70
+ onPress={() => {}}
71
+ style={[styles.box, item.boxStyle]}
72
+ >
73
+ {!!item.title && (
74
+ <AppText
75
+ variant="semiBold"
76
+ size="xlarge"
77
+ style={[
78
+ styles.title,
79
+ { color: item.isError ? colors.error : colors.primary },
80
+ item.titleStyle,
81
+ ]}
82
+ >
83
+ {item.title}
84
+ </AppText>
85
+ )}
86
+ {!!item.message && (
87
+ <AppText
88
+ variant="regular"
89
+ size="normal"
90
+ color={colors.textColor}
91
+ style={[styles.message, item.messageStyle]}
92
+ >
93
+ {item.message}
94
+ </AppText>
95
+ )}
96
+
97
+ {item.onCancel || item.onConfirm ? (
98
+ <View style={styles.btnRow}>
99
+ {Boolean(item.onCancel || item.isCancellable) && (
100
+ <TouchableOpacity
101
+ style={[
102
+ styles.btn,
103
+ { backgroundColor: colors.backgroundColor },
104
+ item.cancelButtonStyle,
105
+ ]}
106
+ onPress={() => {
107
+ hideTop();
108
+ item.onCancel && item.onCancel();
109
+ }}
110
+ >
111
+ <AppText
112
+ variant="medium"
113
+ color={colors.textColor}
114
+ style={item.cancelTextStyle}
115
+ >
116
+ {item.cancelText}
117
+ </AppText>
118
+ </TouchableOpacity>
119
+ )}
120
+
121
+ {item.onConfirm && (
122
+ <TouchableOpacity
123
+ style={[
124
+ styles.btn,
125
+ {
126
+ backgroundColor: item.isError
127
+ ? colors.error
128
+ : colors.primary,
129
+ },
130
+ item.confirmButtonStyle,
131
+ ]}
132
+ onPress={() => {
133
+ hideTop();
134
+ item.onConfirm && item.onConfirm();
135
+ }}
136
+ >
137
+ <AppText
138
+ variant="medium"
139
+ color={colors.white}
140
+ style={item.confirmTextStyle}
141
+ >
142
+ {item.confirmText}
143
+ </AppText>
144
+ </TouchableOpacity>
145
+ )}
146
+ </View>
147
+ ) : null}
148
+ </TouchableOpacity>
149
+ </TouchableOpacity>
150
+ </Modal>
151
+ );
152
+ };
153
+
154
+ const MemoAlert = memo(CustomAlert);
155
+
156
+ (
157
+ MemoAlert as typeof MemoAlert & { show: (opts: AlertOptionsProps) => void }
158
+ ).show = (opts: AlertOptionsProps) => externalShow && externalShow(opts);
159
+
160
+ export default MemoAlert as typeof MemoAlert & {
161
+ show: (opts: AlertOptionsProps) => void;
162
+ };
163
+
164
+ export const getStyles = ({ colors }: ThemeType) =>
165
+ StyleSheet.create({
166
+ overlay: {
167
+ flex: 1,
168
+ backgroundColor: hexWithOpacity(colors.black, 50),
169
+ justifyContent: 'center',
170
+ },
171
+ box: {
172
+ margin: 24,
173
+ padding: 24,
174
+ borderRadius: 16,
175
+ borderWidth: 1,
176
+ backgroundColor: colors.backgroundColor,
177
+ borderColor: colors.borderColor,
178
+ shadowColor: colors.textColor,
179
+ shadowOffset: { width: 0, height: 4 },
180
+ shadowOpacity: 0.1,
181
+ shadowRadius: 12,
182
+ elevation: 5,
183
+ },
184
+ title: {
185
+ marginBottom: 12,
186
+ },
187
+ message: {
188
+ lineHeight: 20,
189
+ },
190
+ btnRow: {
191
+ marginTop: 24,
192
+ flexDirection: 'row',
193
+ justifyContent: 'flex-end',
194
+ },
195
+ btn: {
196
+ paddingVertical: 10,
197
+ paddingHorizontal: 20,
198
+ marginLeft: 12,
199
+ borderRadius: 12,
200
+ minWidth: 80,
201
+ alignItems: 'center',
202
+ },
203
+ });
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { StyleSheet, TouchableOpacity, View } from 'react-native';
3
- import AppText from './AppText';
3
+
4
+ import AppText from '@components/AppText';
4
5
 
5
6
  type CustomToastProps = {
6
7
  text1?: string;
@@ -0,0 +1,127 @@
1
+ import React, { useMemo } from 'react';
2
+ import { StyleSheet, View, TouchableOpacity, ScrollView } from 'react-native';
3
+
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import AppText from '@components/AppText';
7
+ import FullScreenContainer from '@components/FullScreenContainer';
8
+ import { useTheme } from '@context/ThemeContext';
9
+ import { ThemeType } from '@src/theme/colors';
10
+ import { hexWithOpacity } from '@utils/utilsHelper';
11
+
12
+ interface Props {
13
+ error: Error;
14
+ resetError: () => void;
15
+ }
16
+
17
+ const ErrorBoundaryFallback = (props: Props) => {
18
+ const { t } = useTranslation();
19
+ const theme = useTheme();
20
+ const { colors } = theme;
21
+ const styles = useMemo(() => getStyles(theme), [theme]);
22
+
23
+ return (
24
+ <FullScreenContainer style={styles.container}>
25
+ <View style={styles.content}>
26
+ <View style={styles.iconContainer}>
27
+ <AppText style={styles.icon}>⚠️</AppText>
28
+ </View>
29
+
30
+ <AppText variant="h1" style={styles.title}>
31
+ {t('common.errorOccurred')}
32
+ </AppText>
33
+
34
+ <AppText variant="regular" style={styles.subtitle}>
35
+ {t('common.errorDescription')}
36
+ </AppText>
37
+
38
+ <View style={styles.errorBox}>
39
+ <ScrollView bounces={false}>
40
+ <AppText
41
+ size="small"
42
+ color={colors.primary}
43
+ style={styles.errorText}
44
+ >
45
+ {props.error.toString()}
46
+ </AppText>
47
+ </ScrollView>
48
+ </View>
49
+
50
+ <TouchableOpacity
51
+ style={styles.button}
52
+ onPress={props.resetError}
53
+ activeOpacity={0.8}
54
+ >
55
+ <AppText variant="semiBold" color={colors.white}>
56
+ {t('common.tryAgain')}
57
+ </AppText>
58
+ </TouchableOpacity>
59
+ </View>
60
+ </FullScreenContainer>
61
+ );
62
+ };
63
+
64
+ export const getStyles = (theme: ThemeType) => {
65
+ const { colors } = theme;
66
+ return StyleSheet.create({
67
+ container: {
68
+ flex: 1,
69
+ justifyContent: 'center',
70
+ padding: 24,
71
+ },
72
+ content: {
73
+ alignItems: 'center',
74
+ },
75
+ iconContainer: {
76
+ width: 80,
77
+ height: 80,
78
+ borderRadius: 40,
79
+ justifyContent: 'center',
80
+ alignItems: 'center',
81
+ marginBottom: 24,
82
+ backgroundColor: hexWithOpacity(colors.primary, 15),
83
+ },
84
+ icon: {
85
+ fontSize: 40,
86
+ },
87
+ title: {
88
+ textAlign: 'center',
89
+ marginBottom: 12,
90
+ },
91
+ subtitle: {
92
+ textAlign: 'center',
93
+ marginBottom: 32,
94
+ lineHeight: 22,
95
+ color: hexWithOpacity(colors.textColor, 80),
96
+ },
97
+ errorBox: {
98
+ width: '100%',
99
+ maxHeight: 200,
100
+ borderRadius: 12,
101
+ borderWidth: 1,
102
+ padding: 16,
103
+ marginBottom: 32,
104
+ backgroundColor: colors.backgroundColor,
105
+ borderColor: colors.borderColor,
106
+ },
107
+ errorText: {
108
+ lineHeight: 18,
109
+ fontFamily: 'monospace',
110
+ },
111
+ button: {
112
+ width: '100%',
113
+ height: 56,
114
+ borderRadius: 16,
115
+ justifyContent: 'center',
116
+ alignItems: 'center',
117
+ shadowColor: colors.black,
118
+ shadowOffset: { width: 0, height: 4 },
119
+ shadowOpacity: 0.1,
120
+ shadowRadius: 8,
121
+ elevation: 4,
122
+ backgroundColor: colors.primary,
123
+ },
124
+ });
125
+ };
126
+
127
+ export default ErrorBoundaryFallback;
@@ -1,8 +1,10 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
- import AppText from './AppText';
4
- import { useTheme } from '../context/ThemeContext';
5
- import { ThemeType } from '../theme/Colors';
3
+
4
+ import AppText from '@components/AppText';
5
+ import { useTheme } from '@context/ThemeContext';
6
+ import { ThemeType } from '@src/theme/colors';
7
+ import { hexWithOpacity } from '@utils/utilsHelper';
6
8
 
7
9
  interface FeatureItemProps {
8
10
  icon: string;
@@ -16,7 +18,7 @@ const FeatureItem: React.FC<FeatureItemProps> = ({
16
18
  description,
17
19
  }) => {
18
20
  const theme = useTheme();
19
- const styles = getStyles(theme);
21
+ const styles = useMemo(() => getStyles(theme), [theme]);
20
22
 
21
23
  return (
22
24
  <View style={styles.container}>
@@ -56,7 +58,7 @@ const getStyles = ({ colors }: ThemeType) =>
56
58
  marginBottom: 2,
57
59
  },
58
60
  description: {
59
- color: colors.textColor + 'CC',
61
+ color: hexWithOpacity(colors.textColor, 80),
60
62
  lineHeight: 18,
61
63
  },
62
64
  });
@@ -1,12 +1,14 @@
1
+ import React, { FC, memo, useMemo } from 'react';
1
2
  import { StatusBar, StyleSheet } from 'react-native';
2
- import React, { FC, memo } from 'react';
3
- import { SafeAreaView } from 'react-native-safe-area-context';
3
+
4
4
  import { KeyboardAvoidingView } from 'react-native-keyboard-controller';
5
- import { FullScreenContainerProps } from '../types/components.types';
6
- import { useTheme } from '../context/ThemeContext';
7
- import { ThemeType } from '../theme/Colors';
5
+ import { SafeAreaView } from 'react-native-safe-area-context';
6
+
7
+ import { FullScreenContainerProps } from '@app-types/components.types';
8
+ import { useTheme } from '@context/ThemeContext';
9
+ import { ThemeType } from '@src/theme/colors';
8
10
 
9
- export const FullScreenContainer: FC<FullScreenContainerProps> = ({
11
+ const FullScreenContainer: FC<FullScreenContainerProps> = ({
10
12
  children,
11
13
  style,
12
14
  edges = ['top'],
@@ -16,7 +18,7 @@ export const FullScreenContainer: FC<FullScreenContainerProps> = ({
16
18
  isKeyboardAvoidingView = false,
17
19
  }) => {
18
20
  const theme = useTheme();
19
- const styles = getStyles(theme);
21
+ const styles = useMemo(() => getStyles(theme), [theme]);
20
22
 
21
23
  const appBarStyle =
22
24
  barStyle ??
@@ -1,8 +1,10 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
- import AppText from './AppText';
4
- import { useTheme } from '../context/ThemeContext';
5
- import { ThemeType } from '../theme/Colors';
3
+
4
+ import AppText from '@components/AppText';
5
+ import { useTheme } from '@context/ThemeContext';
6
+ import { ThemeType } from '@src/theme/colors';
7
+ import { hexWithOpacity } from '@utils/utilsHelper';
6
8
 
7
9
  interface InfoCardProps {
8
10
  title: string;
@@ -12,7 +14,7 @@ interface InfoCardProps {
12
14
 
13
15
  const InfoCard: React.FC<InfoCardProps> = ({ title, children, icon }) => {
14
16
  const theme = useTheme();
15
- const styles = getStyles(theme);
17
+ const styles = useMemo(() => getStyles(theme), [theme]);
16
18
 
17
19
  return (
18
20
  <View style={styles.card}>
@@ -41,7 +43,7 @@ const getStyles = ({ colors }: ThemeType) =>
41
43
  padding: 16,
42
44
  marginBottom: 16,
43
45
  borderWidth: 1,
44
- borderColor: colors.primary + '20',
46
+ borderColor: hexWithOpacity(colors.primary, 12),
45
47
  shadowColor: colors.textColor,
46
48
  shadowOffset: { width: 0, height: 2 },
47
49
  shadowOpacity: 0.1,
@@ -1,15 +1,17 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { View, TouchableOpacity, StyleSheet } from 'react-native';
3
- import AppText from './AppText';
3
+
4
4
  import { useTranslation } from 'react-i18next';
5
- import { useTheme } from '../context/ThemeContext';
6
- import { ThemeType } from '../theme/Colors';
7
- import StorageHelper from '../utils/storageHelper';
5
+
6
+ import AppText from '@components/AppText';
7
+ import { useTheme } from '@context/ThemeContext';
8
+ import { ThemeType } from '@src/theme/colors';
9
+ import StorageHelper from '@utils/storageHelper';
8
10
 
9
11
  const LanguageSwitcher = () => {
10
12
  const { i18n } = useTranslation();
11
13
  const theme = useTheme();
12
- const styles = getStyles(theme);
14
+ const styles = useMemo(() => getStyles(theme), [theme]);
13
15
 
14
16
  const changeLanguage = (lng: string) => {
15
17
  i18n.changeLanguage(lng);
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import React, { useState, useEffect, useMemo } from 'react';
2
2
  import {
3
3
  TextInput as RNTextInput,
4
4
  TextInputProps,
@@ -7,7 +7,11 @@ import {
7
7
  StyleProp,
8
8
  TextStyle,
9
9
  ViewStyle,
10
+ LayoutChangeEvent,
11
+ FocusEvent,
12
+ BlurEvent,
10
13
  } from 'react-native';
14
+
11
15
  import Animated, {
12
16
  useSharedValue,
13
17
  useAnimatedStyle,
@@ -15,9 +19,11 @@ import Animated, {
15
19
  interpolate,
16
20
  Extrapolate,
17
21
  } from 'react-native-reanimated';
18
- import AppText from './AppText';
19
- import { useTheme } from '../context/ThemeContext';
20
- import { ThemeType } from '../theme/Colors';
22
+
23
+ import AppText from '@components/AppText';
24
+ import { useTheme } from '@context/ThemeContext';
25
+ import { ThemeType } from '@src/theme/colors';
26
+ import { hexWithOpacity } from '@utils/utilsHelper';
21
27
 
22
28
  interface CustomTextInputProps extends TextInputProps {
23
29
  label?: string;
@@ -59,7 +65,7 @@ const TextInput: React.FC<CustomTextInputProps> = ({
59
65
  ...props
60
66
  }) => {
61
67
  const theme = useTheme();
62
- const styles = getStyles(theme);
68
+ const styles = useMemo(() => getStyles(theme), [theme]);
63
69
  const [isFocused, setIsFocused] = useState(false);
64
70
  const [leftWidth, setLeftWidth] = useState(0);
65
71
 
@@ -115,21 +121,25 @@ const TextInput: React.FC<CustomTextInputProps> = ({
115
121
  ? hasError
116
122
  ? theme.colors.primary
117
123
  : theme.colors.primary
118
- : theme.colors.textColor + '80',
124
+ : hexWithOpacity(theme.colors.textColor, 50),
119
125
  };
120
126
  });
121
127
 
122
- const handleFocus = (e: any) => {
128
+ const handleFocus = (e: FocusEvent) => {
123
129
  setIsFocused(true);
124
- onFocus?.(e);
130
+ if (onFocus) {
131
+ onFocus(e);
132
+ }
125
133
  };
126
134
 
127
- const handleBlur = (e: any) => {
135
+ const handleBlur = (e: BlurEvent) => {
128
136
  setIsFocused(false);
129
- onBlur?.(e);
137
+ if (onBlur) {
138
+ onBlur(e);
139
+ }
130
140
  };
131
141
 
132
- const onLeftLayout = (event: any) => {
142
+ const onLeftLayout = (event: LayoutChangeEvent) => {
133
143
  setLeftWidth(event.nativeEvent.layout.width);
134
144
  };
135
145
 
@@ -171,7 +181,7 @@ const TextInput: React.FC<CustomTextInputProps> = ({
171
181
  <RNTextInput
172
182
  style={[styles.input, style]}
173
183
  placeholder={showPlaceholder ? placeholder : ''}
174
- placeholderTextColor={theme.colors.textColor + '60'}
184
+ placeholderTextColor={hexWithOpacity(theme.colors.textColor, 37)}
175
185
  onFocus={handleFocus}
176
186
  onBlur={handleBlur}
177
187
  value={value}
@@ -213,7 +223,7 @@ const getStyles = ({ colors }: ThemeType) =>
213
223
  alignItems: 'center',
214
224
  backgroundColor: colors.backgroundColor,
215
225
  borderWidth: 1,
216
- borderColor: colors.textColor + '30',
226
+ borderColor: hexWithOpacity(colors.textColor, 18),
217
227
  borderRadius: 12,
218
228
  paddingHorizontal: 12,
219
229
  minHeight: 56,
@@ -251,11 +261,11 @@ const getStyles = ({ colors }: ThemeType) =>
251
261
  },
252
262
  prefix: {
253
263
  marginRight: 4,
254
- color: colors.textColor + '80',
264
+ color: hexWithOpacity(colors.textColor, 50),
255
265
  },
256
266
  suffix: {
257
267
  marginLeft: 4,
258
- color: colors.textColor + '80',
268
+ color: hexWithOpacity(colors.textColor, 50),
259
269
  },
260
270
  errorText: {
261
271
  color: colors.primary,
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
2
  import { View, TouchableOpacity, StyleSheet } from 'react-native';
3
- import AppText from './AppText';
4
- import { useTheme } from '../context/ThemeContext';
5
- import { ThemeType } from '../theme/Colors';
3
+
4
+ import AppText from '@components/AppText';
5
+ import { useTheme } from '@context/ThemeContext';
6
+ import { ThemeType } from '@src/theme/colors';
6
7
 
7
8
  const ThemeSwitcher = () => {
8
9
  const { colors, currentTheme, toggleTheme } = useTheme();
@@ -1,7 +1,3 @@
1
- import { userMockData } from '../mock';
2
- import Routes from '../navigation/routes';
3
- import { resetAndNavigate } from '../utils/navigationUtils';
4
- import StorageHelper from '../utils/storageHelper';
5
1
  import {
6
2
  createContext,
7
3
  FC,
@@ -12,6 +8,11 @@ import {
12
8
  useState,
13
9
  } from 'react';
14
10
 
11
+ import { userMockData } from '@mock';
12
+ import Routes from '@navigation/routes';
13
+ import { resetAndNavigate } from '@utils/navigationUtils';
14
+ import StorageHelper from '@utils/storageHelper';
15
+
15
16
  type UserType = typeof userMockData;
16
17
 
17
18
  type AuthContextType = {
@@ -4,12 +4,13 @@ import {
4
4
  ReactNode,
5
5
  useCallback,
6
6
  useContext,
7
- useEffect,
8
7
  useState,
9
8
  } from 'react';
10
- import { darkTheme, lightTheme, ThemeType } from '../theme/Colors';
9
+
11
10
  import { EdgeInsets, useSafeAreaInsets } from 'react-native-safe-area-context';
12
- import storageHelper from '../utils/storageHelper';
11
+
12
+ import { darkTheme, lightTheme, ThemeType } from '@src/theme/colors';
13
+ import storageHelper from '@utils/storageHelper';
13
14
 
14
15
  export type ThemeContextType = {
15
16
  colors: ThemeType['colors'];
@@ -26,24 +27,14 @@ type ThemeProviderProps = {
26
27
 
27
28
  export const ThemeProvider: FC<ThemeProviderProps> = ({ children }) => {
28
29
  const safeAreaInsets = useSafeAreaInsets();
29
- const [currentTheme, setCurrentTheme] =
30
- useState<ThemeContextType['currentTheme']>();
31
- const [colors, setColors] = useState<ThemeContextType['colors']>(
32
- lightTheme.colors,
33
- );
34
-
35
- useEffect(() => {
30
+ const [currentTheme, setCurrentTheme] = useState<
31
+ ThemeContextType['currentTheme']
32
+ >(() => {
36
33
  const theme = storageHelper.getItem(storageHelper.STORAGE_KEYS.THEME);
37
- setCurrentTheme(theme === 'dark' ? 'dark' : 'light');
38
- }, []);
34
+ return theme === 'dark' ? 'dark' : 'light';
35
+ });
39
36
 
40
- useEffect(() => {
41
- if (currentTheme === 'dark') {
42
- setColors(darkTheme.colors);
43
- } else {
44
- setColors(lightTheme.colors);
45
- }
46
- }, [currentTheme]);
37
+ const colors = currentTheme === 'dark' ? darkTheme.colors : lightTheme.colors;
47
38
 
48
39
  const toggleTheme = useCallback(() => {
49
40
  setCurrentTheme(prev => {