create-ej-app 12.0.0 → 14.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 (140) hide show
  1. package/cli.js +5 -4
  2. package/cli.ts +9 -4
  3. package/package.json +1 -1
  4. package/template/base/package.json +9 -15
  5. package/template/base/terraform/artifact-registry.tf +5 -0
  6. package/template/base/terraform/backend-service.tf +13 -0
  7. package/template/base/terraform/cleanup.sh +9 -0
  8. package/template/base/terraform/cloudbuild.tf +70 -0
  9. package/template/base/terraform/cloudrun.tf +68 -0
  10. package/template/base/terraform/database.tf +60 -0
  11. package/template/base/terraform/forwarding-rule.tf +43 -0
  12. package/template/base/terraform/ip-address.tf +11 -0
  13. package/template/base/terraform/network-endpoint-group.tf +11 -0
  14. package/template/base/terraform/network.tf +21 -0
  15. package/template/base/terraform/pre.sh +3 -0
  16. package/template/base/terraform/providers.tf +18 -0
  17. package/template/base/terraform/secret.txt +11 -0
  18. package/template/base/terraform/setup.sh +25 -0
  19. package/template/base/terraform/ssl-certs.tf +32 -0
  20. package/template/base/terraform/target-https-proxy copy.tf +14 -0
  21. package/template/base/terraform/target-https-proxy.tf +14 -0
  22. package/template/base/terraform/terraform.tfvars +4 -0
  23. package/template/base/terraform/url-map.tf +23 -0
  24. package/template/base/terraform/variables.tf +21 -0
  25. package/template/old/.env.example +0 -17
  26. package/template/old/.eslintrc.cjs +0 -26
  27. package/template/old/components.json +0 -17
  28. package/template/old/drizzle.config.ts +0 -11
  29. package/template/old/next.config.mjs +0 -4
  30. package/template/old/package.json +0 -87
  31. package/template/old/postcss.config.mjs +0 -8
  32. package/template/old/prettier.config.mjs +0 -11
  33. package/template/old/public/next.svg +0 -1
  34. package/template/old/public/vercel.svg +0 -1
  35. package/template/old/src/app/(app)/dashboard/layout.tsx +0 -14
  36. package/template/old/src/app/(app)/dashboard/page.tsx +0 -12
  37. package/template/old/src/app/(app)/layout.tsx +0 -125
  38. package/template/old/src/app/(app)/roles/[id]/actions.ts +0 -59
  39. package/template/old/src/app/(app)/roles/[id]/page.tsx +0 -46
  40. package/template/old/src/app/(app)/roles/[id]/render.tsx +0 -264
  41. package/template/old/src/app/(app)/roles/[id]/validation.ts +0 -22
  42. package/template/old/src/app/(app)/roles/actions.ts +0 -33
  43. package/template/old/src/app/(app)/roles/page.tsx +0 -52
  44. package/template/old/src/app/(app)/roles/render.tsx +0 -80
  45. package/template/old/src/app/(app)/settings/actions.ts +0 -17
  46. package/template/old/src/app/(app)/settings/layout.tsx +0 -14
  47. package/template/old/src/app/(app)/settings/loading.tsx +0 -28
  48. package/template/old/src/app/(app)/settings/page.tsx +0 -19
  49. package/template/old/src/app/(app)/settings/render.tsx +0 -107
  50. package/template/old/src/app/(app)/settings/validation.ts +0 -5
  51. package/template/old/src/app/(app)/tasks/[id]/actions.ts +0 -92
  52. package/template/old/src/app/(app)/tasks/[id]/page.tsx +0 -59
  53. package/template/old/src/app/(app)/tasks/[id]/render.tsx +0 -482
  54. package/template/old/src/app/(app)/tasks/[id]/validation.ts +0 -18
  55. package/template/old/src/app/(app)/tasks/actions.ts +0 -39
  56. package/template/old/src/app/(app)/tasks/page.tsx +0 -59
  57. package/template/old/src/app/(app)/tasks/render.tsx +0 -129
  58. package/template/old/src/app/(app)/tasks/statusEnum.ts +0 -3
  59. package/template/old/src/app/(app)/users/[id]/actions.ts +0 -68
  60. package/template/old/src/app/(app)/users/[id]/page.tsx +0 -39
  61. package/template/old/src/app/(app)/users/[id]/render.tsx +0 -325
  62. package/template/old/src/app/(app)/users/[id]/validation.ts +0 -18
  63. package/template/old/src/app/(app)/users/actions.ts +0 -34
  64. package/template/old/src/app/(app)/users/page.tsx +0 -62
  65. package/template/old/src/app/(app)/users/render.tsx +0 -124
  66. package/template/old/src/app/(auth)/layout.tsx +0 -27
  67. package/template/old/src/app/(auth)/login/page.tsx +0 -49
  68. package/template/old/src/app/(auth)/login/render.tsx +0 -146
  69. package/template/old/src/app/(marketing)/layout.tsx +0 -42
  70. package/template/old/src/app/(marketing)/page.tsx +0 -97
  71. package/template/old/src/app/api/auth/[...nextauth]/route.ts +0 -7
  72. package/template/old/src/app/favicon.ico +0 -0
  73. package/template/old/src/app/globals.css +0 -76
  74. package/template/old/src/app/layout.tsx +0 -31
  75. package/template/old/src/components/app-nav-command.tsx +0 -178
  76. package/template/old/src/components/dark-mode-toggle.tsx +0 -43
  77. package/template/old/src/components/data-table/data-table-column-header.tsx +0 -91
  78. package/template/old/src/components/data-table/data-table-faceted-filter.tsx +0 -149
  79. package/template/old/src/components/data-table/data-table-loading.tsx +0 -77
  80. package/template/old/src/components/data-table/data-table-pagination.tsx +0 -94
  81. package/template/old/src/components/data-table/data-table-toolbar.tsx +0 -78
  82. package/template/old/src/components/data-table/data-table-types.ts +0 -17
  83. package/template/old/src/components/data-table/data-table-view-options.tsx +0 -59
  84. package/template/old/src/components/data-table/data-table.tsx +0 -301
  85. package/template/old/src/components/data-table/simple-data-table.tsx +0 -109
  86. package/template/old/src/components/empty-placeholder.tsx +0 -78
  87. package/template/old/src/components/heading.tsx +0 -17
  88. package/template/old/src/components/icons.tsx +0 -101
  89. package/template/old/src/components/main-nav.tsx +0 -64
  90. package/template/old/src/components/mobile-nav.tsx +0 -50
  91. package/template/old/src/components/shell.tsx +0 -13
  92. package/template/old/src/components/side-nav.tsx +0 -51
  93. package/template/old/src/components/site-footer.tsx +0 -31
  94. package/template/old/src/components/system-info.tsx +0 -36
  95. package/template/old/src/components/ui/alert-dialog.tsx +0 -141
  96. package/template/old/src/components/ui/avatar.tsx +0 -50
  97. package/template/old/src/components/ui/badge.tsx +0 -36
  98. package/template/old/src/components/ui/button.tsx +0 -56
  99. package/template/old/src/components/ui/card.tsx +0 -79
  100. package/template/old/src/components/ui/checkbox.tsx +0 -30
  101. package/template/old/src/components/ui/command.tsx +0 -155
  102. package/template/old/src/components/ui/dialog.tsx +0 -122
  103. package/template/old/src/components/ui/dropdown-menu.tsx +0 -200
  104. package/template/old/src/components/ui/form.tsx +0 -176
  105. package/template/old/src/components/ui/input.tsx +0 -25
  106. package/template/old/src/components/ui/label.tsx +0 -26
  107. package/template/old/src/components/ui/popover.tsx +0 -31
  108. package/template/old/src/components/ui/select.tsx +0 -160
  109. package/template/old/src/components/ui/separator.tsx +0 -31
  110. package/template/old/src/components/ui/skeleton.tsx +0 -15
  111. package/template/old/src/components/ui/sonner.tsx +0 -31
  112. package/template/old/src/components/ui/table.tsx +0 -117
  113. package/template/old/src/components/user-account-nav.tsx +0 -60
  114. package/template/old/src/components/user-avatar.tsx +0 -27
  115. package/template/old/src/data-access/resource.ts +0 -85
  116. package/template/old/src/data-access/role-permission.ts +0 -45
  117. package/template/old/src/data-access/role.ts +0 -105
  118. package/template/old/src/data-access/task.ts +0 -141
  119. package/template/old/src/data-access/user.ts +0 -141
  120. package/template/old/src/db/index.ts +0 -14
  121. package/template/old/src/db/schema.ts +0 -287
  122. package/template/old/src/env.mjs +0 -58
  123. package/template/old/src/hooks/use-debounce.tsx +0 -17
  124. package/template/old/src/hooks/use-lock-body.tsx +0 -13
  125. package/template/old/src/lib/auth.ts +0 -89
  126. package/template/old/src/lib/cn.ts +0 -4
  127. package/template/old/src/lib/currentUser.ts +0 -8
  128. package/template/old/src/lib/delay.ts +0 -2
  129. package/template/old/src/lib/formatDate.ts +0 -11
  130. package/template/old/src/lib/generateLabel.ts +0 -5
  131. package/template/old/src/lib/s3Client.ts +0 -156
  132. package/template/old/src/lib/safe-action.ts +0 -19
  133. package/template/old/src/lib/siteConfig.ts +0 -4
  134. package/template/old/src/lib/sortOrderEnum.ts +0 -2
  135. package/template/old/src/use-case/role-permission.ts +0 -19
  136. package/template/old/src/use-case/role.ts +0 -110
  137. package/template/old/src/use-case/task.ts +0 -166
  138. package/template/old/src/use-case/user.ts +0 -121
  139. package/template/old/tailwind.config.ts +0 -81
  140. package/template/old/tsconfig.json +0 -47
