@imksh/create 1.0.30 → 1.0.32

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 (247) 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/src/utils/askTemplate.js +2 -1
  6. package/templates/layers/electron/base/electron/main.js +262 -0
  7. package/templates/layers/electron/base/electron/preload.js +37 -0
  8. package/templates/layers/electron/base/electron-builder.json5 +68 -0
  9. package/templates/layers/electron/javascript/_gitignore +38 -0
  10. package/templates/layers/electron/javascript/package.json +49 -0
  11. package/templates/layers/electron/javascript/src/components/layout/SidebarLayout.jsx +43 -0
  12. package/templates/layers/electron/javascript/src/components/ui/TitleBar.jsx +130 -0
  13. package/templates/layers/electron/javascript/src/config/appConfig.js +51 -0
  14. package/templates/layers/electron/javascript/src/hooks/useElectron.js +68 -0
  15. package/templates/layers/electron/javascript/src/main.jsx +17 -0
  16. package/templates/layers/electron/javascript/src/store/useUiStore.js +59 -0
  17. package/templates/layers/electron/javascript/vite.config.js +29 -0
  18. package/templates/layers/electron/typescript/_gitignore +38 -0
  19. package/templates/layers/electron/typescript/electron/main.ts +213 -0
  20. package/templates/layers/electron/typescript/electron/preload.ts +52 -0
  21. package/templates/layers/electron/typescript/package.json +52 -0
  22. package/templates/layers/electron/typescript/src/components/layout/SidebarLayout.tsx +42 -0
  23. package/templates/layers/electron/typescript/src/components/ui/TitleBar.tsx +120 -0
  24. package/templates/layers/electron/typescript/src/config/appConfig.ts +52 -0
  25. package/templates/layers/electron/typescript/src/hooks/useElectron.ts +68 -0
  26. package/templates/layers/electron/typescript/src/main.tsx +17 -0
  27. package/templates/layers/electron/typescript/src/store/useUiStore.ts +97 -0
  28. package/templates/layers/electron/typescript/src/vite-env.d.ts +13 -0
  29. package/templates/layers/electron/typescript/tsconfig.json +25 -0
  30. package/templates/layers/electron/typescript/tsconfig.node.json +11 -0
  31. package/templates/layers/electron/typescript/vite.config.ts +29 -0
  32. package/templates/layers/next/javascript/package.json +8 -2
  33. package/templates/layers/next/javascript/src/components/common/Breadcrumbs.jsx +44 -6
  34. package/templates/layers/next/javascript/src/components/common/Loading.jsx +1 -0
  35. package/templates/layers/next/javascript/src/components/common/LottieIcon.jsx +1 -0
  36. package/templates/layers/next/javascript/src/components/common/Pagination.jsx +170 -0
  37. package/templates/layers/next/javascript/src/components/common/SidebarModal.jsx +180 -0
  38. package/templates/layers/next/javascript/src/components/common/StatsCard.jsx +168 -0
  39. package/templates/layers/next/javascript/src/components/common/Table.jsx +191 -41
  40. package/templates/layers/next/javascript/src/components/common/Tabs.jsx +187 -0
  41. package/templates/layers/next/javascript/src/components/common/ToggleSwitch.jsx +4 -3
  42. package/templates/layers/next/javascript/src/components/layout/ProtectedRoute.jsx +2 -1
  43. package/templates/layers/next/javascript/src/components/layout/PublicLayout.jsx +3 -6
  44. package/templates/layers/next/javascript/src/components/layout/SidebarLayout.jsx +4 -17
  45. package/templates/layers/next/javascript/src/components/modals/ConfirmModal.jsx +4 -12
  46. package/templates/layers/next/javascript/src/components/modals/Modal.jsx +50 -19
  47. package/templates/layers/next/javascript/src/components/ui/Input.jsx +50 -0
  48. package/templates/layers/next/{typescript/src/components/ui/sidebar.tsx → javascript/src/components/ui/Sidebar.jsx} +65 -53
  49. package/templates/layers/next/javascript/src/components/ui/SidebarHeader.jsx +11 -6
  50. package/templates/layers/next/javascript/src/config/appConfig.js +4 -4
  51. package/templates/layers/next/javascript/src/hooks/useWindowSize.js +2 -3
  52. package/templates/layers/next/javascript/src/store/useUiStore.js +9 -4
  53. package/templates/layers/next/typescript/.eslintrc.json +12 -0
  54. package/templates/layers/next/typescript/package.json +14 -3
  55. package/templates/layers/next/typescript/src/components/common/Breadcrumbs.tsx +57 -8
  56. package/templates/layers/next/typescript/src/components/common/Loading.tsx +2 -1
  57. package/templates/layers/next/typescript/src/components/common/LottieIcon.tsx +2 -2
  58. package/templates/layers/next/typescript/src/components/common/Pagination.tsx +186 -0
  59. package/templates/layers/next/typescript/src/components/common/SidebarModal.tsx +200 -0
  60. package/templates/layers/next/typescript/src/components/common/StatsCard.tsx +232 -0
  61. package/templates/layers/next/typescript/src/components/common/Table.tsx +205 -39
  62. package/templates/layers/next/typescript/src/components/common/Tabs.tsx +190 -0
  63. package/templates/layers/next/typescript/src/components/common/ToggleSwitch.tsx +12 -8
  64. package/templates/layers/next/typescript/src/components/layout/PublicLayout.tsx +8 -6
  65. package/templates/layers/next/typescript/src/components/layout/SidebarLayout.tsx +8 -17
  66. package/templates/layers/next/typescript/src/components/modals/ConfirmModal.tsx +3 -1
  67. package/templates/layers/next/typescript/src/components/modals/Modal.tsx +67 -21
  68. package/templates/layers/next/typescript/src/components/ui/Button.tsx +1 -0
  69. package/templates/layers/next/typescript/src/components/ui/Header.tsx +2 -2
  70. package/templates/layers/next/typescript/src/components/ui/Input.tsx +40 -60
  71. package/templates/layers/next/{javascript/src/components/ui/sidebar.jsx → typescript/src/components/ui/Sidebar.tsx} +77 -44
  72. package/templates/layers/next/typescript/src/components/ui/SidebarHeader.tsx +16 -10
  73. package/templates/layers/next/typescript/src/config/appConfig.ts +4 -4
  74. package/templates/layers/next/typescript/src/hooks/usePwaInstall.ts +10 -4
  75. package/templates/layers/next/typescript/src/hooks/useWindowSize.ts +2 -3
  76. package/templates/layers/next/typescript/src/services/authService.ts +1 -1
  77. package/templates/layers/next/typescript/src/store/useAuthStore.ts +24 -9
  78. package/templates/layers/next/typescript/src/store/useUiStore.ts +14 -4
  79. package/templates/layers/node/javascript/.env.example +3 -1
  80. package/templates/layers/node/javascript/package.json +12 -3
  81. package/templates/layers/node/javascript/src/app.js +2 -1
  82. package/templates/layers/node/javascript/src/controllers/auth.controller.js +106 -168
  83. package/templates/layers/node/javascript/src/controllers/push.controller.js +51 -58
  84. package/templates/layers/node/javascript/src/controllers/upload.controller.js +12 -19
  85. package/templates/layers/node/javascript/src/middleware/auth.middleware.js +5 -11
  86. package/templates/layers/node/javascript/src/middleware/errorHandler.js +6 -4
  87. package/templates/layers/node/javascript/src/routes/auth.route.js +2 -0
  88. package/templates/layers/node/javascript/src/services/auth.service.js +159 -164
  89. package/templates/layers/node/javascript/src/utils/ApiError.js +20 -0
  90. package/templates/layers/node/javascript/src/utils/SuccessResponse.js +15 -0
  91. package/templates/layers/node/javascript/src/utils/apiResponse.js +4 -0
  92. package/templates/layers/node/javascript/src/utils/asyncHandler.js +5 -0
  93. package/templates/layers/node/typescript/.env.example +3 -1
  94. package/templates/layers/node/typescript/.eslintrc.cjs +28 -0
  95. package/templates/layers/node/typescript/package-lock.json +2 -2
  96. package/templates/layers/node/typescript/package.json +17 -3
  97. package/templates/layers/node/typescript/src/app.ts +3 -2
  98. package/templates/layers/node/typescript/src/config/db.ts +3 -2
  99. package/templates/layers/node/typescript/src/config/socket.ts +5 -4
  100. package/templates/layers/node/typescript/src/controllers/auth.controller.ts +104 -132
  101. package/templates/layers/node/typescript/src/controllers/push.controller.ts +52 -59
  102. package/templates/layers/node/typescript/src/controllers/upload.controller.ts +12 -19
  103. package/templates/layers/node/typescript/src/middleware/auth.middleware.ts +13 -7
  104. package/templates/layers/node/typescript/src/middleware/errorHandler.ts +18 -5
  105. package/templates/layers/node/typescript/src/middleware/rateLimiter.ts +2 -2
  106. package/templates/layers/node/typescript/src/routes/auth.route.ts +2 -0
  107. package/templates/layers/node/typescript/src/services/auth.service.ts +86 -43
  108. package/templates/layers/node/typescript/src/types/express.d.ts +5 -3
  109. package/templates/layers/node/typescript/src/utils/ApiError.ts +25 -0
  110. package/templates/layers/node/typescript/src/utils/SuccessResponse.ts +17 -0
  111. package/templates/layers/node/typescript/src/utils/apiResponse.ts +4 -0
  112. package/templates/layers/node/typescript/src/utils/asyncHandler.ts +13 -0
  113. package/templates/layers/node/typescript/src/utils/cloudinaryUpload.ts +18 -7
  114. package/templates/layers/node/typescript/src/utils/expoNotification.ts +1 -1
  115. package/templates/layers/node/typescript/src/utils/genOtpToken.ts +7 -1
  116. package/templates/layers/node/typescript/src/utils/jwt.ts +8 -2
  117. package/templates/layers/node/typescript/src/utils/logger.ts +2 -1
  118. package/templates/layers/node/typescript/src/utils/pushHelper.ts +13 -9
  119. package/templates/layers/node-prisma/javascript/.env.example +3 -1
  120. package/templates/layers/node-prisma/javascript/package.json +11 -2
  121. package/templates/layers/node-prisma/javascript/src/app.js +2 -1
  122. package/templates/layers/node-prisma/javascript/src/controllers/auth.controller.js +90 -135
  123. package/templates/layers/node-prisma/javascript/src/controllers/push.controller.js +64 -76
  124. package/templates/layers/node-prisma/javascript/src/controllers/upload.controller.js +12 -19
  125. package/templates/layers/node-prisma/javascript/src/middleware/auth.middleware.js +5 -4
  126. package/templates/layers/node-prisma/javascript/src/middleware/errorHandler.js +6 -4
  127. package/templates/layers/node-prisma/javascript/src/routes/auth.route.js +2 -0
  128. package/templates/layers/node-prisma/javascript/src/services/auth.service.js +145 -122
  129. package/templates/layers/node-prisma/javascript/src/utils/ApiError.js +20 -0
  130. package/templates/layers/node-prisma/javascript/src/utils/SuccessResponse.js +15 -0
  131. package/templates/layers/node-prisma/javascript/src/utils/apiResponse.js +4 -0
  132. package/templates/layers/node-prisma/javascript/src/utils/asyncHandler.js +5 -0
  133. package/templates/layers/node-prisma/typescript/.env.example +3 -1
  134. package/templates/layers/node-prisma/typescript/.eslintrc.cjs +28 -0
  135. package/templates/layers/node-prisma/typescript/package.json +19 -5
  136. package/templates/layers/node-prisma/typescript/src/app.ts +3 -2
  137. package/templates/layers/node-prisma/typescript/src/config/prisma.ts +3 -2
  138. package/templates/layers/node-prisma/typescript/src/config/socket.ts +5 -4
  139. package/templates/layers/node-prisma/typescript/src/controllers/auth.controller.ts +89 -105
  140. package/templates/layers/node-prisma/typescript/src/controllers/push.controller.ts +67 -83
  141. package/templates/layers/node-prisma/typescript/src/controllers/upload.controller.ts +12 -19
  142. package/templates/layers/node-prisma/typescript/src/middleware/auth.middleware.ts +9 -13
  143. package/templates/layers/node-prisma/typescript/src/middleware/errorHandler.ts +18 -5
  144. package/templates/layers/node-prisma/typescript/src/middleware/rateLimiter.ts +2 -2
  145. package/templates/layers/node-prisma/typescript/src/routes/auth.route.ts +2 -0
  146. package/templates/layers/node-prisma/typescript/src/services/auth.service.ts +83 -31
  147. package/templates/layers/node-prisma/typescript/src/types/express.d.ts +5 -3
  148. package/templates/layers/node-prisma/typescript/src/utils/ApiError.ts +25 -0
  149. package/templates/layers/node-prisma/typescript/src/utils/SuccessResponse.ts +17 -0
  150. package/templates/layers/node-prisma/typescript/src/utils/apiResponse.ts +4 -0
  151. package/templates/layers/node-prisma/typescript/src/utils/asyncHandler.ts +13 -0
  152. package/templates/layers/node-prisma/typescript/src/utils/cloudinaryUpload.ts +18 -7
  153. package/templates/layers/node-prisma/typescript/src/utils/genOtpToken.ts +7 -1
  154. package/templates/layers/node-prisma/typescript/src/utils/jwt.ts +8 -2
  155. package/templates/layers/node-prisma/typescript/src/utils/logger.ts +2 -1
  156. package/templates/layers/node-prisma/typescript/src/utils/pushHelper.ts +10 -6
  157. package/templates/layers/prisma/javascript/package.json +8 -0
  158. package/templates/layers/prisma/typescript/package.json +14 -1
  159. package/templates/layers/prisma/typescript/prisma/schema.prisma +35 -10
  160. package/templates/layers/prisma/typescript/src/config/db.ts +3 -2
  161. package/templates/layers/react/javascript/package.json +6 -0
  162. package/templates/layers/react/javascript/src/components/common/Breadcrumbs.jsx +62 -58
  163. package/templates/layers/react/javascript/src/components/common/Pagination.jsx +164 -76
  164. package/templates/layers/react/javascript/src/components/common/SidebarModal.jsx +179 -0
  165. package/templates/layers/react/javascript/src/components/common/StatsCard.jsx +167 -0
  166. package/templates/layers/react/javascript/src/components/common/Table.jsx +248 -132
  167. package/templates/layers/react/javascript/src/components/common/Tabs.jsx +164 -112
  168. package/templates/layers/react/javascript/src/components/common/ToggleSwitch.jsx +3 -3
  169. package/templates/layers/react/javascript/src/components/layout/SidebarLayout.jsx +4 -12
  170. package/templates/layers/react/javascript/src/components/modals/Modal.jsx +53 -18
  171. package/templates/layers/react/javascript/src/components/ui/Input.jsx +49 -0
  172. package/templates/layers/react/javascript/src/components/ui/Sidebar.jsx +215 -0
  173. package/templates/layers/react/javascript/src/components/ui/SidebarHeader.jsx +25 -30
  174. package/templates/layers/react/javascript/src/config/appConfig.js +3 -3
  175. package/templates/layers/react/javascript/src/hooks/useWindowSize.js +2 -2
  176. package/templates/layers/react/typescript/.eslintrc.cjs +20 -0
  177. package/templates/layers/react/typescript/package.json +11 -2
  178. package/templates/layers/react/typescript/src/components/common/Breadcrumbs.tsx +32 -6
  179. package/templates/layers/react/typescript/src/components/common/Pagination.tsx +151 -57
  180. package/templates/layers/react/typescript/src/components/common/SidebarModal.tsx +199 -0
  181. package/templates/layers/react/typescript/src/components/common/StatsCard.tsx +231 -0
  182. package/templates/layers/react/typescript/src/components/common/Table.tsx +201 -38
  183. package/templates/layers/react/typescript/src/components/common/Tabs.tsx +56 -12
  184. package/templates/layers/react/typescript/src/components/common/ToggleSwitch.tsx +15 -3
  185. package/templates/layers/react/typescript/src/components/layout/SidebarLayout.tsx +3 -6
  186. package/templates/layers/react/typescript/src/components/modals/Modal.tsx +151 -0
  187. package/templates/layers/react/typescript/src/components/ui/Input.tsx +58 -0
  188. package/templates/layers/react/typescript/src/components/ui/Sidebar.tsx +116 -53
  189. package/templates/layers/react/typescript/src/components/ui/SidebarHeader.tsx +5 -4
  190. package/templates/layers/react/typescript/src/config/appConfig.ts +3 -3
  191. package/templates/layers/react/typescript/src/hooks/useWindowSize.ts +2 -3
  192. package/templates/layers/react/typescript/src/main.tsx +11 -11
  193. package/templates/layers/react/typescript/src/services/authService.ts +1 -1
  194. package/templates/layers/react/typescript/src/store/useAuthStore.ts +24 -9
  195. package/templates/layers/react-native/base/app.json +9 -22
  196. package/templates/layers/react-native/base/eslint.config.js +5 -1
  197. package/templates/layers/react-native/base/package.json +11 -1
  198. package/templates/layers/react-native/base/src/app/(auth)/edit-profile.tsx +7 -7
  199. package/templates/layers/react-native/base/src/app/(auth)/login.tsx +31 -7
  200. package/templates/layers/react-native/base/src/app/(tabs)/_layout.tsx +3 -3
  201. package/templates/layers/react-native/base/src/app/(tabs)/index.tsx +6 -5
  202. package/templates/layers/react-native/base/src/app/_layout.tsx +3 -3
  203. package/templates/layers/react-native/base/src/app/doc-viewer.tsx +3 -3
  204. package/templates/layers/react-native/base/src/components/common/ConfirmationToast.tsx +58 -40
  205. package/templates/layers/react-native/base/src/components/common/GoogleAuthButton.tsx +144 -0
  206. package/templates/layers/react-native/base/src/components/common/LocationLoader.tsx +64 -9
  207. package/templates/layers/react-native/base/src/components/common/Typography.tsx +54 -19
  208. package/templates/layers/react-native/base/src/components/ui/ClassicTabBar.tsx +15 -12
  209. package/templates/layers/react-native/base/src/components/ui/CustomTabBar.tsx +84 -90
  210. package/templates/layers/react-native/base/src/components/ui/Drawer.tsx +344 -0
  211. package/templates/layers/react-native/base/src/components/ui/Sidebar.tsx +4 -4
  212. package/templates/layers/react-native/base/src/components/ui/buttons/Button.tsx +29 -6
  213. package/templates/layers/react-native/base/src/components/ui/data-display/Accordion.tsx +2 -2
  214. package/templates/layers/react-native/base/src/components/ui/data-display/Badge.tsx +1 -2
  215. package/templates/layers/react-native/base/src/components/ui/data-display/Image.tsx +3 -3
  216. package/templates/layers/react-native/base/src/components/ui/data-display/SwipeableRow.tsx +28 -7
  217. package/templates/layers/react-native/base/src/components/ui/feedback/GestureWrapper.tsx +11 -4
  218. package/templates/layers/react-native/base/src/components/ui/inputs/DatePicker.tsx +3 -3
  219. package/templates/layers/react-native/base/src/components/ui/inputs/ImagePickerModal.tsx +45 -19
  220. package/templates/layers/react-native/base/src/components/ui/inputs/Input.tsx +28 -9
  221. package/templates/layers/react-native/base/src/components/ui/inputs/SearchablePicker.tsx +199 -0
  222. package/templates/layers/react-native/base/src/components/ui/inputs/Switch.tsx +7 -7
  223. package/templates/layers/react-native/base/src/components/ui/inputs/WebLocationPicker.tsx +146 -72
  224. package/templates/layers/react-native/base/src/config/api.ts +5 -5
  225. package/templates/layers/react-native/base/src/config/appConfig.ts +1 -1
  226. package/templates/layers/react-native/base/src/services/auth.service.ts +3 -1
  227. package/templates/layers/react-native/base/src/services/permission.service.ts +0 -2
  228. package/templates/layers/react-native/base/src/services/socket.service.ts +0 -7
  229. package/templates/layers/react-native/base/src/store/useAuthStore.ts +61 -16
  230. package/templates/layers/react-native/base/src/store/useNotificationStore.ts +36 -42
  231. package/templates/layers/react-native/base/src/types/images.d.ts +7 -5
  232. package/templates/layers/react-native/base/src/utils/fileDownload.ts +206 -0
  233. package/templates/layers/react-native/base/src/utils/storage.ts +1 -1
  234. package/templates/presets/electron/preset.json +9 -0
  235. package/templates/presets/electron-ts/preset.json +9 -0
  236. package/templates/presets/production-fullstack/overrides/client/package.json +9 -0
  237. package/templates/presets/production-fullstack/overrides/mobile/app.json +2 -15
  238. package/templates/presets/production-fullstack/overrides/mobile/package.json +11 -1
  239. package/templates/presets/production-fullstack/overrides/mobile/src/app/_layout.tsx +3 -3
  240. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/Drawer.tsx +344 -0
  241. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/DatePicker.tsx +3 -3
  242. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/ImagePickerModal.tsx +3 -3
  243. package/templates/presets/production-fullstack/overrides/server/package.json +11 -2
  244. package/templates/layers/react/javascript/src/components/ui/sidebar.jsx +0 -169
  245. package/templates/layers/react-native/base/src/components/ui/BottomModal.tsx +0 -176
  246. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/BottomModal.tsx +0 -159
  247. /package/templates/layers/react-native/base/assets/images/logo/{logoWithBg.png → icon.png} +0 -0
