create-einja-app 0.2.17 → 0.2.18

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 (270) hide show
  1. package/package.json +2 -2
  2. package/templates/default/.claude/hooks/einja/playwright-resize.sh +12 -2
  3. package/templates/default/.claude/settings.json +15 -0
  4. package/templates/default/.cursor/commands/task-vibe-kanban-loop.md +107 -42
  5. package/templates/default/.env.develop +0 -4
  6. package/templates/default/.env.example +1 -0
  7. package/templates/default/.env.preview +0 -4
  8. package/templates/default/.env.staging +19 -0
  9. package/templates/default/.github/actions/ci/action.yml +39 -0
  10. package/templates/default/.github/actions/migrate/action.yml +39 -0
  11. package/templates/default/.github/actions/neon-export-env/action.yml +28 -0
  12. package/templates/default/.github/actions/setup/action.yml +20 -0
  13. package/templates/default/.github/workflows/claude.yml +1 -0
  14. package/templates/default/.github/workflows/{cleanup-neon-branches.yml → cleanup-pr-preview-db.yml} +28 -24
  15. package/templates/default/.github/workflows/cleanup-pr-preview-on-close.yml +50 -0
  16. package/templates/default/.github/workflows/deploy-pr-preview.yml +398 -0
  17. package/templates/default/.github/workflows/deploy-stable-branches.yml +259 -0
  18. package/templates/default/.github/workflows/release-create-einja-app.yml +95 -0
  19. package/templates/default/.mcp.json +6 -9
  20. package/templates/default/CLAUDE.md +46 -9
  21. package/templates/default/README.md +5 -14
  22. package/templates/default/apps/admin/next.config.ts +11 -0
  23. package/templates/default/apps/admin/package.json +55 -0
  24. package/templates/default/apps/admin/postcss.config.cjs +5 -0
  25. package/templates/default/apps/admin/src/app/(auth)/forgot-password/page.tsx +97 -0
  26. package/templates/default/apps/admin/src/app/(auth)/layout.tsx +18 -0
  27. package/templates/default/apps/admin/src/app/(auth)/otp/page.tsx +121 -0
  28. package/templates/default/apps/admin/src/app/(auth)/sign-in/page.tsx +145 -0
  29. package/templates/default/apps/admin/src/app/(auth)/sign-up/page.tsx +199 -0
  30. package/templates/default/apps/admin/src/app/(errors)/401/page.tsx +27 -0
  31. package/templates/default/apps/admin/src/app/(errors)/403/page.tsx +28 -0
  32. package/templates/default/apps/admin/src/app/(errors)/500/page.tsx +29 -0
  33. package/templates/default/apps/admin/src/app/(errors)/layout.tsx +7 -0
  34. package/templates/default/apps/admin/src/app/(errors)/maintenance/page.tsx +25 -0
  35. package/templates/default/apps/admin/src/app/dashboard/_components/analytics-chart.tsx +68 -0
  36. package/templates/default/apps/admin/src/app/dashboard/_components/analytics.tsx +182 -0
  37. package/templates/default/apps/admin/src/app/dashboard/_components/dashboard-page.tsx +74 -0
  38. package/templates/default/apps/admin/src/app/dashboard/_components/metric-cards.tsx +49 -0
  39. package/templates/default/apps/admin/src/app/dashboard/_components/overview-chart.tsx +73 -0
  40. package/templates/default/apps/admin/src/app/dashboard/_components/recent-sales.tsx +75 -0
  41. package/templates/default/apps/admin/src/app/dashboard/apps/_components/apps-page.tsx +135 -0
  42. package/templates/default/apps/admin/src/app/dashboard/apps/page.tsx +10 -0
  43. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-list.tsx +82 -0
  44. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-messages.tsx +194 -0
  45. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chats-page.tsx +99 -0
  46. package/templates/default/apps/admin/src/app/dashboard/chats/_components/new-chat.tsx +118 -0
  47. package/templates/default/apps/admin/src/app/dashboard/chats/page.tsx +10 -0
  48. package/templates/default/apps/admin/src/app/dashboard/layout.tsx +9 -0
  49. package/templates/default/apps/admin/src/app/dashboard/not-found.tsx +14 -0
  50. package/templates/default/apps/admin/src/app/dashboard/page.tsx +10 -0
  51. package/templates/default/apps/admin/src/app/dashboard/settings/_components/content-section.tsx +20 -0
  52. package/templates/default/apps/admin/src/app/dashboard/settings/_components/sidebar-nav.tsx +66 -0
  53. package/templates/default/apps/admin/src/app/dashboard/settings/account/page.tsx +173 -0
  54. package/templates/default/apps/admin/src/app/dashboard/settings/appearance/page.tsx +156 -0
  55. package/templates/default/apps/admin/src/app/dashboard/settings/display/page.tsx +125 -0
  56. package/templates/default/apps/admin/src/app/dashboard/settings/layout.tsx +30 -0
  57. package/templates/default/apps/admin/src/app/dashboard/settings/notifications/page.tsx +196 -0
  58. package/templates/default/apps/admin/src/app/dashboard/settings/page.tsx +5 -0
  59. package/templates/default/apps/admin/src/app/dashboard/settings/profile/page.tsx +176 -0
  60. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-bulk-actions.tsx +183 -0
  61. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-row-actions.tsx +79 -0
  62. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-columns.tsx +107 -0
  63. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-dialogs.tsx +71 -0
  64. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-import-dialog.tsx +106 -0
  65. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-multi-delete-dialog.tsx +90 -0
  66. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-mutate-drawer.tsx +207 -0
  67. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-page.tsx +31 -0
  68. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-primary-buttons.tsx +19 -0
  69. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-provider.tsx +37 -0
  70. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-table.tsx +155 -0
  71. package/templates/default/apps/admin/src/app/dashboard/tasks/page.tsx +14 -0
  72. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-bulk-actions.tsx +136 -0
  73. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-row-actions.tsx +62 -0
  74. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-action-dialog.tsx +297 -0
  75. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-columns.tsx +121 -0
  76. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-delete-dialog.tsx +72 -0
  77. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-dialogs.tsx +49 -0
  78. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-invite-dialog.tsx +139 -0
  79. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-multi-delete-dialog.tsx +89 -0
  80. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-page.tsx +30 -0
  81. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-primary-buttons.tsx +19 -0
  82. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-provider.tsx +35 -0
  83. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-table.tsx +157 -0
  84. package/templates/default/apps/admin/src/app/dashboard/users/page.tsx +10 -0
  85. package/templates/default/apps/admin/src/app/globals.css +109 -0
  86. package/templates/default/apps/admin/src/app/layout.tsx +32 -0
  87. package/templates/default/apps/admin/src/app/not-found.tsx +14 -0
  88. package/templates/default/apps/admin/src/app/page.tsx +5 -0
  89. package/templates/default/apps/admin/src/components/layout/admin-layout.tsx +16 -0
  90. package/templates/default/apps/admin/src/components/layout/app-sidebar.tsx +52 -0
  91. package/templates/default/apps/admin/src/components/layout/nav-config.ts +131 -0
  92. package/templates/default/apps/admin/src/components/providers/theme-provider.tsx +10 -0
  93. package/templates/default/apps/admin/src/components/shared/long-text.tsx +78 -0
  94. package/templates/default/apps/admin/src/components/shared/search-input.tsx +16 -0
  95. package/templates/default/apps/admin/src/components/shared/select-dropdown.tsx +64 -0
  96. package/templates/default/apps/admin/src/data/apps.tsx +116 -0
  97. package/templates/default/apps/admin/src/data/chats.ts +114 -0
  98. package/templates/default/apps/admin/src/data/tasks.ts +114 -0
  99. package/templates/default/apps/admin/src/data/users.ts +90 -0
  100. package/templates/default/apps/admin/src/hooks/use-dialog-state.ts +17 -0
  101. package/templates/default/apps/admin/src/hooks/use-table-url-state.ts +243 -0
  102. package/templates/default/apps/admin/src/lib/show-submitted-data.tsx +12 -0
  103. package/templates/default/apps/admin/src/types/table.d.ts +9 -0
  104. package/templates/default/apps/admin/tsconfig.json +32 -0
  105. package/templates/default/apps/web/next.config.ts +1 -0
  106. package/templates/default/apps/web/package.json +0 -22
  107. package/templates/default/apps/web/postcss.config.cjs +0 -1
  108. package/templates/default/apps/web/src/app/(authenticated)/dashboard/page.tsx +4 -20
  109. package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTable.tsx +4 -4
  110. package/templates/default/apps/web/src/app/(authenticated)/data/page.tsx +1 -1
  111. package/templates/default/apps/web/src/app/(authenticated)/profile/page.tsx +1 -1
  112. package/templates/default/apps/web/src/app/error.tsx +8 -70
  113. package/templates/default/apps/web/src/app/global-error.tsx +8 -70
  114. package/templates/default/apps/web/src/app/globals.css +20 -0
  115. package/templates/default/apps/web/src/app/not-found.tsx +5 -39
  116. package/templates/default/apps/web/src/app/page.tsx +27 -203
  117. package/templates/default/apps/web/src/app/signin/page.tsx +27 -191
  118. package/templates/default/apps/web/src/app/signup/page.tsx +33 -240
  119. package/templates/default/apps/web/src/components/dashboard/dashboard-stats.tsx +11 -75
  120. package/templates/default/apps/web/src/components/shared/Sidebar.tsx +3 -3
  121. package/templates/default/apps/web/src/components/shared/header.tsx +17 -112
  122. package/templates/default/apps/web/tsconfig.json +0 -6
  123. package/templates/default/biome.json +1 -2
  124. package/templates/default/components.json +2 -2
  125. package/templates/default/docker-compose.yml +1 -1
  126. package/templates/default/gitignore +4 -0
  127. package/templates/default/package.json +1 -0
  128. package/templates/default/packages/admin-ui/catalog/catalog.css +54 -0
  129. package/templates/default/packages/admin-ui/catalog/catalog.tsx +401 -0
  130. package/templates/default/packages/admin-ui/catalog/index.html +12 -0
  131. package/templates/default/packages/admin-ui/catalog/main.tsx +9 -0
  132. package/templates/default/packages/admin-ui/components.json +21 -0
  133. package/templates/default/packages/admin-ui/package.json +105 -0
  134. package/templates/default/packages/admin-ui/src/command-menu/index.tsx +174 -0
  135. package/templates/default/packages/admin-ui/src/data-table/bulk-actions.tsx +215 -0
  136. package/templates/default/packages/admin-ui/src/data-table/column-header.tsx +73 -0
  137. package/templates/default/packages/admin-ui/src/data-table/data-table.tsx +127 -0
  138. package/templates/default/packages/admin-ui/src/data-table/faceted-filter.tsx +148 -0
  139. package/templates/default/packages/admin-ui/src/data-table/index.tsx +9 -0
  140. package/templates/default/packages/admin-ui/src/data-table/pagination.tsx +101 -0
  141. package/templates/default/packages/admin-ui/src/data-table/toolbar.tsx +87 -0
  142. package/templates/default/packages/admin-ui/src/data-table/view-options.tsx +57 -0
  143. package/templates/default/packages/admin-ui/src/hooks/use-mobile.tsx +23 -0
  144. package/templates/default/packages/admin-ui/src/layout/header.tsx +55 -0
  145. package/templates/default/packages/admin-ui/src/layout/index.ts +10 -0
  146. package/templates/default/packages/admin-ui/src/layout/main.tsx +23 -0
  147. package/templates/default/packages/admin-ui/src/layout/nav-group.tsx +111 -0
  148. package/templates/default/packages/admin-ui/src/layout/nav-user.tsx +114 -0
  149. package/templates/default/packages/admin-ui/src/layout/theme-switch.tsx +40 -0
  150. package/templates/default/packages/admin-ui/src/layout/types.ts +21 -0
  151. package/templates/default/packages/admin-ui/src/lib/utils.ts +6 -0
  152. package/templates/default/packages/admin-ui/src/styles/base.css +65 -0
  153. package/templates/default/packages/admin-ui/src/styles/tokens.css +91 -0
  154. package/templates/default/packages/admin-ui/src/tanstack-table.d.ts +10 -0
  155. package/templates/default/packages/admin-ui/src/ui/alert-dialog.tsx +157 -0
  156. package/templates/default/packages/admin-ui/src/ui/alert.tsx +66 -0
  157. package/templates/default/packages/admin-ui/src/ui/avatar.tsx +53 -0
  158. package/templates/default/packages/admin-ui/src/ui/badge.tsx +46 -0
  159. package/templates/default/packages/admin-ui/src/ui/breadcrumb.tsx +108 -0
  160. package/templates/default/packages/admin-ui/src/ui/button.tsx +59 -0
  161. package/templates/default/packages/admin-ui/src/ui/calendar.tsx +69 -0
  162. package/templates/default/packages/admin-ui/src/ui/card.tsx +92 -0
  163. package/templates/default/packages/admin-ui/src/ui/chart.tsx +345 -0
  164. package/templates/default/packages/admin-ui/src/ui/checkbox.tsx +32 -0
  165. package/templates/default/packages/admin-ui/src/ui/collapsible.tsx +27 -0
  166. package/templates/default/packages/admin-ui/src/ui/command.tsx +161 -0
  167. package/templates/default/packages/admin-ui/src/ui/confirm-dialog.tsx +72 -0
  168. package/templates/default/packages/admin-ui/src/ui/date-picker.tsx +53 -0
  169. package/templates/default/packages/admin-ui/src/ui/dialog.tsx +143 -0
  170. package/templates/default/packages/admin-ui/src/ui/dropdown-menu.tsx +257 -0
  171. package/templates/default/packages/admin-ui/src/ui/form.tsx +168 -0
  172. package/templates/default/packages/admin-ui/src/ui/input-otp.tsx +84 -0
  173. package/templates/default/packages/admin-ui/src/ui/input.tsx +21 -0
  174. package/templates/default/packages/admin-ui/src/ui/label.tsx +24 -0
  175. package/templates/default/packages/admin-ui/src/ui/pagination.tsx +126 -0
  176. package/templates/default/packages/admin-ui/src/ui/password-input.tsx +46 -0
  177. package/templates/default/packages/admin-ui/src/ui/popover.tsx +48 -0
  178. package/templates/default/packages/admin-ui/src/ui/progress.tsx +31 -0
  179. package/templates/default/packages/admin-ui/src/ui/radio-group.tsx +45 -0
  180. package/templates/default/packages/admin-ui/src/ui/scroll-area.tsx +52 -0
  181. package/templates/default/packages/admin-ui/src/ui/select.tsx +185 -0
  182. package/templates/default/packages/admin-ui/src/ui/separator.tsx +28 -0
  183. package/templates/default/packages/admin-ui/src/ui/sheet.tsx +149 -0
  184. package/templates/default/packages/admin-ui/src/ui/sidebar.tsx +728 -0
  185. package/templates/default/packages/admin-ui/src/ui/skeleton.tsx +13 -0
  186. package/templates/default/packages/admin-ui/src/ui/sonner.tsx +25 -0
  187. package/templates/default/packages/admin-ui/src/ui/switch.tsx +31 -0
  188. package/templates/default/packages/admin-ui/src/ui/table.tsx +116 -0
  189. package/templates/default/packages/admin-ui/src/ui/tabs.tsx +66 -0
  190. package/templates/default/packages/admin-ui/src/ui/textarea.tsx +18 -0
  191. package/templates/default/packages/admin-ui/src/ui/toggle-group.tsx +60 -0
  192. package/templates/default/packages/admin-ui/src/ui/toggle.tsx +44 -0
  193. package/templates/default/packages/admin-ui/src/ui/tooltip.tsx +61 -0
  194. package/templates/default/packages/admin-ui/tsconfig.json +8 -0
  195. package/templates/default/packages/admin-ui/vite.config.ts +11 -0
  196. package/templates/default/packages/config/package.json +0 -2
  197. package/templates/default/packages/server-core/package.json +1 -0
  198. package/templates/default/packages/ui/components.json +21 -0
  199. package/templates/default/packages/ui/package.json +42 -5
  200. package/templates/default/packages/ui/src/accordion.tsx +1 -1
  201. package/templates/default/packages/ui/src/alert-dialog.tsx +4 -4
  202. package/templates/default/packages/ui/src/alert.tsx +1 -1
  203. package/templates/default/packages/ui/src/avatar.tsx +1 -1
  204. package/templates/default/packages/ui/src/badge.tsx +1 -1
  205. package/templates/default/packages/ui/src/breadcrumb.tsx +1 -1
  206. package/templates/default/packages/ui/src/button.tsx +1 -1
  207. package/templates/default/packages/ui/src/card.tsx +1 -1
  208. package/templates/default/packages/ui/src/checkbox.tsx +1 -1
  209. package/templates/default/packages/ui/src/dialog.tsx +3 -3
  210. package/templates/default/packages/ui/src/drawer.tsx +3 -3
  211. package/templates/default/packages/ui/src/dropdown-menu.tsx +3 -3
  212. package/templates/default/packages/ui/src/form.tsx +2 -2
  213. package/templates/default/packages/ui/src/hover-card.tsx +2 -2
  214. package/templates/default/packages/ui/src/input.tsx +1 -1
  215. package/templates/default/packages/ui/src/label.tsx +1 -1
  216. package/templates/default/packages/ui/src/pagination.tsx +2 -2
  217. package/templates/default/packages/ui/src/popover.tsx +2 -2
  218. package/templates/default/packages/ui/src/progress.tsx +1 -1
  219. package/templates/default/packages/ui/src/select.tsx +2 -2
  220. package/templates/default/packages/ui/src/separator.tsx +1 -1
  221. package/templates/default/packages/ui/src/skeleton.tsx +1 -1
  222. package/templates/default/packages/ui/src/table.tsx +1 -1
  223. package/templates/default/packages/ui/src/tabs.tsx +1 -1
  224. package/templates/default/packages/ui/src/textarea.tsx +1 -1
  225. package/templates/default/packages/ui/src/tooltip.tsx +3 -3
  226. package/templates/default/packages/ui/src/typography.tsx +1 -1
  227. package/templates/default/packages/ui/tsconfig.json +1 -6
  228. package/templates/default/pnpm-lock.yaml +1319 -936
  229. package/templates/default/postcss.config.cjs +0 -1
  230. package/templates/default/turbo.json +11 -5
  231. package/templates/default/worktree.config.json +5 -0
  232. package/templates/default/.env.ci +0 -32
  233. package/templates/default/.github/workflows/ci.yml +0 -96
  234. package/templates/default/.github/workflows/preview-db.yml +0 -134
  235. package/templates/default/.playwright-mcp/dashboard.png +0 -0
  236. package/templates/default/.playwright-mcp/web-home.png +0 -0
  237. package/templates/default/apps/web/panda.config.ts +0 -114
  238. package/templates/default/apps/web/src/components/ui/accordion.tsx +0 -64
  239. package/templates/default/apps/web/src/components/ui/alert-dialog.tsx +0 -135
  240. package/templates/default/apps/web/src/components/ui/alert.tsx +0 -60
  241. package/templates/default/apps/web/src/components/ui/aspect-ratio.tsx +0 -9
  242. package/templates/default/apps/web/src/components/ui/avatar.tsx +0 -41
  243. package/templates/default/apps/web/src/components/ui/badge.tsx +0 -39
  244. package/templates/default/apps/web/src/components/ui/breadcrumb.tsx +0 -101
  245. package/templates/default/apps/web/src/components/ui/button.tsx +0 -56
  246. package/templates/default/apps/web/src/components/ui/card.tsx +0 -75
  247. package/templates/default/apps/web/src/components/ui/checkbox.tsx +0 -29
  248. package/templates/default/apps/web/src/components/ui/data-table.tsx +0 -189
  249. package/templates/default/apps/web/src/components/ui/dialog-hook.tsx +0 -210
  250. package/templates/default/apps/web/src/components/ui/dialog.tsx +0 -129
  251. package/templates/default/apps/web/src/components/ui/drawer.tsx +0 -124
  252. package/templates/default/apps/web/src/components/ui/dropdown-menu.tsx +0 -228
  253. package/templates/default/apps/web/src/components/ui/form.tsx +0 -152
  254. package/templates/default/apps/web/src/components/ui/hover-card.tsx +0 -38
  255. package/templates/default/apps/web/src/components/ui/input.tsx +0 -21
  256. package/templates/default/apps/web/src/components/ui/label.tsx +0 -21
  257. package/templates/default/apps/web/src/components/ui/pagination.tsx +0 -105
  258. package/templates/default/apps/web/src/components/ui/popover.tsx +0 -42
  259. package/templates/default/apps/web/src/components/ui/progress.tsx +0 -28
  260. package/templates/default/apps/web/src/components/ui/select.tsx +0 -170
  261. package/templates/default/apps/web/src/components/ui/separator.tsx +0 -28
  262. package/templates/default/apps/web/src/components/ui/skeleton.tsx +0 -13
  263. package/templates/default/apps/web/src/components/ui/sonner.tsx +0 -25
  264. package/templates/default/apps/web/src/components/ui/table.tsx +0 -92
  265. package/templates/default/apps/web/src/components/ui/tabs.tsx +0 -54
  266. package/templates/default/apps/web/src/components/ui/textarea.tsx +0 -18
  267. package/templates/default/apps/web/src/components/ui/tooltip.tsx +0 -57
  268. package/templates/default/apps/web/src/components/ui/typography.tsx +0 -158
  269. package/templates/default/packages/config/panda.config.ts +0 -114
  270. package/templates/default/panda.config.ts +0 -114
