transactions-mfe 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1155 @@
1
+ "use client";
2
+ import { useState, useCallback, useEffect } from 'react';
3
+ import Link from 'next/link';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+ import { useRouter, useParams, usePathname } from 'next/navigation';
6
+
7
+ // app/page.tsx
8
+ var COIN_STYLES = {
9
+ btc: { bg: "rgba(217,119,6,0.10)", color: "#b45309", border: "rgba(217,119,6,0.20)" },
10
+ bitcoin: { bg: "rgba(217,119,6,0.10)", color: "#b45309", border: "rgba(217,119,6,0.20)" },
11
+ eth: { bg: "rgba(79,70,229,0.10)", color: "#4338ca", border: "rgba(79,70,229,0.20)" },
12
+ ethereum: { bg: "rgba(79,70,229,0.10)", color: "#4338ca", border: "rgba(79,70,229,0.20)" },
13
+ sol: { bg: "rgba(124,58,237,0.10)", color: "#6d28d9", border: "rgba(124,58,237,0.20)" },
14
+ solana: { bg: "rgba(124,58,237,0.10)", color: "#6d28d9", border: "rgba(124,58,237,0.20)" },
15
+ usdt: { bg: "rgba(5,150,105,0.10)", color: "#047857", border: "rgba(5,150,105,0.20)" },
16
+ usdc: { bg: "rgba(2,132,199,0.10)", color: "#0369a1", border: "rgba(2,132,199,0.20)" },
17
+ bnb: { bg: "rgba(202,138,4,0.10)", color: "#a16207", border: "rgba(202,138,4,0.20)" },
18
+ xrp: { bg: "rgba(37,99,235,0.10)", color: "#1d4ed8", border: "rgba(37,99,235,0.20)" },
19
+ doge: { bg: "rgba(234,88,12,0.10)", color: "#c2410c", border: "rgba(234,88,12,0.20)" }
20
+ };
21
+ var DEFAULT_COIN = { bg: "rgba(145,158,171,0.12)", color: "#637381", border: "rgba(145,158,171,0.24)" };
22
+ var CoinBadge = ({ coin }) => {
23
+ const s = COIN_STYLES[coin.toLowerCase()] ?? DEFAULT_COIN;
24
+ return /* @__PURE__ */ jsx(
25
+ "span",
26
+ {
27
+ className: "inline-flex items-center text-[11px] font-bold px-2.5 py-0.5 rounded-full",
28
+ style: { backgroundColor: s.bg, color: s.color, border: `1px solid ${s.border}`, letterSpacing: "0.05em" },
29
+ children: coin.toUpperCase()
30
+ }
31
+ );
32
+ };
33
+ var GRADIENTS = [
34
+ "linear-gradient(135deg,#6366f1,#4f46e5)",
35
+ "linear-gradient(135deg,#a78bfa,#7c3aed)",
36
+ "linear-gradient(135deg,#38bdf8,#0284c7)",
37
+ "linear-gradient(135deg,#34d399,#059669)",
38
+ "linear-gradient(135deg,#fb7185,#e11d48)",
39
+ "linear-gradient(135deg,#fbbf24,#d97706)"
40
+ ];
41
+ var Avatar = ({ name }) => {
42
+ const ch = name?.charAt(0)?.toUpperCase() ?? "?";
43
+ const g = GRADIENTS[(ch.charCodeAt(0) - 65) % GRADIENTS.length];
44
+ return /* @__PURE__ */ jsx(
45
+ "div",
46
+ {
47
+ className: "w-8 h-8 rounded-full flex items-center justify-center text-white text-xs font-bold shrink-0",
48
+ style: { background: g, boxShadow: "0 3px 6px rgba(0,0,0,0.12)" },
49
+ children: ch
50
+ }
51
+ );
52
+ };
53
+ var Skeleton = () => /* @__PURE__ */ jsx("div", { className: "animate-pulse", children: [1, 2, 3, 4, 5, 6].map((i) => /* @__PURE__ */ jsxs(
54
+ "div",
55
+ {
56
+ className: "flex items-center gap-4 px-6 py-4",
57
+ style: { borderBottom: "1px solid rgba(145,158,171,0.12)" },
58
+ children: [
59
+ /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-gray-200 shrink-0" }),
60
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-4 bg-gray-200 rounded w-28" }),
61
+ /* @__PURE__ */ jsx("div", { className: "h-5 bg-gray-100 rounded-full w-14" }),
62
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-100 rounded w-20 ml-auto" }),
63
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-100 rounded w-24" }),
64
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
65
+ /* @__PURE__ */ jsx("div", { className: "w-7 h-7 bg-gray-100 rounded-lg" }),
66
+ /* @__PURE__ */ jsx("div", { className: "w-7 h-7 bg-gray-100 rounded-lg" })
67
+ ] })
68
+ ]
69
+ },
70
+ i
71
+ )) });
72
+ function TransactionsPage() {
73
+ const [transactions, setTransactions] = useState([]);
74
+ const [loading, setLoading] = useState(true);
75
+ const [error, setError] = useState(null);
76
+ const [deletingId, setDeletingId] = useState(null);
77
+ const [filterCoin, setFilterCoin] = useState("");
78
+ const [filterUser, setFilterUser] = useState("");
79
+ const API = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3000";
80
+ const load = useCallback(async () => {
81
+ setLoading(true);
82
+ setError(null);
83
+ try {
84
+ const res = await fetch(`${API}/api/transactions`);
85
+ if (!res.ok) throw new Error(`Error ${res.status}`);
86
+ const data = await res.json();
87
+ setTransactions(data);
88
+ } catch (e) {
89
+ setError(e instanceof Error ? e.message : "Error desconocido");
90
+ } finally {
91
+ setLoading(false);
92
+ }
93
+ }, [API]);
94
+ useEffect(() => {
95
+ load();
96
+ }, [load]);
97
+ const handleDelete = async (id) => {
98
+ if (!confirm("\xBFEliminar esta transacci\xF3n? Esta acci\xF3n no se puede deshacer.")) return;
99
+ setDeletingId(id);
100
+ try {
101
+ const res = await fetch(`${API}/api/transactions/${id}`, { method: "DELETE" });
102
+ if (!res.ok) throw new Error("No se pudo eliminar");
103
+ setTransactions((prev) => prev.filter((t) => t._id !== id));
104
+ } catch (e) {
105
+ alert(e instanceof Error ? e.message : "Error al eliminar");
106
+ } finally {
107
+ setDeletingId(null);
108
+ }
109
+ };
110
+ const filtered = transactions.filter((t) => {
111
+ const matchCoin = !filterCoin || t.coin.toLowerCase().includes(filterCoin.toLowerCase());
112
+ const matchUser = !filterUser || t.user.toLowerCase().includes(filterUser.toLowerCase());
113
+ return matchCoin && matchUser;
114
+ });
115
+ const coins = [...new Set(transactions.map((t) => t.coin))].sort();
116
+ const formatDate = (iso) => new Date(iso).toLocaleDateString("es-MX", { day: "numeric", month: "short", year: "numeric" });
117
+ const formatTime = (iso) => new Date(iso).toLocaleTimeString("es-MX", { hour: "2-digit", minute: "2-digit" });
118
+ return /* @__PURE__ */ jsxs("div", { className: "p-6 space-y-5", children: [
119
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
120
+ /* @__PURE__ */ jsxs(
121
+ "select",
122
+ {
123
+ value: filterCoin,
124
+ onChange: (e) => setFilterCoin(e.target.value),
125
+ className: "text-sm px-3 py-2 rounded-lg transition-all outline-none",
126
+ style: {
127
+ border: "1px solid var(--border)",
128
+ backgroundColor: "white",
129
+ color: "var(--text-primary)",
130
+ minWidth: 140
131
+ },
132
+ children: [
133
+ /* @__PURE__ */ jsx("option", { value: "", children: "Todas las monedas" }),
134
+ coins.map((c) => /* @__PURE__ */ jsx("option", { value: c, children: c.toUpperCase() }, c))
135
+ ]
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsx(
139
+ "input",
140
+ {
141
+ type: "text",
142
+ value: filterUser,
143
+ onChange: (e) => setFilterUser(e.target.value),
144
+ placeholder: "Buscar usuario...",
145
+ className: "text-sm px-3 py-2 rounded-lg transition-all outline-none",
146
+ style: {
147
+ border: "1px solid var(--border)",
148
+ backgroundColor: "white",
149
+ color: "var(--text-primary)",
150
+ minWidth: 180
151
+ }
152
+ }
153
+ ),
154
+ !loading && /* @__PURE__ */ jsxs("span", { className: "text-xs ml-1", style: { color: "var(--text-disabled)" }, children: [
155
+ filtered.length,
156
+ " de ",
157
+ transactions.length,
158
+ " transacciones"
159
+ ] }),
160
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
161
+ /* @__PURE__ */ jsx(
162
+ "button",
163
+ {
164
+ onClick: load,
165
+ disabled: loading,
166
+ className: "w-9 h-9 rounded-lg flex items-center justify-center transition-all duration-150",
167
+ style: { backgroundColor: "white", border: "1px solid var(--border)", color: "var(--text-secondary)" },
168
+ title: "Refrescar",
169
+ children: /* @__PURE__ */ jsxs(
170
+ "svg",
171
+ {
172
+ width: "16",
173
+ height: "16",
174
+ viewBox: "0 0 24 24",
175
+ fill: "none",
176
+ stroke: "currentColor",
177
+ strokeWidth: "2",
178
+ className: loading ? "animate-spin" : "",
179
+ children: [
180
+ /* @__PURE__ */ jsx("polyline", { points: "23 4 23 10 17 10" }),
181
+ /* @__PURE__ */ jsx("polyline", { points: "1 20 1 14 7 14" }),
182
+ /* @__PURE__ */ jsx("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })
183
+ ]
184
+ }
185
+ )
186
+ }
187
+ ),
188
+ /* @__PURE__ */ jsxs(
189
+ Link,
190
+ {
191
+ href: "/new",
192
+ className: "inline-flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-bold text-white transition-all duration-200",
193
+ style: {
194
+ background: "linear-gradient(135deg, #6366f1 0%, #4f46e5 100%)",
195
+ boxShadow: "0 8px 16px 0 rgba(79,70,229,0.28)",
196
+ letterSpacing: "0.03em"
197
+ },
198
+ children: [
199
+ /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [
200
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
201
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
202
+ ] }),
203
+ "Nueva Transacci\xF3n"
204
+ ]
205
+ }
206
+ )
207
+ ] }),
208
+ /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl overflow-hidden", style: { boxShadow: "var(--shadow-card)" }, children: [
209
+ /* @__PURE__ */ jsxs(
210
+ "div",
211
+ {
212
+ className: "px-6 py-4 flex items-center justify-between",
213
+ style: { borderBottom: "1px solid rgba(145,158,171,0.16)" },
214
+ children: [
215
+ /* @__PURE__ */ jsxs("div", { children: [
216
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-bold", style: { color: "var(--text-primary)" }, children: "Historial de Transacciones" }),
217
+ /* @__PURE__ */ jsxs("p", { className: "text-xs mt-0.5", style: { color: "var(--text-secondary)" }, children: [
218
+ "CRUD completo \xB7 Llamando a ",
219
+ API,
220
+ "/api/transactions"
221
+ ] })
222
+ ] }),
223
+ !loading && !error && /* @__PURE__ */ jsxs(
224
+ "div",
225
+ {
226
+ className: "flex items-center gap-1.5 text-xs font-semibold px-2.5 py-1 rounded-full",
227
+ style: { backgroundColor: "rgba(34,197,94,0.10)", color: "#16a34a", border: "1px solid rgba(34,197,94,0.24)" },
228
+ children: [
229
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-green-500 animate-pulse" }),
230
+ "API conectada"
231
+ ]
232
+ }
233
+ )
234
+ ]
235
+ }
236
+ ),
237
+ loading && /* @__PURE__ */ jsx(Skeleton, {}),
238
+ !loading && error && /* @__PURE__ */ jsxs("div", { className: "px-6 py-12 text-center", children: [
239
+ /* @__PURE__ */ jsx(
240
+ "div",
241
+ {
242
+ className: "w-14 h-14 rounded-full mx-auto mb-3 flex items-center justify-center",
243
+ style: { backgroundColor: "rgba(239,68,68,0.08)" },
244
+ children: /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#dc2626", strokeWidth: "2", children: [
245
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
246
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
247
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
248
+ ] })
249
+ }
250
+ ),
251
+ /* @__PURE__ */ jsx("p", { className: "font-semibold mb-1", style: { color: "#dc2626" }, children: error }),
252
+ /* @__PURE__ */ jsxs("p", { className: "text-xs mb-4", style: { color: "var(--text-secondary)" }, children: [
253
+ "Verifica que el servidor principal est\xE9 corriendo en ",
254
+ API
255
+ ] }),
256
+ /* @__PURE__ */ jsx(
257
+ "button",
258
+ {
259
+ onClick: load,
260
+ className: "px-4 py-2 rounded-lg text-sm font-semibold text-white",
261
+ style: { background: "var(--primary)" },
262
+ children: "Reintentar"
263
+ }
264
+ )
265
+ ] }),
266
+ !loading && !error && filtered.length === 0 && /* @__PURE__ */ jsxs("div", { className: "px-6 py-14 text-center", children: [
267
+ /* @__PURE__ */ jsx(
268
+ "div",
269
+ {
270
+ className: "w-14 h-14 rounded-full mx-auto mb-3 flex items-center justify-center",
271
+ style: { backgroundColor: "rgba(145,158,171,0.08)" },
272
+ children: /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "var(--text-disabled)", strokeWidth: "1.5", children: /* @__PURE__ */ jsx("path", { d: "M12 2v20M17 5H9.5a3.5 3.5 0 1 0 0 7h5a3.5 3.5 0 1 1 0 7H6" }) })
273
+ }
274
+ ),
275
+ /* @__PURE__ */ jsx("p", { className: "font-semibold", style: { color: "var(--text-primary)" }, children: transactions.length === 0 ? "Sin transacciones" : "Sin resultados para los filtros aplicados" }),
276
+ transactions.length === 0 && /* @__PURE__ */ jsx(
277
+ Link,
278
+ {
279
+ href: "/new",
280
+ className: "inline-block mt-4 px-4 py-2 rounded-lg text-sm font-semibold text-white",
281
+ style: { background: "var(--primary)" },
282
+ children: "Crear primera transacci\xF3n"
283
+ }
284
+ )
285
+ ] }),
286
+ !loading && !error && filtered.length > 0 && /* @__PURE__ */ jsxs("div", { className: "overflow-x-auto", children: [
287
+ /* @__PURE__ */ jsxs("table", { className: "w-full text-sm min-w-[700px]", children: [
288
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { style: { backgroundColor: "#F4F6F8", borderBottom: "1px solid rgba(145,158,171,0.24)" }, children: ["Usuario", "Moneda", "Monto", "Fecha", "Acciones"].map((h, i) => /* @__PURE__ */ jsx(
289
+ "th",
290
+ {
291
+ className: "px-6 py-3 text-xs font-semibold uppercase tracking-[0.08em]",
292
+ style: {
293
+ color: "var(--text-secondary)",
294
+ textAlign: i >= 2 ? i === 4 ? "center" : "right" : "left"
295
+ },
296
+ children: h
297
+ },
298
+ h
299
+ )) }) }),
300
+ /* @__PURE__ */ jsx("tbody", { children: filtered.map((tx, idx) => {
301
+ const isLast = idx === filtered.length - 1;
302
+ return /* @__PURE__ */ jsxs(
303
+ "tr",
304
+ {
305
+ className: "transition-colors",
306
+ style: { borderBottom: isLast ? "none" : "1px solid rgba(145,158,171,0.10)" },
307
+ onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "rgba(145,158,171,0.04)",
308
+ onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "transparent",
309
+ children: [
310
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-3.5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
311
+ /* @__PURE__ */ jsx(Avatar, { name: tx.user }),
312
+ /* @__PURE__ */ jsx(
313
+ "span",
314
+ {
315
+ className: "font-medium truncate max-w-[140px]",
316
+ style: { color: "var(--text-primary)" },
317
+ children: tx.user
318
+ }
319
+ )
320
+ ] }) }),
321
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-3.5", children: /* @__PURE__ */ jsx(CoinBadge, { coin: tx.coin }) }),
322
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-3.5 text-right", children: /* @__PURE__ */ jsx(
323
+ "span",
324
+ {
325
+ className: "font-semibold font-mono text-sm",
326
+ style: { color: "var(--text-primary)" },
327
+ children: typeof tx.amount === "number" ? tx.amount.toLocaleString("en-US", { maximumFractionDigits: 6 }) : tx.amount
328
+ }
329
+ ) }),
330
+ /* @__PURE__ */ jsxs("td", { className: "px-6 py-3.5 text-right", children: [
331
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium", style: { color: "var(--text-primary)" }, children: formatDate(tx.createdAt) }),
332
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] mt-0.5", style: { color: "var(--text-disabled)" }, children: formatTime(tx.createdAt) })
333
+ ] }),
334
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-3.5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1.5", children: [
335
+ /* @__PURE__ */ jsx(
336
+ Link,
337
+ {
338
+ href: `/edit/${tx._id}`,
339
+ className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all duration-150",
340
+ style: { color: "var(--text-secondary)", border: "1px solid var(--border)" },
341
+ onMouseEnter: (e) => {
342
+ const el = e.currentTarget;
343
+ el.style.backgroundColor = "rgba(79,70,229,0.08)";
344
+ el.style.borderColor = "rgba(79,70,229,0.30)";
345
+ el.style.color = "var(--primary)";
346
+ },
347
+ onMouseLeave: (e) => {
348
+ const el = e.currentTarget;
349
+ el.style.backgroundColor = "transparent";
350
+ el.style.borderColor = "var(--border)";
351
+ el.style.color = "var(--text-secondary)";
352
+ },
353
+ title: "Editar",
354
+ children: /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
355
+ /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
356
+ /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
357
+ ] })
358
+ }
359
+ ),
360
+ /* @__PURE__ */ jsx(
361
+ "button",
362
+ {
363
+ onClick: () => handleDelete(tx._id),
364
+ disabled: deletingId === tx._id,
365
+ className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all duration-150",
366
+ style: { color: "var(--text-secondary)", border: "1px solid var(--border)" },
367
+ onMouseEnter: (e) => {
368
+ const el = e.currentTarget;
369
+ el.style.backgroundColor = "rgba(239,68,68,0.08)";
370
+ el.style.borderColor = "rgba(239,68,68,0.30)";
371
+ el.style.color = "#dc2626";
372
+ },
373
+ onMouseLeave: (e) => {
374
+ const el = e.currentTarget;
375
+ el.style.backgroundColor = "transparent";
376
+ el.style.borderColor = "var(--border)";
377
+ el.style.color = "var(--text-secondary)";
378
+ },
379
+ title: "Eliminar",
380
+ children: deletingId === tx._id ? /* @__PURE__ */ jsx("span", { className: "w-3 h-3 border-2 border-gray-300 border-t-red-500 rounded-full animate-spin" }) : /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
381
+ /* @__PURE__ */ jsx("polyline", { points: "3 6 5 6 21 6" }),
382
+ /* @__PURE__ */ jsx("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
383
+ /* @__PURE__ */ jsx("path", { d: "M10 11v6M14 11v6" }),
384
+ /* @__PURE__ */ jsx("path", { d: "M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" })
385
+ ] })
386
+ }
387
+ )
388
+ ] }) })
389
+ ]
390
+ },
391
+ tx._id
392
+ );
393
+ }) })
394
+ ] }),
395
+ /* @__PURE__ */ jsxs(
396
+ "div",
397
+ {
398
+ className: "px-6 py-3 flex items-center justify-between",
399
+ style: { borderTop: "1px solid rgba(145,158,171,0.16)", backgroundColor: "#FAFAFA" },
400
+ children: [
401
+ /* @__PURE__ */ jsxs("p", { className: "text-xs", style: { color: "var(--text-disabled)" }, children: [
402
+ filtered.length,
403
+ " ",
404
+ filtered.length === 1 ? "transacci\xF3n" : "transacciones",
405
+ filterCoin || filterUser ? ` (filtradas de ${transactions.length})` : " en total"
406
+ ] }),
407
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
408
+ /* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-green-500 animate-pulse" }),
409
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium", style: { color: "var(--text-secondary)" }, children: API })
410
+ ] })
411
+ ]
412
+ }
413
+ )
414
+ ] })
415
+ ] })
416
+ ] });
417
+ }
418
+ var COINS = [
419
+ { value: "BTC", label: "Bitcoin (BTC)" },
420
+ { value: "ETH", label: "Ethereum (ETH)" },
421
+ { value: "SOL", label: "Solana (SOL)" },
422
+ { value: "BNB", label: "BNB Chain (BNB)" },
423
+ { value: "XRP", label: "XRP" },
424
+ { value: "USDT", label: "Tether (USDT)" },
425
+ { value: "USDC", label: "USD Coin (USDC)" },
426
+ { value: "DOGE", label: "Dogecoin (DOGE)" },
427
+ { value: "ADA", label: "Cardano (ADA)" },
428
+ { value: "MATIC", label: "Polygon (MATIC)" }
429
+ ];
430
+ var Field = ({
431
+ id,
432
+ label,
433
+ children,
434
+ hint
435
+ }) => /* @__PURE__ */ jsxs("div", { children: [
436
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
437
+ /* @__PURE__ */ jsx(
438
+ "label",
439
+ {
440
+ htmlFor: id,
441
+ className: "text-xs font-semibold",
442
+ style: { color: "var(--text-secondary)" },
443
+ children: label
444
+ }
445
+ ),
446
+ hint && /* @__PURE__ */ jsx("span", { className: "text-[10px]", style: { color: "var(--text-disabled)" }, children: hint })
447
+ ] }),
448
+ children
449
+ ] });
450
+ function NewTransactionPage() {
451
+ const router = useRouter();
452
+ const API = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3000";
453
+ const [user, setUser] = useState("");
454
+ const [coin, setCoin] = useState("BTC");
455
+ const [amount, setAmount] = useState("");
456
+ const [loading, setLoading] = useState(false);
457
+ const [error, setError] = useState(null);
458
+ const [success, setSuccess] = useState(false);
459
+ const inputStyle = (focused) => ({
460
+ width: "100%",
461
+ padding: focused ? "11px 13px" : "12px 14px",
462
+ border: `${focused ? 2 : 1}px solid ${focused ? "var(--primary)" : "var(--border)"}`,
463
+ borderRadius: 8,
464
+ fontSize: "0.875rem",
465
+ color: "var(--text-primary)",
466
+ backgroundColor: "white",
467
+ boxShadow: focused ? "0 0 0 3px rgba(79,70,229,0.08)" : "none",
468
+ outline: "none",
469
+ transition: "all 0.2s"
470
+ });
471
+ const [focusedField, setFocusedField] = useState(null);
472
+ const handleSubmit = async (e) => {
473
+ e.preventDefault();
474
+ if (!user.trim()) {
475
+ setError("El nombre de usuario es requerido");
476
+ return;
477
+ }
478
+ if (!coin) {
479
+ setError("Selecciona una moneda");
480
+ return;
481
+ }
482
+ if (!amount || isNaN(Number(amount)) || Number(amount) <= 0) {
483
+ setError("Ingresa un monto v\xE1lido mayor a 0");
484
+ return;
485
+ }
486
+ setLoading(true);
487
+ setError(null);
488
+ try {
489
+ const res = await fetch(`${API}/api/transactions`, {
490
+ method: "POST",
491
+ headers: { "Content-Type": "application/json" },
492
+ body: JSON.stringify({ user: user.trim(), coin, amount: Number(amount) })
493
+ });
494
+ if (!res.ok) {
495
+ const data = await res.json().catch(() => ({}));
496
+ throw new Error(data.message ?? `Error ${res.status}`);
497
+ }
498
+ setSuccess(true);
499
+ setTimeout(() => router.push("/"), 1200);
500
+ } catch (err) {
501
+ setError(err instanceof Error ? err.message : "Error al crear la transacci\xF3n");
502
+ } finally {
503
+ setLoading(false);
504
+ }
505
+ };
506
+ if (success) {
507
+ return /* @__PURE__ */ jsx("div", { className: "p-6 flex items-center justify-center min-h-[60vh]", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
508
+ /* @__PURE__ */ jsx(
509
+ "div",
510
+ {
511
+ className: "w-16 h-16 rounded-full mx-auto mb-4 flex items-center justify-center",
512
+ style: { background: "linear-gradient(135deg, #34d399, #059669)" },
513
+ children: /* @__PURE__ */ jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2.5", children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) })
514
+ }
515
+ ),
516
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold mb-1", style: { color: "var(--text-primary)" }, children: "\xA1Transacci\xF3n creada!" }),
517
+ /* @__PURE__ */ jsx("p", { className: "text-sm", style: { color: "var(--text-secondary)" }, children: "Redirigiendo a la lista..." })
518
+ ] }) });
519
+ }
520
+ return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto", children: [
521
+ /* @__PURE__ */ jsxs(
522
+ Link,
523
+ {
524
+ href: "/",
525
+ className: "inline-flex items-center gap-2 text-sm mb-6 transition-colors",
526
+ style: { color: "var(--text-secondary)" },
527
+ children: [
528
+ /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
529
+ /* @__PURE__ */ jsx("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
530
+ /* @__PURE__ */ jsx("polyline", { points: "12 19 5 12 12 5" })
531
+ ] }),
532
+ "Volver a la lista"
533
+ ]
534
+ }
535
+ ),
536
+ /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl overflow-hidden", style: { boxShadow: "var(--shadow-card)" }, children: [
537
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-5", style: { borderBottom: "1px solid rgba(145,158,171,0.16)" }, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
538
+ /* @__PURE__ */ jsx(
539
+ "div",
540
+ {
541
+ className: "w-10 h-10 rounded-xl flex items-center justify-center text-white",
542
+ style: { background: "linear-gradient(135deg, #6366f1, #4f46e5)", boxShadow: "0 8px 16px rgba(79,70,229,0.28)" },
543
+ children: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2.5", children: [
544
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
545
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
546
+ ] })
547
+ }
548
+ ),
549
+ /* @__PURE__ */ jsxs("div", { children: [
550
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-bold", style: { color: "var(--text-primary)" }, children: "Nueva Transacci\xF3n" }),
551
+ /* @__PURE__ */ jsxs("p", { className: "text-xs mt-0.5", style: { color: "var(--text-secondary)" }, children: [
552
+ "POST ",
553
+ API,
554
+ "/api/transactions"
555
+ ] })
556
+ ] })
557
+ ] }) }),
558
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "px-6 py-6 space-y-5", children: [
559
+ error && /* @__PURE__ */ jsxs(
560
+ "div",
561
+ {
562
+ className: "rounded-xl px-4 py-3 text-sm flex items-center gap-2.5",
563
+ style: { backgroundColor: "rgba(239,68,68,0.08)", border: "1px solid rgba(239,68,68,0.24)", color: "#dc2626" },
564
+ children: [
565
+ /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [
566
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
567
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
568
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
569
+ ] }),
570
+ error
571
+ ]
572
+ }
573
+ ),
574
+ /* @__PURE__ */ jsx(Field, { id: "user", label: "Nombre de usuario", hint: "Quien realiza la transacci\xF3n", children: /* @__PURE__ */ jsx(
575
+ "input",
576
+ {
577
+ id: "user",
578
+ type: "text",
579
+ required: true,
580
+ value: user,
581
+ onChange: (e) => setUser(e.target.value),
582
+ onFocus: () => setFocusedField("user"),
583
+ onBlur: () => setFocusedField(null),
584
+ placeholder: "ej. Juan P\xE9rez",
585
+ style: inputStyle(focusedField === "user")
586
+ }
587
+ ) }),
588
+ /* @__PURE__ */ jsx(Field, { id: "coin", label: "Criptomoneda", children: /* @__PURE__ */ jsx(
589
+ "select",
590
+ {
591
+ id: "coin",
592
+ required: true,
593
+ value: coin,
594
+ onChange: (e) => setCoin(e.target.value),
595
+ onFocus: () => setFocusedField("coin"),
596
+ onBlur: () => setFocusedField(null),
597
+ style: inputStyle(focusedField === "coin"),
598
+ children: COINS.map((c) => /* @__PURE__ */ jsx("option", { value: c.value, children: c.label }, c.value))
599
+ }
600
+ ) }),
601
+ /* @__PURE__ */ jsx(Field, { id: "amount", label: "Monto", hint: "N\xFAmero de unidades de la criptomoneda", children: /* @__PURE__ */ jsx(
602
+ "input",
603
+ {
604
+ id: "amount",
605
+ type: "number",
606
+ required: true,
607
+ min: "0.000001",
608
+ step: "any",
609
+ value: amount,
610
+ onChange: (e) => setAmount(e.target.value),
611
+ onFocus: () => setFocusedField("amount"),
612
+ onBlur: () => setFocusedField(null),
613
+ placeholder: "ej. 0.5",
614
+ style: inputStyle(focusedField === "amount")
615
+ }
616
+ ) }),
617
+ (user || amount) && /* @__PURE__ */ jsxs("div", { className: "rounded-xl p-4", style: { backgroundColor: "#F4F6F8" }, children: [
618
+ /* @__PURE__ */ jsx(
619
+ "p",
620
+ {
621
+ className: "text-[10px] font-semibold uppercase tracking-[0.08em] mb-2",
622
+ style: { color: "var(--text-disabled)" },
623
+ children: "Request body (JSON)"
624
+ }
625
+ ),
626
+ /* @__PURE__ */ jsx("pre", { className: "text-xs font-mono", style: { color: "var(--text-primary)" }, children: JSON.stringify({
627
+ user: user || "...",
628
+ coin,
629
+ amount: amount ? Number(amount) : "..."
630
+ }, null, 2) })
631
+ ] }),
632
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3 pt-1", children: [
633
+ /* @__PURE__ */ jsx(
634
+ Link,
635
+ {
636
+ href: "/",
637
+ className: "flex-1 py-3 rounded-lg text-sm font-bold text-center transition-all duration-150",
638
+ style: { border: "1px solid var(--border)", color: "var(--text-secondary)", backgroundColor: "white" },
639
+ children: "Cancelar"
640
+ }
641
+ ),
642
+ /* @__PURE__ */ jsx(
643
+ "button",
644
+ {
645
+ type: "submit",
646
+ disabled: loading,
647
+ className: "flex-1 py-3 rounded-lg text-sm font-bold text-white transition-all duration-200",
648
+ style: {
649
+ background: loading ? "rgba(79,70,229,0.6)" : "linear-gradient(135deg, #6366f1, #4f46e5)",
650
+ boxShadow: loading ? "none" : "0 8px 16px rgba(79,70,229,0.28)",
651
+ cursor: loading ? "not-allowed" : "pointer",
652
+ letterSpacing: "0.04em"
653
+ },
654
+ children: loading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-center gap-2", children: [
655
+ /* @__PURE__ */ jsx(
656
+ "span",
657
+ {
658
+ className: "w-4 h-4 border-2 rounded-full animate-spin",
659
+ style: { borderColor: "rgba(255,255,255,0.3)", borderTopColor: "white" }
660
+ }
661
+ ),
662
+ "Creando..."
663
+ ] }) : "CREAR TRANSACCI\xD3N"
664
+ }
665
+ )
666
+ ] })
667
+ ] })
668
+ ] })
669
+ ] }) });
670
+ }
671
+ var COINS2 = [
672
+ "BTC",
673
+ "ETH",
674
+ "SOL",
675
+ "BNB",
676
+ "XRP",
677
+ "USDT",
678
+ "USDC",
679
+ "DOGE",
680
+ "ADA",
681
+ "MATIC"
682
+ ];
683
+ function EditTransactionPage() {
684
+ const { id } = useParams();
685
+ const router = useRouter();
686
+ const API = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3000";
687
+ const [user, setUser] = useState("");
688
+ const [coin, setCoin] = useState("BTC");
689
+ const [amount, setAmount] = useState("");
690
+ const [loading, setLoading] = useState(false);
691
+ const [fetching, setFetching] = useState(true);
692
+ const [error, setError] = useState(null);
693
+ const [success, setSuccess] = useState(false);
694
+ const [focusedField, setFocusedField] = useState(null);
695
+ useEffect(() => {
696
+ const load = async () => {
697
+ try {
698
+ const res = await fetch(`${API}/api/transactions`);
699
+ if (!res.ok) throw new Error(`Error ${res.status}`);
700
+ const data = await res.json();
701
+ const tx = data.find((t) => t._id === id);
702
+ if (!tx) throw new Error("Transacci\xF3n no encontrada");
703
+ setUser(tx.user);
704
+ setCoin(tx.coin.toUpperCase());
705
+ setAmount(String(tx.amount));
706
+ } catch (e) {
707
+ setError(e instanceof Error ? e.message : "Error cargando datos");
708
+ } finally {
709
+ setFetching(false);
710
+ }
711
+ };
712
+ load();
713
+ }, [id, API]);
714
+ const inputStyle = (focused) => ({
715
+ width: "100%",
716
+ padding: focused ? "11px 13px" : "12px 14px",
717
+ border: `${focused ? 2 : 1}px solid ${focused ? "var(--primary)" : "var(--border)"}`,
718
+ borderRadius: 8,
719
+ fontSize: "0.875rem",
720
+ color: "var(--text-primary)",
721
+ backgroundColor: "white",
722
+ boxShadow: focused ? "0 0 0 3px rgba(79,70,229,0.08)" : "none",
723
+ outline: "none",
724
+ transition: "all 0.2s"
725
+ });
726
+ const handleSubmit = async (e) => {
727
+ e.preventDefault();
728
+ if (!user.trim()) {
729
+ setError("El nombre de usuario es requerido");
730
+ return;
731
+ }
732
+ if (isNaN(Number(amount)) || Number(amount) <= 0) {
733
+ setError("Ingresa un monto v\xE1lido mayor a 0");
734
+ return;
735
+ }
736
+ setLoading(true);
737
+ setError(null);
738
+ try {
739
+ const res = await fetch(`${API}/api/transactions/${id}`, {
740
+ method: "PUT",
741
+ headers: { "Content-Type": "application/json" },
742
+ body: JSON.stringify({ user: user.trim(), coin, amount: Number(amount) })
743
+ });
744
+ if (!res.ok) {
745
+ const data = await res.json().catch(() => ({}));
746
+ throw new Error(data.message ?? `Error ${res.status}`);
747
+ }
748
+ setSuccess(true);
749
+ setTimeout(() => router.push("/"), 1200);
750
+ } catch (err) {
751
+ setError(err instanceof Error ? err.message : "Error al actualizar");
752
+ } finally {
753
+ setLoading(false);
754
+ }
755
+ };
756
+ if (success) {
757
+ return /* @__PURE__ */ jsx("div", { className: "p-6 flex items-center justify-center min-h-[60vh]", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
758
+ /* @__PURE__ */ jsx(
759
+ "div",
760
+ {
761
+ className: "w-16 h-16 rounded-full mx-auto mb-4 flex items-center justify-center",
762
+ style: { background: "linear-gradient(135deg, #34d399, #059669)" },
763
+ children: /* @__PURE__ */ jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2.5", children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) })
764
+ }
765
+ ),
766
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold mb-1", style: { color: "var(--text-primary)" }, children: "\xA1Transacci\xF3n actualizada!" }),
767
+ /* @__PURE__ */ jsx("p", { className: "text-sm", style: { color: "var(--text-secondary)" }, children: "Redirigiendo..." })
768
+ ] }) });
769
+ }
770
+ return /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto", children: [
771
+ /* @__PURE__ */ jsxs(
772
+ Link,
773
+ {
774
+ href: "/",
775
+ className: "inline-flex items-center gap-2 text-sm mb-6 transition-colors",
776
+ style: { color: "var(--text-secondary)" },
777
+ children: [
778
+ /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
779
+ /* @__PURE__ */ jsx("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
780
+ /* @__PURE__ */ jsx("polyline", { points: "12 19 5 12 12 5" })
781
+ ] }),
782
+ "Volver a la lista"
783
+ ]
784
+ }
785
+ ),
786
+ /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl overflow-hidden", style: { boxShadow: "var(--shadow-card)" }, children: [
787
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-5", style: { borderBottom: "1px solid rgba(145,158,171,0.16)" }, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
788
+ /* @__PURE__ */ jsx(
789
+ "div",
790
+ {
791
+ className: "w-10 h-10 rounded-xl flex items-center justify-center text-white",
792
+ style: { background: "linear-gradient(135deg, #a78bfa, #7c3aed)", boxShadow: "0 8px 16px rgba(124,58,237,0.28)" },
793
+ children: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2.5", children: [
794
+ /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
795
+ /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
796
+ ] })
797
+ }
798
+ ),
799
+ /* @__PURE__ */ jsxs("div", { children: [
800
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-bold", style: { color: "var(--text-primary)" }, children: "Editar Transacci\xF3n" }),
801
+ /* @__PURE__ */ jsxs("p", { className: "text-xs mt-0.5 font-mono", style: { color: "var(--text-disabled)" }, children: [
802
+ "ID: ",
803
+ id?.slice(-12)
804
+ ] })
805
+ ] })
806
+ ] }) }),
807
+ fetching ? /* @__PURE__ */ jsx("div", { className: "px-6 py-12 animate-pulse space-y-4", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs("div", { children: [
808
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-20 bg-gray-200 rounded mb-2" }),
809
+ /* @__PURE__ */ jsx("div", { className: "h-11 bg-gray-100 rounded-lg" })
810
+ ] }, i)) }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "px-6 py-6 space-y-5", children: [
811
+ error && /* @__PURE__ */ jsxs(
812
+ "div",
813
+ {
814
+ className: "rounded-xl px-4 py-3 text-sm flex items-center gap-2.5",
815
+ style: { backgroundColor: "rgba(239,68,68,0.08)", border: "1px solid rgba(239,68,68,0.24)", color: "#dc2626" },
816
+ children: [
817
+ /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [
818
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
819
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
820
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
821
+ ] }),
822
+ error
823
+ ]
824
+ }
825
+ ),
826
+ /* @__PURE__ */ jsxs("div", { children: [
827
+ /* @__PURE__ */ jsx(
828
+ "label",
829
+ {
830
+ htmlFor: "user",
831
+ className: "block text-xs font-semibold mb-1.5",
832
+ style: { color: "var(--text-secondary)" },
833
+ children: "Nombre de usuario"
834
+ }
835
+ ),
836
+ /* @__PURE__ */ jsx(
837
+ "input",
838
+ {
839
+ id: "user",
840
+ type: "text",
841
+ required: true,
842
+ value: user,
843
+ onChange: (e) => setUser(e.target.value),
844
+ onFocus: () => setFocusedField("user"),
845
+ onBlur: () => setFocusedField(null),
846
+ style: inputStyle(focusedField === "user")
847
+ }
848
+ )
849
+ ] }),
850
+ /* @__PURE__ */ jsxs("div", { children: [
851
+ /* @__PURE__ */ jsx(
852
+ "label",
853
+ {
854
+ htmlFor: "coin",
855
+ className: "block text-xs font-semibold mb-1.5",
856
+ style: { color: "var(--text-secondary)" },
857
+ children: "Criptomoneda"
858
+ }
859
+ ),
860
+ /* @__PURE__ */ jsx(
861
+ "select",
862
+ {
863
+ id: "coin",
864
+ required: true,
865
+ value: coin,
866
+ onChange: (e) => setCoin(e.target.value),
867
+ onFocus: () => setFocusedField("coin"),
868
+ onBlur: () => setFocusedField(null),
869
+ style: inputStyle(focusedField === "coin"),
870
+ children: COINS2.map((c) => /* @__PURE__ */ jsx("option", { value: c, children: c }, c))
871
+ }
872
+ )
873
+ ] }),
874
+ /* @__PURE__ */ jsxs("div", { children: [
875
+ /* @__PURE__ */ jsx(
876
+ "label",
877
+ {
878
+ htmlFor: "amount",
879
+ className: "block text-xs font-semibold mb-1.5",
880
+ style: { color: "var(--text-secondary)" },
881
+ children: "Monto"
882
+ }
883
+ ),
884
+ /* @__PURE__ */ jsx(
885
+ "input",
886
+ {
887
+ id: "amount",
888
+ type: "number",
889
+ required: true,
890
+ min: "0.000001",
891
+ step: "any",
892
+ value: amount,
893
+ onChange: (e) => setAmount(e.target.value),
894
+ onFocus: () => setFocusedField("amount"),
895
+ onBlur: () => setFocusedField(null),
896
+ style: inputStyle(focusedField === "amount")
897
+ }
898
+ )
899
+ ] }),
900
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3 pt-1", children: [
901
+ /* @__PURE__ */ jsx(
902
+ Link,
903
+ {
904
+ href: "/",
905
+ className: "flex-1 py-3 rounded-lg text-sm font-bold text-center",
906
+ style: { border: "1px solid var(--border)", color: "var(--text-secondary)", backgroundColor: "white" },
907
+ children: "Cancelar"
908
+ }
909
+ ),
910
+ /* @__PURE__ */ jsx(
911
+ "button",
912
+ {
913
+ type: "submit",
914
+ disabled: loading,
915
+ className: "flex-1 py-3 rounded-lg text-sm font-bold text-white",
916
+ style: {
917
+ background: loading ? "rgba(124,58,237,0.6)" : "linear-gradient(135deg, #a78bfa, #7c3aed)",
918
+ boxShadow: loading ? "none" : "0 8px 16px rgba(124,58,237,0.28)",
919
+ cursor: loading ? "not-allowed" : "pointer",
920
+ letterSpacing: "0.04em"
921
+ },
922
+ children: loading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-center gap-2", children: [
923
+ /* @__PURE__ */ jsx(
924
+ "span",
925
+ {
926
+ className: "w-4 h-4 border-2 rounded-full animate-spin",
927
+ style: { borderColor: "rgba(255,255,255,0.3)", borderTopColor: "white" }
928
+ }
929
+ ),
930
+ "Guardando..."
931
+ ] }) : "GUARDAR CAMBIOS"
932
+ }
933
+ )
934
+ ] })
935
+ ] })
936
+ ] })
937
+ ] }) });
938
+ }
939
+ var IconList = () => /* @__PURE__ */ jsxs("svg", { width: "19", height: "19", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
940
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "6", x2: "21", y2: "6" }),
941
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "12", x2: "21", y2: "12" }),
942
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "18", x2: "21", y2: "18" }),
943
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "6", x2: "3.01", y2: "6" }),
944
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "3.01", y2: "12" }),
945
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "18", x2: "3.01", y2: "18" })
946
+ ] });
947
+ var IconPlus = () => /* @__PURE__ */ jsxs("svg", { width: "19", height: "19", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
948
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
949
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "16" }),
950
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "12", x2: "16", y2: "12" })
951
+ ] });
952
+ var IconArrowLeft = () => /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
953
+ /* @__PURE__ */ jsx("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
954
+ /* @__PURE__ */ jsx("polyline", { points: "12 19 5 12 12 5" })
955
+ ] });
956
+ var IconLogo = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M12 2v20M17 5H9.5a3.5 3.5 0 1 0 0 7h5a3.5 3.5 0 1 1 0 7H6" }) });
957
+ var NAV_ITEMS = [
958
+ { href: "/", label: "Lista de Transacciones", icon: /* @__PURE__ */ jsx(IconList, {}) },
959
+ { href: "/new", label: "Nueva Transacci\xF3n", icon: /* @__PURE__ */ jsx(IconPlus, {}) }
960
+ ];
961
+ function Sidebar() {
962
+ const pathname = usePathname();
963
+ return /* @__PURE__ */ jsxs(
964
+ "aside",
965
+ {
966
+ className: "w-64 min-h-screen flex flex-col shrink-0",
967
+ style: {
968
+ backgroundColor: "var(--sidebar-bg)",
969
+ borderRight: "1px solid var(--sidebar-border)"
970
+ },
971
+ children: [
972
+ /* @__PURE__ */ jsxs(
973
+ "div",
974
+ {
975
+ className: "px-5 py-5",
976
+ style: { borderBottom: "1px solid var(--sidebar-border)" },
977
+ children: [
978
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-3", children: [
979
+ /* @__PURE__ */ jsx(
980
+ "div",
981
+ {
982
+ className: "w-9 h-9 rounded-lg flex items-center justify-center text-white shrink-0",
983
+ style: {
984
+ background: "linear-gradient(135deg, #6366f1 0%, #4f46e5 100%)",
985
+ boxShadow: "0 8px 16px 0 rgba(79,70,229,0.35)"
986
+ },
987
+ children: /* @__PURE__ */ jsx(IconLogo, {})
988
+ }
989
+ ),
990
+ /* @__PURE__ */ jsxs("div", { children: [
991
+ /* @__PURE__ */ jsx("h1", { className: "text-sm font-bold text-white leading-none", children: "Crypto Dashboard" }),
992
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] mt-0.5 leading-none", style: { color: "#637381" }, children: "Panel de Control" })
993
+ ] })
994
+ ] }),
995
+ /* @__PURE__ */ jsxs(
996
+ "div",
997
+ {
998
+ className: "inline-flex items-center gap-1.5 text-[10px] font-bold px-2.5 py-1 rounded-full",
999
+ style: {
1000
+ backgroundColor: "rgba(79,70,229,0.20)",
1001
+ color: "#818CF8",
1002
+ border: "1px solid rgba(79,70,229,0.30)"
1003
+ },
1004
+ children: [
1005
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-indigo-400 animate-pulse" }),
1006
+ "MFE \xB7 Transacciones \xB7 :3001"
1007
+ ]
1008
+ }
1009
+ )
1010
+ ]
1011
+ }
1012
+ ),
1013
+ /* @__PURE__ */ jsxs("nav", { className: "flex-1 px-3 py-5", children: [
1014
+ /* @__PURE__ */ jsx(
1015
+ "p",
1016
+ {
1017
+ className: "text-[10px] font-bold uppercase tracking-[0.1em] px-3 mb-2",
1018
+ style: { color: "rgba(145,158,171,0.48)" },
1019
+ children: "M\xF3dulo"
1020
+ }
1021
+ ),
1022
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: NAV_ITEMS.map((item) => {
1023
+ const fullPath = `/dashboard/transactions${item.href === "/" ? "" : item.href}`;
1024
+ const isActive = pathname === fullPath;
1025
+ return /* @__PURE__ */ jsxs(
1026
+ Link,
1027
+ {
1028
+ href: item.href,
1029
+ className: "group flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-150 relative",
1030
+ style: {
1031
+ color: isActive ? "var(--sidebar-text-active)" : "var(--sidebar-text)",
1032
+ backgroundColor: isActive ? "var(--sidebar-active-bg)" : "transparent"
1033
+ },
1034
+ onMouseEnter: (e) => {
1035
+ if (!isActive) {
1036
+ e.currentTarget.style.backgroundColor = "rgba(255,255,255,0.06)";
1037
+ e.currentTarget.style.color = "#C4CDD5";
1038
+ }
1039
+ },
1040
+ onMouseLeave: (e) => {
1041
+ if (!isActive) {
1042
+ e.currentTarget.style.backgroundColor = "transparent";
1043
+ e.currentTarget.style.color = "var(--sidebar-text)";
1044
+ }
1045
+ },
1046
+ children: [
1047
+ isActive && /* @__PURE__ */ jsx(
1048
+ "span",
1049
+ {
1050
+ className: "absolute left-0 top-1/2 -translate-y-1/2 w-[3px] h-6 rounded-r-full",
1051
+ style: { backgroundColor: "#818CF8" }
1052
+ }
1053
+ ),
1054
+ /* @__PURE__ */ jsx("span", { style: { color: isActive ? "#818CF8" : "#637381" }, children: item.icon }),
1055
+ /* @__PURE__ */ jsx("span", { children: item.label })
1056
+ ]
1057
+ },
1058
+ item.href
1059
+ );
1060
+ }) })
1061
+ ] }),
1062
+ /* @__PURE__ */ jsx(
1063
+ "div",
1064
+ {
1065
+ className: "px-3 py-4",
1066
+ style: { borderTop: "1px solid var(--sidebar-border)" },
1067
+ children: /* @__PURE__ */ jsxs(
1068
+ "a",
1069
+ {
1070
+ href: "http://localhost:3000/dashboard",
1071
+ className: "flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-150 w-full",
1072
+ style: { color: "#637381" },
1073
+ onMouseEnter: (e) => {
1074
+ e.currentTarget.style.color = "#C4CDD5";
1075
+ e.currentTarget.style.backgroundColor = "rgba(255,255,255,0.06)";
1076
+ },
1077
+ onMouseLeave: (e) => {
1078
+ e.currentTarget.style.color = "#637381";
1079
+ e.currentTarget.style.backgroundColor = "transparent";
1080
+ },
1081
+ children: [
1082
+ /* @__PURE__ */ jsx(IconArrowLeft, {}),
1083
+ /* @__PURE__ */ jsx("span", { children: "Dashboard Principal" })
1084
+ ]
1085
+ }
1086
+ )
1087
+ }
1088
+ )
1089
+ ]
1090
+ }
1091
+ );
1092
+ }
1093
+ function EmbeddedShell({ children }) {
1094
+ const [isEmbedded, setIsEmbedded] = useState(false);
1095
+ useEffect(() => {
1096
+ try {
1097
+ setIsEmbedded(window.self !== window.top);
1098
+ } catch {
1099
+ setIsEmbedded(true);
1100
+ }
1101
+ }, []);
1102
+ if (isEmbedded) {
1103
+ return /* @__PURE__ */ jsx("div", { style: { backgroundColor: "var(--background)", minHeight: "100vh" }, children });
1104
+ }
1105
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen", style: { backgroundColor: "var(--background)" }, children: [
1106
+ /* @__PURE__ */ jsx(Sidebar, {}),
1107
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
1108
+ /* @__PURE__ */ jsxs(
1109
+ "header",
1110
+ {
1111
+ className: "h-16 flex items-center px-6 shrink-0",
1112
+ style: {
1113
+ backgroundColor: "rgba(244,246,248,0.95)",
1114
+ borderBottom: "1px solid rgba(145,158,171,0.24)",
1115
+ position: "sticky",
1116
+ top: 0,
1117
+ zIndex: 40
1118
+ },
1119
+ children: [
1120
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
1121
+ /* @__PURE__ */ jsxs("nav", { className: "flex items-center gap-1.5 text-xs mb-0.5", children: [
1122
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--text-secondary)" }, children: "Inicio" }),
1123
+ /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) }),
1124
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--text-secondary)" }, children: "Gesti\xF3n" }),
1125
+ /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) }),
1126
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", style: { color: "var(--text-primary)" }, children: "Transacciones" })
1127
+ ] }),
1128
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold leading-none", style: { color: "var(--text-primary)" }, children: "Transacciones" })
1129
+ ] }),
1130
+ /* @__PURE__ */ jsxs(
1131
+ "div",
1132
+ {
1133
+ className: "hidden sm:flex items-center gap-2 text-xs font-semibold px-3 py-1.5 rounded-full",
1134
+ style: {
1135
+ backgroundColor: "rgba(79,70,229,0.10)",
1136
+ color: "var(--primary)",
1137
+ border: "1px solid rgba(79,70,229,0.20)"
1138
+ },
1139
+ children: [
1140
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse" }),
1141
+ "Microfrontend \xB7 Puerto 3001"
1142
+ ]
1143
+ }
1144
+ )
1145
+ ]
1146
+ }
1147
+ ),
1148
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto", children })
1149
+ ] })
1150
+ ] });
1151
+ }
1152
+
1153
+ export { EditTransactionPage, EmbeddedShell, NewTransactionPage, Sidebar, TransactionsPage as TransactionsListPage };
1154
+ //# sourceMappingURL=index.js.map
1155
+ //# sourceMappingURL=index.js.map