create-ej-app 11.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 (141) 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 +14 -20
  5. package/template/base/src/app/not-found.tsx +1 -7
  6. package/template/base/terraform/artifact-registry.tf +5 -0
  7. package/template/base/terraform/backend-service.tf +13 -0
  8. package/template/base/terraform/cleanup.sh +9 -0
  9. package/template/base/terraform/cloudbuild.tf +70 -0
  10. package/template/base/terraform/cloudrun.tf +68 -0
  11. package/template/base/terraform/database.tf +60 -0
  12. package/template/base/terraform/forwarding-rule.tf +43 -0
  13. package/template/base/terraform/ip-address.tf +11 -0
  14. package/template/base/terraform/network-endpoint-group.tf +11 -0
  15. package/template/base/terraform/network.tf +21 -0
  16. package/template/base/terraform/pre.sh +3 -0
  17. package/template/base/terraform/providers.tf +18 -0
  18. package/template/base/terraform/secret.txt +11 -0
  19. package/template/base/terraform/setup.sh +25 -0
  20. package/template/base/terraform/ssl-certs.tf +32 -0
  21. package/template/base/terraform/target-https-proxy copy.tf +14 -0
  22. package/template/base/terraform/target-https-proxy.tf +14 -0
  23. package/template/base/terraform/terraform.tfvars +4 -0
  24. package/template/base/terraform/url-map.tf +23 -0
  25. package/template/base/terraform/variables.tf +21 -0
  26. package/template/old/.env.example +0 -17
  27. package/template/old/.eslintrc.cjs +0 -26
  28. package/template/old/components.json +0 -17
  29. package/template/old/drizzle.config.ts +0 -11
  30. package/template/old/next.config.mjs +0 -4
  31. package/template/old/package.json +0 -87
  32. package/template/old/postcss.config.mjs +0 -8
  33. package/template/old/prettier.config.mjs +0 -11
  34. package/template/old/public/next.svg +0 -1
  35. package/template/old/public/vercel.svg +0 -1
  36. package/template/old/src/app/(app)/dashboard/layout.tsx +0 -14
  37. package/template/old/src/app/(app)/dashboard/page.tsx +0 -12
  38. package/template/old/src/app/(app)/layout.tsx +0 -125
  39. package/template/old/src/app/(app)/roles/[id]/actions.ts +0 -59
  40. package/template/old/src/app/(app)/roles/[id]/page.tsx +0 -46
  41. package/template/old/src/app/(app)/roles/[id]/render.tsx +0 -264
  42. package/template/old/src/app/(app)/roles/[id]/validation.ts +0 -22
  43. package/template/old/src/app/(app)/roles/actions.ts +0 -33
  44. package/template/old/src/app/(app)/roles/page.tsx +0 -52
  45. package/template/old/src/app/(app)/roles/render.tsx +0 -80
  46. package/template/old/src/app/(app)/settings/actions.ts +0 -17
  47. package/template/old/src/app/(app)/settings/layout.tsx +0 -14
  48. package/template/old/src/app/(app)/settings/loading.tsx +0 -28
  49. package/template/old/src/app/(app)/settings/page.tsx +0 -19
  50. package/template/old/src/app/(app)/settings/render.tsx +0 -107
  51. package/template/old/src/app/(app)/settings/validation.ts +0 -5
  52. package/template/old/src/app/(app)/tasks/[id]/actions.ts +0 -92
  53. package/template/old/src/app/(app)/tasks/[id]/page.tsx +0 -59
  54. package/template/old/src/app/(app)/tasks/[id]/render.tsx +0 -482
  55. package/template/old/src/app/(app)/tasks/[id]/validation.ts +0 -18
  56. package/template/old/src/app/(app)/tasks/actions.ts +0 -39
  57. package/template/old/src/app/(app)/tasks/page.tsx +0 -59
  58. package/template/old/src/app/(app)/tasks/render.tsx +0 -129
  59. package/template/old/src/app/(app)/tasks/statusEnum.ts +0 -3
  60. package/template/old/src/app/(app)/users/[id]/actions.ts +0 -68
  61. package/template/old/src/app/(app)/users/[id]/page.tsx +0 -39
  62. package/template/old/src/app/(app)/users/[id]/render.tsx +0 -325
  63. package/template/old/src/app/(app)/users/[id]/validation.ts +0 -18
  64. package/template/old/src/app/(app)/users/actions.ts +0 -34
  65. package/template/old/src/app/(app)/users/page.tsx +0 -62
  66. package/template/old/src/app/(app)/users/render.tsx +0 -124
  67. package/template/old/src/app/(auth)/layout.tsx +0 -27
  68. package/template/old/src/app/(auth)/login/page.tsx +0 -49
  69. package/template/old/src/app/(auth)/login/render.tsx +0 -146
  70. package/template/old/src/app/(marketing)/layout.tsx +0 -42
  71. package/template/old/src/app/(marketing)/page.tsx +0 -97
  72. package/template/old/src/app/api/auth/[...nextauth]/route.ts +0 -7
  73. package/template/old/src/app/favicon.ico +0 -0
  74. package/template/old/src/app/globals.css +0 -76
  75. package/template/old/src/app/layout.tsx +0 -31
  76. package/template/old/src/components/app-nav-command.tsx +0 -178
  77. package/template/old/src/components/dark-mode-toggle.tsx +0 -43
  78. package/template/old/src/components/data-table/data-table-column-header.tsx +0 -91
  79. package/template/old/src/components/data-table/data-table-faceted-filter.tsx +0 -149
  80. package/template/old/src/components/data-table/data-table-loading.tsx +0 -77
  81. package/template/old/src/components/data-table/data-table-pagination.tsx +0 -94
  82. package/template/old/src/components/data-table/data-table-toolbar.tsx +0 -78
  83. package/template/old/src/components/data-table/data-table-types.ts +0 -17
  84. package/template/old/src/components/data-table/data-table-view-options.tsx +0 -59
  85. package/template/old/src/components/data-table/data-table.tsx +0 -301
  86. package/template/old/src/components/data-table/simple-data-table.tsx +0 -109
  87. package/template/old/src/components/empty-placeholder.tsx +0 -78
  88. package/template/old/src/components/heading.tsx +0 -17
  89. package/template/old/src/components/icons.tsx +0 -101
  90. package/template/old/src/components/main-nav.tsx +0 -64
  91. package/template/old/src/components/mobile-nav.tsx +0 -50
  92. package/template/old/src/components/shell.tsx +0 -13
  93. package/template/old/src/components/side-nav.tsx +0 -51
  94. package/template/old/src/components/site-footer.tsx +0 -31
  95. package/template/old/src/components/system-info.tsx +0 -36
  96. package/template/old/src/components/ui/alert-dialog.tsx +0 -141
  97. package/template/old/src/components/ui/avatar.tsx +0 -50
  98. package/template/old/src/components/ui/badge.tsx +0 -36
  99. package/template/old/src/components/ui/button.tsx +0 -56
  100. package/template/old/src/components/ui/card.tsx +0 -79
  101. package/template/old/src/components/ui/checkbox.tsx +0 -30
  102. package/template/old/src/components/ui/command.tsx +0 -155
  103. package/template/old/src/components/ui/dialog.tsx +0 -122
  104. package/template/old/src/components/ui/dropdown-menu.tsx +0 -200
  105. package/template/old/src/components/ui/form.tsx +0 -176
  106. package/template/old/src/components/ui/input.tsx +0 -25
  107. package/template/old/src/components/ui/label.tsx +0 -26
  108. package/template/old/src/components/ui/popover.tsx +0 -31
  109. package/template/old/src/components/ui/select.tsx +0 -160
  110. package/template/old/src/components/ui/separator.tsx +0 -31
  111. package/template/old/src/components/ui/skeleton.tsx +0 -15
  112. package/template/old/src/components/ui/sonner.tsx +0 -31
  113. package/template/old/src/components/ui/table.tsx +0 -117
  114. package/template/old/src/components/user-account-nav.tsx +0 -60
  115. package/template/old/src/components/user-avatar.tsx +0 -27
  116. package/template/old/src/data-access/resource.ts +0 -85
  117. package/template/old/src/data-access/role-permission.ts +0 -45
  118. package/template/old/src/data-access/role.ts +0 -105
  119. package/template/old/src/data-access/task.ts +0 -141
  120. package/template/old/src/data-access/user.ts +0 -141
  121. package/template/old/src/db/index.ts +0 -14
  122. package/template/old/src/db/schema.ts +0 -287
  123. package/template/old/src/env.mjs +0 -58
  124. package/template/old/src/hooks/use-debounce.tsx +0 -17
  125. package/template/old/src/hooks/use-lock-body.tsx +0 -13
  126. package/template/old/src/lib/auth.ts +0 -89
  127. package/template/old/src/lib/cn.ts +0 -4
  128. package/template/old/src/lib/currentUser.ts +0 -8
  129. package/template/old/src/lib/delay.ts +0 -2
  130. package/template/old/src/lib/formatDate.ts +0 -11
  131. package/template/old/src/lib/generateLabel.ts +0 -5
  132. package/template/old/src/lib/s3Client.ts +0 -156
  133. package/template/old/src/lib/safe-action.ts +0 -19
  134. package/template/old/src/lib/siteConfig.ts +0 -4
  135. package/template/old/src/lib/sortOrderEnum.ts +0 -2
  136. package/template/old/src/use-case/role-permission.ts +0 -19
  137. package/template/old/src/use-case/role.ts +0 -110
  138. package/template/old/src/use-case/task.ts +0 -166
  139. package/template/old/src/use-case/user.ts +0 -121
  140. package/template/old/tailwind.config.ts +0 -81
  141. package/template/old/tsconfig.json +0 -47
