@digilogiclabs/create-saas-app 1.17.1 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +6 -2
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/template-generator.d.ts.map +1 -1
- package/dist/generators/template-generator.js +13 -7
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/README.md +655 -0
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +683 -0
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +787 -0
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +346 -0
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +180 -0
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/package.json +113 -0
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +599 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/README.md +434 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +642 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +466 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +393 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +457 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +478 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +250 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/package.json +74 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +622 -0
- package/dist/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +396 -0
- package/package.json +1 -1
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/README.md +655 -0
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +683 -0
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +787 -0
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +346 -0
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +180 -0
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/package.json +113 -0
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +599 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/README.md +434 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +642 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +466 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +393 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +457 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +478 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +250 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/package.json +74 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +622 -0
- package/src/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +396 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from 'react'
|
|
4
|
+
import { Card } from '@digilogiclabs/saas-factory-ui'
|
|
5
|
+
import {
|
|
6
|
+
TrendingUp,
|
|
7
|
+
TrendingDown,
|
|
8
|
+
Activity,
|
|
9
|
+
Users,
|
|
10
|
+
Clock,
|
|
11
|
+
Database,
|
|
12
|
+
MessageSquare,
|
|
13
|
+
BarChart3,
|
|
14
|
+
PieChart,
|
|
15
|
+
Calendar,
|
|
16
|
+
RefreshCw,
|
|
17
|
+
Download
|
|
18
|
+
} from 'lucide-react'
|
|
19
|
+
import {
|
|
20
|
+
LineChart,
|
|
21
|
+
Line,
|
|
22
|
+
AreaChart,
|
|
23
|
+
Area,
|
|
24
|
+
XAxis,
|
|
25
|
+
YAxis,
|
|
26
|
+
CartesianGrid,
|
|
27
|
+
Tooltip,
|
|
28
|
+
ResponsiveContainer,
|
|
29
|
+
BarChart,
|
|
30
|
+
Bar,
|
|
31
|
+
PieChart as RechartsPieChart,
|
|
32
|
+
Cell
|
|
33
|
+
} from 'recharts'
|
|
34
|
+
import type { UseRAGSystemReturn } from '../../hooks/useRAGSystem'
|
|
35
|
+
|
|
36
|
+
interface RAGAnalyticsProps {
|
|
37
|
+
ragSystem: UseRAGSystemReturn<any>
|
|
38
|
+
timeRange?: '1d' | '7d' | '30d' | '90d'
|
|
39
|
+
showDetailedMetrics?: boolean
|
|
40
|
+
className?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface AnalyticsData {
|
|
44
|
+
usage: {
|
|
45
|
+
totalQueries: number
|
|
46
|
+
successfulQueries: number
|
|
47
|
+
failedQueries: number
|
|
48
|
+
averageResponseTime: number
|
|
49
|
+
queriesPerDay: Array<{ date: string; queries: number }>
|
|
50
|
+
}
|
|
51
|
+
knowledge: {
|
|
52
|
+
totalDocuments: number
|
|
53
|
+
documentsAdded: number
|
|
54
|
+
documentsUpdated: number
|
|
55
|
+
documentsDeleted: number
|
|
56
|
+
categoriesDistribution: Array<{ category: string; count: number }>
|
|
57
|
+
}
|
|
58
|
+
performance: {
|
|
59
|
+
averageConfidence: number
|
|
60
|
+
responseTimeDistribution: Array<{ range: string; count: number }>
|
|
61
|
+
popularQueries: Array<{ query: string; count: number; averageConfidence: number }>
|
|
62
|
+
}
|
|
63
|
+
users: {
|
|
64
|
+
activeUsers: number
|
|
65
|
+
newUsers: number
|
|
66
|
+
userSatisfaction: number
|
|
67
|
+
feedbackDistribution: Array<{ type: string; count: number }>
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4']
|
|
72
|
+
|
|
73
|
+
export function RAGAnalytics({
|
|
74
|
+
ragSystem,
|
|
75
|
+
timeRange = '7d',
|
|
76
|
+
showDetailedMetrics = true,
|
|
77
|
+
className = ''
|
|
78
|
+
}: RAGAnalyticsProps) {
|
|
79
|
+
const [analyticsData, setAnalyticsData] = useState<AnalyticsData | null>(null)
|
|
80
|
+
const [selectedTimeRange, setSelectedTimeRange] = useState(timeRange)
|
|
81
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
loadAnalyticsData()
|
|
85
|
+
}, [selectedTimeRange, ragSystem])
|
|
86
|
+
|
|
87
|
+
const loadAnalyticsData = async () => {
|
|
88
|
+
if (!ragSystem.ragSystem) return
|
|
89
|
+
|
|
90
|
+
setIsLoading(true)
|
|
91
|
+
try {
|
|
92
|
+
const data = await ragSystem.getAnalytics(selectedTimeRange)
|
|
93
|
+
if (data) {
|
|
94
|
+
setAnalyticsData(data)
|
|
95
|
+
} else {
|
|
96
|
+
// Generate mock data for demonstration
|
|
97
|
+
setAnalyticsData(generateMockData())
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('Failed to load analytics:', error)
|
|
101
|
+
setAnalyticsData(generateMockData()) // Fallback to mock data
|
|
102
|
+
} finally {
|
|
103
|
+
setIsLoading(false)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const generateMockData = (): AnalyticsData => {
|
|
108
|
+
const days = parseInt(selectedTimeRange.replace('d', ''))
|
|
109
|
+
const queriesPerDay = Array.from({ length: days }, (_, i) => ({
|
|
110
|
+
date: new Date(Date.now() - (days - 1 - i) * 24 * 60 * 60 * 1000).toLocaleDateString(),
|
|
111
|
+
queries: Math.floor(Math.random() * 50) + 10
|
|
112
|
+
}))
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
usage: {
|
|
116
|
+
totalQueries: ragSystem.totalQueries || Math.floor(Math.random() * 1000) + 500,
|
|
117
|
+
successfulQueries: Math.floor(Math.random() * 900) + 450,
|
|
118
|
+
failedQueries: Math.floor(Math.random() * 50) + 10,
|
|
119
|
+
averageResponseTime: Math.floor(Math.random() * 2000) + 500,
|
|
120
|
+
queriesPerDay
|
|
121
|
+
},
|
|
122
|
+
knowledge: {
|
|
123
|
+
totalDocuments: ragSystem.totalDocuments || Math.floor(Math.random() * 500) + 100,
|
|
124
|
+
documentsAdded: Math.floor(Math.random() * 50) + 10,
|
|
125
|
+
documentsUpdated: Math.floor(Math.random() * 30) + 5,
|
|
126
|
+
documentsDeleted: Math.floor(Math.random() * 10) + 1,
|
|
127
|
+
categoriesDistribution: [
|
|
128
|
+
{ category: 'general', count: 45 },
|
|
129
|
+
{ category: 'faq', count: 32 },
|
|
130
|
+
{ category: 'guides', count: 28 },
|
|
131
|
+
{ category: 'reference', count: 15 },
|
|
132
|
+
{ category: 'manual', count: 12 }
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
performance: {
|
|
136
|
+
averageConfidence: 0.78,
|
|
137
|
+
responseTimeDistribution: [
|
|
138
|
+
{ range: '0-500ms', count: 45 },
|
|
139
|
+
{ range: '500-1000ms', count: 35 },
|
|
140
|
+
{ range: '1000-2000ms', count: 15 },
|
|
141
|
+
{ range: '2000ms+', count: 5 }
|
|
142
|
+
],
|
|
143
|
+
popularQueries: [
|
|
144
|
+
{ query: 'How to get started?', count: 45, averageConfidence: 0.89 },
|
|
145
|
+
{ query: 'What are the features?', count: 38, averageConfidence: 0.85 },
|
|
146
|
+
{ query: 'Pricing information', count: 32, averageConfidence: 0.82 },
|
|
147
|
+
{ query: 'Technical support', count: 28, averageConfidence: 0.75 },
|
|
148
|
+
{ query: 'API documentation', count: 24, averageConfidence: 0.88 }
|
|
149
|
+
]
|
|
150
|
+
},
|
|
151
|
+
users: {
|
|
152
|
+
activeUsers: Math.floor(Math.random() * 100) + 50,
|
|
153
|
+
newUsers: Math.floor(Math.random() * 20) + 5,
|
|
154
|
+
userSatisfaction: 4.2,
|
|
155
|
+
feedbackDistribution: [
|
|
156
|
+
{ type: 'positive', count: 78 },
|
|
157
|
+
{ type: 'neutral', count: 15 },
|
|
158
|
+
{ type: 'negative', count: 7 }
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const exportAnalytics = () => {
|
|
165
|
+
if (!analyticsData) return
|
|
166
|
+
|
|
167
|
+
const exportData = {
|
|
168
|
+
timeRange: selectedTimeRange,
|
|
169
|
+
exportedAt: new Date().toISOString(),
|
|
170
|
+
data: analyticsData
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const blob = new Blob([JSON.stringify(exportData, null, 2)], {
|
|
174
|
+
type: 'application/json'
|
|
175
|
+
})
|
|
176
|
+
const url = URL.createObjectURL(blob)
|
|
177
|
+
const a = document.createElement('a')
|
|
178
|
+
a.href = url
|
|
179
|
+
a.download = `rag-analytics-${selectedTimeRange}-${new Date().toISOString().split('T')[0]}.json`
|
|
180
|
+
a.click()
|
|
181
|
+
URL.revokeObjectURL(url)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!analyticsData) {
|
|
185
|
+
return (
|
|
186
|
+
<div className={`space-y-6 ${className}`}>
|
|
187
|
+
<div className="flex items-center justify-center h-64">
|
|
188
|
+
<div className="text-center">
|
|
189
|
+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-4"></div>
|
|
190
|
+
<p>Loading analytics data...</p>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<div className={`space-y-6 ${className}`}>
|
|
199
|
+
{/* Header */}
|
|
200
|
+
<div className="flex items-center justify-between">
|
|
201
|
+
<div>
|
|
202
|
+
<h2 className="text-2xl font-bold">RAG Analytics</h2>
|
|
203
|
+
<p className="text-gray-600 dark:text-gray-300">
|
|
204
|
+
Performance insights for your AI knowledge system
|
|
205
|
+
</p>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
<div className="flex items-center gap-3">
|
|
209
|
+
<select
|
|
210
|
+
value={selectedTimeRange}
|
|
211
|
+
onChange={(e) => setSelectedTimeRange(e.target.value as any)}
|
|
212
|
+
className="px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
213
|
+
>
|
|
214
|
+
<option value="1d">Last 24 hours</option>
|
|
215
|
+
<option value="7d">Last 7 days</option>
|
|
216
|
+
<option value="30d">Last 30 days</option>
|
|
217
|
+
<option value="90d">Last 90 days</option>
|
|
218
|
+
</select>
|
|
219
|
+
|
|
220
|
+
<button
|
|
221
|
+
onClick={loadAnalyticsData}
|
|
222
|
+
disabled={isLoading}
|
|
223
|
+
className="p-2 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 disabled:opacity-50"
|
|
224
|
+
>
|
|
225
|
+
<RefreshCw className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
|
|
226
|
+
</button>
|
|
227
|
+
|
|
228
|
+
<button
|
|
229
|
+
onClick={exportAnalytics}
|
|
230
|
+
className="flex items-center gap-2 px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800"
|
|
231
|
+
>
|
|
232
|
+
<Download className="w-4 h-4" />
|
|
233
|
+
Export
|
|
234
|
+
</button>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
{/* Key Metrics */}
|
|
239
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
240
|
+
<Card className="p-6">
|
|
241
|
+
<div className="flex items-center gap-3">
|
|
242
|
+
<div className="p-2 bg-blue-100 dark:bg-blue-900/30 rounded-lg">
|
|
243
|
+
<MessageSquare className="w-6 h-6 text-blue-600" />
|
|
244
|
+
</div>
|
|
245
|
+
<div>
|
|
246
|
+
<p className="text-2xl font-bold">{analyticsData.usage.totalQueries.toLocaleString()}</p>
|
|
247
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Total Queries</p>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<div className="mt-2 flex items-center gap-1 text-sm">
|
|
251
|
+
<TrendingUp className="w-4 h-4 text-green-500" />
|
|
252
|
+
<span className="text-green-500">+12%</span>
|
|
253
|
+
<span className="text-gray-500">vs last period</span>
|
|
254
|
+
</div>
|
|
255
|
+
</Card>
|
|
256
|
+
|
|
257
|
+
<Card className="p-6">
|
|
258
|
+
<div className="flex items-center gap-3">
|
|
259
|
+
<div className="p-2 bg-green-100 dark:bg-green-900/30 rounded-lg">
|
|
260
|
+
<Database className="w-6 h-6 text-green-600" />
|
|
261
|
+
</div>
|
|
262
|
+
<div>
|
|
263
|
+
<p className="text-2xl font-bold">{analyticsData.knowledge.totalDocuments.toLocaleString()}</p>
|
|
264
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Knowledge Docs</p>
|
|
265
|
+
</div>
|
|
266
|
+
</div>
|
|
267
|
+
<div className="mt-2 flex items-center gap-1 text-sm">
|
|
268
|
+
<TrendingUp className="w-4 h-4 text-green-500" />
|
|
269
|
+
<span className="text-green-500">+{analyticsData.knowledge.documentsAdded}</span>
|
|
270
|
+
<span className="text-gray-500">this period</span>
|
|
271
|
+
</div>
|
|
272
|
+
</Card>
|
|
273
|
+
|
|
274
|
+
<Card className="p-6">
|
|
275
|
+
<div className="flex items-center gap-3">
|
|
276
|
+
<div className="p-2 bg-purple-100 dark:bg-purple-900/30 rounded-lg">
|
|
277
|
+
<Clock className="w-6 h-6 text-purple-600" />
|
|
278
|
+
</div>
|
|
279
|
+
<div>
|
|
280
|
+
<p className="text-2xl font-bold">{analyticsData.usage.averageResponseTime}ms</p>
|
|
281
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Avg Response Time</p>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
<div className="mt-2 flex items-center gap-1 text-sm">
|
|
285
|
+
<TrendingDown className="w-4 h-4 text-green-500" />
|
|
286
|
+
<span className="text-green-500">-5%</span>
|
|
287
|
+
<span className="text-gray-500">faster</span>
|
|
288
|
+
</div>
|
|
289
|
+
</Card>
|
|
290
|
+
|
|
291
|
+
<Card className="p-6">
|
|
292
|
+
<div className="flex items-center gap-3">
|
|
293
|
+
<div className="p-2 bg-orange-100 dark:bg-orange-900/30 rounded-lg">
|
|
294
|
+
<TrendingUp className="w-6 h-6 text-orange-600" />
|
|
295
|
+
</div>
|
|
296
|
+
<div>
|
|
297
|
+
<p className="text-2xl font-bold">
|
|
298
|
+
{Math.round(analyticsData.performance.averageConfidence * 100)}%
|
|
299
|
+
</p>
|
|
300
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Avg Confidence</p>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
<div className="mt-2 flex items-center gap-1 text-sm">
|
|
304
|
+
<TrendingUp className="w-4 h-4 text-green-500" />
|
|
305
|
+
<span className="text-green-500">+3%</span>
|
|
306
|
+
<span className="text-gray-500">improvement</span>
|
|
307
|
+
</div>
|
|
308
|
+
</Card>
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
{/* Charts */}
|
|
312
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
313
|
+
{/* Query Volume Chart */}
|
|
314
|
+
<Card className="p-6">
|
|
315
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
316
|
+
<BarChart3 className="w-5 h-5" />
|
|
317
|
+
Query Volume
|
|
318
|
+
</h3>
|
|
319
|
+
<ResponsiveContainer width="100%" height={300}>
|
|
320
|
+
<AreaChart data={analyticsData.usage.queriesPerDay}>
|
|
321
|
+
<CartesianGrid strokeDasharray="3 3" />
|
|
322
|
+
<XAxis dataKey="date" />
|
|
323
|
+
<YAxis />
|
|
324
|
+
<Tooltip />
|
|
325
|
+
<Area
|
|
326
|
+
type="monotone"
|
|
327
|
+
dataKey="queries"
|
|
328
|
+
stroke="#3b82f6"
|
|
329
|
+
fill="#3b82f6"
|
|
330
|
+
fillOpacity={0.3}
|
|
331
|
+
/>
|
|
332
|
+
</AreaChart>
|
|
333
|
+
</ResponsiveContainer>
|
|
334
|
+
</Card>
|
|
335
|
+
|
|
336
|
+
{/* Response Time Distribution */}
|
|
337
|
+
<Card className="p-6">
|
|
338
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
339
|
+
<Clock className="w-5 h-5" />
|
|
340
|
+
Response Time Distribution
|
|
341
|
+
</h3>
|
|
342
|
+
<ResponsiveContainer width="100%" height={300}>
|
|
343
|
+
<BarChart data={analyticsData.performance.responseTimeDistribution}>
|
|
344
|
+
<CartesianGrid strokeDasharray="3 3" />
|
|
345
|
+
<XAxis dataKey="range" />
|
|
346
|
+
<YAxis />
|
|
347
|
+
<Tooltip />
|
|
348
|
+
<Bar dataKey="count" fill="#10b981" />
|
|
349
|
+
</BarChart>
|
|
350
|
+
</ResponsiveContainer>
|
|
351
|
+
</Card>
|
|
352
|
+
|
|
353
|
+
{/* Categories Distribution */}
|
|
354
|
+
<Card className="p-6">
|
|
355
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
356
|
+
<PieChart className="w-5 h-5" />
|
|
357
|
+
Knowledge Categories
|
|
358
|
+
</h3>
|
|
359
|
+
<ResponsiveContainer width="100%" height={300}>
|
|
360
|
+
<RechartsPieChart>
|
|
361
|
+
<Pie
|
|
362
|
+
data={analyticsData.knowledge.categoriesDistribution}
|
|
363
|
+
cx="50%"
|
|
364
|
+
cy="50%"
|
|
365
|
+
outerRadius={80}
|
|
366
|
+
dataKey="count"
|
|
367
|
+
label={({ category, count }) => `${category}: ${count}`}
|
|
368
|
+
>
|
|
369
|
+
{analyticsData.knowledge.categoriesDistribution.map((entry, index) => (
|
|
370
|
+
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
|
|
371
|
+
))}
|
|
372
|
+
</Pie>
|
|
373
|
+
<Tooltip />
|
|
374
|
+
</RechartsPieChart>
|
|
375
|
+
</ResponsiveContainer>
|
|
376
|
+
</Card>
|
|
377
|
+
|
|
378
|
+
{/* User Feedback */}
|
|
379
|
+
<Card className="p-6">
|
|
380
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
381
|
+
<Users className="w-5 h-5" />
|
|
382
|
+
User Feedback
|
|
383
|
+
</h3>
|
|
384
|
+
<div className="space-y-4">
|
|
385
|
+
<div className="flex items-center justify-between">
|
|
386
|
+
<span className="text-sm font-medium">Overall Satisfaction</span>
|
|
387
|
+
<span className="text-2xl font-bold text-green-500">
|
|
388
|
+
{analyticsData.users.userSatisfaction}/5.0
|
|
389
|
+
</span>
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
{analyticsData.users.feedbackDistribution.map((feedback, index) => (
|
|
393
|
+
<div key={feedback.type} className="space-y-2">
|
|
394
|
+
<div className="flex justify-between text-sm">
|
|
395
|
+
<span className="capitalize">{feedback.type}</span>
|
|
396
|
+
<span>{feedback.count}</span>
|
|
397
|
+
</div>
|
|
398
|
+
<div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
399
|
+
<div
|
|
400
|
+
className="h-2 rounded-full"
|
|
401
|
+
style={{
|
|
402
|
+
width: `${(feedback.count / analyticsData.users.feedbackDistribution.reduce((sum, f) => sum + f.count, 0)) * 100}%`,
|
|
403
|
+
backgroundColor: COLORS[index % COLORS.length]
|
|
404
|
+
}}
|
|
405
|
+
/>
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
408
|
+
))}
|
|
409
|
+
</div>
|
|
410
|
+
</Card>
|
|
411
|
+
</div>
|
|
412
|
+
|
|
413
|
+
{/* Popular Queries */}
|
|
414
|
+
{showDetailedMetrics && (
|
|
415
|
+
<Card className="p-6">
|
|
416
|
+
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
|
417
|
+
<Activity className="w-5 h-5" />
|
|
418
|
+
Popular Queries
|
|
419
|
+
</h3>
|
|
420
|
+
<div className="space-y-3">
|
|
421
|
+
{analyticsData.performance.popularQueries.map((query, index) => (
|
|
422
|
+
<div key={index} className="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800/50 rounded-lg">
|
|
423
|
+
<div className="flex-1">
|
|
424
|
+
<p className="font-medium">{query.query}</p>
|
|
425
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">
|
|
426
|
+
{query.count} queries • {Math.round(query.averageConfidence * 100)}% avg confidence
|
|
427
|
+
</p>
|
|
428
|
+
</div>
|
|
429
|
+
<div className="text-right">
|
|
430
|
+
<div className="text-2xl font-bold text-blue-500">#{index + 1}</div>
|
|
431
|
+
</div>
|
|
432
|
+
</div>
|
|
433
|
+
))}
|
|
434
|
+
</div>
|
|
435
|
+
</Card>
|
|
436
|
+
)}
|
|
437
|
+
|
|
438
|
+
{/* System Health Summary */}
|
|
439
|
+
<Card className="p-6">
|
|
440
|
+
<h3 className="text-lg font-semibold mb-4">System Health Summary</h3>
|
|
441
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
442
|
+
<div className="text-center">
|
|
443
|
+
<div className="text-3xl font-bold text-green-500 mb-2">
|
|
444
|
+
{Math.round((analyticsData.usage.successfulQueries / analyticsData.usage.totalQueries) * 100)}%
|
|
445
|
+
</div>
|
|
446
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Success Rate</p>
|
|
447
|
+
</div>
|
|
448
|
+
|
|
449
|
+
<div className="text-center">
|
|
450
|
+
<div className="text-3xl font-bold text-blue-500 mb-2">
|
|
451
|
+
{analyticsData.users.activeUsers}
|
|
452
|
+
</div>
|
|
453
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Active Users</p>
|
|
454
|
+
</div>
|
|
455
|
+
|
|
456
|
+
<div className="text-center">
|
|
457
|
+
<div className="text-3xl font-bold text-purple-500 mb-2">
|
|
458
|
+
{Math.round((analyticsData.knowledge.documentsAdded / analyticsData.knowledge.totalDocuments) * 100)}%
|
|
459
|
+
</div>
|
|
460
|
+
<p className="text-sm text-gray-600 dark:text-gray-300">Growth Rate</p>
|
|
461
|
+
</div>
|
|
462
|
+
</div>
|
|
463
|
+
</Card>
|
|
464
|
+
</div>
|
|
465
|
+
)
|
|
466
|
+
}
|