Skip to content

Commit c51efef

Browse files
committed
Create GrowthPieChart and redesign history analytics layout
1 parent 520e656 commit c51efef

2 files changed

Lines changed: 198 additions & 6 deletions

File tree

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import React, { useMemo } from 'react';
2+
import { ResponsiveContainer, PieChart, Pie, Cell, Tooltip, Legend } from 'recharts';
3+
import { useTheme, alpha, Box, Typography, Paper } from '@mui/material';
4+
import { useHistoryContext } from '../HistoryContext';
5+
import { useHistoryData } from '../hooks/useHistoryData';
6+
import { shorten } from '../../../../util';
7+
import ChartContainer from '../Components/ChartContainer';
8+
9+
const GrowthPieChart = ({ title, icon, color, prefix, names }) => {
10+
const theme = useTheme();
11+
const { timeRange, customRange } = useHistoryContext();
12+
const { filteredData } = useHistoryData(timeRange, customRange);
13+
14+
const pieData = useMemo(() => {
15+
if (!filteredData || filteredData.length < 2) return [];
16+
17+
const start = filteredData[0];
18+
const end = filteredData[filteredData.length - 1];
19+
20+
const data = names.map((name, i) => {
21+
const key = `${prefix}_${i}`;
22+
const valStart = Number(start[key]) || 0;
23+
const valEnd = Number(end[key]) || 0;
24+
const growth = Math.max(0, valEnd - valStart);
25+
26+
return {
27+
name,
28+
value: growth,
29+
originalTotal: valEnd,
30+
index: i
31+
};
32+
}).filter(item => item.value > 0);
33+
34+
return data.sort((a, b) => b.value - a.value);
35+
}, [filteredData, names, prefix]);
36+
37+
const totalGrowth = useMemo(() => pieData.reduce((acc, curr) => acc + curr.value, 0), [pieData]);
38+
39+
const CustomTooltip = ({ active, payload }) => {
40+
if (active && payload && payload.length) {
41+
const data = payload[0].payload;
42+
const percentage = totalGrowth > 0 ? ((data.value / totalGrowth) * 100).toFixed(1) : 0;
43+
44+
return (
45+
<Paper
46+
elevation={10}
47+
sx={{
48+
p: 1.5,
49+
bgcolor: alpha(theme.palette.background.paper, 0.95),
50+
backdropFilter: 'blur(8px)',
51+
border: `1px solid ${theme.palette.divider}`,
52+
borderRadius: 2,
53+
minWidth: 160
54+
}}
55+
>
56+
<Typography variant="subtitle2" sx={{ fontWeight: 800, color: 'text.primary', mb: 0.5, borderBottom: `1px solid ${theme.palette.divider}`, pb: 0.5 }}>
57+
{data.name}
58+
</Typography>
59+
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5, mt: 1 }}>
60+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 2 }}>
61+
<Typography variant="caption" color="text.secondary">Levels Up:</Typography>
62+
<Typography variant="body2" sx={{ fontWeight: 800, color: 'success.main' }}>+{shorten(data.value)}</Typography>
63+
</Box>
64+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 2 }}>
65+
<Typography variant="caption" color="text.secondary">Focus %:</Typography>
66+
<Typography variant="body2" sx={{ fontWeight: 800 }}>{percentage}%</Typography>
67+
</Box>
68+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 2, mt: 0.5, pt: 0.5, borderTop: `1px dashed ${theme.palette.divider}` }}>
69+
<Typography variant="caption" color="text.secondary">Current Lvl:</Typography>
70+
<Typography variant="caption" sx={{ fontWeight: 700 }}>{shorten(data.originalTotal)}</Typography>
71+
</Box>
72+
</Box>
73+
</Paper>
74+
);
75+
}
76+
return null;
77+
};
78+
79+
if (pieData.length === 0) {
80+
return (
81+
<ChartContainer title={title} icon={icon} color={color}>
82+
<Box sx={{ height: 380, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column' }}>
83+
<Typography variant="h6" color="text.disabled" sx={{ fontWeight: 800 }}>+ 0</Typography>
84+
<Typography variant="body2" color="text.disabled">No levels gained in this period</Typography>
85+
</Box>
86+
</ChartContainer>
87+
);
88+
}
89+
90+
return (
91+
<ChartContainer title={title} icon={icon} color={color}>
92+
<Box sx={{ height: 380, position: 'relative' }}>
93+
{/* Center text showing Total Growth */}
94+
<Box sx={{
95+
position: 'absolute',
96+
top: '50%',
97+
left: '50%',
98+
transform: 'translate(-50%, -50%)',
99+
textAlign: 'center',
100+
pointerEvents: 'none',
101+
zIndex: 0
102+
}}>
103+
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', fontWeight: 700, mb: -0.5 }}>
104+
TOTAL GAIN
105+
</Typography>
106+
<Typography variant="h5" sx={{ fontWeight: 900, color: theme.palette.text.primary }}>
107+
+{shorten(totalGrowth)}
108+
</Typography>
109+
</Box>
110+
111+
<ResponsiveContainer width="100%" height="100%">
112+
<PieChart>
113+
<Pie
114+
data={pieData}
115+
cx="50%"
116+
cy="50%"
117+
innerRadius={90}
118+
outerRadius={140}
119+
paddingAngle={2}
120+
dataKey="value"
121+
stroke="none"
122+
cornerRadius={4}
123+
animationDuration={1000}
124+
>
125+
{pieData.map((entry, index) => {
126+
// Calculate hue based on original index to maintain consistent colors
127+
const hue = (entry.index * (360 / Math.max(names.length, 1))) % 360;
128+
const fillColor = `hsl(${hue}, 70%, 55%)`;
129+
return <Cell key={`cell-${index}`} fill={fillColor} />;
130+
})}
131+
</Pie>
132+
<Tooltip content={<CustomTooltip />} />
133+
<Legend
134+
verticalAlign="bottom"
135+
height={36}
136+
content={(props) => {
137+
const { payload } = props;
138+
return (
139+
<Box sx={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: 1.5, mt: 2 }}>
140+
{payload.map((entry, index) => (
141+
<Box key={`item-${index}`} sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
142+
<Box sx={{ width: 10, height: 10, borderRadius: '50%', bgcolor: entry.color }} />
143+
<Typography variant="caption" sx={{ fontWeight: 600, color: 'text.secondary' }}>
144+
{entry.value}
145+
</Typography>
146+
</Box>
147+
))}
148+
</Box>
149+
);
150+
}}
151+
/>
152+
</PieChart>
153+
</ResponsiveContainer>
154+
</Box>
155+
</ChartContainer>
156+
);
157+
};
158+
159+
export default GrowthPieChart;

