create-nextjs-cms 0.5.8
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 -0
- package/README.md +71 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +395 -0
- package/dist/lib/utils.d.ts +11 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +48 -0
- package/package.json +44 -0
- package/templates/default/.env +24 -0
- package/templates/default/.env.development +8 -0
- package/templates/default/.eslintrc.json +5 -0
- package/templates/default/.prettierignore +7 -0
- package/templates/default/.prettierrc.json +19 -0
- package/templates/default/CHANGELOG.md +77 -0
- package/templates/default/README.md +45 -0
- package/templates/default/app/(auth)/auth/login/LoginPage.tsx +175 -0
- package/templates/default/app/(auth)/auth/login/page.tsx +12 -0
- package/templates/default/app/(rootLayout)/admins/page.tsx +5 -0
- package/templates/default/app/(rootLayout)/advanced/page.tsx +5 -0
- package/templates/default/app/(rootLayout)/analytics/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/browse/[section]/[page]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/categorized/[section]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/dashboard/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/emails/page.tsx +6 -0
- package/templates/default/app/(rootLayout)/layout.tsx +5 -0
- package/templates/default/app/(rootLayout)/loading.tsx +10 -0
- package/templates/default/app/(rootLayout)/log/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/new/[section]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/page.tsx +9 -0
- package/templates/default/app/(rootLayout)/section/[section]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/settings/page.tsx +7 -0
- package/templates/default/app/_trpc/client.ts +4 -0
- package/templates/default/app/api/auth/csrf/route.ts +25 -0
- package/templates/default/app/api/auth/refresh/route.ts +10 -0
- package/templates/default/app/api/auth/route.ts +23 -0
- package/templates/default/app/api/auth/session/route.ts +20 -0
- package/templates/default/app/api/editor/photo/route.ts +42 -0
- package/templates/default/app/api/photo/route.ts +27 -0
- package/templates/default/app/api/placeholder/route.ts +7 -0
- package/templates/default/app/api/submit/section/item/[slug]/route.ts +63 -0
- package/templates/default/app/api/submit/section/item/route.ts +53 -0
- package/templates/default/app/api/submit/section/simple/route.ts +54 -0
- package/templates/default/app/api/trpc/[trpc]/route.ts +33 -0
- package/templates/default/app/api/video/route.ts +174 -0
- package/templates/default/app/dictionaries.ts +14 -0
- package/templates/default/app/layout.tsx +28 -0
- package/templates/default/app/providers.tsx +151 -0
- package/templates/default/cli.ts +4 -0
- package/templates/default/components/AdminCard.tsx +163 -0
- package/templates/default/components/AdminEditPage.tsx +123 -0
- package/templates/default/components/AdminPrivilegeCard.tsx +184 -0
- package/templates/default/components/AdminsPage.tsx +43 -0
- package/templates/default/components/AdvancedSettingsPage.tsx +167 -0
- package/templates/default/components/AnalyticsPage.tsx +127 -0
- package/templates/default/components/BarChartBox.tsx +43 -0
- package/templates/default/components/BrowsePage.tsx +119 -0
- package/templates/default/components/CategorizedSectionPage.tsx +36 -0
- package/templates/default/components/CategoryDeleteConfirmPage.tsx +129 -0
- package/templates/default/components/CategorySectionSelectInput.tsx +139 -0
- package/templates/default/components/ConditionalFields.tsx +49 -0
- package/templates/default/components/ContainerBox.tsx +24 -0
- package/templates/default/components/DashboardPage.tsx +187 -0
- package/templates/default/components/DashboardPageAlt.tsx +43 -0
- package/templates/default/components/DefaultNavItems.tsx +3 -0
- package/templates/default/components/Dropzone.tsx +153 -0
- package/templates/default/components/EmailCard.tsx +137 -0
- package/templates/default/components/EmailPasswordForm.tsx +84 -0
- package/templates/default/components/EmailQuotaForm.tsx +72 -0
- package/templates/default/components/EmailsPage.tsx +48 -0
- package/templates/default/components/GalleryPhoto.tsx +93 -0
- package/templates/default/components/InfoCard.tsx +94 -0
- package/templates/default/components/ItemEditPage.tsx +217 -0
- package/templates/default/components/Layout.tsx +70 -0
- package/templates/default/components/LoadingSpinners.tsx +67 -0
- package/templates/default/components/LogPage.tsx +17 -0
- package/templates/default/components/Modal.tsx +99 -0
- package/templates/default/components/Navbar.tsx +29 -0
- package/templates/default/components/NavbarAlt.tsx +182 -0
- package/templates/default/components/NewAdminForm.tsx +172 -0
- package/templates/default/components/NewEmailForm.tsx +131 -0
- package/templates/default/components/NewPage.tsx +206 -0
- package/templates/default/components/NewVariantComponent.tsx +228 -0
- package/templates/default/components/PhotoGallery.tsx +35 -0
- package/templates/default/components/PieChartBox.tsx +101 -0
- package/templates/default/components/ProgressBar.tsx +24 -0
- package/templates/default/components/ProtectedDocument.tsx +78 -0
- package/templates/default/components/ProtectedImage.tsx +143 -0
- package/templates/default/components/ProtectedVideo.tsx +76 -0
- package/templates/default/components/SectionItemCard.tsx +143 -0
- package/templates/default/components/SectionItemStatusBadge.tsx +16 -0
- package/templates/default/components/SectionPage.tsx +124 -0
- package/templates/default/components/SelectBox.tsx +99 -0
- package/templates/default/components/SelectInputButtons.tsx +124 -0
- package/templates/default/components/SettingsPage.tsx +238 -0
- package/templates/default/components/Sidebar.tsx +209 -0
- package/templates/default/components/SidebarDropdownItem.tsx +74 -0
- package/templates/default/components/SidebarItem.tsx +19 -0
- package/templates/default/components/TempPage.tsx +12 -0
- package/templates/default/components/ThemeProvider.tsx +8 -0
- package/templates/default/components/TooltipComponent.tsx +27 -0
- package/templates/default/components/VariantCard.tsx +123 -0
- package/templates/default/components/VariantEditPage.tsx +229 -0
- package/templates/default/components/analytics/BounceRate.tsx +69 -0
- package/templates/default/components/analytics/LivePageViews.tsx +54 -0
- package/templates/default/components/analytics/LiveUsersCount.tsx +32 -0
- package/templates/default/components/analytics/MonthlyPageViews.tsx +41 -0
- package/templates/default/components/analytics/TopCountries.tsx +51 -0
- package/templates/default/components/analytics/TopDevices.tsx +45 -0
- package/templates/default/components/analytics/TopMediums.tsx +57 -0
- package/templates/default/components/analytics/TopSources.tsx +44 -0
- package/templates/default/components/analytics/TotalPageViews.tsx +40 -0
- package/templates/default/components/analytics/TotalSessions.tsx +40 -0
- package/templates/default/components/analytics/TotalUniqueUsers.tsx +40 -0
- package/templates/default/components/custom/RightHomeRoomVariantCard.tsx +137 -0
- package/templates/default/components/dndKit/Draggable.tsx +21 -0
- package/templates/default/components/dndKit/Droppable.tsx +20 -0
- package/templates/default/components/dndKit/SortableItem.tsx +18 -0
- package/templates/default/components/form/DateRangeFormInput.tsx +55 -0
- package/templates/default/components/form/Form.tsx +298 -0
- package/templates/default/components/form/FormInputElement.tsx +68 -0
- package/templates/default/components/form/FormInputs.tsx +108 -0
- package/templates/default/components/form/helpers/util.ts +20 -0
- package/templates/default/components/form/inputs/CheckboxFormInput.tsx +33 -0
- package/templates/default/components/form/inputs/ColorFormInput.tsx +44 -0
- package/templates/default/components/form/inputs/DateFormInput.tsx +107 -0
- package/templates/default/components/form/inputs/DocumentFormInput.tsx +124 -0
- package/templates/default/components/form/inputs/MapFormInput.tsx +139 -0
- package/templates/default/components/form/inputs/MultipleSelectFormInput.tsx +150 -0
- package/templates/default/components/form/inputs/NumberFormInput.tsx +42 -0
- package/templates/default/components/form/inputs/PasswordFormInput.tsx +47 -0
- package/templates/default/components/form/inputs/PhotoFormInput.tsx +218 -0
- package/templates/default/components/form/inputs/RichTextFormInput.tsx +133 -0
- package/templates/default/components/form/inputs/SelectFormInput.tsx +164 -0
- package/templates/default/components/form/inputs/TagsFormInput.tsx +63 -0
- package/templates/default/components/form/inputs/TextFormInput.tsx +48 -0
- package/templates/default/components/form/inputs/TextareaFormInput.tsx +47 -0
- package/templates/default/components/form/inputs/VideoFormInput.tsx +117 -0
- package/templates/default/components/pagination/Pagination.tsx +36 -0
- package/templates/default/components/pagination/PaginationButtons.tsx +145 -0
- package/templates/default/components/ui/accordion.tsx +57 -0
- package/templates/default/components/ui/alert.tsx +46 -0
- package/templates/default/components/ui/badge.tsx +33 -0
- package/templates/default/components/ui/button.tsx +57 -0
- package/templates/default/components/ui/calendar.tsx +68 -0
- package/templates/default/components/ui/card.tsx +76 -0
- package/templates/default/components/ui/checkbox.tsx +29 -0
- package/templates/default/components/ui/dropdown-menu.tsx +205 -0
- package/templates/default/components/ui/input.tsx +25 -0
- package/templates/default/components/ui/label.tsx +26 -0
- package/templates/default/components/ui/popover.tsx +31 -0
- package/templates/default/components/ui/scroll-area.tsx +42 -0
- package/templates/default/components/ui/select.tsx +164 -0
- package/templates/default/components/ui/sheet.tsx +107 -0
- package/templates/default/components/ui/switch.tsx +29 -0
- package/templates/default/components/ui/table.tsx +120 -0
- package/templates/default/components/ui/tabs.tsx +55 -0
- package/templates/default/components/ui/toast.tsx +113 -0
- package/templates/default/components/ui/toaster.tsx +35 -0
- package/templates/default/components/ui/tooltip.tsx +30 -0
- package/templates/default/components/ui/use-toast.ts +188 -0
- package/templates/default/components.json +16 -0
- package/templates/default/context/ModalProvider.tsx +53 -0
- package/templates/default/drizzle.config.ts +4 -0
- package/templates/default/dynamic-schemas/schema.ts +373 -0
- package/templates/default/env/env.js +130 -0
- package/templates/default/envConfig.ts +4 -0
- package/templates/default/hooks/useModal.ts +8 -0
- package/templates/default/lib/apiHelpers.ts +106 -0
- package/templates/default/lz.config.ts +40 -0
- package/templates/default/middleware.ts +33 -0
- package/templates/default/next.config.ts +46 -0
- package/templates/default/package.json +134 -0
- package/templates/default/postcss.config.js +6 -0
- package/templates/default/postinstall.js +14 -0
- package/templates/default/public/blank_avatar.png +0 -0
- package/templates/default/public/favicon.ico +0 -0
- package/templates/default/public/img/placeholder.svg +1 -0
- package/templates/default/public/lazemni_logo.png +0 -0
- package/templates/default/public/next.svg +1 -0
- package/templates/default/public/vercel.svg +1 -0
- package/templates/default/section-tests.ts +92 -0
- package/templates/default/styles/globals.css +88 -0
- package/templates/default/tailwind.config.js +95 -0
- package/templates/default/test.ts +77 -0
- package/templates/default/tsconfig.json +44 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import getString from 'nextjs-cms/translations'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { EmailItem } from 'nextjs-cms/core/types'
|
|
4
|
+
import useModal from '@/hooks/useModal'
|
|
5
|
+
import { useToast } from '@/components/ui/use-toast'
|
|
6
|
+
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
|
|
7
|
+
import { Button } from '@/components/ui/button'
|
|
8
|
+
import ProgressBar from '@/components/ProgressBar'
|
|
9
|
+
import EmailQuotaForm from '@/components/EmailQuotaForm'
|
|
10
|
+
import EmailPasswordForm from '@/components/EmailPasswordForm'
|
|
11
|
+
import { trpc } from '@/app/_trpc/client'
|
|
12
|
+
|
|
13
|
+
export default function EmailCard({ email, action }: { email: EmailItem; action: any }) {
|
|
14
|
+
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
15
|
+
const { toast } = useToast()
|
|
16
|
+
|
|
17
|
+
const deleteMutation = trpc.cpanel.deleteEmail.useMutation({
|
|
18
|
+
onError: (error) => {
|
|
19
|
+
setModalResponse({
|
|
20
|
+
message: error.message,
|
|
21
|
+
messageColor: 'text-red-900',
|
|
22
|
+
borderColor: 'border-red-600',
|
|
23
|
+
bgColor: 'bg-red-200',
|
|
24
|
+
})
|
|
25
|
+
},
|
|
26
|
+
onSuccess: (data) => {
|
|
27
|
+
action()
|
|
28
|
+
setModal(null)
|
|
29
|
+
setModalResponse(null)
|
|
30
|
+
toast({
|
|
31
|
+
variant: 'success',
|
|
32
|
+
title: getString('deleteEmailAccount'),
|
|
33
|
+
description: data.message,
|
|
34
|
+
})
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
const deleteEmail = async () => {
|
|
38
|
+
deleteMutation.mutate(email.user)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Card className='border border-gray-400 shadow-sm'>
|
|
43
|
+
<CardHeader>
|
|
44
|
+
<CardTitle>
|
|
45
|
+
<div className='flex flex-row items-center'>
|
|
46
|
+
<div className='flex flex-col break-all'>
|
|
47
|
+
<div className='text-sm font-medium text-foreground'>
|
|
48
|
+
<div className='me-2 font-bold'>{email.email}</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</CardTitle>
|
|
53
|
+
</CardHeader>
|
|
54
|
+
<CardContent>
|
|
55
|
+
{email.humandiskused} / {email.humandiskquota !== 'None' ? email.humandiskquota : email.diskquota}
|
|
56
|
+
<ProgressBar variant='determinate' value={parseInt(email.diskusedpercent)} />
|
|
57
|
+
</CardContent>
|
|
58
|
+
<CardFooter className='flex flex-wrap gap-1'>
|
|
59
|
+
<Button
|
|
60
|
+
size='sm'
|
|
61
|
+
variant='default'
|
|
62
|
+
onClick={() => {
|
|
63
|
+
setModal({
|
|
64
|
+
title: getString('emailQuota'),
|
|
65
|
+
body: (
|
|
66
|
+
<div className='p-4'>
|
|
67
|
+
<EmailQuotaForm email={email.user} action={() => action()} />
|
|
68
|
+
</div>
|
|
69
|
+
),
|
|
70
|
+
headerColor: 'bg-sky-700',
|
|
71
|
+
titleColor: 'text-white',
|
|
72
|
+
lang: 'en',
|
|
73
|
+
})
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
{getString('quota')}
|
|
77
|
+
</Button>
|
|
78
|
+
<Button
|
|
79
|
+
size='sm'
|
|
80
|
+
variant='default'
|
|
81
|
+
onClick={() => {
|
|
82
|
+
setModal({
|
|
83
|
+
title: getString('change_password'),
|
|
84
|
+
body: (
|
|
85
|
+
<div className='p-4'>
|
|
86
|
+
<EmailPasswordForm email={email.user} action={() => action()} />
|
|
87
|
+
</div>
|
|
88
|
+
),
|
|
89
|
+
headerColor: 'bg-sky-700',
|
|
90
|
+
titleColor: 'text-white',
|
|
91
|
+
lang: 'en',
|
|
92
|
+
})
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
{getString('password')}
|
|
96
|
+
</Button>
|
|
97
|
+
<Button
|
|
98
|
+
size='sm'
|
|
99
|
+
variant='destructive'
|
|
100
|
+
onClick={() => {
|
|
101
|
+
setModal({
|
|
102
|
+
title: getString('delete'),
|
|
103
|
+
body: (
|
|
104
|
+
<div className='p-4'>
|
|
105
|
+
<div className='flex flex-col gap-4'>
|
|
106
|
+
<div>{getString('deleteEmailText')}</div>
|
|
107
|
+
<div className='flex gap-2'>
|
|
108
|
+
<button
|
|
109
|
+
className='rounded bg-green-600 px-2 py-1 text-white'
|
|
110
|
+
onClick={deleteEmail}
|
|
111
|
+
>
|
|
112
|
+
Yes
|
|
113
|
+
</button>
|
|
114
|
+
<button
|
|
115
|
+
className='rounded bg-red-800 px-2 py-1 text-white'
|
|
116
|
+
onClick={() => {
|
|
117
|
+
setModal(null)
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
No
|
|
121
|
+
</button>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
),
|
|
126
|
+
headerColor: 'bg-red-700',
|
|
127
|
+
titleColor: 'text-white',
|
|
128
|
+
lang: 'en',
|
|
129
|
+
})
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
132
|
+
{getString('delete')}
|
|
133
|
+
</Button>
|
|
134
|
+
</CardFooter>
|
|
135
|
+
</Card>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import getString from 'nextjs-cms/translations'
|
|
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 { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
10
|
+
|
|
11
|
+
const { toast } = useToast()
|
|
12
|
+
const quotaMutation = trpc.cpanel.passwordChange.useMutation({
|
|
13
|
+
onError: (error) => {
|
|
14
|
+
setModal({
|
|
15
|
+
title: getString('error'),
|
|
16
|
+
body: (
|
|
17
|
+
<div className='p-4'>
|
|
18
|
+
<InfoCard result={{ key: 'danger', title: error.message, status: false }} />
|
|
19
|
+
</div>
|
|
20
|
+
),
|
|
21
|
+
headerColor: 'bg-red-700',
|
|
22
|
+
titleColor: 'text-white',
|
|
23
|
+
lang: 'en',
|
|
24
|
+
})
|
|
25
|
+
},
|
|
26
|
+
onSuccess: (data) => {
|
|
27
|
+
action()
|
|
28
|
+
setModal(null)
|
|
29
|
+
setModalResponse(null)
|
|
30
|
+
toast({
|
|
31
|
+
variant: 'success',
|
|
32
|
+
title: getString('success'),
|
|
33
|
+
})
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
37
|
+
e.preventDefault()
|
|
38
|
+
quotaMutation.mutate({
|
|
39
|
+
email,
|
|
40
|
+
password: e.currentTarget.password.value,
|
|
41
|
+
passwordConfirm: e.currentTarget.passwordConfirm.value,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<form onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
47
|
+
<div>
|
|
48
|
+
<label htmlFor='password' className='block text-sm font-medium leading-6 text-foreground'>
|
|
49
|
+
{getString('new_password')}
|
|
50
|
+
</label>
|
|
51
|
+
<div className=''>
|
|
52
|
+
<input
|
|
53
|
+
id='password'
|
|
54
|
+
name='password'
|
|
55
|
+
type='text'
|
|
56
|
+
autoComplete='password'
|
|
57
|
+
required
|
|
58
|
+
className='block w-full rounded-md border-0 bg-input p-2.5 text-foreground shadow-sm 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'
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div>
|
|
63
|
+
<label htmlFor='passwordConfirm' className='block text-sm font-medium leading-6 text-foreground'>
|
|
64
|
+
{getString('confirm_new_password')}
|
|
65
|
+
</label>
|
|
66
|
+
<div className=''>
|
|
67
|
+
<input
|
|
68
|
+
id='passwordConfirm'
|
|
69
|
+
name='passwordConfirm'
|
|
70
|
+
type='text'
|
|
71
|
+
autoComplete='passwordConfirm'
|
|
72
|
+
required
|
|
73
|
+
className='block w-full rounded-md border-0 bg-input p-2.5 text-foreground shadow-sm 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'
|
|
74
|
+
/>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
<div className='mt-4'>
|
|
78
|
+
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
79
|
+
{getString('change_password')}
|
|
80
|
+
</button>
|
|
81
|
+
</div>
|
|
82
|
+
</form>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import getString from 'nextjs-cms/translations'
|
|
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 { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
11
|
+
const { toast } = useToast()
|
|
12
|
+
|
|
13
|
+
const quotaMutation = trpc.cpanel.quotaChange.useMutation({
|
|
14
|
+
onError: (error) => {
|
|
15
|
+
setModal({
|
|
16
|
+
title: getString('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: getString('success'),
|
|
34
|
+
})
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
38
|
+
e.preventDefault()
|
|
39
|
+
quotaMutation.mutate({
|
|
40
|
+
email,
|
|
41
|
+
quota: e.currentTarget.quota.value,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<form onSubmit={handleSubmit} className='flex flex-col gap-2'>
|
|
47
|
+
<div>
|
|
48
|
+
<label htmlFor='quota' className='block text-sm font-medium leading-6 text-foreground'>
|
|
49
|
+
{getString('emailQuota')}
|
|
50
|
+
</label>
|
|
51
|
+
<div className=''>
|
|
52
|
+
<input
|
|
53
|
+
id='quota'
|
|
54
|
+
name='quota'
|
|
55
|
+
type='number'
|
|
56
|
+
autoComplete='quota'
|
|
57
|
+
required
|
|
58
|
+
className='block rounded-md border-0 bg-input p-2.5 text-foreground shadow-sm 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'
|
|
59
|
+
/>
|
|
60
|
+
<Badge className='rounded-sm border-muted-foreground text-muted-foreground' variant='secondary'>
|
|
61
|
+
0 = {getString('unlimited')}
|
|
62
|
+
</Badge>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<div className='mt-4'>
|
|
66
|
+
<button className='rounded bg-blue-700 px-2 py-1 font-bold text-white'>
|
|
67
|
+
{getString('update_quota')}
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
</form>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useEffect } from 'react'
|
|
4
|
+
import { EmailItem } from 'nextjs-cms/core/types'
|
|
5
|
+
import getString from 'nextjs-cms/translations'
|
|
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 controller = new AbortController()
|
|
13
|
+
|
|
14
|
+
const { isLoading, isError, data, error, refetch } = trpc.cpanel.getEmails.useQuery()
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
return () => {
|
|
18
|
+
controller.abort()
|
|
19
|
+
}
|
|
20
|
+
}, [])
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className='bg-white dark:bg-slate-900'>
|
|
24
|
+
<div className='bg-gradient-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'>
|
|
25
|
+
<h1 className='text-3xl'>{getString('email_accounts')}</h1>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div className='flex flex-col gap-2 p-4'>
|
|
29
|
+
<ContainerBox title={getString('create_new_email_account')}>
|
|
30
|
+
<NewEmailForm action={() => refetch()} />
|
|
31
|
+
</ContainerBox>
|
|
32
|
+
|
|
33
|
+
{isLoading && <div>Loading...</div>}
|
|
34
|
+
{data && data.emails && data.emails.length > 0 && (
|
|
35
|
+
<ContainerBox title={getString('admins_list')}>
|
|
36
|
+
<div className='mt-2 grid w-full grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3'>
|
|
37
|
+
{data.emails.map((email: EmailItem) => (
|
|
38
|
+
<EmailCard key={email.user} action={() => refetch()} email={email} />
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
</ContainerBox>
|
|
42
|
+
)}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default EmailsPage
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { PhotoGalleryItem } from 'nextjs-cms/core/types'
|
|
2
|
+
import getString from 'nextjs-cms/translations'
|
|
3
|
+
import { MinusIcon } from '@radix-ui/react-icons'
|
|
4
|
+
import ProtectedImage from '@/components/ProtectedImage'
|
|
5
|
+
import React from 'react'
|
|
6
|
+
import useModal from '@/hooks/useModal'
|
|
7
|
+
import { useToast } from '@/components/ui/use-toast'
|
|
8
|
+
import { trpc } from '@/app/_trpc/client'
|
|
9
|
+
|
|
10
|
+
const GalleryPhoto = ({ item, sectionName, action }: { item: PhotoGalleryItem; sectionName: string; action?: any }) => {
|
|
11
|
+
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
12
|
+
const deleteMutation = trpc.gallery.deletePhoto.useMutation({
|
|
13
|
+
onError: (error) => {
|
|
14
|
+
toast({
|
|
15
|
+
variant: 'destructive',
|
|
16
|
+
title: getString('delete_gallery_photo'),
|
|
17
|
+
description: error.message,
|
|
18
|
+
})
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
onSuccess: (data) => {
|
|
22
|
+
setModal(null)
|
|
23
|
+
setModalResponse(null)
|
|
24
|
+
toast({
|
|
25
|
+
variant: 'success',
|
|
26
|
+
title: getString('gallery_photo_deleted'),
|
|
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: getString('delete_gallery_photo'),
|
|
48
|
+
body: (
|
|
49
|
+
<div className='p-4'>
|
|
50
|
+
<div className='flex flex-col gap-4'>
|
|
51
|
+
<div>{getString('delete_gallery_photo_text')}</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 ring-gray-400'
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default GalleryPhoto
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import Link from 'next/link'
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import { CheckCircle, OctagonIcon, TriangleIcon } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
type result = {
|
|
8
|
+
key: string
|
|
9
|
+
title: string
|
|
10
|
+
status?: boolean
|
|
11
|
+
icon?: boolean
|
|
12
|
+
action?: {
|
|
13
|
+
text: string
|
|
14
|
+
link: string
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default function InfoCard({ result, className }: { result: result; className?: string }) {
|
|
19
|
+
let bgColor
|
|
20
|
+
let iconBgColor
|
|
21
|
+
let textColor
|
|
22
|
+
let buttonColor
|
|
23
|
+
switch (result.key) {
|
|
24
|
+
case 'success':
|
|
25
|
+
bgColor = 'bg-green-100'
|
|
26
|
+
iconBgColor = 'bg-green-200'
|
|
27
|
+
textColor = 'text-green-800'
|
|
28
|
+
buttonColor = 'bg-green-500 hover:bg-green-400'
|
|
29
|
+
|
|
30
|
+
break
|
|
31
|
+
case 'danger':
|
|
32
|
+
bgColor = 'bg-rose-100'
|
|
33
|
+
iconBgColor = 'bg-rose-200'
|
|
34
|
+
textColor = 'text-red-800'
|
|
35
|
+
buttonColor = 'bg-rose-600 hover:bg-red-500'
|
|
36
|
+
|
|
37
|
+
break
|
|
38
|
+
case 'warning':
|
|
39
|
+
bgColor = 'bg-orange-100'
|
|
40
|
+
iconBgColor = 'bg-orange-200'
|
|
41
|
+
textColor = 'text-orange-800'
|
|
42
|
+
buttonColor = 'bg-orange-500 hover:bg-orange-400'
|
|
43
|
+
break
|
|
44
|
+
case 'info':
|
|
45
|
+
bgColor = 'bg-sky-100'
|
|
46
|
+
iconBgColor = 'bg-sky-200'
|
|
47
|
+
textColor = 'text-blue-900'
|
|
48
|
+
buttonColor = 'bg-blue-500 hover:bg-blue-400'
|
|
49
|
+
break
|
|
50
|
+
default:
|
|
51
|
+
break
|
|
52
|
+
}
|
|
53
|
+
return (
|
|
54
|
+
<div className={className}>
|
|
55
|
+
<div className='col-span-full relative w-full overflow-hidden rounded-lg bg-white text-left border border-sky-700 transition-all'>
|
|
56
|
+
<div className=''>
|
|
57
|
+
<div className=''>
|
|
58
|
+
<div className={`w-full ${bgColor}`}>
|
|
59
|
+
<div className={`flex items-center text-md font-semibold ${textColor} py-1 px-2`}>
|
|
60
|
+
{result.icon && (
|
|
61
|
+
<div
|
|
62
|
+
className={` flex h-10 w-10 p-1 shrink-0 items-center justify-center rounded-full ${iconBgColor}`}
|
|
63
|
+
>
|
|
64
|
+
{result.key === 'success' ? (
|
|
65
|
+
<CheckCircle />
|
|
66
|
+
) : result.key === 'danger' ? (
|
|
67
|
+
<OctagonIcon />
|
|
68
|
+
) : result.key === 'warning' ? (
|
|
69
|
+
<TriangleIcon />
|
|
70
|
+
) : (
|
|
71
|
+
<OctagonIcon />
|
|
72
|
+
)}
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
<div className='ps-2 py-2'>
|
|
76
|
+
<div dangerouslySetInnerHTML={{ __html: result.title }}></div>
|
|
77
|
+
{result.action && (
|
|
78
|
+
<Link
|
|
79
|
+
href={result.action.link}
|
|
80
|
+
type='link'
|
|
81
|
+
className={`justify-center text-sm font-bold ms-2 text-blue-600`}
|
|
82
|
+
>
|
|
83
|
+
{result.action.text}
|
|
84
|
+
</Link>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
)
|
|
94
|
+
}
|