create-nextblock 0.0.1

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 (206) hide show
  1. package/bin/create-nextblock.js +997 -0
  2. package/package.json +25 -0
  3. package/scripts/sync-template.js +284 -0
  4. package/templates/nextblock-template/.env.example +37 -0
  5. package/templates/nextblock-template/.swcrc +30 -0
  6. package/templates/nextblock-template/README.md +194 -0
  7. package/templates/nextblock-template/app/(auth-pages)/forgot-password/page.tsx +57 -0
  8. package/templates/nextblock-template/app/(auth-pages)/layout.tsx +9 -0
  9. package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +28 -0
  10. package/templates/nextblock-template/app/(auth-pages)/sign-in/page.tsx +67 -0
  11. package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +70 -0
  12. package/templates/nextblock-template/app/ToasterProvider.tsx +17 -0
  13. package/templates/nextblock-template/app/[slug]/PageClientContent.tsx +147 -0
  14. package/templates/nextblock-template/app/[slug]/page.tsx +145 -0
  15. package/templates/nextblock-template/app/[slug]/page.utils.ts +183 -0
  16. package/templates/nextblock-template/app/actions/email.ts +31 -0
  17. package/templates/nextblock-template/app/actions/formActions.ts +65 -0
  18. package/templates/nextblock-template/app/actions/languageActions.ts +130 -0
  19. package/templates/nextblock-template/app/actions/postActions.ts +80 -0
  20. package/templates/nextblock-template/app/actions.ts +146 -0
  21. package/templates/nextblock-template/app/api/process-image/route.ts +210 -0
  22. package/templates/nextblock-template/app/api/revalidate/route.ts +86 -0
  23. package/templates/nextblock-template/app/api/revalidate-log/route.ts +23 -0
  24. package/templates/nextblock-template/app/api/upload/presigned-url/route.ts +106 -0
  25. package/templates/nextblock-template/app/api/upload/proxy/route.ts +84 -0
  26. package/templates/nextblock-template/app/auth/callback/route.ts +58 -0
  27. package/templates/nextblock-template/app/blog/[slug]/PostClientContent.tsx +169 -0
  28. package/templates/nextblock-template/app/blog/[slug]/page.tsx +177 -0
  29. package/templates/nextblock-template/app/blog/[slug]/page.utils.ts +136 -0
  30. package/templates/nextblock-template/app/blog/page.tsx +77 -0
  31. package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +321 -0
  32. package/templates/nextblock-template/app/cms/blocks/actions.ts +434 -0
  33. package/templates/nextblock-template/app/cms/blocks/components/BackgroundSelector.tsx +348 -0
  34. package/templates/nextblock-template/app/cms/blocks/components/BlockEditorArea.tsx +567 -0
  35. package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +98 -0
  36. package/templates/nextblock-template/app/cms/blocks/components/BlockTypeCard.tsx +58 -0
  37. package/templates/nextblock-template/app/cms/blocks/components/BlockTypeSelector.tsx +62 -0
  38. package/templates/nextblock-template/app/cms/blocks/components/ColumnEditor.tsx +276 -0
  39. package/templates/nextblock-template/app/cms/blocks/components/DeleteBlockButtonClient.tsx +47 -0
  40. package/templates/nextblock-template/app/cms/blocks/components/EditableBlock.tsx +182 -0
  41. package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +120 -0
  42. package/templates/nextblock-template/app/cms/blocks/components/SectionConfigPanel.tsx +133 -0
  43. package/templates/nextblock-template/app/cms/blocks/components/SortableBlockItem.tsx +46 -0
  44. package/templates/nextblock-template/app/cms/blocks/editors/ButtonBlockEditor.tsx +85 -0
  45. package/templates/nextblock-template/app/cms/blocks/editors/FormBlockEditor.tsx +182 -0
  46. package/templates/nextblock-template/app/cms/blocks/editors/HeadingBlockEditor.tsx +111 -0
  47. package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +150 -0
  48. package/templates/nextblock-template/app/cms/blocks/editors/PostsGridBlockEditor.tsx +79 -0
  49. package/templates/nextblock-template/app/cms/blocks/editors/SectionBlockEditor.tsx +337 -0
  50. package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +81 -0
  51. package/templates/nextblock-template/app/cms/blocks/editors/VideoEmbedBlockEditor.tsx +64 -0
  52. package/templates/nextblock-template/app/cms/components/ConfirmationModal.tsx +51 -0
  53. package/templates/nextblock-template/app/cms/components/ContentLanguageSwitcher.tsx +145 -0
  54. package/templates/nextblock-template/app/cms/components/CopyContentFromLanguage.tsx +203 -0
  55. package/templates/nextblock-template/app/cms/components/LanguageFilterSelect.tsx +69 -0
  56. package/templates/nextblock-template/app/cms/dashboard/page.tsx +247 -0
  57. package/templates/nextblock-template/app/cms/layout.tsx +10 -0
  58. package/templates/nextblock-template/app/cms/media/UploadFolderContext.tsx +22 -0
  59. package/templates/nextblock-template/app/cms/media/[id]/edit/page.tsx +80 -0
  60. package/templates/nextblock-template/app/cms/media/actions.ts +577 -0
  61. package/templates/nextblock-template/app/cms/media/components/DeleteMediaButtonClient.tsx +53 -0
  62. package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -0
  63. package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -0
  64. package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +157 -0
  65. package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +275 -0
  66. package/templates/nextblock-template/app/cms/media/components/MediaImage.tsx +70 -0
  67. package/templates/nextblock-template/app/cms/media/components/MediaPickerDialog.tsx +195 -0
  68. package/templates/nextblock-template/app/cms/media/components/MediaUploadForm.tsx +362 -0
  69. package/templates/nextblock-template/app/cms/media/page.tsx +120 -0
  70. package/templates/nextblock-template/app/cms/navigation/[id]/edit/page.tsx +101 -0
  71. package/templates/nextblock-template/app/cms/navigation/actions.ts +358 -0
  72. package/templates/nextblock-template/app/cms/navigation/components/DeleteNavItemButton.tsx +52 -0
  73. package/templates/nextblock-template/app/cms/navigation/components/NavigationItemForm.tsx +248 -0
  74. package/templates/nextblock-template/app/cms/navigation/components/NavigationLanguageSwitcher.tsx +132 -0
  75. package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +701 -0
  76. package/templates/nextblock-template/app/cms/navigation/components/SortableNavItem.tsx +98 -0
  77. package/templates/nextblock-template/app/cms/navigation/new/page.tsx +26 -0
  78. package/templates/nextblock-template/app/cms/navigation/page.tsx +102 -0
  79. package/templates/nextblock-template/app/cms/navigation/utils.ts +51 -0
  80. package/templates/nextblock-template/app/cms/pages/[id]/edit/EditPageClient.tsx +121 -0
  81. package/templates/nextblock-template/app/cms/pages/[id]/edit/page.tsx +79 -0
  82. package/templates/nextblock-template/app/cms/pages/actions.ts +241 -0
  83. package/templates/nextblock-template/app/cms/pages/components/DeletePageButtonClient.tsx +47 -0
  84. package/templates/nextblock-template/app/cms/pages/components/PageForm.tsx +253 -0
  85. package/templates/nextblock-template/app/cms/pages/new/page.tsx +52 -0
  86. package/templates/nextblock-template/app/cms/pages/page.tsx +232 -0
  87. package/templates/nextblock-template/app/cms/posts/[id]/edit/page.tsx +183 -0
  88. package/templates/nextblock-template/app/cms/posts/actions.ts +309 -0
  89. package/templates/nextblock-template/app/cms/posts/components/DeletePostButtonClient.tsx +55 -0
  90. package/templates/nextblock-template/app/cms/posts/components/PostForm.tsx +419 -0
  91. package/templates/nextblock-template/app/cms/posts/new/page.tsx +21 -0
  92. package/templates/nextblock-template/app/cms/posts/page.tsx +192 -0
  93. package/templates/nextblock-template/app/cms/revisions/JsonDiffView.tsx +86 -0
  94. package/templates/nextblock-template/app/cms/revisions/RevisionHistoryButton.tsx +201 -0
  95. package/templates/nextblock-template/app/cms/revisions/actions.ts +84 -0
  96. package/templates/nextblock-template/app/cms/revisions/service.ts +344 -0
  97. package/templates/nextblock-template/app/cms/revisions/utils.ts +127 -0
  98. package/templates/nextblock-template/app/cms/settings/copyright/actions.ts +68 -0
  99. package/templates/nextblock-template/app/cms/settings/copyright/components/CopyrightForm.tsx +78 -0
  100. package/templates/nextblock-template/app/cms/settings/copyright/page.tsx +32 -0
  101. package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +117 -0
  102. package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +216 -0
  103. package/templates/nextblock-template/app/cms/settings/languages/[id]/edit/page.tsx +77 -0
  104. package/templates/nextblock-template/app/cms/settings/languages/actions.ts +261 -0
  105. package/templates/nextblock-template/app/cms/settings/languages/components/DeleteLanguageButton.tsx +76 -0
  106. package/templates/nextblock-template/app/cms/settings/languages/components/LanguageForm.tsx +167 -0
  107. package/templates/nextblock-template/app/cms/settings/languages/new/page.tsx +34 -0
  108. package/templates/nextblock-template/app/cms/settings/languages/page.tsx +156 -0
  109. package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +19 -0
  110. package/templates/nextblock-template/app/cms/settings/logos/actions.ts +114 -0
  111. package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +177 -0
  112. package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +11 -0
  113. package/templates/nextblock-template/app/cms/settings/logos/page.tsx +118 -0
  114. package/templates/nextblock-template/app/cms/settings/logos/types.ts +8 -0
  115. package/templates/nextblock-template/app/cms/users/[id]/edit/page.tsx +91 -0
  116. package/templates/nextblock-template/app/cms/users/actions.ts +156 -0
  117. package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +71 -0
  118. package/templates/nextblock-template/app/cms/users/components/UserForm.tsx +138 -0
  119. package/templates/nextblock-template/app/cms/users/page.tsx +183 -0
  120. package/templates/nextblock-template/app/favicon.ico +0 -0
  121. package/templates/nextblock-template/app/globals.css +401 -0
  122. package/templates/nextblock-template/app/layout.tsx +191 -0
  123. package/templates/nextblock-template/app/lib/sitemap-utils.ts +68 -0
  124. package/templates/nextblock-template/app/page.tsx +109 -0
  125. package/templates/nextblock-template/app/providers.tsx +43 -0
  126. package/templates/nextblock-template/app/robots.txt/route.ts +19 -0
  127. package/templates/nextblock-template/app/sitemap.xml/route.ts +63 -0
  128. package/templates/nextblock-template/app/unauthorized/page.tsx +27 -0
  129. package/templates/nextblock-template/backup/backup_2025-06-19.sql +8057 -0
  130. package/templates/nextblock-template/backup/backup_2025-06-20.sql +8159 -0
  131. package/templates/nextblock-template/backup/backup_2025-07-08.sql +8411 -0
  132. package/templates/nextblock-template/backup/backup_2025-07-09.sql +8442 -0
  133. package/templates/nextblock-template/backup/backup_2025-07-10.sql +8442 -0
  134. package/templates/nextblock-template/backup/backup_2025-10-01.sql +8803 -0
  135. package/templates/nextblock-template/backup/backup_2025-10-02.sql +9749 -0
  136. package/templates/nextblock-template/components/BlockRenderer.tsx +119 -0
  137. package/templates/nextblock-template/components/FooterNavigation.tsx +33 -0
  138. package/templates/nextblock-template/components/Header.tsx +42 -0
  139. package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -0
  140. package/templates/nextblock-template/components/LanguageSwitcher.tsx +103 -0
  141. package/templates/nextblock-template/components/ResponsiveNav.tsx +372 -0
  142. package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +17 -0
  143. package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +93 -0
  144. package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +180 -0
  145. package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -0
  146. package/templates/nextblock-template/components/blocks/renderers/ClientTextBlockRenderer.tsx +69 -0
  147. package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +98 -0
  148. package/templates/nextblock-template/components/blocks/renderers/HeadingBlockRenderer.tsx +41 -0
  149. package/templates/nextblock-template/components/blocks/renderers/HeroBlockRenderer.tsx +240 -0
  150. package/templates/nextblock-template/components/blocks/renderers/ImageBlockRenderer.tsx +79 -0
  151. package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +33 -0
  152. package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +189 -0
  153. package/templates/nextblock-template/components/blocks/renderers/TextBlockRenderer.tsx +31 -0
  154. package/templates/nextblock-template/components/blocks/renderers/VideoEmbedBlockRenderer.tsx +59 -0
  155. package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +51 -0
  156. package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +40 -0
  157. package/templates/nextblock-template/components/blocks/types.ts +8 -0
  158. package/templates/nextblock-template/components/env-var-warning.tsx +33 -0
  159. package/templates/nextblock-template/components/form-message.tsx +26 -0
  160. package/templates/nextblock-template/components/header-auth.tsx +71 -0
  161. package/templates/nextblock-template/components/submit-button.tsx +23 -0
  162. package/templates/nextblock-template/components/theme-switcher.tsx +78 -0
  163. package/templates/nextblock-template/context/AuthContext.tsx +138 -0
  164. package/templates/nextblock-template/context/CurrentContentContext.tsx +42 -0
  165. package/templates/nextblock-template/context/LanguageContext.tsx +206 -0
  166. package/templates/nextblock-template/docs/cms-application-overview.md +56 -0
  167. package/templates/nextblock-template/docs/cms-architecture-overview.md +73 -0
  168. package/templates/nextblock-template/docs/files-structure.md +426 -0
  169. package/templates/nextblock-template/docs/tiptap-bundle-optimization-summary.md +174 -0
  170. package/templates/nextblock-template/eslint.config.mjs +28 -0
  171. package/templates/nextblock-template/index.d.ts +5 -0
  172. package/templates/nextblock-template/lib/blocks/README.md +670 -0
  173. package/templates/nextblock-template/lib/blocks/blockRegistry.ts +1001 -0
  174. package/templates/nextblock-template/lib/ui/ColorPicker.ts +1 -0
  175. package/templates/nextblock-template/lib/ui/ConfirmationDialog.ts +1 -0
  176. package/templates/nextblock-template/lib/ui/CustomSelectWithInput.ts +1 -0
  177. package/templates/nextblock-template/lib/ui/Skeleton.ts +1 -0
  178. package/templates/nextblock-template/lib/ui/avatar.ts +1 -0
  179. package/templates/nextblock-template/lib/ui/badge.ts +1 -0
  180. package/templates/nextblock-template/lib/ui/button.ts +1 -0
  181. package/templates/nextblock-template/lib/ui/card.ts +1 -0
  182. package/templates/nextblock-template/lib/ui/checkbox.ts +1 -0
  183. package/templates/nextblock-template/lib/ui/dialog.ts +1 -0
  184. package/templates/nextblock-template/lib/ui/dropdown-menu.ts +1 -0
  185. package/templates/nextblock-template/lib/ui/input.ts +1 -0
  186. package/templates/nextblock-template/lib/ui/label.ts +1 -0
  187. package/templates/nextblock-template/lib/ui/popover.ts +1 -0
  188. package/templates/nextblock-template/lib/ui/progress.ts +1 -0
  189. package/templates/nextblock-template/lib/ui/select.ts +1 -0
  190. package/templates/nextblock-template/lib/ui/separator.ts +1 -0
  191. package/templates/nextblock-template/lib/ui/table.ts +1 -0
  192. package/templates/nextblock-template/lib/ui/textarea.ts +1 -0
  193. package/templates/nextblock-template/lib/ui/tooltip.ts +1 -0
  194. package/templates/nextblock-template/lib/ui/ui.ts +1 -0
  195. package/templates/nextblock-template/middleware.ts +206 -0
  196. package/templates/nextblock-template/next-env.d.ts +6 -0
  197. package/templates/nextblock-template/next.config.js +99 -0
  198. package/templates/nextblock-template/package.json +52 -0
  199. package/templates/nextblock-template/postcss.config.js +6 -0
  200. package/templates/nextblock-template/project.json +7 -0
  201. package/templates/nextblock-template/public/.gitkeep +0 -0
  202. package/templates/nextblock-template/scripts/backfill-image-meta.ts +149 -0
  203. package/templates/nextblock-template/scripts/backup.js +53 -0
  204. package/templates/nextblock-template/scripts/test-bundle-optimization.js +114 -0
  205. package/templates/nextblock-template/tailwind.config.ts +19 -0
  206. package/templates/nextblock-template/tsconfig.json +62 -0
