-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcomponente-1.8-preview.html
More file actions
209 lines (190 loc) · 11.3 KB
/
Copy pathcomponente-1.8-preview.html
File metadata and controls
209 lines (190 loc) · 11.3 KB
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Componente 1.8: Detalle de Activos y Rendimiento</title>
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Tabulator CSS CDN (using modern theme) -->
<link href="https://cdn.jsdelivr.net/npm/tabulator-tables@5.5.2/dist/css/tabulator_modern.min.css" rel="stylesheet">
<style>
/* Estilos mejorados para Tabulator */
.tabulator {
border: 1px solid #d1d5db; /* Tailwind gray-300 */
border-radius: 0.5rem; /* Tailwind rounded-lg */
overflow: hidden; /* Ensure rounded corners clip content */
font-size: 0.875rem; /* Tailwind text-sm */
}
.tabulator .tabulator-header {
background-color: #f3f4f6; /* Tailwind gray-100 */
border-bottom: 2px solid #d1d5db; /* Tailwind gray-300 */
font-weight: 600; /* Tailwind semibold */
color: #374151; /* Tailwind gray-700 */
}
.tabulator .tabulator-header .tabulator-col {
border-right: 1px solid #e5e7eb; /* Tailwind gray-200 */
padding-top: 0.75rem; /* Tailwind py-3 */
padding-bottom: 0.75rem;
padding-left: 1rem; /* Tailwind px-4 */
padding-right: 1rem;
}
.tabulator .tabulator-header .tabulator-col:last-child {
border-right: none; /* No border on the last header cell */
}
.tabulator .tabulator-row {
border-bottom: 1px solid #e5e7eb; /* Tailwind gray-200 */
}
/* Zebra striping */
.tabulator .tabulator-row:nth-child(even) {
background-color: #f9fafb; /* Tailwind gray-50 */
}
.tabulator .tabulator-row:hover {
background-color: #eff6ff; /* Tailwind blue-100 */
}
.tabulator .tabulator-row .tabulator-cell {
padding: 0.75rem 1rem; /* Tailwind py-3 px-4 */
border-right: 1px solid #f3f4f6; /* Lighter border for cells */
}
.tabulator .tabulator-row .tabulator-cell:last-child {
border-right: none;
}
/* Indicador de ordenamiento */
.tabulator .tabulator-header .tabulator-col[aria-sort="ascending"] .tabulator-col-content::after {
content: ' ▲';
font-size: 0.75em; /* Slightly smaller */
color: #3b82f6; /* Tailwind blue-500 */
}
.tabulator .tabulator-header .tabulator-col[aria-sort="descending"] .tabulator-col-content::after {
content: ' ▼';
font-size: 0.75em; /* Slightly smaller */
color: #3b82f6; /* Tailwind blue-500 */
}
/* Ajuste para alineación vertical en celdas */
.tabulator-cell {
vertical-align: middle;
}
/* Estilo para el logo dentro de la celda */
.company-logo {
height: 20px;
width: 20px;
margin-right: 8px;
display: inline-block;
vertical-align: middle;
border-radius: 4px; /* Slightly rounded corners for logos */
background-color: #f3f4f6; /* Placeholder bg color */
}
.company-name {
vertical-align: middle;
display: inline-block;
}
</style>
</head>
<body class="bg-gray-100 p-4 sm:p-6">
<div class="container mx-auto bg-white p-5 sm:p-6 rounded-xl shadow-lg">
<h2 class="text-xl sm:text-2xl font-semibold mb-2 text-gray-800">Componente 1.8: Detalle de Activos y Rendimiento</h2>
<p class="text-sm sm:text-base text-gray-600 mb-6">
Vista detallada de los activos del portafolio. Ordene haciendo clic en las cabeceras o filtre por Nombre/Ticker.
</p>
<!-- Campo de Filtro -->
<div class="mb-5">
<input type="text" id="filter-input" placeholder="🔍 Filtrar por Nombre o Ticker..." class="p-2 border border-gray-300 rounded-md w-full md:w-1/2 lg:w-1/3 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm">
</div>
<!-- Contenedor para la Tabla Tabulator -->
<div id="asset-table" class="w-full"></div>
<!-- Disclaimer -->
<p class="text-xs sm:text-sm text-gray-500 mt-5 italic">
Nota: Previsualización estática. Funcionalidades avanzadas pueden variar en la implementación final.
</p>
</div>
<!-- Tabulator JS CDN -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/tabulator-tables@5.5.2/dist/js/tabulator.min.js"></script>
<script>
// Datos de ejemplo para la tabla (con campo 'domain' añadido)
const tableData = [
{ id: 1, nombre: "Apple Inc.", ticker: "AAPL", cantidad: 150, valorActual: 25500.75, porcentajePortafolio: 15.50, rendimientoPeriodo: 5.20, contribucionRetorno: 0.81, domain: "apple.com" },
{ id: 2, nombre: "Microsoft Corp.", ticker: "MSFT", cantidad: 100, valorActual: 30100.50, porcentajePortafolio: 18.25, rendimientoPeriodo: 7.10, contribucionRetorno: 1.30, domain: "microsoft.com" },
{ id: 3, nombre: "Amazon.com, Inc.", ticker: "AMZN", cantidad: 50, valorActual: 15000.00, porcentajePortafolio: 9.10, rendimientoPeriodo: -1.50, contribucionRetorno: -0.14, domain: "amazon.com" },
{ id: 4, nombre: "Alphabet Inc. (Class A)", ticker: "GOOGL", cantidad: 25, valorActual: 68750.00, porcentajePortafolio: 41.70, rendimientoPeriodo: 8.00, contribucionRetorno: 3.34, domain: "google.com" },
{ id: 5, nombre: "Tesla, Inc.", ticker: "TSLA", cantidad: 30, valorActual: 21000.00, porcentajePortafolio: 12.73, rendimientoPeriodo: 15.30, contribucionRetorno: 1.95, domain: "tesla.com" },
{ id: 6, nombre: "Meta Platforms, Inc.", ticker: "META", cantidad: 75, valorActual: 18750.25, porcentajePortafolio: 11.37, rendimientoPeriodo: 2.10, contribucionRetorno: 0.24, domain: "meta.com" },
{ id: 7, nombre: "NVIDIA Corporation", ticker: "NVDA", cantidad: 40, valorActual: 24000.00, porcentajePortafolio: 14.55, rendimientoPeriodo: 25.50, contribucionRetorno: 3.71, domain: "nvidia.com" },
{ id: 8, nombre: "Berkshire Hathaway Inc. (Class B)", ticker: "BRK.B", cantidad: 60, valorActual: 19800.00, porcentajePortafolio: 12.00, rendimientoPeriodo: 3.00, contribucionRetorno: 0.36, domain: "berkshirehathaway.com" },
{ id: 9, nombre: "JPMorgan Chase & Co.", ticker: "JPM", cantidad: 120, valorActual: 16800.00, porcentajePortafolio: 10.18, rendimientoPeriodo: 1.80, contribucionRetorno: 0.18, domain: "jpmorganchase.com" },
{ id: 10, nombre: "Johnson & Johnson", ticker: "JNJ", cantidad: 90, valorActual: 15300.00, porcentajePortafolio: 9.27, rendimientoPeriodo: -0.50, contribucionRetorno: -0.05, domain: "jnj.com" },
{ id: 11, nombre: "Visa Inc.", ticker: "V", cantidad: 80, valorActual: 17600.00, porcentajePortafolio: 10.67, rendimientoPeriodo: 4.50, contribucionRetorno: 0.48, domain: "visa.com" },
{ id: 12, nombre: "Procter & Gamble Co.", ticker: "PG", cantidad: 110, valorActual: 16500.00, porcentajePortafolio: 10.00, rendimientoPeriodo: 1.20, contribucionRetorno: 0.12, domain: "pg.com" },
];
// Formateador simple para moneda (USD)
const moneyFormatter = function(cell, formatterParams, onRendered){
let value = cell.getValue();
if(value === null || value === undefined) return "";
return "$" + parseFloat(value).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
};
// Formateador simple para porcentaje
const percentageFormatter = function(cell, formatterParams, onRendered){
let value = cell.getValue();
if(value === null || value === undefined) return "";
return parseFloat(value).toFixed(2) + "%";
};
// Formateador para rendimiento/contribución con color
const performanceFormatter = function(cell, formatterParams, onRendered){
let value = cell.getValue();
if(value === null || value === undefined) return "";
const formattedValue = parseFloat(value).toFixed(2) + "%";
if (value > 0) {
cell.getElement().style.color = "#10b981"; // Tailwind green-500
} else if (value < 0) {
cell.getElement().style.color = "#ef4444"; // Tailwind red-500
} else {
cell.getElement().style.color = "#6b7280"; // Tailwind gray-500
}
return formattedValue;
};
// Formateador para Nombre con Logo
const nameAndLogoFormatter = function(cell, formatterParams, onRendered){
const data = cell.getRow().getData();
const name = data.nombre;
const domain = data.domain;
let logoHtml = '';
if (domain) {
// Usar logo.clearbit.com para obtener logos dinámicamente
const logoUrl = `https://logo.clearbit.com/${domain}`;
logoHtml = `<img src="${logoUrl}" alt="" class="company-logo" onerror="this.style.display='none'; this.onerror=null;">`;
}
// Devolver el HTML combinado
return `${logoHtml}<span class="company-name">${name}</span>`;
};
// Inicialización de Tabulator
const table = new Tabulator("#asset-table", {
height: "480px",
data: tableData,
layout: "fitColumns", // Cambiado a fitColumns para que las columnas llenen el espacio
responsiveLayout: "hide",
columns: [ // Definir columnas - Se eliminan la mayoría de los 'width' fijos
{ title: "Nombre", field: "nombre", sorter: "string", widthGrow: 2.5, hozAlign:"left", frozen:true, minWidth: 200, formatter: nameAndLogoFormatter }, // Aumentado minWidth y aplicado formatter
{ title: "Ticker", field: "ticker", sorter: "string", hozAlign:"left", width: 90 }, // Mantiene un ancho fijo pequeño
{ title: "Cantidad", field: "cantidad", sorter: "number", hozAlign:"right", minWidth: 80 },
{ title: "Valor Actual", field: "valorActual", sorter: "number", hozAlign:"right", formatter: moneyFormatter, minWidth: 120 },
{ title: "% Portafolio", field: "porcentajePortafolio", sorter: "number", hozAlign:"right", formatter: percentageFormatter, minWidth: 110 },
{ title: "Rend. Período", field: "rendimientoPeriodo", sorter: "number", hozAlign:"right", formatter: performanceFormatter, minWidth: 110 },
{ title: "Contrib. Retorno", field: "contribucionRetorno", sorter: "number", hozAlign:"right", formatter: performanceFormatter, minWidth: 120 }
],
});
// Lógica de Filtrado (simple, busca en nombre y ticker)
const filterInput = document.getElementById("filter-input");
filterInput.addEventListener("keyup", function(){
const filterValue = filterInput.value.toLowerCase();
table.setFilter([
[
{field:"nombre", type:"like", value:filterValue},
{field:"ticker", type:"like", value:filterValue}
]
]);
if(filterValue === ""){
table.clearFilter();
}
});
</script>
</body>
</html>