create-ej-app 6.0.0 → 7.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 (364) hide show
  1. package/cli.js +88 -14
  2. package/cli.ts +100 -17
  3. package/package.json +2 -2
  4. package/template/base/.env.example +11 -15
  5. package/template/base/Dockerfile +15 -0
  6. package/template/base/components.json +10 -5
  7. package/template/base/drizzle.config.ts +4 -5
  8. package/template/{new → base}/eslint.config.mjs +6 -1
  9. package/template/base/package.json +58 -75
  10. package/template/base/postcss.config.mjs +1 -4
  11. package/template/base/src/app/(admin)/layout.tsx +20 -0
  12. package/template/base/src/app/(app)/layout.tsx +13 -118
  13. package/template/base/src/app/(auth)/login/page.tsx +65 -42
  14. package/template/base/src/app/(marketing)/layout.tsx +7 -35
  15. package/template/base/src/app/(marketing)/page.tsx +2 -96
  16. package/template/base/src/app/(marketing)/privacy/page.tsx +3 -0
  17. package/template/base/src/app/(marketing)/terms/page.tsx +3 -0
  18. package/template/base/src/app/globals.css +118 -66
  19. package/template/base/src/app/layout.tsx +27 -12
  20. package/template/base/src/app/not-found.tsx +27 -0
  21. package/template/base/src/components/site-footer.tsx +16 -24
  22. package/template/base/src/components/ui/button.tsx +31 -27
  23. package/template/base/src/components/ui/card.tsx +83 -70
  24. package/template/base/src/components/ui/form.tsx +38 -47
  25. package/template/base/src/components/ui/input.tsx +16 -20
  26. package/template/base/src/components/ui/label.tsx +16 -18
  27. package/template/base/src/components/ui/separator.tsx +11 -14
  28. package/template/base/src/components/ui/sonner.tsx +22 -13
  29. package/template/base/src/db/index.ts +4 -11
  30. package/template/base/src/db/schema.ts +60 -268
  31. package/template/{new → base}/src/env.ts +2 -2
  32. package/template/{new → base}/src/lib/auth-client.ts +2 -0
  33. package/template/base/src/lib/auth.ts +64 -80
  34. package/template/base/src/lib/safe-action.ts +30 -6
  35. package/template/base/tsconfig.json +9 -7
  36. package/template/{prisma-advanced → old}/.env.example +10 -9
  37. package/template/{prisma → old}/components.json +1 -1
  38. package/template/old/drizzle.config.ts +11 -0
  39. package/template/old/package.json +87 -0
  40. package/template/old/postcss.config.mjs +8 -0
  41. package/template/{prisma-advanced → old}/src/app/(app)/layout.tsx +11 -3
  42. package/template/{prisma-advanced → old}/src/app/(auth)/login/page.tsx +2 -2
  43. package/template/{prisma → old}/src/app/(marketing)/page.tsx +8 -7
  44. package/template/old/src/app/layout.tsx +31 -0
  45. package/template/old/src/components/ui/sonner.tsx +31 -0
  46. package/template/old/src/db/index.ts +14 -0
  47. package/template/old/src/db/schema.ts +287 -0
  48. package/template/old/src/lib/auth.ts +89 -0
  49. package/template/old/src/lib/safe-action.ts +19 -0
  50. package/template/{prisma-advanced → old}/tsconfig.json +3 -2
  51. package/template/new/.env.example +0 -13
  52. package/template/new/components.json +0 -22
  53. package/template/new/drizzle.config.ts +0 -10
  54. package/template/new/package.json +0 -81
  55. package/template/new/postcss.config.mjs +0 -5
  56. package/template/new/src/app/(auth)/login/page.tsx +0 -72
  57. package/template/new/src/app/globals.css +0 -128
  58. package/template/new/src/app/layout.tsx +0 -50
  59. package/template/new/src/app/page.tsx +0 -3
  60. package/template/new/src/components/ui/button.tsx +0 -60
  61. package/template/new/src/components/ui/card.tsx +0 -92
  62. package/template/new/src/components/ui/form.tsx +0 -167
  63. package/template/new/src/components/ui/input.tsx +0 -21
  64. package/template/new/src/components/ui/label.tsx +0 -24
  65. package/template/new/src/components/ui/separator.tsx +0 -28
  66. package/template/new/src/components/ui/sonner.tsx +0 -40
  67. package/template/new/src/db/index.ts +0 -7
  68. package/template/new/src/db/schema.ts +0 -74
  69. package/template/new/src/lib/auth.ts +0 -67
  70. package/template/new/src/lib/safe-action.ts +0 -15
  71. package/template/new/tsconfig.json +0 -49
  72. package/template/prisma/.env.example +0 -16
  73. package/template/prisma/.eslintrc.cjs +0 -24
  74. package/template/prisma/next.config.mjs +0 -15
  75. package/template/prisma/package.json +0 -80
  76. package/template/prisma/postcss.config.cjs +0 -6
  77. package/template/prisma/prettier.config.ts +0 -11
  78. package/template/prisma/prisma/schema.prisma +0 -115
  79. package/template/prisma/public/next.svg +0 -1
  80. package/template/prisma/src/app/(app)/dashboard/page.tsx +0 -19
  81. package/template/prisma/src/app/(app)/layout.tsx +0 -90
  82. package/template/prisma/src/app/(app)/settings/actions.ts +0 -18
  83. package/template/prisma/src/app/(app)/settings/loading.tsx +0 -28
  84. package/template/prisma/src/app/(app)/settings/page.tsx +0 -28
  85. package/template/prisma/src/app/(app)/settings/render.tsx +0 -113
  86. package/template/prisma/src/app/(app)/tasks/[id]/actions.ts +0 -147
  87. package/template/prisma/src/app/(app)/tasks/[id]/page.tsx +0 -25
  88. package/template/prisma/src/app/(app)/tasks/[id]/render.tsx +0 -413
  89. package/template/prisma/src/app/(app)/tasks/actions.ts +0 -69
  90. package/template/prisma/src/app/(app)/tasks/page.tsx +0 -53
  91. package/template/prisma/src/app/(app)/tasks/render.tsx +0 -107
  92. package/template/prisma/src/app/(app)/users/[id]/actions.ts +0 -83
  93. package/template/prisma/src/app/(app)/users/[id]/page.tsx +0 -32
  94. package/template/prisma/src/app/(app)/users/[id]/render.tsx +0 -240
  95. package/template/prisma/src/app/(app)/users/actions.ts +0 -55
  96. package/template/prisma/src/app/(app)/users/page.tsx +0 -49
  97. package/template/prisma/src/app/(app)/users/render.tsx +0 -80
  98. package/template/prisma/src/app/(auth)/layout.tsx +0 -20
  99. package/template/prisma/src/app/(auth)/login/page.tsx +0 -49
  100. package/template/prisma/src/app/(auth)/login/user-auth-form.tsx +0 -152
  101. package/template/prisma/src/app/api/auth/[...nextauth]/route.ts +0 -7
  102. package/template/prisma/src/app/api/upload/route.ts +0 -36
  103. package/template/prisma/src/app/favicon.ico +0 -0
  104. package/template/prisma/src/app/layout.tsx +0 -34
  105. package/template/prisma/src/components/app-nav-command.tsx +0 -160
  106. package/template/prisma/src/components/dark-mode-toggle.tsx +0 -43
  107. package/template/prisma/src/components/data-table/data-table-column-header.tsx +0 -91
  108. package/template/prisma/src/components/data-table/data-table-faceted-filter.tsx +0 -149
  109. package/template/prisma/src/components/data-table/data-table-loading.tsx +0 -77
  110. package/template/prisma/src/components/data-table/data-table-pagination.tsx +0 -94
  111. package/template/prisma/src/components/data-table/data-table-toolbar.tsx +0 -78
  112. package/template/prisma/src/components/data-table/data-table-types.ts +0 -17
  113. package/template/prisma/src/components/data-table/data-table-view-options.tsx +0 -59
  114. package/template/prisma/src/components/data-table/data-table.tsx +0 -301
  115. package/template/prisma/src/components/data-table/simple-data-table.tsx +0 -109
  116. package/template/prisma/src/components/empty-placeholder.tsx +0 -78
  117. package/template/prisma/src/components/heading.tsx +0 -17
  118. package/template/prisma/src/components/icons.tsx +0 -85
  119. package/template/prisma/src/components/main-nav.tsx +0 -64
  120. package/template/prisma/src/components/mobile-nav.tsx +0 -50
  121. package/template/prisma/src/components/shell.tsx +0 -13
  122. package/template/prisma/src/components/side-nav.tsx +0 -51
  123. package/template/prisma/src/components/site-footer.tsx +0 -31
  124. package/template/prisma/src/components/system-info.tsx +0 -36
  125. package/template/prisma/src/components/theme-provider.tsx +0 -13
  126. package/template/prisma/src/components/ui/alert-dialog.tsx +0 -141
  127. package/template/prisma/src/components/ui/avatar.tsx +0 -50
  128. package/template/prisma/src/components/ui/badge.tsx +0 -36
  129. package/template/prisma/src/components/ui/button.tsx +0 -56
  130. package/template/prisma/src/components/ui/card.tsx +0 -79
  131. package/template/prisma/src/components/ui/checkbox.tsx +0 -30
  132. package/template/prisma/src/components/ui/command.tsx +0 -155
  133. package/template/prisma/src/components/ui/dialog.tsx +0 -122
  134. package/template/prisma/src/components/ui/dropdown-menu.tsx +0 -200
  135. package/template/prisma/src/components/ui/form.tsx +0 -176
  136. package/template/prisma/src/components/ui/input.tsx +0 -25
  137. package/template/prisma/src/components/ui/label.tsx +0 -26
  138. package/template/prisma/src/components/ui/popover.tsx +0 -31
  139. package/template/prisma/src/components/ui/select.tsx +0 -160
  140. package/template/prisma/src/components/ui/separator.tsx +0 -31
  141. package/template/prisma/src/components/ui/skeleton.tsx +0 -15
  142. package/template/prisma/src/components/ui/table.tsx +0 -117
  143. package/template/prisma/src/components/ui/textarea.tsx +0 -24
  144. package/template/prisma/src/components/ui/toast.tsx +0 -127
  145. package/template/prisma/src/components/ui/toaster.tsx +0 -35
  146. package/template/prisma/src/components/ui/use-toast.ts +0 -189
  147. package/template/prisma/src/components/user-account-nav.tsx +0 -60
  148. package/template/prisma/src/components/user-avatar.tsx +0 -25
  149. package/template/prisma/src/env.mjs +0 -78
  150. package/template/prisma/src/hooks/use-debounce.ts +0 -17
  151. package/template/prisma/src/hooks/use-lock-body.tsx +0 -12
  152. package/template/prisma/src/lib/auth.ts +0 -80
  153. package/template/prisma/src/lib/cn.ts +0 -4
  154. package/template/prisma/src/lib/db.ts +0 -20
  155. package/template/prisma/src/lib/delay.ts +0 -2
  156. package/template/prisma/src/lib/formatDate.ts +0 -11
  157. package/template/prisma/src/lib/generateLabel.ts +0 -5
  158. package/template/prisma/src/lib/siteConfig.ts +0 -4
  159. package/template/prisma/src/lib/storageClient.ts +0 -11
  160. package/template/prisma/src/styles/editor.css +0 -61
  161. package/template/prisma/src/styles/globals.css +0 -76
  162. package/template/prisma/src/types/UnwrapPromise.ts +0 -1
  163. package/template/prisma/tailwind.config.ts +0 -80
  164. package/template/prisma/tsconfig.json +0 -46
  165. package/template/prisma-advanced/.eslintrc.cjs +0 -24
  166. package/template/prisma-advanced/components.json +0 -17
  167. package/template/prisma-advanced/next.config.mjs +0 -15
  168. package/template/prisma-advanced/package.json +0 -80
  169. package/template/prisma-advanced/postcss.config.cjs +0 -6
  170. package/template/prisma-advanced/prettier.config.ts +0 -11
  171. package/template/prisma-advanced/prisma/schema.prisma +0 -154
  172. package/template/prisma-advanced/public/next.svg +0 -1
  173. package/template/prisma-advanced/src/app/(app)/dashboard/page.tsx +0 -19
  174. package/template/prisma-advanced/src/app/(app)/roles/[id]/actions.ts +0 -100
  175. package/template/prisma-advanced/src/app/(app)/roles/[id]/page.tsx +0 -36
  176. package/template/prisma-advanced/src/app/(app)/roles/[id]/render.tsx +0 -266
  177. package/template/prisma-advanced/src/app/(app)/roles/actions.ts +0 -67
  178. package/template/prisma-advanced/src/app/(app)/roles/page.tsx +0 -51
  179. package/template/prisma-advanced/src/app/(app)/roles/render.tsx +0 -70
  180. package/template/prisma-advanced/src/app/(app)/settings/actions.ts +0 -18
  181. package/template/prisma-advanced/src/app/(app)/settings/loading.tsx +0 -28
  182. package/template/prisma-advanced/src/app/(app)/settings/page.tsx +0 -28
  183. package/template/prisma-advanced/src/app/(app)/settings/render.tsx +0 -113
  184. package/template/prisma-advanced/src/app/(app)/tasks/[id]/actions.ts +0 -147
  185. package/template/prisma-advanced/src/app/(app)/tasks/[id]/page.tsx +0 -55
  186. package/template/prisma-advanced/src/app/(app)/tasks/[id]/render.tsx +0 -418
  187. package/template/prisma-advanced/src/app/(app)/tasks/actions.ts +0 -69
  188. package/template/prisma-advanced/src/app/(app)/tasks/page.tsx +0 -63
  189. package/template/prisma-advanced/src/app/(app)/tasks/render.tsx +0 -114
  190. package/template/prisma-advanced/src/app/(app)/users/[id]/actions.ts +0 -104
  191. package/template/prisma-advanced/src/app/(app)/users/[id]/page.tsx +0 -39
  192. package/template/prisma-advanced/src/app/(app)/users/[id]/render.tsx +0 -320
  193. package/template/prisma-advanced/src/app/(app)/users/actions.ts +0 -67
  194. package/template/prisma-advanced/src/app/(app)/users/page.tsx +0 -61
  195. package/template/prisma-advanced/src/app/(app)/users/render.tsx +0 -108
  196. package/template/prisma-advanced/src/app/(auth)/layout.tsx +0 -20
  197. package/template/prisma-advanced/src/app/(auth)/login/user-auth-form.tsx +0 -152
  198. package/template/prisma-advanced/src/app/(marketing)/layout.tsx +0 -42
  199. package/template/prisma-advanced/src/app/(marketing)/page.tsx +0 -96
  200. package/template/prisma-advanced/src/app/api/auth/[...nextauth]/route.ts +0 -7
  201. package/template/prisma-advanced/src/app/api/upload/route.ts +0 -36
  202. package/template/prisma-advanced/src/app/favicon.ico +0 -0
  203. package/template/prisma-advanced/src/app/layout.tsx +0 -34
  204. package/template/prisma-advanced/src/components/app-nav-command.tsx +0 -160
  205. package/template/prisma-advanced/src/components/dark-mode-toggle.tsx +0 -43
  206. package/template/prisma-advanced/src/components/data-table/data-table-column-header.tsx +0 -91
  207. package/template/prisma-advanced/src/components/data-table/data-table-faceted-filter.tsx +0 -149
  208. package/template/prisma-advanced/src/components/data-table/data-table-loading.tsx +0 -77
  209. package/template/prisma-advanced/src/components/data-table/data-table-pagination.tsx +0 -94
  210. package/template/prisma-advanced/src/components/data-table/data-table-toolbar.tsx +0 -78
  211. package/template/prisma-advanced/src/components/data-table/data-table-types.ts +0 -17
  212. package/template/prisma-advanced/src/components/data-table/data-table-view-options.tsx +0 -59
  213. package/template/prisma-advanced/src/components/data-table/data-table.tsx +0 -301
  214. package/template/prisma-advanced/src/components/data-table/simple-data-table.tsx +0 -109
  215. package/template/prisma-advanced/src/components/empty-placeholder.tsx +0 -78
  216. package/template/prisma-advanced/src/components/heading.tsx +0 -17
  217. package/template/prisma-advanced/src/components/icons.tsx +0 -85
  218. package/template/prisma-advanced/src/components/main-nav.tsx +0 -64
  219. package/template/prisma-advanced/src/components/shell.tsx +0 -13
  220. package/template/prisma-advanced/src/components/side-nav.tsx +0 -51
  221. package/template/prisma-advanced/src/components/system-info.tsx +0 -36
  222. package/template/prisma-advanced/src/components/theme-provider.tsx +0 -13
  223. package/template/prisma-advanced/src/components/ui/alert-dialog.tsx +0 -141
  224. package/template/prisma-advanced/src/components/ui/avatar.tsx +0 -50
  225. package/template/prisma-advanced/src/components/ui/badge.tsx +0 -36
  226. package/template/prisma-advanced/src/components/ui/checkbox.tsx +0 -30
  227. package/template/prisma-advanced/src/components/ui/command.tsx +0 -155
  228. package/template/prisma-advanced/src/components/ui/dialog.tsx +0 -122
  229. package/template/prisma-advanced/src/components/ui/dropdown-menu.tsx +0 -200
  230. package/template/prisma-advanced/src/components/ui/popover.tsx +0 -31
  231. package/template/prisma-advanced/src/components/ui/select.tsx +0 -160
  232. package/template/prisma-advanced/src/components/ui/skeleton.tsx +0 -15
  233. package/template/prisma-advanced/src/components/ui/table.tsx +0 -117
  234. package/template/prisma-advanced/src/components/ui/textarea.tsx +0 -24
  235. package/template/prisma-advanced/src/components/ui/toast.tsx +0 -127
  236. package/template/prisma-advanced/src/components/ui/toaster.tsx +0 -35
  237. package/template/prisma-advanced/src/components/ui/use-toast.ts +0 -189
  238. package/template/prisma-advanced/src/components/user-account-nav.tsx +0 -60
  239. package/template/prisma-advanced/src/components/user-avatar.tsx +0 -25
  240. package/template/prisma-advanced/src/env.mjs +0 -78
  241. package/template/prisma-advanced/src/hooks/use-debounce.ts +0 -17
  242. package/template/prisma-advanced/src/hooks/use-lock-body.tsx +0 -12
  243. package/template/prisma-advanced/src/lib/auth.ts +0 -180
  244. package/template/prisma-advanced/src/lib/cn.ts +0 -4
  245. package/template/prisma-advanced/src/lib/db.ts +0 -20
  246. package/template/prisma-advanced/src/lib/delay.ts +0 -2
  247. package/template/prisma-advanced/src/lib/formatDate.ts +0 -11
  248. package/template/prisma-advanced/src/lib/generateLabel.ts +0 -5
  249. package/template/prisma-advanced/src/lib/siteConfig.ts +0 -4
  250. package/template/prisma-advanced/src/lib/storageClient.ts +0 -11
  251. package/template/prisma-advanced/src/styles/editor.css +0 -61
  252. package/template/prisma-advanced/src/types/UnwrapPromise.ts +0 -1
  253. package/template/prisma-advanced/tailwind.config.ts +0 -80
  254. package/template/{new → base}/next.config.ts +0 -0
  255. package/template/{new → base}/public/placeholder.svg +0 -0
  256. package/template/{new → base}/src/app/(auth)/login/email-login-form.tsx +0 -0
  257. package/template/{new → base}/src/app/(auth)/login/social-login-buttons.tsx +0 -0
  258. package/template/{new → base}/src/app/api/auth/[...all]/route.ts +0 -0
  259. package/template/{new → base}/src/components/loader.tsx +0 -0
  260. package/template/{new → base}/src/components/react-query-provider.tsx +0 -0
  261. package/template/{new → base}/src/components/screen-size.tsx +0 -0
  262. package/template/{new → base}/src/components/theme-toggle.tsx +0 -0
  263. package/template/{new → base}/src/lib/toast-message.ts +0 -0
  264. package/template/{base → old}/.eslintrc.cjs +0 -0
  265. package/template/{base → old}/next.config.mjs +0 -0
  266. package/template/{new → old}/prettier.config.mjs +0 -0
  267. package/template/{base → old}/public/next.svg +0 -0
  268. package/template/{base → old}/public/vercel.svg +0 -0
  269. package/template/{base → old}/src/app/(app)/dashboard/layout.tsx +0 -0
  270. package/template/{base → old}/src/app/(app)/dashboard/page.tsx +0 -0
  271. package/template/{base → old}/src/app/(app)/roles/[id]/actions.ts +0 -0
  272. package/template/{base → old}/src/app/(app)/roles/[id]/page.tsx +0 -0
  273. package/template/{base → old}/src/app/(app)/roles/[id]/render.tsx +0 -0
  274. package/template/{base → old}/src/app/(app)/roles/[id]/validation.ts +0 -0
  275. package/template/{base → old}/src/app/(app)/roles/actions.ts +0 -0
  276. package/template/{base → old}/src/app/(app)/roles/page.tsx +0 -0
  277. package/template/{base → old}/src/app/(app)/roles/render.tsx +0 -0
  278. package/template/{base → old}/src/app/(app)/settings/actions.ts +0 -0
  279. package/template/{base → old}/src/app/(app)/settings/layout.tsx +0 -0
  280. package/template/{base → old}/src/app/(app)/settings/loading.tsx +0 -0
  281. package/template/{base → old}/src/app/(app)/settings/page.tsx +0 -0
  282. package/template/{base → old}/src/app/(app)/settings/render.tsx +0 -0
  283. package/template/{base → old}/src/app/(app)/settings/validation.ts +0 -0
  284. package/template/{base → old}/src/app/(app)/tasks/[id]/actions.ts +0 -0
  285. package/template/{base → old}/src/app/(app)/tasks/[id]/page.tsx +0 -0
  286. package/template/{base → old}/src/app/(app)/tasks/[id]/render.tsx +0 -0
  287. package/template/{base → old}/src/app/(app)/tasks/[id]/validation.ts +0 -0
  288. package/template/{base → old}/src/app/(app)/tasks/actions.ts +0 -0
  289. package/template/{base → old}/src/app/(app)/tasks/page.tsx +0 -0
  290. package/template/{base → old}/src/app/(app)/tasks/render.tsx +0 -0
  291. package/template/{base → old}/src/app/(app)/tasks/statusEnum.ts +0 -0
  292. package/template/{base → old}/src/app/(app)/users/[id]/actions.ts +0 -0
  293. package/template/{base → old}/src/app/(app)/users/[id]/page.tsx +0 -0
  294. package/template/{base → old}/src/app/(app)/users/[id]/render.tsx +0 -0
  295. package/template/{base → old}/src/app/(app)/users/[id]/validation.ts +0 -0
  296. package/template/{base → old}/src/app/(app)/users/actions.ts +0 -0
  297. package/template/{base → old}/src/app/(app)/users/page.tsx +0 -0
  298. package/template/{base → old}/src/app/(app)/users/render.tsx +0 -0
  299. package/template/{base → old}/src/app/(auth)/layout.tsx +0 -0
  300. package/template/{base → old}/src/app/(auth)/login/render.tsx +0 -0
  301. package/template/{prisma → old}/src/app/(marketing)/layout.tsx +1 -1
  302. /package/template/{base → old}/src/app/api/auth/[...nextauth]/route.ts +0 -0
  303. /package/template/{new → old}/src/app/favicon.ico +0 -0
  304. /package/template/{prisma-advanced/src/styles → old/src/app}/globals.css +0 -0
  305. /package/template/{base → old}/src/components/app-nav-command.tsx +0 -0
  306. /package/template/{base → old}/src/components/dark-mode-toggle.tsx +0 -0
  307. /package/template/{base → old}/src/components/data-table/data-table-column-header.tsx +0 -0
  308. /package/template/{base → old}/src/components/data-table/data-table-faceted-filter.tsx +0 -0
  309. /package/template/{base → old}/src/components/data-table/data-table-loading.tsx +0 -0
  310. /package/template/{base → old}/src/components/data-table/data-table-pagination.tsx +0 -0
  311. /package/template/{base → old}/src/components/data-table/data-table-toolbar.tsx +0 -0
  312. /package/template/{base → old}/src/components/data-table/data-table-types.ts +0 -0
  313. /package/template/{base → old}/src/components/data-table/data-table-view-options.tsx +0 -0
  314. /package/template/{base → old}/src/components/data-table/data-table.tsx +0 -0
  315. /package/template/{base → old}/src/components/data-table/simple-data-table.tsx +0 -0
  316. /package/template/{base → old}/src/components/empty-placeholder.tsx +0 -0
  317. /package/template/{base → old}/src/components/heading.tsx +0 -0
  318. /package/template/{base → old}/src/components/icons.tsx +0 -0
  319. /package/template/{base → old}/src/components/main-nav.tsx +0 -0
  320. /package/template/{base → old}/src/components/mobile-nav.tsx +0 -0
  321. /package/template/{base → old}/src/components/shell.tsx +0 -0
  322. /package/template/{base → old}/src/components/side-nav.tsx +0 -0
  323. /package/template/{prisma-advanced → old}/src/components/site-footer.tsx +0 -0
  324. /package/template/{base → old}/src/components/system-info.tsx +0 -0
  325. /package/template/{base → old}/src/components/ui/alert-dialog.tsx +0 -0
  326. /package/template/{base → old}/src/components/ui/avatar.tsx +0 -0
  327. /package/template/{base → old}/src/components/ui/badge.tsx +0 -0
  328. /package/template/{prisma-advanced → old}/src/components/ui/button.tsx +0 -0
  329. /package/template/{prisma-advanced → old}/src/components/ui/card.tsx +0 -0
  330. /package/template/{base → old}/src/components/ui/checkbox.tsx +0 -0
  331. /package/template/{base → old}/src/components/ui/command.tsx +0 -0
  332. /package/template/{base → old}/src/components/ui/dialog.tsx +0 -0
  333. /package/template/{base → old}/src/components/ui/dropdown-menu.tsx +0 -0
  334. /package/template/{prisma-advanced → old}/src/components/ui/form.tsx +0 -0
  335. /package/template/{prisma-advanced → old}/src/components/ui/input.tsx +0 -0
  336. /package/template/{prisma-advanced → old}/src/components/ui/label.tsx +0 -0
  337. /package/template/{base → old}/src/components/ui/popover.tsx +0 -0
  338. /package/template/{base → old}/src/components/ui/select.tsx +0 -0
  339. /package/template/{prisma-advanced → old}/src/components/ui/separator.tsx +0 -0
  340. /package/template/{base → old}/src/components/ui/skeleton.tsx +0 -0
  341. /package/template/{base → old}/src/components/ui/table.tsx +0 -0
  342. /package/template/{base → old}/src/components/user-account-nav.tsx +0 -0
  343. /package/template/{base → old}/src/components/user-avatar.tsx +0 -0
  344. /package/template/{base → old}/src/data-access/resource.ts +0 -0
  345. /package/template/{base → old}/src/data-access/role-permission.ts +0 -0
  346. /package/template/{base → old}/src/data-access/role.ts +0 -0
  347. /package/template/{base → old}/src/data-access/task.ts +0 -0
  348. /package/template/{base → old}/src/data-access/user.ts +0 -0
  349. /package/template/{base → old}/src/env.mjs +0 -0
  350. /package/template/{base → old}/src/hooks/use-debounce.tsx +0 -0
  351. /package/template/{base → old}/src/hooks/use-lock-body.tsx +0 -0
  352. /package/template/{new → old}/src/lib/cn.ts +0 -0
  353. /package/template/{base → old}/src/lib/currentUser.ts +0 -0
  354. /package/template/{new → old}/src/lib/delay.ts +0 -0
  355. /package/template/{base → old}/src/lib/formatDate.ts +0 -0
  356. /package/template/{base → old}/src/lib/generateLabel.ts +0 -0
  357. /package/template/{base → old}/src/lib/s3Client.ts +0 -0
  358. /package/template/{new → old}/src/lib/siteConfig.ts +0 -0
  359. /package/template/{base → old}/src/lib/sortOrderEnum.ts +0 -0
  360. /package/template/{base → old}/src/use-case/role-permission.ts +0 -0
  361. /package/template/{base → old}/src/use-case/role.ts +0 -0
  362. /package/template/{base → old}/src/use-case/task.ts +0 -0
  363. /package/template/{base → old}/src/use-case/user.ts +0 -0
  364. /package/template/{base → old}/tailwind.config.ts +0 -0
