zoom in and zoom out of price chart

This commit is contained in:
Yinyin Liu 2026-06-12 12:38:38 +02:00
parent 4afeceea5d
commit c0fa353a17
5 changed files with 43 additions and 5 deletions

View File

@ -1,9 +1,10 @@
import React, { useEffect, useState } from 'react';
import { Box, Typography } from '@mui/material';
import { Box, Button, Typography } from '@mui/material';
import CircularProgress from '@mui/material/CircularProgress';
import RestartAltIcon from '@mui/icons-material/RestartAlt';
import { FormattedMessage, useIntl } from 'react-intl';
import ReactApexChart from 'react-apexcharts';
import { ApexOptions } from 'apexcharts';
import ApexCharts, { ApexOptions } from 'apexcharts';
import { I_S3Credentials } from 'src/interfaces/S3Types';
import { UnixTime, TimeSpan } from 'src/dataCache/time';
import {
@ -17,6 +18,7 @@ interface CurrentPriceChartProps {
}
const HISTORY_DAYS = 7;
const CHART_ID = 'current-price-history';
function CurrentPriceChart(props: CurrentPriceChartProps) {
const intl = useIntl();
@ -49,6 +51,14 @@ function CurrentPriceChart(props: CurrentPriceChartProps) {
};
}, [props.id]);
// Snap the x-axis back to the full history window after the user drag-zooms.
const handleResetZoom = () => {
if (!series || series.data.length === 0) return;
const minX = series.data[0][0];
const maxX = series.data[series.data.length - 1][0];
ApexCharts.exec(CHART_ID, 'zoomX', minX, maxX);
};
const title = (
<Typography variant="subtitle1" sx={{ fontWeight: 600, mb: 1 }}>
<FormattedMessage
@ -92,11 +102,13 @@ function CurrentPriceChart(props: CurrentPriceChartProps) {
const options: ApexOptions = {
chart: {
id: 'current-price-history',
id: CHART_ID,
type: 'line',
height: 300,
// Toolbar hidden — its zoom glyphs are easy to miss; we expose an explicit
// "Reset zoom" button instead. Drag-to-zoom still works via zoom.enabled.
toolbar: { show: false },
zoom: { autoScaleYaxis: true }
zoom: { enabled: true, type: 'x', autoScaleYaxis: true }
},
dataLabels: { enabled: false },
// Spot price is constant within each pricing interval -> stepped line
@ -138,7 +150,29 @@ function CurrentPriceChart(props: CurrentPriceChartProps) {
return (
<Box sx={{ mb: 2 }}>
{title}
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
mb: 1
}}
>
<Typography variant="subtitle1" sx={{ fontWeight: 600 }}>
<FormattedMessage
id="currentPriceHistory"
defaultMessage="Current Price (last 7 days)"
/>
</Typography>
<Button
size="small"
variant="outlined"
startIcon={<RestartAltIcon />}
onClick={handleResetZoom}
>
<FormattedMessage id="resetZoom" defaultMessage="Reset zoom" />
</Button>
</Box>
<ReactApexChart
options={options}
series={chartSeries}

View File

@ -592,6 +592,7 @@
"currentPrice": "Aktueller Preis",
"currentPriceHistory": "Aktueller Preis (letzte 7 Tage)",
"currentPriceNoData": "Keine Preishistorie für die letzten 7 Tage verfügbar.",
"resetZoom": "Zoom zurücksetzen",
"priceToSell": "Verkaufspreis",
"priceToBuy": "Kaufpreis",
"timeToSell": "Verkaufszeit",

View File

@ -340,6 +340,7 @@
"currentPrice": "Current Price",
"currentPriceHistory": "Current Price (last 7 days)",
"currentPriceNoData": "No price history available for the last 7 days.",
"resetZoom": "Reset zoom",
"priceToSell": "Price to Sell",
"priceToBuy": "Price to Buy",
"timeToSell": "Time to Sell",

View File

@ -592,6 +592,7 @@
"currentPrice": "Prix actuel",
"currentPriceHistory": "Prix actuel (7 derniers jours)",
"currentPriceNoData": "Aucun historique de prix disponible pour les 7 derniers jours.",
"resetZoom": "Réinitialiser le zoom",
"priceToSell": "Prix de vente",
"priceToBuy": "Prix d'achat",
"timeToSell": "Heure de vente",

View File

@ -592,6 +592,7 @@
"currentPrice": "Prezzo attuale",
"currentPriceHistory": "Prezzo attuale (ultimi 7 giorni)",
"currentPriceNoData": "Nessuno storico prezzi disponibile per gli ultimi 7 giorni.",
"resetZoom": "Reimposta zoom",
"priceToSell": "Prezzo di vendita",
"priceToBuy": "Prezzo di acquisto",
"timeToSell": "Orario di vendita",