create-nextjs-cms 0.9.28 → 0.9.30
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/LICENSE +21 -21
- package/README.md +71 -71
- package/dist/helpers/utils.js +16 -16
- package/dist/lib/section-creators.js +166 -166
- package/package.json +2 -2
- package/templates/default/.eslintrc.json +5 -5
- package/templates/default/.prettierignore +7 -7
- package/templates/default/.prettierrc.json +27 -27
- package/templates/default/CHANGELOG.md +140 -140
- package/templates/default/_gitignore +57 -57
- package/templates/default/app/(auth)/auth/login/LoginPage.tsx +192 -192
- package/templates/default/app/(auth)/auth/login/page.tsx +11 -11
- package/templates/default/app/(auth)/auth-language-provider.tsx +34 -34
- package/templates/default/app/(auth)/layout.tsx +81 -81
- package/templates/default/app/(rootLayout)/admins/page.tsx +10 -10
- package/templates/default/app/(rootLayout)/browse/[section]/[page]/page.tsx +22 -22
- package/templates/default/app/(rootLayout)/categorized/[section]/page.tsx +15 -15
- package/templates/default/app/(rootLayout)/dashboard/page.tsx +70 -70
- package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +20 -20
- package/templates/default/app/(rootLayout)/layout.tsx +81 -81
- package/templates/default/app/(rootLayout)/loading.tsx +10 -10
- package/templates/default/app/(rootLayout)/log/page.tsx +7 -7
- package/templates/default/app/(rootLayout)/new/[section]/page.tsx +15 -15
- package/templates/default/app/(rootLayout)/section/[section]/page.tsx +19 -19
- package/templates/default/app/(rootLayout)/settings/page.tsx +13 -13
- package/templates/default/app/api/auth/csrf/route.ts +25 -25
- package/templates/default/app/api/auth/refresh/route.ts +10 -10
- package/templates/default/app/api/auth/route.ts +49 -49
- package/templates/default/app/api/auth/session/route.ts +20 -20
- package/templates/default/app/api/document/route.ts +165 -165
- package/templates/default/app/api/editor/photo/route.ts +49 -49
- package/templates/default/app/api/photo/route.ts +27 -27
- package/templates/default/app/api/submit/section/item/[slug]/route.ts +95 -95
- package/templates/default/app/api/submit/section/item/route.ts +56 -56
- package/templates/default/app/api/submit/section/simple/route.ts +86 -86
- package/templates/default/app/api/video/route.ts +174 -174
- package/templates/default/app/globals.css +236 -236
- package/templates/default/cms.config.ts +56 -56
- package/templates/default/components/admin/admin-card.tsx +165 -165
- package/templates/default/components/admin/admin-edit-page.tsx +124 -124
- package/templates/default/components/admin/admin-privilege-card.tsx +184 -184
- package/templates/default/components/admin/new-admin-form.tsx +172 -172
- package/templates/default/components/container-box.tsx +24 -24
- package/templates/default/components/dnd-kit/draggable.tsx +21 -21
- package/templates/default/components/dnd-kit/droppable.tsx +20 -20
- package/templates/default/components/dnd-kit/sortable-item.tsx +18 -18
- package/templates/default/components/feedback/error-component.tsx +16 -16
- package/templates/default/components/feedback/info-card.tsx +93 -93
- package/templates/default/components/feedback/loading-spinners.tsx +67 -67
- package/templates/default/components/feedback/modal.tsx +166 -166
- package/templates/default/components/feedback/progress-bar.tsx +48 -48
- package/templates/default/components/feedback/tooltip-component.tsx +27 -27
- package/templates/default/components/form/form-input-element.tsx +70 -70
- package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
- package/templates/default/components/form/helpers/util.ts +17 -17
- package/templates/default/components/form/inputs/checkbox-form-input.tsx +46 -46
- package/templates/default/components/form/inputs/color-form-input.tsx +44 -44
- package/templates/default/components/form/inputs/date-form-input.tsx +93 -93
- package/templates/default/components/form/inputs/map-form-input.tsx +141 -141
- package/templates/default/components/form/inputs/multiple-select-form-input.tsx +85 -85
- package/templates/default/components/form/inputs/number-form-input.tsx +43 -43
- package/templates/default/components/form/inputs/password-form-input.tsx +47 -47
- package/templates/default/components/form/inputs/photo-form-input.tsx +279 -279
- package/templates/default/components/form/inputs/rich-text-form-input.tsx +148 -148
- package/templates/default/components/form/inputs/select-form-input.tsx +159 -159
- package/templates/default/components/form/inputs/slug-form-input.tsx +131 -131
- package/templates/default/components/form/inputs/tags-form-input.tsx +255 -255
- package/templates/default/components/form/inputs/text-form-input.tsx +61 -61
- package/templates/default/components/form/inputs/textarea-form-input.tsx +61 -61
- package/templates/default/components/layout/default-nav-items.tsx +3 -3
- package/templates/default/components/layout/layout.tsx +84 -84
- package/templates/default/components/layout/navbar.tsx +258 -258
- package/templates/default/components/layout/sidebar-dropdown-item.tsx +83 -83
- package/templates/default/components/layout/sidebar-item.tsx +24 -24
- package/templates/default/components/layout/sidebar.tsx +229 -229
- package/templates/default/components/layout/theme-provider.tsx +8 -8
- package/templates/default/components/layout/theme-toggle.tsx +39 -39
- package/templates/default/components/locale/locale-switcher.tsx +98 -98
- package/templates/default/components/media/dropzone.tsx +154 -154
- package/templates/default/components/media/protected-document.tsx +44 -44
- package/templates/default/components/media/protected-image.tsx +143 -143
- package/templates/default/components/media/protected-video.tsx +76 -76
- package/templates/default/components/multi-select.tsx +1150 -1150
- package/templates/default/components/pages/admins-page.tsx +43 -43
- package/templates/default/components/pages/browse-page.tsx +106 -106
- package/templates/default/components/pages/categorized-section-page.tsx +31 -31
- package/templates/default/components/pages/dashboard-page-alt.tsx +45 -45
- package/templates/default/components/pages/item-edit-page.tsx +267 -267
- package/templates/default/components/pages/log-page.tsx +107 -107
- package/templates/default/components/pages/new-page.tsx +183 -183
- package/templates/default/components/pages/section-page.tsx +203 -203
- package/templates/default/components/pages/settings-page.tsx +232 -232
- package/templates/default/components/pagination/pagination-buttons.tsx +147 -147
- package/templates/default/components/pagination/pagination.tsx +36 -36
- package/templates/default/components/sections/category-delete-confirm-page.tsx +130 -130
- package/templates/default/components/sections/category-section-select-input.tsx +139 -139
- package/templates/default/components/sections/conditional-fields.tsx +49 -49
- package/templates/default/components/sections/section-icon.tsx +8 -8
- package/templates/default/components/sections/section-item-card.tsx +143 -143
- package/templates/default/components/sections/section-item-status-badge.tsx +17 -17
- package/templates/default/components/sections/select-input-buttons.tsx +125 -125
- package/templates/default/components/select-box.tsx +98 -98
- package/templates/default/components/ui/accordion.tsx +53 -53
- package/templates/default/components/ui/alert-dialog.tsx +113 -113
- package/templates/default/components/ui/alert.tsx +47 -47
- package/templates/default/components/ui/badge.tsx +38 -38
- package/templates/default/components/ui/card.tsx +43 -43
- package/templates/default/components/ui/command.tsx +137 -137
- package/templates/default/components/ui/custom-alert-dialog.tsx +113 -113
- package/templates/default/components/ui/custom-dialog.tsx +123 -123
- package/templates/default/components/ui/dialog.tsx +123 -123
- package/templates/default/components/ui/direction.tsx +22 -22
- package/templates/default/components/ui/dropdown-menu.tsx +182 -182
- package/templates/default/components/ui/input-group.tsx +54 -54
- package/templates/default/components/ui/input.tsx +22 -22
- package/templates/default/components/ui/label.tsx +19 -19
- package/templates/default/components/ui/popover.tsx +42 -42
- package/templates/default/components/ui/progress.tsx +31 -31
- package/templates/default/components/ui/scroll-area.tsx +42 -42
- package/templates/default/components/ui/select.tsx +165 -165
- package/templates/default/components/ui/separator.tsx +28 -28
- package/templates/default/components/ui/sheet.tsx +103 -103
- package/templates/default/components/ui/spinner.tsx +16 -16
- package/templates/default/components/ui/switch.tsx +29 -29
- package/templates/default/components/ui/table.tsx +83 -83
- package/templates/default/components/ui/tabs.tsx +55 -55
- package/templates/default/components/ui/toast.tsx +113 -113
- package/templates/default/components/ui/toaster.tsx +35 -35
- package/templates/default/components/ui/tooltip.tsx +30 -30
- package/templates/default/components/ui/use-toast.ts +187 -187
- package/templates/default/drizzle.config.ts +4 -4
- package/templates/default/dynamic-schemas/schema.ts +75 -225
- package/templates/default/env/env.ts +46 -46
- package/templates/default/envConfig.ts +4 -4
- package/templates/default/lib/postinstall.js +14 -14
- package/templates/default/lib/utils.ts +6 -6
- package/templates/default/next-env.d.ts +6 -6
- package/templates/default/next.config.ts +24 -24
- package/templates/default/package.json +1 -1
- package/templates/default/postcss.config.mjs +6 -6
- package/templates/default/proxy.ts +32 -32
- package/templates/default/tsconfig.json +48 -48
|
@@ -1,173 +1,173 @@
|
|
|
1
|
-
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { useModal } from '@/components/feedback/modal-context'
|
|
4
|
-
import InfoCard from '@/components/feedback/info-card'
|
|
5
|
-
import { useToast } from '@/components/ui/use-toast'
|
|
6
|
-
import { trpc } from '@/app/_trpc/client'
|
|
7
|
-
import AdminRoleCard from '@/components/admin/admin-privilege-card'
|
|
8
|
-
import { Button } from '@/components/ui/button'
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { useModal } from '@/components/feedback/modal-context'
|
|
4
|
+
import InfoCard from '@/components/feedback/info-card'
|
|
5
|
+
import { useToast } from '@/components/ui/use-toast'
|
|
6
|
+
import { trpc } from '@/app/_trpc/client'
|
|
7
|
+
import AdminRoleCard from '@/components/admin/admin-privilege-card'
|
|
8
|
+
import { Button } from '@/components/ui/button'
|
|
9
9
|
import type { RouterOutputs } from '@/app/_trpc/types'
|
|
10
|
-
|
|
11
|
-
export default function NewAdminForm({
|
|
12
|
-
privileges,
|
|
13
|
-
action,
|
|
14
|
-
}: {
|
|
15
|
-
privileges: RouterOutputs['admins']['list']['privileges']
|
|
16
|
-
action: any
|
|
17
|
-
}) {
|
|
18
|
-
const t = useI18n()
|
|
19
|
-
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
20
|
-
const { toast } = useToast()
|
|
21
|
-
const formRef = React.useRef<HTMLFormElement>(null)
|
|
22
|
-
const [allChecked, setAllChecked] = React.useState<boolean | 'edited' | null>(null)
|
|
23
|
-
const usernameRef = React.useRef<HTMLInputElement>(null)
|
|
24
|
-
const passwordRef = React.useRef<HTMLInputElement>(null)
|
|
25
|
-
|
|
26
|
-
const mutation = trpc.admins.create.useMutation({
|
|
27
|
-
onError: (error) => {
|
|
28
|
-
setModal({
|
|
29
|
-
title: t('createNewAdmin'),
|
|
30
|
-
body: (
|
|
31
|
-
<div className='p-4'>
|
|
32
|
-
<InfoCard result={{ key: 'danger', title: error.message, status: false }} />
|
|
33
|
-
</div>
|
|
34
|
-
),
|
|
35
|
-
headerColor: 'bg-red-700',
|
|
36
|
-
titleColor: 'text-white',
|
|
37
|
-
lang: 'en',
|
|
38
|
-
})
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
onSuccess: (data) => {
|
|
42
|
-
setModal(null)
|
|
43
|
-
setModalResponse(null)
|
|
44
|
-
setAllChecked(false)
|
|
45
|
-
action()
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Empty the form
|
|
49
|
-
*/
|
|
50
|
-
if (formRef.current) {
|
|
51
|
-
formRef.current.reset()
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Show a success toast
|
|
56
|
-
*/
|
|
57
|
-
toast({
|
|
58
|
-
variant: 'success',
|
|
59
|
-
title: t('createNewAdmin'),
|
|
60
|
-
description: t('itemCreatedSuccessfully'),
|
|
61
|
-
})
|
|
62
|
-
},
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
66
|
-
e.preventDefault()
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Check username and password
|
|
70
|
-
*/
|
|
71
|
-
if (!usernameRef.current?.value || !passwordRef.current?.value) {
|
|
72
|
-
setModal({
|
|
73
|
-
title: t('createNewAdmin'),
|
|
74
|
-
body: <div className='p-4'>{t('usernamePasswordRequired')}</div>,
|
|
75
|
-
headerColor: 'bg-red-700',
|
|
76
|
-
titleColor: 'text-white',
|
|
77
|
-
lang: 'en',
|
|
78
|
-
})
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const data = new FormData(e.currentTarget)
|
|
83
|
-
const values = Object.fromEntries(data.entries())
|
|
84
|
-
values.form_type = 'new'
|
|
85
|
-
|
|
86
|
-
// Convert the privileges to an array of objects
|
|
87
|
-
const privileges = Object.entries(values).filter(([key]) => key.includes('privileges'))
|
|
88
|
-
const privilegesArray = privileges.map(([key, value]) => JSON.parse(value as string))
|
|
89
|
-
|
|
90
|
-
mutation.mutate({
|
|
91
|
-
username: usernameRef.current.value,
|
|
92
|
-
password: passwordRef.current.value,
|
|
93
|
-
privileges: privilegesArray,
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return (
|
|
98
|
-
<form ref={formRef} onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
99
|
-
<div>
|
|
100
|
-
<label htmlFor='email' className='block text-sm font-medium leading-6 text-foreground'>
|
|
101
|
-
{t('username')}
|
|
102
|
-
</label>
|
|
103
|
-
<div className=''>
|
|
104
|
-
<input
|
|
105
|
-
ref={usernameRef}
|
|
106
|
-
id='username'
|
|
107
|
-
name='username'
|
|
108
|
-
type='text'
|
|
109
|
-
// required
|
|
110
|
-
className='block w-full rounded-md border-0 bg-input p-3 text-foreground shadow-xs outline-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6'
|
|
111
|
-
/>
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
114
|
-
|
|
115
|
-
<div>
|
|
116
|
-
<label htmlFor='password' className='block text-sm font-medium leading-6 text-foreground'>
|
|
117
|
-
{t('password')}
|
|
118
|
-
</label>
|
|
119
|
-
<div className=''>
|
|
120
|
-
<input
|
|
121
|
-
ref={passwordRef}
|
|
122
|
-
id='password'
|
|
123
|
-
name='password'
|
|
124
|
-
type='text'
|
|
125
|
-
// required
|
|
126
|
-
className='block w-full rounded-md border-0 bg-input p-3 text-foreground shadow-xs outline-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6'
|
|
127
|
-
/>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
{privileges && privileges.length > 0 && (
|
|
131
|
-
<>
|
|
132
|
-
<div className='mt-5 w-full font-semibold'>{t('adminPrivileges')}</div>
|
|
133
|
-
<div className='flex'>
|
|
134
|
-
<Button
|
|
135
|
-
className='border border-foreground'
|
|
136
|
-
type='button'
|
|
137
|
-
variant={allChecked === true ? 'default' : 'secondary'}
|
|
138
|
-
onClick={(event) => {
|
|
139
|
-
event.preventDefault()
|
|
140
|
-
event.stopPropagation()
|
|
141
|
-
if (allChecked === true) {
|
|
142
|
-
setAllChecked(false)
|
|
143
|
-
} else {
|
|
144
|
-
setAllChecked(true)
|
|
145
|
-
}
|
|
146
|
-
}}
|
|
147
|
-
>
|
|
148
|
-
{allChecked === true ? t('removeAll') : t('checkAll')}
|
|
149
|
-
</Button>
|
|
150
|
-
</div>
|
|
151
|
-
<div className='mt-2 grid w-full grid-cols-1 gap-2 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-3 xl-sidebar:grid-cols-4 2xl-sidebar:grid-cols-5'>
|
|
152
|
-
{privileges.map((privilege, index: number) => {
|
|
153
|
-
return (
|
|
154
|
-
<AdminRoleCard
|
|
155
|
-
key={index}
|
|
156
|
-
privilege={privilege}
|
|
157
|
-
allChecked={allChecked}
|
|
158
|
-
setAllChecked={setAllChecked}
|
|
159
|
-
/>
|
|
160
|
-
)
|
|
161
|
-
})}
|
|
162
|
-
</div>
|
|
163
|
-
</>
|
|
164
|
-
)}
|
|
165
|
-
|
|
166
|
-
<div className='mt-4'>
|
|
167
|
-
<button type='submit' className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
168
|
-
{t('submitNewAdmin')}
|
|
169
|
-
</button>
|
|
170
|
-
</div>
|
|
171
|
-
</form>
|
|
172
|
-
)
|
|
173
|
-
}
|
|
10
|
+
|
|
11
|
+
export default function NewAdminForm({
|
|
12
|
+
privileges,
|
|
13
|
+
action,
|
|
14
|
+
}: {
|
|
15
|
+
privileges: RouterOutputs['admins']['list']['privileges']
|
|
16
|
+
action: any
|
|
17
|
+
}) {
|
|
18
|
+
const t = useI18n()
|
|
19
|
+
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
20
|
+
const { toast } = useToast()
|
|
21
|
+
const formRef = React.useRef<HTMLFormElement>(null)
|
|
22
|
+
const [allChecked, setAllChecked] = React.useState<boolean | 'edited' | null>(null)
|
|
23
|
+
const usernameRef = React.useRef<HTMLInputElement>(null)
|
|
24
|
+
const passwordRef = React.useRef<HTMLInputElement>(null)
|
|
25
|
+
|
|
26
|
+
const mutation = trpc.admins.create.useMutation({
|
|
27
|
+
onError: (error) => {
|
|
28
|
+
setModal({
|
|
29
|
+
title: t('createNewAdmin'),
|
|
30
|
+
body: (
|
|
31
|
+
<div className='p-4'>
|
|
32
|
+
<InfoCard result={{ key: 'danger', title: error.message, status: false }} />
|
|
33
|
+
</div>
|
|
34
|
+
),
|
|
35
|
+
headerColor: 'bg-red-700',
|
|
36
|
+
titleColor: 'text-white',
|
|
37
|
+
lang: 'en',
|
|
38
|
+
})
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
onSuccess: (data) => {
|
|
42
|
+
setModal(null)
|
|
43
|
+
setModalResponse(null)
|
|
44
|
+
setAllChecked(false)
|
|
45
|
+
action()
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Empty the form
|
|
49
|
+
*/
|
|
50
|
+
if (formRef.current) {
|
|
51
|
+
formRef.current.reset()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Show a success toast
|
|
56
|
+
*/
|
|
57
|
+
toast({
|
|
58
|
+
variant: 'success',
|
|
59
|
+
title: t('createNewAdmin'),
|
|
60
|
+
description: t('itemCreatedSuccessfully'),
|
|
61
|
+
})
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
66
|
+
e.preventDefault()
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check username and password
|
|
70
|
+
*/
|
|
71
|
+
if (!usernameRef.current?.value || !passwordRef.current?.value) {
|
|
72
|
+
setModal({
|
|
73
|
+
title: t('createNewAdmin'),
|
|
74
|
+
body: <div className='p-4'>{t('usernamePasswordRequired')}</div>,
|
|
75
|
+
headerColor: 'bg-red-700',
|
|
76
|
+
titleColor: 'text-white',
|
|
77
|
+
lang: 'en',
|
|
78
|
+
})
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const data = new FormData(e.currentTarget)
|
|
83
|
+
const values = Object.fromEntries(data.entries())
|
|
84
|
+
values.form_type = 'new'
|
|
85
|
+
|
|
86
|
+
// Convert the privileges to an array of objects
|
|
87
|
+
const privileges = Object.entries(values).filter(([key]) => key.includes('privileges'))
|
|
88
|
+
const privilegesArray = privileges.map(([key, value]) => JSON.parse(value as string))
|
|
89
|
+
|
|
90
|
+
mutation.mutate({
|
|
91
|
+
username: usernameRef.current.value,
|
|
92
|
+
password: passwordRef.current.value,
|
|
93
|
+
privileges: privilegesArray,
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<form ref={formRef} onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
99
|
+
<div>
|
|
100
|
+
<label htmlFor='email' className='block text-sm font-medium leading-6 text-foreground'>
|
|
101
|
+
{t('username')}
|
|
102
|
+
</label>
|
|
103
|
+
<div className=''>
|
|
104
|
+
<input
|
|
105
|
+
ref={usernameRef}
|
|
106
|
+
id='username'
|
|
107
|
+
name='username'
|
|
108
|
+
type='text'
|
|
109
|
+
// required
|
|
110
|
+
className='block w-full rounded-md border-0 bg-input p-3 text-foreground shadow-xs outline-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6'
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<div>
|
|
116
|
+
<label htmlFor='password' className='block text-sm font-medium leading-6 text-foreground'>
|
|
117
|
+
{t('password')}
|
|
118
|
+
</label>
|
|
119
|
+
<div className=''>
|
|
120
|
+
<input
|
|
121
|
+
ref={passwordRef}
|
|
122
|
+
id='password'
|
|
123
|
+
name='password'
|
|
124
|
+
type='text'
|
|
125
|
+
// required
|
|
126
|
+
className='block w-full rounded-md border-0 bg-input p-3 text-foreground shadow-xs outline-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6'
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
{privileges && privileges.length > 0 && (
|
|
131
|
+
<>
|
|
132
|
+
<div className='mt-5 w-full font-semibold'>{t('adminPrivileges')}</div>
|
|
133
|
+
<div className='flex'>
|
|
134
|
+
<Button
|
|
135
|
+
className='border border-foreground'
|
|
136
|
+
type='button'
|
|
137
|
+
variant={allChecked === true ? 'default' : 'secondary'}
|
|
138
|
+
onClick={(event) => {
|
|
139
|
+
event.preventDefault()
|
|
140
|
+
event.stopPropagation()
|
|
141
|
+
if (allChecked === true) {
|
|
142
|
+
setAllChecked(false)
|
|
143
|
+
} else {
|
|
144
|
+
setAllChecked(true)
|
|
145
|
+
}
|
|
146
|
+
}}
|
|
147
|
+
>
|
|
148
|
+
{allChecked === true ? t('removeAll') : t('checkAll')}
|
|
149
|
+
</Button>
|
|
150
|
+
</div>
|
|
151
|
+
<div className='mt-2 grid w-full grid-cols-1 gap-2 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-3 xl-sidebar:grid-cols-4 2xl-sidebar:grid-cols-5'>
|
|
152
|
+
{privileges.map((privilege, index: number) => {
|
|
153
|
+
return (
|
|
154
|
+
<AdminRoleCard
|
|
155
|
+
key={index}
|
|
156
|
+
privilege={privilege}
|
|
157
|
+
allChecked={allChecked}
|
|
158
|
+
setAllChecked={setAllChecked}
|
|
159
|
+
/>
|
|
160
|
+
)
|
|
161
|
+
})}
|
|
162
|
+
</div>
|
|
163
|
+
</>
|
|
164
|
+
)}
|
|
165
|
+
|
|
166
|
+
<div className='mt-4'>
|
|
167
|
+
<button type='submit' className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
168
|
+
{t('submitNewAdmin')}
|
|
169
|
+
</button>
|
|
170
|
+
</div>
|
|
171
|
+
</form>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
// import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
3
|
-
|
|
4
|
-
export default function ContainerBox({ children, title }: { children: React.ReactNode; title?: string }) {
|
|
5
|
-
return (
|
|
6
|
-
<>
|
|
7
|
-
{/*<Card>
|
|
8
|
-
<CardHeader>
|
|
9
|
-
<CardTitle>{title}</CardTitle>
|
|
10
|
-
</CardHeader>
|
|
11
|
-
<CardContent>{children}</CardContent>
|
|
12
|
-
</Card>*/}
|
|
13
|
-
|
|
14
|
-
<div className='relative flex flex-col rounded-lg border border-slate-300 bg-white shadow-xs dark:border-slate-500 dark:bg-slate-900'>
|
|
15
|
-
{title ? (
|
|
16
|
-
<div className='rounded-t-lg px-4 py-1.5 font-bold text-black dark:bg-slate-800 dark:text-white'>
|
|
17
|
-
{title}
|
|
18
|
-
</div>
|
|
19
|
-
) : null}
|
|
20
|
-
<div className='w-full px-4 py-2'>{children}</div>
|
|
21
|
-
</div>
|
|
22
|
-
</>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
1
|
+
import React from 'react'
|
|
2
|
+
// import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
3
|
+
|
|
4
|
+
export default function ContainerBox({ children, title }: { children: React.ReactNode; title?: string }) {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
{/*<Card>
|
|
8
|
+
<CardHeader>
|
|
9
|
+
<CardTitle>{title}</CardTitle>
|
|
10
|
+
</CardHeader>
|
|
11
|
+
<CardContent>{children}</CardContent>
|
|
12
|
+
</Card>*/}
|
|
13
|
+
|
|
14
|
+
<div className='relative flex flex-col rounded-lg border border-slate-300 bg-white shadow-xs dark:border-slate-500 dark:bg-slate-900'>
|
|
15
|
+
{title ? (
|
|
16
|
+
<div className='rounded-t-lg px-4 py-1.5 font-bold text-black dark:bg-slate-800 dark:text-white'>
|
|
17
|
+
{title}
|
|
18
|
+
</div>
|
|
19
|
+
) : null}
|
|
20
|
+
<div className='w-full px-4 py-2'>{children}</div>
|
|
21
|
+
</div>
|
|
22
|
+
</>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { useDraggable } from '@dnd-kit/core'
|
|
3
|
-
|
|
4
|
-
function Draggable({ draggableId, children }: { draggableId: string | number; children: React.ReactNode }) {
|
|
5
|
-
const { attributes, listeners, setNodeRef, transform } = useDraggable({
|
|
6
|
-
id: draggableId,
|
|
7
|
-
})
|
|
8
|
-
const style = transform
|
|
9
|
-
? {
|
|
10
|
-
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
|
|
11
|
-
}
|
|
12
|
-
: undefined
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<div ref={setNodeRef} className='float-start' style={style} {...listeners} {...attributes}>
|
|
16
|
-
{children}
|
|
17
|
-
</div>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default Draggable
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useDraggable } from '@dnd-kit/core'
|
|
3
|
+
|
|
4
|
+
function Draggable({ draggableId, children }: { draggableId: string | number; children: React.ReactNode }) {
|
|
5
|
+
const { attributes, listeners, setNodeRef, transform } = useDraggable({
|
|
6
|
+
id: draggableId,
|
|
7
|
+
})
|
|
8
|
+
const style = transform
|
|
9
|
+
? {
|
|
10
|
+
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
|
|
11
|
+
}
|
|
12
|
+
: undefined
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div ref={setNodeRef} className='float-start' style={style} {...listeners} {...attributes}>
|
|
16
|
+
{children}
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default Draggable
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { useDroppable } from '@dnd-kit/core'
|
|
3
|
-
|
|
4
|
-
function Droppable({ droppableId, children }: { droppableId: string | number; children: React.ReactNode }) {
|
|
5
|
-
const { isOver, setNodeRef } = useDroppable({
|
|
6
|
-
id: droppableId,
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
const style = {
|
|
10
|
-
color: isOver ? 'green' : undefined,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<div ref={setNodeRef} style={style}>
|
|
15
|
-
{children}
|
|
16
|
-
</div>
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default Droppable
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useDroppable } from '@dnd-kit/core'
|
|
3
|
+
|
|
4
|
+
function Droppable({ droppableId, children }: { droppableId: string | number; children: React.ReactNode }) {
|
|
5
|
+
const { isOver, setNodeRef } = useDroppable({
|
|
6
|
+
id: droppableId,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
const style = {
|
|
10
|
+
color: isOver ? 'green' : undefined,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div ref={setNodeRef} style={style}>
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default Droppable
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { useSortable } from '@dnd-kit/sortable'
|
|
3
|
-
import { CSS } from '@dnd-kit/utilities'
|
|
4
|
-
|
|
5
|
-
export default function SortableItem({ id, children }: { id: string | number; children: React.ReactNode }) {
|
|
6
|
-
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: id })
|
|
7
|
-
|
|
8
|
-
const style = {
|
|
9
|
-
transform: CSS.Transform.toString(transform),
|
|
10
|
-
transition,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
|
|
15
|
-
{children}
|
|
16
|
-
</div>
|
|
17
|
-
)
|
|
18
|
-
}
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useSortable } from '@dnd-kit/sortable'
|
|
3
|
+
import { CSS } from '@dnd-kit/utilities'
|
|
4
|
+
|
|
5
|
+
export default function SortableItem({ id, children }: { id: string | number; children: React.ReactNode }) {
|
|
6
|
+
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: id })
|
|
7
|
+
|
|
8
|
+
const style = {
|
|
9
|
+
transform: CSS.Transform.toString(transform),
|
|
10
|
+
transition,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Alert, AlertDescription } from '@/components/ui/alert'
|
|
2
|
-
import { ExclamationTriangleIcon } from '@radix-ui/react-icons'
|
|
3
|
-
|
|
4
|
-
export default function ErrorComponent({ message }: { message: string }) {
|
|
5
|
-
return (
|
|
6
|
-
<div className='px-4'>
|
|
7
|
-
<Alert variant='info' className='my-8'>
|
|
8
|
-
<AlertDescription className='text-md font-bold'>
|
|
9
|
-
<div className='flex items-center gap-1.5'>
|
|
10
|
-
<ExclamationTriangleIcon className='size-5' /> {message}
|
|
11
|
-
</div>
|
|
12
|
-
</AlertDescription>
|
|
13
|
-
</Alert>
|
|
14
|
-
</div>
|
|
15
|
-
)
|
|
16
|
-
|
|
1
|
+
import { Alert, AlertDescription } from '@/components/ui/alert'
|
|
2
|
+
import { ExclamationTriangleIcon } from '@radix-ui/react-icons'
|
|
3
|
+
|
|
4
|
+
export default function ErrorComponent({ message }: { message: string }) {
|
|
5
|
+
return (
|
|
6
|
+
<div className='px-4'>
|
|
7
|
+
<Alert variant='info' className='my-8'>
|
|
8
|
+
<AlertDescription className='text-md font-bold'>
|
|
9
|
+
<div className='flex items-center gap-1.5'>
|
|
10
|
+
<ExclamationTriangleIcon className='size-5' /> {message}
|
|
11
|
+
</div>
|
|
12
|
+
</AlertDescription>
|
|
13
|
+
</Alert>
|
|
14
|
+
</div>
|
|
15
|
+
)
|
|
16
|
+
|
|
17
17
|
}
|