create-nextjs-cms 0.7.0 → 0.7.2
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 +3 -3
- 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-locale-provider.tsx +34 -34
- package/templates/default/app/(auth)/layout.tsx +81 -81
- package/templates/default/app/(rootLayout)/(plugins)/[...slug]/page.tsx +40 -40
- package/templates/default/app/(rootLayout)/(plugins)/[...slug]/plugin-server-registry.ts +22 -22
- 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 +63 -63
- package/templates/default/app/(rootLayout)/dashboard-new/page.tsx +7 -7
- package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +17 -17
- 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 +16 -16
- package/templates/default/app/(rootLayout)/settings/page.tsx +13 -13
- package/templates/default/app/_trpc/client.ts +3 -3
- 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/session/route.ts +20 -20
- 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 +66 -66
- package/templates/default/app/api/submit/section/item/route.ts +56 -56
- package/templates/default/app/api/submit/section/simple/route.ts +57 -57
- package/templates/default/app/api/trpc/[trpc]/route.ts +33 -33
- package/templates/default/app/api/video/route.ts +174 -174
- package/templates/default/app/globals.css +219 -219
- package/templates/default/app/providers.tsx +152 -152
- package/templates/default/cms.config.ts +49 -52
- package/templates/default/components/AdminCard.tsx +166 -166
- package/templates/default/components/AdminEditPage.tsx +124 -124
- package/templates/default/components/AdminPrivilegeCard.tsx +185 -185
- package/templates/default/components/AdminsPage.tsx +43 -43
- package/templates/default/components/AnalyticsPage.tsx +128 -128
- package/templates/default/components/BarChartBox.tsx +42 -42
- package/templates/default/components/BrowsePage.tsx +106 -106
- package/templates/default/components/CategorizedSectionPage.tsx +31 -31
- package/templates/default/components/CategoryDeleteConfirmPage.tsx +130 -130
- package/templates/default/components/CategorySectionSelectInput.tsx +140 -140
- package/templates/default/components/ConditionalFields.tsx +49 -49
- package/templates/default/components/ContainerBox.tsx +24 -24
- package/templates/default/components/DashboardNewPage.tsx +253 -253
- package/templates/default/components/DashboardPage.tsx +188 -188
- package/templates/default/components/DashboardPageAlt.tsx +45 -45
- package/templates/default/components/DefaultNavItems.tsx +3 -3
- package/templates/default/components/Dropzone.tsx +154 -154
- package/templates/default/components/EmailCard.tsx +138 -138
- package/templates/default/components/EmailPasswordForm.tsx +85 -85
- package/templates/default/components/EmailQuotaForm.tsx +73 -73
- package/templates/default/components/EmailsPage.tsx +49 -49
- package/templates/default/components/ErrorComponent.tsx +16 -16
- package/templates/default/components/GalleryPhoto.tsx +93 -93
- package/templates/default/components/InfoCard.tsx +93 -93
- package/templates/default/components/ItemEditPage.tsx +214 -214
- package/templates/default/components/Layout.tsx +84 -84
- package/templates/default/components/LoadingSpinners.tsx +67 -67
- package/templates/default/components/LogPage.tsx +107 -107
- package/templates/default/components/Modal.tsx +166 -166
- package/templates/default/components/Navbar.tsx +258 -258
- package/templates/default/components/NewAdminForm.tsx +173 -173
- package/templates/default/components/NewEmailForm.tsx +132 -132
- package/templates/default/components/NewPage.tsx +205 -205
- package/templates/default/components/NewVariantComponent.tsx +229 -229
- package/templates/default/components/PhotoGallery.tsx +35 -35
- package/templates/default/components/PieChartBox.tsx +101 -101
- package/templates/default/components/ProgressBar.tsx +48 -48
- package/templates/default/components/ProtectedDocument.tsx +78 -78
- package/templates/default/components/ProtectedImage.tsx +143 -143
- package/templates/default/components/ProtectedVideo.tsx +76 -76
- package/templates/default/components/SectionItemCard.tsx +144 -144
- package/templates/default/components/SectionItemStatusBadge.tsx +17 -17
- package/templates/default/components/SectionPage.tsx +125 -125
- package/templates/default/components/SelectBox.tsx +98 -98
- package/templates/default/components/SelectInputButtons.tsx +125 -125
- package/templates/default/components/SettingsPage.tsx +232 -232
- package/templates/default/components/Sidebar.tsx +201 -201
- package/templates/default/components/SidebarDropdownItem.tsx +80 -80
- package/templates/default/components/SidebarItem.tsx +20 -20
- package/templates/default/components/ThemeProvider.tsx +8 -8
- package/templates/default/components/TooltipComponent.tsx +27 -27
- package/templates/default/components/VariantCard.tsx +124 -124
- package/templates/default/components/VariantEditPage.tsx +230 -230
- package/templates/default/components/analytics/BounceRate.tsx +70 -70
- package/templates/default/components/analytics/LivePageViews.tsx +55 -55
- package/templates/default/components/analytics/LiveUsersCount.tsx +33 -33
- package/templates/default/components/analytics/MonthlyPageViews.tsx +42 -42
- package/templates/default/components/analytics/TopCountries.tsx +52 -52
- package/templates/default/components/analytics/TopDevices.tsx +46 -46
- package/templates/default/components/analytics/TopMediums.tsx +58 -58
- package/templates/default/components/analytics/TopSources.tsx +45 -45
- package/templates/default/components/analytics/TotalPageViews.tsx +41 -41
- package/templates/default/components/analytics/TotalSessions.tsx +41 -41
- package/templates/default/components/analytics/TotalUniqueUsers.tsx +41 -41
- package/templates/default/components/custom/RightHomeRoomVariantCard.tsx +138 -138
- package/templates/default/components/dndKit/Draggable.tsx +21 -21
- package/templates/default/components/dndKit/Droppable.tsx +20 -20
- package/templates/default/components/dndKit/SortableItem.tsx +18 -18
- package/templates/default/components/form/DateRangeFormInput.tsx +57 -57
- package/templates/default/components/form/Form.tsx +317 -317
- package/templates/default/components/form/FormInputElement.tsx +70 -70
- package/templates/default/components/form/FormInputs.tsx +112 -112
- 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/CheckboxFormInput.tsx +33 -33
- package/templates/default/components/form/inputs/ColorFormInput.tsx +44 -44
- package/templates/default/components/form/inputs/DateFormInput.tsx +156 -156
- package/templates/default/components/form/inputs/DocumentFormInput.tsx +222 -222
- package/templates/default/components/form/inputs/MapFormInput.tsx +140 -140
- package/templates/default/components/form/inputs/MultipleSelectFormInput.tsx +83 -83
- package/templates/default/components/form/inputs/NumberFormInput.tsx +42 -42
- package/templates/default/components/form/inputs/PasswordFormInput.tsx +47 -47
- package/templates/default/components/form/inputs/PhotoFormInput.tsx +219 -219
- package/templates/default/components/form/inputs/RichTextFormInput.tsx +135 -135
- package/templates/default/components/form/inputs/SelectFormInput.tsx +175 -175
- package/templates/default/components/form/inputs/SlugFormInput.tsx +129 -129
- package/templates/default/components/form/inputs/TagsFormInput.tsx +154 -154
- package/templates/default/components/form/inputs/TextFormInput.tsx +48 -48
- package/templates/default/components/form/inputs/TextareaFormInput.tsx +47 -47
- package/templates/default/components/form/inputs/VideoFormInput.tsx +118 -118
- package/templates/default/components/locale-dropdown.tsx +74 -74
- package/templates/default/components/locale-picker.tsx +85 -85
- package/templates/default/components/login-locale-dropdown.tsx +46 -46
- package/templates/default/components/multi-select.tsx +1144 -1144
- package/templates/default/components/pagination/Pagination.tsx +36 -36
- package/templates/default/components/pagination/PaginationButtons.tsx +147 -147
- package/templates/default/components/theme-toggle.tsx +37 -37
- package/templates/default/components/ui/accordion.tsx +53 -53
- package/templates/default/components/ui/alert-dialog.tsx +157 -157
- package/templates/default/components/ui/alert.tsx +46 -46
- package/templates/default/components/ui/badge.tsx +38 -38
- package/templates/default/components/ui/button.tsx +62 -62
- package/templates/default/components/ui/calendar.tsx +166 -166
- package/templates/default/components/ui/card.tsx +43 -43
- package/templates/default/components/ui/checkbox.tsx +29 -29
- 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/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/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 +188 -188
- package/templates/default/components.json +21 -21
- package/templates/default/context/ModalProvider.tsx +53 -53
- package/templates/default/drizzle.config.ts +4 -4
- package/templates/default/dynamic-schemas/schema.ts +10 -0
- package/templates/default/env/env.js +130 -130
- package/templates/default/envConfig.ts +4 -4
- package/templates/default/hooks/useModal.ts +8 -8
- package/templates/default/lib/apiHelpers.ts +92 -92
- 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 +23 -23
- package/templates/default/package.json +2 -4
- 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 '@/hooks/useModal'
|
|
4
|
-
import InfoCard from '@/components/InfoCard'
|
|
5
|
-
import { useToast } from '@/components/ui/use-toast'
|
|
6
|
-
import { trpc } from '@/app/_trpc/client'
|
|
7
|
-
import AdminRoleCard from '@/components/AdminPrivilegeCard'
|
|
8
|
-
import { Button } from '@/components/ui/button'
|
|
9
|
-
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
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
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import useModal from '@/hooks/useModal'
|
|
4
|
+
import InfoCard from '@/components/InfoCard'
|
|
5
|
+
import { useToast } from '@/components/ui/use-toast'
|
|
6
|
+
import { trpc } from '@/app/_trpc/client'
|
|
7
|
+
import AdminRoleCard from '@/components/AdminPrivilegeCard'
|
|
8
|
+
import { Button } from '@/components/ui/button'
|
|
9
|
+
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
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,132 +1,132 @@
|
|
|
1
|
-
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import useModal from '@/hooks/useModal'
|
|
4
|
-
import { Badge } from '@/components/ui/badge'
|
|
5
|
-
import { useToast } from '@/components/ui/use-toast'
|
|
6
|
-
import InfoCard from '@/components/InfoCard'
|
|
7
|
-
import { trpc } from '@/app/_trpc/client'
|
|
8
|
-
|
|
9
|
-
export default function NewEmailForm({ action }: { action: any }) {
|
|
10
|
-
const t = useI18n()
|
|
11
|
-
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
12
|
-
const formRef = React.useRef<HTMLFormElement>(null)
|
|
13
|
-
const { toast } = useToast()
|
|
14
|
-
const newEmailMutation = trpc.cpanelEmails.createEmail.useMutation({
|
|
15
|
-
onError: (error) => {
|
|
16
|
-
setModal({
|
|
17
|
-
title: t('error'),
|
|
18
|
-
body: (
|
|
19
|
-
<div className='p-4'>
|
|
20
|
-
<InfoCard result={{ key: 'danger', title: error.message, status: false }} />
|
|
21
|
-
</div>
|
|
22
|
-
),
|
|
23
|
-
headerColor: 'bg-red-700',
|
|
24
|
-
titleColor: 'text-white',
|
|
25
|
-
lang: 'en',
|
|
26
|
-
})
|
|
27
|
-
},
|
|
28
|
-
onSuccess: (data) => {
|
|
29
|
-
action()
|
|
30
|
-
toast({
|
|
31
|
-
variant: 'success',
|
|
32
|
-
title: t('success'),
|
|
33
|
-
description: data.message,
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
// Empty the form
|
|
37
|
-
if (formRef.current) {
|
|
38
|
-
formRef.current.reset()
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
})
|
|
42
|
-
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
43
|
-
e.preventDefault()
|
|
44
|
-
newEmailMutation.mutate({
|
|
45
|
-
email: e.currentTarget.username.value,
|
|
46
|
-
password: e.currentTarget.password.value,
|
|
47
|
-
quota: e.currentTarget.quota.value,
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
/*const data = new FormData(e.currentTarget)
|
|
51
|
-
const values = Object.fromEntries(data.entries())
|
|
52
|
-
values.operationType = 'newEmail'
|
|
53
|
-
const response = await handleEmailSubmission(values, axiosPrivate, controller)
|
|
54
|
-
if (response.error) {
|
|
55
|
-
setModal({
|
|
56
|
-
title: t('error'),
|
|
57
|
-
body: (
|
|
58
|
-
<div className='p-4'>
|
|
59
|
-
<InfoCard result={{ key: 'danger', title: response.error.message, status: false }} />
|
|
60
|
-
</div>
|
|
61
|
-
),
|
|
62
|
-
headerColor: 'bg-red-700',
|
|
63
|
-
titleColor: 'text-white',
|
|
64
|
-
lang: 'en',
|
|
65
|
-
})
|
|
66
|
-
} else if (response.code === 200) {
|
|
67
|
-
action()
|
|
68
|
-
toast({
|
|
69
|
-
variant: 'success',
|
|
70
|
-
title: t('success'),
|
|
71
|
-
description: response.message,
|
|
72
|
-
})
|
|
73
|
-
}*/
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<form ref={formRef} onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
78
|
-
<div>
|
|
79
|
-
<label htmlFor='username' className='block text-sm font-medium leading-6 text-foreground'>
|
|
80
|
-
{t('email')}
|
|
81
|
-
</label>
|
|
82
|
-
<div className=''>
|
|
83
|
-
<input
|
|
84
|
-
id='username'
|
|
85
|
-
name='username'
|
|
86
|
-
type='text'
|
|
87
|
-
autoComplete='username'
|
|
88
|
-
required
|
|
89
|
-
className='block w-full rounded-md border-0 bg-input p-2.5 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'
|
|
90
|
-
/>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
|
|
94
|
-
<div>
|
|
95
|
-
<label htmlFor='password' className='block text-sm font-medium leading-6 text-foreground'>
|
|
96
|
-
{t('password')}
|
|
97
|
-
</label>
|
|
98
|
-
<div className=''>
|
|
99
|
-
<input
|
|
100
|
-
id='password'
|
|
101
|
-
name='password'
|
|
102
|
-
type='text'
|
|
103
|
-
autoComplete='password'
|
|
104
|
-
required
|
|
105
|
-
className='block w-full rounded-md border-0 bg-input p-2.5 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'
|
|
106
|
-
/>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
<div>
|
|
110
|
-
<label htmlFor='quota' className='block text-sm font-medium leading-6 text-foreground'>
|
|
111
|
-
{t('emailQuota')}
|
|
112
|
-
</label>
|
|
113
|
-
<div className=''>
|
|
114
|
-
<input
|
|
115
|
-
id='quota'
|
|
116
|
-
name='quota'
|
|
117
|
-
type='number'
|
|
118
|
-
autoComplete='quota'
|
|
119
|
-
required
|
|
120
|
-
className='block rounded-md border-0 bg-input p-2.5 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'
|
|
121
|
-
/>
|
|
122
|
-
<Badge className='rounded-sm border-muted-foreground text-muted-foreground' variant='secondary'>
|
|
123
|
-
0 = {t('unlimited')}
|
|
124
|
-
</Badge>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
<div className='mt-4'>
|
|
128
|
-
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>{t('create')}</button>
|
|
129
|
-
</div>
|
|
130
|
-
</form>
|
|
131
|
-
)
|
|
132
|
-
}
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import useModal from '@/hooks/useModal'
|
|
4
|
+
import { Badge } from '@/components/ui/badge'
|
|
5
|
+
import { useToast } from '@/components/ui/use-toast'
|
|
6
|
+
import InfoCard from '@/components/InfoCard'
|
|
7
|
+
import { trpc } from '@/app/_trpc/client'
|
|
8
|
+
|
|
9
|
+
export default function NewEmailForm({ action }: { action: any }) {
|
|
10
|
+
const t = useI18n()
|
|
11
|
+
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
12
|
+
const formRef = React.useRef<HTMLFormElement>(null)
|
|
13
|
+
const { toast } = useToast()
|
|
14
|
+
const newEmailMutation = trpc.cpanelEmails.createEmail.useMutation({
|
|
15
|
+
onError: (error) => {
|
|
16
|
+
setModal({
|
|
17
|
+
title: t('error'),
|
|
18
|
+
body: (
|
|
19
|
+
<div className='p-4'>
|
|
20
|
+
<InfoCard result={{ key: 'danger', title: error.message, status: false }} />
|
|
21
|
+
</div>
|
|
22
|
+
),
|
|
23
|
+
headerColor: 'bg-red-700',
|
|
24
|
+
titleColor: 'text-white',
|
|
25
|
+
lang: 'en',
|
|
26
|
+
})
|
|
27
|
+
},
|
|
28
|
+
onSuccess: (data) => {
|
|
29
|
+
action()
|
|
30
|
+
toast({
|
|
31
|
+
variant: 'success',
|
|
32
|
+
title: t('success'),
|
|
33
|
+
description: data.message,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// Empty the form
|
|
37
|
+
if (formRef.current) {
|
|
38
|
+
formRef.current.reset()
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
43
|
+
e.preventDefault()
|
|
44
|
+
newEmailMutation.mutate({
|
|
45
|
+
email: e.currentTarget.username.value,
|
|
46
|
+
password: e.currentTarget.password.value,
|
|
47
|
+
quota: e.currentTarget.quota.value,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
/*const data = new FormData(e.currentTarget)
|
|
51
|
+
const values = Object.fromEntries(data.entries())
|
|
52
|
+
values.operationType = 'newEmail'
|
|
53
|
+
const response = await handleEmailSubmission(values, axiosPrivate, controller)
|
|
54
|
+
if (response.error) {
|
|
55
|
+
setModal({
|
|
56
|
+
title: t('error'),
|
|
57
|
+
body: (
|
|
58
|
+
<div className='p-4'>
|
|
59
|
+
<InfoCard result={{ key: 'danger', title: response.error.message, status: false }} />
|
|
60
|
+
</div>
|
|
61
|
+
),
|
|
62
|
+
headerColor: 'bg-red-700',
|
|
63
|
+
titleColor: 'text-white',
|
|
64
|
+
lang: 'en',
|
|
65
|
+
})
|
|
66
|
+
} else if (response.code === 200) {
|
|
67
|
+
action()
|
|
68
|
+
toast({
|
|
69
|
+
variant: 'success',
|
|
70
|
+
title: t('success'),
|
|
71
|
+
description: response.message,
|
|
72
|
+
})
|
|
73
|
+
}*/
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<form ref={formRef} onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
78
|
+
<div>
|
|
79
|
+
<label htmlFor='username' className='block text-sm font-medium leading-6 text-foreground'>
|
|
80
|
+
{t('email')}
|
|
81
|
+
</label>
|
|
82
|
+
<div className=''>
|
|
83
|
+
<input
|
|
84
|
+
id='username'
|
|
85
|
+
name='username'
|
|
86
|
+
type='text'
|
|
87
|
+
autoComplete='username'
|
|
88
|
+
required
|
|
89
|
+
className='block w-full rounded-md border-0 bg-input p-2.5 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'
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div>
|
|
95
|
+
<label htmlFor='password' className='block text-sm font-medium leading-6 text-foreground'>
|
|
96
|
+
{t('password')}
|
|
97
|
+
</label>
|
|
98
|
+
<div className=''>
|
|
99
|
+
<input
|
|
100
|
+
id='password'
|
|
101
|
+
name='password'
|
|
102
|
+
type='text'
|
|
103
|
+
autoComplete='password'
|
|
104
|
+
required
|
|
105
|
+
className='block w-full rounded-md border-0 bg-input p-2.5 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'
|
|
106
|
+
/>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
<div>
|
|
110
|
+
<label htmlFor='quota' className='block text-sm font-medium leading-6 text-foreground'>
|
|
111
|
+
{t('emailQuota')}
|
|
112
|
+
</label>
|
|
113
|
+
<div className=''>
|
|
114
|
+
<input
|
|
115
|
+
id='quota'
|
|
116
|
+
name='quota'
|
|
117
|
+
type='number'
|
|
118
|
+
autoComplete='quota'
|
|
119
|
+
required
|
|
120
|
+
className='block rounded-md border-0 bg-input p-2.5 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'
|
|
121
|
+
/>
|
|
122
|
+
<Badge className='rounded-sm border-muted-foreground text-muted-foreground' variant='secondary'>
|
|
123
|
+
0 = {t('unlimited')}
|
|
124
|
+
</Badge>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
<div className='mt-4'>
|
|
128
|
+
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>{t('create')}</button>
|
|
129
|
+
</div>
|
|
130
|
+
</form>
|
|
131
|
+
)
|
|
132
|
+
}
|