create-ej-app 3.2.0 → 4.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 (276) hide show
  1. package/cli.js +5 -1
  2. package/cli.ts +40 -33
  3. package/package.json +4 -4
  4. package/template/base/.env.example +10 -9
  5. package/template/base/.eslintrc.cjs +17 -15
  6. package/template/base/components.json +1 -1
  7. package/template/base/drizzle.config.ts +11 -0
  8. package/template/base/next.config.mjs +1 -12
  9. package/template/base/package.json +63 -56
  10. package/template/base/postcss.config.mjs +8 -0
  11. package/template/base/prettier.config.mjs +11 -0
  12. package/template/base/public/vercel.svg +1 -0
  13. package/template/base/src/app/(app)/dashboard/layout.tsx +14 -0
  14. package/template/base/src/app/(app)/dashboard/page.tsx +0 -7
  15. package/template/base/src/app/(app)/layout.tsx +55 -20
  16. package/template/base/src/app/(app)/roles/[id]/actions.ts +59 -0
  17. package/template/base/src/app/(app)/roles/[id]/page.tsx +46 -0
  18. package/template/base/src/app/(app)/roles/[id]/render.tsx +264 -0
  19. package/template/base/src/app/(app)/roles/[id]/validation.ts +22 -0
  20. package/template/base/src/app/(app)/roles/actions.ts +33 -0
  21. package/template/base/src/app/(app)/roles/page.tsx +52 -0
  22. package/template/base/src/app/(app)/roles/render.tsx +80 -0
  23. package/template/base/src/app/(app)/settings/actions.ts +11 -12
  24. package/template/base/src/app/(app)/settings/layout.tsx +14 -0
  25. package/template/base/src/app/(app)/settings/page.tsx +1 -10
  26. package/template/base/src/app/(app)/settings/render.tsx +11 -17
  27. package/template/base/src/app/(app)/settings/validation.ts +5 -0
  28. package/template/base/src/app/(app)/tasks/[id]/actions.ts +69 -124
  29. package/template/base/src/app/(app)/tasks/[id]/page.tsx +37 -3
  30. package/template/base/src/app/(app)/tasks/[id]/render.tsx +162 -93
  31. package/template/base/src/app/(app)/tasks/[id]/validation.ts +18 -0
  32. package/template/base/src/app/(app)/tasks/actions.ts +34 -64
  33. package/template/base/src/app/(app)/tasks/page.tsx +15 -9
  34. package/template/base/src/app/(app)/tasks/render.tsx +28 -6
  35. package/template/base/src/app/(app)/tasks/statusEnum.ts +3 -0
  36. package/template/base/src/app/(app)/users/[id]/actions.ts +47 -62
  37. package/template/base/src/app/(app)/users/[id]/page.tsx +15 -8
  38. package/template/base/src/app/(app)/users/[id]/render.tsx +119 -34
  39. package/template/base/src/app/(app)/users/[id]/validation.ts +18 -0
  40. package/template/base/src/app/(app)/users/actions.ts +28 -49
  41. package/template/base/src/app/(app)/users/page.tsx +22 -9
  42. package/template/base/src/app/(app)/users/render.tsx +47 -3
  43. package/template/base/src/app/(auth)/layout.tsx +7 -0
  44. package/template/base/src/app/(auth)/login/page.tsx +2 -2
  45. package/template/base/src/app/(auth)/login/render.tsx +146 -0
  46. package/template/base/src/app/(marketing)/layout.tsx +1 -1
  47. package/template/base/src/app/(marketing)/page.tsx +8 -7
  48. package/template/base/src/app/favicon.ico +0 -0
  49. package/template/base/src/app/layout.tsx +14 -17
  50. package/template/base/src/components/app-nav-command.tsx +18 -0
  51. package/template/base/src/components/data-table/data-table-column-header.tsx +2 -2
  52. package/template/base/src/components/icons.tsx +21 -5
  53. package/template/base/src/components/ui/alert-dialog.tsx +1 -1
  54. package/template/base/src/components/ui/command.tsx +1 -1
  55. package/template/base/src/components/ui/dialog.tsx +1 -1
  56. package/template/base/src/components/ui/sonner.tsx +31 -0
  57. package/template/base/src/components/user-avatar.tsx +4 -2
  58. package/template/base/src/data-access/resource.ts +85 -0
  59. package/template/base/src/data-access/role-permission.ts +45 -0
  60. package/template/base/src/data-access/role.ts +105 -0
  61. package/template/base/src/data-access/task.ts +141 -0
  62. package/template/base/src/data-access/user.ts +141 -0
  63. package/template/base/src/db/index.ts +14 -0
  64. package/template/base/src/db/schema.ts +287 -0
  65. package/template/base/src/env.mjs +10 -30
  66. package/template/base/src/hooks/use-lock-body.tsx +2 -1
  67. package/template/base/src/lib/auth.ts +32 -23
  68. package/template/base/src/lib/currentUser.ts +8 -0
  69. package/template/base/src/lib/s3Client.ts +156 -0
  70. package/template/base/src/lib/safe-action.ts +19 -0
  71. package/template/base/src/lib/sortOrderEnum.ts +2 -0
  72. package/template/base/src/use-case/role-permission.ts +19 -0
  73. package/template/base/src/use-case/role.ts +110 -0
  74. package/template/base/src/use-case/task.ts +166 -0
  75. package/template/base/src/use-case/user.ts +121 -0
  76. package/template/base/tailwind.config.ts +5 -4
  77. package/template/base/tsconfig.json +3 -2
  78. package/template/prisma/.env.example +16 -0
  79. package/template/prisma/.eslintrc.cjs +24 -0
  80. package/template/prisma/components.json +17 -0
  81. package/template/prisma/next.config.mjs +15 -0
  82. package/template/prisma/package.json +80 -0
  83. package/template/prisma/public/next.svg +1 -0
  84. package/template/prisma/src/app/(app)/dashboard/page.tsx +19 -0
  85. package/template/prisma/src/app/(app)/layout.tsx +90 -0
  86. package/template/prisma/src/app/(app)/settings/actions.ts +18 -0
  87. package/template/prisma/src/app/(app)/settings/loading.tsx +28 -0
  88. package/template/prisma/src/app/(app)/settings/page.tsx +28 -0
  89. package/template/prisma/src/app/(app)/settings/render.tsx +113 -0
  90. package/template/prisma/src/app/(app)/tasks/[id]/actions.ts +147 -0
  91. package/template/prisma/src/app/(app)/tasks/[id]/page.tsx +25 -0
  92. package/template/prisma/src/app/(app)/tasks/[id]/render.tsx +413 -0
  93. package/template/prisma/src/app/(app)/tasks/actions.ts +69 -0
  94. package/template/prisma/src/app/(app)/tasks/page.tsx +53 -0
  95. package/template/prisma/src/app/(app)/tasks/render.tsx +107 -0
  96. package/template/prisma/src/app/(app)/users/[id]/actions.ts +83 -0
  97. package/template/prisma/src/app/(app)/users/[id]/page.tsx +32 -0
  98. package/template/prisma/src/app/(app)/users/[id]/render.tsx +240 -0
  99. package/template/prisma/src/app/(app)/users/actions.ts +55 -0
  100. package/template/prisma/src/app/(app)/users/page.tsx +49 -0
  101. package/template/prisma/src/app/(app)/users/render.tsx +80 -0
  102. package/template/prisma/src/app/(auth)/layout.tsx +20 -0
  103. package/template/prisma/src/app/(auth)/login/page.tsx +49 -0
  104. package/template/prisma/src/app/(marketing)/layout.tsx +42 -0
  105. package/template/prisma/src/app/(marketing)/page.tsx +96 -0
  106. package/template/prisma/src/app/api/auth/[...nextauth]/route.ts +7 -0
  107. package/template/prisma/src/app/favicon.ico +0 -0
  108. package/template/prisma/src/app/layout.tsx +34 -0
  109. package/template/prisma/src/components/app-nav-command.tsx +160 -0
  110. package/template/prisma/src/components/dark-mode-toggle.tsx +43 -0
  111. package/template/prisma/src/components/data-table/data-table-column-header.tsx +91 -0
  112. package/template/prisma/src/components/data-table/data-table-faceted-filter.tsx +149 -0
  113. package/template/prisma/src/components/data-table/data-table-loading.tsx +77 -0
  114. package/template/prisma/src/components/data-table/data-table-pagination.tsx +94 -0
  115. package/template/prisma/src/components/data-table/data-table-toolbar.tsx +78 -0
  116. package/template/prisma/src/components/data-table/data-table-types.ts +17 -0
  117. package/template/prisma/src/components/data-table/data-table-view-options.tsx +59 -0
  118. package/template/prisma/src/components/data-table/data-table.tsx +301 -0
  119. package/template/prisma/src/components/data-table/simple-data-table.tsx +109 -0
  120. package/template/prisma/src/components/empty-placeholder.tsx +78 -0
  121. package/template/prisma/src/components/heading.tsx +17 -0
  122. package/template/prisma/src/components/icons.tsx +85 -0
  123. package/template/prisma/src/components/main-nav.tsx +64 -0
  124. package/template/prisma/src/components/shell.tsx +13 -0
  125. package/template/prisma/src/components/side-nav.tsx +51 -0
  126. package/template/prisma/src/components/site-footer.tsx +31 -0
  127. package/template/prisma/src/components/system-info.tsx +36 -0
  128. package/template/prisma/src/components/ui/alert-dialog.tsx +141 -0
  129. package/template/prisma/src/components/ui/avatar.tsx +50 -0
  130. package/template/prisma/src/components/ui/badge.tsx +36 -0
  131. package/template/prisma/src/components/ui/button.tsx +56 -0
  132. package/template/prisma/src/components/ui/card.tsx +79 -0
  133. package/template/prisma/src/components/ui/checkbox.tsx +30 -0
  134. package/template/prisma/src/components/ui/command.tsx +155 -0
  135. package/template/prisma/src/components/ui/dialog.tsx +122 -0
  136. package/template/prisma/src/components/ui/dropdown-menu.tsx +200 -0
  137. package/template/prisma/src/components/ui/form.tsx +176 -0
  138. package/template/prisma/src/components/ui/input.tsx +25 -0
  139. package/template/prisma/src/components/ui/label.tsx +26 -0
  140. package/template/prisma/src/components/ui/popover.tsx +31 -0
  141. package/template/prisma/src/components/ui/select.tsx +160 -0
  142. package/template/prisma/src/components/ui/separator.tsx +31 -0
  143. package/template/prisma/src/components/ui/skeleton.tsx +15 -0
  144. package/template/prisma/src/components/ui/table.tsx +117 -0
  145. package/template/prisma/src/components/user-account-nav.tsx +60 -0
  146. package/template/prisma/src/components/user-avatar.tsx +25 -0
  147. package/template/prisma/src/env.mjs +78 -0
  148. package/template/prisma/src/hooks/use-debounce.ts +17 -0
  149. package/template/prisma/src/hooks/use-lock-body.tsx +12 -0
  150. package/template/prisma/src/lib/auth.ts +80 -0
  151. package/template/prisma/src/lib/cn.ts +4 -0
  152. package/template/prisma/src/lib/delay.ts +2 -0
  153. package/template/prisma/src/lib/formatDate.ts +11 -0
  154. package/template/prisma/src/lib/generateLabel.ts +5 -0
  155. package/template/prisma/src/lib/siteConfig.ts +4 -0
  156. package/template/prisma/src/styles/globals.css +76 -0
  157. package/template/prisma/tailwind.config.ts +80 -0
  158. package/template/prisma/tsconfig.json +46 -0
  159. /package/template/{advanced/src/styles → base/src/app}/globals.css +0 -0
  160. /package/template/{advanced/src/hooks/use-debounce.ts → base/src/hooks/use-debounce.tsx} +0 -0
  161. /package/template/{base → prisma}/postcss.config.cjs +0 -0
  162. /package/template/{base → prisma}/prettier.config.ts +0 -0
  163. /package/template/{base → prisma}/prisma/schema.prisma +0 -0
  164. /package/template/{base → prisma}/src/app/(auth)/login/user-auth-form.tsx +0 -0
  165. /package/template/{base → prisma}/src/app/api/upload/route.ts +0 -0
  166. /package/template/{advanced → prisma}/src/components/mobile-nav.tsx +0 -0
  167. /package/template/{base → prisma}/src/components/theme-provider.tsx +0 -0
  168. /package/template/{base → prisma}/src/components/ui/textarea.tsx +0 -0
  169. /package/template/{base → prisma}/src/components/ui/toast.tsx +0 -0
  170. /package/template/{base → prisma}/src/components/ui/toaster.tsx +0 -0
  171. /package/template/{base → prisma}/src/components/ui/use-toast.ts +0 -0
  172. /package/template/{base → prisma}/src/lib/db.ts +0 -0
  173. /package/template/{base → prisma}/src/lib/storageClient.ts +0 -0
  174. /package/template/{base → prisma}/src/styles/editor.css +0 -0
  175. /package/template/{base → prisma}/src/types/UnwrapPromise.ts +0 -0
  176. /package/template/{advanced → prisma-advanced}/.env.example +0 -0
  177. /package/template/{advanced → prisma-advanced}/.eslintrc.cjs +0 -0
  178. /package/template/{advanced → prisma-advanced}/components.json +0 -0
  179. /package/template/{advanced → prisma-advanced}/next.config.mjs +0 -0
  180. /package/template/{advanced → prisma-advanced}/package.json +0 -0
  181. /package/template/{advanced → prisma-advanced}/postcss.config.cjs +0 -0
  182. /package/template/{advanced → prisma-advanced}/prettier.config.ts +0 -0
  183. /package/template/{advanced → prisma-advanced}/prisma/schema.prisma +0 -0
  184. /package/template/{advanced → prisma-advanced}/public/next.svg +0 -0
  185. /package/template/{advanced → prisma-advanced}/src/app/(app)/dashboard/page.tsx +0 -0
  186. /package/template/{advanced → prisma-advanced}/src/app/(app)/layout.tsx +0 -0
  187. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/actions.ts +0 -0
  188. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/page.tsx +0 -0
  189. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/render.tsx +0 -0
  190. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/actions.ts +0 -0
  191. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/page.tsx +0 -0
  192. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/render.tsx +0 -0
  193. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/actions.ts +0 -0
  194. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/loading.tsx +0 -0
  195. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/page.tsx +0 -0
  196. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/render.tsx +0 -0
  197. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/actions.ts +0 -0
  198. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/page.tsx +0 -0
  199. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/render.tsx +0 -0
  200. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/actions.ts +0 -0
  201. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/page.tsx +0 -0
  202. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/render.tsx +0 -0
  203. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/actions.ts +0 -0
  204. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/page.tsx +0 -0
  205. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/render.tsx +0 -0
  206. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/actions.ts +0 -0
  207. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/page.tsx +0 -0
  208. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/render.tsx +0 -0
  209. /package/template/{advanced → prisma-advanced}/src/app/(auth)/layout.tsx +0 -0
  210. /package/template/{advanced → prisma-advanced}/src/app/(auth)/login/page.tsx +0 -0
  211. /package/template/{advanced → prisma-advanced}/src/app/(auth)/login/user-auth-form.tsx +0 -0
  212. /package/template/{advanced → prisma-advanced}/src/app/(marketing)/layout.tsx +0 -0
  213. /package/template/{advanced → prisma-advanced}/src/app/(marketing)/page.tsx +0 -0
  214. /package/template/{advanced → prisma-advanced}/src/app/api/auth/[...nextauth]/route.ts +0 -0
  215. /package/template/{advanced → prisma-advanced}/src/app/api/upload/route.ts +0 -0
  216. /package/template/{advanced → prisma-advanced}/src/app/favicon.ico +0 -0
  217. /package/template/{advanced → prisma-advanced}/src/app/layout.tsx +0 -0
  218. /package/template/{advanced → prisma-advanced}/src/components/app-nav-command.tsx +0 -0
  219. /package/template/{advanced → prisma-advanced}/src/components/dark-mode-toggle.tsx +0 -0
  220. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-column-header.tsx +0 -0
  221. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-faceted-filter.tsx +0 -0
  222. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-loading.tsx +0 -0
  223. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-pagination.tsx +0 -0
  224. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-toolbar.tsx +0 -0
  225. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-types.ts +0 -0
  226. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-view-options.tsx +0 -0
  227. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table.tsx +0 -0
  228. /package/template/{advanced → prisma-advanced}/src/components/data-table/simple-data-table.tsx +0 -0
  229. /package/template/{advanced → prisma-advanced}/src/components/empty-placeholder.tsx +0 -0
  230. /package/template/{advanced → prisma-advanced}/src/components/heading.tsx +0 -0
  231. /package/template/{advanced → prisma-advanced}/src/components/icons.tsx +0 -0
  232. /package/template/{advanced → prisma-advanced}/src/components/main-nav.tsx +0 -0
  233. /package/template/{advanced → prisma-advanced}/src/components/shell.tsx +0 -0
  234. /package/template/{advanced → prisma-advanced}/src/components/side-nav.tsx +0 -0
  235. /package/template/{advanced → prisma-advanced}/src/components/site-footer.tsx +0 -0
  236. /package/template/{advanced → prisma-advanced}/src/components/system-info.tsx +0 -0
  237. /package/template/{advanced → prisma-advanced}/src/components/theme-provider.tsx +0 -0
  238. /package/template/{advanced → prisma-advanced}/src/components/ui/alert-dialog.tsx +0 -0
  239. /package/template/{advanced → prisma-advanced}/src/components/ui/avatar.tsx +0 -0
  240. /package/template/{advanced → prisma-advanced}/src/components/ui/badge.tsx +0 -0
  241. /package/template/{advanced → prisma-advanced}/src/components/ui/button.tsx +0 -0
  242. /package/template/{advanced → prisma-advanced}/src/components/ui/card.tsx +0 -0
  243. /package/template/{advanced → prisma-advanced}/src/components/ui/checkbox.tsx +0 -0
  244. /package/template/{advanced → prisma-advanced}/src/components/ui/command.tsx +0 -0
  245. /package/template/{advanced → prisma-advanced}/src/components/ui/dialog.tsx +0 -0
  246. /package/template/{advanced → prisma-advanced}/src/components/ui/dropdown-menu.tsx +0 -0
  247. /package/template/{advanced → prisma-advanced}/src/components/ui/form.tsx +0 -0
  248. /package/template/{advanced → prisma-advanced}/src/components/ui/input.tsx +0 -0
  249. /package/template/{advanced → prisma-advanced}/src/components/ui/label.tsx +0 -0
  250. /package/template/{advanced → prisma-advanced}/src/components/ui/popover.tsx +0 -0
  251. /package/template/{advanced → prisma-advanced}/src/components/ui/select.tsx +0 -0
  252. /package/template/{advanced → prisma-advanced}/src/components/ui/separator.tsx +0 -0
  253. /package/template/{advanced → prisma-advanced}/src/components/ui/skeleton.tsx +0 -0
  254. /package/template/{advanced → prisma-advanced}/src/components/ui/table.tsx +0 -0
  255. /package/template/{advanced → prisma-advanced}/src/components/ui/textarea.tsx +0 -0
  256. /package/template/{advanced → prisma-advanced}/src/components/ui/toast.tsx +0 -0
  257. /package/template/{advanced → prisma-advanced}/src/components/ui/toaster.tsx +0 -0
  258. /package/template/{advanced → prisma-advanced}/src/components/ui/use-toast.ts +0 -0
  259. /package/template/{advanced → prisma-advanced}/src/components/user-account-nav.tsx +0 -0
  260. /package/template/{advanced → prisma-advanced}/src/components/user-avatar.tsx +0 -0
  261. /package/template/{advanced → prisma-advanced}/src/env.mjs +0 -0
  262. /package/template/{base → prisma-advanced}/src/hooks/use-debounce.ts +0 -0
  263. /package/template/{advanced → prisma-advanced}/src/hooks/use-lock-body.tsx +0 -0
  264. /package/template/{advanced → prisma-advanced}/src/lib/auth.ts +0 -0
  265. /package/template/{advanced → prisma-advanced}/src/lib/cn.ts +0 -0
  266. /package/template/{advanced → prisma-advanced}/src/lib/db.ts +0 -0
  267. /package/template/{advanced → prisma-advanced}/src/lib/delay.ts +0 -0
  268. /package/template/{advanced → prisma-advanced}/src/lib/formatDate.ts +0 -0
  269. /package/template/{advanced → prisma-advanced}/src/lib/generateLabel.ts +0 -0
  270. /package/template/{advanced → prisma-advanced}/src/lib/siteConfig.ts +0 -0
  271. /package/template/{advanced → prisma-advanced}/src/lib/storageClient.ts +0 -0
  272. /package/template/{advanced → prisma-advanced}/src/styles/editor.css +0 -0
  273. /package/template/{base → prisma-advanced}/src/styles/globals.css +0 -0
  274. /package/template/{advanced → prisma-advanced}/src/types/UnwrapPromise.ts +0 -0
  275. /package/template/{advanced → prisma-advanced}/tailwind.config.ts +0 -0
  276. /package/template/{advanced → prisma-advanced}/tsconfig.json +0 -0
