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,85 +1,85 @@
|
|
|
1
|
-
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import useModal from '@/hooks/useModal'
|
|
4
|
-
import { useToast } from '@/components/ui/use-toast'
|
|
5
|
-
import InfoCard from '@/components/InfoCard'
|
|
6
|
-
import { trpc } from '@/app/_trpc/client'
|
|
7
|
-
|
|
8
|
-
export default function EmailPasswordForm({ email, action }: { email: string; action: any }) {
|
|
9
|
-
const t = useI18n()
|
|
10
|
-
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
11
|
-
|
|
12
|
-
const { toast } = useToast()
|
|
13
|
-
const quotaMutation = trpc.cpanelEmails.passwordChange.useMutation({
|
|
14
|
-
onError: (error) => {
|
|
15
|
-
setModal({
|
|
16
|
-
title: t('error'),
|
|
17
|
-
body: (
|
|
18
|
-
<div className='p-4'>
|
|
19
|
-
<InfoCard result={{ key: 'danger', title: error.message, status: false }} />
|
|
20
|
-
</div>
|
|
21
|
-
),
|
|
22
|
-
headerColor: 'bg-red-700',
|
|
23
|
-
titleColor: 'text-white',
|
|
24
|
-
lang: 'en',
|
|
25
|
-
})
|
|
26
|
-
},
|
|
27
|
-
onSuccess: (data) => {
|
|
28
|
-
action()
|
|
29
|
-
setModal(null)
|
|
30
|
-
setModalResponse(null)
|
|
31
|
-
toast({
|
|
32
|
-
variant: 'success',
|
|
33
|
-
title: t('success'),
|
|
34
|
-
})
|
|
35
|
-
},
|
|
36
|
-
})
|
|
37
|
-
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
38
|
-
e.preventDefault()
|
|
39
|
-
quotaMutation.mutate({
|
|
40
|
-
email,
|
|
41
|
-
password: e.currentTarget.password.value,
|
|
42
|
-
passwordConfirm: e.currentTarget.passwordConfirm.value,
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<form onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
48
|
-
<div>
|
|
49
|
-
<label htmlFor='password' className='block text-sm font-medium leading-6 text-foreground'>
|
|
50
|
-
{t('newPassword')}
|
|
51
|
-
</label>
|
|
52
|
-
<div className=''>
|
|
53
|
-
<input
|
|
54
|
-
id='password'
|
|
55
|
-
name='password'
|
|
56
|
-
type='text'
|
|
57
|
-
autoComplete='password'
|
|
58
|
-
required
|
|
59
|
-
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'
|
|
60
|
-
/>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
<div>
|
|
64
|
-
<label htmlFor='passwordConfirm' className='block text-sm font-medium leading-6 text-foreground'>
|
|
65
|
-
{t('confirmNewPassword')}
|
|
66
|
-
</label>
|
|
67
|
-
<div className=''>
|
|
68
|
-
<input
|
|
69
|
-
id='passwordConfirm'
|
|
70
|
-
name='passwordConfirm'
|
|
71
|
-
type='text'
|
|
72
|
-
autoComplete='passwordConfirm'
|
|
73
|
-
required
|
|
74
|
-
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'
|
|
75
|
-
/>
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
<div className='mt-4'>
|
|
79
|
-
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
80
|
-
{t('changePassword')}
|
|
81
|
-
</button>
|
|
82
|
-
</div>
|
|
83
|
-
</form>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import useModal from '@/hooks/useModal'
|
|
4
|
+
import { useToast } from '@/components/ui/use-toast'
|
|
5
|
+
import InfoCard from '@/components/InfoCard'
|
|
6
|
+
import { trpc } from '@/app/_trpc/client'
|
|
7
|
+
|
|
8
|
+
export default function EmailPasswordForm({ email, action }: { email: string; action: any }) {
|
|
9
|
+
const t = useI18n()
|
|
10
|
+
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
11
|
+
|
|
12
|
+
const { toast } = useToast()
|
|
13
|
+
const quotaMutation = trpc.cpanelEmails.passwordChange.useMutation({
|
|
14
|
+
onError: (error) => {
|
|
15
|
+
setModal({
|
|
16
|
+
title: t('error'),
|
|
17
|
+
body: (
|
|
18
|
+
<div className='p-4'>
|
|
19
|
+
<InfoCard result={{ key: 'danger', title: error.message, status: false }} />
|
|
20
|
+
</div>
|
|
21
|
+
),
|
|
22
|
+
headerColor: 'bg-red-700',
|
|
23
|
+
titleColor: 'text-white',
|
|
24
|
+
lang: 'en',
|
|
25
|
+
})
|
|
26
|
+
},
|
|
27
|
+
onSuccess: (data) => {
|
|
28
|
+
action()
|
|
29
|
+
setModal(null)
|
|
30
|
+
setModalResponse(null)
|
|
31
|
+
toast({
|
|
32
|
+
variant: 'success',
|
|
33
|
+
title: t('success'),
|
|
34
|
+
})
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
38
|
+
e.preventDefault()
|
|
39
|
+
quotaMutation.mutate({
|
|
40
|
+
email,
|
|
41
|
+
password: e.currentTarget.password.value,
|
|
42
|
+
passwordConfirm: e.currentTarget.passwordConfirm.value,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<form onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
48
|
+
<div>
|
|
49
|
+
<label htmlFor='password' className='block text-sm font-medium leading-6 text-foreground'>
|
|
50
|
+
{t('newPassword')}
|
|
51
|
+
</label>
|
|
52
|
+
<div className=''>
|
|
53
|
+
<input
|
|
54
|
+
id='password'
|
|
55
|
+
name='password'
|
|
56
|
+
type='text'
|
|
57
|
+
autoComplete='password'
|
|
58
|
+
required
|
|
59
|
+
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'
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
<div>
|
|
64
|
+
<label htmlFor='passwordConfirm' className='block text-sm font-medium leading-6 text-foreground'>
|
|
65
|
+
{t('confirmNewPassword')}
|
|
66
|
+
</label>
|
|
67
|
+
<div className=''>
|
|
68
|
+
<input
|
|
69
|
+
id='passwordConfirm'
|
|
70
|
+
name='passwordConfirm'
|
|
71
|
+
type='text'
|
|
72
|
+
autoComplete='passwordConfirm'
|
|
73
|
+
required
|
|
74
|
+
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'
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
<div className='mt-4'>
|
|
79
|
+
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
80
|
+
{t('changePassword')}
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
</form>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
@@ -1,73 +1,73 @@
|
|
|
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 EmailQuotaForm({ email, action }: { email: string; action: any }) {
|
|
10
|
-
const t = useI18n()
|
|
11
|
-
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
12
|
-
const { toast } = useToast()
|
|
13
|
-
|
|
14
|
-
const quotaMutation = trpc.cpanelEmails.quotaChange.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
|
-
setModal(null)
|
|
31
|
-
setModalResponse(null)
|
|
32
|
-
toast({
|
|
33
|
-
variant: 'success',
|
|
34
|
-
title: t('success'),
|
|
35
|
-
})
|
|
36
|
-
},
|
|
37
|
-
})
|
|
38
|
-
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
39
|
-
e.preventDefault()
|
|
40
|
-
quotaMutation.mutate({
|
|
41
|
-
email,
|
|
42
|
-
quota: e.currentTarget.quota.value,
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<form onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
48
|
-
<div>
|
|
49
|
-
<label htmlFor='quota' className='block text-sm font-medium leading-6 text-foreground'>
|
|
50
|
-
{t('emailQuota')}
|
|
51
|
-
</label>
|
|
52
|
-
<div className=''>
|
|
53
|
-
<input
|
|
54
|
-
id='quota'
|
|
55
|
-
name='quota'
|
|
56
|
-
type='number'
|
|
57
|
-
autoComplete='quota'
|
|
58
|
-
required
|
|
59
|
-
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'
|
|
60
|
-
/>
|
|
61
|
-
<Badge className='rounded-sm border-muted-foreground text-muted-foreground' variant='secondary'>
|
|
62
|
-
0 = {t('unlimited')}
|
|
63
|
-
</Badge>
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
<div className='mt-4'>
|
|
67
|
-
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
68
|
-
{t('updateQuota')}
|
|
69
|
-
</button>
|
|
70
|
-
</div>
|
|
71
|
-
</form>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
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 EmailQuotaForm({ email, action }: { email: string; action: any }) {
|
|
10
|
+
const t = useI18n()
|
|
11
|
+
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
12
|
+
const { toast } = useToast()
|
|
13
|
+
|
|
14
|
+
const quotaMutation = trpc.cpanelEmails.quotaChange.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
|
+
setModal(null)
|
|
31
|
+
setModalResponse(null)
|
|
32
|
+
toast({
|
|
33
|
+
variant: 'success',
|
|
34
|
+
title: t('success'),
|
|
35
|
+
})
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
39
|
+
e.preventDefault()
|
|
40
|
+
quotaMutation.mutate({
|
|
41
|
+
email,
|
|
42
|
+
quota: e.currentTarget.quota.value,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<form onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
48
|
+
<div>
|
|
49
|
+
<label htmlFor='quota' className='block text-sm font-medium leading-6 text-foreground'>
|
|
50
|
+
{t('emailQuota')}
|
|
51
|
+
</label>
|
|
52
|
+
<div className=''>
|
|
53
|
+
<input
|
|
54
|
+
id='quota'
|
|
55
|
+
name='quota'
|
|
56
|
+
type='number'
|
|
57
|
+
autoComplete='quota'
|
|
58
|
+
required
|
|
59
|
+
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'
|
|
60
|
+
/>
|
|
61
|
+
<Badge className='rounded-sm border-muted-foreground text-muted-foreground' variant='secondary'>
|
|
62
|
+
0 = {t('unlimited')}
|
|
63
|
+
</Badge>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
<div className='mt-4'>
|
|
67
|
+
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
68
|
+
{t('updateQuota')}
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
</form>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useEffect } from 'react'
|
|
4
|
-
import { EmailItem } from 'nextjs-cms/core/types'
|
|
5
|
-
import { useI18n } from 'nextjs-cms/translations/client'
|
|
6
|
-
import ContainerBox from '@/components/ContainerBox'
|
|
7
|
-
import NewEmailForm from '@/components/NewEmailForm'
|
|
8
|
-
import EmailCard from '@/components/EmailCard'
|
|
9
|
-
import { trpc } from '@/app/_trpc/client'
|
|
10
|
-
|
|
11
|
-
const EmailsPage = () => {
|
|
12
|
-
const t = useI18n()
|
|
13
|
-
const controller = new AbortController()
|
|
14
|
-
|
|
15
|
-
const { isLoading, isError, data, error, refetch } = trpc.cpanelEmails.getEmails.useQuery()
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
return () => {
|
|
19
|
-
controller.abort()
|
|
20
|
-
}
|
|
21
|
-
}, [])
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div className='bg-white dark:bg-slate-900'>
|
|
25
|
-
<div className='bg-linear-to-r from-sky-200 via-emerald-300 to-blue-600 p-8 font-extrabold text-foreground dark:from-blue-800 dark:via-amber-700 dark:to-rose-900'>
|
|
26
|
-
<h1 className='text-3xl'>{t('emailAccounts')}</h1>
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<div className='flex flex-col gap-2 p-4'>
|
|
30
|
-
<ContainerBox title={t('createNewEmailAccount')}>
|
|
31
|
-
<NewEmailForm action={() => refetch()} />
|
|
32
|
-
</ContainerBox>
|
|
33
|
-
|
|
34
|
-
{isLoading && <div>{t('loading')}</div>}
|
|
35
|
-
{data && data.emails && data.emails.length > 0 && (
|
|
36
|
-
<ContainerBox title={t('emailAccountsList')}>
|
|
37
|
-
<div className='mt-2 grid w-full grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3'>
|
|
38
|
-
{data.emails.map((email: EmailItem) => (
|
|
39
|
-
<EmailCard key={email.user} action={() => refetch()} email={email} />
|
|
40
|
-
))}
|
|
41
|
-
</div>
|
|
42
|
-
</ContainerBox>
|
|
43
|
-
)}
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export default EmailsPage
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react'
|
|
4
|
+
import { EmailItem } from 'nextjs-cms/core/types'
|
|
5
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
6
|
+
import ContainerBox from '@/components/ContainerBox'
|
|
7
|
+
import NewEmailForm from '@/components/NewEmailForm'
|
|
8
|
+
import EmailCard from '@/components/EmailCard'
|
|
9
|
+
import { trpc } from '@/app/_trpc/client'
|
|
10
|
+
|
|
11
|
+
const EmailsPage = () => {
|
|
12
|
+
const t = useI18n()
|
|
13
|
+
const controller = new AbortController()
|
|
14
|
+
|
|
15
|
+
const { isLoading, isError, data, error, refetch } = trpc.cpanelEmails.getEmails.useQuery()
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
return () => {
|
|
19
|
+
controller.abort()
|
|
20
|
+
}
|
|
21
|
+
}, [])
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div className='bg-white dark:bg-slate-900'>
|
|
25
|
+
<div className='bg-linear-to-r from-sky-200 via-emerald-300 to-blue-600 p-8 font-extrabold text-foreground dark:from-blue-800 dark:via-amber-700 dark:to-rose-900'>
|
|
26
|
+
<h1 className='text-3xl'>{t('emailAccounts')}</h1>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div className='flex flex-col gap-2 p-4'>
|
|
30
|
+
<ContainerBox title={t('createNewEmailAccount')}>
|
|
31
|
+
<NewEmailForm action={() => refetch()} />
|
|
32
|
+
</ContainerBox>
|
|
33
|
+
|
|
34
|
+
{isLoading && <div>{t('loading')}</div>}
|
|
35
|
+
{data && data.emails && data.emails.length > 0 && (
|
|
36
|
+
<ContainerBox title={t('emailAccountsList')}>
|
|
37
|
+
<div className='mt-2 grid w-full grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3'>
|
|
38
|
+
{data.emails.map((email: EmailItem) => (
|
|
39
|
+
<EmailCard key={email.user} action={() => refetch()} email={email} />
|
|
40
|
+
))}
|
|
41
|
+
</div>
|
|
42
|
+
</ContainerBox>
|
|
43
|
+
)}
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default EmailsPage
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Alert, AlertDescription } from './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 './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
|
}
|
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import { PhotoGalleryItem } from 'nextjs-cms/core/types'
|
|
2
|
-
import { useI18n } from 'nextjs-cms/translations/client'
|
|
3
|
-
import { MinusIcon } from '@radix-ui/react-icons'
|
|
4
|
-
import ProtectedImage from '@/components/ProtectedImage'
|
|
5
|
-
import useModal from '@/hooks/useModal'
|
|
6
|
-
import { useToast } from '@/components/ui/use-toast'
|
|
7
|
-
import { trpc } from '@/app/_trpc/client'
|
|
8
|
-
|
|
9
|
-
const GalleryPhoto = ({ item, sectionName, action }: { item: PhotoGalleryItem; sectionName: string; action?: any }) => {
|
|
10
|
-
const t = useI18n()
|
|
11
|
-
const { setModal, setModalResponse } = useModal()
|
|
12
|
-
const deleteMutation = trpc.gallery.deletePhoto.useMutation({
|
|
13
|
-
onError: (error) => {
|
|
14
|
-
toast({
|
|
15
|
-
variant: 'destructive',
|
|
16
|
-
title: t('deleteGalleryPhoto'),
|
|
17
|
-
description: error.message,
|
|
18
|
-
})
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
onSuccess: (data) => {
|
|
22
|
-
setModal(null)
|
|
23
|
-
setModalResponse(null)
|
|
24
|
-
toast({
|
|
25
|
-
variant: 'success',
|
|
26
|
-
title: t('galleryPhotoDeleted'),
|
|
27
|
-
})
|
|
28
|
-
action()
|
|
29
|
-
},
|
|
30
|
-
})
|
|
31
|
-
const { toast } = useToast()
|
|
32
|
-
const handlePhotoDelete = async () => {
|
|
33
|
-
deleteMutation.mutate({
|
|
34
|
-
sectionName: sectionName,
|
|
35
|
-
photoName: item.photo,
|
|
36
|
-
referenceId: item.referenceId,
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
return (
|
|
40
|
-
<div className='relative'>
|
|
41
|
-
{/* Delete Button */}
|
|
42
|
-
<button
|
|
43
|
-
type='button'
|
|
44
|
-
className='absolute -end-2 -top-2 z-10 h-6 w-6 rounded-full bg-red-500 p-1'
|
|
45
|
-
onClick={() => {
|
|
46
|
-
setModal({
|
|
47
|
-
title: t('deleteGalleryPhoto'),
|
|
48
|
-
body: (
|
|
49
|
-
<div className='p-4'>
|
|
50
|
-
<div className='flex flex-col gap-4'>
|
|
51
|
-
<div>{t('deleteGalleryPhotoText')}</div>
|
|
52
|
-
<div className='flex gap-2'>
|
|
53
|
-
<button
|
|
54
|
-
className='rounded bg-green-600 px-2 py-1 text-white'
|
|
55
|
-
onClick={handlePhotoDelete}
|
|
56
|
-
>
|
|
57
|
-
Yes
|
|
58
|
-
</button>
|
|
59
|
-
<button
|
|
60
|
-
className='rounded bg-red-800 px-2 py-1 text-white'
|
|
61
|
-
onClick={() => {
|
|
62
|
-
setModal(null)
|
|
63
|
-
}}
|
|
64
|
-
>
|
|
65
|
-
No
|
|
66
|
-
</button>
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
),
|
|
71
|
-
headerColor: 'bg-red-700',
|
|
72
|
-
titleColor: 'text-white',
|
|
73
|
-
lang: 'en',
|
|
74
|
-
})
|
|
75
|
-
}}
|
|
76
|
-
>
|
|
77
|
-
<MinusIcon className='text-white' />
|
|
78
|
-
</button>
|
|
79
|
-
<ProtectedImage
|
|
80
|
-
section={sectionName}
|
|
81
|
-
photo={item.photo}
|
|
82
|
-
isThumb={true}
|
|
83
|
-
alt={item.photo}
|
|
84
|
-
height={150}
|
|
85
|
-
width={150}
|
|
86
|
-
// fill={true}
|
|
87
|
-
className='mb-4 rounded p-1 ring-3 ring-gray-400'
|
|
88
|
-
/>
|
|
89
|
-
</div>
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export default GalleryPhoto
|
|
1
|
+
import { PhotoGalleryItem } from 'nextjs-cms/core/types'
|
|
2
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
3
|
+
import { MinusIcon } from '@radix-ui/react-icons'
|
|
4
|
+
import ProtectedImage from '@/components/ProtectedImage'
|
|
5
|
+
import useModal from '@/hooks/useModal'
|
|
6
|
+
import { useToast } from '@/components/ui/use-toast'
|
|
7
|
+
import { trpc } from '@/app/_trpc/client'
|
|
8
|
+
|
|
9
|
+
const GalleryPhoto = ({ item, sectionName, action }: { item: PhotoGalleryItem; sectionName: string; action?: any }) => {
|
|
10
|
+
const t = useI18n()
|
|
11
|
+
const { setModal, setModalResponse } = useModal()
|
|
12
|
+
const deleteMutation = trpc.gallery.deletePhoto.useMutation({
|
|
13
|
+
onError: (error) => {
|
|
14
|
+
toast({
|
|
15
|
+
variant: 'destructive',
|
|
16
|
+
title: t('deleteGalleryPhoto'),
|
|
17
|
+
description: error.message,
|
|
18
|
+
})
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
onSuccess: (data) => {
|
|
22
|
+
setModal(null)
|
|
23
|
+
setModalResponse(null)
|
|
24
|
+
toast({
|
|
25
|
+
variant: 'success',
|
|
26
|
+
title: t('galleryPhotoDeleted'),
|
|
27
|
+
})
|
|
28
|
+
action()
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
const { toast } = useToast()
|
|
32
|
+
const handlePhotoDelete = async () => {
|
|
33
|
+
deleteMutation.mutate({
|
|
34
|
+
sectionName: sectionName,
|
|
35
|
+
photoName: item.photo,
|
|
36
|
+
referenceId: item.referenceId,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
return (
|
|
40
|
+
<div className='relative'>
|
|
41
|
+
{/* Delete Button */}
|
|
42
|
+
<button
|
|
43
|
+
type='button'
|
|
44
|
+
className='absolute -end-2 -top-2 z-10 h-6 w-6 rounded-full bg-red-500 p-1'
|
|
45
|
+
onClick={() => {
|
|
46
|
+
setModal({
|
|
47
|
+
title: t('deleteGalleryPhoto'),
|
|
48
|
+
body: (
|
|
49
|
+
<div className='p-4'>
|
|
50
|
+
<div className='flex flex-col gap-4'>
|
|
51
|
+
<div>{t('deleteGalleryPhotoText')}</div>
|
|
52
|
+
<div className='flex gap-2'>
|
|
53
|
+
<button
|
|
54
|
+
className='rounded bg-green-600 px-2 py-1 text-white'
|
|
55
|
+
onClick={handlePhotoDelete}
|
|
56
|
+
>
|
|
57
|
+
Yes
|
|
58
|
+
</button>
|
|
59
|
+
<button
|
|
60
|
+
className='rounded bg-red-800 px-2 py-1 text-white'
|
|
61
|
+
onClick={() => {
|
|
62
|
+
setModal(null)
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
No
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
),
|
|
71
|
+
headerColor: 'bg-red-700',
|
|
72
|
+
titleColor: 'text-white',
|
|
73
|
+
lang: 'en',
|
|
74
|
+
})
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
<MinusIcon className='text-white' />
|
|
78
|
+
</button>
|
|
79
|
+
<ProtectedImage
|
|
80
|
+
section={sectionName}
|
|
81
|
+
photo={item.photo}
|
|
82
|
+
isThumb={true}
|
|
83
|
+
alt={item.photo}
|
|
84
|
+
height={150}
|
|
85
|
+
width={150}
|
|
86
|
+
// fill={true}
|
|
87
|
+
className='mb-4 rounded p-1 ring-3 ring-gray-400'
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default GalleryPhoto
|