@@ -1,152 +0,0 @@
1
- 'use client'
2
-
3
- import { zodResolver } from '@hookform/resolvers/zod'
4
- import { signIn } from 'next-auth/react'
5
- import { useSearchParams } from 'next/navigation'
6
- import { FC, HTMLAttributes, useState } from 'react'
7
- import { useForm } from 'react-hook-form'
8
- import { z } from 'zod'
9
-
10
- import { Icons } from '@/components/icons'
11
- import { Button } from '@/components/ui/button'
12
- import { Input } from '@/components/ui/input'
13
- import { Label } from '@/components/ui/label'
14
- import { toast } from '@/components/ui/use-toast'
15
- import { cn } from '@/lib/cn'
16
-
17
- const userAuthSchema = z.object({
18
- email: z.string().email()
19
- })
20
-
21
- type FormData = z.infer<typeof userAuthSchema>
22
-
23
- interface UserAuthFormProps extends HTMLAttributes<HTMLDivElement> {}
24
-
25
- export const UserAuthForm: FC = ({
26
- className,
27
- ...props
28
- }: UserAuthFormProps) => {
29
- const {
30
- register,
31
- handleSubmit,
32
- formState: { errors }
33
- } = useForm<FormData>({
34
- resolver: zodResolver(userAuthSchema)
35
- })
36
- const [isLoading, setIsLoading] = useState(false)
37
- const [isGoogleLoading, setIsGoogleLoading] = useState(false)
38
- const [isGithubLoading, setIsGithubLoading] = useState(false)
39
-
40
- const searchParams = useSearchParams()
41
-
42
- async function onSubmit(data: FormData) {
43
- setIsLoading(true)
44
-
45
- const signInResult = await signIn('email', {
46
- email: data.email.toLowerCase(),
47
- redirect: false,
48
- callbackUrl: searchParams?.get('from') || '/dashboard'
49
- })
50
-
51
- setIsLoading(false)
52
-
53
- if (!signInResult?.ok) {
54
- return toast({
55
- title: 'Something went wrong.',
56
- description: 'Your sign in request failed. Please try again.',
57
- variant: 'destructive'
58
- })
59
- }
60
-
61
- return toast({
62
- title: 'Check your email',
63
- description: 'We sent you a login link. Be sure to check your spam too.'
64
- })
65
- }
66
-
67
- return (
68
- <div className={cn('grid gap-6', className)} {...props}>
69
- <form onSubmit={handleSubmit(onSubmit)}>
70
- <div className="grid gap-2">
71
- <div className="grid gap-1">
72
- <Label className="sr-only" htmlFor="email">
73
- Email
74
- </Label>
75
- <Input
76
- id="email"
77
- placeholder="name@example.com"
78
- type="email"
79
- autoCapitalize="none"
80
- autoComplete="email"
81
- autoCorrect="off"
82
- disabled={isLoading}
83
- {...register('email')}
84
- />
85
- {errors?.email && (
86
- <p className="px-1 text-xs text-red-600">
87
- {errors.email.message}
88
- </p>
89
- )}
90
- </div>
91
- <Button
92
- disabled={isLoading || isGoogleLoading || isGithubLoading}
93
- type="submit"
94
- >
95
- {isLoading && (
96
- <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
97
- )}
98
- Sign in with Email
99
- </Button>
100
- </div>
101
- </form>
102
- <div className="relative">
103
- <div className="absolute inset-0 flex items-center">
104
- <span className="w-full border-t" />
105
- </div>
106
- <div className="relative flex justify-center text-xs uppercase">
107
- <span className="bg-background px-2 text-muted-foreground">
108
- Or continue with
109
- </span>
110
- </div>
111
- </div>
112
- <div className="grid gap-2">
113
- <Button
114
- variant="outline"
115
- onClick={async () => {
116
- setIsGoogleLoading(true)
117
- await signIn('google', {
118
- callbackUrl: searchParams?.get('from') || '/dashboard'
119
- })
120
- setIsGoogleLoading(false)
121
- }}
122
- disabled={isLoading || isGoogleLoading || isGithubLoading}
123
- >
124
- {isGoogleLoading ? (
125
- <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
126
- ) : (
127
- <Icons.google className="mr-2 h-4 w-4" />
128
- )}
129
- Google
130
- </Button>
131
- <Button
132
- variant="outline"
133
- onClick={async () => {
134
- setIsGithubLoading(true)
135
- await signIn('github', {
136
- callbackUrl: searchParams?.get('from') || '/dashboard'
137
- })
138
- setIsGithubLoading(false)
139
- }}
140
- disabled={isLoading || isGoogleLoading || isGithubLoading}
141
- >
142
- {isGithubLoading ? (
143
- <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
144
- ) : (
145
- <Icons.github className="mr-2 h-4 w-4" />
146
- )}
147
- Github
148
- </Button>
149
- </div>
150
- </div>
151
- )
152
- }
@@ -1,7 +0,0 @@
1
- import NextAuth from 'next-auth'
2
-
3
- import { authOptions } from '@/lib/auth'
4
-
5
- const handler = NextAuth(authOptions)
6
-
7
- export { handler as GET, handler as POST }
@@ -1,36 +0,0 @@
1
- import { NextRequest, NextResponse } from 'next/server'
2
-
3
- import { getAuthSession } from '@/lib/auth'
4
- import { prisma } from '@/lib/db'
5
- import { storageClient } from '@/lib/storageClient'
6
-
7
- export async function POST(request: NextRequest) {
8
- const session = await getAuthSession()
9
- if (!session)
10
- return NextResponse.json({
11
- success: false
12
- })
13
-
14
- const data = await request.formData()
15
- const file: File | null = data.get('file') as unknown as File
16
-
17
- if (!file) return NextResponse.json({ success: false })
18
-
19
- const bytes = await file.arrayBuffer()
20
- const buffer = Buffer.from(bytes)
21
-
22
- const filename = `${Date.now()}-${Math.random()}-${file.name}`
23
- const url = await storageClient.addFile({
24
- filename,
25
- data: buffer
26
- })
27
- const { id } = await prisma.resource.create({
28
- data: {
29
- newFilename: filename,
30
- originalFilename: file.name,
31
- url
32
- }
33
- })
34
-
35
- return NextResponse.json({ success: true, id, url })
36
- }
Binary file
@@ -1,34 +0,0 @@
1
- import { Analytics } from '@vercel/analytics/react'
2
- import { SpeedInsights } from '@vercel/speed-insights/next'
3
- import { Metadata } from 'next'
4
- import { Inter } from 'next/font/google'
5
- import { ReactNode } from 'react'
6
-
7
- import { ThemeProvider } from '@/components/theme-provider'
8
- import { Toaster } from '@/components/ui/toaster'
9
- import { siteConfig } from '@/lib/siteConfig'
10
- import '@/styles/globals.css'
11
-
12
- const inter = Inter({ subsets: ['latin'] })
13
-
14
- export const metadata: Metadata = {
15
- title: siteConfig.name,
16
- description: siteConfig.description
17
- }
18
-
19
- const RootLayout = ({ children }: { children: ReactNode }) => {
20
- return (
21
- <html lang="en" suppressHydrationWarning>
22
- <body className={inter.className}>
23
- <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
24
- {children}
25
- <Analytics />
26
- <SpeedInsights />
27
- <Toaster />
28
- </ThemeProvider>
29
- </body>
30
- </html>
31
- )
32
- }
33
-
34
- export default RootLayout
@@ -1,160 +0,0 @@
1
- 'use client'
2
-
3
- // import debounce from 'lodash/debounce'
4
- import { signOut } from 'next-auth/react'
5
- import { useTheme } from 'next-themes'
6
- import { useRouter } from 'next/navigation'
7
- import { FC, useCallback, useEffect, useState } from 'react'
8
-
9
- import { Icons } from '@/components/icons'
10
- import { Button } from '@/components/ui/button'
11
- import {
12
- Command,
13
- CommandDialog,
14
- CommandEmpty,
15
- CommandGroup,
16
- CommandInput,
17
- CommandItem,
18
- CommandList,
19
- CommandSeparator
20
- } from '@/components/ui/command'
21
- // import { doSearch, type SearchResult } from '../app/(app)/actions/doSearch'
22
-
23
- export const AppNavCommand: FC<{
24
- modules: {
25
- task: boolean
26
- }
27
- }> = ({ modules }) => {
28
- const [open, setOpen] = useState(false)
29
- // const [search, setSearch] = useState('')
30
- // const [searchResults, setSearchResults] = useState<SearchResult[]>([])
31
- const { setTheme } = useTheme()
32
- const router = useRouter()
33
-
34
- useEffect(() => {
35
- const down = (e: KeyboardEvent) => {
36
- if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
37
- e.preventDefault()
38
- setOpen(open => !open)
39
- }
40
- }
41
-
42
- document.addEventListener('keydown', down)
43
- return () => document.removeEventListener('keydown', down)
44
- }, [])
45
-
46
- // useEffect(() => {
47
- // if (!search) {
48
- // setSearchResults([])
49
- // return
50
- // }
51
- // doSearch(search).then(results => setSearchResults(results))
52
- // }, [search])
53
-
54
- const runCommand = useCallback((command: () => unknown) => {
55
- setOpen(false)
56
- command()
57
- }, [])
58
-
59
- // const debouncedSearch = useMemo(
60
- // () =>
61
- // debounce((search: string) => {
62
- // setSearch(search)
63
- // }, 500),
64
- // []
65
- // )
66
-
67
- return (
68
- <>
69
- <Button
70
- variant="outline"
71
- className="relative w-36 justify-start text-sm text-muted-foreground lg:w-64"
72
- onClick={() => setOpen(true)}
73
- >
74
- <span className="truncate">Command Menu</span>
75
- <kbd className="pointer-events-none absolute right-2 top-2 hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 lg:flex">
76
- <span className="text-xs">⌘</span>K
77
- </kbd>
78
- </Button>
79
- <CommandDialog open={open} onOpenChange={setOpen}>
80
- <Command>
81
- <CommandInput
82
- placeholder="Search..."
83
- // onChangeCapture={e => {
84
- // debouncedSearch((e.target as any)?.value || '')
85
- // }}
86
- />
87
- <CommandList>
88
- <CommandEmpty>No search results found.</CommandEmpty>
89
- <CommandGroup heading="Suggestions">
90
- <CommandItem
91
- onSelect={() => runCommand(() => router.push('/dashboard'))}
92
- >
93
- <Icons.dashboard className="mr-2 h-4 w-4" />
94
- Dashboard
95
- </CommandItem>
96
- {modules.task ? (
97
- <CommandItem
98
- onSelect={() => runCommand(() => router.push('/tasks'))}
99
- >
100
- <Icons.task className="mr-2 h-4 w-4" />
101
- Tasks
102
- </CommandItem>
103
- ) : undefined}
104
- </CommandGroup>
105
- <CommandGroup heading="Account">
106
- <CommandItem
107
- onSelect={() => runCommand(() => router.push('/settings'))}
108
- >
109
- <Icons.settings className="mr-2 h-4 w-4" />
110
- Settings
111
- </CommandItem>
112
- <CommandItem
113
- onSelect={() =>
114
- runCommand(() =>
115
- signOut({
116
- callbackUrl: `${window.location.origin}/login`
117
- })
118
- )
119
- }
120
- >
121
- <Icons.logout className="mr-2 h-4 w-4" />
122
- Sign Out
123
- </CommandItem>
124
- </CommandGroup>
125
- <CommandSeparator />
126
- <CommandGroup heading="Theme">
127
- <CommandItem onSelect={() => runCommand(() => setTheme('light'))}>
128
- <Icons.sun className="mr-2 h-4 w-4" />
129
- Light
130
- </CommandItem>
131
- <CommandItem onSelect={() => runCommand(() => setTheme('dark'))}>
132
- <Icons.moon className="mr-2 h-4 w-4" />
133
- Dark
134
- </CommandItem>
135
- <CommandItem
136
- onSelect={() => runCommand(() => setTheme('system'))}
137
- >
138
- <Icons.laptop className="mr-2 h-4 w-4" />
139
- System
140
- </CommandItem>
141
- </CommandGroup>
142
- {/* {searchResults.length ? (
143
- <CommandGroup heading="Search Results">
144
- {searchResults.map((sr, i) => (
145
- <CommandItem
146
- key={i}
147
- onSelect={() => runCommand(() => router.push(sr.link))}
148
- value={sr.id}
149
- >
150
- {sr.title}
151
- </CommandItem>
152
- ))}
153
- </CommandGroup>
154
- ) : undefined} */}
155
- </CommandList>
156
- </Command>
157
- </CommandDialog>
158
- </>
159
- )
160
- }
@@ -1,43 +0,0 @@
1
- 'use client'
2
-
3
- import { useTheme } from 'next-themes'
4
- import { FC } from 'react'
5
-
6
- import { Icons } from '@/components/icons'
7
- import { Button } from '@/components/ui/button'
8
- import {
9
- DropdownMenu,
10
- DropdownMenuContent,
11
- DropdownMenuItem,
12
- DropdownMenuTrigger
13
- } from '@/components/ui/dropdown-menu'
14
-
15
- export const DarkModeToggle: FC = () => {
16
- const { setTheme } = useTheme()
17
-
18
- return (
19
- <DropdownMenu>
20
- <DropdownMenuTrigger asChild>
21
- <Button variant="ghost" size="icon">
22
- <Icons.sun className="rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
23
- <Icons.moon className="absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
24
- <span className="sr-only">Toggle theme</span>
25
- </Button>
26
- </DropdownMenuTrigger>
27
- <DropdownMenuContent align="end">
28
- <DropdownMenuItem onClick={() => setTheme('light')}>
29
- <Icons.sun className="mr-2 h-4 w-4" />
30
- <span>Light</span>
31
- </DropdownMenuItem>
32
- <DropdownMenuItem onClick={() => setTheme('dark')}>
33
- <Icons.moon className="mr-2 h-4 w-4" />
34
- <span>Dark</span>
35
- </DropdownMenuItem>
36
- <DropdownMenuItem onClick={() => setTheme('system')}>
37
- <Icons.laptop className="mr-2 h-4 w-4" />
38
- <span>System</span>
39
- </DropdownMenuItem>
40
- </DropdownMenuContent>
41
- </DropdownMenu>
42
- )
43
- }
@@ -1,91 +0,0 @@
1
- import { type Column } from '@tanstack/react-table'
2
-
3
- import { Icons } from '@/components/icons'
4
- import { Button } from '@/components/ui/button'
5
- import {
6
- DropdownMenu,
7
- DropdownMenuContent,
8
- DropdownMenuItem,
9
- DropdownMenuSeparator,
10
- DropdownMenuTrigger
11
- } from '@/components/ui/dropdown-menu'
12
- import { cn } from '@/lib/cn'
13
-
14
- interface DataTableColumnHeaderProps<TData, TValue>
15
- extends React.HTMLAttributes<HTMLDivElement> {
16
- column: Column<TData, TValue>
17
- title: string
18
- }
19
-
20
- export function DataTableColumnHeader<TData, TValue>({
21
- column,
22
- title,
23
- className
24
- }: DataTableColumnHeaderProps<TData, TValue>) {
25
- if (!column.getCanSort()) {
26
- return <div className={cn(className)}>{title}</div>
27
- }
28
-
29
- return (
30
- <div className={cn('flex items-center space-x-2', className)}>
31
- <DropdownMenu>
32
- <DropdownMenuTrigger asChild>
33
- <Button
34
- aria-label={
35
- column.getIsSorted() === 'desc'
36
- ? `Sorted descending. Click to sort ascending.`
37
- : column.getIsSorted() === 'asc'
38
- ? `Sorted ascending. Click to sort descending.`
39
- : `Not sorted. Click to sort ascending.`
40
- }
41
- variant="ghost"
42
- size="sm"
43
- className="-ml-3 h-8 data-[state=open]:bg-accent"
44
- >
45
- <span>{title}</span>
46
- {column.getIsSorted() === 'desc' ? (
47
- <Icons.arrowDown className="ml-2 h-4 w-4" aria-hidden="true" />
48
- ) : column.getIsSorted() === 'asc' ? (
49
- <Icons.arrowUp className="ml-2 h-4 w-4" aria-hidden="true" />
50
- ) : (
51
- <Icons.arrowUpDown className="ml-2 h-4 w-4" aria-hidden="true" />
52
- )}
53
- </Button>
54
- </DropdownMenuTrigger>
55
- <DropdownMenuContent align="start">
56
- <DropdownMenuItem
57
- aria-label="Sort ascending"
58
- onClick={() => column.toggleSorting(false)}
59
- >
60
- <Icons.arrowUp
61
- className="mr-2 h-3.5 w-3.5 text-muted-foreground/70"
62
- aria-hidden="true"
63
- />
64
- Asc
65
- </DropdownMenuItem>
66
- <DropdownMenuItem
67
- aria-label="Sort descending"
68
- onClick={() => column.toggleSorting(true)}
69
- >
70
- <Icons.arrowDown
71
- className="mr-2 h-3.5 w-3.5 text-muted-foreground/70"
72
- aria-hidden="true"
73
- />
74
- Desc
75
- </DropdownMenuItem>
76
- <DropdownMenuSeparator />
77
- <DropdownMenuItem
78
- aria-label="Hide column"
79
- onClick={() => column.toggleVisibility(false)}
80
- >
81
- <Icons.eyeOff
82
- className="mr-2 h-3.5 w-3.5 text-muted-foreground/70"
83
- aria-hidden="true"
84
- />
85
- Hide
86
- </DropdownMenuItem>
87
- </DropdownMenuContent>
88
- </DropdownMenu>
89
- </div>
90
- )
91
- }
@@ -1,149 +0,0 @@
1
- import { type Column } from '@tanstack/react-table'
2
- import { ComponentType } from 'react'
3
-
4
- import { Icons } from '@/components/icons'
5
- import { Badge } from '@/components/ui/badge'
6
- import { Button } from '@/components/ui/button'
7
- import {
8
- Command,
9
- CommandEmpty,
10
- CommandGroup,
11
- CommandInput,
12
- CommandItem,
13
- CommandList,
14
- CommandSeparator
15
- } from '@/components/ui/command'
16
- import {
17
- Popover,
18
- PopoverContent,
19
- PopoverTrigger
20
- } from '@/components/ui/popover'
21
- import { Separator } from '@/components/ui/separator'
22
- import { cn } from '@/lib/cn'
23
-
24
- export type FilterOption = {
25
- label: string
26
- value: string
27
- icon?: ComponentType<{ className?: string }>
28
- }
29
-
30
- interface DataTableFacetedFilter<TData, TValue> {
31
- column?: Column<TData, TValue>
32
- title?: string
33
- options: FilterOption[]
34
- }
35
-
36
- export function DataTableFacetedFilter<TData, TValue>({
37
- column,
38
- title,
39
- options
40
- }: DataTableFacetedFilter<TData, TValue>) {
41
- const selectedValues = new Set(column?.getFilterValue() as string[])
42
-
43
- return (
44
- <Popover>
45
- <PopoverTrigger asChild>
46
- <Button variant="outline" size="sm" className="h-8 border-dashed">
47
- <Icons.plusCircle className="mr-2 h-4 w-4" />
48
- {title}
49
- {selectedValues?.size > 0 && (
50
- <>
51
- <Separator orientation="vertical" className="mx-2 h-4" />
52
- <Badge
53
- variant="secondary"
54
- className="rounded-sm px-1 font-normal lg:hidden"
55
- >
56
- {selectedValues.size}
57
- </Badge>
58
- <div className="hidden space-x-1 lg:flex">
59
- {selectedValues.size > 2 ? (
60
- <Badge
61
- variant="secondary"
62
- className="rounded-sm px-1 font-normal"
63
- >
64
- {selectedValues.size} selected
65
- </Badge>
66
- ) : (
67
- options
68
- .filter(option => selectedValues.has(option.value))
69
- .map(option => (
70
- <Badge
71
- variant="secondary"
72
- key={option.value}
73
- className="rounded-sm px-1 font-normal"
74
- >
75
- {option.label}
76
- </Badge>
77
- ))
78
- )}
79
- </div>
80
- </>
81
- )}
82
- </Button>
83
- </PopoverTrigger>
84
- <PopoverContent className="w-[200px] p-0" align="start">
85
- <Command>
86
- <CommandInput placeholder={title} />
87
- <CommandList>
88
- <CommandEmpty>No results found.</CommandEmpty>
89
- <CommandGroup>
90
- {options.map(option => {
91
- const isSelected = selectedValues.has(option.value)
92
- return (
93
- <CommandItem
94
- key={option.value}
95
- onSelect={() => {
96
- if (isSelected) {
97
- selectedValues.delete(option.value)
98
- } else {
99
- selectedValues.add(option.value)
100
- }
101
- const filterValues = Array.from(selectedValues)
102
- column?.setFilterValue(
103
- filterValues.length ? filterValues : undefined
104
- )
105
- }}
106
- >
107
- <div
108
- className={cn(
109
- 'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
110
- isSelected
111
- ? 'bg-primary text-primary-foreground'
112
- : 'opacity-50 [&_svg]:invisible'
113
- )}
114
- >
115
- <Icons.check
116
- className={cn('h-4 w-4')}
117
- aria-hidden="true"
118
- />
119
- </div>
120
- {option.icon && (
121
- <option.icon
122
- className="mr-2 h-4 w-4 text-muted-foreground"
123
- aria-hidden="true"
124
- />
125
- )}
126
- <span>{option.label}</span>
127
- </CommandItem>
128
- )
129
- })}
130
- </CommandGroup>
131
- {selectedValues.size > 0 && (
132
- <>
133
- <CommandSeparator />
134
- <CommandGroup>
135
- <CommandItem
136
- onSelect={() => column?.setFilterValue(undefined)}
137
- className="justify-center text-center"
138
- >
139
- Clear filters
140
- </CommandItem>
141
- </CommandGroup>
142
- </>
143
- )}
144
- </CommandList>
145
- </Command>
146
- </PopoverContent>
147
- </Popover>
148
- )
149
- }