File size: 9,027 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

import React, { useState } from 'react';
/* Fix: react-router-dom exports may be flaky in this environment, using standard v6 imports */
import { useParams, useNavigate } from 'react-router-dom';
import { 
  ListTree, 
  ArrowLeft, 
  Edit3, 
  Save, 
  X, 
  MoreVertical, 
  Search, 
  Hash, 
  FileText,
  Tag
} from 'lucide-react';
import { LineItem, LineItemUpdateRequest } from '../types/index';

const MOCK_LINE_ITEMS: LineItem[] = [
  { id: 'LI-001', amount: 12000.50, currency: 'USD', description: 'Monthly Compute - Node A', ledger_account_id: 'LED-991', itemizable_id: 'TXN-8821', itemizable_type: 'payment_orders', createdAt: '2024-03-25' },
  { id: 'LI-002', amount: 2500.00, currency: 'USD', description: 'Storage Surcharge - Region East', ledger_account_id: 'LED-992', itemizable_id: 'TXN-8821', itemizable_type: 'payment_orders', createdAt: '2024-03-25' },
  { id: 'LI-003', amount: 30499.50, currency: 'USD', description: 'Quantum Networking Handshake', ledger_account_id: 'LED-991', itemizable_id: 'TXN-8821', itemizable_type: 'payment_orders', createdAt: '2024-03-25' },
];

