PD03 commited on
Commit
cfa760d
·
verified ·
1 Parent(s): 5d04a05

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +604 -19
index.html CHANGED
@@ -1,19 +1,604 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, BarChart, Bar, PieChart, Pie, Cell } from 'recharts';
3
+ import { Play, Brain, Zap, TrendingUp, AlertTriangle, CheckCircle, XCircle, DollarSign, Clock, Users, BarChart3 } from 'lucide-react';
4
+ import * as tf from 'tensorflow';
5
+
6
+ const ModernSAPDemo = () => {
7
+ const [model, setModel] = useState(null);
8
+ const [isTraining, setIsTraining] = useState(false);
9
+ const [trainingProgress, setTrainingProgress] = useState(0);
10
+ const [trainingMetrics, setTrainingMetrics] = useState(null);
11
+ const [trainingHistory, setTrainingHistory] = useState([]);
12
+ const [predictions, setPredictions] = useState([]);
13
+ const [unpaidInvoices, setUnpaidInvoices] = useState([]);
14
+ const [activeTab, setActiveTab] = useState('overview');
15
+
16
+ // Generate synthetic SAP AR data
17
+ const generateSyntheticData = () => {
18
+ const data = [];
19
+ const customers = ['Mercedes-Benz AG', 'BMW Group', 'Volkswagen AG', 'Bosch GmbH', 'Siemens AG', 'BASF SE', 'Bayer AG', 'Adidas AG'];
20
+
21
+ for (let i = 0; i < 1500; i++) {
22
+ const invoiceAmount = Math.random() * 100000 + 5000;
23
+ const customerCode = customers[Math.floor(Math.random() * customers.length)];
24
+ const daysOverdue = Math.floor(Math.random() * 150);
25
+ const previousDelays = Math.floor(Math.random() * 6);
26
+ const creditScore = Math.random() * 100;
27
+ const industryRisk = Math.random();
28
+ const seasonality = Math.sin((i % 365) * 2 * Math.PI / 365);
29
+
30
+ let paymentProb = 0.75;
31
+ paymentProb -= Math.min(daysOverdue / 120, 0.5);
32
+ paymentProb -= Math.min(previousDelays / 12, 0.3);
33
+ paymentProb += (creditScore - 50) / 150;
34
+ paymentProb -= industryRisk * 0.25;
35
+ paymentProb += seasonality * 0.15;
36
+ paymentProb = Math.max(0.05, Math.min(0.95, paymentProb));
37
+
38
+ const paidOnTime = Math.random() < paymentProb ? 1 : 0;
39
+
40
+ data.push({
41
+ invoiceAmount: invoiceAmount / 100000,
42
+ daysOverdue: daysOverdue / 150,
43
+ previousDelays: previousDelays / 6,
44
+ creditScore: creditScore / 100,
45
+ industryRisk: industryRisk,
46
+ seasonality: (seasonality + 1) / 2,
47
+ paidOnTime: paidOnTime
48
+ });
49
+ }
50
+
51
+ return data;
52
+ };
53
+
54
+ // Generate unpaid invoices for prediction
55
+ const generateUnpaidInvoices = () => {
56
+ const invoices = [];
57
+ const customers = ['Mercedes-Benz AG', 'BMW Group', 'Volkswagen AG', 'Bosch GmbH', 'Siemens AG'];
58
+ const regions = ['DACH', 'EMEA', 'APAC', 'Americas'];
59
+
60
+ for (let i = 0; i < 20; i++) {
61
+ const invoiceId = `SAP-${Date.now().toString().slice(-6)}-${i.toString().padStart(3, '0')}`;
62
+ const customer = customers[Math.floor(Math.random() * customers.length)];
63
+ const amount = Math.floor(Math.random() * 85000 + 15000);
64
+ const daysOverdue = Math.floor(Math.random() * 120);
65
+ const previousDelays = Math.floor(Math.random() * 5);
66
+ const creditScore = Math.floor(Math.random() * 60 + 40);
67
+ const region = regions[Math.floor(Math.random() * regions.length)];
68
+
69
+ invoices.push({
70
+ invoiceId,
71
+ customer,
72
+ amount,
73
+ daysOverdue,
74
+ previousDelays,
75
+ creditScore,
76
+ region,
77
+ industryRisk: Math.random(),
78
+ seasonality: Math.random(),
79
+ dueDate: new Date(Date.now() - daysOverdue * 24 * 60 * 60 * 1000).toLocaleDateString()
80
+ });
81
+ }
82
+
83
+ return invoices;
84
+ };
85
+
86
+ // Train ML model
87
+ const trainModel = async () => {
88
+ setIsTraining(true);
89
+ setTrainingProgress(0);
90
+ setTrainingHistory([]);
91
+
92
+ try {
93
+ // Generate training data
94
+ const trainingData = generateSyntheticData();
95
+
96
+ // Prepare data for TensorFlow
97
+ const features = trainingData.map(d => [
98
+ d.invoiceAmount, d.daysOverdue, d.previousDelays,
99
+ d.creditScore, d.industryRisk, d.seasonality
100
+ ]);
101
+ const labels = trainingData.map(d => d.paidOnTime);
102
+
103
+ const xs = tf.tensor2d(features);
104
+ const ys = tf.tensor1d(labels);
105
+
106
+ // Create advanced model
107
+ const newModel = tf.sequential({
108
+ layers: [
109
+ tf.layers.dense({
110
+ inputShape: [6],
111
+ units: 64,
112
+ activation: 'relu',
113
+ kernelRegularizer: tf.regularizers.l2({ l2: 0.001 })
114
+ }),
115
+ tf.layers.dropout({ rate: 0.3 }),
116
+ tf.layers.dense({
117
+ units: 32,
118
+ activation: 'relu',
119
+ kernelRegularizer: tf.regularizers.l2({ l2: 0.001 })
120
+ }),
121
+ tf.layers.dropout({ rate: 0.2 }),
122
+ tf.layers.dense({
123
+ units: 16,
124
+ activation: 'relu'
125
+ }),
126
+ tf.layers.dense({
127
+ units: 1,
128
+ activation: 'sigmoid'
129
+ })
130
+ ]
131
+ });
132
+
133
+ newModel.compile({
134
+ optimizer: tf.train.adam(0.001),
135
+ loss: 'binaryCrossentropy',
136
+ metrics: ['accuracy']
137
+ });
138
+
139
+ // Train model with callbacks
140
+ const history = await newModel.fit(xs, ys, {
141
+ epochs: 80,
142
+ batchSize: 64,
143
+ validationSplit: 0.25,
144
+ callbacks: {
145
+ onEpochEnd: (epoch, logs) => {
146
+ const progress = ((epoch + 1) / 80) * 100;
147
+ setTrainingProgress(progress);
148
+
149
+ setTrainingHistory(prev => [...prev, {
150
+ epoch: epoch + 1,
151
+ accuracy: logs.acc * 100,
152
+ loss: logs.loss,
153
+ valAccuracy: logs.val_acc * 100,
154
+ valLoss: logs.val_loss
155
+ }]);
156
+ }
157
+ }
158
+ });
159
+
160
+ const finalMetrics = {
161
+ accuracy: (history.history.acc[history.history.acc.length - 1] * 100).toFixed(1),
162
+ valAccuracy: (history.history.val_acc[history.history.val_acc.length - 1] * 100).toFixed(1),
163
+ loss: history.history.loss[history.history.loss.length - 1].toFixed(4),
164
+ valLoss: history.history.val_loss[history.history.val_loss.length - 1].toFixed(4)
165
+ };
166
+
167
+ setTrainingMetrics(finalMetrics);
168
+ setModel(newModel);
169
+
170
+ // Generate unpaid invoices
171
+ setUnpaidInvoices(generateUnpaidInvoices());
172
+
173
+ xs.dispose();
174
+ ys.dispose();
175
+
176
+ } catch (error) {
177
+ console.error('Training failed:', error);
178
+ } finally {
179
+ setIsTraining(false);
180
+ }
181
+ };
182
+
183
+ // Make predictions
184
+ const makePredictions = async () => {
185
+ if (!model || unpaidInvoices.length === 0) return;
186
+
187
+ const features = unpaidInvoices.map(invoice => [
188
+ invoice.amount / 100000,
189
+ invoice.daysOverdue / 150,
190
+ invoice.previousDelays / 6,
191
+ invoice.creditScore / 100,
192
+ invoice.industryRisk,
193
+ invoice.seasonality
194
+ ]);
195
+
196
+ const predictionTensor = tf.tensor2d(features);
197
+ const predictionResults = await model.predict(predictionTensor).data();
198
+ predictionTensor.dispose();
199
+
200
+ const predictionsWithData = unpaidInvoices.map((invoice, index) => ({
201
+ ...invoice,
202
+ probability: predictionResults[index],
203
+ prediction: predictionResults[index] > 0.5 ? 'Will Pay' : 'Risk Default',
204
+ riskLevel: predictionResults[index] > 0.7 ? 'Low' : predictionResults[index] > 0.4 ? 'Medium' : 'High'
205
+ }));
206
+
207
+ setPredictions(predictionsWithData);
208
+ };
209
+
210
+ useEffect(() => {
211
+ if (model && unpaidInvoices.length > 0) {
212
+ makePredictions();
213
+ }
214
+ }, [model, unpaidInvoices]);
215
+
216
+ const getRiskColor = (riskLevel) => {
217
+ switch (riskLevel) {
218
+ case 'Low': return 'text-emerald-600 bg-emerald-50';
219
+ case 'Medium': return 'text-amber-600 bg-amber-50';
220
+ case 'High': return 'text-red-600 bg-red-50';
221
+ default: return 'text-gray-600 bg-gray-50';
222
+ }
223
+ };
224
+
225
+ const getProbabilityColor = (prob) => {
226
+ if (prob > 0.7) return 'bg-gradient-to-r from-emerald-400 to-emerald-600';
227
+ if (prob > 0.4) return 'bg-gradient-to-r from-amber-400 to-amber-600';
228
+ return 'bg-gradient-to-r from-red-400 to-red-600';
229
+ };
230
+
231
+ // Dashboard summary statistics
232
+ const dashboardStats = predictions.length > 0 ? {
233
+ totalInvoices: predictions.length,
234
+ totalValue: predictions.reduce((sum, p) => sum + p.amount, 0),
235
+ highRisk: predictions.filter(p => p.riskLevel === 'High').length,
236
+ avgProbability: (predictions.reduce((sum, p) => sum + p.probability, 0) / predictions.length * 100).toFixed(1)
237
+ } : null;
238
+
239
+ const riskDistribution = predictions.length > 0 ? [
240
+ { name: 'Low Risk', value: predictions.filter(p => p.riskLevel === 'Low').length, color: '#10b981' },
241
+ { name: 'Medium Risk', value: predictions.filter(p => p.riskLevel === 'Medium').length, color: '#f59e0b' },
242
+ { name: 'High Risk', value: predictions.filter(p => p.riskLevel === 'High').length, color: '#ef4444' }
243
+ ] : [];
244
+
245
+ return (
246
+ <div className="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900">
247
+ {/* Header */}
248
+ <div className="bg-black/20 backdrop-blur-sm border-b border-white/10">
249
+ <div className="max-w-7xl mx-auto px-6 py-4">
250
+ <div className="flex items-center justify-between">
251
+ <div className="flex items-center space-x-4">
252
+ <div className="p-3 bg-gradient-to-r from-blue-500 to-purple-600 rounded-xl">
253
+ <BarChart3 className="h-8 w-8 text-white" />
254
+ </div>
255
+ <div>
256
+ <h1 className="text-2xl font-bold text-white">SAP Account Receivable Intelligence</h1>
257
+ <p className="text-slate-300">ML-Powered Payment Prediction Platform</p>
258
+ </div>
259
+ </div>
260
+
261
+ {!isTraining && !model && (
262
+ <button
263
+ onClick={trainModel}
264
+ className="flex items-center space-x-2 px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg hover:shadow-xl"
265
+ >
266
+ <Brain className="h-5 w-5" />
267
+ <span>Train AI Model</span>
268
+ </button>
269
+ )}
270
+ </div>
271
+ </div>
272
+ </div>
273
+
274
+ <div className="max-w-7xl mx-auto px-6 py-8">
275
+ {/* Training Section */}
276
+ {(isTraining || model) && (
277
+ <div className="mb-8">
278
+ <div className="bg-white/10 backdrop-blur-md rounded-2xl border border-white/20 p-6">
279
+ <div className="flex items-center justify-between mb-6">
280
+ <h2 className="text-xl font-bold text-white flex items-center space-x-2">
281
+ <Brain className="h-6 w-6 text-blue-400" />
282
+ <span>Neural Network Training</span>
283
+ </h2>
284
+ {model && (
285
+ <div className="flex items-center space-x-2 text-emerald-400">
286
+ <CheckCircle className="h-5 w-5" />
287
+ <span className="font-medium">Model Ready</span>
288
+ </div>
289
+ )}
290
+ </div>
291
+
292
+ {isTraining && (
293
+ <div className="mb-6">
294
+ <div className="flex justify-between items-center mb-2">
295
+ <span className="text-sm text-slate-300">Training Progress</span>
296
+ <span className="text-sm text-slate-300">{trainingProgress.toFixed(1)}%</span>
297
+ </div>
298
+ <div className="w-full bg-slate-700/50 rounded-full h-3">
299
+ <div
300
+ className="bg-gradient-to-r from-blue-500 to-purple-600 h-3 rounded-full transition-all duration-500"
301
+ style={{ width: `${trainingProgress}%` }}
302
+ ></div>
303
+ </div>
304
+ </div>
305
+ )}
306
+
307
+ {trainingMetrics && (
308
+ <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
309
+ <div className="bg-gradient-to-r from-emerald-500/20 to-emerald-600/20 rounded-xl p-4 border border-emerald-500/30">
310
+ <div className="text-2xl font-bold text-emerald-400">{trainingMetrics.accuracy}%</div>
311
+ <div className="text-sm text-slate-300">Training Accuracy</div>
312
+ </div>
313
+ <div className="bg-gradient-to-r from-blue-500/20 to-blue-600/20 rounded-xl p-4 border border-blue-500/30">
314
+ <div className="text-2xl font-bold text-blue-400">{trainingMetrics.valAccuracy}%</div>
315
+ <div className="text-sm text-slate-300">Validation Accuracy</div>
316
+ </div>
317
+ <div className="bg-gradient-to-r from-purple-500/20 to-purple-600/20 rounded-xl p-4 border border-purple-500/30">
318
+ <div className="text-2xl font-bold text-purple-400">{trainingMetrics.loss}</div>
319
+ <div className="text-sm text-slate-300">Training Loss</div>
320
+ </div>
321
+ <div className="bg-gradient-to-r from-pink-500/20 to-pink-600/20 rounded-xl p-4 border border-pink-500/30">
322
+ <div className="text-2xl font-bold text-pink-400">{trainingMetrics.valLoss}</div>
323
+ <div className="text-sm text-slate-300">Validation Loss</div>
324
+ </div>
325
+ </div>
326
+ )}
327
+
328
+ {trainingHistory.length > 0 && (
329
+ <div className="h-64">
330
+ <ResponsiveContainer width="100%" height="100%">
331
+ <LineChart data={trainingHistory}>
332
+ <CartesianGrid strokeDasharray="3 3" stroke="#374151" />
333
+ <XAxis dataKey="epoch" stroke="#9CA3AF" />
334
+ <YAxis stroke="#9CA3AF" />
335
+ <Tooltip
336
+ contentStyle={{
337
+ backgroundColor: '#1F2937',
338
+ border: '1px solid #374151',
339
+ borderRadius: '8px',
340
+ color: '#F3F4F6'
341
+ }}
342
+ />
343
+ <Line type="monotone" dataKey="accuracy" stroke="#10B981" strokeWidth={2} dot={false} />
344
+ <Line type="monotone" dataKey="valAccuracy" stroke="#3B82F6" strokeWidth={2} dot={false} />
345
+ </LineChart>
346
+ </ResponsiveContainer>
347
+ </div>
348
+ )}
349
+ </div>
350
+ </div>
351
+ )}
352
+
353
+ {/* Dashboard Stats */}
354
+ {dashboardStats && (
355
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
356
+ <div className="bg-gradient-to-r from-blue-500/20 to-blue-600/20 rounded-2xl p-6 border border-blue-500/30">
357
+ <div className="flex items-center justify-between">
358
+ <div>
359
+ <p className="text-slate-300 text-sm">Total Invoices</p>
360
+ <p className="text-3xl font-bold text-blue-400">{dashboardStats.totalInvoices}</p>
361
+ </div>
362
+ <Users className="h-8 w-8 text-blue-400" />
363
+ </div>
364
+ </div>
365
+
366
+ <div className="bg-gradient-to-r from-emerald-500/20 to-emerald-600/20 rounded-2xl p-6 border border-emerald-500/30">
367
+ <div className="flex items-center justify-between">
368
+ <div>
369
+ <p className="text-slate-300 text-sm">Total Value</p>
370
+ <p className="text-3xl font-bold text-emerald-400">${(dashboardStats.totalValue / 1000000).toFixed(1)}M</p>
371
+ </div>
372
+ <DollarSign className="h-8 w-8 text-emerald-400" />
373
+ </div>
374
+ </div>
375
+
376
+ <div className="bg-gradient-to-r from-red-500/20 to-red-600/20 rounded-2xl p-6 border border-red-500/30">
377
+ <div className="flex items-center justify-between">
378
+ <div>
379
+ <p className="text-slate-300 text-sm">High Risk</p>
380
+ <p className="text-3xl font-bold text-red-400">{dashboardStats.highRisk}</p>
381
+ </div>
382
+ <AlertTriangle className="h-8 w-8 text-red-400" />
383
+ </div>
384
+ </div>
385
+
386
+ <div className="bg-gradient-to-r from-purple-500/20 to-purple-600/20 rounded-2xl p-6 border border-purple-500/30">
387
+ <div className="flex items-center justify-between">
388
+ <div>
389
+ <p className="text-slate-300 text-sm">Avg. Pay Probability</p>
390
+ <p className="text-3xl font-bold text-purple-400">{dashboardStats.avgProbability}%</p>
391
+ </div>
392
+ <TrendingUp className="h-8 w-8 text-purple-400" />
393
+ </div>
394
+ </div>
395
+ </div>
396
+ )}
397
+
398
+ {/* Tabs */}
399
+ {predictions.length > 0 && (
400
+ <div className="mb-8">
401
+ <div className="flex space-x-1 bg-white/5 p-1 rounded-xl">
402
+ {[
403
+ { key: 'overview', label: 'Overview', icon: BarChart3 },
404
+ { key: 'predictions', label: 'Predictions', icon: Brain },
405
+ { key: 'analytics', label: 'Analytics', icon: TrendingUp }
406
+ ].map(({ key, label, icon: Icon }) => (
407
+ <button
408
+ key={key}
409
+ onClick={() => setActiveTab(key)}
410
+ className={`flex items-center space-x-2 px-4 py-2 rounded-lg transition-all duration-200 ${
411
+ activeTab === key
412
+ ? 'bg-gradient-to-r from-blue-600 to-purple-600 text-white shadow-lg'
413
+ : 'text-slate-300 hover:text-white hover:bg-white/10'
414
+ }`}
415
+ >
416
+ <Icon className="h-4 w-4" />
417
+ <span>{label}</span>
418
+ </button>
419
+ ))}
420
+ </div>
421
+ </div>
422
+ )}
423
+
424
+ {/* Tab Content */}
425
+ {predictions.length > 0 && (
426
+ <div className="space-y-6">
427
+ {activeTab === 'overview' && (
428
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
429
+ <div className="bg-white/10 backdrop-blur-md rounded-2xl border border-white/20 p-6">
430
+ <h3 className="text-lg font-semibold text-white mb-4">Risk Distribution</h3>
431
+ <div className="h-64">
432
+ <ResponsiveContainer width="100%" height="100%">
433
+ <PieChart>
434
+ <Pie
435
+ data={riskDistribution}
436
+ cx="50%"
437
+ cy="50%"
438
+ labelLine={false}
439
+ outerRadius={80}
440
+ fill="#8884d8"
441
+ dataKey="value"
442
+ label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`}
443
+ >
444
+ {riskDistribution.map((entry, index) => (
445
+ <Cell key={`cell-${index}`} fill={entry.color} />
446
+ ))}
447
+ </Pie>
448
+ <Tooltip />
449
+ </PieChart>
450
+ </ResponsiveContainer>
451
+ </div>
452
+ </div>
453
+
454
+ <div className="bg-white/10 backdrop-blur-md rounded-2xl border border-white/20 p-6">
455
+ <h3 className="text-lg font-semibold text-white mb-4">Payment Probability Distribution</h3>
456
+ <div className="h-64">
457
+ <ResponsiveContainer width="100%" height="100%">
458
+ <BarChart data={predictions.slice(0, 10)}>
459
+ <CartesianGrid strokeDasharray="3 3" stroke="#374151" />
460
+ <XAxis dataKey="invoiceId" stroke="#9CA3AF" angle={-45} textAnchor="end" height={80} />
461
+ <YAxis stroke="#9CA3AF" />
462
+ <Tooltip
463
+ contentStyle={{
464
+ backgroundColor: '#1F2937',
465
+ border: '1px solid #374151',
466
+ borderRadius: '8px',
467
+ color: '#F3F4F6'
468
+ }}
469
+ />
470
+ <Bar dataKey="probability" fill="url(#colorGradient)" />
471
+ <defs>
472
+ <linearGradient id="colorGradient" x1="0" y1="0" x2="0" y2="1">
473
+ <stop offset="5%" stopColor="#3B82F6" stopOpacity={0.8}/>
474
+ <stop offset="95%" stopColor="#1D4ED8" stopOpacity={0.8}/>
475
+ </linearGradient>
476
+ </defs>
477
+ </BarChart>
478
+ </ResponsiveContainer>
479
+ </div>
480
+ </div>
481
+ </div>
482
+ )}
483
+
484
+ {activeTab === 'predictions' && (
485
+ <div className="bg-white/10 backdrop-blur-md rounded-2xl border border-white/20 overflow-hidden">
486
+ <div className="p-6 border-b border-white/10">
487
+ <h3 className="text-lg font-semibold text-white">Invoice Payment Predictions</h3>
488
+ <p className="text-slate-300 text-sm mt-1">AI-powered predictions for unpaid invoices</p>
489
+ </div>
490
+
491
+ <div className="overflow-x-auto">
492
+ <table className="w-full">
493
+ <thead className="bg-white/5">
494
+ <tr className="text-left">
495
+ <th className="px-6 py-4 text-sm font-medium text-slate-300">Invoice ID</th>
496
+ <th className="px-6 py-4 text-sm font-medium text-slate-300">Customer</th>
497
+ <th className="px-6 py-4 text-sm font-medium text-slate-300">Amount</th>
498
+ <th className="px-6 py-4 text-sm font-medium text-slate-300">Days Overdue</th>
499
+ <th className="px-6 py-4 text-sm font-medium text-slate-300">Prediction</th>
500
+ <th className="px-6 py-4 text-sm font-medium text-slate-300">Probability</th>
501
+ <th className="px-6 py-4 text-sm font-medium text-slate-300">Risk Level</th>
502
+ </tr>
503
+ </thead>
504
+ <tbody className="divide-y divide-white/10">
505
+ {predictions.map((prediction, index) => (
506
+ <tr key={index} className="hover:bg-white/5 transition-colors">
507
+ <td className="px-6 py-4 text-sm font-mono text-blue-400">{prediction.invoiceId}</td>
508
+ <td className="px-6 py-4 text-sm text-white">{prediction.customer}</td>
509
+ <td className="px-6 py-4 text-sm text-emerald-400 font-semibold">
510
+ ${prediction.amount.toLocaleString()}
511
+ </td>
512
+ <td className="px-6 py-4 text-sm text-slate-300">{prediction.daysOverdue} days</td>
513
+ <td className="px-6 py-4">
514
+ <div className="flex items-center space-x-2">
515
+ {prediction.prediction === 'Will Pay' ? (
516
+ <CheckCircle className="h-4 w-4 text-emerald-500" />
517
+ ) : (
518
+ <XCircle className="h-4 w-4 text-red-500" />
519
+ )}
520
+ <span className={`text-sm font-medium ${
521
+ prediction.prediction === 'Will Pay' ? 'text-emerald-400' : 'text-red-400'
522
+ }`}>
523
+ {prediction.prediction}
524
+ </span>
525
+ </div>
526
+ </td>
527
+ <td className="px-6 py-4">
528
+ <div className="flex items-center space-x-3">
529
+ <div className="flex-1 bg-slate-700 rounded-full h-2">
530
+ <div
531
+ className={`h-2 rounded-full ${getProbabilityColor(prediction.probability)}`}
532
+ style={{ width: `${prediction.probability * 100}%` }}
533
+ ></div>
534
+ </div>
535
+ <span className="text-sm text-slate-300 font-medium min-w-[50px]">
536
+ {(prediction.probability * 100).toFixed(1)}%
537
+ </span>
538
+ </div>
539
+ </td>
540
+ <td className="px-6 py-4">
541
+ <span className={`inline-flex px-2 py-1 rounded-full text-xs font-medium ${getRiskColor(prediction.riskLevel)}`}>
542
+ {prediction.riskLevel} Risk
543
+ </span>
544
+ </td>
545
+ </tr>
546
+ ))}
547
+ </tbody>
548
+ </table>
549
+ </div>
550
+ </div>
551
+ )}
552
+
553
+ {activeTab === 'analytics' && (
554
+ <div className="grid grid-cols-1 gap-6">
555
+ <div className="bg-white/10 backdrop-blur-md rounded-2xl border border-white/20 p-6">
556
+ <h3 className="text-lg font-semibold text-white mb-4">Payment Probability vs Days Overdue</h3>
557
+ <div className="h-80">
558
+ <ResponsiveContainer width="100%" height="100%">
559
+ <LineChart data={predictions.sort((a, b) => a.daysOverdue - b.daysOverdue)}>
560
+ <CartesianGrid strokeDasharray="3 3" stroke="#374151" />
561
+ <XAxis dataKey="daysOverdue" stroke="#9CA3AF" />
562
+ <YAxis stroke="#9CA3AF" domain={[0, 1]} />
563
+ <Tooltip
564
+ contentStyle={{
565
+ backgroundColor: '#1F2937',
566
+ border: '1px solid #374151',
567
+ borderRadius: '8px',
568
+ color: '#F3F4F6'
569
+ }}
570
+ />
571
+ <Line
572
+ type="monotone"
573
+ dataKey="probability"
574
+ stroke="#3B82F6"
575
+ strokeWidth={3}
576
+ dot={{ fill: '#3B82F6', strokeWidth: 2, r: 4 }}
577
+ />
578
+ </LineChart>
579
+ </ResponsiveContainer>
580
+ </div>
581
+ </div>
582
+ </div>
583
+ )}
584
+ </div>
585
+ )}
586
+
587
+ {/* No predictions state */}
588
+ {!isTraining && !model && predictions.length === 0 && (
589
+ <div className="text-center py-16">
590
+ <div className="mb-8">
591
+ <Brain className="h-24 w-24 text-slate-400 mx-auto mb-4" />
592
+ <h3 className="text-2xl font-bold text-white mb-2">Ready to Get Started</h3>
593
+ <p className="text-slate-300 max-w-md mx-auto">
594
+ Train our advanced neural network on synthetic SAP Account Receivable data to predict invoice payment outcomes with high accuracy.
595
+ </p>
596
+ </div>
597
+ </div>
598
+ )}
599
+ </div>
600
+ </div>
601
+ );
602
+ };
603
+
604
+ export default ModernSAPDemo;