src/components/Content/History/index.js

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import MainProgressChart from './Charts/MainProgressChart';
77
import BossProgressChart from './Charts/BossProgressChart';
88
import ResourceChart from './Charts/ResourceChart';
99
import StackedAreaChart from './Charts/StackedAreaChart';
10+
import GrowthPieChart from './Charts/GrowthPieChart';
1011
import HistoryTable from './HistoryTable';
1112
import CustomRangePicker from './Components/CustomRangePicker';
1213
import { History as HistoryIcon, Analytics, FlashOn, AutoFixHigh, Code } from '@mui/icons-material';
@@ -154,36 +155,68 @@ const DashboardLayout = () => {
154155
</Typography>
155156

156157
<Grid container spacing={3}>
157-
<Grid item xs={12} md={6}>
158+
{/* ---------- ENERGY NGU ROW ---------- */}
159+
<Grid item xs={12} lg={8}>
158160
<StackedAreaChart
159-
title="Energy NGU Levels"
161+
title="Energy NGU Progression"
160162
icon={FlashOn}
161163
color="secondary"
162164
prefix="ngu_e"
163165
names={nguNames}
164166
baseColorHue={0}
165167
/>
166168
</Grid>
167-
<Grid item xs={12} md={6}>
169+
<Grid item xs={12} lg={4}>
170+
<GrowthPieChart
171+
title="Energy NGU Focus Target"
172+
icon={FlashOn}
173+
color="secondary"
174+
prefix="ngu_e"
175+
names={nguNames}
176+
/>
177+
</Grid>
178+
179+
{/* ---------- MAGIC NGU ROW ---------- */}
180+
<Grid item xs={12} lg={8}>
168181
<StackedAreaChart
169-
title="Magic NGU Levels"
182+
title="Magic NGU Progression"
170183
icon={AutoFixHigh}
171184
color="info"
172185
prefix="ngu_m"
173186
names={magicNguNames}
174187
baseColorHue={180}
175188
/>
176189
</Grid>
177-
<Grid item xs={12}>
190+
<Grid item xs={12} lg={4}>
191+
<GrowthPieChart
192+
title="Magic NGU Focus Target"
193+
icon={AutoFixHigh}
194+
color="info"
195+
prefix="ngu_m"
196+
names={magicNguNames}
197+
/>
198+
</Grid>
199+
200+
{/* ---------- HACKS ROW ---------- */}
201+
<Grid item xs={12} lg={8}>
178202
<StackedAreaChart
179-
title="Hack Levels"
203+
title="Hack Levels Timeline"
180204
icon={Code}
181205
color="success"
182206
prefix="hack"
183207
names={hackNames}
184208
baseColorHue={120}
185209
/>
186210
</Grid>
211+
<Grid item xs={12} lg={4}>
212+
<GrowthPieChart
213+
title="Hack Levels Gained"
214+
icon={Code}
215+
color="success"
216+
prefix="hack"
217+
names={hackNames}
218+
/>
219+
</Grid>
187220

188221
{/* Less important charts moved here */}
189222
<Grid item xs={12} lg={8} sx={{ mt: 4 }}>

0 commit comments

Comments
 (0)