create-ej-app 3.2.0 → 5.0.0

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 (316) hide show
  1. package/LICENSE +1 -1
  2. package/cli.js +5 -1
  3. package/cli.ts +40 -33
  4. package/package.json +4 -4
  5. package/template/base/.env.example +10 -9
  6. package/template/base/.eslintrc.cjs +17 -15
  7. package/template/base/components.json +1 -1
  8. package/template/base/drizzle.config.ts +11 -0
  9. package/template/base/next.config.mjs +1 -12
  10. package/template/base/package.json +63 -56
  11. package/template/base/postcss.config.mjs +8 -0
  12. package/template/base/prettier.config.mjs +11 -0
  13. package/template/base/public/vercel.svg +1 -0
  14. package/template/base/src/app/(app)/dashboard/layout.tsx +14 -0
  15. package/template/base/src/app/(app)/dashboard/page.tsx +0 -7
  16. package/template/base/src/app/(app)/layout.tsx +55 -20
  17. package/template/base/src/app/(app)/roles/[id]/actions.ts +59 -0
  18. package/template/base/src/app/(app)/roles/[id]/page.tsx +46 -0
  19. package/template/base/src/app/(app)/roles/[id]/render.tsx +264 -0
  20. package/template/base/src/app/(app)/roles/[id]/validation.ts +22 -0
  21. package/template/base/src/app/(app)/roles/actions.ts +33 -0
  22. package/template/base/src/app/(app)/roles/page.tsx +52 -0
  23. package/template/base/src/app/(app)/roles/render.tsx +80 -0
  24. package/template/base/src/app/(app)/settings/actions.ts +11 -12
  25. package/template/base/src/app/(app)/settings/layout.tsx +14 -0
  26. package/template/base/src/app/(app)/settings/page.tsx +1 -10
  27. package/template/base/src/app/(app)/settings/render.tsx +11 -17
  28. package/template/base/src/app/(app)/settings/validation.ts +5 -0
  29. package/template/base/src/app/(app)/tasks/[id]/actions.ts +69 -124
  30. package/template/base/src/app/(app)/tasks/[id]/page.tsx +37 -3
  31. package/template/base/src/app/(app)/tasks/[id]/render.tsx +162 -93
  32. package/template/base/src/app/(app)/tasks/[id]/validation.ts +18 -0
  33. package/template/base/src/app/(app)/tasks/actions.ts +34 -64
  34. package/template/base/src/app/(app)/tasks/page.tsx +15 -9
  35. package/template/base/src/app/(app)/tasks/render.tsx +28 -6
  36. package/template/base/src/app/(app)/tasks/statusEnum.ts +3 -0
  37. package/template/base/src/app/(app)/users/[id]/actions.ts +47 -62
  38. package/template/base/src/app/(app)/users/[id]/page.tsx +15 -8
  39. package/template/base/src/app/(app)/users/[id]/render.tsx +119 -34
  40. package/template/base/src/app/(app)/users/[id]/validation.ts +18 -0
  41. package/template/base/src/app/(app)/users/actions.ts +28 -49
  42. package/template/base/src/app/(app)/users/page.tsx +22 -9
  43. package/template/base/src/app/(app)/users/render.tsx +47 -3
  44. package/template/base/src/app/(auth)/layout.tsx +7 -0
  45. package/template/base/src/app/(auth)/login/page.tsx +2 -2
  46. package/template/base/src/app/(auth)/login/render.tsx +146 -0
  47. package/template/base/src/app/(marketing)/layout.tsx +1 -1
  48. package/template/base/src/app/(marketing)/page.tsx +8 -7
  49. package/template/base/src/app/favicon.ico +0 -0
  50. package/template/base/src/app/layout.tsx +14 -17
  51. package/template/base/src/components/app-nav-command.tsx +18 -0
  52. package/template/base/src/components/data-table/data-table-column-header.tsx +2 -2
  53. package/template/base/src/components/icons.tsx +21 -5
  54. package/template/base/src/components/ui/alert-dialog.tsx +1 -1
  55. package/template/base/src/components/ui/command.tsx +1 -1
  56. package/template/base/src/components/ui/dialog.tsx +1 -1
  57. package/template/base/src/components/ui/sonner.tsx +31 -0
  58. package/template/base/src/components/user-avatar.tsx +4 -2
  59. package/template/base/src/data-access/resource.ts +85 -0
  60. package/template/base/src/data-access/role-permission.ts +45 -0
  61. package/template/base/src/data-access/role.ts +105 -0
  62. package/template/base/src/data-access/task.ts +141 -0
  63. package/template/base/src/data-access/user.ts +141 -0
  64. package/template/base/src/db/index.ts +14 -0
  65. package/template/base/src/db/schema.ts +287 -0
  66. package/template/base/src/env.mjs +10 -30
  67. package/template/base/src/hooks/use-lock-body.tsx +2 -1
  68. package/template/base/src/lib/auth.ts +32 -23
  69. package/template/base/src/lib/currentUser.ts +8 -0
  70. package/template/base/src/lib/s3Client.ts +156 -0
  71. package/template/base/src/lib/safe-action.ts +19 -0
  72. package/template/base/src/lib/sortOrderEnum.ts +2 -0
  73. package/template/base/src/use-case/role-permission.ts +19 -0
  74. package/template/base/src/use-case/role.ts +110 -0
  75. package/template/base/src/use-case/task.ts +166 -0
  76. package/template/base/src/use-case/user.ts +121 -0
  77. package/template/base/tailwind.config.ts +5 -4
  78. package/template/base/tsconfig.json +3 -2
  79. package/template/new/.env.example +13 -0
  80. package/template/new/components.json +22 -0
  81. package/template/new/drizzle.config.ts +10 -0
  82. package/template/new/eslint.config.mjs +18 -0
  83. package/template/new/next.config.ts +14 -0
  84. package/template/new/package.json +81 -0
  85. package/template/new/postcss.config.mjs +5 -0
  86. package/template/new/prettier.config.mjs +11 -0
  87. package/template/new/public/placeholder.svg +1 -0
  88. package/template/new/src/app/(auth)/login/email-login-form.tsx +97 -0
  89. package/template/new/src/app/(auth)/login/page.tsx +72 -0
  90. package/template/new/src/app/(auth)/login/social-login-buttons.tsx +69 -0
  91. package/template/new/src/app/api/auth/[...all]/route.ts +4 -0
  92. package/template/new/src/app/favicon.ico +0 -0
  93. package/template/new/src/app/globals.css +128 -0
  94. package/template/new/src/app/layout.tsx +50 -0
  95. package/template/new/src/app/page.tsx +3 -0
  96. package/template/new/src/components/loader.tsx +25 -0
  97. package/template/new/src/components/react-query-provider.tsx +12 -0
  98. package/template/new/src/components/screen-size.tsx +40 -0
  99. package/template/new/src/components/theme-toggle.tsx +22 -0
  100. package/template/new/src/components/ui/button.tsx +60 -0
  101. package/template/new/src/components/ui/card.tsx +92 -0
  102. package/template/new/src/components/ui/form.tsx +167 -0
  103. package/template/new/src/components/ui/input.tsx +21 -0
  104. package/template/new/src/components/ui/label.tsx +24 -0
  105. package/template/new/src/components/ui/separator.tsx +28 -0
  106. package/template/new/src/components/ui/sonner.tsx +40 -0
  107. package/template/new/src/db/index.ts +7 -0
  108. package/template/new/src/db/schema.ts +74 -0
  109. package/template/new/src/env.ts +42 -0
  110. package/template/new/src/lib/auth-client.ts +18 -0
  111. package/template/new/src/lib/auth.ts +67 -0
  112. package/template/new/src/lib/safe-action.ts +15 -0
  113. package/template/new/src/lib/toast-message.ts +15 -0
  114. package/template/new/tsconfig.json +49 -0
  115. package/template/prisma/.env.example +16 -0
  116. package/template/prisma/.eslintrc.cjs +24 -0
  117. package/template/prisma/components.json +17 -0
  118. package/template/prisma/next.config.mjs +15 -0
  119. package/template/prisma/package.json +80 -0
  120. package/template/prisma/public/next.svg +1 -0
  121. package/template/prisma/src/app/(app)/dashboard/page.tsx +19 -0
  122. package/template/prisma/src/app/(app)/layout.tsx +90 -0
  123. package/template/prisma/src/app/(app)/settings/actions.ts +18 -0
  124. package/template/prisma/src/app/(app)/settings/loading.tsx +28 -0
  125. package/template/prisma/src/app/(app)/settings/page.tsx +28 -0
  126. package/template/prisma/src/app/(app)/settings/render.tsx +113 -0
  127. package/template/prisma/src/app/(app)/tasks/[id]/actions.ts +147 -0
  128. package/template/prisma/src/app/(app)/tasks/[id]/page.tsx +25 -0
  129. package/template/prisma/src/app/(app)/tasks/[id]/render.tsx +413 -0
  130. package/template/prisma/src/app/(app)/tasks/actions.ts +69 -0
  131. package/template/prisma/src/app/(app)/tasks/page.tsx +53 -0
  132. package/template/prisma/src/app/(app)/tasks/render.tsx +107 -0
  133. package/template/prisma/src/app/(app)/users/[id]/actions.ts +83 -0
  134. package/template/prisma/src/app/(app)/users/[id]/page.tsx +32 -0
  135. package/template/prisma/src/app/(app)/users/[id]/render.tsx +240 -0
  136. package/template/prisma/src/app/(app)/users/actions.ts +55 -0
  137. package/template/prisma/src/app/(app)/users/page.tsx +49 -0
  138. package/template/prisma/src/app/(app)/users/render.tsx +80 -0
  139. package/template/prisma/src/app/(auth)/layout.tsx +20 -0
  140. package/template/prisma/src/app/(auth)/login/page.tsx +49 -0
  141. package/template/prisma/src/app/(marketing)/layout.tsx +42 -0
  142. package/template/prisma/src/app/(marketing)/page.tsx +96 -0
  143. package/template/prisma/src/app/api/auth/[...nextauth]/route.ts +7 -0
  144. package/template/prisma/src/app/favicon.ico +0 -0
  145. package/template/prisma/src/app/layout.tsx +34 -0
  146. package/template/prisma/src/components/app-nav-command.tsx +160 -0
  147. package/template/prisma/src/components/dark-mode-toggle.tsx +43 -0
  148. package/template/prisma/src/components/data-table/data-table-column-header.tsx +91 -0
  149. package/template/prisma/src/components/data-table/data-table-faceted-filter.tsx +149 -0
  150. package/template/prisma/src/components/data-table/data-table-loading.tsx +77 -0
  151. package/template/prisma/src/components/data-table/data-table-pagination.tsx +94 -0
  152. package/template/prisma/src/components/data-table/data-table-toolbar.tsx +78 -0
  153. package/template/prisma/src/components/data-table/data-table-types.ts +17 -0
  154. package/template/prisma/src/components/data-table/data-table-view-options.tsx +59 -0
  155. package/template/prisma/src/components/data-table/data-table.tsx +301 -0
  156. package/template/prisma/src/components/data-table/simple-data-table.tsx +109 -0
  157. package/template/prisma/src/components/empty-placeholder.tsx +78 -0
  158. package/template/prisma/src/components/heading.tsx +17 -0
  159. package/template/prisma/src/components/icons.tsx +85 -0
  160. package/template/prisma/src/components/main-nav.tsx +64 -0
  161. package/template/prisma/src/components/shell.tsx +13 -0
  162. package/template/prisma/src/components/side-nav.tsx +51 -0
  163. package/template/prisma/src/components/site-footer.tsx +31 -0
  164. package/template/prisma/src/components/system-info.tsx +36 -0
  165. package/template/prisma/src/components/ui/alert-dialog.tsx +141 -0
  166. package/template/prisma/src/components/ui/avatar.tsx +50 -0
  167. package/template/prisma/src/components/ui/badge.tsx +36 -0
  168. package/template/prisma/src/components/ui/button.tsx +56 -0
  169. package/template/prisma/src/components/ui/card.tsx +79 -0
  170. package/template/prisma/src/components/ui/checkbox.tsx +30 -0
  171. package/template/prisma/src/components/ui/command.tsx +155 -0
  172. package/template/prisma/src/components/ui/dialog.tsx +122 -0
  173. package/template/prisma/src/components/ui/dropdown-menu.tsx +200 -0
  174. package/template/prisma/src/components/ui/form.tsx +176 -0
  175. package/template/prisma/src/components/ui/input.tsx +25 -0
  176. package/template/prisma/src/components/ui/label.tsx +26 -0
  177. package/template/prisma/src/components/ui/popover.tsx +31 -0
  178. package/template/prisma/src/components/ui/select.tsx +160 -0
  179. package/template/prisma/src/components/ui/separator.tsx +31 -0
  180. package/template/prisma/src/components/ui/skeleton.tsx +15 -0
  181. package/template/prisma/src/components/ui/table.tsx +117 -0
  182. package/template/prisma/src/components/user-account-nav.tsx +60 -0
  183. package/template/prisma/src/components/user-avatar.tsx +25 -0
  184. package/template/prisma/src/env.mjs +78 -0
  185. package/template/prisma/src/hooks/use-debounce.ts +17 -0
  186. package/template/prisma/src/hooks/use-lock-body.tsx +12 -0
  187. package/template/prisma/src/lib/auth.ts +80 -0
  188. package/template/prisma/src/lib/cn.ts +4 -0
  189. package/template/prisma/src/lib/delay.ts +2 -0
  190. package/template/prisma/src/lib/formatDate.ts +11 -0
  191. package/template/prisma/src/lib/generateLabel.ts +5 -0
  192. package/template/prisma/src/lib/siteConfig.ts +4 -0
  193. package/template/prisma/src/styles/globals.css +76 -0
  194. package/template/prisma/tailwind.config.ts +80 -0
  195. package/template/prisma/tsconfig.json +46 -0
  196. package/template/prisma-advanced/src/lib/cn.ts +4 -0
  197. package/template/prisma-advanced/src/lib/delay.ts +2 -0
  198. package/template/prisma-advanced/src/lib/siteConfig.ts +4 -0
  199. /package/template/{advanced/src/styles → base/src/app}/globals.css +0 -0
  200. /package/template/{advanced/src/hooks/use-debounce.ts → base/src/hooks/use-debounce.tsx} +0 -0
  201. /package/template/{advanced → new}/src/lib/cn.ts +0 -0
  202. /package/template/{advanced → new}/src/lib/delay.ts +0 -0
  203. /package/template/{advanced → new}/src/lib/siteConfig.ts +0 -0
  204. /package/template/{base → prisma}/postcss.config.cjs +0 -0
  205. /package/template/{base → prisma}/prettier.config.ts +0 -0
  206. /package/template/{base → prisma}/prisma/schema.prisma +0 -0
  207. /package/template/{base → prisma}/src/app/(auth)/login/user-auth-form.tsx +0 -0
  208. /package/template/{base → prisma}/src/app/api/upload/route.ts +0 -0
  209. /package/template/{advanced → prisma}/src/components/mobile-nav.tsx +0 -0
  210. /package/template/{base → prisma}/src/components/theme-provider.tsx +0 -0
  211. /package/template/{base → prisma}/src/components/ui/textarea.tsx +0 -0
  212. /package/template/{base → prisma}/src/components/ui/toast.tsx +0 -0
  213. /package/template/{base → prisma}/src/components/ui/toaster.tsx +0 -0
  214. /package/template/{base → prisma}/src/components/ui/use-toast.ts +0 -0
  215. /package/template/{base → prisma}/src/lib/db.ts +0 -0
  216. /package/template/{base → prisma}/src/lib/storageClient.ts +0 -0
  217. /package/template/{base → prisma}/src/styles/editor.css +0 -0
  218. /package/template/{base → prisma}/src/types/UnwrapPromise.ts +0 -0
  219. /package/template/{advanced → prisma-advanced}/.env.example +0 -0
  220. /package/template/{advanced → prisma-advanced}/.eslintrc.cjs +0 -0
  221. /package/template/{advanced → prisma-advanced}/components.json +0 -0
  222. /package/template/{advanced → prisma-advanced}/next.config.mjs +0 -0
  223. /package/template/{advanced → prisma-advanced}/package.json +0 -0
  224. /package/template/{advanced → prisma-advanced}/postcss.config.cjs +0 -0
  225. /package/template/{advanced → prisma-advanced}/prettier.config.ts +0 -0
  226. /package/template/{advanced → prisma-advanced}/prisma/schema.prisma +0 -0
  227. /package/template/{advanced → prisma-advanced}/public/next.svg +0 -0
  228. /package/template/{advanced → prisma-advanced}/src/app/(app)/dashboard/page.tsx +0 -0
  229. /package/template/{advanced → prisma-advanced}/src/app/(app)/layout.tsx +0 -0
  230. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/actions.ts +0 -0
  231. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/page.tsx +0 -0
  232. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/render.tsx +0 -0
  233. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/actions.ts +0 -0
  234. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/page.tsx +0 -0
  235. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/render.tsx +0 -0
  236. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/actions.ts +0 -0
  237. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/loading.tsx +0 -0
  238. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/page.tsx +0 -0
  239. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/render.tsx +0 -0
  240. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/actions.ts +0 -0
  241. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/page.tsx +0 -0
  242. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/render.tsx +0 -0
  243. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/actions.ts +0 -0
  244. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/page.tsx +0 -0
  245. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/render.tsx +0 -0
  246. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/actions.ts +0 -0
  247. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/page.tsx +0 -0
  248. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/render.tsx +0 -0
  249. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/actions.ts +0 -0
  250. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/page.tsx +0 -0
  251. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/render.tsx +0 -0
  252. /package/template/{advanced → prisma-advanced}/src/app/(auth)/layout.tsx +0 -0
  253. /package/template/{advanced → prisma-advanced}/src/app/(auth)/login/page.tsx +0 -0
  254. /package/template/{advanced → prisma-advanced}/src/app/(auth)/login/user-auth-form.tsx +0 -0
  255. /package/template/{advanced → prisma-advanced}/src/app/(marketing)/layout.tsx +0 -0
  256. /package/template/{advanced → prisma-advanced}/src/app/(marketing)/page.tsx +0 -0
  257. /package/template/{advanced → prisma-advanced}/src/app/api/auth/[...nextauth]/route.ts +0 -0
  258. /package/template/{advanced → prisma-advanced}/src/app/api/upload/route.ts +0 -0
  259. /package/template/{advanced → prisma-advanced}/src/app/favicon.ico +0 -0
  260. /package/template/{advanced → prisma-advanced}/src/app/layout.tsx +0 -0
  261. /package/template/{advanced → prisma-advanced}/src/components/app-nav-command.tsx +0 -0
  262. /package/template/{advanced → prisma-advanced}/src/components/dark-mode-toggle.tsx +0 -0
  263. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-column-header.tsx +0 -0
  264. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-faceted-filter.tsx +0 -0
  265. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-loading.tsx +0 -0
  266. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-pagination.tsx +0 -0
  267. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-toolbar.tsx +0 -0
  268. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-types.ts +0 -0
  269. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-view-options.tsx +0 -0
  270. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table.tsx +0 -0
  271. /package/template/{advanced → prisma-advanced}/src/components/data-table/simple-data-table.tsx +0 -0
  272. /package/template/{advanced → prisma-advanced}/src/components/empty-placeholder.tsx +0 -0
  273. /package/template/{advanced → prisma-advanced}/src/components/heading.tsx +0 -0
  274. /package/template/{advanced → prisma-advanced}/src/components/icons.tsx +0 -0
  275. /package/template/{advanced → prisma-advanced}/src/components/main-nav.tsx +0 -0
  276. /package/template/{advanced → prisma-advanced}/src/components/shell.tsx +0 -0
  277. /package/template/{advanced → prisma-advanced}/src/components/side-nav.tsx +0 -0
  278. /package/template/{advanced → prisma-advanced}/src/components/site-footer.tsx +0 -0
  279. /package/template/{advanced → prisma-advanced}/src/components/system-info.tsx +0 -0
  280. /package/template/{advanced → prisma-advanced}/src/components/theme-provider.tsx +0 -0
  281. /package/template/{advanced → prisma-advanced}/src/components/ui/alert-dialog.tsx +0 -0
  282. /package/template/{advanced → prisma-advanced}/src/components/ui/avatar.tsx +0 -0
  283. /package/template/{advanced → prisma-advanced}/src/components/ui/badge.tsx +0 -0
  284. /package/template/{advanced → prisma-advanced}/src/components/ui/button.tsx +0 -0
  285. /package/template/{advanced → prisma-advanced}/src/components/ui/card.tsx +0 -0
  286. /package/template/{advanced → prisma-advanced}/src/components/ui/checkbox.tsx +0 -0
  287. /package/template/{advanced → prisma-advanced}/src/components/ui/command.tsx +0 -0
  288. /package/template/{advanced → prisma-advanced}/src/components/ui/dialog.tsx +0 -0
  289. /package/template/{advanced → prisma-advanced}/src/components/ui/dropdown-menu.tsx +0 -0
  290. /package/template/{advanced → prisma-advanced}/src/components/ui/form.tsx +0 -0
  291. /package/template/{advanced → prisma-advanced}/src/components/ui/input.tsx +0 -0
  292. /package/template/{advanced → prisma-advanced}/src/components/ui/label.tsx +0 -0
  293. /package/template/{advanced → prisma-advanced}/src/components/ui/popover.tsx +0 -0
  294. /package/template/{advanced → prisma-advanced}/src/components/ui/select.tsx +0 -0
  295. /package/template/{advanced → prisma-advanced}/src/components/ui/separator.tsx +0 -0
  296. /package/template/{advanced → prisma-advanced}/src/components/ui/skeleton.tsx +0 -0
  297. /package/template/{advanced → prisma-advanced}/src/components/ui/table.tsx +0 -0
  298. /package/template/{advanced → prisma-advanced}/src/components/ui/textarea.tsx +0 -0
  299. /package/template/{advanced → prisma-advanced}/src/components/ui/toast.tsx +0 -0
  300. /package/template/{advanced → prisma-advanced}/src/components/ui/toaster.tsx +0 -0
  301. /package/template/{advanced → prisma-advanced}/src/components/ui/use-toast.ts +0 -0
  302. /package/template/{advanced → prisma-advanced}/src/components/user-account-nav.tsx +0 -0
  303. /package/template/{advanced → prisma-advanced}/src/components/user-avatar.tsx +0 -0
  304. /package/template/{advanced → prisma-advanced}/src/env.mjs +0 -0
  305. /package/template/{base → prisma-advanced}/src/hooks/use-debounce.ts +0 -0
  306. /package/template/{advanced → prisma-advanced}/src/hooks/use-lock-body.tsx +0 -0
  307. /package/template/{advanced → prisma-advanced}/src/lib/auth.ts +0 -0
  308. /package/template/{advanced → prisma-advanced}/src/lib/db.ts +0 -0
  309. /package/template/{advanced → prisma-advanced}/src/lib/formatDate.ts +0 -0
  310. /package/template/{advanced → prisma-advanced}/src/lib/generateLabel.ts +0 -0
  311. /package/template/{advanced → prisma-advanced}/src/lib/storageClient.ts +0 -0
  312. /package/template/{advanced → prisma-advanced}/src/styles/editor.css +0 -0
  313. /package/template/{base → prisma-advanced}/src/styles/globals.css +0 -0
  314. /package/template/{advanced → prisma-advanced}/src/types/UnwrapPromise.ts +0 -0
  315. /package/template/{advanced → prisma-advanced}/tailwind.config.ts +0 -0
  316. /package/template/{advanced → prisma-advanced}/tsconfig.json +0 -0