@@ -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
- }
@@ -1,22 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- import { RolePermission } from '@/db/schema'
4
- import { generateLabel } from '@/lib/generateLabel'
5
-
6
- const RolePermissionsEnumArr = RolePermission.permission.enumValues
7
-
8
- export const RoleCreateUpdateSchema = z.object({
9
- name: z.string().min(1).trim(),
10
- permissions: z.array(z.enum(RolePermissionsEnumArr))
11
- })
12
-
13
- export const defaultPermissions = RolePermissionsEnumArr.map(x => ({
14
- label: generateLabel(x),
15
- value: x
16
- }))
17
-
18
- export const RoleUpdateServerSchema = RoleCreateUpdateSchema.merge(
19
- z.object({
20
- id: z.string().min(1)
21
- })
22
- )
@@ -1,33 +0,0 @@
1
- 'use server'
2
-
3
- import { z } from 'zod'
4
-
5
- import { authActionClient } from '@/lib/safe-action'
6
- import { SortOrderEnum } from '@/lib/sortOrderEnum'
7
- import { getRolesUseCase } from '@/use-case/role'
8
-
9
- export const getRolesAction = authActionClient
10
- .schema(
11
- z.object({
12
- page: z.number().gte(1),
13
- limit: z.number().gte(1).lte(1000),
14
- sortBy: z.enum(['id', 'name', 'createdAt', 'updatedAt']).optional(),
15
- sortOrder: z.enum(SortOrderEnum).optional(),
16
- name: z.string().optional()
17
- })
18
- )
19
- .action(
20
- async ({ parsedInput: { page, limit, sortBy, sortOrder, name }, ctx }) => {
21
- return await getRolesUseCase(ctx.user.type, {
22
- page,
23
- limit,
24
- sortBy,
25
- sortOrder,
26
- filters: name
27
- ? {
28
- name
29
- }
30
- : undefined
31
- })
32
- }
33
- )
@@ -1,52 +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 { getRolesAction } from './actions'
7
- import { Render } from './render'
8
-
9
- export const metadata: Metadata = {
10
- title: 'Roles' + ' | ' + siteConfig.name
11
- }
12
-
13
- const RolesPage = async ({
14
- searchParams
15
- }: {
16
- searchParams: {
17
- page?: string
18
- limit?: string
19
- sort?: string
20
- name?: string
21
- }
22
- }) => {
23
- const session = await getAuthSession()
24
- if (!session) return notFound()
25
-
26
- const g = await authGuard(session)
27
- if (!g) return notFound()
28
-
29
- const page = searchParams.page ? parseInt(searchParams.page) : 1
30
- const limit = searchParams.limit ? parseInt(searchParams.limit) : 10
31
-
32
- const [sortBy, sortOrder] =
33
- typeof searchParams.sort === 'string'
34
- ? (searchParams.sort.split('.') as [any, 'asc' | 'desc' | undefined])
35
- : []
36
-
37
- const name = searchParams.name
38
-
39
- const data = await getRolesAction({
40
- page,
41
- limit,
42
- sortBy,
43
- sortOrder,
44
- name
45
- })
46
-
47
- if (!data?.data) throw new Error('Roles data not found')
48
-
49
- return <Render data={data.data} />
50
- }
51
-
52
- export default RolesPage
@@ -1,80 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { FC } from 'react'
5
-
6
- import { DataTable } from '@/components/data-table/data-table'
7
- import { DataTableColumnHeader } from '@/components/data-table/data-table-column-header'
8
- import { Heading } from '@/components/heading'
9
- import { Icons } from '@/components/icons'
10
- import { Shell } from '@/components/shell'
11
- import { Button } from '@/components/ui/button'
12
- import { formatDateTime, timesAgo } from '@/lib/formatDate'
13
-
14
- export const Render: FC<{
15
- data: {
16
- roles: {
17
- id: string
18
- name: string
19
- createdAt: Date
20
- updatedAt?: Date | null
21
- }[]
22
- total: number
23
- }
24
- }> = ({ data }) => {
25
- return (
26
- <Shell>
27
- <Heading heading="Roles" text="List of all the roles">
28
- <Link href="/roles/new">
29
- <Button>
30
- <Icons.add className="mr-2 h-4 w-4" />
31
- New
32
- </Button>
33
- </Link>
34
- </Heading>
35
- <DataTable
36
- columns={[
37
- {
38
- accessorKey: 'name',
39
- header: ({ column }) => (
40
- <DataTableColumnHeader column={column} title="Name" />
41
- ),
42
- cell: ({ row }) => (
43
- <Link
44
- className="underline underline-offset-4"
45
- href={`/roles/${row.original.id}`}
46
- >
47
- {row.original.name}
48
- </Link>
49
- )
50
- },
51
- {
52
- accessorKey: 'createdAt',
53
- header: ({ column }) => (
54
- <DataTableColumnHeader column={column} title="Created At" />
55
- ),
56
- cell: ({ row }) => formatDateTime(row.original.createdAt)
57
- },
58
- {
59
- accessorKey: 'updatedAt',
60
- header: ({ column }) => (
61
- <DataTableColumnHeader column={column} title="Updated At" />
62
- ),
63
- cell: ({ row }) =>
64
- row.original.updatedAt
65
- ? timesAgo(row.original.updatedAt)
66
- : undefined
67
- }
68
- ]}
69
- data={data.roles}
70
- total={data.total}
71
- searchableColumns={[
72
- {
73
- id: 'name',
74
- title: 'Name'
75
- }
76
- ]}
77
- />
78
- </Shell>
79
- )
80
- }
@@ -1,17 +0,0 @@
1
- 'use server'
2
-
3
- import { authActionClient } from '@/lib/safe-action'
4
- import { updateCurrentUserNameUseCase } from '@/use-case/user'
5
- import { userSchema } from './validation'
6
-
7
- export const updateNameAction = authActionClient
8
- .schema(userSchema)
9
- .action(async ({ parsedInput: { name }, ctx: { user } }) => {
10
- await updateCurrentUserNameUseCase(user.id, {
11
- name
12
- })
13
-
14
- return {
15
- success: true
16
- }
17
- })
@@ -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: 'Settings' + ' | ' + siteConfig.name
8
- }
9
-
10
- const Layout = ({ children }: { children: ReactNode }) => {
11
- return <>{children}</>
12
- }
13
-
14
- export default Layout
@@ -1,28 +0,0 @@
1
- import { Heading } from '@/components/heading'
2
- import { Shell } from '@/components/shell'
3
- import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card'
4
- import { Skeleton } from '@/components/ui/skeleton'
5
-
6
- const Loading = () => {
7
- return (
8
- <Shell>
9
- <Heading heading="Settings" text="Manage account and profile settings." />
10
- <div className="grid gap-10">
11
- <Card>
12
- <CardHeader className="gap-2">
13
- <Skeleton className="h-6 w-1/5" />
14
- <Skeleton className="h-4 w-4/5" />
15
- </CardHeader>
16
- <CardContent className="h-10">
17
- <Skeleton className="h-8 w-full max-w-[400px]" />
18
- </CardContent>
19
- <CardFooter>
20
- <Skeleton className="h-8 w-full max-w-[120px]" />
21
- </CardFooter>
22
- </Card>
23
- </div>
24
- </Shell>
25
- )
26
- }
27
-
28
- export default Loading
@@ -1,19 +0,0 @@
1
- import { Heading } from '@/components/heading'
2
- import { Shell } from '@/components/shell'
3
- import { getAuthSession } from '@/lib/auth'
4
- import { Render } from './render'
5
-
6
- const SettingsPage = async () => {
7
- const session = await getAuthSession()
8
-
9
- return (
10
- <Shell>
11
- <Heading heading="Settings" text="Manage account and profile settings." />
12
- <div className="grid gap-10">
13
- <Render name={session?.user.name || ''} />
14
- </div>
15
- </Shell>
16
- )
17
- }
18
-
19
- export default SettingsPage
@@ -1,107 +0,0 @@
1
- 'use client'
2
-
3
- import { zodResolver } from '@hookform/resolvers/zod'
4
- import { useRouter } from 'next/navigation'
5
- import { FC, useState } from 'react'
6
- import { useForm } from 'react-hook-form'
7
- import { toast } from 'sonner'
8
- import { z } from 'zod'
9
-
10
- import { Icons } from '@/components/icons'
11
- import { Button } from '@/components/ui/button'
12
- import {
13
- Card,
14
- CardContent,
15
- CardDescription,
16
- CardFooter,
17
- CardHeader,
18
- CardTitle
19
- } from '@/components/ui/card'
20
- import {
21
- Form,
22
- FormControl,
23
- FormField,
24
- FormItem,
25
- FormMessage
26
- } from '@/components/ui/form'
27
- import { Input } from '@/components/ui/input'
28
- import { updateNameAction } from './actions'
29
- import { userSchema } from './validation'
30
-
31
- type FormData = z.infer<typeof userSchema>
32
-
33
- export const Render: FC<{ name: string }> = ({ name }) => {
34
- const form = useForm<FormData>({
35
- resolver: zodResolver(userSchema),
36
- defaultValues: {
37
- name
38
- }
39
- })
40
- const router = useRouter()
41
- const [isSaving, setIsSaving] = useState(false)
42
-
43
- async function onSubmit(data: FormData) {
44
- setIsSaving(true)
45
-
46
- const res = await updateNameAction({
47
- ...data
48
- })
49
-
50
- if (res?.data) {
51
- toast('Your name has been updated.')
52
- router.refresh()
53
- } else {
54
- toast('Internal Server Error', {
55
- description: 'Please try again later.'
56
- })
57
- }
58
-
59
- setIsSaving(false)
60
- }
61
-
62
- return (
63
- <Form {...form}>
64
- <form onSubmit={form.handleSubmit(onSubmit)}>
65
- <Card>
66
- <CardHeader>
67
- <CardTitle>Your Name</CardTitle>
68
- <CardDescription>
69
- Please enter your full name or a display name you are comfortable
70
- with.
71
- </CardDescription>
72
- </CardHeader>
73
- <CardContent>
74
- <FormField
75
- control={form.control}
76
- name="name"
77
- render={({ field }) => (
78
- <FormItem className="max-w-[400px]">
79
- <FormControl>
80
- <Input
81
- type="text"
82
- placeholder="Your Name"
83
- autoComplete="name"
84
- disabled={isSaving}
85
- {...field}
86
- />
87
- </FormControl>
88
- <FormMessage />
89
- </FormItem>
90
- )}
91
- />
92
- </CardContent>
93
- <CardFooter>
94
- <Button type="submit" disabled={isSaving}>
95
- {isSaving ? (
96
- <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
97
- ) : (
98
- <Icons.save className="mr-2 h-4 w-4" />
99
- )}
100
- <span>Save</span>
101
- </Button>
102
- </CardFooter>
103
- </Card>
104
- </form>
105
- </Form>
106
- )
107
- }
@@ -1,5 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const userSchema = z.object({
4
- name: z.string().min(1)
5
- })