create-nextjs-cms 0.9.6 → 0.9.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.
Files changed (184) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +71 -71
  3. package/dist/helpers/check-directory.d.ts +1 -0
  4. package/dist/helpers/check-directory.d.ts.map +1 -1
  5. package/dist/helpers/check-directory.js +98 -23
  6. package/dist/helpers/utils.js +16 -16
  7. package/dist/index.js +13 -8
  8. package/dist/lib/create-project.js +1 -1
  9. package/dist/lib/section-creators.js +166 -166
  10. package/package.json +1 -1
  11. package/templates/default/.eslintrc.json +5 -5
  12. package/templates/default/.prettierignore +7 -7
  13. package/templates/default/.prettierrc.json +27 -27
  14. package/templates/default/CHANGELOG.md +140 -140
  15. package/templates/default/_gitignore +57 -57
  16. package/templates/default/app/(auth)/auth/login/LoginPage.tsx +192 -192
  17. package/templates/default/app/(auth)/auth/login/page.tsx +11 -11
  18. package/templates/default/app/(auth)/auth-language-provider.tsx +34 -34
  19. package/templates/default/app/(auth)/layout.tsx +81 -81
  20. package/templates/default/app/(rootLayout)/(plugins)/[...slug]/page.tsx +40 -40
  21. package/templates/default/app/(rootLayout)/(plugins)/[...slug]/plugin-server-registry.ts +16 -16
  22. package/templates/default/app/(rootLayout)/admins/page.tsx +10 -10
  23. package/templates/default/app/(rootLayout)/browse/[section]/[page]/page.tsx +22 -22
  24. package/templates/default/app/(rootLayout)/categorized/[section]/page.tsx +15 -15
  25. package/templates/default/app/(rootLayout)/dashboard/page.tsx +63 -63
  26. package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +20 -20
  27. package/templates/default/app/(rootLayout)/layout.tsx +81 -81
  28. package/templates/default/app/(rootLayout)/loading.tsx +10 -10
  29. package/templates/default/app/(rootLayout)/log/page.tsx +7 -7
  30. package/templates/default/app/(rootLayout)/new/[section]/page.tsx +15 -15
  31. package/templates/default/app/(rootLayout)/section/[section]/page.tsx +19 -19
  32. package/templates/default/app/(rootLayout)/settings/page.tsx +13 -13
  33. package/templates/default/app/_trpc/client.ts +3 -3
  34. package/templates/default/app/api/auth/csrf/route.ts +25 -25
  35. package/templates/default/app/api/auth/refresh/route.ts +10 -10
  36. package/templates/default/app/api/auth/route.ts +49 -49
  37. package/templates/default/app/api/auth/session/route.ts +20 -20
  38. package/templates/default/app/api/document/route.ts +165 -165
  39. package/templates/default/app/api/editor/photo/route.ts +49 -49
  40. package/templates/default/app/api/photo/route.ts +27 -27
  41. package/templates/default/app/api/submit/section/item/[slug]/route.ts +95 -95
  42. package/templates/default/app/api/submit/section/item/route.ts +56 -56
  43. package/templates/default/app/api/submit/section/simple/route.ts +86 -86
  44. package/templates/default/app/api/trpc/[trpc]/route.ts +33 -33
  45. package/templates/default/app/api/video/route.ts +174 -174
  46. package/templates/default/app/globals.css +228 -228
  47. package/templates/default/app/providers.tsx +152 -152
  48. package/templates/default/cms.config.ts +57 -58
  49. package/templates/default/components/AdminCard.tsx +166 -166
  50. package/templates/default/components/AdminEditPage.tsx +124 -124
  51. package/templates/default/components/AdminPrivilegeCard.tsx +185 -185
  52. package/templates/default/components/AdminsPage.tsx +43 -43
  53. package/templates/default/components/AnalyticsPage.tsx +144 -144
  54. package/templates/default/components/BarChartBox.tsx +42 -42
  55. package/templates/default/components/BrowsePage.tsx +106 -106
  56. package/templates/default/components/CategorizedSectionPage.tsx +31 -31
  57. package/templates/default/components/CategoryDeleteConfirmPage.tsx +130 -130
  58. package/templates/default/components/CategorySectionSelectInput.tsx +140 -140
  59. package/templates/default/components/ConditionalFields.tsx +49 -49
  60. package/templates/default/components/ContainerBox.tsx +24 -24
  61. package/templates/default/components/DashboardPageAlt.tsx +45 -45
  62. package/templates/default/components/DefaultNavItems.tsx +3 -3
  63. package/templates/default/components/Dropzone.tsx +154 -154
  64. package/templates/default/components/ErrorComponent.tsx +16 -16
  65. package/templates/default/components/GalleryPhoto.tsx +93 -93
  66. package/templates/default/components/InfoCard.tsx +93 -93
  67. package/templates/default/components/ItemEditPage.tsx +294 -294
  68. package/templates/default/components/Layout.tsx +84 -84
  69. package/templates/default/components/LoadingSpinners.tsx +67 -67
  70. package/templates/default/components/LocaleSwitcher.tsx +89 -89
  71. package/templates/default/components/LogPage.tsx +107 -107
  72. package/templates/default/components/Modal.tsx +166 -166
  73. package/templates/default/components/Navbar.tsx +258 -258
  74. package/templates/default/components/NewAdminForm.tsx +173 -173
  75. package/templates/default/components/NewPage.tsx +206 -206
  76. package/templates/default/components/NewVariantComponent.tsx +229 -229
  77. package/templates/default/components/PhotoGallery.tsx +35 -35
  78. package/templates/default/components/PieChartBox.tsx +101 -101
  79. package/templates/default/components/ProgressBar.tsx +48 -48
  80. package/templates/default/components/ProtectedDocument.tsx +44 -44
  81. package/templates/default/components/ProtectedImage.tsx +143 -143
  82. package/templates/default/components/ProtectedVideo.tsx +76 -76
  83. package/templates/default/components/SectionIcon.tsx +8 -8
  84. package/templates/default/components/SectionItemCard.tsx +144 -144
  85. package/templates/default/components/SectionItemStatusBadge.tsx +17 -17
  86. package/templates/default/components/SectionPage.tsx +205 -205
  87. package/templates/default/components/SelectBox.tsx +98 -98
  88. package/templates/default/components/SelectInputButtons.tsx +125 -125
  89. package/templates/default/components/SettingsPage.tsx +232 -232
  90. package/templates/default/components/Sidebar.tsx +204 -204
  91. package/templates/default/components/SidebarDropdownItem.tsx +83 -83
  92. package/templates/default/components/SidebarItem.tsx +24 -24
  93. package/templates/default/components/ThemeProvider.tsx +8 -8
  94. package/templates/default/components/TooltipComponent.tsx +27 -27
  95. package/templates/default/components/VariantCard.tsx +124 -124
  96. package/templates/default/components/VariantEditPage.tsx +230 -230
  97. package/templates/default/components/analytics/BounceRate.tsx +70 -70
  98. package/templates/default/components/analytics/LivePageViews.tsx +55 -55
  99. package/templates/default/components/analytics/LiveUsersCount.tsx +33 -33
  100. package/templates/default/components/analytics/MonthlyPageViews.tsx +42 -42
  101. package/templates/default/components/analytics/TopCountries.tsx +52 -52
  102. package/templates/default/components/analytics/TopDevices.tsx +46 -46
  103. package/templates/default/components/analytics/TopMediums.tsx +58 -58
  104. package/templates/default/components/analytics/TopSources.tsx +45 -45
  105. package/templates/default/components/analytics/TotalPageViews.tsx +41 -41
  106. package/templates/default/components/analytics/TotalSessions.tsx +41 -41
  107. package/templates/default/components/analytics/TotalUniqueUsers.tsx +41 -41
  108. package/templates/default/components/custom/RightHomeRoomVariantCard.tsx +138 -138
  109. package/templates/default/components/dndKit/Draggable.tsx +21 -21
  110. package/templates/default/components/dndKit/Droppable.tsx +20 -20
  111. package/templates/default/components/dndKit/SortableItem.tsx +18 -18
  112. package/templates/default/components/form/Form.tsx +370 -370
  113. package/templates/default/components/form/FormInputElement.tsx +70 -70
  114. package/templates/default/components/form/FormInputs.tsx +136 -136
  115. package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
  116. package/templates/default/components/form/helpers/util.ts +17 -17
  117. package/templates/default/components/form/inputs/CheckboxFormInput.tsx +46 -46
  118. package/templates/default/components/form/inputs/ColorFormInput.tsx +44 -44
  119. package/templates/default/components/form/inputs/DateFormInput.tsx +167 -110
  120. package/templates/default/components/form/inputs/DateRangeFormInput.tsx +46 -6
  121. package/templates/default/components/form/inputs/DocumentFormInput.tsx +222 -222
  122. package/templates/default/components/form/inputs/MapFormInput.tsx +140 -140
  123. package/templates/default/components/form/inputs/MultipleSelectFormInput.tsx +85 -85
  124. package/templates/default/components/form/inputs/NumberFormInput.tsx +43 -43
  125. package/templates/default/components/form/inputs/PasswordFormInput.tsx +47 -47
  126. package/templates/default/components/form/inputs/PhotoFormInput.tsx +275 -275
  127. package/templates/default/components/form/inputs/RichTextFormInput.tsx +138 -138
  128. package/templates/default/components/form/inputs/SelectFormInput.tsx +175 -175
  129. package/templates/default/components/form/inputs/SlugFormInput.tsx +131 -131
  130. package/templates/default/components/form/inputs/TagsFormInput.tsx +265 -265
  131. package/templates/default/components/form/inputs/TextFormInput.tsx +51 -51
  132. package/templates/default/components/form/inputs/TextareaFormInput.tsx +50 -50
  133. package/templates/default/components/form/inputs/VideoFormInput.tsx +118 -118
  134. package/templates/default/components/multi-select.tsx +1146 -1146
  135. package/templates/default/components/pagination/Pagination.tsx +36 -36
  136. package/templates/default/components/pagination/PaginationButtons.tsx +147 -147
  137. package/templates/default/components/theme-toggle.tsx +39 -39
  138. package/templates/default/components/ui/accordion.tsx +53 -53
  139. package/templates/default/components/ui/alert-dialog.tsx +157 -157
  140. package/templates/default/components/ui/alert.tsx +47 -47
  141. package/templates/default/components/ui/badge.tsx +38 -38
  142. package/templates/default/components/ui/button.tsx +62 -62
  143. package/templates/default/components/ui/calendar.tsx +166 -166
  144. package/templates/default/components/ui/card.tsx +43 -43
  145. package/templates/default/components/ui/checkbox.tsx +29 -29
  146. package/templates/default/components/ui/command.tsx +137 -137
  147. package/templates/default/components/ui/custom-alert-dialog.tsx +113 -113
  148. package/templates/default/components/ui/custom-dialog.tsx +123 -123
  149. package/templates/default/components/ui/dialog.tsx +123 -123
  150. package/templates/default/components/ui/direction.tsx +22 -22
  151. package/templates/default/components/ui/dropdown-menu.tsx +182 -182
  152. package/templates/default/components/ui/input-group.tsx +54 -54
  153. package/templates/default/components/ui/input.tsx +22 -22
  154. package/templates/default/components/ui/label.tsx +19 -19
  155. package/templates/default/components/ui/popover.tsx +42 -42
  156. package/templates/default/components/ui/progress.tsx +31 -31
  157. package/templates/default/components/ui/scroll-area.tsx +42 -42
  158. package/templates/default/components/ui/select.tsx +165 -165
  159. package/templates/default/components/ui/separator.tsx +28 -28
  160. package/templates/default/components/ui/sheet.tsx +103 -103
  161. package/templates/default/components/ui/spinner.tsx +16 -16
  162. package/templates/default/components/ui/switch.tsx +29 -29
  163. package/templates/default/components/ui/table.tsx +83 -83
  164. package/templates/default/components/ui/tabs.tsx +55 -55
  165. package/templates/default/components/ui/toast.tsx +113 -113
  166. package/templates/default/components/ui/toaster.tsx +35 -35
  167. package/templates/default/components/ui/tooltip.tsx +30 -30
  168. package/templates/default/components/ui/use-toast.ts +188 -188
  169. package/templates/default/components.json +21 -21
  170. package/templates/default/context/ModalProvider.tsx +53 -53
  171. package/templates/default/drizzle.config.ts +4 -4
  172. package/templates/default/dynamic-schemas/schema.ts +475 -0
  173. package/templates/default/env/env.js +130 -130
  174. package/templates/default/envConfig.ts +4 -4
  175. package/templates/default/hooks/useModal.ts +8 -8
  176. package/templates/default/lib/apiHelpers.ts +92 -92
  177. package/templates/default/lib/postinstall.js +14 -14
  178. package/templates/default/lib/utils.ts +6 -6
  179. package/templates/default/next-env.d.ts +6 -6
  180. package/templates/default/next.config.ts +23 -23
  181. package/templates/default/package.json +1 -1
  182. package/templates/default/postcss.config.mjs +6 -6
  183. package/templates/default/proxy.ts +32 -32
  184. package/templates/default/tsconfig.json +48 -48