@@ -0,0 +1,94 @@
1
+ import { type Table } from '@tanstack/react-table'
2
+
3
+ import { Icons } from '@/components/icons'
4
+ import { Button } from '@/components/ui/button'
5
+ import {
6
+ Select,
7
+ SelectContent,
8
+ SelectItem,
9
+ SelectTrigger,
10
+ SelectValue
11
+ } from '@/components/ui/select'
12
+
13
+ interface DataTablePaginationProps<TData> {
14
+ table: Table<TData>
15
+ pageSizeOptions?: number[]
16
+ }
17
+
18
+ export function DataTablePagination<TData>({
19
+ table,
20
+ pageSizeOptions = [10, 20, 30, 50]
21
+ }: DataTablePaginationProps<TData>) {
22
+ return (
23
+ <div className="flex w-full flex-col items-center justify-between gap-4 overflow-auto px-2 py-1 sm:flex-row sm:gap-8">
24
+ <div className="flex-1 whitespace-nowrap text-sm text-muted-foreground">
25
+ {table.getFilteredSelectedRowModel().rows.length} of{' '}
26
+ {table.getFilteredRowModel().rows.length} row(s) selected.
27
+ </div>
28
+ <div className="flex flex-col items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8">
29
+ <div className="flex items-center space-x-2">
30
+ <p className="whitespace-nowrap text-sm font-medium">Rows per page</p>
31
+ <Select
32
+ value={`${table.getState().pagination.pageSize}`}
33
+ onValueChange={value => {
34
+ table.setPageSize(Number(value))
35
+ }}
36
+ >
37
+ <SelectTrigger className="h-8 w-[70px]">
38
+ <SelectValue placeholder={table.getState().pagination.pageSize} />
39
+ </SelectTrigger>
40
+ <SelectContent side="top">
41
+ {pageSizeOptions.map(pageSize => (
42
+ <SelectItem key={pageSize} value={`${pageSize}`}>
43
+ {pageSize}
44
+ </SelectItem>
45
+ ))}
46
+ </SelectContent>
47
+ </Select>
48
+ </div>
49
+ <div className="flex w-[100px] items-center justify-center text-sm font-medium">
50
+ Page {table.getState().pagination.pageIndex + 1} of{' '}
51
+ {table.getPageCount()}
52
+ </div>
53
+ <div className="flex items-center space-x-2">
54
+ <Button
55
+ aria-label="Go to first page"
56
+ variant="outline"
57
+ className="hidden h-8 w-8 p-0 lg:flex"
58
+ onClick={() => table.setPageIndex(0)}
59
+ disabled={!table.getCanPreviousPage()}
60
+ >
61
+ <Icons.chevronsLeft className="h-4 w-4" aria-hidden="true" />
62
+ </Button>
63
+ <Button
64
+ aria-label="Go to previous page"
65
+ variant="outline"
66
+ className="h-8 w-8 p-0"
67
+ onClick={() => table.previousPage()}
68
+ disabled={!table.getCanPreviousPage()}
69
+ >
70
+ <Icons.chevronLeft className="h-4 w-4" aria-hidden="true" />
71
+ </Button>
72
+ <Button
73
+ aria-label="Go to next page"
74
+ variant="outline"
75
+ className="h-8 w-8 p-0"
76
+ onClick={() => table.nextPage()}
77
+ disabled={!table.getCanNextPage()}
78
+ >
79
+ <Icons.chevronRight className="h-4 w-4" aria-hidden="true" />
80
+ </Button>
81
+ <Button
82
+ aria-label="Go to last page"
83
+ variant="outline"
84
+ className="hidden h-8 w-8 p-0 lg:flex"
85
+ onClick={() => table.setPageIndex(table.getPageCount() - 1)}
86
+ disabled={!table.getCanNextPage()}
87
+ >
88
+ <Icons.chevronsRight className="h-4 w-4" aria-hidden="true" />
89
+ </Button>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ )
94
+ }
@@ -0,0 +1,78 @@
1
+ 'use client'
2
+
3
+ import type { Table } from '@tanstack/react-table'
4
+
5
+ import { DataTableFacetedFilter } from '@/components/data-table/data-table-faceted-filter'
6
+ import { DataTableViewOptions } from '@/components/data-table/data-table-view-options'
7
+ import { Icons } from '@/components/icons'
8
+ import { Button } from '@/components/ui/button'
9
+ import { Input } from '@/components/ui/input'
10
+ import {
11
+ DataTableFilterableColumn,
12
+ DataTableSearchableColumn
13
+ } from './data-table-types'
14
+
15
+ interface DataTableToolbarProps<TData> {
16
+ table: Table<TData>
17
+ filterableColumns?: DataTableFilterableColumn<TData>[]
18
+ searchableColumns?: DataTableSearchableColumn<TData>[]
19
+ }
20
+
21
+ export function DataTableToolbar<TData>({
22
+ table,
23
+ filterableColumns = [],
24
+ searchableColumns = []
25
+ }: DataTableToolbarProps<TData>) {
26
+ const isFiltered = table.getState().columnFilters.length > 0
27
+
28
+ return (
29
+ <div className="flex items-center justify-between p-1">
30
+ <div className="flex flex-1 items-center space-x-2">
31
+ {searchableColumns.length > 0 &&
32
+ searchableColumns.map(
33
+ column =>
34
+ table.getColumn(column.id ? String(column.id) : '') && (
35
+ <Input
36
+ key={String(column.id)}
37
+ placeholder={`Filter ${column.title}...`}
38
+ value={
39
+ (table
40
+ .getColumn(String(column.id))
41
+ ?.getFilterValue() as string) ?? ''
42
+ }
43
+ onChange={event =>
44
+ table
45
+ .getColumn(String(column.id))
46
+ ?.setFilterValue(event.target.value)
47
+ }
48
+ className="h-8 w-[150px] lg:w-[250px]"
49
+ />
50
+ )
51
+ )}
52
+ {filterableColumns.length > 0 &&
53
+ filterableColumns.map(
54
+ column =>
55
+ table.getColumn(column.id ? String(column.id) : '') && (
56
+ <DataTableFacetedFilter
57
+ key={String(column.id)}
58
+ column={table.getColumn(column.id ? String(column.id) : '')}
59
+ title={column.title}
60
+ options={column.options}
61
+ />
62
+ )
63
+ )}
64
+ {isFiltered && (
65
+ <Button
66
+ variant="ghost"
67
+ onClick={() => table.resetColumnFilters()}
68
+ className="h-8 px-2 lg:px-3"
69
+ >
70
+ Reset
71
+ <Icons.close className="ml-2 h-4 w-4" />
72
+ </Button>
73
+ )}
74
+ </div>
75
+ <DataTableViewOptions table={table} />
76
+ </div>
77
+ )
78
+ }
@@ -0,0 +1,17 @@
1
+ import { ComponentType } from 'react'
2
+
3
+ export type Option = {
4
+ label: string
5
+ value: string
6
+ icon?: ComponentType<{ className?: string }>
7
+ }
8
+
9
+ export interface DataTableSearchableColumn<TData> {
10
+ id: keyof TData
11
+ title: string
12
+ }
13
+
14
+ export interface DataTableFilterableColumn<TData>
15
+ extends DataTableSearchableColumn<TData> {
16
+ options: Option[]
17
+ }
@@ -0,0 +1,59 @@
1
+ 'use client'
2
+
3
+ import { DropdownMenuTrigger } from '@radix-ui/react-dropdown-menu'
4
+ import { type Table } from '@tanstack/react-table'
5
+
6
+ import { Icons } from '@/components/icons'
7
+ import { Button } from '@/components/ui/button'
8
+ import {
9
+ DropdownMenu,
10
+ DropdownMenuCheckboxItem,
11
+ DropdownMenuContent,
12
+ DropdownMenuLabel,
13
+ DropdownMenuSeparator
14
+ } from '@/components/ui/dropdown-menu'
15
+
16
+ interface DataTableViewOptionsProps<TData> {
17
+ table: Table<TData>
18
+ }
19
+
20
+ export function DataTableViewOptions<TData>({
21
+ table
22
+ }: DataTableViewOptionsProps<TData>) {
23
+ return (
24
+ <DropdownMenu>
25
+ <DropdownMenuTrigger asChild>
26
+ <Button
27
+ variant="outline"
28
+ size="sm"
29
+ className="ml-auto hidden h-8 lg:flex"
30
+ >
31
+ <Icons.mixer className="mr-2 h-4 w-4" />
32
+ View
33
+ </Button>
34
+ </DropdownMenuTrigger>
35
+ <DropdownMenuContent align="end" className="w-[150px]">
36
+ <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>
37
+ <DropdownMenuSeparator />
38
+ {table
39
+ .getAllColumns()
40
+ .filter(
41
+ column =>
42
+ typeof column.accessorFn !== 'undefined' && column.getCanHide()
43
+ )
44
+ .map(column => {
45
+ return (
46
+ <DropdownMenuCheckboxItem
47
+ key={column.id}
48
+ className="capitalize"
49
+ checked={column.getIsVisible()}
50
+ onCheckedChange={value => column.toggleVisibility(!!value)}
51
+ >
52
+ {column.id}
53
+ </DropdownMenuCheckboxItem>
54
+ )
55
+ })}
56
+ </DropdownMenuContent>
57
+ </DropdownMenu>
58
+ )
59
+ }
@@ -0,0 +1,301 @@
1
+ 'use client'
2
+
3
+ import {
4
+ flexRender,
5
+ getCoreRowModel,
6
+ getFacetedRowModel,
7
+ getFacetedUniqueValues,
8
+ getFilteredRowModel,
9
+ getPaginationRowModel,
10
+ getSortedRowModel,
11
+ useReactTable,
12
+ type ColumnDef,
13
+ type ColumnFiltersState,
14
+ type PaginationState,
15
+ type SortingState,
16
+ type VisibilityState
17
+ } from '@tanstack/react-table'
18
+ import { usePathname, useRouter, useSearchParams } from 'next/navigation'
19
+
20
+ import { DataTablePagination } from '@/components/data-table/data-table-pagination'
21
+ import { DataTableToolbar } from '@/components/data-table/data-table-toolbar'
22
+ import {
23
+ Table,
24
+ TableBody,
25
+ TableCell,
26
+ TableHead,
27
+ TableHeader,
28
+ TableRow
29
+ } from '@/components/ui/table'
30
+ import { useDebounce } from '@/hooks/use-debounce'
31
+ import { useCallback, useEffect, useMemo, useState } from 'react'
32
+ import {
33
+ DataTableFilterableColumn,
34
+ DataTableSearchableColumn
35
+ } from './data-table-types'
36
+
37
+ interface DataTableProps<TData, TValue> {
38
+ columns: ColumnDef<TData, TValue>[]
39
+ data: TData[]
40
+ total: number
41
+ filterableColumns?: DataTableFilterableColumn<TData>[]
42
+ searchableColumns?: DataTableSearchableColumn<TData>[]
43
+ }
44
+
45
+ export function DataTable<TData, TValue>({
46
+ columns,
47
+ data,
48
+ total,
49
+ filterableColumns = [],
50
+ searchableColumns = []
51
+ }: DataTableProps<TData, TValue>) {
52
+ const router = useRouter()
53
+ const pathname = usePathname()
54
+ const searchParams = useSearchParams()
55
+
56
+ // Search params
57
+ const page = searchParams?.get('page') ?? '1'
58
+ const limit = searchParams?.get('limit') ?? '10'
59
+ const sort = searchParams?.get('sort')
60
+ const [column, order] = sort?.split('.') ?? []
61
+
62
+ // Create query string
63
+ const createQueryString = useCallback(
64
+ (params: Record<string, string | number | null>) => {
65
+ const newSearchParams = new URLSearchParams(searchParams?.toString())
66
+
67
+ for (const [key, value] of Object.entries(params)) {
68
+ if (value === null) {
69
+ newSearchParams.delete(key)
70
+ } else {
71
+ newSearchParams.set(key, String(value))
72
+ }
73
+ }
74
+
75
+ return newSearchParams.toString()
76
+ },
77
+ [searchParams]
78
+ )
79
+
80
+ // Table states
81
+ const [rowSelection, setRowSelection] = useState({})
82
+ const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
83
+ const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
84
+
85
+ // Handle server-side pagination
86
+ const [{ pageIndex, pageSize }, setPagination] = useState<PaginationState>({
87
+ pageIndex: Number(page) - 1,
88
+ pageSize: Number(limit)
89
+ })
90
+
91
+ const pagination = useMemo(
92
+ () => ({
93
+ pageIndex,
94
+ pageSize
95
+ }),
96
+ [pageIndex, pageSize]
97
+ )
98
+
99
+ useEffect(() => {
100
+ setPagination({
101
+ pageIndex: Number(page) - 1,
102
+ pageSize: Number(limit)
103
+ })
104
+ }, [page, limit])
105
+
106
+ useEffect(() => {
107
+ router.push(
108
+ `${pathname}?${createQueryString({
109
+ page: pageIndex + 1,
110
+ limit: pageSize
111
+ })}`
112
+ )
113
+ // eslint-disable-next-line react-hooks/exhaustive-deps
114
+ }, [pageIndex, pageSize])
115
+
116
+ // Handle server-side sorting
117
+ const [sorting, setSorting] = useState<SortingState>([
118
+ {
119
+ id: column ?? '',
120
+ desc: order === 'desc'
121
+ }
122
+ ])
123
+
124
+ useEffect(() => {
125
+ router.push(
126
+ `${pathname}?${createQueryString({
127
+ page,
128
+ sort: sorting[0]?.id
129
+ ? `${sorting[0]?.id}.${sorting[0]?.desc ? 'desc' : 'asc'}`
130
+ : null
131
+ })}`
132
+ )
133
+ // eslint-disable-next-line react-hooks/exhaustive-deps
134
+ }, [sorting])
135
+
136
+ // Handle server-side filtering
137
+ const debouncedSearchableColumnFilters = JSON.parse(
138
+ useDebounce(
139
+ JSON.stringify(
140
+ columnFilters.filter(filter => {
141
+ return searchableColumns.find(column => column.id === filter.id)
142
+ })
143
+ ),
144
+ 500
145
+ )
146
+ ) as ColumnFiltersState
147
+
148
+ const filterableColumnFilters = columnFilters.filter(filter => {
149
+ return filterableColumns.find(column => column.id === filter.id)
150
+ })
151
+
152
+ useEffect(() => {
153
+ for (const column of debouncedSearchableColumnFilters) {
154
+ if (typeof column.value === 'string') {
155
+ router.push(
156
+ `${pathname}?${createQueryString({
157
+ page: 1,
158
+ [column.id]: typeof column.value === 'string' ? column.value : null
159
+ })}`
160
+ )
161
+ }
162
+ }
163
+
164
+ for (const key of searchParams.keys()) {
165
+ if (
166
+ searchableColumns.find(column => column.id === key) &&
167
+ !debouncedSearchableColumnFilters.find(column => column.id === key)
168
+ ) {
169
+ router.push(
170
+ `${pathname}?${createQueryString({
171
+ page: 1,
172
+ [key]: null
173
+ })}`
174
+ )
175
+ }
176
+ }
177
+ // eslint-disable-next-line react-hooks/exhaustive-deps
178
+ }, [JSON.stringify(debouncedSearchableColumnFilters)])
179
+
180
+ useEffect(() => {
181
+ for (const column of filterableColumnFilters) {
182
+ if (typeof column.value === 'object' && Array.isArray(column.value)) {
183
+ router.push(
184
+ `${pathname}?${createQueryString({
185
+ page: 1,
186
+ [column.id]: column.value.join('.')
187
+ })}`
188
+ )
189
+ }
190
+ }
191
+
192
+ for (const key of searchParams.keys()) {
193
+ if (
194
+ filterableColumns.find(column => column.id === key) &&
195
+ !filterableColumnFilters.find(column => column.id === key)
196
+ ) {
197
+ router.push(
198
+ `${pathname}?${createQueryString({
199
+ page: 1,
200
+ [key]: null
201
+ })}`
202
+ )
203
+ }
204
+ }
205
+ // eslint-disable-next-line react-hooks/exhaustive-deps
206
+ }, [JSON.stringify(filterableColumnFilters)])
207
+
208
+ const pageCount = useMemo(
209
+ () => Math.ceil(total / pageSize),
210
+ [total, pageSize]
211
+ )
212
+
213
+ const table = useReactTable({
214
+ data,
215
+ columns,
216
+ pageCount,
217
+ state: {
218
+ pagination,
219
+ sorting,
220
+ columnVisibility,
221
+ rowSelection,
222
+ columnFilters
223
+ },
224
+ enableRowSelection: true,
225
+ onRowSelectionChange: setRowSelection,
226
+ onPaginationChange: setPagination,
227
+ onSortingChange: setSorting,
228
+ onColumnFiltersChange: setColumnFilters,
229
+ onColumnVisibilityChange: setColumnVisibility,
230
+ getCoreRowModel: getCoreRowModel(),
231
+ getFilteredRowModel: getFilteredRowModel(),
232
+ getPaginationRowModel: getPaginationRowModel(),
233
+ getSortedRowModel: getSortedRowModel(),
234
+ getFacetedRowModel: getFacetedRowModel(),
235
+ getFacetedUniqueValues: getFacetedUniqueValues(),
236
+ manualPagination: true,
237
+ manualSorting: true,
238
+ manualFiltering: true
239
+ })
240
+
241
+ return (
242
+ <div className="w-full space-y-4 overflow-auto">
243
+ <DataTableToolbar
244
+ table={table}
245
+ filterableColumns={filterableColumns}
246
+ searchableColumns={searchableColumns}
247
+ />
248
+ <div className="rounded-md border">
249
+ <Table>
250
+ <TableHeader>
251
+ {table.getHeaderGroups().map(headerGroup => (
252
+ <TableRow key={headerGroup.id}>
253
+ {headerGroup.headers.map(header => {
254
+ return (
255
+ <TableHead key={header.id}>
256
+ {header.isPlaceholder
257
+ ? null
258
+ : flexRender(
259
+ header.column.columnDef.header,
260
+ header.getContext()
261
+ )}
262
+ </TableHead>
263
+ )
264
+ })}
265
+ </TableRow>
266
+ ))}
267
+ </TableHeader>
268
+ <TableBody>
269
+ {table.getRowModel().rows?.length ? (
270
+ table.getRowModel().rows.map(row => (
271
+ <TableRow
272
+ key={row.id}
273
+ data-state={row.getIsSelected() && 'selected'}
274
+ >
275
+ {row.getVisibleCells().map(cell => (
276
+ <TableCell key={cell.id}>
277
+ {flexRender(
278
+ cell.column.columnDef.cell,
279
+ cell.getContext()
280
+ )}
281
+ </TableCell>
282
+ ))}
283
+ </TableRow>
284
+ ))
285
+ ) : (
286
+ <TableRow>
287
+ <TableCell
288
+ colSpan={columns.length}
289
+ className="h-24 text-center"
290
+ >
291
+ No results.
292
+ </TableCell>
293
+ </TableRow>
294
+ )}
295
+ </TableBody>
296
+ </Table>
297
+ </div>
298
+ <DataTablePagination table={table} />
299
+ </div>
300
+ )
301
+ }
@@ -0,0 +1,109 @@
1
+ 'use client'
2
+
3
+ import {
4
+ ColumnDef,
5
+ flexRender,
6
+ getCoreRowModel,
7
+ getPaginationRowModel,
8
+ useReactTable
9
+ } from '@tanstack/react-table'
10
+
11
+ import { Button } from '@/components/ui/button'
12
+ import {
13
+ Table,
14
+ TableBody,
15
+ TableCell,
16
+ TableHead,
17
+ TableHeader,
18
+ TableRow
19
+ } from '@/components/ui/table'
20
+
21
+ interface DataTableProps<TData, TValue> {
22
+ columns: ColumnDef<TData, TValue>[]
23
+ data: TData[]
24
+ }
25
+
26
+ export function SimpleDataTable<TData, TValue>({
27
+ columns,
28
+ data
29
+ }: DataTableProps<TData, TValue>) {
30
+ const table = useReactTable({
31
+ data,
32
+ columns,
33
+ getCoreRowModel: getCoreRowModel(),
34
+ getPaginationRowModel: getPaginationRowModel()
35
+ })
36
+
37
+ return (
38
+ <div>
39
+ <div className="rounded-md border">
40
+ <Table>
41
+ <TableHeader>
42
+ {table.getHeaderGroups().map(headerGroup => (
43
+ <TableRow key={headerGroup.id}>
44
+ {headerGroup.headers.map(header => {
45
+ return (
46
+ <TableHead key={header.id}>
47
+ {header.isPlaceholder
48
+ ? null
49
+ : flexRender(
50
+ header.column.columnDef.header,
51
+ header.getContext()
52
+ )}
53
+ </TableHead>
54
+ )
55
+ })}
56
+ </TableRow>
57
+ ))}
58
+ </TableHeader>
59
+ <TableBody>
60
+ {table.getRowModel().rows?.length ? (
61
+ table.getRowModel().rows.map(row => (
62
+ <TableRow
63
+ key={row.id}
64
+ data-state={row.getIsSelected() && 'selected'}
65
+ >
66
+ {row.getVisibleCells().map(cell => (
67
+ <TableCell key={cell.id}>
68
+ {flexRender(
69
+ cell.column.columnDef.cell,
70
+ cell.getContext()
71
+ )}
72
+ </TableCell>
73
+ ))}
74
+ </TableRow>
75
+ ))
76
+ ) : (
77
+ <TableRow>
78
+ <TableCell
79
+ colSpan={columns.length}
80
+ className="h-24 text-center"
81
+ >
82
+ No results.
83
+ </TableCell>
84
+ </TableRow>
85
+ )}
86
+ </TableBody>
87
+ </Table>
88
+ </div>
89
+ <div className="flex items-center justify-end space-x-2 py-4">
90
+ <Button
91
+ variant="outline"
92
+ size="sm"
93
+ onClick={() => table.previousPage()}
94
+ disabled={!table.getCanPreviousPage()}
95
+ >
96
+ Previous
97
+ </Button>
98
+ <Button
99
+ variant="outline"
100
+ size="sm"
101
+ onClick={() => table.nextPage()}
102
+ disabled={!table.getCanNextPage()}
103
+ >
104
+ Next
105
+ </Button>
106
+ </div>
107
+ </div>
108
+ )
109
+ }