@nextsparkjs/theme-default 0.1.0-beta.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 (333) hide show
  1. package/about/business.md +49 -0
  2. package/about/features.json +302 -0
  3. package/about/team.md +79 -0
  4. package/api/ai/chat/stream/route.ts +212 -0
  5. package/api/ai/orchestrator/route.ts +226 -0
  6. package/api/ai/single-agent/route.ts +291 -0
  7. package/api/ai/usage/route.ts +122 -0
  8. package/blocks/benefits/component.tsx +100 -0
  9. package/blocks/benefits/config.ts +11 -0
  10. package/blocks/benefits/examples.ts +85 -0
  11. package/blocks/benefits/fields.ts +156 -0
  12. package/blocks/benefits/schema.ts +33 -0
  13. package/blocks/cta-section/component.tsx +100 -0
  14. package/blocks/cta-section/config.ts +11 -0
  15. package/blocks/cta-section/examples.ts +41 -0
  16. package/blocks/cta-section/fields.ts +89 -0
  17. package/blocks/cta-section/index.ts +6 -0
  18. package/blocks/cta-section/schema.ts +32 -0
  19. package/blocks/cta-section/thumbnail.png +1 -0
  20. package/blocks/faq-accordion/component.tsx +156 -0
  21. package/blocks/faq-accordion/config.ts +11 -0
  22. package/blocks/faq-accordion/examples.ts +77 -0
  23. package/blocks/faq-accordion/fields.ts +119 -0
  24. package/blocks/faq-accordion/index.ts +6 -0
  25. package/blocks/faq-accordion/schema.ts +45 -0
  26. package/blocks/features-grid/component.tsx +112 -0
  27. package/blocks/features-grid/config.ts +11 -0
  28. package/blocks/features-grid/examples.ts +63 -0
  29. package/blocks/features-grid/fields.ts +97 -0
  30. package/blocks/features-grid/index.ts +6 -0
  31. package/blocks/features-grid/schema.ts +40 -0
  32. package/blocks/features-grid/thumbnail.png +1 -0
  33. package/blocks/hero/component.tsx +100 -0
  34. package/blocks/hero/config.ts +11 -0
  35. package/blocks/hero/examples.ts +35 -0
  36. package/blocks/hero/fields.ts +60 -0
  37. package/blocks/hero/index.ts +6 -0
  38. package/blocks/hero/schema.ts +32 -0
  39. package/blocks/hero/thumbnail.png +1 -0
  40. package/blocks/hero/thumbnail.png.txt +6 -0
  41. package/blocks/hero-with-form/component.tsx +232 -0
  42. package/blocks/hero-with-form/config.ts +11 -0
  43. package/blocks/hero-with-form/examples.ts +16 -0
  44. package/blocks/hero-with-form/fields.ts +207 -0
  45. package/blocks/hero-with-form/index.ts +6 -0
  46. package/blocks/hero-with-form/schema.ts +54 -0
  47. package/blocks/jumbotron/component.tsx +136 -0
  48. package/blocks/jumbotron/config.ts +11 -0
  49. package/blocks/jumbotron/examples.ts +36 -0
  50. package/blocks/jumbotron/fields.ts +202 -0
  51. package/blocks/jumbotron/index.ts +6 -0
  52. package/blocks/jumbotron/schema.ts +55 -0
  53. package/blocks/logo-cloud/component.tsx +154 -0
  54. package/blocks/logo-cloud/config.ts +11 -0
  55. package/blocks/logo-cloud/examples.ts +34 -0
  56. package/blocks/logo-cloud/fields.ts +133 -0
  57. package/blocks/logo-cloud/index.ts +6 -0
  58. package/blocks/logo-cloud/schema.ts +46 -0
  59. package/blocks/post-content/component.tsx +197 -0
  60. package/blocks/post-content/config.ts +11 -0
  61. package/blocks/post-content/examples.ts +33 -0
  62. package/blocks/post-content/fields.ts +165 -0
  63. package/blocks/post-content/index.ts +4 -0
  64. package/blocks/post-content/schema.ts +46 -0
  65. package/blocks/pricing-table/component.tsx +154 -0
  66. package/blocks/pricing-table/config.ts +11 -0
  67. package/blocks/pricing-table/examples.ts +96 -0
  68. package/blocks/pricing-table/fields.ts +161 -0
  69. package/blocks/pricing-table/index.ts +4 -0
  70. package/blocks/pricing-table/schema.ts +50 -0
  71. package/blocks/split-content/component.tsx +135 -0
  72. package/blocks/split-content/config.ts +11 -0
  73. package/blocks/split-content/examples.ts +38 -0
  74. package/blocks/split-content/fields.ts +198 -0
  75. package/blocks/split-content/index.ts +6 -0
  76. package/blocks/split-content/schema.ts +67 -0
  77. package/blocks/stats-counter/component.tsx +124 -0
  78. package/blocks/stats-counter/config.ts +11 -0
  79. package/blocks/stats-counter/examples.ts +61 -0
  80. package/blocks/stats-counter/fields.ts +134 -0
  81. package/blocks/stats-counter/index.ts +6 -0
  82. package/blocks/stats-counter/schema.ts +47 -0
  83. package/blocks/testimonials/component.tsx +114 -0
  84. package/blocks/testimonials/config.ts +11 -0
  85. package/blocks/testimonials/examples.ts +65 -0
  86. package/blocks/testimonials/fields.ts +105 -0
  87. package/blocks/testimonials/index.ts +6 -0
  88. package/blocks/testimonials/schema.ts +41 -0
  89. package/blocks/testimonials/thumbnail.png +1 -0
  90. package/blocks/text-content/component.tsx +97 -0
  91. package/blocks/text-content/config.ts +11 -0
  92. package/blocks/text-content/examples.ts +30 -0
  93. package/blocks/text-content/fields.ts +88 -0
  94. package/blocks/text-content/index.ts +6 -0
  95. package/blocks/text-content/schema.ts +30 -0
  96. package/blocks/text-content/thumbnail.png +1 -0
  97. package/blocks/timeline/component.tsx +267 -0
  98. package/blocks/timeline/config.ts +11 -0
  99. package/blocks/timeline/examples.ts +68 -0
  100. package/blocks/timeline/fields.ts +147 -0
  101. package/blocks/timeline/index.ts +6 -0
  102. package/blocks/timeline/schema.ts +49 -0
  103. package/blocks/video-hero/component.tsx +270 -0
  104. package/blocks/video-hero/config.ts +11 -0
  105. package/blocks/video-hero/examples.ts +24 -0
  106. package/blocks/video-hero/fields.ts +98 -0
  107. package/blocks/video-hero/index.ts +6 -0
  108. package/blocks/video-hero/schema.ts +39 -0
  109. package/components/ai-chat/ChatPanel.tsx +575 -0
  110. package/components/ai-chat/ConversationItem.tsx +266 -0
  111. package/components/ai-chat/ConversationSidebar.tsx +99 -0
  112. package/components/ai-chat/MarkdownRenderer.tsx +15 -0
  113. package/components/ai-chat/Message.tsx +42 -0
  114. package/components/ai-chat/MessageInput.tsx +49 -0
  115. package/components/ai-chat/MessageList.tsx +46 -0
  116. package/components/ai-chat/TypingIndicator.tsx +11 -0
  117. package/config/app.config.ts +367 -0
  118. package/config/billing.config.ts +349 -0
  119. package/config/dashboard.config.ts +506 -0
  120. package/config/dev.config.ts +104 -0
  121. package/config/features.config.ts +203 -0
  122. package/config/flows.config.ts +129 -0
  123. package/config/permissions.config.ts +245 -0
  124. package/config/theme.config.ts +74 -0
  125. package/docs/01-overview/01-introduction.md +335 -0
  126. package/docs/01-overview/02-customization.md +671 -0
  127. package/docs/02-features/01-components.md +155 -0
  128. package/docs/02-features/02-styling.md +139 -0
  129. package/docs/02-features/03-tasks-entity.md +407 -0
  130. package/docs/03-ai/01-overview.md +211 -0
  131. package/docs/03-ai/02-customization.md +436 -0
  132. package/entities/customers/customers.config.ts +75 -0
  133. package/entities/customers/customers.fields.ts +165 -0
  134. package/entities/customers/customers.service.ts +516 -0
  135. package/entities/customers/customers.types.ts +83 -0
  136. package/entities/customers/messages/en.json +66 -0
  137. package/entities/customers/messages/es.json +66 -0
  138. package/entities/customers/migrations/001_customers_table.sql +102 -0
  139. package/entities/customers/migrations/002_customers_metas.sql +92 -0
  140. package/entities/pages/messages/en.json +41 -0
  141. package/entities/pages/messages/es.json +41 -0
  142. package/entities/pages/migrations/001_pages_table.sql +112 -0
  143. package/entities/pages/migrations/002_pages_metas.sql +56 -0
  144. package/entities/pages/migrations/003_add_status.sql +50 -0
  145. package/entities/pages/pages-management.service.ts +610 -0
  146. package/entities/pages/pages.config.ts +94 -0
  147. package/entities/pages/pages.fields.ts +101 -0
  148. package/entities/pages/pages.service.ts +290 -0
  149. package/entities/pages/pages.types.ts +124 -0
  150. package/entities/posts/components/post-header.tsx +97 -0
  151. package/entities/posts/messages/en.json +55 -0
  152. package/entities/posts/messages/es.json +55 -0
  153. package/entities/posts/migrations/001_posts_table.sql +115 -0
  154. package/entities/posts/migrations/003_add_status.sql +44 -0
  155. package/entities/posts/migrations/004_entity_taxonomy_relations.sql +129 -0
  156. package/entities/posts/migrations/006_posts_metas.sql +56 -0
  157. package/entities/posts/posts.config.ts +101 -0
  158. package/entities/posts/posts.fields.ts +116 -0
  159. package/entities/posts/posts.service.ts +376 -0
  160. package/entities/posts/posts.types.ts +74 -0
  161. package/entities/tasks/messages/en.json +204 -0
  162. package/entities/tasks/messages/es.json +204 -0
  163. package/entities/tasks/migrations/001_tasks_table.sql +105 -0
  164. package/entities/tasks/migrations/002_task_metas.sql +85 -0
  165. package/entities/tasks/migrations/sample_data.json +77 -0
  166. package/entities/tasks/tasks.config.ts +79 -0
  167. package/entities/tasks/tasks.fields.ts +196 -0
  168. package/entities/tasks/tasks.service.ts +541 -0
  169. package/entities/tasks/tasks.types.ts +56 -0
  170. package/lib/hooks/useAiChat.ts +114 -0
  171. package/lib/hooks/useConversations.ts +376 -0
  172. package/lib/hooks/useOrchestratorChat.ts +122 -0
  173. package/lib/hooks/usePersistentChat.ts +315 -0
  174. package/lib/hooks/useStreamingChat.ts +127 -0
  175. package/lib/hooks/useTokenUsage.ts +63 -0
  176. package/lib/langchain/agents/customer-assistant.md +69 -0
  177. package/lib/langchain/agents/index.ts +61 -0
  178. package/lib/langchain/agents/orchestrator.md +59 -0
  179. package/lib/langchain/agents/page-assistant.md +85 -0
  180. package/lib/langchain/agents/single-agent.md +46 -0
  181. package/lib/langchain/agents/task-assistant.md +55 -0
  182. package/lib/langchain/config.ts +45 -0
  183. package/lib/langchain/handlers/customer-handler.ts +338 -0
  184. package/lib/langchain/handlers/page-handler.ts +232 -0
  185. package/lib/langchain/handlers/task-handler.ts +323 -0
  186. package/lib/langchain/langchain.config.ts +223 -0
  187. package/lib/langchain/observability.config.ts +30 -0
  188. package/lib/langchain/orchestrator.ts +562 -0
  189. package/lib/langchain/tools/customers.ts +176 -0
  190. package/lib/langchain/tools/index.ts +10 -0
  191. package/lib/langchain/tools/orchestrator.ts +92 -0
  192. package/lib/langchain/tools/pages.ts +289 -0
  193. package/lib/langchain/tools/tasks.ts +167 -0
  194. package/lib/scheduled-actions/billing.ts +149 -0
  195. package/lib/scheduled-actions/index.ts +170 -0
  196. package/lib/scheduled-actions/webhook.ts +231 -0
  197. package/lib/selectors.ts +197 -0
  198. package/messages/de/admin.json +219 -0
  199. package/messages/de/aiUsage.json +36 -0
  200. package/messages/de/buttons.json +19 -0
  201. package/messages/de/categories.json +35 -0
  202. package/messages/de/common.json +16 -0
  203. package/messages/de/dev.json +101 -0
  204. package/messages/de/docs.json +27 -0
  205. package/messages/de/entities.json +7 -0
  206. package/messages/de/features.json +119 -0
  207. package/messages/de/footer.json +22 -0
  208. package/messages/de/home.json +57 -0
  209. package/messages/de/index.ts +39 -0
  210. package/messages/de/mobileNav.json +13 -0
  211. package/messages/de/navigation.json +8 -0
  212. package/messages/de/observability.json +74 -0
  213. package/messages/de/posts.json +54 -0
  214. package/messages/de/pricing.json +102 -0
  215. package/messages/de/support.json +9 -0
  216. package/messages/de/teams.json +8 -0
  217. package/messages/en/admin.json +219 -0
  218. package/messages/en/aiUsage.json +36 -0
  219. package/messages/en/buttons.json +19 -0
  220. package/messages/en/categories.json +35 -0
  221. package/messages/en/common.json +16 -0
  222. package/messages/en/dev.json +106 -0
  223. package/messages/en/docs.json +27 -0
  224. package/messages/en/entities.json +7 -0
  225. package/messages/en/features.json +119 -0
  226. package/messages/en/footer.json +22 -0
  227. package/messages/en/home.json +57 -0
  228. package/messages/en/index.ts +39 -0
  229. package/messages/en/mobileNav.json +13 -0
  230. package/messages/en/navigation.json +8 -0
  231. package/messages/en/observability.json +74 -0
  232. package/messages/en/posts.json +54 -0
  233. package/messages/en/pricing.json +102 -0
  234. package/messages/en/support.json +9 -0
  235. package/messages/en/teams.json +8 -0
  236. package/messages/es/admin.json +219 -0
  237. package/messages/es/aiUsage.json +36 -0
  238. package/messages/es/buttons.json +19 -0
  239. package/messages/es/categories.json +35 -0
  240. package/messages/es/common.json +16 -0
  241. package/messages/es/dev.json +101 -0
  242. package/messages/es/docs.json +27 -0
  243. package/messages/es/entities.json +7 -0
  244. package/messages/es/features.json +119 -0
  245. package/messages/es/footer.json +22 -0
  246. package/messages/es/home.json +57 -0
  247. package/messages/es/index.ts +39 -0
  248. package/messages/es/mobileNav.json +13 -0
  249. package/messages/es/navigation.json +8 -0
  250. package/messages/es/observability.json +74 -0
  251. package/messages/es/posts.json +54 -0
  252. package/messages/es/pricing.json +102 -0
  253. package/messages/es/support.json +9 -0
  254. package/messages/es/teams.json +8 -0
  255. package/messages/fr/admin.json +219 -0
  256. package/messages/fr/aiUsage.json +36 -0
  257. package/messages/fr/buttons.json +19 -0
  258. package/messages/fr/categories.json +35 -0
  259. package/messages/fr/common.json +16 -0
  260. package/messages/fr/dev.json +101 -0
  261. package/messages/fr/docs.json +27 -0
  262. package/messages/fr/entities.json +7 -0
  263. package/messages/fr/features.json +119 -0
  264. package/messages/fr/footer.json +22 -0
  265. package/messages/fr/home.json +57 -0
  266. package/messages/fr/index.ts +39 -0
  267. package/messages/fr/mobileNav.json +13 -0
  268. package/messages/fr/navigation.json +8 -0
  269. package/messages/fr/observability.json +74 -0
  270. package/messages/fr/posts.json +54 -0
  271. package/messages/fr/pricing.json +102 -0
  272. package/messages/fr/support.json +9 -0
  273. package/messages/fr/teams.json +8 -0
  274. package/messages/it/admin.json +219 -0
  275. package/messages/it/aiUsage.json +36 -0
  276. package/messages/it/buttons.json +19 -0
  277. package/messages/it/categories.json +35 -0
  278. package/messages/it/common.json +16 -0
  279. package/messages/it/dev.json +101 -0
  280. package/messages/it/docs.json +27 -0
  281. package/messages/it/entities.json +7 -0
  282. package/messages/it/features.json +119 -0
  283. package/messages/it/footer.json +22 -0
  284. package/messages/it/home.json +57 -0
  285. package/messages/it/index.ts +39 -0
  286. package/messages/it/mobileNav.json +13 -0
  287. package/messages/it/navigation.json +8 -0
  288. package/messages/it/observability.json +74 -0
  289. package/messages/it/posts.json +54 -0
  290. package/messages/it/pricing.json +102 -0
  291. package/messages/it/support.json +9 -0
  292. package/messages/it/teams.json +8 -0
  293. package/messages/pt/admin.json +219 -0
  294. package/messages/pt/aiUsage.json +36 -0
  295. package/messages/pt/buttons.json +19 -0
  296. package/messages/pt/categories.json +35 -0
  297. package/messages/pt/common.json +16 -0
  298. package/messages/pt/dev.json +101 -0
  299. package/messages/pt/docs.json +27 -0
  300. package/messages/pt/entities.json +7 -0
  301. package/messages/pt/features.json +119 -0
  302. package/messages/pt/footer.json +22 -0
  303. package/messages/pt/home.json +57 -0
  304. package/messages/pt/index.ts +39 -0
  305. package/messages/pt/mobileNav.json +13 -0
  306. package/messages/pt/navigation.json +8 -0
  307. package/messages/pt/observability.json +74 -0
  308. package/messages/pt/posts.json +54 -0
  309. package/messages/pt/pricing.json +102 -0
  310. package/messages/pt/support.json +9 -0
  311. package/messages/pt/teams.json +8 -0
  312. package/migrations/089_add_editor_team_role.sql +39 -0
  313. package/migrations/090_demo_users_teams.sql +540 -0
  314. package/migrations/091_greek_teams_billing.sql +523 -0
  315. package/migrations/092_billing_sample_data.sql +774 -0
  316. package/migrations/093_pages_sample_data.sql +1158 -0
  317. package/migrations/094_posts_sample_data.sql +278 -0
  318. package/migrations/095_tasks_sample_data.sql +440 -0
  319. package/migrations/096_customers_sample_data.sql +358 -0
  320. package/migrations/097_scheduled_actions_sample_data.sql +111 -0
  321. package/package.json +22 -0
  322. package/public/docs/desktop-layout-example.png +0 -0
  323. package/styles/components.css +11 -0
  324. package/styles/globals.css +179 -0
  325. package/templates/(public)/blog/[slug]/page.tsx +65 -0
  326. package/templates/(public)/layout.tsx +25 -0
  327. package/templates/(public)/page.tsx +200 -0
  328. package/templates/(public)/support/page.tsx +321 -0
  329. package/templates/dashboard/(main)/agent-multi/page.tsx +63 -0
  330. package/templates/dashboard/(main)/agent-single/page.tsx +142 -0
  331. package/templates/dashboard/(main)/settings/ai-usage/page.tsx +157 -0
  332. package/templates/superadmin/ai-observability/[traceId]/page.tsx +27 -0
  333. package/templates/superadmin/ai-observability/page.tsx +17 -0
