File size: 4,258 Bytes
2ecc4a7
dc7b682
2ecc4a7
 
 
 
 
 
dc7b682
 
 
 
 
 
 
 
 
 
 
 
2ecc4a7
 
dc7b682
2ecc4a7
 
 
 
dc7b682
2ecc4a7
dc7b682
 
2ecc4a7
dc7b682
 
2ecc4a7
dc7b682
2ecc4a7
 
dc7b682
2ecc4a7
 
dc7b682
 
 
 
 
 
 
 
 
 
 
2ecc4a7
dc7b682
 
 
 
 
2ecc4a7
dc7b682
 
 
 
 
 
 
 
 
 
 
 
 
 
2ecc4a7
 
 
 
 
 
 
 
 
dc7b682
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
import React from 'react';
import { CheckCircle2, CircleDashed, AlertCircle, Code, Layers, FileText } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';

export default function PipelineVisualizer({ steps }) {
  if (!steps || steps.length === 0) return null;

  return (
    <div className="mt-8 space-y-4">
      <div className="flex items-center justify-between border-b border-surface-800 pb-3">
        <div className="flex items-center gap-2">
          <div className="w-2.5 h-2.5 bg-green-500 rounded-full animate-pulse shadow-[0_0_8px_rgba(34,197,94,0.6)]" />
          <h2 className="text-lg font-bold uppercase tracking-wider text-gray-200 flex items-center gap-2">
            <Layers className="w-5 h-5 text-accent-400" />
            A-to-Z Execution Trace & Index Log
          </h2>
        </div>
        <span className="text-xs font-mono font-bold bg-surface-800 text-gray-400 px-2.5 py-1 rounded-full border border-surface-700">
          {steps.length} Steps Recorded
        </span>
      </div>
      
      <div className="space-y-3">
        <AnimatePresence initial={false}>
          {steps.map((step, i) => (
            <motion.div
              key={i}
              initial={{ opacity: 0, x: -15 }}
              animate={{ opacity: 1, x: 0 }}
              className="flex items-start gap-4 p-4 rounded-2xl bg-surface-900/80 border border-surface-800 hover:border-surface-700 transition-all shadow-sm"
              style={{ borderLeftColor: step.color || '#8b5cf6', borderLeftWidth: '4px' }}
            >
              <div className="mt-1 flex items-center justify-center shrink-0">
                {step.status === 'done' || step.step === 'RETRIEVAL_COMPLETE' || step.step === 'DONE' ? (
                  <CheckCircle2 className="w-5 h-5 text-green-500" />
                ) : step.status === 'error' || step.step === 'ERROR' ? (
                  <AlertCircle className="w-5 h-5 text-red-500" />
                ) : (
                  <CircleDashed className="w-5 h-5 animate-spin text-accent-400" />
                )}
              </div>

              <div className="flex-1 space-y-2">
                <div className="flex flex-wrap justify-between items-center gap-2">
                  <div className="flex items-center gap-2">
                    <span className="text-xs font-mono font-bold px-2 py-0.5 rounded bg-surface-800 border border-surface-700" style={{ color: step.color || '#8b5cf6' }}>
                      STEP {i + 1}: {step.step}
                    </span>
                  </div>
                  <span className="text-[10px] text-gray-500 font-mono">
                    {step.timestamp ? new Date(step.timestamp).toLocaleTimeString() : new Date().toLocaleTimeString()}
                  </span>
                </div>

                <p className="text-xs text-gray-200 leading-relaxed font-medium">
                  {step.detail}
                </p>

                {step.metadata && Object.keys(step.metadata).length > 0 && (
                  <div className="mt-2 bg-black/40 border border-surface-800 rounded-xl p-3 space-y-1">
                    <div className="flex items-center gap-1.5 text-[10px] font-mono text-gray-400 uppercase font-bold border-b border-surface-800 pb-1 mb-2">
                      <Code className="w-3 h-3 text-accent-400" />
                      <span>Execution Parameters & Storage Metadata</span>
                    </div>
                    <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 text-[11px] font-mono">
                      {Object.entries(step.metadata).map(([key, val]) => (
                        <div key={key} className="flex items-start gap-2 bg-surface-900/60 p-1.5 rounded border border-surface-800/40">
                          <span className="text-accent-400 font-semibold shrink-0">{key}:</span>
                          <span className="text-gray-300 truncate font-mono">{typeof val === 'object' ? JSON.stringify(val) : String(val)}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            </motion.div>
          ))}
        </AnimatePresence>
      </div>
    </div>
  );
}