@imksh/create 1.0.31 → 1.0.33

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 (158) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/src/commands/create.js +2 -0
  4. package/src/index.js +1 -1
  5. package/templates/layers/next/javascript/package.json +8 -2
  6. package/templates/layers/next/typescript/.eslintrc.json +12 -0
  7. package/templates/layers/next/typescript/package.json +14 -3
  8. package/templates/layers/next/typescript/src/components/common/Loading.tsx +1 -1
  9. package/templates/layers/next/typescript/src/components/common/LottieIcon.tsx +2 -2
  10. package/templates/layers/next/typescript/src/components/common/Table.tsx +4 -4
  11. package/templates/layers/next/typescript/src/components/modals/ConfirmModal.tsx +2 -1
  12. package/templates/layers/next/typescript/src/components/ui/Header.tsx +2 -2
  13. package/templates/layers/next/typescript/src/hooks/usePwaInstall.ts +10 -4
  14. package/templates/layers/next/typescript/src/services/authService.ts +1 -1
  15. package/templates/layers/next/typescript/src/store/useAuthStore.ts +24 -9
  16. package/templates/layers/node/javascript/.env.example +3 -1
  17. package/templates/layers/node/javascript/package.json +12 -3
  18. package/templates/layers/node/javascript/src/app.js +2 -1
  19. package/templates/layers/node/javascript/src/controllers/auth.controller.js +106 -168
  20. package/templates/layers/node/javascript/src/controllers/push.controller.js +51 -58
  21. package/templates/layers/node/javascript/src/controllers/upload.controller.js +12 -19
  22. package/templates/layers/node/javascript/src/middleware/auth.middleware.js +5 -11
  23. package/templates/layers/node/javascript/src/middleware/errorHandler.js +6 -4
  24. package/templates/layers/node/javascript/src/routes/auth.route.js +2 -0
  25. package/templates/layers/node/javascript/src/services/auth.service.js +159 -164
  26. package/templates/layers/node/javascript/src/utils/ApiError.js +20 -0
  27. package/templates/layers/node/javascript/src/utils/SuccessResponse.js +15 -0
  28. package/templates/layers/node/javascript/src/utils/apiResponse.js +4 -0
  29. package/templates/layers/node/javascript/src/utils/asyncHandler.js +5 -0
  30. package/templates/layers/node/typescript/.env.example +3 -1
  31. package/templates/layers/node/typescript/.eslintrc.cjs +28 -0
  32. package/templates/layers/node/typescript/package.json +16 -2
  33. package/templates/layers/node/typescript/src/app.ts +3 -2
  34. package/templates/layers/node/typescript/src/config/db.ts +3 -2
  35. package/templates/layers/node/typescript/src/config/socket.ts +5 -4
  36. package/templates/layers/node/typescript/src/controllers/auth.controller.ts +104 -132
  37. package/templates/layers/node/typescript/src/controllers/push.controller.ts +52 -59
  38. package/templates/layers/node/typescript/src/controllers/upload.controller.ts +12 -19
  39. package/templates/layers/node/typescript/src/middleware/auth.middleware.ts +13 -7
  40. package/templates/layers/node/typescript/src/middleware/errorHandler.ts +18 -5
  41. package/templates/layers/node/typescript/src/middleware/rateLimiter.ts +2 -2
  42. package/templates/layers/node/typescript/src/routes/auth.route.ts +2 -0
  43. package/templates/layers/node/typescript/src/services/auth.service.ts +86 -43
  44. package/templates/layers/node/typescript/src/types/express.d.ts +5 -3
  45. package/templates/layers/node/typescript/src/utils/ApiError.ts +25 -0
  46. package/templates/layers/node/typescript/src/utils/SuccessResponse.ts +17 -0
  47. package/templates/layers/node/typescript/src/utils/apiResponse.ts +4 -0
  48. package/templates/layers/node/typescript/src/utils/asyncHandler.ts +13 -0
  49. package/templates/layers/node/typescript/src/utils/cloudinaryUpload.ts +18 -7
  50. package/templates/layers/node/typescript/src/utils/expoNotification.ts +1 -1
  51. package/templates/layers/node/typescript/src/utils/genOtpToken.ts +7 -1
  52. package/templates/layers/node/typescript/src/utils/jwt.ts +8 -2
  53. package/templates/layers/node/typescript/src/utils/logger.ts +2 -1
  54. package/templates/layers/node/typescript/src/utils/pushHelper.ts +13 -9
  55. package/templates/layers/node-prisma/javascript/.env.example +3 -1
  56. package/templates/layers/node-prisma/javascript/package.json +11 -2
  57. package/templates/layers/node-prisma/javascript/src/app.js +2 -1
  58. package/templates/layers/node-prisma/javascript/src/controllers/auth.controller.js +90 -135
  59. package/templates/layers/node-prisma/javascript/src/controllers/push.controller.js +64 -76
  60. package/templates/layers/node-prisma/javascript/src/controllers/upload.controller.js +12 -19
  61. package/templates/layers/node-prisma/javascript/src/middleware/auth.middleware.js +5 -4
  62. package/templates/layers/node-prisma/javascript/src/middleware/errorHandler.js +6 -4
  63. package/templates/layers/node-prisma/javascript/src/routes/auth.route.js +2 -0
  64. package/templates/layers/node-prisma/javascript/src/services/auth.service.js +145 -122
  65. package/templates/layers/node-prisma/javascript/src/utils/ApiError.js +20 -0
  66. package/templates/layers/node-prisma/javascript/src/utils/SuccessResponse.js +15 -0
  67. package/templates/layers/node-prisma/javascript/src/utils/apiResponse.js +4 -0
  68. package/templates/layers/node-prisma/javascript/src/utils/asyncHandler.js +5 -0
  69. package/templates/layers/node-prisma/typescript/.env.example +3 -1
  70. package/templates/layers/node-prisma/typescript/.eslintrc.cjs +28 -0
  71. package/templates/layers/node-prisma/typescript/package.json +19 -5
  72. package/templates/layers/node-prisma/typescript/src/app.ts +3 -2
  73. package/templates/layers/node-prisma/typescript/src/config/prisma.ts +3 -2
  74. package/templates/layers/node-prisma/typescript/src/config/socket.ts +5 -4
  75. package/templates/layers/node-prisma/typescript/src/controllers/auth.controller.ts +89 -105
  76. package/templates/layers/node-prisma/typescript/src/controllers/push.controller.ts +67 -83
  77. package/templates/layers/node-prisma/typescript/src/controllers/upload.controller.ts +12 -19
  78. package/templates/layers/node-prisma/typescript/src/middleware/auth.middleware.ts +9 -13
  79. package/templates/layers/node-prisma/typescript/src/middleware/errorHandler.ts +18 -5
  80. package/templates/layers/node-prisma/typescript/src/middleware/rateLimiter.ts +2 -2
  81. package/templates/layers/node-prisma/typescript/src/routes/auth.route.ts +2 -0
  82. package/templates/layers/node-prisma/typescript/src/services/auth.service.ts +83 -31
  83. package/templates/layers/node-prisma/typescript/src/types/express.d.ts +5 -3
  84. package/templates/layers/node-prisma/typescript/src/utils/ApiError.ts +25 -0
  85. package/templates/layers/node-prisma/typescript/src/utils/SuccessResponse.ts +17 -0
  86. package/templates/layers/node-prisma/typescript/src/utils/apiResponse.ts +4 -0
  87. package/templates/layers/node-prisma/typescript/src/utils/asyncHandler.ts +13 -0
  88. package/templates/layers/node-prisma/typescript/src/utils/cloudinaryUpload.ts +18 -7
  89. package/templates/layers/node-prisma/typescript/src/utils/genOtpToken.ts +7 -1
  90. package/templates/layers/node-prisma/typescript/src/utils/jwt.ts +8 -2
  91. package/templates/layers/node-prisma/typescript/src/utils/logger.ts +2 -1
  92. package/templates/layers/node-prisma/typescript/src/utils/pushHelper.ts +10 -6
  93. package/templates/layers/prisma/javascript/package.json +8 -0
  94. package/templates/layers/prisma/typescript/package.json +14 -1
  95. package/templates/layers/prisma/typescript/src/config/db.ts +3 -2
  96. package/templates/layers/react/javascript/package.json +6 -0
  97. package/templates/layers/react/typescript/.eslintrc.cjs +20 -0
  98. package/templates/layers/react/typescript/package.json +11 -2
  99. package/templates/layers/react/typescript/src/components/common/Table.tsx +4 -4
  100. package/templates/layers/react/typescript/src/components/ui/Sidebar.tsx +1 -1
  101. package/templates/layers/react/typescript/src/main.tsx +11 -11
  102. package/templates/layers/react/typescript/src/services/authService.ts +1 -1
  103. package/templates/layers/react/typescript/src/store/useAuthStore.ts +24 -9
  104. package/templates/layers/react-native/base/app.json +9 -22
  105. package/templates/layers/react-native/base/eslint.config.js +5 -1
  106. package/templates/layers/react-native/base/package.json +40 -33
  107. package/templates/layers/react-native/base/src/app/(auth)/edit-profile.tsx +7 -7
  108. package/templates/layers/react-native/base/src/app/(auth)/login.tsx +31 -7
  109. package/templates/layers/react-native/base/src/app/(tabs)/_layout.tsx +3 -3
  110. package/templates/layers/react-native/base/src/app/(tabs)/index.tsx +6 -5
  111. package/templates/layers/react-native/base/src/app/_layout.tsx +4 -8
  112. package/templates/layers/react-native/base/src/app/screens/doc-viewer.tsx +378 -0
  113. package/templates/layers/react-native/base/src/components/common/ConfirmationToast.tsx +58 -40
  114. package/templates/layers/react-native/base/src/components/common/GoogleAuthButton.tsx +123 -0
  115. package/templates/layers/react-native/base/src/components/common/LocationLoader.tsx +64 -9
  116. package/templates/layers/react-native/base/src/components/common/Typography.tsx +54 -19
  117. package/templates/layers/react-native/base/src/components/ui/BiometricLock.tsx +3 -3
  118. package/templates/layers/react-native/base/src/components/ui/ClassicTabBar.tsx +15 -12
  119. package/templates/layers/react-native/base/src/components/ui/CustomTabBar.tsx +90 -91
  120. package/templates/layers/react-native/base/src/components/ui/Drawer.tsx +344 -0
  121. package/templates/layers/react-native/base/src/components/ui/Sidebar.tsx +4 -4
  122. package/templates/layers/react-native/base/src/components/ui/buttons/Button.tsx +29 -6
  123. package/templates/layers/react-native/base/src/components/ui/data-display/Accordion.tsx +2 -2
  124. package/templates/layers/react-native/base/src/components/ui/data-display/Badge.tsx +1 -2
  125. package/templates/layers/react-native/base/src/components/ui/data-display/Image.tsx +3 -3
  126. package/templates/layers/react-native/base/src/components/ui/data-display/SwipeableRow.tsx +28 -7
  127. package/templates/layers/react-native/base/src/components/ui/feedback/GestureWrapper.tsx +11 -4
  128. package/templates/layers/react-native/base/src/components/ui/inputs/DatePicker.tsx +3 -3
  129. package/templates/layers/react-native/base/src/components/ui/inputs/ImagePickerModal.tsx +45 -19
  130. package/templates/layers/react-native/base/src/components/ui/inputs/Input.tsx +28 -9
  131. package/templates/layers/react-native/base/src/components/ui/inputs/SearchablePicker.tsx +199 -0
  132. package/templates/layers/react-native/base/src/components/ui/inputs/Switch.tsx +7 -7
  133. package/templates/layers/react-native/base/src/components/ui/inputs/WebLocationPicker.tsx +146 -72
  134. package/templates/layers/react-native/base/src/config/api.ts +5 -5
  135. package/templates/layers/react-native/base/src/services/auth.service.ts +3 -1
  136. package/templates/layers/react-native/base/src/services/permission.service.ts +168 -44
  137. package/templates/layers/react-native/base/src/services/socket.service.ts +0 -7
  138. package/templates/layers/react-native/base/src/store/useAuthStore.ts +61 -16
  139. package/templates/layers/react-native/base/src/store/useNotificationStore.ts +36 -42
  140. package/templates/layers/react-native/base/src/types/images.d.ts +7 -5
  141. package/templates/layers/react-native/base/src/utils/env.ts +47 -0
  142. package/templates/layers/react-native/base/src/utils/fileDownload.ts +206 -0
  143. package/templates/layers/react-native/base/src/utils/storage.ts +1 -1
  144. package/templates/presets/production-fullstack/overrides/client/package.json +9 -0
  145. package/templates/presets/production-fullstack/overrides/mobile/app.json +2 -15
  146. package/templates/presets/production-fullstack/overrides/mobile/package.json +39 -29
  147. package/templates/presets/production-fullstack/overrides/mobile/src/app/_layout.tsx +3 -3
  148. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/Drawer.tsx +344 -0
  149. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/DatePicker.tsx +3 -3
  150. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/ImagePickerModal.tsx +3 -3
  151. package/templates/presets/production-fullstack/overrides/mobile/src/services/permission.service.ts +168 -44
  152. package/templates/presets/production-fullstack/overrides/mobile/src/store/useNotificationStore.ts +16 -0
  153. package/templates/presets/production-fullstack/overrides/mobile/src/utils/env.ts +47 -0
  154. package/templates/presets/production-fullstack/overrides/server/package.json +11 -2
  155. package/templates/layers/react-native/base/src/app/doc-viewer.tsx +0 -193
  156. package/templates/layers/react-native/base/src/components/ui/BottomModal.tsx +0 -176
  157. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/BottomModal.tsx +0 -159
  158. /package/templates/layers/react-native/base/assets/images/logo/{logoWithBg.png → icon.png} +0 -0
