File size: 8,214 Bytes
b8b3edf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

import React, { useState } from 'react';
import { 
  Activity, 
  RefreshCw, 
  Terminal, 
  ShieldCheck, 
  AlertCircle,
  Database,
  Link2,
  X,
  Plus,
  Loader2,
  CheckCircle2,
  MoreVertical
} from 'lucide-react';
import { Connection } from '../types/index.ts';

const MOCK_CONNS: Connection[] = [
  { id: 'CON-101', vendorCustomerId: 'CUST-A992', entity: 'JPM_USA', status: 'CONNECTED', lastSyncedAt: '2024-03-31T12:00:00Z' },
  { id: 'CON-102', vendorCustomerId: 'CUST-D102', entity: 'DB_EURO', status: 'CONNECTED', lastSyncedAt: '2024-03-31T11:55:00Z' },
  { id: 'CON-103', vendorCustomerId: 'CUST-L551', entity: 'LUMINA_INTERNAL', status: 'ERROR', lastSyncedAt: '2024-03-30T22:00:00Z' },
];

const Connectivity: React.FC = () => {
  const [conns, setConns] = useState<Connection[]>(MOCK_CONNS);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [provisioning, setProvisioning] = useState(false);
  const [newVendor, setNewVendor] = useState({ entity: 'STRIPE_GLOBAL', id: 'CUST-X' });

  const handleProvision = () => {
    setProvisioning(true);
    setTimeout(() => {
      const newConn: Connection = {
        id: `CON-${Math.floor(200 + Math.random() * 800)}`,
        vendorCustomerId: newVendor.id,
        entity: newVendor.entity,
        status: 'CONNECTED',
        lastSyncedAt: new Date().toISOString()
      };
      setConns([newConn, ...conns]);
      setProvisioning(false);
      setIsModalOpen(false);
    }, 2000);
  };

  return (
    <div className="space-y-10 animate-in fade-in duration-700 pb-20">
      <div className="flex flex-col md:flex-row justify-between items-start md:items-end gap-6">
        <div>
          <h2 className="text-3xl font-black text-white italic tracking-tighter uppercase mb-2">System <span className="text-blue-500 not-italic">Fabric</span></h2>
          <p className="text-zinc-500 text-[10px] font-black uppercase tracking-[0.3em]">Machine-to-Machine Integration Node Monitoring</p>
        </div>
        <button 
          onClick={() => setIsModalOpen(true)}
          className="flex items-center space-x-2 px-8 py-4 bg-blue-600 hover:bg-blue-500 text-white rounded-[1.8rem] font-black text-[10px] uppercase tracking-widest transition-all shadow-xl shadow-blue-900/40"
        >
          <Link2 size={18} />
          <span>Provision New Vendor</span>
        </button>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
        {conns.map(conn => (
          <div key={conn.id} className="bg-zinc-950 border border-zinc-900 rounded-[3rem] p-10 relative overflow-hidden group hover:border-zinc-700 transition-all shadow-2xl">
            <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-opacity">
              <Database size={100} />
            </div>
            
            <div className="flex justify-between items-start mb-8 relative z-10">
              <div className={`p-4 rounded-2xl ${conn.status === 'CONNECTED' ? 'bg-emerald-500/10 text-emerald-500' : 'bg-rose-500/10 text-rose-500'}`}>
                {conn.status === 'CONNECTED' ? <ShieldCheck size={24} /> : <AlertCircle size={24} />}
              </div>
              <div className="text-right">
                <p className="text-[10px] font-black text-zinc-600 uppercase tracking-widest mb-1">Status</p>
                <p className={`text-xs font-black uppercase tracking-widest ${conn.status === 'CONNECTED' ? 'text-emerald-500' : 'text-rose-500'}`}>{conn.status}</p>
              </div>
            </div>

            <div className="space-y-6 relative z-10">
              <div>
                <h4 className="text-lg font-black text-white uppercase italic tracking-tighter mb-1">{conn.entity}</h4>
                <p className="text-[10px] text-zinc-500 font-mono font-bold uppercase">Vendor ID: {conn.vendorCustomerId}</p>
              </div>
              <div className="h-px bg-zinc-900"></div>
              <div className="flex justify-between items-center text-[10px] font-black uppercase tracking-widest text-zinc-600">
                <span>Handshake ID</span>
                <span className="text-zinc-400 mono">{conn.id}</span>
              </div>
            </div>
            
            <div className="mt-8 pt-8 border-t border-zinc-900 flex justify-between items-center opacity-0 group-hover:opacity-100 transition-opacity">
               <span className="text-[9px] font-black uppercase text-zinc-600 tracking-widest">Last Sync: {new Date(conn.lastSyncedAt).toLocaleTimeString()}</span>
               <button className="text-zinc-500 hover:text-white"><MoreVertical size={16} /></button>
            </div>
          </div>
        ))}
      </div>

      {isModalOpen && (
        <div className="fixed inset-0 z-[150] flex items-center justify-center p-6 backdrop-blur-md bg-black/80">
          <div className="bg-zinc-950 border border-zinc-900 w-full max-w-lg rounded-[3.5rem] p-12 shadow-2xl animate-in zoom-in-95">
            <div className="flex justify-between items-start mb-10">
               <div className="flex items-center gap-4">
                  <div className="w-16 h-16 bg-blue-600/10 text-blue-500 rounded-3xl flex items-center justify-center border border-blue-500/20">
                     <Link2 size={32} />
                  </div>
                  <div>
                    <h3 className="text-2xl font-black text-white italic tracking-tighter uppercase">Vendor <span className="text-blue-500 not-italic">Handshake</span></h3>
                    <p className="text-[10px] text-zinc-500 font-black uppercase tracking-widest">Fabric Extension Module</p>
                  </div>
               </div>
               <button onClick={() => setIsModalOpen(false)} className="p-3 text-zinc-600 hover:text-white transition-colors"><X size={24}/></button>
            </div>

            <div className="space-y-8">
               <div className="space-y-4">
                  <div className="space-y-2">
                    <label className="text-[10px] font-black text-zinc-600 uppercase tracking-widest ml-1">Vendor Provider</label>
                    <input 
                      value={newVendor.entity}
                      onChange={e => setNewVendor({...newVendor, entity: e.target.value})}
                      className="w-full bg-black border border-zinc-800 rounded-2xl py-4 px-6 text-white text-xs outline-none focus:border-blue-500 transition-all font-bold uppercase tracking-widest"
                      placeholder="e.g. STRIPE_US"
                    />
                  </div>
                  <div className="space-y-2">
                    <label className="text-[10px] font-black text-zinc-600 uppercase tracking-widest ml-1">Corporate Client ID</label>
                    <input 
                      value={newVendor.id}
                      onChange={e => setNewVendor({...newVendor, id: e.target.value})}
                      className="w-full bg-black border border-zinc-800 rounded-2xl py-4 px-6 text-white text-xs outline-none focus:border-blue-500 transition-all font-mono"
                      placeholder="CUST-..."
                    />
                  </div>
               </div>

               <div className="p-6 bg-blue-500/5 border border-blue-500/10 rounded-3xl">
                  <p className="text-[10px] font-black text-zinc-500 leading-relaxed uppercase tracking-widest">Establishing a secure tunnel via RSA-OAEP. Metadata persistence will be shredded post-handshake.</p>
               </div>

               <button 
                onClick={handleProvision}
                disabled={provisioning}
                className="w-full py-6 bg-blue-600 hover:bg-blue-500 text-white rounded-[2.2rem] font-black text-[11px] uppercase tracking-[0.4em] transition-all shadow-xl shadow-blue-900/40 flex items-center justify-center gap-4"
               >
                 {provisioning ? <Loader2 className="animate-spin" size={20} /> : <CheckCircle2 size={20} />}
                 {provisioning ? 'FORGING FABRIC...' : 'INITIALIZE Integration'}
               </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default Connectivity;