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.
- package/cli.js +5 -4
- package/cli.ts +9 -4
- package/package.json +1 -1
- package/template/base/package.json +9 -15
- package/template/base/terraform/artifact-registry.tf +5 -0
- package/template/base/terraform/backend-service.tf +13 -0
- package/template/base/terraform/cleanup.sh +9 -0
- package/template/base/terraform/cloudbuild.tf +70 -0
- package/template/base/terraform/cloudrun.tf +68 -0
- package/template/base/terraform/database.tf +60 -0
- package/template/base/terraform/forwarding-rule.tf +43 -0
- package/template/base/terraform/ip-address.tf +11 -0
- package/template/base/terraform/network-endpoint-group.tf +11 -0
- package/template/base/terraform/network.tf +21 -0
- package/template/base/terraform/pre.sh +3 -0
- package/template/base/terraform/providers.tf +18 -0
- package/template/base/terraform/secret.txt +11 -0
- package/template/base/terraform/setup.sh +25 -0
- package/template/base/terraform/ssl-certs.tf +32 -0
- package/template/base/terraform/target-https-proxy copy.tf +14 -0
- package/template/base/terraform/target-https-proxy.tf +14 -0
- package/template/base/terraform/terraform.tfvars +4 -0
- package/template/base/terraform/url-map.tf +23 -0
- package/template/base/terraform/variables.tf +21 -0
- package/template/old/.env.example +0 -17
- package/template/old/.eslintrc.cjs +0 -26
- package/template/old/components.json +0 -17
- package/template/old/drizzle.config.ts +0 -11
- package/template/old/next.config.mjs +0 -4
- package/template/old/package.json +0 -87
- package/template/old/postcss.config.mjs +0 -8
- package/template/old/prettier.config.mjs +0 -11
- package/template/old/public/next.svg +0 -1
- package/template/old/public/vercel.svg +0 -1
- package/template/old/src/app/(app)/dashboard/layout.tsx +0 -14
- package/template/old/src/app/(app)/dashboard/page.tsx +0 -12
- package/template/old/src/app/(app)/layout.tsx +0 -125
- package/template/old/src/app/(app)/roles/[id]/actions.ts +0 -59
- package/template/old/src/app/(app)/roles/[id]/page.tsx +0 -46
- package/template/old/src/app/(app)/roles/[id]/render.tsx +0 -264
- package/template/old/src/app/(app)/roles/[id]/validation.ts +0 -22
- package/template/old/src/app/(app)/roles/actions.ts +0 -33
- package/template/old/src/app/(app)/roles/page.tsx +0 -52
- package/template/old/src/app/(app)/roles/render.tsx +0 -80
- package/template/old/src/app/(app)/settings/actions.ts +0 -17
- package/template/old/src/app/(app)/settings/layout.tsx +0 -14
- package/template/old/src/app/(app)/settings/loading.tsx +0 -28
- package/template/old/src/app/(app)/settings/page.tsx +0 -19
- package/template/old/src/app/(app)/settings/render.tsx +0 -107
- package/template/old/src/app/(app)/settings/validation.ts +0 -5
- package/template/old/src/app/(app)/tasks/[id]/actions.ts +0 -92
- package/template/old/src/app/(app)/tasks/[id]/page.tsx +0 -59
- package/template/old/src/app/(app)/tasks/[id]/render.tsx +0 -482
- package/template/old/src/app/(app)/tasks/[id]/validation.ts +0 -18
- package/template/old/src/app/(app)/tasks/actions.ts +0 -39
- package/template/old/src/app/(app)/tasks/page.tsx +0 -59
- package/template/old/src/app/(app)/tasks/render.tsx +0 -129
- package/template/old/src/app/(app)/tasks/statusEnum.ts +0 -3
- package/template/old/src/app/(app)/users/[id]/actions.ts +0 -68
- package/template/old/src/app/(app)/users/[id]/page.tsx +0 -39
- package/template/old/src/app/(app)/users/[id]/render.tsx +0 -325
- package/template/old/src/app/(app)/users/[id]/validation.ts +0 -18
- package/template/old/src/app/(app)/users/actions.ts +0 -34
- package/template/old/src/app/(app)/users/page.tsx +0 -62
- package/template/old/src/app/(app)/users/render.tsx +0 -124
- package/template/old/src/app/(auth)/layout.tsx +0 -27
- package/template/old/src/app/(auth)/login/page.tsx +0 -49
- package/template/old/src/app/(auth)/login/render.tsx +0 -146
- package/template/old/src/app/(marketing)/layout.tsx +0 -42
- package/template/old/src/app/(marketing)/page.tsx +0 -97
- package/template/old/src/app/api/auth/[...nextauth]/route.ts +0 -7
- package/template/old/src/app/favicon.ico +0 -0
- package/template/old/src/app/globals.css +0 -76
- package/template/old/src/app/layout.tsx +0 -31
- package/template/old/src/components/app-nav-command.tsx +0 -178
- package/template/old/src/components/dark-mode-toggle.tsx +0 -43
- package/template/old/src/components/data-table/data-table-column-header.tsx +0 -91
- package/template/old/src/components/data-table/data-table-faceted-filter.tsx +0 -149
- package/template/old/src/components/data-table/data-table-loading.tsx +0 -77
- package/template/old/src/components/data-table/data-table-pagination.tsx +0 -94
- package/template/old/src/components/data-table/data-table-toolbar.tsx +0 -78
- package/template/old/src/components/data-table/data-table-types.ts +0 -17
- package/template/old/src/components/data-table/data-table-view-options.tsx +0 -59
- package/template/old/src/components/data-table/data-table.tsx +0 -301
- package/template/old/src/components/data-table/simple-data-table.tsx +0 -109
- package/template/old/src/components/empty-placeholder.tsx +0 -78
- package/template/old/src/components/heading.tsx +0 -17
- package/template/old/src/components/icons.tsx +0 -101
- package/template/old/src/components/main-nav.tsx +0 -64
- package/template/old/src/components/mobile-nav.tsx +0 -50
- package/template/old/src/components/shell.tsx +0 -13
- package/template/old/src/components/side-nav.tsx +0 -51
- package/template/old/src/components/site-footer.tsx +0 -31
- package/template/old/src/components/system-info.tsx +0 -36
- package/template/old/src/components/ui/alert-dialog.tsx +0 -141
- package/template/old/src/components/ui/avatar.tsx +0 -50
- package/template/old/src/components/ui/badge.tsx +0 -36
- package/template/old/src/components/ui/button.tsx +0 -56
- package/template/old/src/components/ui/card.tsx +0 -79
- package/template/old/src/components/ui/checkbox.tsx +0 -30
- package/template/old/src/components/ui/command.tsx +0 -155
- package/template/old/src/components/ui/dialog.tsx +0 -122
- package/template/old/src/components/ui/dropdown-menu.tsx +0 -200
- package/template/old/src/components/ui/form.tsx +0 -176
- package/template/old/src/components/ui/input.tsx +0 -25
- package/template/old/src/components/ui/label.tsx +0 -26
- package/template/old/src/components/ui/popover.tsx +0 -31
- package/template/old/src/components/ui/select.tsx +0 -160
- package/template/old/src/components/ui/separator.tsx +0 -31
- package/template/old/src/components/ui/skeleton.tsx +0 -15
- package/template/old/src/components/ui/sonner.tsx +0 -31
- package/template/old/src/components/ui/table.tsx +0 -117
- package/template/old/src/components/user-account-nav.tsx +0 -60
- package/template/old/src/components/user-avatar.tsx +0 -27
- package/template/old/src/data-access/resource.ts +0 -85
- package/template/old/src/data-access/role-permission.ts +0 -45
- package/template/old/src/data-access/role.ts +0 -105
- package/template/old/src/data-access/task.ts +0 -141
- package/template/old/src/data-access/user.ts +0 -141
- package/template/old/src/db/index.ts +0 -14
- package/template/old/src/db/schema.ts +0 -287
- package/template/old/src/env.mjs +0 -58
- package/template/old/src/hooks/use-debounce.tsx +0 -17
- package/template/old/src/hooks/use-lock-body.tsx +0 -13
- package/template/old/src/lib/auth.ts +0 -89
- package/template/old/src/lib/cn.ts +0 -4
- package/template/old/src/lib/currentUser.ts +0 -8
- package/template/old/src/lib/delay.ts +0 -2
- package/template/old/src/lib/formatDate.ts +0 -11
- package/template/old/src/lib/generateLabel.ts +0 -5
- package/template/old/src/lib/s3Client.ts +0 -156
- package/template/old/src/lib/safe-action.ts +0 -19
- package/template/old/src/lib/siteConfig.ts +0 -4
- package/template/old/src/lib/sortOrderEnum.ts +0 -2
- package/template/old/src/use-case/role-permission.ts +0 -19
- package/template/old/src/use-case/role.ts +0 -110
- package/template/old/src/use-case/task.ts +0 -166
- package/template/old/src/use-case/user.ts +0 -121
- package/template/old/tailwind.config.ts +0 -81
- package/template/old/tsconfig.json +0 -47
|
@@ -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,92 +0,0 @@
|
|
|
1
|
-
'use server'
|
|
2
|
-
|
|
3
|
-
import { revalidatePath } from 'next/cache'
|
|
4
|
-
import { z } from 'zod'
|
|
5
|
-
|
|
6
|
-
import { getPresignedUrl, markFileUploaded } from '@/lib/s3Client'
|
|
7
|
-
import { authActionClient } from '@/lib/safe-action'
|
|
8
|
-
import {
|
|
9
|
-
createTaskUseCase,
|
|
10
|
-
deleteTaskUseCase,
|
|
11
|
-
getTaskByIdWithUserUseCase,
|
|
12
|
-
updateTaskUseCase
|
|
13
|
-
} from '@/use-case/task'
|
|
14
|
-
import { TaskCreateUpdateSchema, TaskUpdateServerSchema } from './validation'
|
|
15
|
-
|
|
16
|
-
export const getTaskAction = authActionClient
|
|
17
|
-
.schema(z.string())
|
|
18
|
-
.action(async ({ parsedInput, ctx }) => {
|
|
19
|
-
return await getTaskByIdWithUserUseCase(ctx.user, parsedInput)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
export const createTaskAction = authActionClient
|
|
23
|
-
.schema(TaskCreateUpdateSchema)
|
|
24
|
-
.action(async ({ parsedInput, ctx }) => {
|
|
25
|
-
const id = await createTaskUseCase(ctx.user, parsedInput)
|
|
26
|
-
|
|
27
|
-
revalidatePath('/tasks')
|
|
28
|
-
revalidatePath(`/tasks/${id}`)
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
id,
|
|
32
|
-
success: true
|
|
33
|
-
}
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
export const updateTaskAction = authActionClient
|
|
37
|
-
.schema(TaskUpdateServerSchema)
|
|
38
|
-
.action(async ({ parsedInput: id, ctx }) => {
|
|
39
|
-
await updateTaskUseCase(ctx.user, id)
|
|
40
|
-
|
|
41
|
-
revalidatePath('/tasks')
|
|
42
|
-
revalidatePath(`/tasks/${id}`)
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
success: true
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
export const deleteTaskAction = authActionClient
|
|
50
|
-
.schema(z.string())
|
|
51
|
-
.action(async ({ parsedInput: id, ctx }) => {
|
|
52
|
-
await deleteTaskUseCase(ctx.user, id)
|
|
53
|
-
|
|
54
|
-
revalidatePath('/tasks')
|
|
55
|
-
revalidatePath(`/tasks/${id}`)
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
success: true
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
export const getTaskImageUploadPresignedUrlAction = authActionClient
|
|
63
|
-
.schema(
|
|
64
|
-
z.object({
|
|
65
|
-
filename: z.string().min(1),
|
|
66
|
-
contentType: z.string().min(1)
|
|
67
|
-
})
|
|
68
|
-
)
|
|
69
|
-
.action(async ({ ctx, parsedInput }) => {
|
|
70
|
-
return await getPresignedUrl({
|
|
71
|
-
// contentTypeStartsWith: 'image/',
|
|
72
|
-
isPublic: true,
|
|
73
|
-
filename: parsedInput.filename,
|
|
74
|
-
contentType: parsedInput.contentType,
|
|
75
|
-
createdById: ctx.user.id
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
export const markTaskImageUploadedAction = authActionClient
|
|
80
|
-
.schema(z.string())
|
|
81
|
-
.action(async ({ parsedInput: id, ctx }) => {
|
|
82
|
-
try {
|
|
83
|
-
await markFileUploaded(ctx.user, id)
|
|
84
|
-
return {
|
|
85
|
-
success: true
|
|
86
|
-
}
|
|
87
|
-
} catch (err) {
|
|
88
|
-
return {
|
|
89
|
-
success: false
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
})
|
|
@@ -1,59 +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 { getTaskAction } from './actions'
|
|
7
|
-
import { Render } from './render'
|
|
8
|
-
|
|
9
|
-
export const generateMetadata = async (props: {
|
|
10
|
-
params: { id: string }
|
|
11
|
-
}): Promise<Metadata> => ({
|
|
12
|
-
title: 'Task - ' + props.params.id + ' | ' + siteConfig.name
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
const TaskPage = 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, 'TaskView')
|
|
26
|
-
if (!g) return notFound()
|
|
27
|
-
|
|
28
|
-
const [canCreate, canUpdate, canDelete] = await Promise.all([
|
|
29
|
-
authGuard(session, 'TaskCreate'),
|
|
30
|
-
authGuard(session, 'TaskUpdate'),
|
|
31
|
-
authGuard(session, 'TaskDelete')
|
|
32
|
-
])
|
|
33
|
-
|
|
34
|
-
if (id === 'new') {
|
|
35
|
-
if (!canCreate) return notFound()
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<Render
|
|
39
|
-
canCreate={canCreate}
|
|
40
|
-
canUpdate={canUpdate}
|
|
41
|
-
canDelete={canDelete}
|
|
42
|
-
/>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const task = await getTaskAction(id)
|
|
47
|
-
if (!task?.data) return notFound()
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<Render
|
|
51
|
-
task={task.data}
|
|
52
|
-
canCreate={canCreate}
|
|
53
|
-
canUpdate={canUpdate}
|
|
54
|
-
canDelete={canDelete}
|
|
55
|
-
/>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default TaskPage
|