@@ -0,0 +1,173 @@
1
+ "use client";
2
+
3
+ import { showSubmittedData } from "@/lib/show-submitted-data";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import { cn } from "{{packageName}}/admin-ui/lib/utils";
6
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
7
+ import {
8
+ Command,
9
+ CommandEmpty,
10
+ CommandGroup,
11
+ CommandInput,
12
+ CommandItem,
13
+ CommandList,
14
+ } from "{{packageName}}/admin-ui/ui/command";
15
+ import { DatePicker } from "{{packageName}}/admin-ui/ui/date-picker";
16
+ import {
17
+ Form,
18
+ FormControl,
19
+ FormDescription,
20
+ FormField,
21
+ FormItem,
22
+ FormLabel,
23
+ FormMessage,
24
+ } from "{{packageName}}/admin-ui/ui/form";
25
+ import { Input } from "{{packageName}}/admin-ui/ui/input";
26
+ import { Popover, PopoverContent, PopoverTrigger } from "{{packageName}}/admin-ui/ui/popover";
27
+ import { Check, ChevronsUpDown } from "lucide-react";
28
+ import { useForm } from "react-hook-form";
29
+ import { z } from "zod";
30
+ import { ContentSection } from "../_components/content-section";
31
+
32
+ const languages = [
33
+ { label: "English", value: "en" },
34
+ { label: "French", value: "fr" },
35
+ { label: "German", value: "de" },
36
+ { label: "Spanish", value: "es" },
37
+ { label: "Portuguese", value: "pt" },
38
+ { label: "Russian", value: "ru" },
39
+ { label: "Japanese", value: "ja" },
40
+ { label: "Korean", value: "ko" },
41
+ { label: "Chinese", value: "zh" },
42
+ ] as const;
43
+
44
+ const accountFormSchema = z.object({
45
+ name: z
46
+ .string()
47
+ .min(2, "Name must be at least 2 characters.")
48
+ .max(30, "Name must not be longer than 30 characters."),
49
+ dob: z.date({
50
+ required_error: "Please select your date of birth.",
51
+ }),
52
+ language: z.string({
53
+ required_error: "Please select a language.",
54
+ }),
55
+ });
56
+
57
+ type AccountFormValues = z.infer<typeof accountFormSchema>;
58
+
59
+ const defaultValues: Partial<AccountFormValues> = {
60
+ name: "",
61
+ };
62
+
63
+ export default function AccountPage() {
64
+ const form = useForm<AccountFormValues>({
65
+ resolver: zodResolver(accountFormSchema),
66
+ defaultValues,
67
+ });
68
+
69
+ function onSubmit(data: AccountFormValues) {
70
+ showSubmittedData(data);
71
+ }
72
+
73
+ return (
74
+ <ContentSection
75
+ title="Account"
76
+ desc="Update your account settings. Set your preferred language and timezone."
77
+ >
78
+ <Form {...form}>
79
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
80
+ <FormField
81
+ control={form.control}
82
+ name="name"
83
+ render={({ field }) => (
84
+ <FormItem>
85
+ <FormLabel>Name</FormLabel>
86
+ <FormControl>
87
+ <Input placeholder="Your name" {...field} />
88
+ </FormControl>
89
+ <FormDescription>
90
+ This is the name that will be displayed on your profile and in emails.
91
+ </FormDescription>
92
+ <FormMessage />
93
+ </FormItem>
94
+ )}
95
+ />
96
+ <FormField
97
+ control={form.control}
98
+ name="dob"
99
+ render={({ field }) => (
100
+ <FormItem className="flex flex-col">
101
+ <FormLabel>Date of birth</FormLabel>
102
+ <DatePicker date={field.value} onDateChange={field.onChange} />
103
+ <FormDescription>Your date of birth is used to calculate your age.</FormDescription>
104
+ <FormMessage />
105
+ </FormItem>
106
+ )}
107
+ />
108
+ <FormField
109
+ control={form.control}
110
+ name="language"
111
+ render={({ field }) => (
112
+ <FormItem className="flex flex-col">
113
+ <FormLabel>Language</FormLabel>
114
+ <Popover>
115
+ <PopoverTrigger asChild>
116
+ <FormControl>
117
+ <Button
118
+ variant="outline"
119
+ // biome-ignore lint/a11y/useSemanticElements: shadcn/ui Combobox pattern
120
+ role="combobox"
121
+ className={cn(
122
+ "w-[200px] justify-between",
123
+ !field.value && "text-muted-foreground"
124
+ )}
125
+ >
126
+ {field.value
127
+ ? languages.find((language) => language.value === field.value)?.label
128
+ : "Select language"}
129
+ <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
130
+ </Button>
131
+ </FormControl>
132
+ </PopoverTrigger>
133
+ <PopoverContent className="w-[200px] p-0">
134
+ <Command>
135
+ <CommandInput placeholder="Search language..." />
136
+ <CommandEmpty>No language found.</CommandEmpty>
137
+ <CommandGroup>
138
+ <CommandList>
139
+ {languages.map((language) => (
140
+ <CommandItem
141
+ value={language.label}
142
+ key={language.value}
143
+ onSelect={() => {
144
+ form.setValue("language", language.value);
145
+ }}
146
+ >
147
+ <Check
148
+ className={cn(
149
+ "mr-2 size-4",
150
+ language.value === field.value ? "opacity-100" : "opacity-0"
151
+ )}
152
+ />
153
+ {language.label}
154
+ </CommandItem>
155
+ ))}
156
+ </CommandList>
157
+ </CommandGroup>
158
+ </Command>
159
+ </PopoverContent>
160
+ </Popover>
161
+ <FormDescription>
162
+ This is the language that will be used in the dashboard.
163
+ </FormDescription>
164
+ <FormMessage />
165
+ </FormItem>
166
+ )}
167
+ />
168
+ <Button type="submit">Update account</Button>
169
+ </form>
170
+ </Form>
171
+ </ContentSection>
172
+ );
173
+ }
@@ -0,0 +1,156 @@
1
+ "use client";
2
+
3
+ import { showSubmittedData } from "@/lib/show-submitted-data";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import { cn } from "{{packageName}}/admin-ui/lib/utils";
6
+ import { Button, buttonVariants } from "{{packageName}}/admin-ui/ui/button";
7
+ import {
8
+ Form,
9
+ FormControl,
10
+ FormDescription,
11
+ FormField,
12
+ FormItem,
13
+ FormLabel,
14
+ FormMessage,
15
+ } from "{{packageName}}/admin-ui/ui/form";
16
+ import { RadioGroup, RadioGroupItem } from "{{packageName}}/admin-ui/ui/radio-group";
17
+ import { ChevronDown } from "lucide-react";
18
+ import { useForm } from "react-hook-form";
19
+ import { z } from "zod";
20
+ import { ContentSection } from "../_components/content-section";
21
+
22
+ const fonts = ["inter", "manrope", "system"] as const;
23
+
24
+ const appearanceFormSchema = z.object({
25
+ theme: z.enum(["light", "dark"], {
26
+ required_error: "Please select a theme.",
27
+ }),
28
+ font: z.enum(fonts, {
29
+ required_error: "Please select a font.",
30
+ }),
31
+ });
32
+
33
+ type AppearanceFormValues = z.infer<typeof appearanceFormSchema>;
34
+
35
+ const defaultValues: Partial<AppearanceFormValues> = {
36
+ theme: "light",
37
+ font: "inter",
38
+ };
39
+
40
+ export default function AppearancePage() {
41
+ const form = useForm<AppearanceFormValues>({
42
+ resolver: zodResolver(appearanceFormSchema),
43
+ defaultValues,
44
+ });
45
+
46
+ function onSubmit(data: AppearanceFormValues) {
47
+ showSubmittedData(data);
48
+ }
49
+
50
+ return (
51
+ <ContentSection
52
+ title="Appearance"
53
+ desc="Customize the appearance of the app. Automatically switch between day and night themes."
54
+ >
55
+ <Form {...form}>
56
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
57
+ <FormField
58
+ control={form.control}
59
+ name="font"
60
+ render={({ field }) => (
61
+ <FormItem>
62
+ <FormLabel>Font</FormLabel>
63
+ <div className="relative w-max">
64
+ <FormControl>
65
+ <select
66
+ className={cn(
67
+ buttonVariants({ variant: "outline" }),
68
+ "w-[200px] appearance-none font-normal capitalize"
69
+ )}
70
+ {...field}
71
+ >
72
+ {fonts.map((font) => (
73
+ <option key={font} value={font}>
74
+ {font}
75
+ </option>
76
+ ))}
77
+ </select>
78
+ </FormControl>
79
+ <ChevronDown className="pointer-events-none absolute right-3 top-2.5 size-4 opacity-50" />
80
+ </div>
81
+ <FormDescription>Set the font you want to use in the dashboard.</FormDescription>
82
+ <FormMessage />
83
+ </FormItem>
84
+ )}
85
+ />
86
+ <FormField
87
+ control={form.control}
88
+ name="theme"
89
+ render={({ field }) => (
90
+ <FormItem className="space-y-1">
91
+ <FormLabel>Theme</FormLabel>
92
+ <FormDescription>Select the theme for the dashboard.</FormDescription>
93
+ <FormMessage />
94
+ <RadioGroup
95
+ onValueChange={field.onChange}
96
+ defaultValue={field.value}
97
+ className="grid max-w-md grid-cols-2 gap-8 pt-2"
98
+ >
99
+ <FormItem>
100
+ <FormLabel className="[&:has([data-state=checked])>div]:border-primary">
101
+ <FormControl>
102
+ <RadioGroupItem value="light" className="sr-only" />
103
+ </FormControl>
104
+ <div className="items-center rounded-md border-2 border-muted p-1 hover:border-accent">
105
+ <div className="space-y-2 rounded-sm bg-[#ecedef] p-2">
106
+ <div className="space-y-2 rounded-md bg-white p-2 shadow-sm">
107
+ <div className="h-2 w-[80px] rounded-lg bg-[#ecedef]" />
108
+ <div className="h-2 w-[100px] rounded-lg bg-[#ecedef]" />
109
+ </div>
110
+ <div className="flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm">
111
+ <div className="size-4 rounded-full bg-[#ecedef]" />
112
+ <div className="h-2 w-[100px] rounded-lg bg-[#ecedef]" />
113
+ </div>
114
+ <div className="flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm">
115
+ <div className="size-4 rounded-full bg-[#ecedef]" />
116
+ <div className="h-2 w-[100px] rounded-lg bg-[#ecedef]" />
117
+ </div>
118
+ </div>
119
+ </div>
120
+ <span className="block w-full p-2 text-center font-normal">Light</span>
121
+ </FormLabel>
122
+ </FormItem>
123
+ <FormItem>
124
+ <FormLabel className="[&:has([data-state=checked])>div]:border-primary">
125
+ <FormControl>
126
+ <RadioGroupItem value="dark" className="sr-only" />
127
+ </FormControl>
128
+ <div className="items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground">
129
+ <div className="space-y-2 rounded-sm bg-slate-950 p-2">
130
+ <div className="space-y-2 rounded-md bg-slate-800 p-2 shadow-sm">
131
+ <div className="h-2 w-[80px] rounded-lg bg-slate-400" />
132
+ <div className="h-2 w-[100px] rounded-lg bg-slate-400" />
133
+ </div>
134
+ <div className="flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm">
135
+ <div className="size-4 rounded-full bg-slate-400" />
136
+ <div className="h-2 w-[100px] rounded-lg bg-slate-400" />
137
+ </div>
138
+ <div className="flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm">
139
+ <div className="size-4 rounded-full bg-slate-400" />
140
+ <div className="h-2 w-[100px] rounded-lg bg-slate-400" />
141
+ </div>
142
+ </div>
143
+ </div>
144
+ <span className="block w-full p-2 text-center font-normal">Dark</span>
145
+ </FormLabel>
146
+ </FormItem>
147
+ </RadioGroup>
148
+ </FormItem>
149
+ )}
150
+ />
151
+ <Button type="submit">Update preferences</Button>
152
+ </form>
153
+ </Form>
154
+ </ContentSection>
155
+ );
156
+ }
@@ -0,0 +1,125 @@
1
+ "use client";
2
+
3
+ import { showSubmittedData } from "@/lib/show-submitted-data";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
6
+ import { Checkbox } from "{{packageName}}/admin-ui/ui/checkbox";
7
+ import {
8
+ Form,
9
+ FormControl,
10
+ FormDescription,
11
+ FormField,
12
+ FormItem,
13
+ FormLabel,
14
+ FormMessage,
15
+ } from "{{packageName}}/admin-ui/ui/form";
16
+ import { useForm } from "react-hook-form";
17
+ import { z } from "zod";
18
+ import { ContentSection } from "../_components/content-section";
19
+
20
+ const items = [
21
+ {
22
+ id: "recents",
23
+ label: "Recents",
24
+ },
25
+ {
26
+ id: "home",
27
+ label: "Home",
28
+ },
29
+ {
30
+ id: "applications",
31
+ label: "Applications",
32
+ },
33
+ {
34
+ id: "desktop",
35
+ label: "Desktop",
36
+ },
37
+ {
38
+ id: "downloads",
39
+ label: "Downloads",
40
+ },
41
+ {
42
+ id: "documents",
43
+ label: "Documents",
44
+ },
45
+ ] as const;
46
+
47
+ const displayFormSchema = z.object({
48
+ items: z.array(z.string()).refine((value) => value.some((item) => item), {
49
+ message: "You have to select at least one item.",
50
+ }),
51
+ });
52
+
53
+ type DisplayFormValues = z.infer<typeof displayFormSchema>;
54
+
55
+ const defaultValues: Partial<DisplayFormValues> = {
56
+ items: ["recents", "home"],
57
+ };
58
+
59
+ export default function DisplayPage() {
60
+ const form = useForm<DisplayFormValues>({
61
+ resolver: zodResolver(displayFormSchema),
62
+ defaultValues,
63
+ });
64
+
65
+ function onSubmit(data: DisplayFormValues) {
66
+ showSubmittedData(data);
67
+ }
68
+
69
+ return (
70
+ <ContentSection
71
+ title="Display"
72
+ desc="Turn items on or off to control what's displayed in the app."
73
+ >
74
+ <Form {...form}>
75
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
76
+ <FormField
77
+ control={form.control}
78
+ name="items"
79
+ render={() => (
80
+ <FormItem>
81
+ <div className="mb-4">
82
+ <FormLabel className="text-base">Sidebar</FormLabel>
83
+ <FormDescription>
84
+ Select the items you want to display in the sidebar.
85
+ </FormDescription>
86
+ </div>
87
+ {items.map((item) => (
88
+ <FormField
89
+ key={item.id}
90
+ control={form.control}
91
+ name="items"
92
+ render={({ field }) => {
93
+ return (
94
+ <FormItem
95
+ key={item.id}
96
+ className="flex flex-row items-start space-x-3 space-y-0"
97
+ >
98
+ <FormControl>
99
+ <Checkbox
100
+ checked={field.value?.includes(item.id)}
101
+ onCheckedChange={(checked) => {
102
+ return checked
103
+ ? field.onChange([...field.value, item.id])
104
+ : field.onChange(
105
+ field.value?.filter((value) => value !== item.id)
106
+ );
107
+ }}
108
+ />
109
+ </FormControl>
110
+ <FormLabel className="font-normal">{item.label}</FormLabel>
111
+ </FormItem>
112
+ );
113
+ }}
114
+ />
115
+ ))}
116
+ <FormMessage />
117
+ </FormItem>
118
+ )}
119
+ />
120
+ <Button type="submit">Update display</Button>
121
+ </form>
122
+ </Form>
123
+ </ContentSection>
124
+ );
125
+ }
@@ -0,0 +1,30 @@
1
+ import { Header, Main } from "{{packageName}}/admin-ui/layout";
2
+ import { Separator } from "{{packageName}}/admin-ui/ui/separator";
3
+ import { SidebarNav } from "./_components/sidebar-nav";
4
+
5
+ export default function SettingsLayout({
6
+ children,
7
+ }: {
8
+ children: React.ReactNode;
9
+ }) {
10
+ return (
11
+ <>
12
+ <Header />
13
+ <Main fixed>
14
+ <div className="space-y-0.5">
15
+ <h1 className="text-2xl font-bold tracking-tight md:text-3xl">Settings</h1>
16
+ <p className="text-muted-foreground">
17
+ Manage your account settings and set e-mail preferences.
18
+ </p>
19
+ </div>
20
+ <Separator className="my-4 lg:my-6" />
21
+ <div className="flex flex-1 flex-col space-y-2 overflow-hidden md:space-y-2 lg:flex-row lg:space-y-0 lg:space-x-12">
22
+ <aside className="top-0 lg:sticky lg:w-1/5">
23
+ <SidebarNav />
24
+ </aside>
25
+ <div className="flex w-full overflow-y-hidden p-1 pr-4">{children}</div>
26
+ </div>
27
+ </Main>
28
+ </>
29
+ );
30
+ }
@@ -0,0 +1,196 @@
1
+ "use client";
2
+
3
+ import { showSubmittedData } from "@/lib/show-submitted-data";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import { Button } from "{{packageName}}/admin-ui/ui/button";
6
+ import { Checkbox } from "{{packageName}}/admin-ui/ui/checkbox";
7
+ import {
8
+ Form,
9
+ FormControl,
10
+ FormDescription,
11
+ FormField,
12
+ FormItem,
13
+ FormLabel,
14
+ FormMessage,
15
+ } from "{{packageName}}/admin-ui/ui/form";
16
+ import { RadioGroup, RadioGroupItem } from "{{packageName}}/admin-ui/ui/radio-group";
17
+ import { Switch } from "{{packageName}}/admin-ui/ui/switch";
18
+ import Link from "next/link";
19
+ import { useForm } from "react-hook-form";
20
+ import { z } from "zod";
21
+ import { ContentSection } from "../_components/content-section";
22
+
23
+ const notificationsFormSchema = z.object({
24
+ type: z.enum(["all", "mentions", "none"], {
25
+ required_error: "Please select a notification type.",
26
+ }),
27
+ mobile: z.boolean().default(false).optional(),
28
+ communication_emails: z.boolean().default(false).optional(),
29
+ social_emails: z.boolean().default(false).optional(),
30
+ marketing_emails: z.boolean().default(false).optional(),
31
+ security_emails: z.boolean(),
32
+ });
33
+
34
+ type NotificationsFormValues = z.infer<typeof notificationsFormSchema>;
35
+
36
+ const defaultValues: Partial<NotificationsFormValues> = {
37
+ type: "all",
38
+ communication_emails: false,
39
+ marketing_emails: false,
40
+ social_emails: true,
41
+ security_emails: true,
42
+ };
43
+
44
+ export default function NotificationsPage() {
45
+ const form = useForm<NotificationsFormValues>({
46
+ resolver: zodResolver(notificationsFormSchema),
47
+ defaultValues,
48
+ });
49
+
50
+ function onSubmit(data: NotificationsFormValues) {
51
+ showSubmittedData(data);
52
+ }
53
+
54
+ return (
55
+ <ContentSection title="Notifications" desc="Configure how you receive notifications.">
56
+ <Form {...form}>
57
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
58
+ <FormField
59
+ control={form.control}
60
+ name="type"
61
+ render={({ field }) => (
62
+ <FormItem className="space-y-3">
63
+ <FormLabel>Notify me about...</FormLabel>
64
+ <FormControl>
65
+ <RadioGroup
66
+ onValueChange={field.onChange}
67
+ defaultValue={field.value}
68
+ className="flex flex-col space-y-1"
69
+ >
70
+ <FormItem className="flex items-center space-x-3 space-y-0">
71
+ <FormControl>
72
+ <RadioGroupItem value="all" />
73
+ </FormControl>
74
+ <FormLabel className="font-normal">All new messages</FormLabel>
75
+ </FormItem>
76
+ <FormItem className="flex items-center space-x-3 space-y-0">
77
+ <FormControl>
78
+ <RadioGroupItem value="mentions" />
79
+ </FormControl>
80
+ <FormLabel className="font-normal">Direct messages and mentions</FormLabel>
81
+ </FormItem>
82
+ <FormItem className="flex items-center space-x-3 space-y-0">
83
+ <FormControl>
84
+ <RadioGroupItem value="none" />
85
+ </FormControl>
86
+ <FormLabel className="font-normal">Nothing</FormLabel>
87
+ </FormItem>
88
+ </RadioGroup>
89
+ </FormControl>
90
+ <FormMessage />
91
+ </FormItem>
92
+ )}
93
+ />
94
+ <div>
95
+ <h3 className="mb-4 text-lg font-medium">Email Notifications</h3>
96
+ <div className="space-y-4">
97
+ <FormField
98
+ control={form.control}
99
+ name="communication_emails"
100
+ render={({ field }) => (
101
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
102
+ <div className="space-y-0.5">
103
+ <FormLabel className="text-base">Communication emails</FormLabel>
104
+ <FormDescription>Receive emails about your account activity.</FormDescription>
105
+ </div>
106
+ <FormControl>
107
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
108
+ </FormControl>
109
+ </FormItem>
110
+ )}
111
+ />
112
+ <FormField
113
+ control={form.control}
114
+ name="marketing_emails"
115
+ render={({ field }) => (
116
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
117
+ <div className="space-y-0.5">
118
+ <FormLabel className="text-base">Marketing emails</FormLabel>
119
+ <FormDescription>
120
+ Receive emails about new products, features, and more.
121
+ </FormDescription>
122
+ </div>
123
+ <FormControl>
124
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
125
+ </FormControl>
126
+ </FormItem>
127
+ )}
128
+ />
129
+ <FormField
130
+ control={form.control}
131
+ name="social_emails"
132
+ render={({ field }) => (
133
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
134
+ <div className="space-y-0.5">
135
+ <FormLabel className="text-base">Social emails</FormLabel>
136
+ <FormDescription>
137
+ Receive emails for friend requests, follows, and more.
138
+ </FormDescription>
139
+ </div>
140
+ <FormControl>
141
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
142
+ </FormControl>
143
+ </FormItem>
144
+ )}
145
+ />
146
+ <FormField
147
+ control={form.control}
148
+ name="security_emails"
149
+ render={({ field }) => (
150
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
151
+ <div className="space-y-0.5">
152
+ <FormLabel className="text-base">Security emails</FormLabel>
153
+ <FormDescription>
154
+ Receive emails about your account activity and security.
155
+ </FormDescription>
156
+ </div>
157
+ <FormControl>
158
+ <Switch
159
+ checked={field.value}
160
+ onCheckedChange={field.onChange}
161
+ disabled
162
+ aria-readonly
163
+ />
164
+ </FormControl>
165
+ </FormItem>
166
+ )}
167
+ />
168
+ </div>
169
+ </div>
170
+ <FormField
171
+ control={form.control}
172
+ name="mobile"
173
+ render={({ field }) => (
174
+ <FormItem className="flex flex-row items-start space-x-3 space-y-0">
175
+ <FormControl>
176
+ <Checkbox checked={field.value} onCheckedChange={field.onChange} />
177
+ </FormControl>
178
+ <div className="space-y-1 leading-none">
179
+ <FormLabel>Use different settings for my mobile devices</FormLabel>
180
+ <FormDescription>
181
+ You can manage your mobile notifications in the{" "}
182
+ <Link href="/dashboard/settings" className="underline">
183
+ mobile settings
184
+ </Link>{" "}
185
+ page.
186
+ </FormDescription>
187
+ </div>
188
+ </FormItem>
189
+ )}
190
+ />
191
+ <Button type="submit">Update notifications</Button>
192
+ </form>
193
+ </Form>
194
+ </ContentSection>
195
+ );
196
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from "next/navigation";
2
+
3
+ export default function SettingsPage() {
4
+ redirect("/dashboard/settings/profile");
5
+ }