From 8adcd6c417597a58c657b674fd5b4bece2e0446d Mon Sep 17 00:00:00 2001 From: Gabriel Menezes Date: Mon, 2 Nov 2026 13:17:00 -0400 Subject: [PATCH] fix(dashboard): center donut chart text dead-center inside donut hole --- .../dashboard/CategoryTimePieChart.tsx | 177 +++++++++--------- 1 file changed, 91 insertions(+), 86 deletions(-) diff --git a/frontend/src/components/dashboard/CategoryTimePieChart.tsx b/frontend/src/components/dashboard/CategoryTimePieChart.tsx index a579020..c82990f 100644 --- a/frontend/src/components/dashboard/CategoryTimePieChart.tsx +++ b/frontend/src/components/dashboard/CategoryTimePieChart.tsx @@ -103,10 +103,10 @@ export const CategoryTimePieChart: React.FC = ({ }, [tasks, startDate, endDate, isAllPeriod, activeTaskId, activeSeconds]) // SVG Donut geometry - const size = 180 + const size = 190 const center = size / 2 - const radius = 64 - const strokeWidth = 22 + const radius = 68 + const strokeWidth = 24 const circumference = 2 * Math.PI * radius const hoveredItem = categoryList.find((c) => c.id === hoveredId) || null @@ -156,92 +156,97 @@ export const CategoryTimePieChart: React.FC = ({ ) : (
{/* Donut Chart (Left 5 cols) */} -
- - {/* Background Track Circle */} - - - {/* Slices */} - {categoryList.map((item) => { - const sliceRatio = item.seconds / totalSeconds - const sliceLength = sliceRatio * circumference - const gap = categoryList.length > 1 ? 2.5 : 0 - const actualLength = Math.max(0, sliceLength - gap) - const offset = -accumulatedLength - accumulatedLength += sliceLength - - const isHovered = hoveredId === item.id - const currentStrokeWidth = isHovered ? strokeWidth + 4 : strokeWidth - - return ( - setHoveredId(item.id)} - onMouseLeave={() => setHoveredId(null)} - /> - ) - })} - - - {/* Donut Hole Center Content (Absolute) */} +
- {hoveredItem ? ( -
- - {hoveredItem.name} - -

- {formatSecondsToTimer(hoveredItem.seconds)} -

- - {hoveredItem.percentage.toFixed(1)}% do tempo - -
- ) : ( -
- - Total Auditado - -

- {formatSecondsToTimer(totalSeconds)} -

- - {categoryList.length} {categoryList.length === 1 ? 'categoria' : 'categorias'} - -
- )} + + {/* Background Track Circle */} + + + {/* Slices */} + {categoryList.map((item) => { + const sliceRatio = item.seconds / totalSeconds + const sliceLength = sliceRatio * circumference + const gap = categoryList.length > 1 ? 2.5 : 0 + const actualLength = Math.max(0, sliceLength - gap) + const offset = -accumulatedLength + accumulatedLength += sliceLength + + const isHovered = hoveredId === item.id + const currentStrokeWidth = isHovered ? strokeWidth + 4 : strokeWidth + + return ( + setHoveredId(item.id)} + onMouseLeave={() => setHoveredId(null)} + /> + ) + })} + + + {/* Donut Hole Center Content (Absolute & Dead Centered) */} +
+ {hoveredItem ? ( +
+ + {hoveredItem.name} + +

+ {formatSecondsToTimer(hoveredItem.seconds)} +

+ + {hoveredItem.percentage.toFixed(1)}% do tempo + +
+ ) : ( +
+ + Total Auditado + +

+ {formatSecondsToTimer(totalSeconds)} +

+ + {categoryList.length} {categoryList.length === 1 ? 'categoria' : 'categorias'} + +
+ )} +