create-einja-app 0.2.17 → 0.2.19

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 (275) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +685 -1715
  3. package/dist/cli.js.map +1 -1
  4. package/package.json +2 -2
  5. package/templates/default/.claude/hooks/einja/playwright-resize.sh +12 -2
  6. package/templates/default/.claude/settings.json +16 -0
  7. package/templates/default/.cursor/commands/task-vibe-kanban-loop.md +107 -42
  8. package/templates/default/.env.develop +0 -4
  9. package/templates/default/.env.example +1 -0
  10. package/templates/default/.env.preview +0 -4
  11. package/templates/default/.env.staging +19 -0
  12. package/templates/default/.github/actions/ci/action.yml +39 -0
  13. package/templates/default/.github/actions/migrate/action.yml +39 -0
  14. package/templates/default/.github/actions/neon-export-env/action.yml +28 -0
  15. package/templates/default/.github/actions/setup/action.yml +20 -0
  16. package/templates/default/.github/workflows/claude.yml +1 -0
  17. package/templates/default/.github/workflows/{cleanup-neon-branches.yml → cleanup-pr-preview-db.yml} +28 -24
  18. package/templates/default/.github/workflows/cleanup-pr-preview-on-close.yml +50 -0
  19. package/templates/default/.github/workflows/deploy-pr-preview.yml +398 -0
  20. package/templates/default/.github/workflows/deploy-stable-branches.yml +259 -0
  21. package/templates/default/.github/workflows/release-create-einja-app.yml +95 -0
  22. package/templates/default/.mcp.json +29 -11
  23. package/templates/default/.serena/project.yml +4 -0
  24. package/templates/default/.vscode/settings.json +18 -0
  25. package/templates/default/CLAUDE.md +129 -353
  26. package/templates/default/README.md +5 -14
  27. package/templates/default/apps/admin/next.config.ts +11 -0
  28. package/templates/default/apps/admin/package.json +55 -0
  29. package/templates/default/apps/admin/postcss.config.cjs +5 -0
  30. package/templates/default/apps/admin/src/app/(auth)/forgot-password/page.tsx +97 -0
  31. package/templates/default/apps/admin/src/app/(auth)/layout.tsx +18 -0
  32. package/templates/default/apps/admin/src/app/(auth)/otp/page.tsx +121 -0
  33. package/templates/default/apps/admin/src/app/(auth)/sign-in/page.tsx +145 -0
  34. package/templates/default/apps/admin/src/app/(auth)/sign-up/page.tsx +199 -0
  35. package/templates/default/apps/admin/src/app/(errors)/401/page.tsx +27 -0
  36. package/templates/default/apps/admin/src/app/(errors)/403/page.tsx +28 -0
  37. package/templates/default/apps/admin/src/app/(errors)/500/page.tsx +29 -0
  38. package/templates/default/apps/admin/src/app/(errors)/layout.tsx +7 -0
  39. package/templates/default/apps/admin/src/app/(errors)/maintenance/page.tsx +25 -0
  40. package/templates/default/apps/admin/src/app/dashboard/_components/analytics-chart.tsx +68 -0
  41. package/templates/default/apps/admin/src/app/dashboard/_components/analytics.tsx +182 -0
  42. package/templates/default/apps/admin/src/app/dashboard/_components/dashboard-page.tsx +74 -0
  43. package/templates/default/apps/admin/src/app/dashboard/_components/metric-cards.tsx +49 -0
  44. package/templates/default/apps/admin/src/app/dashboard/_components/overview-chart.tsx +73 -0
  45. package/templates/default/apps/admin/src/app/dashboard/_components/recent-sales.tsx +75 -0
  46. package/templates/default/apps/admin/src/app/dashboard/apps/_components/apps-page.tsx +135 -0
  47. package/templates/default/apps/admin/src/app/dashboard/apps/page.tsx +10 -0
  48. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-list.tsx +82 -0
  49. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-messages.tsx +194 -0
  50. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chats-page.tsx +99 -0
  51. package/templates/default/apps/admin/src/app/dashboard/chats/_components/new-chat.tsx +118 -0
  52. package/templates/default/apps/admin/src/app/dashboard/chats/page.tsx +10 -0
  53. package/templates/default/apps/admin/src/app/dashboard/layout.tsx +9 -0
  54. package/templates/default/apps/admin/src/app/dashboard/not-found.tsx +14 -0
  55. package/templates/default/apps/admin/src/app/dashboard/page.tsx +10 -0
  56. package/templates/default/apps/admin/src/app/dashboard/settings/_components/content-section.tsx +20 -0
  57. package/templates/default/apps/admin/src/app/dashboard/settings/_components/sidebar-nav.tsx +66 -0
  58. package/templates/default/apps/admin/src/app/dashboard/settings/account/page.tsx +173 -0
  59. package/templates/default/apps/admin/src/app/dashboard/settings/appearance/page.tsx +156 -0
  60. package/templates/default/apps/admin/src/app/dashboard/settings/display/page.tsx +125 -0
  61. package/templates/default/apps/admin/src/app/dashboard/settings/layout.tsx +30 -0
  62. package/templates/default/apps/admin/src/app/dashboard/settings/notifications/page.tsx +196 -0
  63. package/templates/default/apps/admin/src/app/dashboard/settings/page.tsx +5 -0
  64. package/templates/default/apps/admin/src/app/dashboard/settings/profile/page.tsx +176 -0
  65. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-bulk-actions.tsx +183 -0
  66. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-row-actions.tsx +79 -0
  67. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-columns.tsx +107 -0
  68. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-dialogs.tsx +71 -0
  69. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-import-dialog.tsx +106 -0
  70. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-multi-delete-dialog.tsx +90 -0
  71. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-mutate-drawer.tsx +207 -0
  72. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-page.tsx +31 -0
  73. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-primary-buttons.tsx +19 -0
  74. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-provider.tsx +37 -0
  75. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-table.tsx +155 -0
  76. package/templates/default/apps/admin/src/app/dashboard/tasks/page.tsx +14 -0
  77. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-bulk-actions.tsx +136 -0
  78. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-row-actions.tsx +62 -0
  79. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-action-dialog.tsx +297 -0
  80. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-columns.tsx +121 -0
  81. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-delete-dialog.tsx +72 -0
  82. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-dialogs.tsx +49 -0
  83. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-invite-dialog.tsx +139 -0
  84. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-multi-delete-dialog.tsx +89 -0
  85. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-page.tsx +30 -0
  86. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-primary-buttons.tsx +19 -0
  87. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-provider.tsx +35 -0
  88. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-table.tsx +157 -0
  89. package/templates/default/apps/admin/src/app/dashboard/users/page.tsx +10 -0
  90. package/templates/default/apps/admin/src/app/globals.css +109 -0
  91. package/templates/default/apps/admin/src/app/layout.tsx +32 -0
  92. package/templates/default/apps/admin/src/app/not-found.tsx +14 -0
  93. package/templates/default/apps/admin/src/app/page.tsx +5 -0
  94. package/templates/default/apps/admin/src/components/layout/admin-layout.tsx +16 -0
  95. package/templates/default/apps/admin/src/components/layout/app-sidebar.tsx +52 -0
  96. package/templates/default/apps/admin/src/components/layout/nav-config.ts +131 -0
  97. package/templates/default/apps/admin/src/components/providers/theme-provider.tsx +10 -0
  98. package/templates/default/apps/admin/src/components/shared/long-text.tsx +78 -0
  99. package/templates/default/apps/admin/src/components/shared/search-input.tsx +16 -0
  100. package/templates/default/apps/admin/src/components/shared/select-dropdown.tsx +64 -0
  101. package/templates/default/apps/admin/src/data/apps.tsx +116 -0
  102. package/templates/default/apps/admin/src/data/chats.ts +114 -0
  103. package/templates/default/apps/admin/src/data/tasks.ts +114 -0
  104. package/templates/default/apps/admin/src/data/users.ts +90 -0
  105. package/templates/default/apps/admin/src/hooks/use-dialog-state.ts +17 -0
  106. package/templates/default/apps/admin/src/hooks/use-table-url-state.ts +243 -0
  107. package/templates/default/apps/admin/src/lib/show-submitted-data.tsx +12 -0
  108. package/templates/default/apps/admin/src/types/table.d.ts +9 -0
  109. package/templates/default/apps/admin/tsconfig.json +32 -0
  110. package/templates/default/apps/web/next.config.ts +1 -0
  111. package/templates/default/apps/web/package.json +0 -22
  112. package/templates/default/apps/web/postcss.config.cjs +0 -1
  113. package/templates/default/apps/web/src/app/(authenticated)/dashboard/page.tsx +4 -20
  114. package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTable.tsx +4 -4
  115. package/templates/default/apps/web/src/app/(authenticated)/data/page.tsx +1 -1
  116. package/templates/default/apps/web/src/app/(authenticated)/profile/page.tsx +1 -1
  117. package/templates/default/apps/web/src/app/error.tsx +8 -70
  118. package/templates/default/apps/web/src/app/global-error.tsx +8 -70
  119. package/templates/default/apps/web/src/app/globals.css +20 -0
  120. package/templates/default/apps/web/src/app/not-found.tsx +5 -39
  121. package/templates/default/apps/web/src/app/page.tsx +27 -203
  122. package/templates/default/apps/web/src/app/signin/page.tsx +27 -191
  123. package/templates/default/apps/web/src/app/signup/page.tsx +33 -240
  124. package/templates/default/apps/web/src/components/dashboard/dashboard-stats.tsx +11 -75
  125. package/templates/default/apps/web/src/components/shared/Sidebar.tsx +3 -3
  126. package/templates/default/apps/web/src/components/shared/header.tsx +17 -112
  127. package/templates/default/apps/web/tsconfig.json +0 -6
  128. package/templates/default/biome.json +1 -2
  129. package/templates/default/components.json +2 -2
  130. package/templates/default/docker-compose.yml +1 -1
  131. package/templates/default/gitignore +4 -0
  132. package/templates/default/package.json +1 -0
  133. package/templates/default/packages/admin-ui/catalog/catalog.css +54 -0
  134. package/templates/default/packages/admin-ui/catalog/catalog.tsx +401 -0
  135. package/templates/default/packages/admin-ui/catalog/index.html +12 -0
  136. package/templates/default/packages/admin-ui/catalog/main.tsx +9 -0
  137. package/templates/default/packages/admin-ui/components.json +21 -0
  138. package/templates/default/packages/admin-ui/package.json +105 -0
  139. package/templates/default/packages/admin-ui/src/command-menu/index.tsx +174 -0
  140. package/templates/default/packages/admin-ui/src/data-table/bulk-actions.tsx +215 -0
  141. package/templates/default/packages/admin-ui/src/data-table/column-header.tsx +73 -0
  142. package/templates/default/packages/admin-ui/src/data-table/data-table.tsx +127 -0
  143. package/templates/default/packages/admin-ui/src/data-table/faceted-filter.tsx +148 -0
  144. package/templates/default/packages/admin-ui/src/data-table/index.tsx +9 -0
  145. package/templates/default/packages/admin-ui/src/data-table/pagination.tsx +101 -0
  146. package/templates/default/packages/admin-ui/src/data-table/toolbar.tsx +87 -0
  147. package/templates/default/packages/admin-ui/src/data-table/view-options.tsx +57 -0
  148. package/templates/default/packages/admin-ui/src/hooks/use-mobile.tsx +23 -0
  149. package/templates/default/packages/admin-ui/src/layout/header.tsx +55 -0
  150. package/templates/default/packages/admin-ui/src/layout/index.ts +10 -0
  151. package/templates/default/packages/admin-ui/src/layout/main.tsx +23 -0
  152. package/templates/default/packages/admin-ui/src/layout/nav-group.tsx +111 -0
  153. package/templates/default/packages/admin-ui/src/layout/nav-user.tsx +114 -0
  154. package/templates/default/packages/admin-ui/src/layout/theme-switch.tsx +40 -0
  155. package/templates/default/packages/admin-ui/src/layout/types.ts +21 -0
  156. package/templates/default/packages/admin-ui/src/lib/utils.ts +6 -0
  157. package/templates/default/packages/admin-ui/src/styles/base.css +65 -0
  158. package/templates/default/packages/admin-ui/src/styles/tokens.css +91 -0
  159. package/templates/default/packages/admin-ui/src/tanstack-table.d.ts +10 -0
  160. package/templates/default/packages/admin-ui/src/ui/alert-dialog.tsx +157 -0
  161. package/templates/default/packages/admin-ui/src/ui/alert.tsx +66 -0
  162. package/templates/default/packages/admin-ui/src/ui/avatar.tsx +53 -0
  163. package/templates/default/packages/admin-ui/src/ui/badge.tsx +46 -0
  164. package/templates/default/packages/admin-ui/src/ui/breadcrumb.tsx +108 -0
  165. package/templates/default/packages/admin-ui/src/ui/button.tsx +59 -0
  166. package/templates/default/packages/admin-ui/src/ui/calendar.tsx +69 -0
  167. package/templates/default/packages/admin-ui/src/ui/card.tsx +92 -0
  168. package/templates/default/packages/admin-ui/src/ui/chart.tsx +345 -0
  169. package/templates/default/packages/admin-ui/src/ui/checkbox.tsx +32 -0
  170. package/templates/default/packages/admin-ui/src/ui/collapsible.tsx +27 -0
  171. package/templates/default/packages/admin-ui/src/ui/command.tsx +161 -0
  172. package/templates/default/packages/admin-ui/src/ui/confirm-dialog.tsx +72 -0
  173. package/templates/default/packages/admin-ui/src/ui/date-picker.tsx +53 -0
  174. package/templates/default/packages/admin-ui/src/ui/dialog.tsx +143 -0
  175. package/templates/default/packages/admin-ui/src/ui/dropdown-menu.tsx +257 -0
  176. package/templates/default/packages/admin-ui/src/ui/form.tsx +168 -0
  177. package/templates/default/packages/admin-ui/src/ui/input-otp.tsx +84 -0
  178. package/templates/default/packages/admin-ui/src/ui/input.tsx +21 -0
  179. package/templates/default/packages/admin-ui/src/ui/label.tsx +24 -0
  180. package/templates/default/packages/admin-ui/src/ui/pagination.tsx +126 -0
  181. package/templates/default/packages/admin-ui/src/ui/password-input.tsx +46 -0
  182. package/templates/default/packages/admin-ui/src/ui/popover.tsx +48 -0
  183. package/templates/default/packages/admin-ui/src/ui/progress.tsx +31 -0
  184. package/templates/default/packages/admin-ui/src/ui/radio-group.tsx +45 -0
  185. package/templates/default/packages/admin-ui/src/ui/scroll-area.tsx +52 -0
  186. package/templates/default/packages/admin-ui/src/ui/select.tsx +185 -0
  187. package/templates/default/packages/admin-ui/src/ui/separator.tsx +28 -0
  188. package/templates/default/packages/admin-ui/src/ui/sheet.tsx +149 -0
  189. package/templates/default/packages/admin-ui/src/ui/sidebar.tsx +728 -0
  190. package/templates/default/packages/admin-ui/src/ui/skeleton.tsx +13 -0
  191. package/templates/default/packages/admin-ui/src/ui/sonner.tsx +25 -0
  192. package/templates/default/packages/admin-ui/src/ui/switch.tsx +31 -0
  193. package/templates/default/packages/admin-ui/src/ui/table.tsx +116 -0
  194. package/templates/default/packages/admin-ui/src/ui/tabs.tsx +66 -0
  195. package/templates/default/packages/admin-ui/src/ui/textarea.tsx +18 -0
  196. package/templates/default/packages/admin-ui/src/ui/toggle-group.tsx +60 -0
  197. package/templates/default/packages/admin-ui/src/ui/toggle.tsx +44 -0
  198. package/templates/default/packages/admin-ui/src/ui/tooltip.tsx +61 -0
  199. package/templates/default/packages/admin-ui/tsconfig.json +8 -0
  200. package/templates/default/packages/admin-ui/vite.config.ts +11 -0
  201. package/templates/default/packages/config/package.json +0 -2
  202. package/templates/default/packages/server-core/package.json +1 -0
  203. package/templates/default/packages/ui/components.json +21 -0
  204. package/templates/default/packages/ui/package.json +42 -5
  205. package/templates/default/packages/ui/src/accordion.tsx +1 -1
  206. package/templates/default/packages/ui/src/alert-dialog.tsx +4 -4
  207. package/templates/default/packages/ui/src/alert.tsx +1 -1
  208. package/templates/default/packages/ui/src/avatar.tsx +1 -1
  209. package/templates/default/packages/ui/src/badge.tsx +1 -1
  210. package/templates/default/packages/ui/src/breadcrumb.tsx +1 -1
  211. package/templates/default/packages/ui/src/button.tsx +1 -1
  212. package/templates/default/packages/ui/src/card.tsx +1 -1
  213. package/templates/default/packages/ui/src/checkbox.tsx +1 -1
  214. package/templates/default/packages/ui/src/dialog.tsx +3 -3
  215. package/templates/default/packages/ui/src/drawer.tsx +3 -3
  216. package/templates/default/packages/ui/src/dropdown-menu.tsx +3 -3
  217. package/templates/default/packages/ui/src/form.tsx +2 -2
  218. package/templates/default/packages/ui/src/hover-card.tsx +2 -2
  219. package/templates/default/packages/ui/src/input.tsx +1 -1
  220. package/templates/default/packages/ui/src/label.tsx +1 -1
  221. package/templates/default/packages/ui/src/pagination.tsx +2 -2
  222. package/templates/default/packages/ui/src/popover.tsx +2 -2
  223. package/templates/default/packages/ui/src/progress.tsx +1 -1
  224. package/templates/default/packages/ui/src/select.tsx +2 -2
  225. package/templates/default/packages/ui/src/separator.tsx +1 -1
  226. package/templates/default/packages/ui/src/skeleton.tsx +1 -1
  227. package/templates/default/packages/ui/src/table.tsx +1 -1
  228. package/templates/default/packages/ui/src/tabs.tsx +1 -1
  229. package/templates/default/packages/ui/src/textarea.tsx +1 -1
  230. package/templates/default/packages/ui/src/tooltip.tsx +3 -3
  231. package/templates/default/packages/ui/src/typography.tsx +1 -1
  232. package/templates/default/packages/ui/tsconfig.json +1 -6
  233. package/templates/default/pnpm-lock.yaml +1319 -936
  234. package/templates/default/postcss.config.cjs +0 -1
  235. package/templates/default/turbo.json +11 -5
  236. package/templates/default/worktree.config.json +5 -0
  237. package/templates/default/.env.ci +0 -32
  238. package/templates/default/.github/workflows/ci.yml +0 -96
  239. package/templates/default/.github/workflows/preview-db.yml +0 -134
  240. package/templates/default/.playwright-mcp/dashboard.png +0 -0
  241. package/templates/default/.playwright-mcp/web-home.png +0 -0
  242. package/templates/default/apps/web/panda.config.ts +0 -114
  243. package/templates/default/apps/web/src/components/ui/accordion.tsx +0 -64
  244. package/templates/default/apps/web/src/components/ui/alert-dialog.tsx +0 -135
  245. package/templates/default/apps/web/src/components/ui/alert.tsx +0 -60
  246. package/templates/default/apps/web/src/components/ui/aspect-ratio.tsx +0 -9
  247. package/templates/default/apps/web/src/components/ui/avatar.tsx +0 -41
  248. package/templates/default/apps/web/src/components/ui/badge.tsx +0 -39
  249. package/templates/default/apps/web/src/components/ui/breadcrumb.tsx +0 -101
  250. package/templates/default/apps/web/src/components/ui/button.tsx +0 -56
  251. package/templates/default/apps/web/src/components/ui/card.tsx +0 -75
  252. package/templates/default/apps/web/src/components/ui/checkbox.tsx +0 -29
  253. package/templates/default/apps/web/src/components/ui/data-table.tsx +0 -189
  254. package/templates/default/apps/web/src/components/ui/dialog-hook.tsx +0 -210
  255. package/templates/default/apps/web/src/components/ui/dialog.tsx +0 -129
  256. package/templates/default/apps/web/src/components/ui/drawer.tsx +0 -124
  257. package/templates/default/apps/web/src/components/ui/dropdown-menu.tsx +0 -228
  258. package/templates/default/apps/web/src/components/ui/form.tsx +0 -152
  259. package/templates/default/apps/web/src/components/ui/hover-card.tsx +0 -38
  260. package/templates/default/apps/web/src/components/ui/input.tsx +0 -21
  261. package/templates/default/apps/web/src/components/ui/label.tsx +0 -21
  262. package/templates/default/apps/web/src/components/ui/pagination.tsx +0 -105
  263. package/templates/default/apps/web/src/components/ui/popover.tsx +0 -42
  264. package/templates/default/apps/web/src/components/ui/progress.tsx +0 -28
  265. package/templates/default/apps/web/src/components/ui/select.tsx +0 -170
  266. package/templates/default/apps/web/src/components/ui/separator.tsx +0 -28
  267. package/templates/default/apps/web/src/components/ui/skeleton.tsx +0 -13
  268. package/templates/default/apps/web/src/components/ui/sonner.tsx +0 -25
  269. package/templates/default/apps/web/src/components/ui/table.tsx +0 -92
  270. package/templates/default/apps/web/src/components/ui/tabs.tsx +0 -54
  271. package/templates/default/apps/web/src/components/ui/textarea.tsx +0 -18
  272. package/templates/default/apps/web/src/components/ui/tooltip.tsx +0 -57
  273. package/templates/default/apps/web/src/components/ui/typography.tsx +0 -158
  274. package/templates/default/packages/config/panda.config.ts +0 -114
  275. package/templates/default/panda.config.ts +0 -114
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@repo/admin",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "rm -rf .next && next dev --turbopack --port ${PORT_ADMIN:-4000}",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "biome check .",
10
+ "lint:fix": "biome check --write",
11
+ "format": "biome format .",
12
+ "format:fix": "biome format --write .",
13
+ "typecheck": "tsc --noEmit",
14
+ "test": "vitest run --passWithNoTests",
15
+ "test:watch": "vitest",
16
+ "test:ui": "vitest --ui",
17
+ "test:coverage": "vitest run --coverage"
18
+ },
19
+ "dependencies": {
20
+ "@hookform/resolvers": "^5.1.1",
21
+ "@radix-ui/react-icons": "^1.3.2",
22
+ "@repo/admin-ui": "workspace:*",
23
+ "@repo/front-core": "workspace:*",
24
+ "@repo/server-core": "workspace:*",
25
+ "@tailwindcss/postcss": "^4.1.10",
26
+ "@tanstack/react-query": "^5.81.5",
27
+ "@tanstack/react-table": "^8.21.3",
28
+ "clsx": "^2.1.1",
29
+ "date-fns": "^4.1.0",
30
+ "lucide-react": "^0.523.0",
31
+ "next": "15.3.3",
32
+ "next-auth": "^5.0.0-beta.28",
33
+ "next-themes": "^0.4.6",
34
+ "postcss": "^8.5.6",
35
+ "react": "^19.0.0",
36
+ "react-dom": "^19.0.0",
37
+ "react-hook-form": "^7.59.0",
38
+ "recharts": "^2.15.4",
39
+ "sonner": "^2.0.7",
40
+ "tailwind-merge": "^3.3.1",
41
+ "tailwindcss": "^4.1.10",
42
+ "zod": "^3.25.67"
43
+ },
44
+ "devDependencies": {
45
+ "@biomejs/biome": "1.9.4",
46
+ "@faker-js/faker": "^9.0.0",
47
+ "@repo/config": "workspace:*",
48
+ "@types/node": "^22",
49
+ "@types/react": "^19",
50
+ "@types/react-dom": "^19",
51
+ "tw-animate-css": "^1.3.4",
52
+ "typescript": "^5",
53
+ "vitest": "^3.2.2"
54
+ }
55
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
@@ -0,0 +1,97 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import { cn } from "{{packageName}}/admin-ui/lib/utils";
5
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
6
+ import {
7
+ Card,
8
+ CardContent,
9
+ CardDescription,
10
+ CardFooter,
11
+ CardHeader,
12
+ CardTitle,
13
+ } from "{{packageName}}/admin-ui/ui/card";
14
+ import {
15
+ Form,
16
+ FormControl,
17
+ FormField,
18
+ FormItem,
19
+ FormLabel,
20
+ FormMessage,
21
+ } from "{{packageName}}/admin-ui/ui/form";
22
+ import { Input } from "{{packageName}}/admin-ui/ui/input";
23
+ import { ArrowRight, Loader2 } from "lucide-react";
24
+ import Link from "next/link";
25
+ import { useRouter } from "next/navigation";
26
+ import { useState } from "react";
27
+ import { useForm } from "react-hook-form";
28
+ import { z } from "zod";
29
+
30
+ const formSchema = z.object({
31
+ email: z.string().email("Invalid email address").min(1, "Please enter your email"),
32
+ });
33
+
34
+ export default function ForgotPasswordPage() {
35
+ const router = useRouter();
36
+ const [isLoading, setIsLoading] = useState(false);
37
+
38
+ const form = useForm<z.infer<typeof formSchema>>({
39
+ resolver: zodResolver(formSchema),
40
+ defaultValues: { email: "" },
41
+ });
42
+
43
+ function onSubmit(data: z.infer<typeof formSchema>) {
44
+ setIsLoading(true);
45
+ console.log("Forgot Password Data:", data);
46
+
47
+ setTimeout(() => {
48
+ setIsLoading(false);
49
+ form.reset();
50
+ alert(`Email sent to ${data.email}`);
51
+ router.push("/otp");
52
+ }, 2000);
53
+ }
54
+
55
+ return (
56
+ <Card className="gap-4">
57
+ <CardHeader>
58
+ <CardTitle className="text-lg tracking-tight">Forgot Password</CardTitle>
59
+ <CardDescription>
60
+ Enter your registered email and <br /> we will send you a link to reset your password.
61
+ </CardDescription>
62
+ </CardHeader>
63
+ <CardContent>
64
+ <Form {...form}>
65
+ <form onSubmit={form.handleSubmit(onSubmit)} className={cn("grid gap-2")}>
66
+ <FormField
67
+ control={form.control}
68
+ name="email"
69
+ render={({ field }) => (
70
+ <FormItem>
71
+ <FormLabel>Email</FormLabel>
72
+ <FormControl>
73
+ <Input placeholder="name@example.com" {...field} />
74
+ </FormControl>
75
+ <FormMessage />
76
+ </FormItem>
77
+ )}
78
+ />
79
+ <Button className="mt-2" disabled={isLoading}>
80
+ Continue
81
+ {isLoading ? <Loader2 className="animate-spin" /> : <ArrowRight />}
82
+ </Button>
83
+ </form>
84
+ </Form>
85
+ </CardContent>
86
+ <CardFooter>
87
+ <p className="mx-auto px-8 text-center text-sm text-balance text-muted-foreground">
88
+ Don&apos;t have an account?{" "}
89
+ <Link href="/sign-up" className="underline underline-offset-4 hover:text-primary">
90
+ Sign up
91
+ </Link>
92
+ .
93
+ </p>
94
+ </CardFooter>
95
+ </Card>
96
+ );
97
+ }
@@ -0,0 +1,18 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ interface AuthLayoutProps {
4
+ children: ReactNode;
5
+ }
6
+
7
+ export default function AuthLayout({ children }: AuthLayoutProps) {
8
+ return (
9
+ <div className="container grid h-svh max-w-none items-center justify-center">
10
+ <div className="mx-auto flex w-full flex-col justify-center space-y-2 py-8 sm:w-[480px] sm:p-8">
11
+ <div className="mb-4 flex items-center justify-center">
12
+ <h1 className="text-xl font-medium">Admin Portal</h1>
13
+ </div>
14
+ {children}
15
+ </div>
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,121 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import { cn } from "{{packageName}}/admin-ui/lib/utils";
5
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
6
+ import {
7
+ Card,
8
+ CardContent,
9
+ CardDescription,
10
+ CardFooter,
11
+ CardHeader,
12
+ CardTitle,
13
+ } from "{{packageName}}/admin-ui/ui/card";
14
+ import {
15
+ Form,
16
+ FormControl,
17
+ FormField,
18
+ FormItem,
19
+ FormLabel,
20
+ FormMessage,
21
+ } from "{{packageName}}/admin-ui/ui/form";
22
+ import {
23
+ InputOTP,
24
+ InputOTPGroup,
25
+ InputOTPSeparator,
26
+ InputOTPSlot,
27
+ } from "{{packageName}}/admin-ui/ui/input-otp";
28
+ import Link from "next/link";
29
+ import { useRouter } from "next/navigation";
30
+ import { useState } from "react";
31
+ import { useForm } from "react-hook-form";
32
+ import { z } from "zod";
33
+
34
+ const formSchema = z.object({
35
+ otp: z.string().min(6, "Please enter the 6-digit code").max(6, "Please enter the 6-digit code"),
36
+ });
37
+
38
+ export default function OtpPage() {
39
+ const router = useRouter();
40
+ const [isLoading, setIsLoading] = useState(false);
41
+
42
+ const form = useForm<z.infer<typeof formSchema>>({
43
+ resolver: zodResolver(formSchema),
44
+ defaultValues: { otp: "" },
45
+ });
46
+
47
+ const otp = form.watch("otp");
48
+
49
+ function onSubmit(data: z.infer<typeof formSchema>) {
50
+ setIsLoading(true);
51
+ console.log("OTP Data:", data);
52
+
53
+ setTimeout(() => {
54
+ setIsLoading(false);
55
+ alert(`OTP verified: ${data.otp}`);
56
+ router.push("/");
57
+ }, 1000);
58
+ }
59
+
60
+ return (
61
+ <Card className="gap-4">
62
+ <CardHeader>
63
+ <CardTitle className="text-base tracking-tight">Two-factor Authentication</CardTitle>
64
+ <CardDescription>
65
+ Please enter the authentication code. <br /> We have sent the authentication code to your
66
+ email.
67
+ </CardDescription>
68
+ </CardHeader>
69
+ <CardContent>
70
+ <Form {...form}>
71
+ <form onSubmit={form.handleSubmit(onSubmit)} className={cn("grid gap-2")}>
72
+ <FormField
73
+ control={form.control}
74
+ name="otp"
75
+ render={({ field }) => (
76
+ <FormItem>
77
+ <FormLabel className="sr-only">One-Time Password</FormLabel>
78
+ <FormControl>
79
+ <InputOTP
80
+ maxLength={6}
81
+ {...field}
82
+ containerClassName="justify-between sm:[&>[data-slot='input-otp-group']>div]:w-12"
83
+ >
84
+ <InputOTPGroup>
85
+ <InputOTPSlot index={0} />
86
+ <InputOTPSlot index={1} />
87
+ </InputOTPGroup>
88
+ <InputOTPSeparator />
89
+ <InputOTPGroup>
90
+ <InputOTPSlot index={2} />
91
+ <InputOTPSlot index={3} />
92
+ </InputOTPGroup>
93
+ <InputOTPSeparator />
94
+ <InputOTPGroup>
95
+ <InputOTPSlot index={4} />
96
+ <InputOTPSlot index={5} />
97
+ </InputOTPGroup>
98
+ </InputOTP>
99
+ </FormControl>
100
+ <FormMessage />
101
+ </FormItem>
102
+ )}
103
+ />
104
+ <Button className="mt-2" disabled={otp.length < 6 || isLoading}>
105
+ Verify
106
+ </Button>
107
+ </form>
108
+ </Form>
109
+ </CardContent>
110
+ <CardFooter>
111
+ <p className="px-8 text-center text-sm text-muted-foreground">
112
+ Haven&apos;t received it?{" "}
113
+ <Link href="/sign-in" className="underline underline-offset-4 hover:text-primary">
114
+ Resend a new code
115
+ </Link>
116
+ .
117
+ </p>
118
+ </CardFooter>
119
+ </Card>
120
+ );
121
+ }
@@ -0,0 +1,145 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import { cn } from "{{packageName}}/admin-ui/lib/utils";
5
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
6
+ import {
7
+ Card,
8
+ CardContent,
9
+ CardDescription,
10
+ CardFooter,
11
+ CardHeader,
12
+ CardTitle,
13
+ } from "{{packageName}}/admin-ui/ui/card";
14
+ import {
15
+ Form,
16
+ FormControl,
17
+ FormField,
18
+ FormItem,
19
+ FormLabel,
20
+ FormMessage,
21
+ } from "{{packageName}}/admin-ui/ui/form";
22
+ import { Input } from "{{packageName}}/admin-ui/ui/input";
23
+ import { PasswordInput } from "{{packageName}}/admin-ui/ui/password-input";
24
+ import { Separator } from "{{packageName}}/admin-ui/ui/separator";
25
+ import { Loader2, LogIn } from "lucide-react";
26
+ import Link from "next/link";
27
+ import { useState } from "react";
28
+ import { useForm } from "react-hook-form";
29
+ import { z } from "zod";
30
+
31
+ const formSchema = z.object({
32
+ email: z.string().email("Invalid email address").min(1, "Please enter your email"),
33
+ password: z
34
+ .string()
35
+ .min(1, "Please enter your password")
36
+ .min(7, "Password must be at least 7 characters long"),
37
+ });
38
+
39
+ export default function SignInPage() {
40
+ const [isLoading, setIsLoading] = useState(false);
41
+
42
+ const form = useForm<z.infer<typeof formSchema>>({
43
+ resolver: zodResolver(formSchema),
44
+ defaultValues: {
45
+ email: "",
46
+ password: "",
47
+ },
48
+ });
49
+
50
+ function onSubmit(data: z.infer<typeof formSchema>) {
51
+ setIsLoading(true);
52
+ console.log("Sign In Data:", data);
53
+
54
+ // Simulate async operation
55
+ setTimeout(() => {
56
+ setIsLoading(false);
57
+ alert(`Welcome back, ${data.email}!`);
58
+ }, 2000);
59
+ }
60
+
61
+ return (
62
+ <Card className="gap-4">
63
+ <CardHeader>
64
+ <CardTitle className="text-lg tracking-tight">Sign in</CardTitle>
65
+ <CardDescription>
66
+ Enter your email and password below to <br />
67
+ log into your account
68
+ </CardDescription>
69
+ </CardHeader>
70
+ <CardContent>
71
+ <Form {...form}>
72
+ <form onSubmit={form.handleSubmit(onSubmit)} className={cn("grid gap-3")}>
73
+ <FormField
74
+ control={form.control}
75
+ name="email"
76
+ render={({ field }) => (
77
+ <FormItem>
78
+ <FormLabel>Email</FormLabel>
79
+ <FormControl>
80
+ <Input placeholder="name@example.com" {...field} />
81
+ </FormControl>
82
+ <FormMessage />
83
+ </FormItem>
84
+ )}
85
+ />
86
+ <FormField
87
+ control={form.control}
88
+ name="password"
89
+ render={({ field }) => (
90
+ <FormItem className="relative">
91
+ <FormLabel>Password</FormLabel>
92
+ <FormControl>
93
+ <PasswordInput placeholder="********" {...field} />
94
+ </FormControl>
95
+ <FormMessage />
96
+ <Link
97
+ href="/forgot-password"
98
+ className="absolute end-0 -top-0.5 text-sm font-medium text-muted-foreground hover:opacity-75"
99
+ >
100
+ Forgot password?
101
+ </Link>
102
+ </FormItem>
103
+ )}
104
+ />
105
+ <Button className="mt-2" disabled={isLoading}>
106
+ {isLoading ? <Loader2 className="animate-spin" /> : <LogIn />}
107
+ Sign in
108
+ </Button>
109
+
110
+ <div className="relative my-2">
111
+ <div className="absolute inset-0 flex items-center">
112
+ <Separator />
113
+ </div>
114
+ <div className="relative flex justify-center text-xs uppercase">
115
+ <span className="bg-background px-2 text-muted-foreground">Or continue with</span>
116
+ </div>
117
+ </div>
118
+
119
+ <div className="grid grid-cols-2 gap-2">
120
+ <Button variant="outline" type="button" disabled={isLoading}>
121
+ GitHub
122
+ </Button>
123
+ <Button variant="outline" type="button" disabled={isLoading}>
124
+ Google
125
+ </Button>
126
+ </div>
127
+ </form>
128
+ </Form>
129
+ </CardContent>
130
+ <CardFooter>
131
+ <p className="px-8 text-center text-sm text-muted-foreground">
132
+ By clicking sign in, you agree to our{" "}
133
+ <a href="/terms" className="underline underline-offset-4 hover:text-primary">
134
+ Terms of Service
135
+ </a>{" "}
136
+ and{" "}
137
+ <a href="/privacy" className="underline underline-offset-4 hover:text-primary">
138
+ Privacy Policy
139
+ </a>
140
+ .
141
+ </p>
142
+ </CardFooter>
143
+ </Card>
144
+ );
145
+ }
@@ -0,0 +1,199 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import { cn } from "{{packageName}}/admin-ui/lib/utils";
5
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
6
+ import {
7
+ Card,
8
+ CardContent,
9
+ CardDescription,
10
+ CardFooter,
11
+ CardHeader,
12
+ CardTitle,
13
+ } from "{{packageName}}/admin-ui/ui/card";
14
+ import { Checkbox } from "{{packageName}}/admin-ui/ui/checkbox";
15
+ import {
16
+ Form,
17
+ FormControl,
18
+ FormField,
19
+ FormItem,
20
+ FormLabel,
21
+ FormMessage,
22
+ } from "{{packageName}}/admin-ui/ui/form";
23
+ import { Input } from "{{packageName}}/admin-ui/ui/input";
24
+ import { PasswordInput } from "{{packageName}}/admin-ui/ui/password-input";
25
+ import { Separator } from "{{packageName}}/admin-ui/ui/separator";
26
+ import Link from "next/link";
27
+ import { useState } from "react";
28
+ import { useForm } from "react-hook-form";
29
+ import { z } from "zod";
30
+
31
+ const formSchema = z
32
+ .object({
33
+ name: z.string().min(1, "Please enter your name"),
34
+ email: z.string().email("Invalid email address").min(1, "Please enter your email"),
35
+ password: z
36
+ .string()
37
+ .min(1, "Please enter your password")
38
+ .min(7, "Password must be at least 7 characters long"),
39
+ confirmPassword: z.string().min(1, "Please confirm your password"),
40
+ terms: z.boolean().refine((val) => val === true, {
41
+ message: "You must accept the terms and conditions",
42
+ }),
43
+ })
44
+ .refine((data) => data.password === data.confirmPassword, {
45
+ message: "Passwords don't match",
46
+ path: ["confirmPassword"],
47
+ });
48
+
49
+ export default function SignUpPage() {
50
+ const [isLoading, setIsLoading] = useState(false);
51
+
52
+ const form = useForm<z.infer<typeof formSchema>>({
53
+ resolver: zodResolver(formSchema),
54
+ defaultValues: {
55
+ name: "",
56
+ email: "",
57
+ password: "",
58
+ confirmPassword: "",
59
+ terms: false,
60
+ },
61
+ });
62
+
63
+ function onSubmit(data: z.infer<typeof formSchema>) {
64
+ setIsLoading(true);
65
+ console.log("Sign Up Data:", data);
66
+
67
+ setTimeout(() => {
68
+ setIsLoading(false);
69
+ alert(`Account created for ${data.email}!`);
70
+ }, 2000);
71
+ }
72
+
73
+ return (
74
+ <Card className="gap-4">
75
+ <CardHeader>
76
+ <CardTitle className="text-lg tracking-tight">Create an account</CardTitle>
77
+ <CardDescription>
78
+ Enter your email and password to create an account. <br />
79
+ Already have an account?{" "}
80
+ <Link href="/sign-in" className="underline underline-offset-4 hover:text-primary">
81
+ Sign In
82
+ </Link>
83
+ </CardDescription>
84
+ </CardHeader>
85
+ <CardContent>
86
+ <Form {...form}>
87
+ <form onSubmit={form.handleSubmit(onSubmit)} className={cn("grid gap-3")}>
88
+ <FormField
89
+ control={form.control}
90
+ name="name"
91
+ render={({ field }) => (
92
+ <FormItem>
93
+ <FormLabel>Name</FormLabel>
94
+ <FormControl>
95
+ <Input placeholder="John Doe" {...field} />
96
+ </FormControl>
97
+ <FormMessage />
98
+ </FormItem>
99
+ )}
100
+ />
101
+ <FormField
102
+ control={form.control}
103
+ name="email"
104
+ render={({ field }) => (
105
+ <FormItem>
106
+ <FormLabel>Email</FormLabel>
107
+ <FormControl>
108
+ <Input placeholder="name@example.com" {...field} />
109
+ </FormControl>
110
+ <FormMessage />
111
+ </FormItem>
112
+ )}
113
+ />
114
+ <FormField
115
+ control={form.control}
116
+ name="password"
117
+ render={({ field }) => (
118
+ <FormItem>
119
+ <FormLabel>Password</FormLabel>
120
+ <FormControl>
121
+ <PasswordInput placeholder="********" {...field} />
122
+ </FormControl>
123
+ <FormMessage />
124
+ </FormItem>
125
+ )}
126
+ />
127
+ <FormField
128
+ control={form.control}
129
+ name="confirmPassword"
130
+ render={({ field }) => (
131
+ <FormItem>
132
+ <FormLabel>Confirm Password</FormLabel>
133
+ <FormControl>
134
+ <PasswordInput placeholder="********" {...field} />
135
+ </FormControl>
136
+ <FormMessage />
137
+ </FormItem>
138
+ )}
139
+ />
140
+ <FormField
141
+ control={form.control}
142
+ name="terms"
143
+ render={({ field }) => (
144
+ <FormItem className="flex flex-row items-start space-x-3 space-y-0">
145
+ <FormControl>
146
+ <Checkbox checked={field.value} onCheckedChange={field.onChange} />
147
+ </FormControl>
148
+ <div className="space-y-1 leading-none">
149
+ <FormLabel>
150
+ I agree to the{" "}
151
+ <a href="/terms" className="underline underline-offset-4 hover:text-primary">
152
+ Terms and Conditions
153
+ </a>
154
+ </FormLabel>
155
+ <FormMessage />
156
+ </div>
157
+ </FormItem>
158
+ )}
159
+ />
160
+ <Button className="mt-2" disabled={isLoading}>
161
+ Create Account
162
+ </Button>
163
+
164
+ <div className="relative my-2">
165
+ <div className="absolute inset-0 flex items-center">
166
+ <Separator />
167
+ </div>
168
+ <div className="relative flex justify-center text-xs uppercase">
169
+ <span className="bg-background px-2 text-muted-foreground">Or continue with</span>
170
+ </div>
171
+ </div>
172
+
173
+ <div className="grid grid-cols-2 gap-2">
174
+ <Button variant="outline" className="w-full" type="button" disabled={isLoading}>
175
+ GitHub
176
+ </Button>
177
+ <Button variant="outline" className="w-full" type="button" disabled={isLoading}>
178
+ Google
179
+ </Button>
180
+ </div>
181
+ </form>
182
+ </Form>
183
+ </CardContent>
184
+ <CardFooter>
185
+ <p className="px-8 text-center text-sm text-muted-foreground">
186
+ By creating an account, you agree to our{" "}
187
+ <a href="/terms" className="underline underline-offset-4 hover:text-primary">
188
+ Terms of Service
189
+ </a>{" "}
190
+ and{" "}
191
+ <a href="/privacy" className="underline underline-offset-4 hover:text-primary">
192
+ Privacy Policy
193
+ </a>
194
+ .
195
+ </p>
196
+ </CardFooter>
197
+ </Card>
198
+ );
199
+ }
@@ -0,0 +1,27 @@
1
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
2
+ import type { Metadata } from "next";
3
+ import Link from "next/link";
4
+
5
+ export const metadata: Metadata = {
6
+ title: "401 - Unauthorized",
7
+ description: "Unauthorized Access",
8
+ };
9
+
10
+ export default function UnauthorizedPage() {
11
+ return (
12
+ <div className="h-svh">
13
+ <div className="m-auto flex h-full w-full flex-col items-center justify-center gap-2">
14
+ <h1 className="text-[7rem] font-bold leading-tight">401</h1>
15
+ <span className="font-medium">Unauthorized Access</span>
16
+ <p className="text-center text-muted-foreground">
17
+ Please log in with the appropriate credentials <br /> to access this resource.
18
+ </p>
19
+ <div className="mt-6 flex gap-4">
20
+ <Button variant="outline" asChild>
21
+ <Link href="/dashboard">Back to Home</Link>
22
+ </Button>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ );
27
+ }