const LineItems: React.FC = () => {
  const { type, id } = useParams<{ type: string; id: string }>();
  const navigate = useNavigate();
  const [items, setItems] = useState<LineItem[]>(MOCK_LINE_ITEMS);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [editForm, setEditForm] = useState<LineItemUpdateRequest>({});

  const handleEdit = (item: LineItem) => {
    setEditingId(item.id);
    setEditForm({ description: item.description });
  };

  const handleSave = (id: string) => {
    setItems(prev => prev.map(item => item.id === id ? { ...item, ...editForm } : item));
    setEditingId(null);
  };

  return (
    <div className="space-y-10 animate-in fade-in duration-700">
      <div className="flex flex-col md:flex-row justify-between items-start md:items-end gap-6">
        <div className="flex items-center gap-6">
          <button 
            onClick={() => navigate(-1)}
            className="p-3 bg-zinc-900 border border-zinc-800 rounded-2xl text-zinc-500 hover:text-white transition-all"
          >
            <ArrowLeft size={20} />
          </button>
          <div>
            <h2 className="text-3xl font-black text-white italic tracking-tighter uppercase mb-2">Line <span className="text-blue-500 not-italic">Ledger</span></h2>
            <p className="text-zinc-500 text-[10px] font-black uppercase tracking-[0.3em]">
              {type?.replace('_', ' ')} ID: <span className="text-zinc-400 mono">{id}</span>
            </p>
          </div>
        </div>
        <div className="flex gap-4">
          <div className="relative">
            <Search className="absolute left-4 top-1/2 -translate-y-1/2 text-zinc-600" size={14} />
            <input 
              placeholder="Search Items..."
              className="bg-black border border-zinc-800 rounded-xl py-2 pl-10 pr-4 text-[10px] font-black uppercase tracking-widest text-white outline-none focus:border-blue-500/50 transition-all w-64"
            />
          </div>
        </div>
      </div>

      <div className="bg-zinc-950 border border-zinc-900 rounded-[3rem] overflow-hidden shadow-2xl">
        <div className="p-10 border-b border-zinc-900 flex justify-between items-center bg-black/20">
          <div className="flex items-center space-x-4">
            <div className="p-3 bg-blue-500/10 text-blue-500 rounded-2xl">
              <ListTree size={20} />
            </div>
            <h3 className="text-white font-black uppercase tracking-[0.2em] italic">Granular Breakdown</h3>
          </div>
        </div>

        <div className="overflow-x-auto">
          <table className="w-full text-left">
            <thead>
              <tr className="border-b border-zinc-900 bg-black/40 text-[9px] font-black uppercase tracking-[0.3em] text-zinc-500">
                <th className="px-10 py-5">Item Detail</th>
                <th className="py-5">Ledger Mapping</th>
                <th className="py-5">Created At</th>
                <th className="py-5 text-right">Amount (USD)</th>
                <th className="px-10 py-5 text-right">Actions</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-zinc-900/50">
              {items.map(item => (
                <tr key={item.id} className="group hover:bg-white/[0.01] transition-colors">
                  <td className="px-10 py-8">
                    <div className="flex items-center gap-4">
                      <div className="w-10 h-10 rounded-xl bg-zinc-900 border border-zinc-800 flex items-center justify-center text-zinc-500 group-hover:text-blue-400 transition-colors">
                        <Tag size={18} />
                      </div>
                      <div className="flex-1 min-w-[300px]">
                        {editingId === item.id ? (
                          <input 
                            value={editForm.description}
                            onChange={e => setEditForm({ ...editForm, description: e.target.value })}
                            className="w-full bg-black border border-zinc-800 rounded-lg px-3 py-1 text-xs text-white outline-none focus:border-blue-500/50"
                            autoFocus
                          />
                        ) : (
                          <p className="text-white font-black text-xs uppercase italic">{item.description}</p>
                        )}
                        <p className="text-[10px] text-zinc-600 font-mono font-bold mt-1 uppercase tracking-tighter">ID: {item.id}</p>
                      </div>
                    </div>
                  </td>
                  <td className="py-8">
                    <div className="flex items-center gap-2">
                      <Hash size={12} className="text-zinc-600" />
                      <p className="text-[10px] font-black text-zinc-400 uppercase tracking-widest">{item.ledger_account_id}</p>
                    </div>
                  </td>
                  <td className="py-8">
                    <p className="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">{item.createdAt}</p>
                  </td>
                  <td className="py-8 text-right">
                    <p className="text-sm font-black text-white mono tracking-tighter">${item.amount.toLocaleString(undefined, { minimumFractionDigits: 2 })}</p>
                    <p className="text-[9px] text-zinc-600 font-bold uppercase mt-1">{item.currency}</p>
                  </td>
                  <td className="px-10 py-8 text-right">
                    <div className="flex items-center justify-end gap-3">
                      {editingId === item.id ? (
                        <>
                          <button onClick={() => handleSave(item.id)} className="p-2 text-emerald-500 hover:text-emerald-400 transition-colors">
                            <Save size={18} />
                          </button>
                          <button onClick={() => setEditingId(null)} className="p-2 text-rose-500 hover:text-rose-400 transition-colors">
                            <X size={18} />
                          </button>
                        </>
                      ) : (
                        <div className="flex items-center justify-end gap-3 opacity-0 group-hover:opacity-100 transition-opacity">
                          <button onClick={() => handleEdit(item)} className="p-2 text-zinc-500 hover:text-white" title="Update Line Item">
                            <Edit3 size={16} />
                          </button>
                          <button className="p-2 text-zinc-500 hover:text-white"><MoreVertical size={16} /></button>
                        </div>
                      )}
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <div className="bg-zinc-900/50 border border-zinc-800 p-10 rounded-[2.5rem] flex flex-col md:flex-row justify-between items-center gap-8">
        <div className="flex items-center gap-6">
          <div className="p-4 bg-zinc-800 rounded-2xl text-zinc-400">
            <FileText size={24} />
          </div>
          <div>
            <h4 className="text-white font-black text-sm uppercase tracking-widest mb-1 italic">Total Aggregate</h4>
            <p className="text-zinc-500 text-[10px] font-bold uppercase tracking-widest">Calculated from {items.length} granular entries</p>
          </div>
        </div>
        <div className="text-right">
          <p className="text-3xl font-black text-white mono tracking-tighter">
            ${items.reduce((sum, i) => sum + i.amount, 0).toLocaleString(undefined, { minimumFractionDigits: 2 })}
          </p>
          <p className="text-[10px] font-black text-blue-500 uppercase tracking-widest mt-1">Verified Audit Payload</p>
        </div>
      </div>
    </div>
  );
};

export default LineItems;