@@ -7,6 +7,7 @@ export interface User {
7
7
  email: string;
8
8
  phone?: string;
9
9
  role: string;
10
+ orgRole?: string;
10
11
  avatar?: {
11
12
  url?: string;
12
13
  publicId?: string;
@@ -15,6 +16,20 @@ export interface User {
15
16
  updatedAt?: string;
16
17
  }
17
18
 
19
+ interface ApiErrorResponse {
20
+ response?: {
21
+ data?: {
22
+ message?: string;
23
+ };
24
+ };
25
+ message?: string;
26
+ }
27
+
28
+ const getErrorMessage = (err: unknown): string => {
29
+ const apiErr = err as ApiErrorResponse;
30
+ return apiErr.response?.data?.message || apiErr.message || "An unexpected error occurred";
31
+ };
32
+
18
33
  export interface AuthState {
19
34
  user: User | null;
20
35
  loading: boolean;
@@ -39,9 +54,9 @@ export const useAuthStore = create<AuthState>((set) => ({
39
54
  try {
40
55
  await authService.sendOtp(email);
41
56
  return true;
42
- } catch (err: any) {
57
+ } catch (err: unknown) {
43
58
  set({
44
- error: err.response?.data?.message || err.message,
59
+ error: getErrorMessage(err),
45
60
  loading: false,
46
61
  });
47
62
  return false;
@@ -62,9 +77,9 @@ export const useAuthStore = create<AuthState>((set) => ({
62
77
  loading: false,
63
78
  });
64
79
  return true;
65
- } catch (err: any) {
80
+ } catch (err: unknown) {
66
81
  set({
67
- error: err.response?.data?.message || err.message,
82
+ error: getErrorMessage(err),
68
83
  loading: false,
69
84
  });
70
85
  return false;
@@ -85,9 +100,9 @@ export const useAuthStore = create<AuthState>((set) => ({
85
100
  loading: false,
86
101
  });
87
102
  return true;
88
- } catch (err: any) {
103
+ } catch (err: unknown) {
89
104
  set({
90
- error: err.response?.data?.message || err.message,
105
+ error: getErrorMessage(err),
91
106
  loading: false,
92
107
  });
93
108
  return false;
@@ -101,7 +116,7 @@ export const useAuthStore = create<AuthState>((set) => ({
101
116
  try {
102
117
  const { data } = await authService.getMe();
103
118
  set({ user: data.data, isCheckingAuth: false });
104
- } catch (err: any) {
119
+ } catch {
105
120
  set({ isCheckingAuth: false });
106
121
  } finally {
107
122
  set({ isCheckingAuth: false });
@@ -114,9 +129,9 @@ export const useAuthStore = create<AuthState>((set) => ({
114
129
  const { data } = await authService.updateMe(updates);
115
130
  set({ user: data.data, loading: false });
116
131
  return true;
117
- } catch (err: any) {
132
+ } catch (err: unknown) {
118
133
  set({
119
- error: err.response?.data?.message || err.message,
134
+ error: getErrorMessage(err),
120
135
  loading: false,
121
136
  });
122
137
  return false;
@@ -4,47 +4,39 @@
4
4
  "slug": "mobile",
5
5
  "version": "1.0.0",
6
6
  "orientation": "portrait",
7
- "icon": "./assets/images/logo/logoWithBg.png",
7
+ "icon": "./assets/images/logo/icon.png",
8
8
  "scheme": "mobile",
9
9
  "userInterfaceStyle": "automatic",
10
10
  "ios": {
11
- "icon": "./assets/images/logo/logoWithBg.png",
11
+ "icon": "./assets/images/logo/icon.png",
12
12
  "bundleIdentifier": "com.anonymous.mobile"
13
13
  },
14
14
  "android": {
15
15
  "adaptiveIcon": {
16
16
  "backgroundColor": "#E6F4FE",
17
- "foregroundImage": "./assets/images/logo/logoWithBg.png",
18
- "backgroundImage": "./assets/images/logo/logoWithBg.png",
19
- "monochromeImage": "./assets/images/logo/logoWithBg.png"
17
+ "foregroundImage": "./assets/images/logo/icon.png",
18
+ "backgroundImage": "./assets/images/logo/icon.png",
19
+ "monochromeImage": "./assets/images/logo/icon.png"
20
20
  },
21
21
  "predictiveBackGestureEnabled": false,
22
22
  "package": "com.anonymous.mobile",
23
23
  "permissions": [
24
24
  "android.permission.CAMERA",
25
- "android.permission.RECORD_AUDIO",
26
25
  "android.permission.ACCESS_FINE_LOCATION",
27
- "android.permission.ACCESS_COARSE_LOCATION",
28
- "android.permission.READ_CONTACTS",
29
- "android.permission.READ_CALENDAR",
30
- "android.permission.READ_EXTERNAL_STORAGE",
31
- "android.permission.WRITE_EXTERNAL_STORAGE",
32
- "android.permission.BLUETOOTH_CONNECT",
33
- "android.permission.BLUETOOTH_SCAN",
34
- "android.permission.CALL_PHONE"
26
+ "android.permission.ACCESS_COARSE_LOCATION"
35
27
  ]
36
28
  },
37
29
  "web": {
38
30
  "bundler": "metro",
39
31
  "output": "static",
40
- "favicon": "./assets/images/logo/logoWithBg.png"
32
+ "favicon": "./assets/images/logo/icon.png"
41
33
  },
42
34
  "plugins": [
43
35
  "expo-router",
44
36
  [
45
37
  "expo-splash-screen",
46
38
  {
47
- "image": "./assets/images/logo/logoWithBg.png",
39
+ "image": "./assets/images/logo/icon.png",
48
40
  "imageWidth": 200,
49
41
  "resizeMode": "contain",
50
42
  "backgroundColor": "#FFFFFF",
@@ -58,14 +50,9 @@
58
50
  {
59
51
  "iosPermissions": [
60
52
  "Camera",
61
- "Microphone",
62
- "LocationAlways",
63
53
  "LocationWhenInUse",
64
54
  "Notifications",
65
- "PhotoLibrary",
66
- "Contacts",
67
- "Calendars",
68
- "BluetoothPeripheral"
55
+ "PhotoLibrary"
69
56
  ]
70
57
  }
71
58
  ]
@@ -6,5 +6,9 @@ module.exports = defineConfig([
6
6
  expoConfig,
7
7
  {
8
8
  ignores: ["dist/*"],
9
- }
9
+ rules: {
10
+ "@typescript-eslint/no-explicit-any": "error",
11
+ "no-console": "error",
12
+ },
13
+ },
10
14
  ]);
@@ -1,62 +1,62 @@
1
1
  {
2
- "name": "shivAi",
2
+ "name": "Mobile",
3
3
  "main": "expo-router/entry",
4
4
  "version": "1.0.0",
5
5
  "dependencies": {
6
- "@expo/ui": "~57.0.7",
6
+ "@expo/ui": "~57.0.22",
7
7
  "@expo/vector-icons": "^15.1.1",
8
8
  "@react-native-async-storage/async-storage": "2.2.0",
9
9
  "@react-native-community/slider": "^5.2.0",
10
+ "@react-native-google-signin/google-signin": "^13.1.0",
10
11
  "@react-native-picker/picker": "^2.11.4",
11
12
  "@react-navigation/bottom-tabs": "^7.18.10",
12
13
  "axios": "^1.18.1",
13
14
  "babel-preset-expo": "^57.0.3",
15
+ "dayjs": "^1.11.13",
14
16
  "drizzle-orm": "^0.45.2",
15
- "expo": "~57.0.7",
16
- "expo-blur": "~57.0.2",
17
+ "expo": "~57.0.27",
18
+ "expo-blur": "~57.0.3",
17
19
  "expo-constants": "~57.0.6",
18
- "expo-device": "~57.0.1",
19
- "expo-file-system": "~18.0.7",
20
+ "expo-device": "~57.0.2",
21
+ "expo-file-system": "~57.0.7",
20
22
  "expo-font": "~57.0.1",
21
- "expo-glass-effect": "~57.0.1",
22
- "expo-image": "~57.0.1",
23
- "expo-image-picker": "^57.0.6",
24
- "expo-linear-gradient": "^57.0.1",
25
- "expo-linking": "~57.0.3",
26
- "expo-local-authentication": "~15.0.2",
27
- "expo-location": "~18.0.5",
28
- "expo-notifications": "~57.0.6",
29
- "dayjs": "^1.11.13",
30
- "expo-router": "~57.0.7",
31
- "expo-splash-screen": "~57.0.4",
32
- "expo-sqlite": "^57.0.1",
23
+ "expo-glass-effect": "~57.0.4",
24
+ "expo-image": "~57.0.5",
25
+ "expo-image-picker": "~57.0.20",
26
+ "expo-linear-gradient": "~57.0.2",
27
+ "expo-linking": "~57.0.12",
28
+ "expo-local-authentication": "~57.0.3",
29
+ "expo-location": "~57.0.20",
30
+ "expo-notifications": "~57.0.22",
31
+ "expo-router": "~57.0.25",
32
+ "expo-sharing": "~57.0.22",
33
+ "expo-splash-screen": "~57.0.9",
34
+ "expo-sqlite": "~57.0.4",
33
35
  "expo-status-bar": "~57.0.1",
34
- "expo-symbols": "~57.0.1",
35
- "expo-system-ui": "~57.0.1",
36
- "expo-web-browser": "~57.0.1",
37
- "lottie-react": "^2.4.1",
36
+ "expo-symbols": "~57.0.3",
37
+ "expo-system-ui": "~57.0.4",
38
+ "expo-web-browser": "~57.0.3",
38
39
  "lottie-react-native": "^7.3.8",
39
40
  "nativewind": "^4.2.6",
40
41
  "prettier-plugin-tailwindcss": "^0.5.14",
41
42
  "react": "19.2.3",
42
43
  "react-dom": "19.2.3",
43
- "react-native": "0.86.0",
44
+ "react-native": "0.86.3",
45
+ "react-native-blob-util": "^0.19.11",
44
46
  "react-native-gesture-handler": "~2.32.0",
45
47
  "react-native-image-viewing": "^0.2.2",
46
- "react-native-maps": "^1.18.0",
47
48
  "react-native-keyboard-aware-scroll-view": "^0.9.5",
48
49
  "react-native-otp-entry": "^1.8.6",
49
50
  "react-native-paper": "^5.15.3",
50
- "react-native-pdf": "^6.7.5",
51
- "react-native-blob-util": "^0.19.11",
51
+ "react-native-pdf": "^7.0.5",
52
52
  "react-native-permissions": "^5.6.0",
53
- "react-native-reanimated": "^4.5.2",
54
- "react-native-safe-area-context": "^5.8.0",
55
- "react-native-screens": "4.25.2",
53
+ "react-native-reanimated": "4.5.1",
54
+ "react-native-safe-area-context": "~5.7.0",
55
+ "react-native-screens": "~4.26.0",
56
56
  "react-native-toast-message": "^2.4.0",
57
57
  "react-native-web": "~0.21.0",
58
- "react-native-webview": "^13.12.5",
59
- "react-native-worklets": "0.10.0",
58
+ "react-native-webview": "13.16.1",
59
+ "react-native-worklets": "0.10.1",
60
60
  "socket.io-client": "^4.8.3",
61
61
  "tailwindcss": "^3.4.19",
62
62
  "zustand": "^5.0.14"
@@ -64,9 +64,12 @@
64
64
  "devDependencies": {
65
65
  "@types/react": "~19.2.2",
66
66
  "babel-plugin-inline-import": "^3.0.0",
67
+ "dpdm": "^3.14.0",
67
68
  "drizzle-kit": "^0.31.10",
68
69
  "eslint": "^9.0.0",
69
- "eslint-config-expo": "~57.0.0",
70
+ "eslint-config-expo": "~57.0.2",
71
+ "prettier": "^3.4.2",
72
+ "ts-prune": "^0.10.3",
70
73
  "typescript": "~6.0.3"
71
74
  },
72
75
  "scripts": {
@@ -77,7 +80,11 @@
77
80
  "ios": "expo run:ios",
78
81
  "web": "expo start --web",
79
82
  "lint": "expo lint",
80
- "format": "expo lint --fix",
83
+ "lint:fix": "expo lint --fix",
84
+ "format": "prettier --write \"src/**/*.{ts,tsx,json}\"",
85
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,json}\"",
86
+ "circular-check": "dpdm --circular --no-warning --no-tree --exit-code circular:1 \"src/**/*.{ts,tsx}\"",
87
+ "prune:unused": "ts-prune",
81
88
  "ts:check": "tsc --noEmit",
82
89
  "build": "eas build",
83
90
  "build:android": "eas build -p android",
@@ -45,13 +45,14 @@ export default function EditProfileScreen() {
45
45
  uri: avatarUri,
46
46
  name: filename,
47
47
  type,
48
- } as any);
48
+ } as unknown as Blob);
49
49
  }
50
50
 
51
51
  // Only update if something changed
52
+ const rnFormData = formData as unknown as { getParts?: () => unknown[] };
52
53
  if (
53
- (formData as any).getParts &&
54
- (formData as any).getParts().length === 0
54
+ rnFormData.getParts &&
55
+ rnFormData.getParts().length === 0
55
56
  ) {
56
57
  router.back();
57
58
  return;
@@ -65,10 +66,9 @@ export default function EditProfileScreen() {
65
66
  } else {
66
67
  toast.error(res.data.message);
67
68
  }
68
-
69
- console.log(res.data.data);
70
- } catch (error: any) {
71
- toast.error(error.response?.data?.message || error.message);
69
+ } catch (error: unknown) {
70
+ const err = error as { response?: { data?: { message?: string } }; message?: string };
71
+ toast.error(err.response?.data?.message || err.message || "Failed to update profile");
72
72
  } finally {
73
73
  setLoading(false);
74
74
  }
@@ -2,13 +2,17 @@ import React, { useState, useCallback } from "react";
2
2
  import { View } from "react-native";
3
3
  import { useAuthStore } from "../../store/useAuthStore";
4
4
  import { Txt } from "../../components/common/Typography";
5
- import { Redirect, router, useFocusEffect } from "expo-router";
5
+ import { router, useFocusEffect } from "expo-router";
6
6
  import ScrollContainer from "../../components/ui/layout/ScrollContainer";
7
7
  import Input from "../../components/ui/inputs/Input";
8
8
  import Button from "../../components/ui/buttons/Button";
9
9
  import Tabs from "../../components/ui/navigation/Tabs";
10
10
  import Image from "@/components/ui/data-display/Image";
11
11
  import logo from "../../../assets/images/logo/logo.png";
12
+ import GoogleAuthButton from "../../components/common/GoogleAuthButton";
13
+ import { ActivityIndicator } from "react-native-paper";
14
+ import { useColorScheme } from "nativewind";
15
+ import { Colors } from "@/constants/Colors";
12
16
 
13
17
  export default function LoginScreen() {
14
18
  const {
@@ -22,6 +26,9 @@ export default function LoginScreen() {
22
26
  clearError,
23
27
  demoLogin,
24
28
  } = useAuthStore();
29
+ const { colorScheme } = useColorScheme();
30
+ const colors = Colors[colorScheme ?? "light"];
31
+ const [isNavigating, setIsNavigating] = useState(false);
25
32
 
26
33
  useFocusEffect(
27
34
  useCallback(() => {
@@ -55,13 +62,13 @@ export default function LoginScreen() {
55
62
  };
56
63
 
57
64
  const handleSubmit = async () => {
58
- let ok;
65
+ let ok = false;
59
66
  if (mode === "login") {
60
67
  ok = await login(form.email, form.password);
61
68
  } else {
62
69
  if (!otpSent) {
63
- ok = await sendOtp(form.email);
64
- if (ok) {
70
+ const sent = await sendOtp(form.email);
71
+ if (sent) {
65
72
  setOtpSent(true);
66
73
  setTimer(60);
67
74
  }
@@ -69,10 +76,17 @@ export default function LoginScreen() {
69
76
  ok = await signup(form.name, form.email, form.password, form.otp);
70
77
  }
71
78
  }
79
+ if (ok && (mode === "login" || otpSent)) {
80
+ setIsNavigating(true);
81
+ }
72
82
  };
73
83
 
74
- if (!isCheckingAuth && user) {
75
- return <Redirect href="/(tabs)" />;
84
+ if (isNavigating || (!isCheckingAuth && user)) {
85
+ return (
86
+ <View className="flex-1 bg-base-100 items-center justify-center">
87
+ <ActivityIndicator size="large" color={colors.primary} />
88
+ </View>
89
+ );
76
90
  }
77
91
 
78
92
  return (
@@ -204,7 +218,10 @@ export default function LoginScreen() {
204
218
  <View className="mt-2">
205
219
  <Button
206
220
  label="Demo Login"
207
- onPress={() => demoLogin()}
221
+ onPress={async () => {
222
+ await demoLogin();
223
+ setIsNavigating(true);
224
+ }}
208
225
  isLoading={loading}
209
226
  variant="outline"
210
227
  isFullWidth
@@ -212,6 +229,13 @@ export default function LoginScreen() {
212
229
  </View>
213
230
  )}
214
231
 
232
+ <GoogleAuthButton
233
+ isLogin={mode === "login"}
234
+ onSuccess={() => {
235
+ setIsNavigating(true);
236
+ }}
237
+ />
238
+
215
239
  {mode === "signup" && otpSent && (
216
240
  <View className="mt-2">
217
241
  <Button
@@ -1,4 +1,4 @@
1
- import { Tabs, Redirect } from "expo-router";
1
+ import { Tabs } from "expo-router";
2
2
  import { useColorScheme } from "nativewind";
3
3
  import { Colors } from "../../constants/Colors";
4
4
  import CustomTabBar from "../../components/ui/CustomTabBar";
@@ -10,7 +10,7 @@ const TabLayout = () => {
10
10
  const { user, isCheckingAuth } = useAuthStore();
11
11
 
12
12
  if (!isCheckingAuth && !user) {
13
- return <Redirect href="/login" />;
13
+ return null;
14
14
  }
15
15
 
16
16
  return (
@@ -19,7 +19,7 @@ const TabLayout = () => {
19
19
  <CustomTabBar
20
20
  {...props}
21
21
  showCenterButton={false}
22
- onCenterButtonPress={() => console.log("Create button pressed!")}
22
+ onCenterButtonPress={() => {}}
23
23
  />
24
24
  )}
25
25
  screenOptions={{
@@ -38,7 +38,7 @@ import CircularProgress from "@/components/ui/feedback/CircularProgress";
38
38
  import Skeleton from "@/components/ui/feedback/Skeleton";
39
39
  import { GestureWrapper } from "@/components/ui/feedback/GestureWrapper";
40
40
 
41
- import BottomModal from "@/components/ui/BottomModal";
41
+ import Drawer from "@/components/ui/Drawer";
42
42
  import Tabs from "@/components/ui/navigation/Tabs";
43
43
  import { useColorScheme } from "nativewind";
44
44
  import { Colors } from "@/constants/Colors";
@@ -424,11 +424,12 @@ const Index = () => {
424
424
  <FloatingActionButton icon="add" onPress={() => setIsModalOpen(true)} />
425
425
  </View>
426
426
 
427
- {/* Interactive Bottom Modal */}
428
- <BottomModal
427
+ {/* Interactive Drawer */}
428
+ <Drawer
429
429
  isOpen={isModalOpen}
430
430
  onClose={() => setIsModalOpen(false)}
431
- heightPercent={0.45}
431
+ position="bottom"
432
+ sizePercent={0.45}
432
433
  >
433
434
  <VStack spacing={20} className="px-4 py-2">
434
435
  <View className="h-16 w-16 bg-primary/10 rounded-full items-center justify-center self-center mb-2">
@@ -456,7 +457,7 @@ const Index = () => {
456
457
  onPress={() => setIsModalOpen(false)}
457
458
  />
458
459
  </VStack>
459
- </BottomModal>
460
+ </Drawer>
460
461
  </View>
461
462
  );
462
463
  };
@@ -30,7 +30,7 @@ export default function RootLayout() {
30
30
  const { getMe, isCheckingAuth, loadCachedUser, user } = useAuthStore();
31
31
  const { colorScheme, setColorScheme } = useColorScheme();
32
32
  const colors = Colors[colorScheme ?? "light"];
33
-
33
+
34
34
  const segments = useSegments();
35
35
  const router = useRouter();
36
36
 
@@ -63,8 +63,8 @@ export default function RootLayout() {
63
63
  if (!user && !inAuthGroup) {
64
64
  // Redirect to the auth group
65
65
  router.replace("/(auth)/login");
66
- } else if (user && inAuthGroup) {
67
- // Redirect away from auth
66
+ } else if (user && (inAuthGroup || !segments[0])) {
67
+ // Redirect away from auth or root to main app tabs
68
68
  router.replace("/(tabs)");
69
69
  }
70
70
  }, [user, isCheckingAuth, segments]);
@@ -93,14 +93,10 @@ export default function RootLayout() {
93
93
  name="(auth)"
94
94
  options={{ headerShown: false, animation: "fade" }}
95
95
  />
96
- <Stack.Screen
97
- name="doc-viewer"
98
- options={{ presentation: "fullScreenModal" }}
99
- />
100
96
  </Stack>
101
97
  </BiometricLock>
102
- <Toast />
103
98
  </PaperProvider>
99
+ <Toast />
104
100
  </GestureHandlerRootView>
105
101
  );
106
102
  }