Skip to content

Commit 553eb4c

Browse files
te-ceclaude
andcommitted
feat(table,sprint): honor category description setting in labels
The table column headers and the sprint report rows still showed the raw category name when preferCategoryDescriptionAsPrimary was enabled. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent e4de57b commit 553eb4c

5 files changed

Lines changed: 71 additions & 4 deletions

File tree

src/features/sprint/SprintReportPanel.test.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@ describe('SprintReportPanel', () => {
3030
expect(screen.getAllByText('0.00h')).toHaveLength(2)
3131
})
3232

33+
it('shows the description as the primary label when preferCategoryDescriptionAsPrimary is set', () => {
34+
render(
35+
<SprintReportPanel
36+
hoursPerCategory={{ QA: 3 }}
37+
allCategories={['QA']}
38+
categoryDescriptions={{ QA: 'Quality assurance' }}
39+
preferCategoryDescriptionAsPrimary
40+
/>,
41+
)
42+
expect(screen.getByText('Quality assurance')).toBeInTheDocument()
43+
expect(screen.getByText('QA')).toBeInTheDocument()
44+
})
45+
46+
it('keeps the category name primary when the preference is off', () => {
47+
render(
48+
<SprintReportPanel
49+
hoursPerCategory={{ QA: 3 }}
50+
allCategories={['QA']}
51+
categoryDescriptions={{ QA: 'Quality assurance' }}
52+
/>,
53+
)
54+
expect(screen.getByText('QA')).toBeInTheDocument()
55+
expect(screen.getByText('Quality assurance')).toBeInTheDocument()
56+
})
57+
3358
it('formats fractional hours correctly in both formats', () => {
3459
render(<SprintReportPanel hoursPerCategory={{ Dev: 1.75 }} allCategories={['Dev']} />)
3560
expect(screen.getAllByText('1.75h')).toHaveLength(2)

src/features/sprint/SprintReportPanel.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import { formatHours } from '../../shared/formatHours'
2+
import { categoryDisplay } from '../day/categoryLabel'
23

34
interface Props {
45
hoursPerCategory: Record<string, number>
56
allCategories: string[]
7+
categoryDescriptions?: Record<string, string> | undefined
8+
preferCategoryDescriptionAsPrimary?: boolean | undefined
69
}
710

8-
export function SprintReportPanel({ hoursPerCategory, allCategories }: Props) {
11+
export function SprintReportPanel({
12+
hoursPerCategory,
13+
allCategories,
14+
categoryDescriptions,
15+
preferCategoryDescriptionAsPrimary,
16+
}: Props) {
917
const total = allCategories.reduce((sum, cat) => sum + (hoursPerCategory[cat] ?? 0), 0)
1018
const maxHours = Math.max(...allCategories.map((c) => hoursPerCategory[c] ?? 0), 1)
1119

@@ -15,12 +23,22 @@ export function SprintReportPanel({ hoursPerCategory, allCategories }: Props) {
1523
<tbody>
1624
{allCategories.map((category, i) => {
1725
const hours = hoursPerCategory[category] ?? 0
26+
const { primary, secondary } = categoryDisplay(
27+
category,
28+
categoryDescriptions ?? {},
29+
preferCategoryDescriptionAsPrimary ?? false,
30+
)
1831
return (
1932
<tr
2033
key={category}
2134
className={i % 2 === 0 ? 'bg-white dark:bg-gray-800' : 'bg-gray-50 dark:bg-gray-800/60'}
2235
>
23-
<td className="px-3 py-1.5 font-medium">{category}</td>
36+
<td className="px-3 py-1.5 font-medium">
37+
{primary}
38+
{secondary && (
39+
<span className="ml-2 text-xs font-normal text-gray-400 dark:text-gray-500">{secondary}</span>
40+
)}
41+
</td>
2442
<td className="w-32 px-3 py-1.5">
2543
<div className="h-1.5 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700">
2644
<div

src/features/sprint/SprintView.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,12 @@ export function SprintView() {
106106
onSprintIndexChange={setSprintIndex}
107107
today={today}
108108
/>
109-
<SprintReportPanel hoursPerCategory={hoursPerCategory} allCategories={allCategories} />
109+
<SprintReportPanel
110+
hoursPerCategory={hoursPerCategory}
111+
allCategories={allCategories}
112+
categoryDescriptions={config.categoryDescriptions}
113+
preferCategoryDescriptionAsPrimary={config.preferCategoryDescriptionAsPrimary}
114+
/>
110115
</>
111116
)}
112117
<SprintConfigPanel

src/features/table/CategoryColumnHeader.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,20 @@ describe('CategoryColumnHeader', () => {
4040
expect(screen.getByRole('columnheader')).toBeInTheDocument()
4141
expect(screen.getByText('SUPPORT')).toBeInTheDocument()
4242
})
43+
44+
it('renders the description as header text when preferCategoryDescriptionAsPrimary is set', () => {
45+
setup({
46+
categoryDescriptions: { _SUPPORT: 'Customer support tasks' },
47+
preferCategoryDescriptionAsPrimary: true,
48+
})
49+
expect(screen.getByText('Customer support tasks')).toBeInTheDocument()
50+
expect(screen.queryByText('SUPPORT')).not.toBeInTheDocument()
51+
})
52+
53+
it('falls back to the category name when the preference is set but no description exists', () => {
54+
setup({ preferCategoryDescriptionAsPrimary: true })
55+
expect(screen.getByText('SUPPORT')).toBeInTheDocument()
56+
})
4357
})
4458

4559
describe('tooltip', () => {

src/features/table/CategoryColumnHeader.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ function displayCategoryName(cat: string): string {
3131
return cat.replace(/^_/, '')
3232
}
3333

34+
function headerText(cat: string, description: string | undefined, preferDescription: boolean): string {
35+
return preferDescription && description ? description : displayCategoryName(cat)
36+
}
37+
3438
function handleRenameKeyDown(
3539
e: React.KeyboardEvent<HTMLInputElement>,
3640
cat: string,
@@ -148,6 +152,7 @@ export function CategoryColumnHeader({
148152
colDragOverIdx === catIdx ? 'ring-2 ring-inset ring-indigo-500 bg-indigo-50 dark:bg-indigo-900/40' : ''
149153
const color = colorForCategory(cat, allCategories)
150154
const nameClass = `block truncate text-[11px] ${color.text} ${onCategoryRename ? 'cursor-text' : ''}`
155+
const headerLabel = headerText(cat, description, preferCategoryDescriptionAsPrimary ?? false)
151156
const tooltipContent = (
152157
<CategoryTooltipContent
153158
cat={cat}
@@ -194,7 +199,7 @@ export function CategoryColumnHeader({
194199
}
195200
}}
196201
>
197-
{displayCategoryName(cat)}
202+
{headerLabel}
198203
</span>
199204
</Tooltip>
200205
)}

0 commit comments

Comments
 (0)