Feat: Currency 2 Decimal Format - Fix: Charts Scale
This commit is contained in:
@@ -2,7 +2,7 @@ import { Box, CircularProgress, Alert } from '@mui/material';
|
||||
import type { CotizacionBolsa } from '../models/mercadoModels';
|
||||
import { useApiData } from '../hooks/useApiData';
|
||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
|
||||
import { formatFullDateTime } from '../utils/formatters';
|
||||
import { formatFullDateTime, formatCurrency2Decimal } from '../utils/formatters';
|
||||
|
||||
interface HistoricalChartWidgetProps {
|
||||
ticker: string;
|
||||
@@ -10,6 +10,11 @@ interface HistoricalChartWidgetProps {
|
||||
dias: number;
|
||||
}
|
||||
|
||||
// Formateador para el eje X que solo muestra día/mes
|
||||
const formatXAxis = (tickItem: string) => {
|
||||
return new Date(tickItem).toLocaleDateString('es-AR', { day: '2-digit', month: '2-digit' });
|
||||
};
|
||||
|
||||
const formatTooltipLabel = (label: string) => {
|
||||
return formatFullDateTime(label);
|
||||
};
|
||||
@@ -30,9 +35,18 @@ export const HistoricalChartWidget = ({ ticker, mercado, dias }: HistoricalChart
|
||||
return <Alert severity="info" sx={{ height: 300 }}>No hay suficientes datos históricos para graficar.</Alert>;
|
||||
}
|
||||
|
||||
// Formateador para el eje X que solo muestra día/mes
|
||||
const formatXAxis = (tickItem: string) => {
|
||||
return new Date(tickItem).toLocaleDateString('es-AR', { day: '2-digit', month: '2-digit' });
|
||||
// 1. Calcular el dominio del eje Y con un margen
|
||||
const prices = data.map(p => p.precioActual);
|
||||
const dataMin = Math.min(...prices);
|
||||
const dataMax = Math.max(...prices);
|
||||
const padding = (dataMax - dataMin) * 0.05; // 5% de padding
|
||||
const domainMin = Math.floor(dataMin - padding);
|
||||
const domainMax = Math.ceil(dataMax + padding);
|
||||
|
||||
// 2. Formateador de ticks para el eje Y más robusto
|
||||
const yAxisTickFormatter = (tick: number) => {
|
||||
// Usamos el formateador de moneda
|
||||
return `$${formatCurrency2Decimal(tick)}`;
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -40,13 +54,17 @@ export const HistoricalChartWidget = ({ ticker, mercado, dias }: HistoricalChart
|
||||
<LineChart data={data} margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="fechaRegistro" tickFormatter={formatXAxis} />
|
||||
<YAxis domain={['dataMin - dataMin * 0.02', 'dataMax + dataMax * 0.02']} tickFormatter={(tick) => `$${tick.toLocaleString('es-AR')}`} />
|
||||
<YAxis
|
||||
domain={[domainMin, domainMax]}
|
||||
tickFormatter={yAxisTickFormatter}
|
||||
width={80} // Damos un poco más de espacio para números grandes
|
||||
/>
|
||||
<Tooltip
|
||||
formatter={(value: number) => [`$${value.toFixed(2)}`, 'Precio']}
|
||||
formatter={(value: number) => [`$${formatCurrency2Decimal(value)}`, 'Precio']}
|
||||
labelFormatter={formatTooltipLabel}
|
||||
/>
|
||||
<Legend />
|
||||
<Line type="monotone" dataKey="precioActual" name="Precio de Cierre" stroke="#028fbe" strokeWidth={2} dot={false} />
|
||||
<Line type="monotone" dataKey="precioActual" name="Precio de Cierre" stroke="#8884d8" strokeWidth={2} dot={false} />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
|
||||
import type { CotizacionBolsa } from '../models/mercadoModels';
|
||||
import { formatInteger, formatCurrency } from '../utils/formatters';
|
||||
import { formatInteger, formatCurrency, formatCurrency2Decimal } from '../utils/formatters';
|
||||
import { HistoricalChartWidget } from './HistoricalChartWidget';
|
||||
import { useApiData } from '../hooks/useApiData';
|
||||
|
||||
@@ -53,7 +53,7 @@ export const MervalHeroCard = () => {
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
|
||||
<Box>
|
||||
<Typography variant="h5" component="h2" sx={{ fontWeight: 'bold' }}>Índice S&P MERVAL</Typography>
|
||||
<Typography variant="h3" component="p" sx={{ fontWeight: 'bold', mt:1 }}>{formatInteger(mervalData.precioActual)}</Typography>
|
||||
<Typography variant="h3" component="p" sx={{ fontWeight: 'bold', mt:1 }}>{formatCurrency2Decimal(mervalData.precioActual)}</Typography>
|
||||
</Box>
|
||||
<Box sx={{ pt: 2 }}>
|
||||
<VariacionMerval actual={mervalData.precioActual} anterior={mervalData.cierreAnterior} />
|
||||
|
||||
@@ -11,6 +11,18 @@ export const formatCurrency = (num: number, currency = 'ARS') => {
|
||||
}).format(num);
|
||||
};
|
||||
|
||||
export const formatCurrency2Decimal = (num: number, currency = 'ARS') => {
|
||||
const style = currency === 'USD' ? 'currency' : 'decimal';
|
||||
const locale = currency === 'USD' ? 'en-US' : 'es-AR';
|
||||
|
||||
return new Intl.NumberFormat(locale, {
|
||||
style: style,
|
||||
currency: currency,
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(num);
|
||||
};
|
||||
|
||||
export const formatInteger = (num: number) => {
|
||||
return new Intl.NumberFormat('es-AR').format(num);
|
||||
};
|
||||
@@ -23,7 +35,7 @@ export const formatFullDateTime = (dateString: string) => {
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hourCycle: 'h23', // <--- LA CLAVE PARA EL FORMATO 24HS
|
||||
hourCycle: 'h23',
|
||||
timeZone: 'America/Argentina/Buenos_Aires',
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user