@@ -1,144 +1,144 @@
1
- 'use client'
2
- import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'
3
- import React, { useEffect, useRef } from 'react'
4
- import { useI18n } from 'nextjs-cms/translations/client'
5
- import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'
6
- import DateRangeFormInput from '@/components/form/inputs/DateRangeFormInput'
7
- import { MonthlyPageViews } from '@/components/analytics/MonthlyPageViews'
8
- import { TopSources } from '@/components/analytics/TopSources'
9
- import { TopMediums } from '@/components/analytics/TopMediums'
10
- import { LiveUsersCount } from '@/components/analytics/LiveUsersCount'
11
- import { TotalPageViews } from '@/components/analytics/TotalPageViews'
12
- import { TotalSessions } from '@/components/analytics/TotalSessions'
13
- import { TotalUniqueUsers } from '@/components/analytics/TotalUniqueUsers'
14
- import { BounceRate } from '@/components/analytics/BounceRate'
15
- import { LivePageViews } from '@/components/analytics/LivePageViews'
16
- import { TopCountries } from '@/components/analytics/TopCountries'
17
- import { TopDevices } from '@/components/analytics/TopDevices'
18
- // import { trpc } from '@/app/_trpc/client'
19
- ChartJS.register(ArcElement, Tooltip, Legend)
20
-
21
- // TODO: MOVE THIS TO THE PLUGIN
22
-
23
- const AnalyticsPage = () => {
24
- const t = useI18n()
25
- const controller = new AbortController()
26
- const datePickerRangeRef = useRef<HTMLDivElement>(null)
27
- const [fromDate, setFromDate] = React.useState<Date | string>('30daysAgo')
28
- const [toDate, setToDate] = React.useState<Date | string>('today')
29
-
30
- // const { data, isError } = trpc.googleAnalytics.test.useQuery()
31
-
32
- useEffect(() => {
33
- return () => {
34
- controller.abort()
35
- }
36
- }, [])
37
-
38
- return (
39
- <div className='w-full'>
40
- <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'>
41
- <h1 className='text-3xl'>{t('analytics')}</h1>
42
- </div>
43
- <div className='p-4'>
44
- <div className='flex gap-2'>
45
- <Tabs
46
- defaultValue='account'
47
- onValueChange={(value) => {
48
- if (value === 'custom') {
49
- // Remove hidden class from date picker range
50
- datePickerRangeRef.current?.classList.remove('hidden')
51
- } else {
52
- // Add hidden class to date picker range
53
- datePickerRangeRef.current?.classList.add('hidden')
54
- }
55
- }}
56
- >
57
- <Tabs
58
- defaultValue='lastMonth'
59
- onValueChange={(value) => {
60
- if (value === 'custom') {
61
- // Remove hidden class from date picker range
62
- datePickerRangeRef.current?.classList.remove('hidden')
63
- } else {
64
- switch (value) {
65
- case 'today':
66
- setFromDate('yesterday')
67
- setToDate('today')
68
- break
69
- case 'lastWeek':
70
- setFromDate('10daysAgo')
71
- setToDate('today')
72
- break
73
- case 'lastMonth':
74
- setFromDate('30daysAgo')
75
- setToDate('today')
76
- break
77
- case 'lastYear':
78
- setFromDate('365daysAgo')
79
- setToDate('today')
80
- break
81
- }
82
- // Add hidden class to date picker range
83
- datePickerRangeRef.current?.classList.add('hidden')
84
- }
85
- }}
86
- >
87
- <TabsList>
88
- <TabsTrigger value='today'>{t('today')}</TabsTrigger>
89
- <TabsTrigger value='lastWeek'>{t('last7Days')}</TabsTrigger>
90
- <TabsTrigger value='lastMonth'>{t('last30Days')}</TabsTrigger>
91
- <TabsTrigger value='lastYear'>{t('last365Days')}</TabsTrigger>
92
- <TabsTrigger value='custom'>{t('custom')}</TabsTrigger>
93
- </TabsList>
94
- </Tabs>
95
- </Tabs>
96
- <div ref={datePickerRangeRef} className='hidden'>
97
- <DateRangeFormInput input={{
98
- name: 'dateRange',
99
- label: 'Date Range',
100
- required: true,
101
- conditionalFields: [],
102
- readonly: false,
103
- defaultValue: undefined,
104
- value: undefined,
105
- startName: 'fromDate',
106
- endName: 'toDate',
107
- format: 'date',
108
- startValue: fromDate,
109
- endValue: toDate,
110
- type: 'date_range',
111
- }} />
112
- </div>
113
- </div>
114
- <div className='my-2 grid grid-cols-2 gap-4 sm-sidebar:grid-cols-2 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-4'>
115
- <LiveUsersCount />
116
- <TotalPageViews fromDate={fromDate} toDate={toDate} />
117
- <TotalSessions fromDate={fromDate} toDate={toDate} />
118
- <TotalUniqueUsers fromDate={fromDate} toDate={toDate} />
119
- </div>
120
- <div className='my-4 grid grid-cols-1 gap-4 sm-sidebar:grid-cols-1 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-4'>
121
- <div className='col-span-2'>
122
- <MonthlyPageViews fromDate={fromDate} toDate={toDate} />
123
- </div>
124
- <div className='col-span-2 grid grid-cols-1 gap-4 sm-sidebar:grid-cols-1 md-sidebar:grid-cols-2'>
125
- <TopCountries fromDate={fromDate} toDate={toDate} />
126
- <BounceRate fromDate={fromDate} toDate={toDate} />
127
- </div>
128
- </div>
129
- <div className='my-4 grid grid-cols-1 gap-4 sm-sidebar:grid-cols-1 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-4'>
130
- <div className='col-span-2'>
131
- <TopSources fromDate={fromDate} toDate={toDate} />
132
- </div>
133
- <TopMediums fromDate={fromDate} toDate={toDate} />
134
- <TopDevices fromDate={fromDate} toDate={toDate} />
135
- </div>
136
- <div className='my-2'>
137
- <LivePageViews />
138
- </div>
139
- </div>
140
- </div>
141
- )
142
- }
143
-
144
- export default AnalyticsPage
1
+ 'use client'
2
+ import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'
3
+ import React, { useEffect, useRef } from 'react'
4
+ import { useI18n } from 'nextjs-cms/translations/client'
5
+ import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'
6
+ import DateRangeFormInput from '@/components/form/inputs/DateRangeFormInput'
7
+ import { MonthlyPageViews } from '@/components/analytics/MonthlyPageViews'
8
+ import { TopSources } from '@/components/analytics/TopSources'
9
+ import { TopMediums } from '@/components/analytics/TopMediums'
10
+ import { LiveUsersCount } from '@/components/analytics/LiveUsersCount'
11
+ import { TotalPageViews } from '@/components/analytics/TotalPageViews'
12
+ import { TotalSessions } from '@/components/analytics/TotalSessions'
13
+ import { TotalUniqueUsers } from '@/components/analytics/TotalUniqueUsers'
14
+ import { BounceRate } from '@/components/analytics/BounceRate'
15
+ import { LivePageViews } from '@/components/analytics/LivePageViews'
16
+ import { TopCountries } from '@/components/analytics/TopCountries'
17
+ import { TopDevices } from '@/components/analytics/TopDevices'
18
+ // import { trpc } from '@/app/_trpc/client'
19
+ ChartJS.register(ArcElement, Tooltip, Legend)
20
+
21
+ // TODO: MOVE THIS TO THE PLUGIN
22
+
23
+ const AnalyticsPage = () => {
24
+ const t = useI18n()
25
+ const controller = new AbortController()
26
+ const datePickerRangeRef = useRef<HTMLDivElement>(null)
27
+ const [fromDate, setFromDate] = React.useState<string>('30daysAgo')
28
+ const [toDate, setToDate] = React.useState<string>('today')
29
+
30
+ // const { data, isError } = trpc.googleAnalytics.test.useQuery()
31
+
32
+ useEffect(() => {
33
+ return () => {
34
+ controller.abort()
35
+ }
36
+ }, [])
37
+
38
+ return (
39
+ <div className='w-full'>
40
+ <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'>
41
+ <h1 className='text-3xl'>{t('analytics')}</h1>
42
+ </div>
43
+ <div className='p-4'>
44
+ <div className='flex gap-2'>
45
+ <Tabs
46
+ defaultValue='account'
47
+ onValueChange={(value) => {
48
+ if (value === 'custom') {
49
+ // Remove hidden class from date picker range
50
+ datePickerRangeRef.current?.classList.remove('hidden')
51
+ } else {
52
+ // Add hidden class to date picker range
53
+ datePickerRangeRef.current?.classList.add('hidden')
54
+ }
55
+ }}
56
+ >
57
+ <Tabs
58
+ defaultValue='lastMonth'
59
+ onValueChange={(value) => {
60
+ if (value === 'custom') {
61
+ // Remove hidden class from date picker range
62
+ datePickerRangeRef.current?.classList.remove('hidden')
63
+ } else {
64
+ switch (value) {
65
+ case 'today':
66
+ setFromDate('yesterday')
67
+ setToDate('today')
68
+ break
69
+ case 'lastWeek':
70
+ setFromDate('10daysAgo')
71
+ setToDate('today')
72
+ break
73
+ case 'lastMonth':
74
+ setFromDate('30daysAgo')
75
+ setToDate('today')
76
+ break
77
+ case 'lastYear':
78
+ setFromDate('365daysAgo')
79
+ setToDate('today')
80
+ break
81
+ }
82
+ // Add hidden class to date picker range
83
+ datePickerRangeRef.current?.classList.add('hidden')
84
+ }
85
+ }}
86
+ >
87
+ <TabsList>
88
+ <TabsTrigger value='today'>{t('today')}</TabsTrigger>
89
+ <TabsTrigger value='lastWeek'>{t('last7Days')}</TabsTrigger>
90
+ <TabsTrigger value='lastMonth'>{t('last30Days')}</TabsTrigger>
91
+ <TabsTrigger value='lastYear'>{t('last365Days')}</TabsTrigger>
92
+ <TabsTrigger value='custom'>{t('custom')}</TabsTrigger>
93
+ </TabsList>
94
+ </Tabs>
95
+ </Tabs>
96
+ <div ref={datePickerRangeRef} className='hidden'>
97
+ <DateRangeFormInput input={{
98
+ name: 'dateRange',
99
+ label: 'Date Range',
100
+ required: true,
101
+ conditionalFields: [],
102
+ readonly: false,
103
+ defaultValue: undefined,
104
+ value: undefined,
105
+ startName: 'fromDate',
106
+ endName: 'toDate',
107
+ format: 'date',
108
+ startValue: fromDate,
109
+ endValue: toDate,
110
+ type: 'date_range',
111
+ }} />
112
+ </div>
113
+ </div>
114
+ <div className='my-2 grid grid-cols-2 gap-4 sm-sidebar:grid-cols-2 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-4'>
115
+ <LiveUsersCount />
116
+ <TotalPageViews fromDate={fromDate} toDate={toDate} />
117
+ <TotalSessions fromDate={fromDate} toDate={toDate} />
118
+ <TotalUniqueUsers fromDate={fromDate} toDate={toDate} />
119
+ </div>
120
+ <div className='my-4 grid grid-cols-1 gap-4 sm-sidebar:grid-cols-1 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-4'>
121
+ <div className='col-span-2'>
122
+ <MonthlyPageViews fromDate={fromDate} toDate={toDate} />
123
+ </div>
124
+ <div className='col-span-2 grid grid-cols-1 gap-4 sm-sidebar:grid-cols-1 md-sidebar:grid-cols-2'>
125
+ <TopCountries fromDate={fromDate} toDate={toDate} />
126
+ <BounceRate fromDate={fromDate} toDate={toDate} />
127
+ </div>
128
+ </div>
129
+ <div className='my-4 grid grid-cols-1 gap-4 sm-sidebar:grid-cols-1 md-sidebar:grid-cols-2 lg-sidebar:grid-cols-4'>
130
+ <div className='col-span-2'>
131
+ <TopSources fromDate={fromDate} toDate={toDate} />
132
+ </div>
133
+ <TopMediums fromDate={fromDate} toDate={toDate} />
134
+ <TopDevices fromDate={fromDate} toDate={toDate} />
135
+ </div>
136
+ <div className='my-2'>
137
+ <LivePageViews />
138
+ </div>
139
+ </div>
140
+ </div>
141
+ )
142
+ }
143
+
144
+ export default AnalyticsPage
@@ -1,42 +1,42 @@
1
- import ContainerBox from '@/components/ContainerBox'
2
- import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer } from 'recharts'
3
- import { BarChartDataItem } from 'nextjs-cms/core/types'
4
- import LoadingSpinners from '@/components/LoadingSpinners'
5
-
6
- export default function BarChartBox({
7
- chartData,
8
- title,
9
- fill = '#adfa1d',
10
- isLoading,
11
- }: {
12
- chartData: BarChartDataItem[]
13
- title: string
14
- fill?: string
15
- isLoading?: boolean
16
- }) {
17
- return (
18
- <ContainerBox title={title}>
19
- <div>
20
- <div style={{ width: '100%', height: 300 }}>
21
- {isLoading ? (
22
- <LoadingSpinners single={true} />
23
- ) : (
24
- <ResponsiveContainer width='100%' height='100%'>
25
- <BarChart data={chartData}>
26
- <XAxis
27
- dataKey='name'
28
- stroke='#888888'
29
- fontSize={12}
30
- tickLine={false}
31
- axisLine={false}
32
- />
33
- <YAxis stroke='#888888' fontSize={12} tickLine={false} axisLine={true} />
34
- <Bar dataKey='value' fill={fill} radius={[4, 4, 0, 0]} />
35
- </BarChart>
36
- </ResponsiveContainer>
37
- )}
38
- </div>
39
- </div>
40
- </ContainerBox>
41
- )
42
- }
1
+ import ContainerBox from '@/components/ContainerBox'
2
+ import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer } from 'recharts'
3
+ import { BarChartDataItem } from 'nextjs-cms/core/types'
4
+ import LoadingSpinners from '@/components/LoadingSpinners'
5
+
6
+ export default function BarChartBox({
7
+ chartData,
8
+ title,
9
+ fill = '#adfa1d',
10
+ isLoading,
11
+ }: {
12
+ chartData: BarChartDataItem[]
13
+ title: string
14
+ fill?: string
15
+ isLoading?: boolean
16
+ }) {
17
+ return (
18
+ <ContainerBox title={title}>
19
+ <div>
20
+ <div style={{ width: '100%', height: 300 }}>
21
+ {isLoading ? (
22
+ <LoadingSpinners single={true} />
23
+ ) : (
24
+ <ResponsiveContainer width='100%' height='100%'>
25
+ <BarChart data={chartData}>
26
+ <XAxis
27
+ dataKey='name'
28
+ stroke='#888888'
29
+ fontSize={12}
30
+ tickLine={false}
31
+ axisLine={false}
32
+ />
33
+ <YAxis stroke='#888888' fontSize={12} tickLine={false} axisLine={true} />
34
+ <Bar dataKey='value' fill={fill} radius={[4, 4, 0, 0]} />
35
+ </BarChart>
36
+ </ResponsiveContainer>
37
+ )}
38
+ </div>
39
+ </div>
40
+ </ContainerBox>
41
+ )
42
+ }
@@ -1,106 +1,106 @@
1
- 'use client'
2
-
3
- import { useRef } from 'react'
4
- import { useI18n } from 'nextjs-cms/translations/client'
5
- import SectionItemCard from '@/components/SectionItemCard'
6
- import ContainerBox from '@/components/ContainerBox'
7
- import Pagination from '@/components/pagination/Pagination'
8
- import { Alert, AlertDescription } from '@/components/ui/alert'
9
- import { Card, CardContent, CardFooter, CardHeader, CardTitle } from './ui/card'
10
- import { Input } from './ui/input'
11
- import { Button } from './ui/button'
12
- import { useRouter, useSearchParams } from 'next/navigation'
13
- import { trpc } from '@/app/_trpc/client'
14
- import { capitalizeWords } from 'nextjs-cms/utils'
15
- import ErrorComponent from '@/components/ErrorComponent'
16
-
17
- export default function BrowsePage({ section, page }: { section: string; page: string }) {
18
- const t = useI18n()
19
- const pageInt = parseInt(page) ?? 1
20
- const params = useSearchParams()
21
- const router = useRouter()
22
- const q = params.get('q') ?? ''
23
- const searchInputRef = useRef<HTMLInputElement>(null)
24
- const [data, {refetch}] = trpc.hasItemsSections.listItems.useSuspenseQuery({
25
- sectionName: section,
26
- page: pageInt,
27
- q,
28
- })
29
-
30
- if (data.error) {
31
- return <ErrorComponent message={data.error.message} />
32
- }
33
-
34
- return (
35
- <div>
36
- <div className='text-foreground relative z-1 border-b-2 p-8 pt-12 font-extrabold'>
37
- <div className='absolute top-0 left-0 z-2 h-4 w-full bg-linear-to-r from-sky-300 via-gray-300 to-blue-400'></div>
38
- <h1 className='text-3xl'>{data?.section?.title}</h1>
39
- </div>
40
- <div className='p-4'>
41
- {data?.section?.hasSearch ? (
42
- <Card className='border-accent-foreground mb-4 border'>
43
- <form
44
- onSubmit={(event) => {
45
- event.preventDefault()
46
- event.stopPropagation()
47
-
48
- router.push(
49
- decodeURIComponent(`/browse/${section}?q=${searchInputRef.current?.value || ''}`),
50
- )
51
- }}
52
- >
53
- <CardHeader>
54
- <CardTitle>{t('search')} {data?.section?.title}</CardTitle>
55
- {/*<CardDescription>Search by title</CardDescription>*/}
56
- </CardHeader>
57
- <CardContent>
58
- <Input
59
- className='border-accent-foreground bg-input'
60
- ref={searchInputRef}
61
- placeholder={`${capitalizeWords(t('search'))}...`}
62
- defaultValue={q || ''}
63
- />
64
- </CardContent>
65
- <CardFooter className='border-t px-6 py-4'>
66
- <Button>{capitalizeWords(t('search'))}</Button>
67
- </CardFooter>
68
- </form>
69
- </Card>
70
- ) : null}
71
- <ContainerBox title={t('browse')}>
72
-
73
-
74
- { data.items && data.items.length > 0 ? (
75
- <div className='mt-2 grid w-full grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'>
76
- {data.items.map((item, index: number) => (
77
- <SectionItemCard
78
- key={`${data.section.name}-${item.id}-${index}`}
79
- item={item}
80
- sectionName={data.section.name}
81
- action={() => refetch()}
82
- />
83
- ))}
84
- </div>
85
- ) : (
86
- <Alert variant='default' className='bg-primary text-primary-foreground my-8'>
87
- <AlertDescription className='font-bold'>{t('noItems')}</AlertDescription>
88
- </Alert>
89
- )}
90
-
91
- </ContainerBox>
92
- {data?.totalCount && data?.totalCount > 0 ? (
93
- <Pagination
94
- page={pageInt}
95
- totalCount={data?.totalCount}
96
- limit={12}
97
- route={`browse/${section}`}
98
- lang='en'
99
- paginationLinksToShow={4}
100
- searchParams={q ? `q=${q}` : null}
101
- />
102
- ) : null}
103
- </div>
104
- </div>
105
- )
106
- }
1
+ 'use client'
2
+
3
+ import { useRef } from 'react'
4
+ import { useI18n } from 'nextjs-cms/translations/client'
5
+ import SectionItemCard from '@/components/SectionItemCard'
6
+ import ContainerBox from '@/components/ContainerBox'
7
+ import Pagination from '@/components/pagination/Pagination'
8
+ import { Alert, AlertDescription } from '@/components/ui/alert'
9
+ import { Card, CardContent, CardFooter, CardHeader, CardTitle } from './ui/card'
10
+ import { Input } from './ui/input'
11
+ import { Button } from './ui/button'
12
+ import { useRouter, useSearchParams } from 'next/navigation'
13
+ import { trpc } from '@/app/_trpc/client'
14
+ import { capitalizeWords } from 'nextjs-cms/utils'
15
+ import ErrorComponent from '@/components/ErrorComponent'
16
+
17
+ export default function BrowsePage({ section, page }: { section: string; page: string }) {
18
+ const t = useI18n()
19
+ const pageInt = parseInt(page) ?? 1
20
+ const params = useSearchParams()
21
+ const router = useRouter()
22
+ const q = params.get('q') ?? ''
23
+ const searchInputRef = useRef<HTMLInputElement>(null)
24
+ const [data, {refetch}] = trpc.hasItemsSections.listItems.useSuspenseQuery({
25
+ sectionName: section,
26
+ page: pageInt,
27
+ q,
28
+ })
29
+
30
+ if (data.error) {
31
+ return <ErrorComponent message={data.error.message} />
32
+ }
33
+
34
+ return (
35
+ <div>
36
+ <div className='text-foreground relative z-1 border-b-2 p-8 pt-12 font-extrabold'>
37
+ <div className='absolute top-0 left-0 z-2 h-4 w-full bg-linear-to-r from-sky-300 via-gray-300 to-blue-400'></div>
38
+ <h1 className='text-3xl'>{data?.section?.title}</h1>
39
+ </div>
40
+ <div className='p-4'>
41
+ {data?.section?.hasSearch ? (
42
+ <Card className='border-accent-foreground mb-4 border'>
43
+ <form
44
+ onSubmit={(event) => {
45
+ event.preventDefault()
46
+ event.stopPropagation()
47
+
48
+ router.push(
49
+ decodeURIComponent(`/browse/${section}?q=${searchInputRef.current?.value || ''}`),
50
+ )
51
+ }}
52
+ >
53
+ <CardHeader>
54
+ <CardTitle>{t('search')} {data?.section?.title}</CardTitle>
55
+ {/*<CardDescription>Search by title</CardDescription>*/}
56
+ </CardHeader>
57
+ <CardContent>
58
+ <Input
59
+ className='border-accent-foreground bg-input'
60
+ ref={searchInputRef}
61
+ placeholder={`${capitalizeWords(t('search'))}...`}
62
+ defaultValue={q || ''}
63
+ />
64
+ </CardContent>
65
+ <CardFooter className='border-t px-6 py-4'>
66
+ <Button>{capitalizeWords(t('search'))}</Button>
67
+ </CardFooter>
68
+ </form>
69
+ </Card>
70
+ ) : null}
71
+ <ContainerBox title={t('browse')}>
72
+
73
+
74
+ { data.items && data.items.length > 0 ? (
75
+ <div className='mt-2 grid w-full grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'>
76
+ {data.items.map((item, index: number) => (
77
+ <SectionItemCard
78
+ key={`${data.section.name}-${item.id}-${index}`}
79
+ item={item}
80
+ sectionName={data.section.name}
81
+ action={() => refetch()}
82
+ />
83
+ ))}
84
+ </div>
85
+ ) : (
86
+ <Alert variant='default' className='bg-primary text-primary-foreground my-8'>
87
+ <AlertDescription className='font-bold'>{t('noItems')}</AlertDescription>
88
+ </Alert>
89
+ )}
90
+
91
+ </ContainerBox>
92
+ {data?.totalCount && data?.totalCount > 0 ? (
93
+ <Pagination
94
+ page={pageInt}
95
+ totalCount={data?.totalCount}
96
+ limit={12}
97
+ route={`browse/${section}`}
98
+ lang='en'
99
+ paginationLinksToShow={4}
100
+ searchParams={q ? `q=${q}` : null}
101
+ />
102
+ ) : null}
103
+ </div>
104
+ </div>
105
+ )
106
+ }