@@ -0,0 +1,142 @@
1
+ 'use client'
2
+
3
+ import { ChatPanel, type SidebarConfig } from '@/themes/default/components/ai-chat/ChatPanel'
4
+ import { usePersistentChat } from '@/themes/default/lib/hooks/usePersistentChat'
5
+ import { useConversations } from '@/themes/default/lib/hooks/useConversations'
6
+ import { Bot, Loader2, MessageSquarePlus } from 'lucide-react'
7
+
8
+ /**
9
+ * AI Assistant Page with Multiple Conversations
10
+ *
11
+ * Features:
12
+ * - Sidebar with list of all conversations
13
+ * - Create new conversations
14
+ * - Switch between conversations
15
+ * - Rename, delete, pin/unpin conversations
16
+ * - Persistent message history per conversation
17
+ * - Max 50 conversations, 50 messages per conversation
18
+ */
19
+ export default function AiAssistantTemplate() {
20
+ const {
21
+ conversations,
22
+ activeSessionId,
23
+ setActiveSession,
24
+ createConversation,
25
+ deleteConversation,
26
+ renameConversation,
27
+ togglePin,
28
+ isLoading: isLoadingConversations,
29
+ isCreating,
30
+ canCreateNew,
31
+ conversationCount,
32
+ maxConversations,
33
+ isReady: isConversationsReady,
34
+ } = useConversations()
35
+
36
+ const {
37
+ messages,
38
+ input,
39
+ setInput,
40
+ isLoading: isSending,
41
+ isLoadingHistory,
42
+ sendMessage,
43
+ error,
44
+ isReady: isChatReady,
45
+ hasSession,
46
+ } = usePersistentChat(activeSessionId)
47
+
48
+ const isReady = isConversationsReady && isChatReady
49
+
50
+ const handleNewConversation = async () => {
51
+ await createConversation()
52
+ }
53
+
54
+ // Sidebar configuration
55
+ const sidebarConfig: SidebarConfig = {
56
+ conversations,
57
+ activeSessionId,
58
+ onSelect: setActiveSession,
59
+ onNew: handleNewConversation,
60
+ onRename: renameConversation,
61
+ onDelete: deleteConversation,
62
+ onTogglePin: togglePin,
63
+ isLoading: isLoadingConversations,
64
+ isCreating,
65
+ canCreateNew,
66
+ conversationCount,
67
+ maxConversations,
68
+ }
69
+
70
+ return (
71
+ <ChatPanel
72
+ cyPrefix="ai-chat"
73
+ messages={messages}
74
+ input={input}
75
+ onInputChange={setInput}
76
+ onSend={sendMessage}
77
+ isLoading={isSending}
78
+ error={error}
79
+ isReady={isReady}
80
+ isLoadingHistory={isLoadingHistory}
81
+ hasSession={hasSession}
82
+ sessionId={activeSessionId}
83
+ showSessionDebug
84
+ sidebar={sidebarConfig}
85
+ header={{
86
+ title: 'AI Assistant',
87
+ subtitle: hasSession
88
+ ? 'Ask me about your tasks or anything else.'
89
+ : 'Select or create a conversation to begin.',
90
+ icon: Bot,
91
+ mobileAction: (
92
+ <button
93
+ onClick={handleNewConversation}
94
+ disabled={!canCreateNew || isCreating}
95
+ className="p-2 rounded-md hover:bg-muted disabled:opacity-50"
96
+ data-cy="new-conversation-mobile"
97
+ >
98
+ {isCreating ? (
99
+ <Loader2 className="h-5 w-5 animate-spin" />
100
+ ) : (
101
+ <MessageSquarePlus className="h-5 w-5" />
102
+ )}
103
+ </button>
104
+ ),
105
+ }}
106
+ emptyState={{
107
+ icon: Bot,
108
+ title: 'Welcome to your AI Assistant',
109
+ description: 'Your conversation history is automatically saved. Ask me anything!',
110
+ suggestions: [
111
+ 'Show me my tasks',
112
+ 'Create a new task: Review project proposal',
113
+ 'What tasks are due this week?',
114
+ ],
115
+ }}
116
+ noSessionState={{
117
+ icon: MessageSquarePlus,
118
+ title: conversations.length === 0
119
+ ? 'Start your first conversation'
120
+ : 'Select a conversation',
121
+ description: conversations.length === 0
122
+ ? 'Create a new conversation to start chatting with your AI assistant.'
123
+ : 'Choose a conversation from the sidebar or create a new one.',
124
+ action: (
125
+ <button
126
+ onClick={handleNewConversation}
127
+ disabled={!canCreateNew || isCreating}
128
+ className="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50"
129
+ data-cy="start-conversation-btn"
130
+ >
131
+ {isCreating ? (
132
+ <Loader2 className="h-4 w-4 animate-spin" />
133
+ ) : (
134
+ <MessageSquarePlus className="h-4 w-4" />
135
+ )}
136
+ New conversation
137
+ </button>
138
+ ),
139
+ }}
140
+ />
141
+ )
142
+ }
@@ -0,0 +1,157 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { Card, CardContent, CardHeader, CardTitle } from '@nextsparkjs/core/components/ui/card'
5
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@nextsparkjs/core/components/ui/select'
6
+ import { useTokenUsage } from '@/themes/default/lib/hooks/useTokenUsage'
7
+ import { useTranslations } from 'next-intl'
8
+ import { Loader2, Coins, Zap, TrendingUp } from 'lucide-react'
9
+
10
+ type Period = 'today' | '7d' | '30d' | 'all'
11
+
12
+ export default function AIUsagePage() {
13
+ const t = useTranslations('aiUsage')
14
+ const [period, setPeriod] = useState<Period>('30d')
15
+ const { data, isLoading, error } = useTokenUsage(period)
16
+
17
+ if (isLoading) {
18
+ return (
19
+ <div className="flex items-center justify-center h-64" data-cy="ai-usage-loading">
20
+ <Loader2 className="h-8 w-8 animate-spin" />
21
+ </div>
22
+ )
23
+ }
24
+
25
+ if (error) {
26
+ return (
27
+ <div className="p-4 text-destructive" data-cy="ai-usage-error">
28
+ {t('error')}: {error.message}
29
+ </div>
30
+ )
31
+ }
32
+
33
+ const stats = data?.data?.stats
34
+ const daily = data?.data?.daily || []
35
+
36
+ return (
37
+ <div className="space-y-6" data-cy="ai-usage-page">
38
+ {/* Header */}
39
+ <div className="flex items-center justify-between">
40
+ <div>
41
+ <h1 className="text-2xl font-bold">{t('title')}</h1>
42
+ <p className="text-muted-foreground">{t('description')}</p>
43
+ </div>
44
+
45
+ <Select value={period} onValueChange={(v: string) => setPeriod(v as Period)}>
46
+ <SelectTrigger className="w-32" data-cy="ai-usage-period-select">
47
+ <SelectValue />
48
+ </SelectTrigger>
49
+ <SelectContent>
50
+ <SelectItem value="today">{t('period.today')}</SelectItem>
51
+ <SelectItem value="7d">{t('period.7d')}</SelectItem>
52
+ <SelectItem value="30d">{t('period.30d')}</SelectItem>
53
+ <SelectItem value="all">{t('period.all')}</SelectItem>
54
+ </SelectContent>
55
+ </Select>
56
+ </div>
57
+
58
+ {/* Stats Cards */}
59
+ <div className="grid gap-4 md:grid-cols-3">
60
+ <Card data-cy="ai-usage-total-tokens">
61
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
62
+ <CardTitle className="text-sm font-medium">{t('stats.totalTokens.title')}</CardTitle>
63
+ <Zap className="h-4 w-4 text-muted-foreground" />
64
+ </CardHeader>
65
+ <CardContent>
66
+ <div className="text-2xl font-bold">
67
+ {stats?.totalTokens.toLocaleString() || 0}
68
+ </div>
69
+ <p className="text-xs text-muted-foreground">
70
+ {stats?.inputTokens.toLocaleString() || 0} {t('stats.totalTokens.input')} / {stats?.outputTokens.toLocaleString() || 0} {t('stats.totalTokens.output')}
71
+ </p>
72
+ </CardContent>
73
+ </Card>
74
+
75
+ <Card data-cy="ai-usage-total-cost">
76
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
77
+ <CardTitle className="text-sm font-medium">{t('stats.estimatedCost.title')}</CardTitle>
78
+ <Coins className="h-4 w-4 text-muted-foreground" />
79
+ </CardHeader>
80
+ <CardContent>
81
+ <div className="text-2xl font-bold">
82
+ ${stats?.totalCost.toFixed(4) || '0.0000'}
83
+ </div>
84
+ <p className="text-xs text-muted-foreground">
85
+ {t('stats.estimatedCost.currency')}
86
+ </p>
87
+ </CardContent>
88
+ </Card>
89
+
90
+ <Card data-cy="ai-usage-requests">
91
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
92
+ <CardTitle className="text-sm font-medium">{t('stats.requests.title')}</CardTitle>
93
+ <TrendingUp className="h-4 w-4 text-muted-foreground" />
94
+ </CardHeader>
95
+ <CardContent>
96
+ <div className="text-2xl font-bold">
97
+ {stats?.requestCount.toLocaleString() || 0}
98
+ </div>
99
+ <p className="text-xs text-muted-foreground">
100
+ {t('stats.requests.description')}
101
+ </p>
102
+ </CardContent>
103
+ </Card>
104
+ </div>
105
+
106
+ {/* Usage by Model */}
107
+ {stats?.byModel && Object.keys(stats.byModel).length > 0 && (
108
+ <Card data-cy="ai-usage-by-model">
109
+ <CardHeader>
110
+ <CardTitle>{t('usageByModel.title')}</CardTitle>
111
+ </CardHeader>
112
+ <CardContent>
113
+ <div className="space-y-4">
114
+ {Object.entries(stats.byModel).map(([model, data]) => (
115
+ <div key={model} className="flex items-center justify-between">
116
+ <div>
117
+ <p className="font-medium">{model}</p>
118
+ <p className="text-sm text-muted-foreground">
119
+ {data.tokens.toLocaleString()} {t('usageByModel.tokens')}
120
+ </p>
121
+ </div>
122
+ <div className="text-right">
123
+ <p className="font-medium">${data.cost.toFixed(4)}</p>
124
+ </div>
125
+ </div>
126
+ ))}
127
+ </div>
128
+ </CardContent>
129
+ </Card>
130
+ )}
131
+
132
+ {/* Daily Chart */}
133
+ <Card data-cy="ai-usage-chart">
134
+ <CardHeader>
135
+ <CardTitle>{t('dailyUsage.title')}</CardTitle>
136
+ </CardHeader>
137
+ <CardContent>
138
+ {daily.length === 0 ? (
139
+ <p className="text-muted-foreground text-center py-8">
140
+ {t('dailyUsage.noData')}
141
+ </p>
142
+ ) : (
143
+ <div className="space-y-2">
144
+ {daily.slice(0, 7).map((day) => (
145
+ <div key={day.date} className="flex items-center justify-between text-sm">
146
+ <span>{day.date}</span>
147
+ <span>{day.tokens.toLocaleString()} {t('dailyUsage.tokens')}</span>
148
+ <span>${day.cost.toFixed(4)}</span>
149
+ </div>
150
+ ))}
151
+ </div>
152
+ )}
153
+ </CardContent>
154
+ </Card>
155
+ </div>
156
+ )
157
+ }
@@ -0,0 +1,27 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * AI Observability Trace Detail Page
5
+ *
6
+ * Theme implementation of the trace detail page.
7
+ * Uses the plugin preset and applies theme-specific configuration.
8
+ */
9
+
10
+ import { use } from 'react'
11
+ import { observabilityConfig } from '@/themes/default/lib/langchain/observability.config'
12
+ import { TraceDetailPagePreset } from '@/plugins/langchain/presets/templates/sector7/ai-observability/[traceId]/page'
13
+
14
+ interface PageProps {
15
+ params: Promise<{ traceId: string }>
16
+ }
17
+
18
+ export default function TraceDetailPage({ params }: PageProps) {
19
+ const { traceId } = use(params)
20
+
21
+ return (
22
+ <TraceDetailPagePreset
23
+ traceId={traceId}
24
+ enabled={observabilityConfig.observability?.enabled ?? false}
25
+ />
26
+ )
27
+ }
@@ -0,0 +1,17 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * AI Observability Dashboard Page
5
+ *
6
+ * Theme implementation of the LangChain observability dashboard.
7
+ * Uses the plugin preset and applies theme-specific configuration.
8
+ */
9
+
10
+ import { observabilityConfig } from '@/themes/default/lib/langchain/observability.config'
11
+ import { AIObservabilityPagePreset } from '@/plugins/langchain/presets/templates/sector7/ai-observability/page'
12
+
13
+ export default function AIObservabilityPage() {
14
+ return (
15
+ <AIObservabilityPagePreset enabled={observabilityConfig.observability?.enabled ?? false} />
16
+ )
17
+ }