@@ -1,17 +0,0 @@
1
- {
2
- "$schema": "https://ui.shadcn.com/schema.json",
3
- "style": "default",
4
- "rsc": true,
5
- "tsx": true,
6
- "tailwind": {
7
- "config": "tailwind.config.ts",
8
- "css": "src/app/globals.css",
9
- "baseColor": "neutral",
10
- "cssVariables": true,
11
- "prefix": ""
12
- },
13
- "aliases": {
14
- "components": "@/components",
15
- "utils": "@/lib/cn"
16
- }
17
- }
@@ -1,11 +0,0 @@
1
- import { type Config } from 'drizzle-kit'
2
-
3
- import { env } from '@/env.mjs'
4
-
5
- export default {
6
- schema: './src/db/schema.ts',
7
- dialect: 'postgresql',
8
- dbCredentials: {
9
- url: env.DATABASE_URL
10
- }
11
- } satisfies Config
@@ -1,4 +0,0 @@
1
- /** @type {import('next').NextConfig} */
2
- const nextConfig = {}
3
-
4
- export default nextConfig
@@ -1,87 +0,0 @@
1
- {
2
- "name": "my-app",
3
- "version": "1.0.0",
4
- "description": "A Legendary Next.js App",
5
- "private": true,
6
- "scripts": {
7
- "format": "prettier --write \"src/**/*.{js,cjs,mjs,jsx,ts,tsx}\"",
8
- "lint": "next lint",
9
- "dev": "next dev",
10
- "build": "next build",
11
- "start": "next start",
12
- "db:generate": "drizzle-kit generate",
13
- "db:push": "drizzle-kit push",
14
- "db:studio": "drizzle-kit studio"
15
- },
16
- "dependencies": {
17
- "@auth/drizzle-adapter": "^1.4.1",
18
- "@aws-sdk/client-s3": "^3.600.0",
19
- "@aws-sdk/s3-presigned-post": "^3.600.0",
20
- "@editorjs/checklist": "^1.6.0",
21
- "@editorjs/code": "^2.9.0",
22
- "@editorjs/delimiter": "^1.4.0",
23
- "@editorjs/editorjs": "^2.29.1",
24
- "@editorjs/header": "^2.8.1",
25
- "@editorjs/image": "^2.9.0",
26
- "@editorjs/inline-code": "^1.5.0",
27
- "@editorjs/list": "^1.9.0",
28
- "@editorjs/nested-list": "^1.4.2",
29
- "@editorjs/quote": "^2.6.0",
30
- "@editorjs/table": "^2.3.0",
31
- "@hookform/resolvers": "^3.6.0",
32
- "@paralleldrive/cuid2": "^2.2.2",
33
- "@radix-ui/react-alert-dialog": "^1.1.1",
34
- "@radix-ui/react-avatar": "^1.1.0",
35
- "@radix-ui/react-checkbox": "^1.1.0",
36
- "@radix-ui/react-dialog": "^1.1.1",
37
- "@radix-ui/react-dropdown-menu": "^2.1.1",
38
- "@radix-ui/react-label": "^2.1.0",
39
- "@radix-ui/react-popover": "^1.1.1",
40
- "@radix-ui/react-select": "^2.1.1",
41
- "@radix-ui/react-separator": "^1.1.0",
42
- "@radix-ui/react-slot": "^1.1.0",
43
- "@t3-oss/env-nextjs": "^0.10.1",
44
- "@tailwindcss/typography": "^0.5.13",
45
- "@tanstack/react-table": "^8.17.3",
46
- "@types/eslint": "^8.56.10",
47
- "@types/node": "^20.14.9",
48
- "@types/nodemailer": "^6.4.15",
49
- "@types/react": "^18.3.3",
50
- "@types/react-dom": "^18.3.0",
51
- "@typescript-eslint/eslint-plugin": "^7.14.1",
52
- "@typescript-eslint/parser": "^7.14.1",
53
- "class-variance-authority": "^0.7.0",
54
- "clsx": "^2.1.1",
55
- "cmdk": "^1.0.0",
56
- "dayjs": "^1.11.11",
57
- "drizzle-kit": "^0.22.7",
58
- "drizzle-orm": "^0.31.2",
59
- "editorjs-html": "^3.4.3",
60
- "eslint": "^8.57.0",
61
- "eslint-config-next": "^14.2.4",
62
- "eslint-plugin-drizzle": "^0.2.3",
63
- "geist": "^1.3.0",
64
- "lucide-react": "^0.397.0",
65
- "next": "^14.2.4",
66
- "next-auth": "^4.24.7",
67
- "next-safe-action": "^7.1.3",
68
- "next-themes": "^0.3.0",
69
- "nextjs-toploader": "^1.6.12",
70
- "nodemailer": "^6.9.14",
71
- "postcss": "^8.4.38",
72
- "postcss-load-config": "^6.0.1",
73
- "postgres": "^3.4.4",
74
- "prettier": "^3.3.2",
75
- "prettier-plugin-organize-imports": "^3.2.4",
76
- "prettier-plugin-tailwindcss": "^0.6.5",
77
- "react": "^18.3.1",
78
- "react-dom": "^18.3.1",
79
- "react-hook-form": "^7.52.0",
80
- "sonner": "^1.5.0",
81
- "tailwind-merge": "^2.3.0",
82
- "tailwindcss": "^3.4.4",
83
- "tailwindcss-animate": "^1.0.7",
84
- "typescript": "^5.5.2",
85
- "zod": "^3.23.8"
86
- }
87
- }
@@ -1,8 +0,0 @@
1
- /** @type {import('postcss-load-config').Config} */
2
- const config = {
3
- plugins: {
4
- tailwindcss: {}
5
- }
6
- }
7
-
8
- export default config
@@ -1,11 +0,0 @@
1
- /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
2
- const config = {
3
- plugins: ['prettier-plugin-organize-imports', 'prettier-plugin-tailwindcss'],
4
- arrowParens: 'avoid',
5
- trailingComma: 'none',
6
- semi: false,
7
- singleQuote: true,
8
- tabWidth: 2
9
- }
10
-
11
- export default config
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
@@ -1,14 +0,0 @@
1
- import { Metadata } from 'next'
2
- import { ReactNode } from 'react'
3
-
4
- import { siteConfig } from '@/lib/siteConfig'
5
-
6
- export const metadata: Metadata = {
7
- title: 'Dashboard' + ' | ' + siteConfig.name
8
- }
9
-
10
- const Layout = ({ children }: { children: ReactNode }) => {
11
- return <>{children}</>
12
- }
13
-
14
- export default Layout
@@ -1,12 +0,0 @@
1
- import { Heading } from '@/components/heading'
2
- import { Shell } from '@/components/shell'
3
-
4
- const DashboardPage = () => {
5
- return (
6
- <Shell>
7
- <Heading heading="Dashboard" />
8
- </Shell>
9
- )
10
- }
11
-
12
- export default DashboardPage
@@ -1,125 +0,0 @@
1
- import { notFound } from 'next/navigation'
2
- import { ReactNode } from 'react'
3
-
4
- import { AppNavCommand } from '@/components/app-nav-command'
5
- import { MainNav } from '@/components/main-nav'
6
- import { SideNav } from '@/components/side-nav'
7
- import { SiteFooter } from '@/components/site-footer'
8
- import { UserAccountNav } from '@/components/user-account-nav'
9
- import { getAuthSession } from '@/lib/auth'
10
- import { checkForRolePermissionUseCase } from '@/use-case/role-permission'
11
-
12
- const Layout = async ({ children }: { children: ReactNode }) => {
13
- const session = await getAuthSession()
14
-
15
- if (!session?.user) return notFound()
16
-
17
- const isRoot = session.user.type === 'Root'
18
- const [isTask] = await Promise.all([
19
- checkForRolePermissionUseCase(
20
- session.user.type,
21
- session.user.roleId,
22
- 'TaskList'
23
- )
24
- ])
25
-
26
- return (
27
- <div className="flex min-h-screen flex-col space-y-6">
28
- <header className="sticky top-0 z-40 border-b bg-background">
29
- <div className="container flex h-16 items-center justify-between py-4">
30
- <MainNav
31
- logoLink="/dashboard"
32
- items={[
33
- {
34
- title: 'Dashboard',
35
- href: '/dashboard'
36
- },
37
- ...(isRoot
38
- ? [
39
- {
40
- title: 'Users',
41
- href: '/users'
42
- },
43
- {
44
- title: 'Roles',
45
- href: '/roles'
46
- }
47
- ]
48
- : []),
49
- ...(isTask
50
- ? [
51
- {
52
- title: 'Tasks',
53
- href: '/tasks'
54
- }
55
- ]
56
- : [])
57
- ]}
58
- />
59
- <div className="flex items-center justify-center space-x-4">
60
- <AppNavCommand
61
- modules={{
62
- task: true,
63
- root: session.user.type === 'Root'
64
- }}
65
- />
66
- <UserAccountNav
67
- user={{
68
- name: session.user.name,
69
- image: session.user.image,
70
- email: session.user.email
71
- }}
72
- />
73
- </div>
74
- </div>
75
- </header>
76
- <div className="container grid flex-1 gap-12 md:grid-cols-[200px_1fr]">
77
- <aside className="hidden w-[200px] flex-col md:flex">
78
- <SideNav
79
- items={[
80
- {
81
- title: 'Dashboard',
82
- href: '/dashboard',
83
- icon: 'dashboard'
84
- },
85
- ...(isRoot
86
- ? [
87
- {
88
- title: 'Users',
89
- href: '/users',
90
- icon: 'user' as const
91
- },
92
- {
93
- title: 'Roles',
94
- href: '/roles',
95
- icon: 'mixer' as const
96
- }
97
- ]
98
- : []),
99
- ...(isTask
100
- ? [
101
- {
102
- title: 'Tasks',
103
- href: '/tasks',
104
- icon: 'task' as const
105
- }
106
- ]
107
- : []),
108
- {
109
- title: 'Settings',
110
- href: '/settings',
111
- icon: 'settings'
112
- }
113
- ]}
114
- />
115
- </aside>
116
- <main className="flex w-full flex-1 flex-col overflow-hidden">
117
- {children}
118
- </main>
119
- </div>
120
- <SiteFooter className="border-t" />
121
- </div>
122
- )
123
- }
124
-
125
- export default Layout
@@ -1,59 +0,0 @@
1
- 'use server'
2
-
3
- import { revalidatePath } from 'next/cache'
4
- import { z } from 'zod'
5
-
6
- import { authActionClient } from '@/lib/safe-action'
7
- import {
8
- createRoleUseCase,
9
- deleteRoleUseCase,
10
- getRoleByIdWithPermissionsUseCase,
11
- updateRoleUseCase
12
- } from '@/use-case/role'
13
- import { RoleCreateUpdateSchema, RoleUpdateServerSchema } from './validation'
14
-
15
- export const getRoleAction = authActionClient
16
- .schema(z.string())
17
- .action(async ({ parsedInput: id, ctx }) => {
18
- return await getRoleByIdWithPermissionsUseCase(ctx.user.type, id)
19
- })
20
-
21
- export const createRoleAction = authActionClient
22
- .schema(RoleCreateUpdateSchema)
23
- .action(async ({ parsedInput: { name, permissions }, ctx }) => {
24
- const id = await createRoleUseCase(ctx.user.type, { name, permissions })
25
-
26
- revalidatePath('/roles')
27
- revalidatePath(`/roles/${id}`)
28
-
29
- return {
30
- success: true,
31
- id
32
- }
33
- })
34
-
35
- export const updateRoleAction = authActionClient
36
- .schema(RoleUpdateServerSchema)
37
- .action(async ({ parsedInput: { id, name, permissions }, ctx }) => {
38
- await updateRoleUseCase(ctx.user.type, { id, name, permissions })
39
-
40
- revalidatePath('/roles')
41
- revalidatePath(`/roles/${id}`)
42
-
43
- return {
44
- success: true
45
- }
46
- })
47
-
48
- export const deleteRoleAction = authActionClient
49
- .schema(z.string())
50
- .action(async ({ parsedInput: id, ctx }) => {
51
- await deleteRoleUseCase(ctx.user.type, id)
52
-
53
- revalidatePath('/roles')
54
- revalidatePath(`/roles/${id}`)
55
-
56
- return {
57
- success: true
58
- }
59
- })
@@ -1,46 +0,0 @@
1
- import { Metadata } from 'next'
2
- import { notFound } from 'next/navigation'
3
-
4
- import { authGuard, getAuthSession } from '@/lib/auth'
5
- import { siteConfig } from '@/lib/siteConfig'
6
- import { getRoleAction } from './actions'
7
- import { Render } from './render'
8
-
9
- export const generateMetadata = async (props: {
10
- params: { id: string }
11
- }): Promise<Metadata> => ({
12
- title: 'Role - ' + props.params.id + ' | ' + siteConfig.name
13
- })
14
-
15
- const RolePage = async ({
16
- params: { id }
17
- }: {
18
- params: {
19
- id: string
20
- }
21
- }) => {
22
- const session = await getAuthSession()
23
- if (!session) return notFound()
24
-
25
- const g = await authGuard(session)
26
- if (!g) return notFound()
27
-
28
- if (id == 'new') return <Render />
29
-
30
- const role = await getRoleAction(id)
31
- if (!role?.data) return notFound()
32
-
33
- return (
34
- <Render
35
- role={{
36
- id: role.data.id,
37
- name: role.data.name,
38
- permissions: role.data.permissions.map(p => p.permission),
39
- createdAt: role.data.createdAt,
40
- updatedAt: role.data.updatedAt
41
- }}
42
- />
43
- )
44
- }
45
-
46
- export default RolePage
@@ -1,264 +0,0 @@
1
- 'use client'
2
-
3
- import { zodResolver } from '@hookform/resolvers/zod'
4
- import Link from 'next/link'
5
- import { useRouter } from 'next/navigation'
6
- import { FC, useState } from 'react'
7
- import { useForm } from 'react-hook-form'
8
- import { toast } from 'sonner'
9
- import { z } from 'zod'
10
-
11
- import { Heading } from '@/components/heading'
12
- import { Icons } from '@/components/icons'
13
- import { Shell } from '@/components/shell'
14
- import { SystemInfo } from '@/components/system-info'
15
- import {
16
- AlertDialog,
17
- AlertDialogAction,
18
- AlertDialogCancel,
19
- AlertDialogContent,
20
- AlertDialogDescription,
21
- AlertDialogFooter,
22
- AlertDialogHeader,
23
- AlertDialogTitle,
24
- AlertDialogTrigger
25
- } from '@/components/ui/alert-dialog'
26
- import { Button } from '@/components/ui/button'
27
- import { Checkbox } from '@/components/ui/checkbox'
28
- import {
29
- Form,
30
- FormControl,
31
- FormField,
32
- FormItem,
33
- FormLabel,
34
- FormMessage
35
- } from '@/components/ui/form'
36
- import { Input } from '@/components/ui/input'
37
- import { type RolePermissionType } from '@/data-access/role-permission'
38
- import { formatDateTime, timesAgo } from '@/lib/formatDate'
39
- import { createRoleAction, deleteRoleAction, updateRoleAction } from './actions'
40
- import { RoleCreateUpdateSchema, defaultPermissions } from './validation'
41
-
42
- type FormData = z.infer<typeof RoleCreateUpdateSchema>
43
-
44
- export const Render: FC<{
45
- role?: {
46
- id: string
47
- name: string
48
- permissions: RolePermissionType['permission'][]
49
- createdAt: Date
50
- updatedAt?: Date | null
51
- } | null
52
- }> = ({ role }) => {
53
- const form = useForm<FormData>({
54
- resolver: zodResolver(RoleCreateUpdateSchema),
55
- defaultValues: {
56
- name: role?.name ?? '',
57
- permissions: role?.permissions ?? []
58
- }
59
- })
60
-
61
- const router = useRouter()
62
-
63
- const [isSaving, setIsSaving] = useState(false)
64
- const [isDeleting, setIsDeleting] = useState(false)
65
-
66
- async function onSubmit(data: FormData) {
67
- setIsSaving(true)
68
- try {
69
- if (!role) {
70
- const res = await createRoleAction(data)
71
- if (!res?.data?.success)
72
- throw new Error(res?.serverError || 'No success returned from server')
73
- if (!res?.data?.id) throw new Error('No id returned from server')
74
- router.replace(`/roles/${res.data.id}`)
75
- } else {
76
- const res = await updateRoleAction({
77
- id: role.id,
78
- ...data
79
- })
80
- if (!res?.data?.success)
81
- throw new Error(res?.serverError || 'No success returned from server')
82
- }
83
- toast('Role saved')
84
- } catch (err) {
85
- toast('Error saving role', {
86
- description: (err as any).message || undefined
87
- })
88
- }
89
- setIsSaving(false)
90
- }
91
-
92
- return (
93
- <Shell>
94
- <Heading heading={role ? role.name : 'New Role'} />
95
- <Form {...form}>
96
- <form
97
- className="grid grid-cols-1 gap-3 md:grid-cols-2"
98
- onSubmit={form.handleSubmit(onSubmit)}
99
- >
100
- <div className="col-span-1 mb-1 grid grid-cols-2 gap-2 sm:flex md:col-span-2">
101
- <Button type="button" onClick={() => router.back()} variant="ghost">
102
- <Icons.chevronLeft className="mr-2 h-4 w-4" />
103
- Back
104
- </Button>
105
- <Button type="submit" disabled={isSaving || isDeleting}>
106
- {isSaving ? (
107
- <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
108
- ) : (
109
- <Icons.save className="mr-2 h-4 w-4" />
110
- )}
111
- <span>Save</span>
112
- </Button>
113
- {role ? (
114
- <AlertDialog>
115
- <AlertDialogTrigger asChild>
116
- <Button
117
- type="button"
118
- variant="destructive"
119
- disabled={isSaving || isDeleting}
120
- >
121
- {isDeleting ? (
122
- <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
123
- ) : (
124
- <Icons.delete className="mr-2 h-4 w-4" />
125
- )}
126
- Delete
127
- </Button>
128
- </AlertDialogTrigger>
129
- <AlertDialogContent>
130
- <AlertDialogHeader>
131
- <AlertDialogTitle>
132
- Are you absolutely sure?
133
- </AlertDialogTitle>
134
- <AlertDialogDescription>
135
- This action cannot be undone.
136
- </AlertDialogDescription>
137
- </AlertDialogHeader>
138
- <AlertDialogFooter>
139
- <AlertDialogCancel>Cancel</AlertDialogCancel>
140
- <AlertDialogAction
141
- onClick={async () => {
142
- setIsDeleting(true)
143
- try {
144
- const res = await deleteRoleAction(role.id)
145
- if (!res?.data?.success)
146
- throw new Error(
147
- res?.serverError ||
148
- 'No success returned from server'
149
- )
150
- toast('Role deleted')
151
- router.replace('/roles')
152
- } catch (err) {
153
- toast('Error deleting role', {
154
- description:
155
- (err as any).message || 'Something went wrong'
156
- })
157
- }
158
- setIsDeleting(false)
159
- }}
160
- >
161
- Continue
162
- </AlertDialogAction>
163
- </AlertDialogFooter>
164
- </AlertDialogContent>
165
- </AlertDialog>
166
- ) : undefined}
167
- {role ? (
168
- <Link href="/roles/new">
169
- <Button
170
- type="button"
171
- disabled={isSaving || isDeleting}
172
- variant="secondary"
173
- className="w-full"
174
- >
175
- <Icons.add className="mr-2 h-4 w-4" />
176
- New
177
- </Button>
178
- </Link>
179
- ) : undefined}
180
- </div>
181
-
182
- <FormField
183
- control={form.control}
184
- name="name"
185
- render={({ field }) => (
186
- <FormItem>
187
- <FormLabel>Name</FormLabel>
188
- <FormControl>
189
- <Input
190
- type="text"
191
- placeholder="Enter a name"
192
- disabled={isSaving}
193
- {...field}
194
- />
195
- </FormControl>
196
- <FormMessage />
197
- </FormItem>
198
- )}
199
- />
200
-
201
- <div></div>
202
-
203
- <FormField
204
- control={form.control}
205
- name="permissions"
206
- render={() => (
207
- <FormItem>
208
- <FormLabel className="text-base">Permissions</FormLabel>
209
- {defaultPermissions.map(item => (
210
- <FormField
211
- key={item.value}
212
- control={form.control}
213
- name="permissions"
214
- render={({ field }) => (
215
- <FormItem
216
- key={item.value}
217
- className="flex flex-row items-start space-x-3 space-y-0"
218
- >
219
- <FormControl>
220
- <Checkbox
221
- checked={field.value?.includes(item.value)}
222
- onCheckedChange={checked => {
223
- return checked
224
- ? field.onChange([...field.value, item.value])
225
- : field.onChange(
226
- field.value?.filter(
227
- value => value !== item.value
228
- )
229
- )
230
- }}
231
- />
232
- </FormControl>
233
- <FormLabel>{item.label}</FormLabel>
234
- </FormItem>
235
- )}
236
- />
237
- ))}
238
- <FormMessage />
239
- </FormItem>
240
- )}
241
- />
242
- </form>
243
- </Form>
244
- {role ? (
245
- <SystemInfo
246
- items={[
247
- {
248
- label: 'Id',
249
- value: role.id
250
- },
251
- {
252
- label: 'Created At',
253
- value: formatDateTime(role.createdAt)
254
- },
255
- {
256
- label: 'Updated At',
257
- value: role.updatedAt ? timesAgo(role.updatedAt) : '-'
258
- }
259
- ]}
260
- />
261
- ) : undefined}
262
- </Shell>
263
- )
264
- }