fix(tours): give the snowboard a corner glyph of its own

Snowboarding used the snowflake, the same glyph the winter hike label
shows in the same corner badge, so a snowboard track looked like a winter
hike in lists and the day plan. It now draws a board with its bindings.
This commit is contained in:
Maurice
2026-10-20 14:52:15 +02:00
parent fcdb7e48cd
commit dfe11e9c4c
2 changed files with 36 additions and 7 deletions
@@ -2,9 +2,17 @@ import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import { TourDayRowAvatar } from '../TourDayRowFacts';
import { TourGradeTile } from '../tourParts';
import { SkiCornerMark, SkiHeadPill, skiClassificationText, skiDisciplineOf, skiTechniqueOf } from './skiMarks';
import { WINTER_ACTIVITY_ICON } from '../winter/winterMarks';
import {
SKI_DISCIPLINE_ICON,
SkiCornerMark,
SkiHeadPill,
skiClassificationText,
skiDisciplineOf,
skiTechniqueOf,
} from './skiMarks';
// FE-TOUR-SKI-MARK-001 to FE-TOUR-SKI-MARK-005
// FE-TOUR-SKI-MARK-001 to FE-TOUR-SKI-MARK-006
const t = (key: string) => key;
const skiTrack = {
@@ -39,6 +47,8 @@ describe('ski marks (SKI-02)', () => {
const mark = screen.getByRole('img', { name: 'tours.ski.discipline.snowboard' });
expect(mark).toHaveAttribute('data-testid', 'tour-ski-mark');
expect(mark).toHaveStyle({ width: '20px', height: '20px' });
expect(mark.querySelector('svg.lucide-snowboard')).not.toBeNull();
expect(mark.querySelector('svg.lucide-snowflake')).toBeNull();
});
it('FE-TOUR-SKI-MARK-003: the head pill names the discipline with a cross-country technique inside it', () => {
@@ -68,4 +78,9 @@ describe('ski marks (SKI-02)', () => {
rerender(<TourDayRowAvatar tour={skiTrack} size={50} />);
expect(screen.getByTestId('tour-ski-mark')).toHaveStyle({ width: '22px' });
});
it('FE-TOUR-SKI-MARK-006: no discipline shares its corner glyph with another, nor with a winter label', () => {
const icons = [...Object.values(SKI_DISCIPLINE_ICON), ...Object.values(WINTER_ACTIVITY_ICON)];
expect(new Set(icons).size).toBe(icons.length);
});
});
+19 -5
View File
@@ -1,18 +1,32 @@
import type { SkiDiscipline, SkiTechnique, TourListItem } from '@trek/shared';
import { CableCar, Snowflake, Spline, TrendingUp, type LucideIcon } from 'lucide-react';
import { CableCar, createLucideIcon, Spline, TrendingUp, type LucideIcon } from 'lucide-react';
import { useTranslation } from '../../../i18n';
import { fs } from '../../shared/DialogShell';
import { Tooltip } from '../../shared/Tooltip';
import { TourCornerMark } from '../TourCornerMark';
/**
* SKI-02: the icon each discipline goes by: a lift for alpine skiing, a
* snowflake for the board, a winding trail for cross-country and the climb on
* skins for ski touring.
* SKI-02: a snowboard seen from above, laid across the square with its two
* bindings. Lucide has no board, and the snowflake is the winter hike's mark
* (HIK-01): both sit in the same corner badge, so the board needs a glyph of
* its own to be told apart there.
*/
const BOARD = 'rotate(-45 12 12)';
const Snowboard = createLucideIcon('snowboard', [
['rect', { x: '1.5', y: '8.5', width: '21', height: '7', rx: '3.5', transform: BOARD, key: 'board' }],
['path', { d: 'M8.5 10v4', transform: BOARD, key: 'binding-front' }],
['path', { d: 'M15.5 10v4', transform: BOARD, key: 'binding-back' }],
]);
/**
* SKI-02: the icon each discipline goes by: a lift for alpine skiing, a board
* for snowboarding, a winding trail for cross-country and the climb on skins
* for ski touring. None of them is the winter hike's snowflake, which takes
* the same corner of a tile.
*/
export const SKI_DISCIPLINE_ICON: Record<SkiDiscipline, LucideIcon> = {
alpine: CableCar,
snowboard: Snowflake,
snowboard: Snowboard,
cross_country: Spline,
touring: TrendingUp,
};