@@ -0,0 +1,247 @@
1
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@nextblock-cms/ui"
2
+ import { Calendar, FileText, PenTool, Users, ArrowUpRight, ArrowDownRight, Eye } from "lucide-react"
3
+
4
+ export default function CmsDashboardPage() {
5
+ return (
6
+ <div className="w-full space-y-6">
7
+ <div>
8
+ <h2 className="text-xl font-bold mb-2">Welcome to the CMS Dashboard</h2>
9
+ <p className="text-muted-foreground">Manage your content and monitor site performance from one place.</p>
10
+ </div>
11
+
12
+ {/* Stats overview */}
13
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
14
+ <Card>
15
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
16
+ <CardTitle className="text-sm font-medium">Total Pages</CardTitle>
17
+ <FileText className="h-4 w-4 text-muted-foreground" />
18
+ </CardHeader>
19
+ <CardContent>
20
+ <div className="text-2xl font-bold">24</div>
21
+ <p className="text-xs text-muted-foreground mt-1">
22
+ <span className="text-emerald-500 font-medium inline-flex items-center">
23
+ <ArrowUpRight className="h-3 w-3 mr-1" />
24
+ 12%
25
+ </span>{" "}
26
+ from last month
27
+ </p>
28
+ </CardContent>
29
+ </Card>
30
+
31
+ <Card>
32
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
33
+ <CardTitle className="text-sm font-medium">Total Posts</CardTitle>
34
+ <PenTool className="h-4 w-4 text-muted-foreground" />
35
+ </CardHeader>
36
+ <CardContent>
37
+ <div className="text-2xl font-bold">142</div>
38
+ <p className="text-xs text-muted-foreground mt-1">
39
+ <span className="text-emerald-500 font-medium inline-flex items-center">
40
+ <ArrowUpRight className="h-3 w-3 mr-1" />
41
+ 8%
42
+ </span>{" "}
43
+ from last month
44
+ </p>
45
+ </CardContent>
46
+ </Card>
47
+
48
+ <Card>
49
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
50
+ <CardTitle className="text-sm font-medium">Page Views</CardTitle>
51
+ <Eye className="h-4 w-4 text-muted-foreground" />
52
+ </CardHeader>
53
+ <CardContent>
54
+ <div className="text-2xl font-bold">8,623</div>
55
+ <p className="text-xs text-muted-foreground mt-1">
56
+ <span className="text-emerald-500 font-medium inline-flex items-center">
57
+ <ArrowUpRight className="h-3 w-3 mr-1" />
58
+ 24%
59
+ </span>{" "}
60
+ from last month
61
+ </p>
62
+ </CardContent>
63
+ </Card>
64
+
65
+ <Card>
66
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
67
+ <CardTitle className="text-sm font-medium">Active Users</CardTitle>
68
+ <Users className="h-4 w-4 text-muted-foreground" />
69
+ </CardHeader>
70
+ <CardContent>
71
+ <div className="text-2xl font-bold">573</div>
72
+ <p className="text-xs text-muted-foreground mt-1">
73
+ <span className="text-red-500 font-medium inline-flex items-center">
74
+ <ArrowDownRight className="h-3 w-3 mr-1" />
75
+ 3%
76
+ </span>{" "}
77
+ from last month
78
+ </p>
79
+ </CardContent>
80
+ </Card>
81
+ </div>
82
+
83
+ {/* Recent activity and analytics */}
84
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
85
+ <Card className="col-span-1">
86
+ <CardHeader>
87
+ <CardTitle>Recent Content</CardTitle>
88
+ <CardDescription>Latest content updates across your site</CardDescription>
89
+ </CardHeader>
90
+ <CardContent>
91
+ <div className="space-y-4">
92
+ {recentContent.map((item, index) => (
93
+ <div key={index} className="flex items-start gap-4 pb-4 border-b last:border-0 last:pb-0">
94
+ <div
95
+ className={`w-8 h-8 rounded-full flex items-center justify-center ${item.type === "page" ? "bg-blue-100 text-blue-600" : "bg-amber-100 text-amber-600"} dark:bg-opacity-20`}
96
+ >
97
+ {item.type === "page" ? <FileText className="h-4 w-4" /> : <PenTool className="h-4 w-4" />}
98
+ </div>
99
+ <div className="flex-1">
100
+ <h4 className="text-sm font-medium">{item.title}</h4>
101
+ <div className="flex items-center gap-2 mt-1">
102
+ <p className="text-xs text-muted-foreground">{item.author}</p>
103
+ <span className="text-xs text-muted-foreground">•</span>
104
+ <p className="text-xs text-muted-foreground">{item.date}</p>
105
+ </div>
106
+ </div>
107
+ <div className="flex items-center">
108
+ <span
109
+ className={`text-xs px-2 py-1 rounded-full ${item.status === "Published" ? "bg-emerald-100 text-emerald-700" : "bg-amber-100 text-amber-700"} dark:bg-opacity-20`}
110
+ >
111
+ {item.status}
112
+ </span>
113
+ </div>
114
+ </div>
115
+ ))}
116
+ </div>
117
+ </CardContent>
118
+ </Card>
119
+
120
+ <Card className="col-span-1">
121
+ <CardHeader>
122
+ <CardTitle>Upcoming Schedule</CardTitle>
123
+ <CardDescription>Content scheduled for publication</CardDescription>
124
+ </CardHeader>
125
+ <CardContent>
126
+ <div className="space-y-4">
127
+ {scheduledContent.map((item, index) => (
128
+ <div key={index} className="flex items-start gap-4 pb-4 border-b last:border-0 last:pb-0">
129
+ <div className="w-10 h-10 rounded bg-slate-100 dark:bg-slate-800 flex flex-col items-center justify-center text-center">
130
+ <span className="text-xs font-medium">{item.month}</span>
131
+ <span className="text-sm font-bold">{item.day}</span>
132
+ </div>
133
+ <div className="flex-1">
134
+ <h4 className="text-sm font-medium">{item.title}</h4>
135
+ <div className="flex items-center gap-2 mt-1">
136
+ <Calendar className="h-3 w-3 text-muted-foreground" />
137
+ <p className="text-xs text-muted-foreground">{item.time}</p>
138
+ </div>
139
+ </div>
140
+ <div className="flex items-center">
141
+ <span className="text-xs px-2 py-1 rounded-full bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300">
142
+ {item.type}
143
+ </span>
144
+ </div>
145
+ </div>
146
+ ))}
147
+ </div>
148
+ </CardContent>
149
+ </Card>
150
+ </div>
151
+
152
+ {/* Analytics chart */}
153
+ <Card>
154
+ <CardHeader>
155
+ <CardTitle>Traffic Overview</CardTitle>
156
+ <CardDescription>Page views over the last 30 days</CardDescription>
157
+ </CardHeader>
158
+ <CardContent>
159
+ <div className="h-[200px] flex items-end gap-2">
160
+ {analyticsData.map((item, index) => (
161
+ <div key={index} className="flex-1 flex flex-col items-center">
162
+ <div
163
+ className="w-full bg-primary/10 dark:bg-primary/20 rounded-sm"
164
+ style={{ height: `${item.value}%` }}
165
+ ></div>
166
+ <span className="text-xs text-muted-foreground mt-2">{item.label}</span>
167
+ </div>
168
+ ))}
169
+ </div>
170
+ </CardContent>
171
+ </Card>
172
+ </div>
173
+ )
174
+ }
175
+
176
+ // Sample data
177
+ const recentContent = [
178
+ {
179
+ title: "Homepage Redesign",
180
+ type: "page",
181
+ author: "John Smith",
182
+ date: "Today, 2:30 PM",
183
+ status: "Published",
184
+ },
185
+ {
186
+ title: "New Product Launch",
187
+ type: "post",
188
+ author: "Sarah Johnson",
189
+ date: "Yesterday, 10:15 AM",
190
+ status: "Published",
191
+ },
192
+ {
193
+ title: "Q2 Marketing Strategy",
194
+ type: "post",
195
+ author: "Michael Brown",
196
+ date: "May 12, 2023",
197
+ status: "Draft",
198
+ },
199
+ {
200
+ title: "About Us Page",
201
+ type: "page",
202
+ author: "John Smith",
203
+ date: "May 10, 2023",
204
+ status: "Published",
205
+ },
206
+ ]
207
+
208
+ const scheduledContent = [
209
+ {
210
+ title: "Summer Sale Announcement",
211
+ month: "May",
212
+ day: "20",
213
+ time: "9:00 AM",
214
+ type: "Post",
215
+ },
216
+ {
217
+ title: "New Feature Release",
218
+ month: "May",
219
+ day: "22",
220
+ time: "12:00 PM",
221
+ type: "Page",
222
+ },
223
+ {
224
+ title: "Customer Testimonials",
225
+ month: "May",
226
+ day: "25",
227
+ time: "3:30 PM",
228
+ type: "Post",
229
+ },
230
+ {
231
+ title: "Team Page Update",
232
+ month: "May",
233
+ day: "28",
234
+ time: "10:00 AM",
235
+ type: "Page",
236
+ },
237
+ ]
238
+
239
+ const analyticsData = [
240
+ { label: "1", value: 20 },
241
+ { label: "5", value: 40 },
242
+ { label: "10", value: 35 },
243
+ { label: "15", value: 50 },
244
+ { label: "20", value: 30 },
245
+ { label: "25", value: 80 },
246
+ { label: "30", value: 60 },
247
+ ]
@@ -0,0 +1,10 @@
1
+ import 'katex/dist/katex.min.css';
2
+ import CmsClientLayout from "./CmsClientLayout";
3
+
4
+ export default function CmsLayout({
5
+ children,
6
+ }: {
7
+ children: React.ReactNode;
8
+ }) {
9
+ return <CmsClientLayout>{children}</CmsClientLayout>;
10
+ }
@@ -0,0 +1,22 @@
1
+ "use client";
2
+
3
+ import React, { createContext, useContext } from "react";
4
+
5
+ type UploadFolderContextValue = {
6
+ defaultFolder?: string | null;
7
+ };
8
+
9
+ const UploadFolderContext = createContext<UploadFolderContextValue>({ defaultFolder: undefined });
10
+
11
+ export function UploadFolderProvider({ defaultFolder, children }: { defaultFolder?: string; children: React.ReactNode }) {
12
+ return (
13
+ <UploadFolderContext.Provider value={{ defaultFolder }}>
14
+ {children}
15
+ </UploadFolderContext.Provider>
16
+ );
17
+ }
18
+
19
+ export function useUploadFolder() {
20
+ return useContext(UploadFolderContext);
21
+ }
22
+
@@ -0,0 +1,80 @@
1
+ // app/cms/media/[id]/edit/page.tsx
2
+ import React from "react";
3
+ import { createClient } from "@nextblock-cms/db/server";
4
+ import MediaEditForm from "../../components/MediaEditForm"; // Adjusted path
5
+ import { updateMediaItem } from "../../actions"; // Server action for updating
6
+ import type { Database } from "@nextblock-cms/db";
7
+ import { notFound, redirect } from "next/navigation";
8
+
9
+ type Media = Database['public']['Tables']['media']['Row'];
10
+ import { ArrowLeft } from "lucide-react";
11
+ import Link from "next/link";
12
+ import { Button } from "@nextblock-cms/ui";
13
+
14
+ async function getMediaData(id: string): Promise<Media | null> {
15
+ const supabase = createClient();
16
+ // Validate if ID is a UUID, otherwise Supabase might error
17
+ // For simplicity, we assume it's a valid UUID format if it reaches here.
18
+ const { data, error } = await supabase
19
+ .from("media")
20
+ .select("*")
21
+ .eq("id", id)
22
+ .single();
23
+
24
+ if (error) {
25
+ console.error("Error fetching media for edit:", error);
26
+ return null;
27
+ }
28
+ return data;
29
+ }
30
+
31
+ export default async function EditMediaPage(props: { params: Promise<{ id: string }> }) {
32
+ const params = await props.params;
33
+ const mediaId = params.id;
34
+ if (!mediaId) { // Basic check, UUID validation could be added
35
+ return notFound();
36
+ }
37
+
38
+ // Verify admin/writer role before even fetching (optional, RLS on media table should also protect)
39
+ const supabase = createClient();
40
+ const { data: { user } } = await supabase.auth.getUser();
41
+ if (!user) return redirect("/sign-in?redirect=/cms/media");
42
+
43
+ const { data: profile } = await supabase.from("profiles").select("role").eq("id", user.id).single();
44
+ if (!profile || !["ADMIN", "WRITER"].includes(profile.role)) {
45
+ return <div className="p-6">Access Denied. You do not have permission to edit media.</div>;
46
+ }
47
+
48
+ const mediaItem = await getMediaData(mediaId);
49
+
50
+ if (!mediaItem) {
51
+ return notFound();
52
+ }
53
+
54
+ // Bind the mediaId to the updateMediaItem server action
55
+ // Wrap to accept FormData as expected by MediaEditForm
56
+ const updateMediaFormAction = async (formData: FormData) => {
57
+ "use server";
58
+ const description = formData.get("description") as string | undefined;
59
+ const file_name = formData.get("file_name") as string | undefined;
60
+ // Return data instead of redirect to avoid NEXT_REDIRECT noise during dev
61
+ return await updateMediaItem(mediaItem.id, { description, file_name }, true);
62
+ };
63
+
64
+ return (
65
+ <div className="w-full">
66
+ <div className="mb-6 flex items-center gap-3">
67
+ <Button variant="outline" size="icon" asChild>
68
+ <Link href="/cms/media">
69
+ <ArrowLeft className="h-4 w-4" />
70
+ </Link>
71
+ </Button>
72
+ <h1 className="text-2xl font-semibold">Edit Media: {mediaItem.file_name}</h1>
73
+ </div>
74
+ <MediaEditForm
75
+ mediaItem={mediaItem}
76
+ formAction={updateMediaFormAction}
77
+ />
78
+ </div>
79
+ );
80
+ }