File size: 4,862 Bytes
c89a139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import React from 'react';
import { motion } from 'framer-motion';
import { Brain, TrendingUp, AlertTriangle, CheckCircle } from 'lucide-react';

const PredictionCard = ({ predictions, confidence, vertical }) => {
    // Helper to format values based on key
    const formatValue = (key, value) => {
        if (key.includes('amount') || key.includes('impact_usd')) return `$${(value / 1000000).toFixed(1)}M`;
        if (key.includes('days')) return `${value} days`;
        if (key.includes('pct') || key.includes('probability')) return `${value}%`;
        return value;
    };

    // Helper to get confidence color
    const getConfidenceColor = (score) => {
        if (score >= 0.9) return 'text-emerald-500';
        if (score >= 0.7) return 'text-blue-500';
        return 'text-amber-500';
    };

    return (
        <div className="bg-slate-900 border border-slate-800 rounded-xl p-6 shadow-2xl">
            <div className="flex items-center justify-between mb-6">
                <div className="flex items-center gap-3">
                    <div className="p-2 bg-blue-500/10 rounded-lg">
                        <Brain className="w-6 h-6 text-blue-400" />
                    </div>
                    <div>
                        <h3 className="text-lg font-bold text-white">Live ML Predictions</h3>
                        <p className="text-xs text-slate-400 uppercase tracking-wider">Inference Engine v2.1</p>
                    </div>
                </div>
                <div className="flex items-center gap-2">
                    <span className="relative flex h-3 w-3">
                        <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
                        <span className="relative inline-flex rounded-full h-3 w-3 bg-emerald-500"></span>
                    </span>
                    <span className="text-xs font-mono text-emerald-400">LIVE</span>
                </div>
            </div>

            <div className="space-y-4">
                {predictions && Object.entries(predictions).map(([key, value], idx) => {
                    const conf = confidence ? (confidence[key] || 0.85) : 0.85;
                    const confPct = (conf * 100).toFixed(1);

                    return (
                        <motion.div
                            key={key}
                            initial={{ opacity: 0, x: -20 }}
                            animate={{ opacity: 1, x: 0 }}
                            transition={{ delay: idx * 0.1 }}
                            className="bg-slate-800/50 rounded-lg p-4 border border-slate-700/50"
                        >
                            <div className="flex justify-between items-start mb-2">
                                <span className="text-sm text-slate-400 font-medium capitalize">
                                    {key.replace(/_/g, ' ')}
                                </span>
                                <div className={`flex items-center gap-1 text-xs font-mono ${getConfidenceColor(conf)}`}>
                                    <CheckCircle className="w-3 h-3" />
                                    {confPct}% Conf.
                                </div>
                            </div>
                            <div className="flex items-baseline gap-2">
                                <span className="text-2xl font-bold text-white tracking-tight">
                                    {formatValue(key, value)}
                                </span>
                                <span className="text-xs text-slate-500">
                                    (±{(100 - conf * 100).toFixed(1)}% range)
                                </span>
                            </div>

                            {/* Confidence Bar */}
                            <div className="mt-3 h-1.5 bg-slate-700 rounded-full overflow-hidden">
                                <motion.div
                                    initial={{ width: 0 }}
                                    animate={{ width: `${confPct}%` }}
                                    transition={{ duration: 1, delay: 0.5 }}
                                    className={`h-full rounded-full ${conf >= 0.9 ? 'bg-emerald-500' : conf >= 0.7 ? 'bg-blue-500' : 'bg-amber-500'}`}
                                />
                            </div>
                        </motion.div>
                    );
                })}
            </div>

            <div className="mt-6 pt-4 border-t border-slate-800">
                <div className="flex justify-between text-xs text-slate-500 font-mono">
                    <span>MODEL: XGBoost-Pro-v4</span>
                    <span>LATENCY: 42ms</span>
                </div>
            </div>
        </div>
    );
};

export default PredictionCard;