diff --git a/docs/AI_USAGE.md b/docs/AI_USAGE.md index bc5eb73..d428a79 100644 --- a/docs/AI_USAGE.md +++ b/docs/AI_USAGE.md @@ -371,3 +371,14 @@ - **Review:** The team reviewed the theme changes and confirmed the colors should come from the existing CSS variables rather than new palette values. + +## The variant letter in the element title (`src/lib/catalog.ts`, `src/components/elements/`, `src/components/ui/ElementVariants.tsx`) + +- **Tool:** Claude Code +- **What the team did:** Wrote issue #94 and chose to show the letter only when the + code has other variants. In the review, the team found that the card test also + passed without the letter, that the diagram alt text was the same for every + variant, and that an id in another format would give a strange title, and asked + for a smaller solution. +- **What Claude did:** Checked that all 836 ids in `data/` end in "-" and a letter, + wrote `displayCode` and the tests, and fixed the review points. diff --git a/src/components/elements/ElementDetailHeader.test.tsx b/src/components/elements/ElementDetailHeader.test.tsx new file mode 100644 index 0000000..fe746b9 --- /dev/null +++ b/src/components/elements/ElementDetailHeader.test.tsx @@ -0,0 +1,36 @@ +import { renderToString } from 'react-dom/server' +import { MemoryRouter } from 'react-router-dom' +import { describe, expect, it } from 'vitest' +import type { ElementDetail } from '@/lib/catalog' +import ElementDetailHeader from './ElementDetailHeader' + +const element: ElementDetail = { + id: 'UB-2.305-a', + code: '2.305', + name: null, + description: 'Giant circle with hop', + value: 0.5, + isVault: false, + apparatusId: 'UB', + apparatusName: 'Uneven bars', + elementGroupName: 'Giant circles', + imageUrl: null, + variants: [], +} + +const titleOf = (detail: ElementDetail) => + /]*>(.*?)<\/h1>/.exec( + renderToString( + + + , + ), + )?.[1] + +describe('ElementDetailHeader', () => { + it('gives two variants of the same code different titles', () => { + const b = { ...element, id: 'UB-2.305-b' } + expect(titleOf({ ...element, variants: [b] })).toBe('2.305-a') + expect(titleOf({ ...b, variants: [element] })).toBe('2.305-b') + }) +}) diff --git a/src/components/elements/ElementDetailHeader.tsx b/src/components/elements/ElementDetailHeader.tsx index 7c35d3d..70eabdb 100644 --- a/src/components/elements/ElementDetailHeader.tsx +++ b/src/components/elements/ElementDetailHeader.tsx @@ -1,6 +1,6 @@ import { ArrowLeft } from 'lucide-react' import { useNavigate } from 'react-router-dom' -import type { ElementDetail } from '@/lib/catalog' +import { displayCode, type ElementDetail } from '@/lib/catalog' export default function ElementDetailHeader({ element, @@ -22,7 +22,7 @@ export default function ElementDetailHeader({

- {element.code} + {displayCode(element, element.variants.length > 0)} {element.name && ( <> diff --git a/src/components/elements/ElementDiagram.tsx b/src/components/elements/ElementDiagram.tsx index 1f0ca8a..4b23503 100644 --- a/src/components/elements/ElementDiagram.tsx +++ b/src/components/elements/ElementDiagram.tsx @@ -1,5 +1,5 @@ import { Card, CardContent } from '@/components/ui/card' -import type { ElementDetail } from '@/lib/catalog' +import { displayCode, type ElementDetail } from '@/lib/catalog' export default function ElementDiagram({ element, @@ -13,7 +13,7 @@ export default function ElementDiagram({ {element.imageUrl ? ( {`Illustration 0)}${element.name ? `: ${element.name}` : ''}`} className="block h-auto w-full object-contain" /> ) : ( diff --git a/src/components/ui/ElementVariants.test.tsx b/src/components/ui/ElementVariants.test.tsx index 2db38d7..17565aa 100644 --- a/src/components/ui/ElementVariants.test.tsx +++ b/src/components/ui/ElementVariants.test.tsx @@ -24,6 +24,8 @@ describe('ElementVariants', () => { expect(markup).toMatch(/Variants of this element.*1.*<\/h2>/) expect(markup).toContain('href="/elements/UB-1.101-b"') + // In the h3, since the link address also contains "1.101-b". + expect(markup).toMatch(/]*>1\.101-b<\/h3>/) expect(markup).toContain('Glide kip with half turn') expect(markup).toContain('Difficulty ') expect(markup).toContain('Value ') diff --git a/src/components/ui/ElementVariants.tsx b/src/components/ui/ElementVariants.tsx index 7cb74bf..63996b7 100644 --- a/src/components/ui/ElementVariants.tsx +++ b/src/components/ui/ElementVariants.tsx @@ -2,7 +2,7 @@ import { Link } from 'react-router-dom' import { Card, CardContent, CardTitle } from '@/components/ui/card' import DifficultyBadge from '@/components/ui/DifficultyBadge' import ElementValueBadge from '@/components/ui/ElementValueBadge' -import type { CatalogVariant } from '@/lib/catalog' +import { displayCode, type CatalogVariant } from '@/lib/catalog' import { getDifficultyLetter } from '@/lib/difficulty' export default function ElementVariants({ @@ -39,7 +39,8 @@ export default function ElementVariants({
- {variant.code} + {/* A card is only here because the code has several variants. */} + {displayCode(variant, true)} {variant.name && ` · ${variant.name}`}

diff --git a/src/lib/catalog.test.ts b/src/lib/catalog.test.ts index 13b7d6e..d3bb3a6 100644 --- a/src/lib/catalog.test.ts +++ b/src/lib/catalog.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { buildImageUrl, getElementDetail } from './catalog' +import { buildImageUrl, displayCode, getElementDetail } from './catalog' describe('getElementDetail', () => { it('returns catalog metadata, other variants, and the diagram URL', async () => { @@ -32,3 +32,12 @@ describe('buildImageUrl', () => { expect(buildImageUrl('/', 'UB', 'a.webp')).toBe('/data/images/UB/a.webp') }) }) + +describe('displayCode', () => { + it('adds the variant letter only when the code has other variants', () => { + const item = { id: 'UB-2.305-b', code: '2.305' } + expect(displayCode(item, true)).toBe('2.305-b') + expect(displayCode(item, false)).toBe('2.305') + expect(displayCode({ id: 'UB-2.305', code: '2.305' }, true)).toBe('2.305') + }) +}) diff --git a/src/lib/catalog.ts b/src/lib/catalog.ts index e6091e2..8261305 100644 --- a/src/lib/catalog.ts +++ b/src/lib/catalog.ts @@ -50,6 +50,19 @@ export function buildImageUrl( return `${baseUrl.replace(/\/+$/, '')}/data/images/${apparatusId}/${image}` } +/** + * The code to show: "2.305-b" when the code has other variants, so they can be + * told apart, and "2.305" otherwise. An id that does not end in "-" and a + * letter gives the code alone. + */ +export function displayCode( + item: Pick, + hasOtherVariants: boolean, +): string { + const letter = /-([a-z])$/.exec(item.id)?.[1] + return hasOtherVariants && letter ? `${item.code}-${letter}` : item.code +} + function toCatalogVariant(record: CatalogRecord): CatalogVariant { const isVault = 'dValue' in record