create-nextjs-cms 0.5.92 → 0.5.93
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/package.json +3 -3
- package/templates/default/app/(auth)/auth/login/LoginPage.tsx +13 -12
- package/templates/default/app/(auth)/layout.tsx +56 -0
- package/templates/default/app/(rootLayout)/layout.tsx +58 -8
- package/templates/default/app/globals.css +1 -1
- package/templates/default/components/AdminCard.tsx +16 -15
- package/templates/default/components/AdminEditPage.tsx +8 -7
- package/templates/default/components/AdminPrivilegeCard.tsx +12 -11
- package/templates/default/components/AdminsPage.tsx +5 -4
- package/templates/default/components/AnalyticsPage.tsx +8 -7
- package/templates/default/components/BrowsePage.tsx +7 -6
- package/templates/default/components/CategoryDeleteConfirmPage.tsx +12 -11
- package/templates/default/components/CategorySectionSelectInput.tsx +3 -2
- package/templates/default/components/DashboardNewPage.tsx +40 -39
- package/templates/default/components/DashboardPage.tsx +34 -33
- package/templates/default/components/DashboardPageAlt.tsx +3 -1
- package/templates/default/components/Dropzone.tsx +8 -7
- package/templates/default/components/EmailCard.tsx +12 -11
- package/templates/default/components/EmailPasswordForm.tsx +7 -6
- package/templates/default/components/EmailQuotaForm.tsx +7 -6
- package/templates/default/components/EmailsPage.tsx +6 -5
- package/templates/default/components/GalleryPhoto.tsx +6 -5
- package/templates/default/components/ItemEditPage.tsx +5 -4
- package/templates/default/components/Layout.tsx +1 -1
- package/templates/default/components/LoadingSpinners.tsx +1 -1
- package/templates/default/components/LogPage.tsx +24 -9
- package/templates/default/components/Navbar.tsx +13 -12
- package/templates/default/components/NewAdminForm.tsx +12 -11
- package/templates/default/components/NewEmailForm.tsx +11 -10
- package/templates/default/components/NewPage.tsx +6 -5
- package/templates/default/components/NewVariantComponent.tsx +6 -5
- package/templates/default/components/PhotoGallery.tsx +4 -3
- package/templates/default/components/SectionItemCard.tsx +8 -8
- package/templates/default/components/SectionItemStatusBadge.tsx +3 -2
- package/templates/default/components/SectionPage.tsx +6 -5
- package/templates/default/components/SelectInputButtons.tsx +8 -7
- package/templates/default/components/SettingsPage.tsx +18 -17
- package/templates/default/components/Sidebar.tsx +23 -15
- package/templates/default/components/SidebarDropdownItem.tsx +11 -5
- package/templates/default/components/SidebarItem.tsx +1 -0
- package/templates/default/components/VariantCard.tsx +8 -8
- package/templates/default/components/VariantEditPage.tsx +5 -4
- package/templates/default/components/analytics/BounceRate.tsx +6 -5
- package/templates/default/components/analytics/LivePageViews.tsx +8 -7
- package/templates/default/components/analytics/LiveUsersCount.tsx +3 -2
- package/templates/default/components/analytics/MonthlyPageViews.tsx +3 -2
- package/templates/default/components/analytics/TopCountries.tsx +4 -3
- package/templates/default/components/analytics/TopDevices.tsx +4 -3
- package/templates/default/components/analytics/TopMediums.tsx +4 -3
- package/templates/default/components/analytics/TopSources.tsx +4 -3
- package/templates/default/components/analytics/TotalPageViews.tsx +3 -2
- package/templates/default/components/analytics/TotalSessions.tsx +3 -2
- package/templates/default/components/analytics/TotalUniqueUsers.tsx +3 -2
- package/templates/default/components/custom/RightHomeRoomVariantCard.tsx +9 -8
- package/templates/default/components/form/Form.tsx +5 -4
- package/templates/default/components/form/FormInputElement.tsx +3 -1
- package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
- package/templates/default/components/form/inputs/DateFormInput.tsx +3 -2
- package/templates/default/components/form/inputs/DocumentFormInput.tsx +16 -15
- package/templates/default/components/form/inputs/MapFormInput.tsx +5 -4
- package/templates/default/components/form/inputs/PhotoFormInput.tsx +16 -15
- package/templates/default/components/form/inputs/SelectFormInput.tsx +3 -2
- package/templates/default/components/form/inputs/TagsFormInput.tsx +3 -2
- package/templates/default/components/form/inputs/VideoFormInput.tsx +7 -6
- package/templates/default/components/pagination/PaginationButtons.tsx +8 -6
- package/templates/default/package.json +2 -2
- package/templates/default/app/layout.tsx +0 -40
|
@@ -6,13 +6,14 @@ import { SidebarProps } from 'nextjs-cms/core/types'
|
|
|
6
6
|
import SidebarItem from '@/components/SidebarItem'
|
|
7
7
|
import SidebarDropdownItem from '@/components/SidebarDropdownItem'
|
|
8
8
|
import { ScrollArea } from '@/components/ui/scroll-area'
|
|
9
|
-
import
|
|
9
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
10
10
|
import ProtectedImage from '@/components/ProtectedImage'
|
|
11
11
|
import { trpc } from '@/app/_trpc/client'
|
|
12
12
|
import { useToast } from '@/components/ui/use-toast'
|
|
13
13
|
import { logout, useSession } from 'nextjs-cms/auth/react'
|
|
14
14
|
|
|
15
15
|
const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }) => {
|
|
16
|
+
const t = useI18n()
|
|
16
17
|
const session = useSession()
|
|
17
18
|
const [navItems] = trpc.navigation.getSidebar.useSuspenseQuery()
|
|
18
19
|
const { toast } = useToast()
|
|
@@ -24,19 +25,26 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
24
25
|
} catch (error: any) {
|
|
25
26
|
toast({
|
|
26
27
|
variant: 'destructive',
|
|
27
|
-
title:
|
|
28
|
+
title: t('logoutError'),
|
|
28
29
|
description: error.message,
|
|
29
30
|
})
|
|
30
31
|
}
|
|
31
32
|
}
|
|
33
|
+
const isRTL = session?.data?.user?.locale === 'ar'
|
|
32
34
|
return (
|
|
33
35
|
<div
|
|
34
36
|
className={classNames({
|
|
35
|
-
'fixed z-20 h-full bg-linear-to-br from-indigo-600 to-sky-500 text-zinc-50
|
|
37
|
+
'fixed z-20 h-full bg-linear-to-br from-indigo-600 to-sky-500 text-zinc-50 dark:from-slate-950 dark:to-pink-950':
|
|
36
38
|
true,
|
|
37
39
|
'transition-all duration-100 ease-in-out': true,
|
|
38
40
|
'w-[300px] md:w-[275px]': true,
|
|
41
|
+
// LTR: sidebar on left, slides in from left
|
|
42
|
+
'left-0 md:translate-x-0': true,
|
|
39
43
|
'-translate-x-full': !props.mobileSidebar,
|
|
44
|
+
// RTL: sidebar on right, slides in from right
|
|
45
|
+
'rtl:left-auto rtl:right-0': true,
|
|
46
|
+
'rtl:translate-x-full rtl:md:translate-x-0': !props.mobileSidebar,
|
|
47
|
+
'rtl:translate-x-0': props.mobileSidebar,
|
|
40
48
|
})}
|
|
41
49
|
>
|
|
42
50
|
<div
|
|
@@ -56,7 +64,7 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
56
64
|
{props.logoText}
|
|
57
65
|
</span>
|
|
58
66
|
</div>
|
|
59
|
-
<ScrollArea type='always' className='grow'>
|
|
67
|
+
<ScrollArea dir={isRTL ? 'rtl' : 'ltr'} type='always' className='grow'>
|
|
60
68
|
<ul
|
|
61
69
|
className={classNames({
|
|
62
70
|
'my-2 flex flex-col items-stretch gap-2': true,
|
|
@@ -66,7 +74,7 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
66
74
|
<>
|
|
67
75
|
{navItems.fixed_sections && navItems.fixed_sections.length > 0 && (
|
|
68
76
|
<div className='border-primary/40 mx-3 flex flex-col border-b py-2'>
|
|
69
|
-
<h2 className='my-2 text-xs text-gray-300'>
|
|
77
|
+
<h2 className='my-2 text-start text-xs text-gray-300'>{t('main')}</h2>
|
|
70
78
|
{navItems.fixed_sections.map((item, index) => {
|
|
71
79
|
return (
|
|
72
80
|
<SidebarItem
|
|
@@ -81,7 +89,7 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
81
89
|
|
|
82
90
|
{navItems.cat_sections && navItems.cat_sections.length > 0 && (
|
|
83
91
|
<div className='border-primary/40 mx-3 flex flex-col border-b py-2'>
|
|
84
|
-
<h2 className='my-2 text-xs text-gray-300'>
|
|
92
|
+
<h2 className='my-2 text-start text-xs text-gray-300'>{t('categorySections')}</h2>
|
|
85
93
|
{navItems.cat_sections.map((item, index) => {
|
|
86
94
|
return (
|
|
87
95
|
<SidebarItem
|
|
@@ -96,7 +104,7 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
96
104
|
|
|
97
105
|
{navItems.has_items_sections && navItems.has_items_sections.length > 0 && (
|
|
98
106
|
<div className='border-primary/40 mx-3 flex flex-col border-b py-2'>
|
|
99
|
-
<h2 className='my-2 text-xs text-gray-300'>
|
|
107
|
+
<h2 className='my-2 text-start text-xs text-gray-300'>{t('sectionsWithItems')}</h2>
|
|
100
108
|
<div className='flex flex-col gap-y-2'>
|
|
101
109
|
{navItems.has_items_sections.map((item, index) => {
|
|
102
110
|
return (
|
|
@@ -112,7 +120,7 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
112
120
|
)}
|
|
113
121
|
{navItems.simple_sections && navItems.simple_sections.length > 0 && (
|
|
114
122
|
<div className='mx-3 flex flex-col border-b border-blue-900 py-2'>
|
|
115
|
-
<h2 className='my-2 text-xs text-gray-300'>
|
|
123
|
+
<h2 className='my-2 text-start text-xs text-gray-300'>{t('simpleSections')}</h2>
|
|
116
124
|
{navItems.simple_sections.map((item, index) => {
|
|
117
125
|
return (
|
|
118
126
|
<SidebarItem
|
|
@@ -125,13 +133,13 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
125
133
|
</div>
|
|
126
134
|
)}
|
|
127
135
|
<div className='mx-3 flex flex-col py-2'>
|
|
128
|
-
<h2 className='my-2 text-xs text-gray-300'>
|
|
136
|
+
<h2 className='my-2 text-start text-xs text-gray-300'>{t('settings')}</h2>
|
|
129
137
|
<SidebarItem
|
|
130
138
|
closeSideBar={props.closeSideBar}
|
|
131
139
|
key={101}
|
|
132
140
|
item={{
|
|
133
141
|
path: '/settings',
|
|
134
|
-
title:
|
|
142
|
+
title: t('accountSettings'),
|
|
135
143
|
}}
|
|
136
144
|
/>
|
|
137
145
|
<Link
|
|
@@ -140,10 +148,10 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
140
148
|
className={classNames({
|
|
141
149
|
'rounded-lg text-white hover:bg-indigo-900 dark:hover:bg-emerald-600': true, //colors
|
|
142
150
|
'transition-colors duration-100': false, //animation
|
|
143
|
-
'gap-4 p-2': true,
|
|
151
|
+
'gap-4 p-2 text-start': true,
|
|
144
152
|
})}
|
|
145
153
|
>
|
|
146
|
-
<span>{
|
|
154
|
+
<span>{t('logout')}</span>
|
|
147
155
|
</Link>
|
|
148
156
|
</div>
|
|
149
157
|
</>
|
|
@@ -155,7 +163,7 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
155
163
|
'grid place-content-stretch bg-indigo-700 p-2 dark:bg-slate-800': true,
|
|
156
164
|
})}
|
|
157
165
|
>
|
|
158
|
-
|
|
166
|
+
<div className='flex h-12 items-center gap-4'>
|
|
159
167
|
{session?.data?.user.image ? (
|
|
160
168
|
<ProtectedImage
|
|
161
169
|
section={'admins'}
|
|
@@ -177,10 +185,10 @@ const Sidebar = (props: SidebarProps & { logoUrlPath: string; logoText: string }
|
|
|
177
185
|
/>
|
|
178
186
|
)}
|
|
179
187
|
|
|
180
|
-
<div className='flex flex-col'>
|
|
188
|
+
<div className='flex flex-col text-start'>
|
|
181
189
|
<span className='my-0 text-indigo-50'>{session?.data?.user.name}</span>
|
|
182
190
|
<Link href='/settings' className='text-sm text-indigo-200'>
|
|
183
|
-
{
|
|
191
|
+
{t('settings')}
|
|
184
192
|
</Link>
|
|
185
193
|
</div>
|
|
186
194
|
</div>
|
|
@@ -4,15 +4,17 @@ import { useState } from 'react'
|
|
|
4
4
|
import { SidebarItemProps } from 'nextjs-cms/core/types'
|
|
5
5
|
import { useAutoAnimate } from '@formkit/auto-animate/react'
|
|
6
6
|
import { ChevronDownIcon, ChevronUpIcon, FolderIcon, PlusCircleIcon, PlusIcon } from 'lucide-react'
|
|
7
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
7
8
|
|
|
8
9
|
export default function SidebarDropdownItem({ item, closeSideBar }: SidebarItemProps) {
|
|
10
|
+
const t = useI18n()
|
|
9
11
|
const [parent] = useAutoAnimate()
|
|
10
12
|
const [open, setOpen] = useState(false)
|
|
11
13
|
return (
|
|
12
14
|
<div ref={parent}>
|
|
13
15
|
<div
|
|
14
16
|
className={classNames({
|
|
15
|
-
'flex text-white hover:bg-indigo-900 dark:hover:bg-emerald-600': true, //colors
|
|
17
|
+
'flex cursor-pointer text-white hover:bg-indigo-900 dark:hover:bg-emerald-600': true, //colors
|
|
16
18
|
'transition-colors duration-100': false, //animation
|
|
17
19
|
'gap-4 rounded-md p-2': true,
|
|
18
20
|
'rounded-b-none bg-indigo-700 dark:bg-emerald-600': open,
|
|
@@ -21,9 +23,13 @@ export default function SidebarDropdownItem({ item, closeSideBar }: SidebarItemP
|
|
|
21
23
|
>
|
|
22
24
|
<li className='relative flex w-full items-center justify-between gap-2'>
|
|
23
25
|
{/*<span>{item.icon}</span>*/}
|
|
24
|
-
<span>{item.title}</span>
|
|
26
|
+
<span className='text-start'>{item.title}</span>
|
|
25
27
|
<span>
|
|
26
|
-
{open ?
|
|
28
|
+
{open ? (
|
|
29
|
+
<ChevronUpIcon className='h-5 w-5' />
|
|
30
|
+
) : (
|
|
31
|
+
<ChevronDownIcon className='h-5 w-5 rtl:rotate-0' />
|
|
32
|
+
)}
|
|
27
33
|
</span>
|
|
28
34
|
</li>
|
|
29
35
|
</div>
|
|
@@ -48,7 +54,7 @@ export default function SidebarDropdownItem({ item, closeSideBar }: SidebarItemP
|
|
|
48
54
|
<span>
|
|
49
55
|
<PlusIcon className='size-4' />
|
|
50
56
|
</span>
|
|
51
|
-
<span>
|
|
57
|
+
<span>{t('new')}</span>
|
|
52
58
|
</li>
|
|
53
59
|
</Link>
|
|
54
60
|
<Link
|
|
@@ -64,7 +70,7 @@ export default function SidebarDropdownItem({ item, closeSideBar }: SidebarItemP
|
|
|
64
70
|
<span>
|
|
65
71
|
<FolderIcon className='size-4' />
|
|
66
72
|
</span>
|
|
67
|
-
<span>
|
|
73
|
+
<span>{t('browse')}</span>
|
|
68
74
|
</li>
|
|
69
75
|
</Link>
|
|
70
76
|
</div>
|
|
@@ -11,6 +11,7 @@ export default function SidebarItem({ item, closeSideBar }: SidebarItemProps) {
|
|
|
11
11
|
'rounded-lg text-white hover:bg-indigo-900 dark:hover:bg-emerald-600': true, //colors
|
|
12
12
|
'transition-colors duration-100': false, //animation
|
|
13
13
|
'gap-4 p-2': true,
|
|
14
|
+
'text-start': true, // RTL support
|
|
14
15
|
})}
|
|
15
16
|
>
|
|
16
17
|
<span>{item.title}</span>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import ContainerBox from '@/components/ContainerBox'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { Variant } from 'nextjs-cms/core/types'
|
|
@@ -30,7 +30,7 @@ const VariantCard = ({
|
|
|
30
30
|
if (response.error) {
|
|
31
31
|
toast({
|
|
32
32
|
variant: 'destructive',
|
|
33
|
-
title:
|
|
33
|
+
title: t('deleteAdmin'),
|
|
34
34
|
description: response.error.message,
|
|
35
35
|
})
|
|
36
36
|
} else if (response.code === 200) {
|
|
@@ -39,7 +39,7 @@ const VariantCard = ({
|
|
|
39
39
|
setModalResponse(null)
|
|
40
40
|
toast({
|
|
41
41
|
variant: 'success',
|
|
42
|
-
title:
|
|
42
|
+
title: t('itemDeletedSuccessfully'),
|
|
43
43
|
description: response.message,
|
|
44
44
|
})
|
|
45
45
|
}
|
|
@@ -55,7 +55,7 @@ const VariantCard = ({
|
|
|
55
55
|
onClick={() => {
|
|
56
56
|
setModal({
|
|
57
57
|
size: 'lg',
|
|
58
|
-
title:
|
|
58
|
+
title: t('edit'),
|
|
59
59
|
body: (
|
|
60
60
|
<div className='p-4'>
|
|
61
61
|
<VariantEditPage
|
|
@@ -73,7 +73,7 @@ const VariantCard = ({
|
|
|
73
73
|
})
|
|
74
74
|
}}
|
|
75
75
|
>
|
|
76
|
-
{
|
|
76
|
+
{t('edit')}
|
|
77
77
|
</Button>
|
|
78
78
|
{/* Delete Button */}
|
|
79
79
|
<Button
|
|
@@ -82,11 +82,11 @@ const VariantCard = ({
|
|
|
82
82
|
variant='destructive'
|
|
83
83
|
onClick={() => {
|
|
84
84
|
setModal({
|
|
85
|
-
title:
|
|
85
|
+
title: t('delete'),
|
|
86
86
|
body: (
|
|
87
87
|
<div className='p-4'>
|
|
88
88
|
<div className='flex flex-col gap-4'>
|
|
89
|
-
<div>{
|
|
89
|
+
<div>{t('deleteItemText')}</div>
|
|
90
90
|
<div className='flex gap-2'>
|
|
91
91
|
<button
|
|
92
92
|
className='rounded bg-green-600 px-2 py-1 text-white'
|
|
@@ -112,7 +112,7 @@ const VariantCard = ({
|
|
|
112
112
|
})
|
|
113
113
|
}}
|
|
114
114
|
>
|
|
115
|
-
{
|
|
115
|
+
{t('delete')}
|
|
116
116
|
</Button>
|
|
117
117
|
</div>
|
|
118
118
|
</div>
|
|
@@ -5,7 +5,7 @@ import { getVariantPage } from '@/lib/apiHelpers'
|
|
|
5
5
|
import React, { RefObject, useEffect, useRef, useState } from 'react'
|
|
6
6
|
import { useQuery } from '@tanstack/react-query'
|
|
7
7
|
import { InputGroup } from 'nextjs-cms/core/types'
|
|
8
|
-
import
|
|
8
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
9
9
|
import useModal from '@/hooks/useModal'
|
|
10
10
|
import { AxiosError } from 'axios'
|
|
11
11
|
import InfoCard from '@/components/InfoCard'
|
|
@@ -37,6 +37,7 @@ export default function VariantEditPage({
|
|
|
37
37
|
}[]
|
|
38
38
|
action?: any
|
|
39
39
|
}) {
|
|
40
|
+
const t = useI18n()
|
|
40
41
|
const [response, setResponse] = useState<any>(null)
|
|
41
42
|
const [progress, setProgress] = useState(0)
|
|
42
43
|
const [progressVariant, setProgressVariant] = useState<'determinate' | 'query'>('determinate')
|
|
@@ -117,7 +118,7 @@ export default function VariantEditPage({
|
|
|
117
118
|
setResponse(null)
|
|
118
119
|
toast({
|
|
119
120
|
variant: 'success',
|
|
120
|
-
description:
|
|
121
|
+
description: t('itemUpdatedSuccessfully'),
|
|
121
122
|
})
|
|
122
123
|
|
|
123
124
|
// Redirect to the edit page
|
|
@@ -159,7 +160,7 @@ export default function VariantEditPage({
|
|
|
159
160
|
<>
|
|
160
161
|
<h1 className='pb-4 text-4xl'>{data?.variant?.variant_html_name_en}</h1>
|
|
161
162
|
<span>
|
|
162
|
-
/{
|
|
163
|
+
/{t('edit')} {data?.variant?.variant_single_item_name_en}
|
|
163
164
|
</span>
|
|
164
165
|
</>
|
|
165
166
|
)}
|
|
@@ -208,7 +209,7 @@ export default function VariantEditPage({
|
|
|
208
209
|
type='submit'
|
|
209
210
|
disabled={isSubmitting}
|
|
210
211
|
>
|
|
211
|
-
{isSubmitting ?
|
|
212
|
+
{isSubmitting ? t('loading') : t('save')}
|
|
212
213
|
</button>
|
|
213
214
|
{isSubmitting && (
|
|
214
215
|
<div className='mt-0.5'>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
3
3
|
import PieChartBox from '@/components/PieChartBox'
|
|
4
4
|
import React, { useEffect } from 'react'
|
|
@@ -9,6 +9,7 @@ import { useAxiosPrivate } from 'nextjs-cms/auth/hooks'
|
|
|
9
9
|
import { useTheme } from 'next-themes'
|
|
10
10
|
|
|
11
11
|
export const BounceRate = ({ fromDate, toDate }: { fromDate: Date | string | null; toDate: Date | string | null }) => {
|
|
12
|
+
const t = useI18n()
|
|
12
13
|
const axiosPrivate = useAxiosPrivate()
|
|
13
14
|
let controller = new AbortController()
|
|
14
15
|
const { theme } = useTheme()
|
|
@@ -34,12 +35,12 @@ export const BounceRate = ({ fromDate, toDate }: { fromDate: Date | string | nul
|
|
|
34
35
|
|
|
35
36
|
const bounceRateData: PieChartDataItem[] = [
|
|
36
37
|
{
|
|
37
|
-
name:
|
|
38
|
+
name: t('totalDiskSpace'),
|
|
38
39
|
value: 100 - parseInt(data?.bounceRate),
|
|
39
40
|
fill: 'transparent',
|
|
40
41
|
},
|
|
41
42
|
{
|
|
42
|
-
name:
|
|
43
|
+
name: t('usedDiskSpace'),
|
|
43
44
|
value: parseInt(data?.bounceRate),
|
|
44
45
|
fill: theme === 'dark' ? '#adfa1d' : '#E1315B',
|
|
45
46
|
},
|
|
@@ -58,9 +59,9 @@ export const BounceRate = ({ fromDate, toDate }: { fromDate: Date | string | nul
|
|
|
58
59
|
chartData={bounceRateData}
|
|
59
60
|
isLoading={isLoading}
|
|
60
61
|
chartBoxTitles={{
|
|
61
|
-
mainTitle:
|
|
62
|
+
mainTitle: t('bounceRate'),
|
|
62
63
|
totalUnitSubtitle: {
|
|
63
|
-
key:
|
|
64
|
+
key: t('sessionsPerUser'),
|
|
64
65
|
value: formatNumber(data?.sessionsPerUser),
|
|
65
66
|
},
|
|
66
67
|
}}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
|
3
3
|
import ContainerBox from '@/components/ContainerBox'
|
|
4
4
|
import React, { useEffect } from 'react'
|
|
@@ -7,6 +7,7 @@ import { useQuery } from '@tanstack/react-query'
|
|
|
7
7
|
import { getAnalytics } from '@/lib/apiHelpers'
|
|
8
8
|
|
|
9
9
|
export const LivePageViews = () => {
|
|
10
|
+
const t = useI18n()
|
|
10
11
|
const axiosPrivate = useAxiosPrivate()
|
|
11
12
|
const controller = new AbortController()
|
|
12
13
|
|
|
@@ -21,14 +22,14 @@ export const LivePageViews = () => {
|
|
|
21
22
|
})
|
|
22
23
|
|
|
23
24
|
return (
|
|
24
|
-
<ContainerBox title={
|
|
25
|
+
<ContainerBox title={t('liveUsersAreViewing')}>
|
|
25
26
|
<Table>
|
|
26
|
-
<TableCaption>{
|
|
27
|
+
<TableCaption>{t('liveUsersSubtitle')}</TableCaption>
|
|
27
28
|
<TableHeader>
|
|
28
29
|
<TableRow>
|
|
29
|
-
<TableHead>{
|
|
30
|
-
<TableHead>{
|
|
31
|
-
<TableHead>{
|
|
30
|
+
<TableHead>{t('country')}</TableHead>
|
|
31
|
+
<TableHead>{t('device')}</TableHead>
|
|
32
|
+
<TableHead>{t('page')}</TableHead>
|
|
32
33
|
</TableRow>
|
|
33
34
|
</TableHeader>
|
|
34
35
|
<TableBody>
|
|
@@ -43,7 +44,7 @@ export const LivePageViews = () => {
|
|
|
43
44
|
) : (
|
|
44
45
|
<TableRow>
|
|
45
46
|
<TableCell colSpan={3} className='text-center'>
|
|
46
|
-
{
|
|
47
|
+
{t('noLiveUsers')}
|
|
47
48
|
</TableCell>
|
|
48
49
|
</TableRow>
|
|
49
50
|
)}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
3
3
|
import ContainerBox from '@/components/ContainerBox'
|
|
4
4
|
import React from 'react'
|
|
@@ -8,6 +8,7 @@ import { getAnalytics } from '@/lib/apiHelpers'
|
|
|
8
8
|
import LoadingSpinners from '@/components/LoadingSpinners'
|
|
9
9
|
|
|
10
10
|
export const LiveUsersCount = () => {
|
|
11
|
+
const t = useI18n()
|
|
11
12
|
const axiosPrivate = useAxiosPrivate()
|
|
12
13
|
const controller = new AbortController()
|
|
13
14
|
|
|
@@ -21,7 +22,7 @@ export const LiveUsersCount = () => {
|
|
|
21
22
|
}),
|
|
22
23
|
})
|
|
23
24
|
return (
|
|
24
|
-
<ContainerBox title={
|
|
25
|
+
<ContainerBox title={t('liveUsers')}>
|
|
25
26
|
{isLoading ? (
|
|
26
27
|
<LoadingSpinners single={true} />
|
|
27
28
|
) : (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import BarChartBox from '@/components/BarChartBox'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { useTheme } from 'next-themes'
|
|
@@ -13,6 +13,7 @@ export const MonthlyPageViews = ({
|
|
|
13
13
|
fromDate: Date | string | null
|
|
14
14
|
toDate: Date | string | null
|
|
15
15
|
}) => {
|
|
16
|
+
const t = useI18n()
|
|
16
17
|
const axiosPrivate = useAxiosPrivate()
|
|
17
18
|
const controller = new AbortController()
|
|
18
19
|
const { theme } = useTheme()
|
|
@@ -33,7 +34,7 @@ export const MonthlyPageViews = ({
|
|
|
33
34
|
<BarChartBox
|
|
34
35
|
isLoading={isLoading}
|
|
35
36
|
chartData={data?.monthlyPageViews}
|
|
36
|
-
title={
|
|
37
|
+
title={t('monthlyPageViews')}
|
|
37
38
|
fill={theme === 'dark' ? '#adfa1d' : '#ff6688'}
|
|
38
39
|
/>
|
|
39
40
|
</>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { BarChartDataItem } from 'nextjs-cms/core/types'
|
|
3
3
|
import { Badge } from '@/components/ui/badge'
|
|
4
4
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
@@ -16,6 +16,7 @@ export const TopCountries = ({
|
|
|
16
16
|
fromDate: Date | string | null
|
|
17
17
|
toDate: Date | string | null
|
|
18
18
|
}) => {
|
|
19
|
+
const t = useI18n()
|
|
19
20
|
const axiosPrivate = useAxiosPrivate()
|
|
20
21
|
const controller = new AbortController()
|
|
21
22
|
|
|
@@ -32,9 +33,9 @@ export const TopCountries = ({
|
|
|
32
33
|
})
|
|
33
34
|
|
|
34
35
|
return (
|
|
35
|
-
<ContainerBox title={
|
|
36
|
+
<ContainerBox title={t('countries')}>
|
|
36
37
|
<div className='w-full mb-6'>
|
|
37
|
-
<h1 className='font-bold border-b pb-1 my-1'>{
|
|
38
|
+
<h1 className='font-bold border-b pb-1 my-1'>{t('topCountries')}</h1>
|
|
38
39
|
{isLoading && <LoadingSpinners single={true} />}
|
|
39
40
|
{data?.topCountries?.length > 0 &&
|
|
40
41
|
data.topCountries.map((country: BarChartDataItem, index: number) => (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { BarChartDataItem } from 'nextjs-cms/core/types'
|
|
3
3
|
import { Badge } from '@/components/ui/badge'
|
|
4
4
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
@@ -10,6 +10,7 @@ import { getAnalytics } from '@/lib/apiHelpers'
|
|
|
10
10
|
import LoadingSpinners from '@/components/LoadingSpinners'
|
|
11
11
|
|
|
12
12
|
export const TopDevices = ({ fromDate, toDate }: { fromDate: Date | string | null; toDate: Date | string | null }) => {
|
|
13
|
+
const t = useI18n()
|
|
13
14
|
const axiosPrivate = useAxiosPrivate()
|
|
14
15
|
const controller = new AbortController()
|
|
15
16
|
|
|
@@ -26,9 +27,9 @@ export const TopDevices = ({ fromDate, toDate }: { fromDate: Date | string | nul
|
|
|
26
27
|
})
|
|
27
28
|
|
|
28
29
|
return (
|
|
29
|
-
<ContainerBox title={
|
|
30
|
+
<ContainerBox title={t('devices')}>
|
|
30
31
|
<div className='w-full'>
|
|
31
|
-
<h1 className='font-bold border-b pb-1 my-1'>{
|
|
32
|
+
<h1 className='font-bold border-b pb-1 my-1'>{t('topDevices')}</h1>
|
|
32
33
|
{isLoading && <LoadingSpinners single={true} />}
|
|
33
34
|
{data?.topDevices?.length > 0 &&
|
|
34
35
|
data.topDevices.map((device: BarChartDataItem, index: number) => (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { BarChartDataItem } from 'nextjs-cms/core/types'
|
|
3
3
|
import { Badge } from '@/components/ui/badge'
|
|
4
4
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
@@ -10,6 +10,7 @@ import { getAnalytics } from '@/lib/apiHelpers'
|
|
|
10
10
|
import LoadingSpinners from '@/components/LoadingSpinners'
|
|
11
11
|
|
|
12
12
|
export const TopMediums = ({ fromDate, toDate }: { fromDate: Date | string | null; toDate: Date | string | null }) => {
|
|
13
|
+
const t = useI18n()
|
|
13
14
|
const axiosPrivate = useAxiosPrivate()
|
|
14
15
|
let controller = new AbortController()
|
|
15
16
|
|
|
@@ -38,9 +39,9 @@ export const TopMediums = ({ fromDate, toDate }: { fromDate: Date | string | nul
|
|
|
38
39
|
}, [])
|
|
39
40
|
|
|
40
41
|
return (
|
|
41
|
-
<ContainerBox title={
|
|
42
|
+
<ContainerBox title={t('mediums')}>
|
|
42
43
|
<div className='w-full mb-6'>
|
|
43
|
-
<h1 className='font-bold border-b pb-1 my-1'>{
|
|
44
|
+
<h1 className='font-bold border-b pb-1 my-1'>{t('topMediums')}</h1>
|
|
44
45
|
{isLoading && <LoadingSpinners single={true} />}
|
|
45
46
|
{data?.topMediums?.length > 0 &&
|
|
46
47
|
data.topMediums.map((medium: BarChartDataItem, index: number) => (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { BarChartDataItem } from 'nextjs-cms/core/types'
|
|
3
3
|
import { Badge } from '@/components/ui/badge'
|
|
4
4
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
@@ -10,6 +10,7 @@ import { getAnalytics } from '@/lib/apiHelpers'
|
|
|
10
10
|
import LoadingSpinners from '@/components/LoadingSpinners'
|
|
11
11
|
|
|
12
12
|
export const TopSources = ({ fromDate, toDate }: { fromDate: Date | string | null; toDate: Date | string | null }) => {
|
|
13
|
+
const t = useI18n()
|
|
13
14
|
const axiosPrivate = useAxiosPrivate()
|
|
14
15
|
const controller = new AbortController()
|
|
15
16
|
|
|
@@ -25,9 +26,9 @@ export const TopSources = ({ fromDate, toDate }: { fromDate: Date | string | nul
|
|
|
25
26
|
}),
|
|
26
27
|
})
|
|
27
28
|
return (
|
|
28
|
-
<ContainerBox title={
|
|
29
|
+
<ContainerBox title={t('sources')}>
|
|
29
30
|
<div className='w-full mb-6'>
|
|
30
|
-
<h1 className='font-bold border-b pb-1 my-1'>{
|
|
31
|
+
<h1 className='font-bold border-b pb-1 my-1'>{t('topSources')}</h1>
|
|
31
32
|
{isLoading && <LoadingSpinners single={true} />}
|
|
32
33
|
{data?.topSources?.length > 0 &&
|
|
33
34
|
data.topSources.map((source: BarChartDataItem, index: number) => (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
3
3
|
import ContainerBox from '@/components/ContainerBox'
|
|
4
4
|
import React from 'react'
|
|
@@ -14,6 +14,7 @@ export const TotalPageViews = ({
|
|
|
14
14
|
fromDate: Date | string | null
|
|
15
15
|
toDate: Date | string | null
|
|
16
16
|
}) => {
|
|
17
|
+
const t = useI18n()
|
|
17
18
|
const axiosPrivate = useAxiosPrivate()
|
|
18
19
|
const controller = new AbortController()
|
|
19
20
|
|
|
@@ -29,7 +30,7 @@ export const TotalPageViews = ({
|
|
|
29
30
|
}),
|
|
30
31
|
})
|
|
31
32
|
return (
|
|
32
|
-
<ContainerBox title={
|
|
33
|
+
<ContainerBox title={t('totalPageViews')}>
|
|
33
34
|
{isLoading ? (
|
|
34
35
|
<LoadingSpinners single={true} />
|
|
35
36
|
) : (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
3
3
|
import ContainerBox from '@/components/ContainerBox'
|
|
4
4
|
import React from 'react'
|
|
@@ -14,6 +14,7 @@ export const TotalSessions = ({
|
|
|
14
14
|
fromDate: Date | string | null
|
|
15
15
|
toDate: Date | string | null
|
|
16
16
|
}) => {
|
|
17
|
+
const t = useI18n()
|
|
17
18
|
const axiosPrivate = useAxiosPrivate()
|
|
18
19
|
const controller = new AbortController()
|
|
19
20
|
|
|
@@ -29,7 +30,7 @@ export const TotalSessions = ({
|
|
|
29
30
|
}),
|
|
30
31
|
})
|
|
31
32
|
return (
|
|
32
|
-
<ContainerBox title={
|
|
33
|
+
<ContainerBox title={t('totalSessions')}>
|
|
33
34
|
{isLoading ? (
|
|
34
35
|
<LoadingSpinners single={true} />
|
|
35
36
|
) : (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
2
2
|
import { formatNumber } from 'nextjs-cms/utils'
|
|
3
3
|
import ContainerBox from '@/components/ContainerBox'
|
|
4
4
|
import React from 'react'
|
|
@@ -14,6 +14,7 @@ export const TotalUniqueUsers = ({
|
|
|
14
14
|
fromDate: Date | string | null
|
|
15
15
|
toDate: Date | string | null
|
|
16
16
|
}) => {
|
|
17
|
+
const t = useI18n()
|
|
17
18
|
const axiosPrivate = useAxiosPrivate()
|
|
18
19
|
const controller = new AbortController()
|
|
19
20
|
|
|
@@ -29,7 +30,7 @@ export const TotalUniqueUsers = ({
|
|
|
29
30
|
}),
|
|
30
31
|
})
|
|
31
32
|
return (
|
|
32
|
-
<ContainerBox title={
|
|
33
|
+
<ContainerBox title={t('totalUniqueUsers')}>
|
|
33
34
|
{isLoading ? (
|
|
34
35
|
<LoadingSpinners single={true} />
|
|
35
36
|
) : (
|