@@ -0,0 +1,78 @@
1
+ import { createEnv } from '@t3-oss/env-nextjs'
2
+ import { z } from 'zod'
3
+
4
+ export const env = createEnv({
5
+ /**
6
+ * Specify your server-side environment variables schema here. This way you can ensure the app
7
+ * isn't built with invalid env vars.
8
+ */
9
+ server: {
10
+ NODE_ENV: z.enum(['development', 'test', 'production']),
11
+ DATABASE_URL: z.string().url(),
12
+ NEXTAUTH_SECRET:
13
+ process.env.NODE_ENV === 'production'
14
+ ? z.string().min(1)
15
+ : z.string().min(1).optional(),
16
+ NEXTAUTH_URL: z.preprocess(
17
+ // This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
18
+ // Since NextAuth.js automatically uses the VERCEL_URL if present.
19
+ str => process.env.VERCEL_URL ?? str,
20
+ // VERCEL_URL doesn't include `https` so it cant be validated as a URL
21
+ process.env.VERCEL ? z.string().min(1) : z.string().url()
22
+ ),
23
+ EMAIL_SERVER_HOST: z.string().min(1),
24
+ EMAIL_SERVER_PORT: z.number(),
25
+ EMAIL_SERVER_USER: z.string().min(1),
26
+ EMAIL_SERVER_PASSWORD: z.string().min(1),
27
+ EMAIL_FROM: z.string().email(),
28
+ GOOGLE_ID: z.string().min(1),
29
+ GOOGLE_SECRET: z.string().min(1),
30
+ GITHUB_ID: z.string().min(1),
31
+ GITHUB_SECRET: z.string().min(1),
32
+ FIREBASE_PROJECT_ID: z.string().min(1),
33
+ FIREBASE_PRIVATE_KEY: z.string().min(1),
34
+ FIREBASE_CLIENT_EMAIL: z.string().min(1),
35
+ FIREBASE_STORAGE_BUCKET: z.string().min(1)
36
+ },
37
+
38
+ /**
39
+ * Specify your client-side environment variables schema here. This way you can ensure the app
40
+ * isn't built with invalid env vars. To expose them to the client, prefix them with
41
+ * `NEXT_PUBLIC_`.
42
+ */
43
+ client: {
44
+ // NEXT_PUBLIC_CLIENTVAR: z.string().min(1),
45
+ },
46
+
47
+ /**
48
+ * You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
49
+ * middlewares) or client-side so we need to destruct manually.
50
+ */
51
+ runtimeEnv: {
52
+ NODE_ENV: process.env.NODE_ENV,
53
+ DATABASE_URL: process.env.DATABASE_URL,
54
+ NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
55
+ NEXTAUTH_URL: process.env.NEXTAUTH_URL,
56
+ EMAIL_SERVER_HOST: process.env.EMAIL_SERVER_HOST,
57
+ EMAIL_SERVER_PORT: parseInt(process.env.EMAIL_SERVER_PORT || ''),
58
+ EMAIL_SERVER_USER: process.env.EMAIL_SERVER_USER,
59
+ EMAIL_SERVER_PASSWORD: process.env.EMAIL_SERVER_PASSWORD,
60
+ EMAIL_FROM: process.env.EMAIL_FROM,
61
+ GOOGLE_ID: process.env.GOOGLE_ID,
62
+ GOOGLE_SECRET: process.env.GOOGLE_SECRET,
63
+ GITHUB_ID: process.env.GITHUB_ID,
64
+ GITHUB_SECRET: process.env.GITHUB_SECRET,
65
+ FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
66
+ FIREBASE_PRIVATE_KEY: process.env.FIREBASE_PRIVATE_KEY,
67
+ FIREBASE_CLIENT_EMAIL: process.env.FIREBASE_CLIENT_EMAIL,
68
+ FIREBASE_STORAGE_BUCKET: process.env.FIREBASE_STORAGE_BUCKET
69
+ },
70
+ /**
71
+ * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
72
+ * This is especially useful for Docker builds.
73
+ */
74
+ skipValidation: !!process.env.SKIP_ENV_VALIDATION,
75
+
76
+ // This makes empty strings be treated as undefined
77
+ emptyStringAsUndefined: true
78
+ })
@@ -0,0 +1,17 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useState } from 'react'
4
+
5
+ export function useDebounce<T>(value: T, delay?: number): T {
6
+ const [debouncedValue, setDebouncedValue] = useState<T>(value)
7
+
8
+ useEffect(() => {
9
+ const timer = setTimeout(() => setDebouncedValue(value), delay || 500)
10
+
11
+ return () => {
12
+ clearTimeout(timer)
13
+ }
14
+ }, [value, delay])
15
+
16
+ return debouncedValue
17
+ }
@@ -0,0 +1,12 @@
1
+ import { useLayoutEffect } from 'react'
2
+
3
+ // @see https://usehooks.com/useLockBodyScroll.
4
+ export function useLockBody() {
5
+ useLayoutEffect((): (() => void) => {
6
+ const originalStyle: string = window.getComputedStyle(
7
+ document.body
8
+ ).overflow
9
+ document.body.style.overflow = 'hidden'
10
+ return () => (document.body.style.overflow = originalStyle)
11
+ }, [])
12
+ }
@@ -0,0 +1,80 @@
1
+ import { PrismaAdapter } from '@next-auth/prisma-adapter'
2
+ import { User as PrismaUser } from '@prisma/client'
3
+ import {
4
+ getServerSession,
5
+ type DefaultSession,
6
+ type NextAuthOptions
7
+ } from 'next-auth'
8
+ import EmailProvider from 'next-auth/providers/email'
9
+ import GitHubProvider from 'next-auth/providers/github'
10
+ import GoogleProvider from 'next-auth/providers/google'
11
+
12
+ import { env } from '@/env.mjs'
13
+ import { prisma } from '@/lib/db'
14
+
15
+ /**
16
+ * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
17
+ * object and keep type safety.
18
+ *
19
+ * @see https://next-auth.js.org/getting-started/typescript#module-augmentation
20
+ */
21
+ declare module 'next-auth' {
22
+ interface Session extends DefaultSession {
23
+ user: {
24
+ id: string
25
+ } & DefaultSession['user']
26
+ }
27
+
28
+ interface User extends PrismaUser {}
29
+ }
30
+
31
+ /**
32
+ * Options for NextAuth.js used to configure adapters, providers, callbacks, etc.
33
+ *
34
+ * @see https://next-auth.js.org/configuration/options
35
+ */
36
+ export const authOptions: NextAuthOptions = {
37
+ pages: {
38
+ signIn: '/login'
39
+ },
40
+ callbacks: {
41
+ session({ session, user }) {
42
+ return {
43
+ ...session,
44
+ user: {
45
+ ...session.user,
46
+ id: user.id
47
+ }
48
+ }
49
+ }
50
+ },
51
+ adapter: PrismaAdapter(prisma),
52
+ providers: [
53
+ EmailProvider({
54
+ server: {
55
+ host: env.EMAIL_SERVER_HOST,
56
+ port: env.EMAIL_SERVER_PORT,
57
+ auth: {
58
+ user: env.EMAIL_SERVER_USER,
59
+ pass: env.EMAIL_SERVER_PASSWORD
60
+ }
61
+ },
62
+ from: env.EMAIL_FROM
63
+ }),
64
+ GoogleProvider({
65
+ clientId: env.GOOGLE_ID,
66
+ clientSecret: env.GOOGLE_SECRET
67
+ }),
68
+ GitHubProvider({
69
+ clientId: env.GITHUB_ID,
70
+ clientSecret: env.GITHUB_SECRET
71
+ })
72
+ ]
73
+ }
74
+
75
+ /**
76
+ * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file.
77
+ *
78
+ * @see https://next-auth.js.org/configuration/nextjs
79
+ */
80
+ export const getAuthSession = () => getServerSession(authOptions)
@@ -0,0 +1,4 @@
1
+ import { clsx, type ClassValue } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs))
@@ -0,0 +1,2 @@
1
+ export const delay = (ms: number) =>
2
+ new Promise(resolve => setTimeout(resolve, ms))
@@ -0,0 +1,11 @@
1
+ import dayjs from 'dayjs'
2
+ import relativeTime from 'dayjs/plugin/relativeTime'
3
+
4
+ dayjs.extend(relativeTime)
5
+
6
+ export const formatDate = (date: Date) => dayjs(date).format('DD/MM/YYYY')
7
+
8
+ export const formatDateTime = (date: Date) =>
9
+ dayjs(date).format('DD/MM/YYYY hh:mm:ss A')
10
+
11
+ export const timesAgo = (date: Date) => dayjs(date).fromNow()
@@ -0,0 +1,5 @@
1
+ export const generateLabel = (str: string) =>
2
+ str
3
+ .replaceAll('_', ' ')
4
+ .replaceAll(/([A-Z])/g, ' $1')
5
+ .trim()
@@ -0,0 +1,4 @@
1
+ export const siteConfig = {
2
+ name: 'Project Name',
3
+ description: 'Project Description'
4
+ }
@@ -0,0 +1,76 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 100%;
8
+ --foreground: 0 0% 3.9%;
9
+
10
+ --card: 0 0% 100%;
11
+ --card-foreground: 0 0% 3.9%;
12
+
13
+ --popover: 0 0% 100%;
14
+ --popover-foreground: 0 0% 3.9%;
15
+
16
+ --primary: 0 0% 9%;
17
+ --primary-foreground: 0 0% 98%;
18
+
19
+ --secondary: 0 0% 96.1%;
20
+ --secondary-foreground: 0 0% 9%;
21
+
22
+ --muted: 0 0% 96.1%;
23
+ --muted-foreground: 0 0% 45.1%;
24
+
25
+ --accent: 0 0% 96.1%;
26
+ --accent-foreground: 0 0% 9%;
27
+
28
+ --destructive: 0 84.2% 60.2%;
29
+ --destructive-foreground: 0 0% 98%;
30
+
31
+ --border: 0 0% 89.8%;
32
+ --input: 0 0% 89.8%;
33
+ --ring: 0 0% 3.9%;
34
+
35
+ --radius: 0.5rem;
36
+ }
37
+
38
+ .dark {
39
+ --background: 0 0% 3.9%;
40
+ --foreground: 0 0% 98%;
41
+
42
+ --card: 0 0% 3.9%;
43
+ --card-foreground: 0 0% 98%;
44
+
45
+ --popover: 0 0% 3.9%;
46
+ --popover-foreground: 0 0% 98%;
47
+
48
+ --primary: 0 0% 98%;
49
+ --primary-foreground: 0 0% 9%;
50
+
51
+ --secondary: 0 0% 14.9%;
52
+ --secondary-foreground: 0 0% 98%;
53
+
54
+ --muted: 0 0% 14.9%;
55
+ --muted-foreground: 0 0% 63.9%;
56
+
57
+ --accent: 0 0% 14.9%;
58
+ --accent-foreground: 0 0% 98%;
59
+
60
+ --destructive: 0 62.8% 30.6%;
61
+ --destructive-foreground: 0 0% 98%;
62
+
63
+ --border: 0 0% 14.9%;
64
+ --input: 0 0% 14.9%;
65
+ --ring: 0 0% 83.1%;
66
+ }
67
+ }
68
+
69
+ @layer base {
70
+ * {
71
+ @apply border-border;
72
+ }
73
+ body {
74
+ @apply bg-background text-foreground;
75
+ }
76
+ }
@@ -0,0 +1,80 @@
1
+ import type { Config } from 'tailwindcss'
2
+
3
+ const config = {
4
+ darkMode: ['class'],
5
+ content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
6
+ prefix: '',
7
+ theme: {
8
+ container: {
9
+ center: true,
10
+ padding: '2rem',
11
+ screens: {
12
+ '2xl': '1400px'
13
+ }
14
+ },
15
+ extend: {
16
+ backgroundImage: {
17
+ 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
18
+ 'gradient-conic':
19
+ 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))'
20
+ },
21
+ colors: {
22
+ border: 'hsl(var(--border))',
23
+ input: 'hsl(var(--input))',
24
+ ring: 'hsl(var(--ring))',
25
+ background: 'hsl(var(--background))',
26
+ foreground: 'hsl(var(--foreground))',
27
+ primary: {
28
+ DEFAULT: 'hsl(var(--primary))',
29
+ foreground: 'hsl(var(--primary-foreground))'
30
+ },
31
+ secondary: {
32
+ DEFAULT: 'hsl(var(--secondary))',
33
+ foreground: 'hsl(var(--secondary-foreground))'
34
+ },
35
+ destructive: {
36
+ DEFAULT: 'hsl(var(--destructive))',
37
+ foreground: 'hsl(var(--destructive-foreground))'
38
+ },
39
+ muted: {
40
+ DEFAULT: 'hsl(var(--muted))',
41
+ foreground: 'hsl(var(--muted-foreground))'
42
+ },
43
+ accent: {
44
+ DEFAULT: 'hsl(var(--accent))',
45
+ foreground: 'hsl(var(--accent-foreground))'
46
+ },
47
+ popover: {
48
+ DEFAULT: 'hsl(var(--popover))',
49
+ foreground: 'hsl(var(--popover-foreground))'
50
+ },
51
+ card: {
52
+ DEFAULT: 'hsl(var(--card))',
53
+ foreground: 'hsl(var(--card-foreground))'
54
+ }
55
+ },
56
+ borderRadius: {
57
+ lg: 'var(--radius)',
58
+ md: 'calc(var(--radius) - 2px)',
59
+ sm: 'calc(var(--radius) - 4px)'
60
+ },
61
+ keyframes: {
62
+ 'accordion-down': {
63
+ from: { height: '0' },
64
+ to: { height: 'var(--radix-accordion-content-height)' }
65
+ },
66
+ 'accordion-up': {
67
+ from: { height: 'var(--radix-accordion-content-height)' },
68
+ to: { height: '0' }
69
+ }
70
+ },
71
+ animation: {
72
+ 'accordion-down': 'accordion-down 0.2s ease-out',
73
+ 'accordion-up': 'accordion-up 0.2s ease-out'
74
+ }
75
+ }
76
+ },
77
+ plugins: [require('tailwindcss-animate'), require('@tailwindcss/typography')]
78
+ } satisfies Config
79
+
80
+ export default config
@@ -0,0 +1,46 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
5
+ "allowJs": true,
6
+ "checkJs": true,
7
+ "skipLibCheck": true,
8
+ "strict": true,
9
+ "noImplicitAny": true,
10
+ "strictNullChecks": true,
11
+ "strictFunctionTypes": true,
12
+ "noImplicitThis": true,
13
+ "noUncheckedIndexedAccess": true,
14
+ "noUnusedLocals": true,
15
+ "noUnusedParameters": true,
16
+ "noImplicitReturns": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "forceConsistentCasingInFileNames": true,
19
+ "noEmit": true,
20
+ "esModuleInterop": true,
21
+ "module": "ESNext",
22
+ "moduleResolution": "Bundler",
23
+ "resolveJsonModule": true,
24
+ "isolatedModules": true,
25
+ "jsx": "preserve",
26
+ "incremental": true,
27
+ "plugins": [
28
+ {
29
+ "name": "next"
30
+ }
31
+ ],
32
+ "paths": {
33
+ "@/*": ["./src/*"]
34
+ }
35
+ },
36
+ "include": [
37
+ ".eslintrc.cjs",
38
+ "next-env.d.ts",
39
+ "**/*.ts",
40
+ "**/*.tsx",
41
+ "**/*.cjs",
42
+ "**/*.mjs",
43
+ ".next/types/**/*.ts"
44
+ ],
45
+ "exclude": ["node_modules"]
46
+ }
File without changes
File without changes
File without changes
File without changes
File without changes