Feat: RawData Table Format

This commit is contained in:
2025-07-17 11:52:00 -03:00
parent 8878ec632e
commit 23f0d02fe3
6 changed files with 227 additions and 181 deletions

View File

@@ -1,33 +1,29 @@
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button } from '@mui/material';
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button, Typography } from '@mui/material';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
// Importaciones de nuestro proyecto
import { useApiData } from '../../hooks/useApiData';
import { useIsHoliday } from '../../hooks/useIsHoliday';
import type { CotizacionGanado } from '../../models/mercadoModels';
import { formatInteger, formatCurrency, formatFullDateTime } from '../../utils/formatters';
import { formatInteger, formatFullDateTime } from '../../utils/formatters';
import { copyToClipboard } from '../../utils/clipboardUtils';
import { HolidayAlert } from '../common/HolidayAlert';
/**
* Función para convertir los datos de la tabla a un formato CSV para el portapapeles.
* Función para convertir los datos a formato TSV (Tab-Separated Values)
* con el formato específico solicitado por redacción.
*/
const toCSV = (headers: string[], data: CotizacionGanado[]) => {
const headerRow = headers.join(';');
const dataRows = data.map(row =>
[
row.categoria,
row.especificaciones,
formatCurrency(row.maximo),
formatCurrency(row.minimo),
formatCurrency(row.mediano),
formatInteger(row.cabezas),
formatInteger(row.kilosTotales),
formatInteger(row.importeTotal),
formatFullDateTime(row.fechaRegistro)
].join(';')
);
return [headerRow, ...dataRows].join('\n');
const toTSV = (data: CotizacionGanado[]) => {
const dataRows = data.map(row => {
// Unimos Categoría y Especificaciones en una sola columna para el copiado
const categoriaCompleta = `${row.categoria}/${row.especificaciones}`;
const cabezas = formatInteger(row.cabezas);
const importeTotal = formatInteger(row.importeTotal);
return [categoriaCompleta, cabezas, importeTotal].join('\t');
});
return dataRows.join('\n');
};
/**
@@ -35,24 +31,21 @@ const toCSV = (headers: string[], data: CotizacionGanado[]) => {
* diseñado para la página de redacción.
*/
export const RawAgroTable = () => {
// Hooks para obtener los datos y el estado de feriado.
const { data, loading: dataLoading, error: dataError } = useApiData<CotizacionGanado[]>('/mercados/agroganadero');
const isHoliday = useIsHoliday('BA');
const handleCopy = () => {
if (!data) return;
const headers = ["Categoría", "Especificaciones", "Máximo", "Mínimo", "Mediano", "Cabezas", "Kg Total", "Importe Total", "Fecha de Registro"];
const csvData = toCSV(headers, data);
const tsvData = toTSV(data);
copyToClipboard(csvData)
.then(() => alert('¡Tabla copiada al portapapeles!'))
copyToClipboard(tsvData)
.then(() => alert('Datos del Mercado Agroganadero copiados al portapapeles!'))
.catch(err => {
console.error('Error al copiar:', err);
alert('Error: No se pudo copiar la tabla.');
});
};
// Estado de carga unificado.
const isLoading = dataLoading || isHoliday === null;
if (isLoading) return <CircularProgress />;
@@ -67,43 +60,37 @@ export const RawAgroTable = () => {
return (
<Box>
{/* Si es feriado, mostramos una alerta informativa encima de la tabla. */}
{isHoliday && (
<Box sx={{ mb: 2 }}>
<HolidayAlert />
</Box>
)}
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy} sx={{ mb: 1 }}>
Copiar como CSV
</Button>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy}>
Copiar Datos para Redacción
</Button>
<Typography variant="caption" sx={{ fontStyle: 'italic', color: 'text.secondary' }}>
Última actualización: {formatFullDateTime(data[0].fechaRegistro)}
</Typography>
</Box>
{/* La tabla ahora muestra solo las columnas requeridas para facilitar la visualización */}
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Categoría</TableCell>
<TableCell>Especificaciones</TableCell>
<TableCell align="right">Máximo</TableCell>
<TableCell align="right">Mínimo</TableCell>
<TableCell align="right">Mediano</TableCell>
<TableCell>Categoría / Especificaciones</TableCell>
<TableCell align="right">Cabezas</TableCell>
<TableCell align="right">Kg Total</TableCell>
<TableCell align="right">Importe Total</TableCell>
<TableCell>Última Act.</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(row => (
<TableRow key={row.id}>
<TableCell>{row.categoria}</TableCell>
<TableCell>{row.especificaciones}</TableCell>
<TableCell align="right">${formatCurrency(row.maximo)}</TableCell>
<TableCell align="right">${formatCurrency(row.minimo)}</TableCell>
<TableCell align="right">${formatCurrency(row.mediano)}</TableCell>
<TableCell>{row.categoria} / {row.especificaciones}</TableCell>
<TableCell align="right">{formatInteger(row.cabezas)}</TableCell>
<TableCell align="right">{formatInteger(row.kilosTotales)}</TableCell>
<TableCell align="right">${formatInteger(row.importeTotal)}</TableCell>
<TableCell>{formatFullDateTime(row.fechaRegistro)}</TableCell>
</TableRow>
))}
</TableBody>

View File

@@ -1,105 +1,121 @@
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button } from '@mui/material';
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button, Typography, Divider } from '@mui/material';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
// Importaciones de nuestro proyecto
import { useApiData } from '../../hooks/useApiData';
import { useIsHoliday } from '../../hooks/useIsHoliday';
import type { CotizacionBolsa } from '../../models/mercadoModels';
import { formatCurrency, formatFullDateTime } from '../../utils/formatters';
import { copyToClipboard } from '../../utils/clipboardUtils';
import { HolidayAlert } from '../common/HolidayAlert';
import { TICKERS_PRIORITARIOS_LOCAL } from '../../config/priorityTickers';
/**
* Función para convertir los datos de la tabla a formato CSV.
* Función para convertir los datos prioritarios a formato TSV (Tab-Separated Values).
*/
const toCSV = (headers: string[], data: CotizacionBolsa[]) => {
const headerRow = headers.join(';');
const dataRows = data.map(row =>
[
row.ticker,
row.nombreEmpresa,
formatCurrency(row.precioActual),
formatCurrency(row.cierreAnterior),
`${row.porcentajeCambio.toFixed(2)}%`,
formatFullDateTime(row.fechaRegistro)
].join(';')
);
return [headerRow, ...dataRows].join('\n');
const toTSV = (data: CotizacionBolsa[]) => {
const dataRows = data.map(row => {
// Formateamos el nombre para que quede como "GGAL.BA (GRUPO FINANCIERO GALICIA)"
const nombreCompleto = `${row.ticker} (${row.nombreEmpresa || ''})`;
const precio = `$${formatCurrency(row.precioActual)}`
const cambio = `${row.porcentajeCambio.toFixed(2)}%`
// Unimos los campos con un carácter de tabulación '\t'
return [nombreCompleto, precio, cambio].join('\t');
});
// Unimos todas las filas con un salto de línea
return dataRows.join('\n');
};
/**
* Componente de tabla de datos crudos para la Bolsa Local (MERVAL y acciones),
* diseñado para la página de redacción.
* Componente de tabla de datos crudos para la Bolsa Local, adaptado para redacción.
*/
export const RawBolsaLocalTable = () => {
// Hooks para obtener los datos y el estado de feriado.
const { data, loading: dataLoading, error: dataError } = useApiData<CotizacionBolsa[]>('/mercados/bolsa/local');
const isHoliday = useIsHoliday('BA');
const { data, loading, error } = useApiData<CotizacionBolsa[]>('/mercados/bolsa/local');
// Separamos los datos en prioritarios y el resto
const priorityData = data?.filter(d => TICKERS_PRIORITARIOS_LOCAL.includes(d.ticker))
.sort((a, b) => TICKERS_PRIORITARIOS_LOCAL.indexOf(a.ticker) - TICKERS_PRIORITARIOS_LOCAL.indexOf(b.ticker)); // Mantenemos el orden
const otherData = data?.filter(d => !TICKERS_PRIORITARIOS_LOCAL.includes(d.ticker));
const handleCopy = () => {
if (!data) return;
const headers = ["Ticker", "Nombre", "Último Precio", "Cierre Anterior", "Variación %", "Fecha de Registro"];
const csvData = toCSV(headers, data);
if (!priorityData) return;
const tsvData = toTSV(priorityData);
copyToClipboard(csvData)
.then(() => alert('¡Tabla copiada al portapapeles!'))
copyToClipboard(tsvData)
.then(() => alert('Datos prioritarios copiados al portapapeles.'))
.catch(err => {
console.error('Error al copiar:', err);
alert('Error: No se pudo copiar la tabla.');
});
};
// Estado de carga unificado.
const isLoading = dataLoading || isHoliday === null;
if (isLoading) return <CircularProgress />;
if (dataError) return <Alert severity="error">{dataError}</Alert>;
if (!data || data.length === 0) {
if (isHoliday) {
return <HolidayAlert />;
}
return <Alert severity="info">No hay datos disponibles para el mercado local.</Alert>;
}
if (loading) return <CircularProgress />;
if (error) return <Alert severity="error">{error}</Alert>;
if (!data || data.length === 0) return <Alert severity="info">No hay datos disponibles para el mercado local.</Alert>;
return (
<Box>
{/* Si es feriado, mostramos una alerta informativa encima de la tabla. */}
{isHoliday && (
<Box sx={{ mb: 2 }}>
<HolidayAlert />
</Box>
)}
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy}>
Copiar Datos Principales
</Button>
<Typography variant="caption" sx={{ fontStyle: 'italic', color: 'text.secondary' }}>
Última actualización: {formatFullDateTime(data[0].fechaRegistro)}
</Typography>
</Box>
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy} sx={{ mb: 1 }}>
Copiar como CSV
</Button>
{/* Tabla de Datos Prioritarios */}
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Ticker</TableCell>
<TableCell>Nombre</TableCell>
<TableCell align="right">Último Precio</TableCell>
<TableCell align="right">Cierre Anterior</TableCell>
<TableCell align="right">Variación %</TableCell>
<TableCell>Última Act.</TableCell>
<TableCell>Símbolo (Nombre)</TableCell>
<TableCell align="right">Precio Actual</TableCell>
<TableCell align="right">% Cambio</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(row => (
{priorityData?.map(row => (
<TableRow key={row.id}>
<TableCell>{row.ticker}</TableCell>
<TableCell>{row.nombreEmpresa}</TableCell>
<TableCell>
<Typography component="span" sx={{ fontWeight: 'bold' }}>{row.ticker}</Typography>
<Typography component="span" sx={{ ml: 1, color: 'text.secondary' }}>({row.nombreEmpresa})</Typography>
</TableCell>
<TableCell align="right">${formatCurrency(row.precioActual)}</TableCell>
<TableCell align="right">${formatCurrency(row.cierreAnterior)}</TableCell>
<TableCell align="right">{row.porcentajeCambio.toFixed(2)}%</TableCell>
<TableCell>{formatFullDateTime(row.fechaRegistro)}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
{/* Sección para Otros Tickers (solo para consulta) */}
{otherData && otherData.length > 0 && (
<Box mt={4}>
<Divider sx={{ mb: 2 }}>
<Typography variant="overline">Otros Tickers (Solo Consulta)</Typography>
</Divider>
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Ticker</TableCell>
<TableCell>Nombre</TableCell>
<TableCell align="right">Precio</TableCell>
</TableRow>
</TableHead>
<TableBody>
{otherData.map(row => (
<TableRow key={row.id}>
<TableCell>{row.ticker}</TableCell>
<TableCell>{row.nombreEmpresa}</TableCell>
<TableCell align="right">${formatCurrency(row.precioActual)}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
)}
</Box>
);
};

View File

@@ -1,4 +1,4 @@
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button } from '@mui/material';
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button, Typography, Divider } from '@mui/material';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
// Importaciones de nuestro proyecto
@@ -8,98 +8,125 @@ import type { CotizacionBolsa } from '../../models/mercadoModels';
import { formatCurrency, formatFullDateTime } from '../../utils/formatters';
import { copyToClipboard } from '../../utils/clipboardUtils';
import { HolidayAlert } from '../common/HolidayAlert';
import { TICKERS_PRIORITARIOS_USA } from '../../config/priorityTickers';
/**
* Función para convertir los datos de la tabla a formato CSV.
* Función para convertir los datos prioritarios a formato TSV (Tab-Separated Values).
*/
const toCSV = (headers: string[], data: CotizacionBolsa[]) => {
const headerRow = headers.join(';');
const dataRows = data.map(row =>
[
row.ticker,
row.nombreEmpresa,
formatCurrency(row.precioActual, 'USD'),
formatCurrency(row.cierreAnterior, 'USD'),
`${row.porcentajeCambio.toFixed(2)}%`,
formatFullDateTime(row.fechaRegistro)
].join(';')
);
return [headerRow, ...dataRows].join('\n');
const toTSV = (data: CotizacionBolsa[]) => {
const dataRows = data.map(row => {
// Formateamos los datos según los requisitos de redacción
const nombreCompleto = `${row.ticker} (${row.nombreEmpresa || ''})`;
const precio = `$${formatCurrency(row.precioActual)}`;
const cambio = `${row.porcentajeCambio.toFixed(2)}%`;
return [nombreCompleto, precio, cambio].join('\t');
});
return dataRows.join('\n');
};
/**
* Componente de tabla de datos crudos para la Bolsa de EEUU y ADRs,
* diseñado para la página de redacción.
* adaptado para las necesidades de redacción.
*/
export const RawBolsaUsaTable = () => {
// Hooks para obtener los datos y el estado de feriado para el mercado de EEUU.
const { data, loading: dataLoading, error: dataError } = useApiData<CotizacionBolsa[]>('/mercados/bolsa/eeuu');
const isHoliday = useIsHoliday('US');
// Separamos los datos en prioritarios y el resto, manteniendo el orden de la lista
const priorityData = data?.filter(d => TICKERS_PRIORITARIOS_USA.includes(d.ticker))
.sort((a, b) => TICKERS_PRIORITARIOS_USA.indexOf(a.ticker) - TICKERS_PRIORITARIOS_USA.indexOf(b.ticker));
const otherData = data?.filter(d => !TICKERS_PRIORITARIOS_USA.includes(d.ticker));
const handleCopy = () => {
if (!data) return;
const headers = ["Ticker", "Nombre", "Último Precio (USD)", "Cierre Anterior (USD)", "Variación %", "Fecha de Registro"];
const csvData = toCSV(headers, data);
if (!priorityData) return;
const tsvData = toTSV(priorityData);
copyToClipboard(csvData)
.then(() => alert('¡Tabla copiada al portapapeles!'))
copyToClipboard(tsvData)
.then(() => alert('Datos prioritarios copiados al portapapeles!'))
.catch(err => {
console.error('Error al copiar:', err);
alert('Error: No se pudo copiar la tabla.');
});
};
// Estado de carga unificado.
const isLoading = dataLoading || isHoliday === null;
if (isLoading) return <CircularProgress />;
if (dataError) return <Alert severity="error">{dataError}</Alert>;
if (!data || data.length === 0) {
if (isHoliday) {
return <HolidayAlert />;
}
return <Alert severity="info">No hay datos disponibles para el mercado de EEUU (el fetcher puede estar desactivado).</Alert>;
if (isHoliday) { return <HolidayAlert />; }
return <Alert severity="info">No hay datos disponibles para el mercado de EEUU.</Alert>;
}
return (
<Box>
{/* Si es feriado, mostramos una alerta informativa encima de la tabla. */}
{isHoliday && (
<Box sx={{ mb: 2 }}>
<HolidayAlert />
</Box>
)}
{isHoliday && <Box sx={{ mb: 2 }}><HolidayAlert /></Box>}
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy} sx={{ mb: 1 }}>
Copiar como CSV
</Button>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy}>
Copiar Datos Principales
</Button>
<Typography variant="caption" sx={{ fontStyle: 'italic', color: 'text.secondary' }}>
Última actualización: {formatFullDateTime(data[0].fechaRegistro)}
</Typography>
</Box>
{/* Tabla de Datos Prioritarios */}
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Ticker</TableCell>
<TableCell>Nombre</TableCell>
<TableCell align="right">Último Precio</TableCell>
<TableCell align="right">Cierre Anterior</TableCell>
<TableCell align="right">Variación %</TableCell>
<TableCell>Última Act.</TableCell>
<TableCell>Símbolo (Nombre)</TableCell>
<TableCell align="right">Precio Actual</TableCell>
<TableCell align="right">% Cambio</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(row => (
{priorityData?.map(row => (
<TableRow key={row.id}>
<TableCell>{row.ticker}</TableCell>
<TableCell>{row.nombreEmpresa}</TableCell>
<TableCell>
<Typography component="span" sx={{ fontWeight: 'bold' }}>{row.ticker}</Typography>
<Typography component="span" sx={{ ml: 1, color: 'text.secondary' }}>({row.nombreEmpresa})</Typography>
</TableCell>
<TableCell align="right">{formatCurrency(row.precioActual, 'USD')}</TableCell>
<TableCell align="right">{formatCurrency(row.cierreAnterior, 'USD')}</TableCell>
<TableCell align="right">{row.porcentajeCambio.toFixed(2)}%</TableCell>
<TableCell>{formatFullDateTime(row.fechaRegistro)}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
{/* Sección para Otros Tickers (solo para consulta) */}
{otherData && otherData.length > 0 && (
<Box mt={4}>
<Divider sx={{ mb: 2 }}>
<Typography variant="overline">Otros Tickers (Solo Consulta)</Typography>
</Divider>
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Ticker</TableCell>
<TableCell>Nombre</TableCell>
<TableCell align="right">Precio</TableCell>
</TableRow>
</TableHead>
<TableBody>
{otherData.map(row => (
<TableRow key={row.id}>
<TableCell>{row.ticker}</TableCell>
<TableCell>{row.nombreEmpresa}</TableCell>
<TableCell align="right">{formatCurrency(row.precioActual, 'USD')}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
)}
</Box>
);
};

View File

@@ -1,29 +1,32 @@
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button } from '@mui/material';
import { Box, CircularProgress, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button, Typography } from '@mui/material';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
// Importaciones de nuestro proyecto
import { useApiData } from '../../hooks/useApiData';
import { useIsHoliday } from '../../hooks/useIsHoliday';
import type { CotizacionGrano } from '../../models/mercadoModels';
import { formatInteger, formatDateOnly, formatFullDateTime } from '../../utils/formatters';
import { formatInteger, formatFullDateTime } from '../../utils/formatters';
import { copyToClipboard } from '../../utils/clipboardUtils';
import { HolidayAlert } from '../common/HolidayAlert';
/**
* Función para convertir los datos de la tabla a formato CSV.
* Función para convertir los datos a formato TSV (Tab-Separated Values)
* con el formato específico solicitado por redacción.
*/
const toCSV = (headers: string[], data: CotizacionGrano[]) => {
const headerRow = headers.join(';');
const dataRows = data.map(row =>
[
row.nombre,
formatInteger(row.precio),
formatInteger(row.variacionPrecio),
formatDateOnly(row.fechaOperacion),
formatFullDateTime(row.fechaRegistro)
].join(';')
);
return [headerRow, ...dataRows].join('\n');
const toTSV = (data: CotizacionGrano[]) => {
const dataRows = data.map(row => {
// Formateamos la variación para que muestre "=" si es cero.
const variacion = row.variacionPrecio === 0
? '= 0'
: formatInteger(row.variacionPrecio);
const precio = formatInteger(row.precio);
// Unimos los campos con un carácter de tabulación '\t'
return [row.nombre, precio, variacion].join('\t');
});
return dataRows.join('\n');
};
/**
@@ -31,24 +34,21 @@ const toCSV = (headers: string[], data: CotizacionGrano[]) => {
* diseñado para la página de redacción.
*/
export const RawGranosTable = () => {
// Hooks para obtener los datos y el estado de feriado para el mercado argentino.
const { data, loading: dataLoading, error: dataError } = useApiData<CotizacionGrano[]>('/mercados/granos');
const isHoliday = useIsHoliday('BA');
const handleCopy = () => {
if (!data) return;
const headers = ["Grano", "Precio ($/Tn)", "Variación", "Fecha Op.", "Fecha de Registro"];
const csvData = toCSV(headers, data);
const tsvData = toTSV(data);
copyToClipboard(csvData)
.then(() => alert('¡Tabla copiada al portapapeles!'))
copyToClipboard(tsvData)
.then(() => alert('Datos de Granos copiados al portapapeles!'))
.catch(err => {
console.error('Error al copiar:', err);
alert('Error: No se pudo copiar la tabla.');
});
};
// Estado de carga unificado.
const isLoading = dataLoading || isHoliday === null;
if (isLoading) return <CircularProgress />;
@@ -63,16 +63,21 @@ export const RawGranosTable = () => {
return (
<Box>
{/* Si es feriado, mostramos una alerta informativa encima de la tabla. */}
{isHoliday && (
<Box sx={{ mb: 2 }}>
<HolidayAlert />
</Box>
)}
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy} sx={{ mb: 1 }}>
Copiar como CSV
</Button>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
<Button startIcon={<ContentCopyIcon />} onClick={handleCopy}>
Copiar Datos para Redacción
</Button>
<Typography variant="caption" sx={{ fontStyle: 'italic', color: 'text.secondary' }}>
Última actualización: {formatFullDateTime(data[0].fechaRegistro)}
</Typography>
</Box>
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
@@ -80,8 +85,6 @@ export const RawGranosTable = () => {
<TableCell>Grano</TableCell>
<TableCell align="right">Precio ($/Tn)</TableCell>
<TableCell align="right">Variación</TableCell>
<TableCell>Fecha Op.</TableCell>
<TableCell>Última Act.</TableCell>
</TableRow>
</TableHead>
<TableBody>
@@ -89,9 +92,7 @@ export const RawGranosTable = () => {
<TableRow key={row.id}>
<TableCell>{row.nombre}</TableCell>
<TableCell align="right">${formatInteger(row.precio)}</TableCell>
<TableCell align="right">{formatInteger(row.variacionPrecio)}</TableCell>
<TableCell>{formatDateOnly(row.fechaOperacion)}</TableCell>
<TableCell>{formatFullDateTime(row.fechaRegistro)}</TableCell>
<TableCell align="right">{row.variacionPrecio === 0 ? '= 0' : formatInteger(row.variacionPrecio)}</TableCell>
</TableRow>
))}
</TableBody>

View File

@@ -0,0 +1,11 @@
export const TICKERS_PRIORITARIOS_LOCAL = [
'^MERV', 'GGAL.BA', 'YPFD.BA', 'PAMP.BA', 'BMA.BA',
'COME.BA', 'TECO2.BA', 'EDN.BA', 'CRES.BA', 'TXAR.BA',
'MIRG.BA', 'CEPU.BA', 'LOMA.BA', 'VALO.BA'
];
// Dejaremos las otras listas aquí para los siguientes componentes
export const TICKERS_PRIORITARIOS_USA = [
'AAPL', 'AMD', 'AMZN', 'BRK-B', 'KO', 'MSFT', 'NVDA',
'GLD', 'XLF', 'XLI', 'XLE', 'XLK', 'MELI'
];