@@ -1,13 +1,20 @@
1
+ "use client";
1
2
  import { useEffect } from "react";
2
3
  import { createPortal } from "react-dom";
3
4
  import { IoClose } from "react-icons/io5";
5
+ import { useUiStore } from "../../store/useUiStore";
4
6
 
5
7
  const sizes = {
6
8
  sm: "max-w-sm",
7
9
  md: "max-w-md",
8
10
  lg: "max-w-lg",
9
- xl: "max-w-2xl",
10
- "2xl": "max-w-4xl",
11
+ xl: "max-w-xl",
12
+ "2xl": "max-w-2xl",
13
+ "3xl": "max-w-3xl",
14
+ "4xl": "max-w-4xl",
15
+ "5xl": "max-w-5xl",
16
+ "6xl": "max-w-6xl",
17
+ "7xl": "max-w-7xl",
11
18
  full: "max-w-7xl",
12
19
  };
13
20
 
@@ -16,12 +23,27 @@ const Modal = ({
16
23
  onClose,
17
24
  title,
18
25
  children,
19
- size = "md",
26
+ size = "4xl",
20
27
  closeOnBackdrop = true,
21
28
  closeOnEsc = true,
22
29
  showCloseButton = true,
30
+ hideHeader = false,
31
+ className = "",
32
+ bodyClass = "p-2 sm:p-4",
23
33
  footer,
34
+ height,
24
35
  }) => {
36
+ const setModalOpen = useUiStore((state) => state.setModalOpen);
37
+
38
+ useEffect(() => {
39
+ if (open) {
40
+ setModalOpen(true);
41
+ return () => {
42
+ setModalOpen(false);
43
+ };
44
+ }
45
+ }, [open, setModalOpen]);
46
+
25
47
  useEffect(() => {
26
48
  if (!open || !closeOnEsc) return;
27
49
 
@@ -33,8 +55,9 @@ const Modal = ({
33
55
 
34
56
  document.addEventListener("keydown", handleKeyDown);
35
57
 
36
- return () =>
58
+ return () => {
37
59
  document.removeEventListener("keydown", handleKeyDown);
60
+ };
38
61
  }, [open, closeOnEsc, onClose]);
39
62
 
40
63
  if (!open) return null;
@@ -51,37 +74,45 @@ const Modal = ({
51
74
  <div
52
75
  className={`
53
76
  relative
77
+ flex flex-col overflow-hidden max-h-[90vh]
54
78
  w-full
55
79
  ${sizes[size]}
56
80
  rounded-2xl
57
81
  bg-base-100
58
- shadow-2xl
82
+ shadow-md
59
83
  border border-base-300
60
84
  animate-in zoom-in-95 fade-in duration-200
85
+ ${className}
61
86
  `}
87
+ style={height ? { height } : undefined}
62
88
  >
63
89
  {/* Header */}
64
- <div className="flex items-center justify-between border-b border-base-300 px-6 py-4">
65
- <h2 className="text-lg font-bold">{title}</h2>
90
+ {!hideHeader && (title || showCloseButton) && (
91
+ <div className="flex items-center justify-between border-b border-base-300 px-6 py-4 shrink-0">
92
+ {title && <h2 className="text-lg font-bold">{title}</h2>}
66
93
 
67
- {showCloseButton && (
68
- <button
69
- className="btn btn-circle btn-sm btn-ghost"
70
- onClick={onClose}
71
- >
72
- <IoClose size={20} />
73
- </button>
74
- )}
75
- </div>
94
+ {showCloseButton && (
95
+ <button
96
+ className="btn btn-circle btn-sm btn-error btn-soft text-error/70 hover:text-error hover:bg-error/20 hover:shadow-sm hover:rotate-180 transition-transform duration-200"
97
+ onClick={onClose}
98
+ >
99
+ <IoClose size={20} className="" />
100
+ </button>
101
+ )}
102
+ </div>
103
+ )}
76
104
 
77
105
  {/* Body */}
78
- <div className="max-h-[70vh] overflow-y-auto p-6">
106
+ <div
107
+ className={`flex-1 min-h-0 overflow-y-auto ${bodyClass}`}
108
+ data-lenis-prevent="true"
109
+ >
79
110
  {children}
80
111
  </div>
81
112
 
82
113
  {/* Footer */}
83
114
  {footer && (
84
- <div className="border-t border-base-300 px-6 py-4">
115
+ <div className="border-t border-base-300 px-6 py-4 shrink-0">
85
116
  {footer}
86
117
  </div>
87
118
  )}
@@ -91,4 +122,4 @@ const Modal = ({
91
122
  );
92
123
  };
93
124
 
94
- export default Modal;
125
+ export default Modal;
@@ -0,0 +1,50 @@
1
+ "use client";
2
+ import React from "react";
3
+ import { X } from "lucide-react";
4
+
5
+ export const Input = React.forwardRef(
6
+ (
7
+ {
8
+ icon,
9
+ wrapperClassName = "",
10
+ onClear,
11
+ className = "",
12
+ value,
13
+ size,
14
+ ...props
15
+ },
16
+ ref,
17
+ ) => {
18
+ const sizeClass = size ? `input-${size}` : "";
19
+ return (
20
+ <div className={`relative ${wrapperClassName}`}>
21
+ {icon && (
22
+ <div className="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/50 pointer-events-none flex items-center justify-center z-10">
23
+ {icon}
24
+ </div>
25
+ )}
26
+ <input
27
+ ref={ref}
28
+ value={value}
29
+ className={`input input-bordered w-full ${sizeClass} ${icon ? "pl-10" : ""} ${
30
+ onClear && value ? "pr-10" : ""
31
+ } ${className}`}
32
+ {...props}
33
+ />
34
+
35
+ {onClear && value && (
36
+ <button
37
+ type="button"
38
+ onClick={onClear}
39
+ className="absolute right-3 top-1/2 -translate-y-1/2 text-base-content/40 hover:text-base-content transition-colors flex items-center justify-center"
40
+ aria-label="Clear input"
41
+ >
42
+ <X size={16} />
43
+ </button>
44
+ )}
45
+ </div>
46
+ );
47
+ },
48
+ );
49
+
50
+ Input.displayName = "Input";
@@ -1,26 +1,36 @@
1
1
  "use client";
2
2
  import Link from "next/link";
3
- import { usePathname } from "next/navigation";
3
+ import { usePathname, useRouter } from "next/navigation";
4
4
  import { IoClose } from "react-icons/io5";
5
5
  import { useUiStore } from "../../store/useUiStore";
6
6
  import { navigation } from "../../config/navigation";
7
- import { ChevronLeft, ChevronRight, Moon, Sun } from "lucide-react";
7
+ import { Moon, Sun } from "lucide-react";
8
8
  import appConfig from "../../config/appConfig";
9
9
  import { motion, AnimatePresence } from "framer-motion";
10
10
  import useWindowSize from "../../hooks/useWindowSize";
11
+ import { useAuthStore } from "../../store/useAuthStore";
12
+ import { GoSidebarCollapse, GoSidebarExpand } from "react-icons/go";
13
+ import { CiLogout } from "react-icons/ci";
11
14
 
12
15
  const Sidebar = () => {
13
- const { open, close, collapsed, toggleCollapsed } = useUiStore();
14
- const { theme, toggleTheme } = useUiStore();
16
+ const { open, close, collapsed, toggleCollapsed, theme, toggleTheme } =
17
+ useUiStore();
18
+ const { logout, user } = useAuthStore();
15
19
  const { width } = useWindowSize();
16
20
  const pathname = usePathname();
17
- const isMobile = width < 1024; // lg breakpoint
21
+ const router = useRouter();
22
+ const isMobile = width < 1024;
18
23
 
19
24
  const showSidebar = !isMobile || open;
20
25
 
26
+ const handleLogout = async () => {
27
+ await logout();
28
+ close();
29
+ router.replace("/login");
30
+ };
31
+
21
32
  return (
22
33
  <>
23
- {/* Overlay with AnimatePresence */}
24
34
  <AnimatePresence>
25
35
  {isMobile && open && (
26
36
  <motion.div
@@ -34,7 +44,6 @@ const Sidebar = () => {
34
44
  )}
35
45
  </AnimatePresence>
36
46
 
37
- {/* Sidebar with AnimatePresence */}
38
47
  <AnimatePresence>
39
48
  {showSidebar && (
40
49
  <motion.aside
@@ -47,18 +56,14 @@ const Sidebar = () => {
47
56
  h-screen bg-base-200 border-r border-base-300
48
57
  flex flex-col overflow-hidden
49
58
  transition-[width] duration-300
50
- ${collapsed ? "w-20" : "w-[75%] md:w-[16%] md:max-w-60"}
59
+ ${collapsed ? "w-18" : "w-[75%] md:w-[16%] md:max-w-60"}
51
60
  `}
52
61
  >
53
62
  {/* Header */}
54
63
  <div className="h-16 border-b border-base-300 flex items-center justify-between px-5">
55
64
  <div className="flex items-center gap-3">
56
65
  {appConfig.app.logo ? (
57
- <img
58
- src={appConfig.app.logo}
59
- alt=""
60
- className="w-8 h-8 rounded-lg"
61
- />
66
+ <img src={appConfig.app.logo} alt="" className="w-8 h-8 rounded-lg" />
62
67
  ) : (
63
68
  <div className="flex items-center">
64
69
  <div className="bg-primary w-8 h-8 rounded-lg flex items-center justify-center text-primary-content font-bold">
@@ -85,65 +90,72 @@ const Sidebar = () => {
85
90
  <nav className="flex-1 overflow-y-auto p-2.5 space-y-1" data-lenis-prevent>
86
91
  {navigation.map((item) => {
87
92
  const Icon = item.icon;
88
- const isActive = pathname === item.path;
93
+ const isActive =
94
+ item.path === "/" ? pathname === "/" : pathname.startsWith(item.path);
89
95
 
90
96
  return (
91
97
  <Link
92
98
  key={item.path}
93
99
  href={item.path}
94
100
  onClick={isMobile ? close : undefined}
95
- className={`flex items-center gap-3 rounded-box px-4 py-3 transition-all h-12
96
- ${
97
- isActive
98
- ? "bg-primary text-primary-content"
99
- : "hover:bg-base-300"
100
- } ${collapsed ? "justify-center px-0" : ""}`
101
- }
102
101
  title={collapsed ? item.title : ""}
102
+ className={`flex items-center gap-3 rounded-box px-4 py-3 h-12 transition-colors
103
+ ${isActive ? "bg-primary text-primary-content" : "hover:bg-base-300"}
104
+ ${collapsed ? "justify-center px-0" : ""}`}
103
105
  >
104
- <Icon
105
- size={18}
106
- className={`shrink-0 ${collapsed && "mr-auto"}`}
107
- />
108
-
106
+ <Icon size={18} className={`shrink-0 ${collapsed ? "mr-auto" : ""}`} />
109
107
  {!collapsed && (
110
- <span className="font-medium transition-all duration-300">
111
- {item.title}
112
- </span>
108
+ <span className="font-medium whitespace-nowrap">{item.title}</span>
113
109
  )}
114
110
  </Link>
115
111
  );
116
112
  })}
117
113
  </nav>
118
114
 
119
- {/* Footer with Collapse Button */}
120
- <button
121
- onClick={toggleTheme}
122
- className={`w-full flex items-center gap-3 px-3 py-2.5 md:px-4 text-sm font-semibold transition-all duration-150 text-base-content/60 hover:text-base-content hover:bg-base-300/60 justify-between rounded-none ${collapsed ? "justify-center" : ""}`}
123
- title="Toggle Theme"
115
+ {/* Footer */}
116
+ <div
117
+ className={`p-3 border-t border-base-300/50 shrink-0 flex gap-2 ${
118
+ collapsed ? "flex-col items-center justify-center" : "flex-row items-center justify-between"
119
+ }`}
124
120
  >
125
- {!collapsed && <span>{theme === "dark" ? "Dark" : "Light"}</span>}
126
- <span className="btn btn-xs btn-ghost btn-circle ">
127
- {theme === "dark" ? (
128
- <Sun size={16} className="shrink-0 " />
129
- ) : (
130
- <Moon size={16} className="shrink-0" />
131
- )}
132
- </span>
133
- </button>
134
- <div className="p-3 border-t border-base-300/50 shrink-0 flex flex-col gap-2">
135
121
  <button
136
- onClick={toggleCollapsed}
137
- className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-semibold transition-all duration-150 text-base-content/60 hover:text-base-content hover:bg-base-300/60 ${collapsed ? "justify-center" : ""}`}
138
- title={collapsed ? "Expand Sidebar" : "Collapse Sidebar"}
122
+ onClick={handleLogout}
123
+ className={`btn btn-sm btn-circle btn-soft btn-error ${collapsed ? "hidden" : "flex"}`}
124
+ title="Logout"
139
125
  >
140
- {collapsed ? (
141
- <ChevronRight size={18} className="shrink-0 mr-auto" />
142
- ) : (
143
- <ChevronLeft size={18} className="shrink-0" />
144
- )}
145
- {!collapsed && <span className="truncate">Collapse</span>}
126
+ <CiLogout size={18} />
146
127
  </button>
128
+
129
+ <div className={`flex items-center gap-2 ${collapsed ? "flex-col" : ""}`}>
130
+ <button
131
+ onClick={toggleTheme}
132
+ className="flex items-center gap-3 hover:opacity-80 transition-opacity"
133
+ title="Toggle Theme"
134
+ >
135
+ <div
136
+ className={`btn btn-sm btn-circle btn-primary btn-soft pointer-events-none ${collapsed ? "hidden" : "flex"}`}
137
+ >
138
+ {theme === "dark" ? (
139
+ <Sun size={16} className="shrink-0" />
140
+ ) : (
141
+ <Moon size={16} className="shrink-0" />
142
+ )}
143
+ </div>
144
+ {!collapsed && (
145
+ <span className="md:hidden font-medium text-sm text-base-content/80">
146
+ {theme === "dark" ? "Dark Mode" : "Light Mode"}
147
+ </span>
148
+ )}
149
+ </button>
150
+
151
+ <button
152
+ onClick={toggleCollapsed}
153
+ className="btn btn-sm btn-circle btn-outline border-none text-base-content/70 hover:text-base-content hover:bg-base-300/60 hidden md:flex"
154
+ title={collapsed ? "Expand Sidebar" : "Collapse Sidebar"}
155
+ >
156
+ {collapsed ? <GoSidebarExpand size={18} /> : <GoSidebarCollapse size={18} />}
157
+ </button>
158
+ </div>
147
159
  </div>
148
160
  </motion.aside>
149
161
  )}
@@ -1,11 +1,14 @@
1
+ "use client";
2
+ import React from "react";
1
3
  import { FiMenu } from "react-icons/fi";
2
4
  import { useUiStore } from "../../store/useUiStore";
5
+ import { Breadcrumbs } from "../common/Breadcrumbs";
3
6
 
4
7
  const SidebarHeader = ({ title = "Dashboard", actions = null }) => {
5
- const { toggleSidebar } = useUiStore();
8
+ const { toggleSidebar, breadcrumbs } = useUiStore();
6
9
 
7
10
  return (
8
- <header className="sticky top-0 z-30 h-16 bg-base-200 backdrop-blur border-b border-base-300 flex items-center justify-between px-4 lg:px-6">
11
+ <header className="sticky top-0 z-30 h-16 bg-base-200 backdrop-blur border-b border-base-200 flex items-center justify-between px-4 lg:px-6">
9
12
  <div className="flex items-center gap-3">
10
13
  <button
11
14
  onClick={toggleSidebar}
@@ -14,12 +17,14 @@ const SidebarHeader = ({ title = "Dashboard", actions = null }) => {
14
17
  <FiMenu size={22} />
15
18
  </button>
16
19
 
17
- <h1 className="text-xl font-bold">{title}</h1>
20
+ {breadcrumbs && breadcrumbs.length > 0 ? (
21
+ <Breadcrumbs items={breadcrumbs} />
22
+ ) : (
23
+ <h1 className="text-xl font-bold">{title}</h1>
24
+ )}
18
25
  </div>
19
26
 
20
- <div className="flex items-center gap-2">
21
- {actions}
22
- </div>
27
+ <div className="flex items-center gap-2">{actions}</div>
23
28
  </header>
24
29
  );
25
30
  };
@@ -1,11 +1,11 @@
1
1
  const appConfig = {
2
2
  app: {
3
- name: "React App",
3
+ name: "My App",
4
4
  logo: "./logo.png",
5
- shortName: "React",
6
- description: "A React application built with @imksh/create",
5
+ shortName: "App",
6
+ description: "A Next.js application built with @imksh/create",
7
7
  version: "1.0.0",
8
- author: "Karan Sharma",
8
+ author: "",
9
9
  },
10
10
 
11
11
  api: {
@@ -2,11 +2,10 @@ import { useState, useEffect } from "react";
2
2
 
3
3
  const useWindowSize = () => {
4
4
  const [size, setSize] = useState({
5
- width: window.innerWidth,
6
- height: window.innerHeight,
5
+ width: typeof window !== "undefined" ? window.innerWidth : 1024,
6
+ height: typeof window !== "undefined" ? window.innerHeight : 768,
7
7
  });
8
8
 
9
-
10
9
  useEffect(() => {
11
10
  const handleResize = () => {
12
11
  setSize({
@@ -6,6 +6,8 @@ export const useUiStore = create((set, get) => ({
6
6
  isMobileMenuOpened: false,
7
7
  headerTitle: "Dashboard",
8
8
  headerActions: null,
9
+ breadcrumbs: null,
10
+ setBreadcrumbs: (items) => set({ breadcrumbs: items }),
9
11
  setHeaderTitle: (title) => set({ headerTitle: title }),
10
12
  setHeaderActions: (actions) => set({ headerActions: actions }),
11
13
  toggleCollapsed: () => set((state) => ({ collapsed: !state.collapsed })),
@@ -17,7 +19,10 @@ export const useUiStore = create((set, get) => ({
17
19
  set((state) => ({ isMobileMenuOpened: !state.isMobileMenuOpened }));
18
20
  },
19
21
 
20
- theme: typeof window !== "undefined" ? localStorage.getItem("theme") || "light" : "light",
22
+ theme:
23
+ typeof window !== "undefined"
24
+ ? localStorage.getItem("theme") || "light"
25
+ : "light",
21
26
 
22
27
  setTheme: (theme) => {
23
28
  if (typeof document !== "undefined") {
@@ -26,20 +31,17 @@ export const useUiStore = create((set, get) => ({
26
31
  if (typeof window !== "undefined") {
27
32
  localStorage.setItem("theme", theme);
28
33
  }
29
-
30
34
  set({ theme });
31
35
  },
32
36
 
33
37
  toggleTheme: () => {
34
38
  const nextTheme = get().theme === "light" ? "dark" : "light";
35
-
36
39
  if (typeof document !== "undefined") {
37
40
  document.documentElement.setAttribute("data-theme", nextTheme);
38
41
  }
39
42
  if (typeof window !== "undefined") {
40
43
  localStorage.setItem("theme", nextTheme);
41
44
  }
42
-
43
45
  set({ theme: nextTheme });
44
46
  },
45
47
 
@@ -57,4 +59,7 @@ export const useUiStore = create((set, get) => ({
57
59
  set({
58
60
  open: false,
59
61
  }),
62
+
63
+ modalOpen: false,
64
+ setModalOpen: (open) => set({ modalOpen: open }),
60
65
  }));
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": [
3
+ "next/core-web-vitals",
4
+ "plugin:@typescript-eslint/recommended"
5
+ ],
6
+ "parser": "@typescript-eslint/parser",
7
+ "plugins": ["@typescript-eslint"],
8
+ "rules": {
9
+ "@typescript-eslint/no-explicit-any": "error",
10
+ "no-console": "error"
11
+ }
12
+ }
@@ -6,7 +6,13 @@
6
6
  "dev": "next dev",
7
7
  "build": "next build",
8
8
  "start": "next start",
9
- "lint": "next lint"
9
+ "lint": "next lint",
10
+ "lint:fix": "next lint --fix",
11
+ "format": "prettier --write \"src/**/*.{ts,tsx,css,json}\"",
12
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,css,json}\"",
13
+ "circular-check": "dpdm --circular --no-warning --no-tree --exit-code circular:1 \"src/**/*.{ts,tsx}\"",
14
+ "ts-prune": "ts-prune",
15
+ "ts-purns": "ts-prune"
10
16
  },
11
17
  "dependencies": {
12
18
  "@ducanh2912/next-pwa": "latest",
@@ -30,8 +36,13 @@
30
36
  "@types/node": "^20",
31
37
  "@types/react": "^19.2.18",
32
38
  "@types/react-dom": "^19.2.4",
33
- "eslint": "^10.8.1",
34
- "eslint-config-next": "^16.3.0",
39
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
40
+ "@typescript-eslint/parser": "^8.0.0",
41
+ "dpdm": "^3.14.0",
42
+ "eslint": "^9.0.0",
43
+ "eslint-config-next": "^15.0.0",
44
+ "prettier": "^3.4.2",
45
+ "ts-prune": "^0.10.3",
35
46
  "typescript": "^5"
36
47
  }
37
48
  }
@@ -1,25 +1,74 @@
1
1
  "use client";
2
2
  import React from "react";
3
3
  import Link from "next/link";
4
- import { ChevronRight } from "lucide-react";
4
+ import { useRouter } from "next/navigation";
5
+ import { ArrowLeft, ChevronRight } from "lucide-react";
5
6
 
6
- export const Breadcrumbs = ({ items }: { items: any[] }) => {
7
+ export interface BreadcrumbItem {
8
+ label: React.ReactNode;
9
+ path?: string;
10
+ subtitle?: string;
11
+ onClick?: () => void;
12
+ }
13
+
14
+ interface BreadcrumbsProps {
15
+ items: BreadcrumbItem[];
16
+ }
17
+
18
+ export const Breadcrumbs = ({ items }: BreadcrumbsProps) => {
19
+ const router = useRouter();
7
20
  return (
8
21
  <div className="flex items-center gap-1.5 text-sm font-bold text-base-content/50 flex-wrap">
9
- {items.map((item: any, idx: number) => {
22
+ <button
23
+ className="btn btn-primary btn-soft btn-square btn-sm mr-1 hidden md:flex"
24
+ onClick={() => router.back()}
25
+ >
26
+ <ArrowLeft size={18} />
27
+ </button>
28
+ {items.map((item, idx) => {
10
29
  const isLast = idx === items.length - 1;
11
30
  return (
12
31
  <React.Fragment key={idx}>
13
32
  {item.path && !isLast ? (
14
- <Link href={item.path} className="hover:text-primary transition-colors">
33
+ <Link
34
+ href={item.path}
35
+ onClick={item.onClick}
36
+ className="hover:text-primary transition-colors hidden sm:flex items-center gap-1"
37
+ >
15
38
  {item.label}
16
39
  </Link>
17
- ) : (
18
- <span className={isLast ? "text-base font-black text-base-content tracking-tight" : ""}>
40
+ ) : item.onClick && !isLast ? (
41
+ <button
42
+ type="button"
43
+ onClick={item.onClick}
44
+ className="hover:text-primary transition-colors hidden sm:flex items-center gap-1"
45
+ >
19
46
  {item.label}
20
- </span>
47
+ </button>
48
+ ) : (
49
+ <div className="flex flex-col">
50
+ <span
51
+ className={
52
+ isLast
53
+ ? "text-lg md:text-xl font-bold leading-tight text-base-content tracking-tight truncate max-w-[200px] md:max-w-none"
54
+ : ""
55
+ }
56
+ >
57
+ {item.label}
58
+ </span>
59
+ {item.subtitle && (
60
+ <span className="text-xs text-base-content/60 font-normal truncate">
61
+ {item.subtitle}
62
+ </span>
63
+ )}
64
+ </div>
65
+ )}
66
+ {!isLast && (
67
+ <ChevronRight
68
+ size={14}
69
+ className="text-base-content/30 shrink-0 hidden sm:block"
70
+ />
21
71
  )}
22
- {!isLast && <ChevronRight size={14} className="text-base-content/30 shrink-0" />}
23
72
  </React.Fragment>
24
73
  );
25
74
  })}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import React from "react";
2
3
  import LottieAnimation from "./LottieIcon";
3
4
  import loader from "../../assets/animations/loading.json";
@@ -9,7 +10,7 @@ const Loading = ({
9
10
  }: {
10
11
  className?: string;
11
12
  bgClass?: string;
12
- animationData?: any;
13
+ animationData?: object;
13
14
  }) => {
14
15
  return (
15
16
  <div
@@ -10,12 +10,12 @@ const LottieIcon = memo(
10
10
  loop = true,
11
11
  autoplay = true,
12
12
  }: {
13
- animation: any;
13
+ animation: object;
14
14
  className?: string;
15
15
  loop?: boolean;
16
16
  autoplay?: boolean;
17
17
  }) => {
18
- const containerRef = useRef(null);
18
+ const containerRef = useRef<HTMLDivElement>(null);
19
19
 
20
20
  const isInView = useInView(containerRef, {
21
21
  once: true,