Skip to content

Commit 0d2ea6e

Browse files
committed
Resolved Merge Conflicts
1 parent 0dd8441 commit 0d2ea6e

2 files changed

Lines changed: 182 additions & 207 deletions

File tree

src/components/common/PieChart/PieChart.jsx

Lines changed: 99 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ import { CHART_RADIUS, CHART_SIZE } from './constants';
55
import { generateArrayOfUniqColors } from './colorsGenerator';
66
import './UserProjectPieChart.css';
77

8-
export const PieChart = ({
8+
export function PieChart({
99
tasksData = [], // New array format: [{ projectId: "123", projectName: "Project A", totalTime: 10.5 }, ...]
1010
pieChartId,
1111
darkMode,
12-
projectsData = []
13-
}) => {
14-
15-
if (!tasksData || tasksData.length === 0) return <div>Loading</div>;
12+
projectsData = [],
13+
}) {
1614
const [totalHours, setTotalHours] = useState(0);
1715
const colors = useMemo(() => generateArrayOfUniqColors(tasksData?.length), [tasksData]);
1816
const color = useMemo(() => d3.scaleOrdinal().range(colors), [colors]);
1917

2018
const [togglePercentage, setTogglePercentage] = useState(false);
21-
const [selectedProjects, setSelectedProjects] = useState(tasksData?.map(project => project.projectId));
19+
const [selectedProjects, setSelectedProjects] = useState(
20+
tasksData?.map(project => project.projectId),
21+
);
2222

2323
const handleTogglePercentage = () => {
2424
setTogglePercentage(prev => {
@@ -27,13 +27,14 @@ export const PieChart = ({
2727
if (!newToggleState) {
2828
setSelectedProjects(tasksData?.map(project => project.projectId));
2929
}
30+
return newToggleState;
3031
});
3132
};
32-
const calculateTotalHours = (projectsData, tasksData) => {
33-
const totalTaskTime = tasksData?.reduce((sum, project) => sum + project.totalTime, 0);
34-
const projectsDataTime= projectsData.reduce((sum, project) => sum + project.totalTime, 0);
35-
return totalTaskTime+projectsDataTime;
36-
}
33+
const calculateTotalHours = (projectsdata, tasksdata) => {
34+
const totalTaskTime = tasksdata?.reduce((sum, project) => sum + project.totalTime, 0);
35+
const projectsDataTime = projectsdata.reduce((sum, project) => sum + project.totalTime, 0);
36+
return totalTaskTime + projectsDataTime;
37+
};
3738

3839
const handleProjectClick = projectId => {
3940
if (togglePercentage) {
@@ -46,7 +47,7 @@ export const PieChart = ({
4647
};
4748

4849
const getCreateSvgPie = totalValue => {
49-
if(totalValue === 0) return;
50+
if (totalValue === 0) return;
5051
// Clear existing SVG before creating new one
5152
d3.select(`#pie-chart-${pieChartId}`).remove();
5253
const svg = d3
@@ -57,55 +58,67 @@ export const PieChart = ({
5758
.attr('height', CHART_SIZE)
5859
.append('g')
5960
.attr('transform', `translate(${CHART_SIZE / 2}, ${CHART_SIZE / 2})`);
60-
61+
6162
const displayValue = togglePercentage
62-
// ? (selectedProjects.reduce((sum, projectId) => {
63-
// const project = tasksData.find(p => p.projectId === projectId);
64-
// return sum + (project ? project.totalTime : 0);
65-
// }, 0) / totalValue) * 100
66-
// : totalValue;
67-
? (totalValue / calculateTotalHours(projectsData, tasksData)) * 100
68-
: totalValue;
69-
63+
? // ? (selectedProjects.reduce((sum, projectId) => {
64+
// const project = tasksData.find(p => p.projectId === projectId);
65+
// return sum + (project ? project.totalTime : 0);
66+
// }, 0) / totalValue) * 100
67+
// : totalValue;
68+
(totalValue / calculateTotalHours(projectsData, tasksData)) * 100
69+
: totalValue;
70+
7071
svg
7172
.append('text')
7273
.attr('text-anchor', 'middle')
7374
.style('fill', darkMode ? 'white' : 'black')
7475
.text(
7576
togglePercentage
76-
? `${displayValue.toFixed(2)}% of ${calculateTotalHours(projectsData,tasksData).toFixed(2)}`
77+
? `${displayValue.toFixed(2)}% of ${calculateTotalHours(projectsData, tasksData).toFixed(
78+
2,
79+
)}`
7780
: totalValue.toFixed(2),
7881
);
79-
82+
8083
svg
8184
.append('foreignObject')
8285
.attr('x', -40)
8386
.attr('y', 10)
8487
.attr('width', 80)
8588
.attr('height', 40)
8689
.append('xhtml:div')
87-
.html(`
90+
.html(
91+
`
8892
<label class="switch">
8993
<input type="checkbox" ${togglePercentage ? 'checked' : ''} />
9094
<span class="slider"></span>
9195
</label>
92-
`)
96+
`,
97+
)
9398
.select('input')
9499
.on('change', handleTogglePercentage); // Use the existing React handler
95100

96-
return svg;
101+
// return svg;
97102
};
98-
103+
99104
const pie = d3.pie().value(d => d.totalTime);
100105

101106
useEffect(() => {
102107
if (!tasksData || tasksData.length === 0) {
103-
return;
104-
}
108+
return undefined;
109+
}
105110
const totalValue = tasksData?.reduce((sum, project) => sum + project.totalTime, 0);
106-
if(totalValue === 0) return;
111+
107112
setTotalHours(totalValue);
108113

114+
if (totalValue === 0) {
115+
return undefined;
116+
}
117+
118+
if (!tasksData || tasksData.length === 0) {
119+
return <div>Loading</div>;
120+
}
121+
109122
const dataReady = pie(tasksData);
110123

111124
let div = d3.select('.tooltip-donut');
@@ -119,10 +132,11 @@ export const PieChart = ({
119132
.style('pointer-events', 'none');
120133
}
121134

122-
const svg= getCreateSvgPie(totalValue)
123-
if (!svg) return; // Early return if no svg created
135+
const svg = getCreateSvgPie(totalValue);
136+
if (!svg) return undefined; // Early return if no svg created
124137
// Create the pie chart
125-
svg.selectAll('path')
138+
svg
139+
.selectAll('path')
126140
.data(dataReady)
127141
.join('path')
128142
.attr(
@@ -132,65 +146,19 @@ export const PieChart = ({
132146
.innerRadius(70)
133147
.outerRadius(CHART_RADIUS),
134148
)
135-
//.attr('fill', d => color(d.data[0]))
136-
//.style('opacity', d => (selectedTasks.includes(d.data[0]) ? 1 : 0.1))
137-
//.on('click', (event, d) => handleTaskClick(d.data[0]))
138-
//.on('mouseover', function handleMouseOver(d, i) {
139-
// d3.select(this)
140-
// .transition()
141-
// .duration('50')
142-
// .attr('opacity', '.5');
143-
// div
144-
// .transition()
145-
// .duration(50)
146-
// .style('opacity', 1)
147-
// .style('visibility', 'visible');
148-
// const taskName = Object.keys(chartLegend).map(key => {
149-
// return chartLegend[key][0];
150-
// });
151-
// const index = Object.keys(chartLegend)
152-
// .map(function(e) {
153-
// return e;
154-
// })
155-
// .indexOf(i.data[0]);
156-
// const legendInfo = taskName[index].toString();
157-
// const taskName = chartLegend[i.data[0]][0];
158-
// const taskValue = i.value;
159-
// const percentage = ((taskValue / totalValue) * 100).toFixed(2);
160-
161-
162149
.attr('fill', d => color(d.data.projectId))
163150
.style('opacity', d => (selectedProjects.includes(d.data.projectId) ? 1 : 0.1))
164151
.on('click', (event, d) => handleProjectClick(d.data.projectId))
165152
.on('mouseover', (event, d) => {
166-
d3.select(event.currentTarget).transition().duration(50).attr('opacity', 0.5);
153+
d3.select(event.currentTarget)
154+
.transition()
155+
.duration(50)
156+
.attr('opacity', 0.5);
167157
const percentage = ((d.data.totalTime / totalValue) * 100).toFixed(2);
168158
const legendInfo = togglePercentage
169159
? `${d.data.projectName}: ${percentage}% of ${totalValue.toFixed(2)}`
170160
: `${d.data.projectName}: ${d.data.totalTime.toFixed(2)} Hours`;
171161

172-
//const containerWidth = document.getElementById(`pie-chart-container-${pieChartId}`)
173-
// .offsetWidth;
174-
//const tooltipWidth = div.node().offsetWidth;
175-
//const mouseX = d.pageX;
176-
177-
//const tooltipX =
178-
//mouseX + 10 + tooltipWidth > containerWidth ? mouseX - tooltipWidth - 10 : mouseX + 10;
179-
180-
//div.style('left', `${tooltipX}px`).style('top', `${d.pageY - 15}px`);
181-
//})
182-
//.on('mouseout', function handleMouseOut() {
183-
// d3.select(this)
184-
// .transition()
185-
// .duration('50')
186-
// .attr('opacity', '.85');
187-
// div
188-
// .transition()
189-
// .duration('50')
190-
// .style('opacity', 0)
191-
// .on('end', function hideTooltip() {
192-
// d3.select(this).style('visibility', 'hidden'); // Hide after transition
193-
// });
194162
div
195163
.html(legendInfo)
196164
.style('max-width', '150px')
@@ -200,73 +168,63 @@ export const PieChart = ({
200168
.style('left', `${event.pageX + 10}px`)
201169
.style('top', `${event.pageY - 15}px`);
202170
})
203-
.on('mouseout', function () {
204-
d3.select(this).transition().duration(50).attr('opacity', 1);
205-
div.transition().duration(50).style('opacity', 0).on('end', function () {
206-
d3.select(this).style('visibility', 'hidden');
207-
});
171+
.on('mouseout', function handleMouseOut() {
172+
d3.select(this)
173+
.transition()
174+
.duration(50)
175+
.attr('opacity', 1);
176+
div
177+
.transition()
178+
.duration(50)
179+
.style('opacity', 0)
180+
.on('end', function hideToolTip() {
181+
d3.select(this).style('visibility', 'hidden');
182+
});
208183
});
209184

210185
return () => {
211186
d3.select(`#pie-chart-${pieChartId}`).remove();
212187
};
213188
}, [tasksData, togglePercentage, selectedProjects]);
214189

215-
216-
217-
return (
218-
!tasksData || tasksData?.length===0? <div>Loading</div> :<div className={`pie-chart-wrapper ${darkMode ? 'text-light' : ''}`}>
190+
return !tasksData || tasksData?.length === 0 ? (
191+
<div>Loading</div>
192+
) : (
193+
<div className={`pie-chart-wrapper ${darkMode ? 'text-light' : ''}`}>
219194
<div id={`pie-chart-container-${pieChartId}`} className="pie-chart" />
220-
//<div className="pie-chart-legend-container">
221-
// <div className="pie-chart-legend-header">
222-
// <div>Name</div>
223-
// <div>{dataLegendHeader}</div>
224-
// </div>
225-
// {Object.keys(dataLegend).map(key => (
226-
// <div key={key} className="pie-chart-legend-item">
227-
// <div className="data-legend-color" style={{ backgroundColor: color(key) }} />
228-
// <div className="data-legend-info">
229-
// {dataLegend[key].map((legendPart, index) => (
230-
// <div
231-
// className={`data-legend-info-part ${darkMode ? 'text-light' : ''}`}
232-
// eslint-disable-next-line react/no-array-index-key
233-
// key={index}
234-
// >
235-
// {legendPart}
236-
// </div>
237-
// ))}
238-
// </div>
239-
// </div>
240-
// ))}
241-
// <div className="data-total-value">Total Hours : {totalHours.toFixed(2)}</div>
242-
<div className="pie-chart-legend-container">
243-
<div className="pie-chart-legend-table-wrapper">
244-
<table className={darkMode ?"pie-chart-legend-table-dark":"pie-chart-legend-table"}>
245-
<thead>
246-
<tr>
247-
<th>Color</th>
248-
<th>Project Name</th>
249-
<th>Hours</th>
250-
</tr>
251-
</thead>
252-
<tbody>
253-
{tasksData?.map(project => (
254-
<tr key={project.projectId}>
255-
<td>
256-
<div id="project-chart-legend" style={{ backgroundColor: `${color(project.projectId)}`}}></div>
257-
</td>
258-
<td>{project.projectName}</td>
259-
<td>{project.totalTime.toFixed(2)} </td>
195+
<div className="pie-chart-legend-container">
196+
<div className="pie-chart-legend-table-wrapper">
197+
<table className={darkMode ? 'pie-chart-legend-table-dark' : 'pie-chart-legend-table'}>
198+
<thead>
199+
<tr>
200+
<th>Color</th>
201+
<th>Project Name</th>
202+
<th>Hours</th>
260203
</tr>
261-
))}
262-
</tbody>
263-
</table>
264-
</div>
265-
266-
<div className="data-total-value">
267-
<strong>Total Hours:</strong> {totalHours.toFixed(2)}
204+
</thead>
205+
<tbody>
206+
{tasksData?.map(project => (
207+
<tr key={project.projectId}>
208+
<td>
209+
<div
210+
id="project-chart-legend"
211+
style={{ backgroundColor: `${color(project.projectId)}` }}
212+
/>
213+
</td>
214+
<td>{project.projectName}</td>
215+
<td>{project.totalTime.toFixed(2)} </td>
216+
</tr>
217+
))}
218+
</tbody>
219+
</table>
220+
</div>
221+
222+
<div className="data-total-value">
223+
<strong>Total Hours:</strong> {totalHours.toFixed(2)}
224+
</div>
268225
</div>
269226
</div>
270-
</div>
271227
);
272-
};
228+
}
229+
230+
export default PieChart;

0 commit comments

Comments
 (0)