added logic to only show 7 or 6 bars based on daily period or not
This commit is contained in:
@@ -11,6 +11,9 @@ import {
|
|||||||
HistoryChartProps,
|
HistoryChartProps,
|
||||||
ChartData,
|
ChartData,
|
||||||
} from "../types/historyChart";
|
} from "../types/historyChart";
|
||||||
|
import IconButton from "@mui/material/IconButton";
|
||||||
|
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
|
||||||
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||||
|
|
||||||
const formatDisplay = (
|
const formatDisplay = (
|
||||||
point: ChartDataPoint,
|
point: ChartDataPoint,
|
||||||
@@ -99,6 +102,32 @@ export default function HistoryChart({
|
|||||||
)
|
)
|
||||||
: 1;
|
: 1;
|
||||||
|
|
||||||
|
const [startIndex, setStartIndex] = React.useState(0);
|
||||||
|
const visibleCount = activeDataKey == 'daily' ? 7 : 6;
|
||||||
|
const total = currentData.length;
|
||||||
|
|
||||||
|
// clamp startIndex so we always show full 5 (when possible)
|
||||||
|
const clampedStartIndex = Math.min(
|
||||||
|
startIndex,
|
||||||
|
Math.max(total - visibleCount, 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
const visibleData = currentData.slice(
|
||||||
|
clampedStartIndex,
|
||||||
|
clampedStartIndex + visibleCount
|
||||||
|
);
|
||||||
|
|
||||||
|
const canGoLeft = startIndex > 0;
|
||||||
|
const canGoRight = startIndex + visibleCount < currentData.length;
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
if (canGoLeft) setStartIndex((prev) => prev - visibleCount);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
if (canGoRight) setStartIndex((prev) => prev + visibleCount);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
sx={{
|
sx={{
|
||||||
@@ -159,116 +188,158 @@ export default function HistoryChart({
|
|||||||
</ToggleButtonGroup>
|
</ToggleButtonGroup>
|
||||||
|
|
||||||
{currentData.length > 0 ? (
|
{currentData.length > 0 ? (
|
||||||
<Box sx={{ display: "flex", alignItems: "flex-end", height: 220, mt: 4 }}>
|
<Box sx={{ position: "relative", mt: 4 }}>
|
||||||
{currentData.map((point) => {
|
|
||||||
const currentHeight = (point.amount / maxAmount) * 100;
|
|
||||||
const compareHeight = comparison
|
|
||||||
? ((point.compareAmount || 0) / maxAmount) * 100
|
|
||||||
: 0;
|
|
||||||
const labelHeight = Math.max(currentHeight, compareHeight);
|
|
||||||
|
|
||||||
return (
|
{/* LEFT ARROW */}
|
||||||
<Box
|
{canGoLeft && (
|
||||||
key={point.id}
|
<IconButton
|
||||||
sx={{
|
onClick={handlePrev}
|
||||||
flex: 1,
|
size="small"
|
||||||
display: "flex",
|
sx={{
|
||||||
flexDirection: "column",
|
position: "absolute",
|
||||||
alignItems: "center",
|
left: 0,
|
||||||
justifyContent: "flex-end",
|
top: "50%",
|
||||||
height: "100%"
|
transform: "translateY(-50%)",
|
||||||
}}
|
zIndex: 2,
|
||||||
>
|
bgcolor: "background.paper",
|
||||||
|
boxShadow: 1
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ChevronLeftIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* CHART */}
|
||||||
|
<Box sx={{ display: "flex", alignItems: "flex-end", height: 220, mt: 4 }}>
|
||||||
|
{visibleData.map((point) => {
|
||||||
|
const currentHeight = (point.amount / maxAmount) * 100;
|
||||||
|
const compareHeight = comparison
|
||||||
|
? ((point.compareAmount || 0) / maxAmount) * 100
|
||||||
|
: 0;
|
||||||
|
const labelHeight = Math.max(currentHeight, compareHeight);
|
||||||
|
|
||||||
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
key={point.id}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
flex: 1,
|
||||||
alignItems: "flex-end",
|
|
||||||
gap: comparison ? 0.5 : 0,
|
|
||||||
height: "100%",
|
|
||||||
position: "relative"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
variant="caption"
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
bottom: `${labelHeight}%`,
|
|
||||||
left: "50%",
|
|
||||||
transform: "translate(-50%, -6px)",
|
|
||||||
fontSize: "0.65rem",
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
pointerEvents: "none"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{formatDisplay(point, activeTab.toLowerCase(), comparison)}
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
{/* Compare */}
|
|
||||||
{comparison && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: 6,
|
|
||||||
height: `${compareHeight}%`,
|
|
||||||
bgcolor: "grey.400",
|
|
||||||
borderRadius: 2
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Spacer */}
|
|
||||||
<Box sx={{ width: 4 }} />
|
|
||||||
|
|
||||||
{/* Current */}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: 10,
|
|
||||||
height: `${currentHeight}%`,
|
|
||||||
bgcolor: point.highlighted ? "error.main" : "primary.main",
|
|
||||||
borderRadius: 2
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
mt: 1,
|
|
||||||
textAlign: "center",
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
lineHeight: 1.1
|
justifyContent: "flex-end",
|
||||||
|
height: "100%"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography
|
<Box
|
||||||
variant="caption"
|
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: "0.7rem",
|
display: "flex",
|
||||||
opacity: 0.7,
|
alignItems: "flex-end",
|
||||||
color: "text.primary",
|
gap: comparison ? 0.5 : 0,
|
||||||
|
height: "100%",
|
||||||
|
position: "relative"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{formatLabel(point.id, activeDataKey)}
|
<Typography
|
||||||
</Typography>
|
variant="caption"
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: `${labelHeight}%`,
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -6px)",
|
||||||
|
fontSize: "0.65rem",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
pointerEvents: "none"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatDisplay(point, activeTab.toLowerCase(), comparison)}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
<Typography
|
{/* Compare */}
|
||||||
variant="caption"
|
{comparison && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: 6,
|
||||||
|
height: `${compareHeight}%`,
|
||||||
|
bgcolor: "grey.400",
|
||||||
|
borderRadius: 2
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Spacer */}
|
||||||
|
<Box sx={{ width: 4 }} />
|
||||||
|
|
||||||
|
{/* Current */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: 10,
|
||||||
|
height: `${currentHeight}%`,
|
||||||
|
bgcolor: point.highlighted ? "error.main" : "primary.main",
|
||||||
|
borderRadius: 2
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: "0.65rem",
|
mt: 1,
|
||||||
color: "grey.400",
|
textAlign: "center",
|
||||||
visibility:
|
display: "flex",
|
||||||
comparison && point.compareLabel && activeDataKey !== "daily"
|
flexDirection: "column",
|
||||||
? "visible"
|
alignItems: "center",
|
||||||
: "hidden"
|
lineHeight: 1.1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{point.compareLabel
|
<Typography
|
||||||
? formatLabel(point.compareLabel, activeDataKey)
|
variant="caption"
|
||||||
: "placeholder"}
|
sx={{
|
||||||
</Typography>
|
fontSize: "0.7rem",
|
||||||
|
opacity: 0.7,
|
||||||
|
color: "text.primary",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatLabel(point.id, activeDataKey)}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
sx={{
|
||||||
|
fontSize: "0.65rem",
|
||||||
|
color: "grey.400",
|
||||||
|
visibility:
|
||||||
|
comparison && point.compareLabel && activeDataKey !== "daily"
|
||||||
|
? "visible"
|
||||||
|
: "hidden"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{point.compareLabel
|
||||||
|
? formatLabel(point.compareLabel, activeDataKey)
|
||||||
|
: "placeholder"}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
</Box>
|
||||||
|
|
||||||
|
{/* RIGHT ARROW */}
|
||||||
|
{canGoRight && (
|
||||||
|
<IconButton
|
||||||
|
onClick={handleNext}
|
||||||
|
size="small"
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
right: 0,
|
||||||
|
top: "50%",
|
||||||
|
transform: "translateY(-50%)",
|
||||||
|
zIndex: 2,
|
||||||
|
bgcolor: "background.paper",
|
||||||
|
boxShadow: 1
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ChevronRightIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Box sx={{ height: 200, display: "flex", alignItems: "center", justifyContent: "center" }}>
|
<Box sx={{ height: 200, display: "flex", alignItems: "center", justifyContent: "center" }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user