clean(lme): remove previous/next navigation buttons from timeframe bar
This commit is contained in:
parent
8ec51d92a8
commit
24b3b3d6a3
|
|
@ -123,7 +123,6 @@ export function LmeView() {
|
||||||
const [diagramData, setDiagramData] = useState<DiagramResponse | null>(null);
|
const [diagramData, setDiagramData] = useState<DiagramResponse | null>(null);
|
||||||
const [diagramLoading, setDiagramLoading] = useState<boolean>(false);
|
const [diagramLoading, setDiagramLoading] = useState<boolean>(false);
|
||||||
const [timeframe, setTimeframe] = useState<Timeframe>("ENTIRE");
|
const [timeframe, setTimeframe] = useState<Timeframe>("ENTIRE");
|
||||||
const [offsetIndex, setOffsetIndex] = useState<number>(0);
|
|
||||||
|
|
||||||
// Visibility toggles for dual-series charts
|
// Visibility toggles for dual-series charts
|
||||||
const [showPrice, setShowPrice] = useState<boolean>(true);
|
const [showPrice, setShowPrice] = useState<boolean>(true);
|
||||||
|
|
@ -157,7 +156,6 @@ export function LmeView() {
|
||||||
|
|
||||||
let alive = true;
|
let alive = true;
|
||||||
setDiagramLoading(true);
|
setDiagramLoading(true);
|
||||||
setOffsetIndex(0);
|
|
||||||
setShowPrice(true);
|
setShowPrice(true);
|
||||||
setShowStocks(true);
|
setShowStocks(true);
|
||||||
|
|
||||||
|
|
@ -199,7 +197,7 @@ export function LmeView() {
|
||||||
return diagramData?.lines?.find((l) => l.series_type === "stocks");
|
return diagramData?.lines?.find((l) => l.series_type === "stocks");
|
||||||
}, [diagramData]);
|
}, [diagramData]);
|
||||||
|
|
||||||
// Filter main series by timeframe & offset
|
// Filter main series by timeframe
|
||||||
const chartData = useMemo(() => {
|
const chartData = useMemo(() => {
|
||||||
if (!diagramData?.lines?.length) return [];
|
if (!diagramData?.lines?.length) return [];
|
||||||
const baseLine = priceLine || diagramData.lines[0];
|
const baseLine = priceLine || diagramData.lines[0];
|
||||||
|
|
@ -213,12 +211,8 @@ export function LmeView() {
|
||||||
else if (timeframe === "2Y") sliceCount = 520;
|
else if (timeframe === "2Y") sliceCount = 520;
|
||||||
else if (timeframe === "ENTIRE") sliceCount = total;
|
else if (timeframe === "ENTIRE") sliceCount = total;
|
||||||
|
|
||||||
const maxOffset = Math.max(0, total - sliceCount);
|
const start = Math.max(0, total - sliceCount);
|
||||||
const effectiveOffset = Math.min(offsetIndex, maxOffset);
|
const windowPoints = baseLine.points.slice(start);
|
||||||
const end = total - effectiveOffset;
|
|
||||||
const start = Math.max(0, end - sliceCount);
|
|
||||||
|
|
||||||
const windowPoints = baseLine.points.slice(start, end);
|
|
||||||
|
|
||||||
if (stockLine) {
|
if (stockLine) {
|
||||||
const stockMap = new Map(stockLine.points.map((p) => [p.x, p.y]));
|
const stockMap = new Map(stockLine.points.map((p) => [p.x, p.y]));
|
||||||
|
|
@ -235,7 +229,7 @@ export function LmeView() {
|
||||||
date_display: p.date_display,
|
date_display: p.date_display,
|
||||||
priceVal: p.y,
|
priceVal: p.y,
|
||||||
}));
|
}));
|
||||||
}, [diagramData, priceLine, stockLine, timeframe, offsetIndex]);
|
}, [diagramData, priceLine, stockLine, timeframe]);
|
||||||
|
|
||||||
// Statistics calculation for the active window
|
// Statistics calculation for the active window
|
||||||
const stats = useMemo(() => {
|
const stats = useMemo(() => {
|
||||||
|
|
@ -256,26 +250,6 @@ export function LmeView() {
|
||||||
return { max, min, avg, diff, pct, first, last };
|
return { max, min, avg, diff, pct, first, last };
|
||||||
}, [chartData]);
|
}, [chartData]);
|
||||||
|
|
||||||
const canStepPrev = useMemo(() => {
|
|
||||||
if (timeframe === "ENTIRE") return false;
|
|
||||||
const total = (priceLine || diagramData?.lines?.[0])?.points?.length || 0;
|
|
||||||
const count = timeframe === "3M" ? 65 : timeframe === "6M" ? 130 : timeframe === "1Y" ? 260 : 520;
|
|
||||||
return offsetIndex + count < total;
|
|
||||||
}, [timeframe, priceLine, diagramData, offsetIndex]);
|
|
||||||
|
|
||||||
const canStepNext = useMemo(() => {
|
|
||||||
return offsetIndex > 0 && timeframe !== "ENTIRE";
|
|
||||||
}, [offsetIndex, timeframe]);
|
|
||||||
|
|
||||||
const stepWindow = (dir: "prev" | "next") => {
|
|
||||||
const step = timeframe === "3M" ? 22 : timeframe === "6M" ? 45 : timeframe === "1Y" ? 65 : 130;
|
|
||||||
if (dir === "prev") {
|
|
||||||
setOffsetIndex((prev) => prev + step);
|
|
||||||
} else {
|
|
||||||
setOffsetIndex((prev) => Math.max(0, prev - step));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const filteredMetals = useMemo(() => {
|
const filteredMetals = useMemo(() => {
|
||||||
if (!data?.metals) return [];
|
if (!data?.metals) return [];
|
||||||
if (!search.trim()) return data.metals;
|
if (!search.trim()) return data.metals;
|
||||||
|
|
@ -569,7 +543,9 @@ export function LmeView() {
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-start justify-between border-b border-border/60 pb-4">
|
<div className="flex items-start justify-between border-b border-border/60 pb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-12 h-12 rounded-2xl grid place-items-center border shrink-0 bg-primary/10 border-primary/30">
|
<div
|
||||||
|
className="w-12 h-12 rounded-2xl grid place-items-center border shrink-0 bg-primary/10 border-primary/30"
|
||||||
|
>
|
||||||
<LineChartIcon className="w-6 h-6 text-primary" />
|
<LineChartIcon className="w-6 h-6 text-primary" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -636,7 +612,7 @@ export function LmeView() {
|
||||||
<div className="flex flex-wrap items-center justify-between gap-3 border-b border-border/40 pb-3">
|
<div className="flex flex-wrap items-center justify-between gap-3 border-b border-border/40 pb-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xs font-semibold text-foreground">راهنمای رنگها:</span>
|
<span className="text-xs font-semibold text-foreground">راهنمای رنگها:</span>
|
||||||
|
|
||||||
{/* Price Line Toggle */}
|
{/* Price Line Toggle */}
|
||||||
{priceLine && (
|
{priceLine && (
|
||||||
<button
|
<button
|
||||||
|
|
@ -726,7 +702,7 @@ export function LmeView() {
|
||||||
hide={!showPrice}
|
hide={!showPrice}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Left Y-Axis for Warehouse Stocks (Scaled properly!) */}
|
{/* Left Y-Axis for Warehouse Stocks */}
|
||||||
{stockLine && (
|
{stockLine && (
|
||||||
<YAxis
|
<YAxis
|
||||||
yAxisId="stocks"
|
yAxisId="stocks"
|
||||||
|
|
@ -794,7 +770,7 @@ export function LmeView() {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Stock Curve (Mapped to Left Y-Axis!) */}
|
{/* Stock Curve (Mapped to Left Y-Axis) */}
|
||||||
{showStocks && stockLine && (
|
{showStocks && stockLine && (
|
||||||
<Line
|
<Line
|
||||||
yAxisId="stocks"
|
yAxisId="stocks"
|
||||||
|
|
@ -811,25 +787,12 @@ export function LmeView() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* TIMEFRAME BAR (100% Persian) */}
|
{/* TIMEFRAME BAR (Clean pills without قبلی / بعدی) */}
|
||||||
<div className="pt-3 border-t border-border/40 flex flex-wrap items-center justify-center gap-2" dir="rtl">
|
<div className="pt-3 border-t border-border/40 flex flex-wrap items-center justify-center gap-2" dir="rtl">
|
||||||
{/* Step Backwards */}
|
|
||||||
<button
|
|
||||||
onClick={() => stepWindow("prev")}
|
|
||||||
disabled={!canStepPrev}
|
|
||||||
className="rounded-xl border border-border/80 bg-background/80 px-3 py-1.5 text-xs text-foreground transition hover:bg-accent disabled:opacity-30 disabled:cursor-not-allowed"
|
|
||||||
title="نمایش دادههای قدیمیتر"
|
|
||||||
>
|
|
||||||
> قبلی
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* 3 months */}
|
{/* 3 months */}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setTimeframe("3M")}
|
||||||
setTimeframe("3M");
|
className={`rounded-xl border px-4 py-1.5 text-xs font-semibold transition ${
|
||||||
setOffsetIndex(0);
|
|
||||||
}}
|
|
||||||
className={`rounded-xl border px-3.5 py-1.5 text-xs font-semibold transition ${
|
|
||||||
timeframe === "3M"
|
timeframe === "3M"
|
||||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||||
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||||
|
|
@ -840,11 +803,8 @@ export function LmeView() {
|
||||||
|
|
||||||
{/* 6 months */}
|
{/* 6 months */}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setTimeframe("6M")}
|
||||||
setTimeframe("6M");
|
className={`rounded-xl border px-4 py-1.5 text-xs font-semibold transition ${
|
||||||
setOffsetIndex(0);
|
|
||||||
}}
|
|
||||||
className={`rounded-xl border px-3.5 py-1.5 text-xs font-semibold transition ${
|
|
||||||
timeframe === "6M"
|
timeframe === "6M"
|
||||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||||
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||||
|
|
@ -855,11 +815,8 @@ export function LmeView() {
|
||||||
|
|
||||||
{/* 1 year */}
|
{/* 1 year */}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setTimeframe("1Y")}
|
||||||
setTimeframe("1Y");
|
className={`rounded-xl border px-4 py-1.5 text-xs font-semibold transition ${
|
||||||
setOffsetIndex(0);
|
|
||||||
}}
|
|
||||||
className={`rounded-xl border px-3.5 py-1.5 text-xs font-semibold transition ${
|
|
||||||
timeframe === "1Y"
|
timeframe === "1Y"
|
||||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||||
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||||
|
|
@ -870,11 +827,8 @@ export function LmeView() {
|
||||||
|
|
||||||
{/* 2 year */}
|
{/* 2 year */}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setTimeframe("2Y")}
|
||||||
setTimeframe("2Y");
|
className={`rounded-xl border px-4 py-1.5 text-xs font-semibold transition ${
|
||||||
setOffsetIndex(0);
|
|
||||||
}}
|
|
||||||
className={`rounded-xl border px-3.5 py-1.5 text-xs font-semibold transition ${
|
|
||||||
timeframe === "2Y"
|
timeframe === "2Y"
|
||||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||||
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||||
|
|
@ -885,11 +839,8 @@ export function LmeView() {
|
||||||
|
|
||||||
{/* entire data (ACTIVE HIGHLIGHT) */}
|
{/* entire data (ACTIVE HIGHLIGHT) */}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setTimeframe("ENTIRE")}
|
||||||
setTimeframe("ENTIRE");
|
className={`rounded-xl border px-5 py-1.5 text-xs font-bold transition ${
|
||||||
setOffsetIndex(0);
|
|
||||||
}}
|
|
||||||
className={`rounded-xl border px-4 py-1.5 text-xs font-bold transition ${
|
|
||||||
timeframe === "ENTIRE"
|
timeframe === "ENTIRE"
|
||||||
? "border-primary bg-primary text-primary-foreground shadow-md ring-2 ring-primary/20"
|
? "border-primary bg-primary text-primary-foreground shadow-md ring-2 ring-primary/20"
|
||||||
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
: "border-border/80 bg-background/80 text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||||
|
|
@ -897,16 +848,6 @@ export function LmeView() {
|
||||||
>
|
>
|
||||||
کل دادهها (تاریخچه کامل)
|
کل دادهها (تاریخچه کامل)
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Step Forwards */}
|
|
||||||
<button
|
|
||||||
onClick={() => stepWindow("next")}
|
|
||||||
disabled={!canStepNext}
|
|
||||||
className="rounded-xl border border-border/80 bg-background/80 px-3 py-1.5 text-xs text-foreground transition hover:bg-accent disabled:opacity-30 disabled:cursor-not-allowed"
|
|
||||||
title="نمایش دادههای جدیدتر"
|
|
||||||
>
|
|
||||||
بعدی <
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue