diff --git a/src/assets/index.css b/src/assets/index.css index 40f116d..15464af 100644 --- a/src/assets/index.css +++ b/src/assets/index.css @@ -21,3 +21,8 @@ display: flex; flex-shrink: 1; } + +/* @cubing/icons 3.0.5 provides the FTO glyph under its former unofficial name. */ +.cubing-icon.event-fto:before { + content: '\f135'; +} diff --git a/src/components/RoundSelector/RoundListItem.tsx b/src/components/RoundSelector/RoundListItem.tsx index 388cc3d..62c54ae 100644 --- a/src/components/RoundSelector/RoundListItem.tsx +++ b/src/components/RoundSelector/RoundListItem.tsx @@ -1,4 +1,5 @@ import { + activityCodeToName, cumulativeGroupCount, findGroupActivitiesByRound, parseActivityCode, @@ -12,7 +13,7 @@ import { } from '../../store/selectors'; import '@cubing/icons'; import { Collapse, ListItemAvatar, ListItemButton, ListItemText } from '@mui/material'; -import { activityCodeToName, type Round } from '@wca/helpers'; +import { type Round } from '@wca/helpers'; import { useEffect, useRef } from 'react'; import { Link as RouterLink } from 'react-router-dom'; import type { AppState } from '../../store/initialState'; diff --git a/src/dialogs/ConfigureGroupDialog.tsx b/src/dialogs/ConfigureGroupDialog.tsx index 6377a8e..8b8b324 100644 --- a/src/dialogs/ConfigureGroupDialog.tsx +++ b/src/dialogs/ConfigureGroupDialog.tsx @@ -1,4 +1,8 @@ -import { generateNextChildActivityId, parseActivityCode } from '../lib/domain/activities'; +import { + activityCodeToName, + generateNextChildActivityId, + parseActivityCode, +} from '../lib/domain/activities'; import { useAppSelector } from '../store'; import { editActivity } from '../store/actions'; import { @@ -12,7 +16,7 @@ import { TextField, Typography, } from '@mui/material'; -import { type Activity, activityCodeToName } from '@wca/helpers'; +import { type Activity } from '@wca/helpers'; import { useEffect, useState } from 'react'; import { useDispatch } from 'react-redux'; diff --git a/src/dialogs/ConfigureGroupsDialog.tsx b/src/dialogs/ConfigureGroupsDialog.tsx index 7f3bac4..6951d9b 100644 --- a/src/dialogs/ConfigureGroupsDialog.tsx +++ b/src/dialogs/ConfigureGroupsDialog.tsx @@ -1,4 +1,8 @@ -import { createGroupActivity, findAllActivities } from '../lib/domain/activities'; +import { + activityCodeToName, + createGroupActivity, + findAllActivities, +} from '../lib/domain/activities'; import { formatTimeRange } from '../lib/utils/time'; import { useAppSelector, useAppDispatch } from '../store'; import { updateRoundChildActivities } from '../store/actions'; @@ -33,7 +37,7 @@ import { type GridRowModesModel, GridToolbarContainer, } from '@mui/x-data-grid'; -import { type Activity, activityCodeToName, parseActivityCode } from '@wca/helpers'; +import { type Activity, parseActivityCode } from '@wca/helpers'; import { formatDuration } from 'date-fns'; import { omit } from 'lodash'; import React, { Fragment, useCallback } from 'react'; diff --git a/src/lib/domain/activities/activityCode.test.ts b/src/lib/domain/activities/activityCode.test.ts index 2d8ff1c..a6da0b4 100644 --- a/src/lib/domain/activities/activityCode.test.ts +++ b/src/lib/domain/activities/activityCode.test.ts @@ -111,6 +111,12 @@ describe('activityCodeToName', () => { it('handles different event types', () => { expect(activityCodeToName('444bf-r1')).toBe('4x4x4 Blindfolded, Round 1'); }); + + it('handles FTO', () => { + expect(activityCodeToName('fto-r1-g2')).toBe( + 'Face-Turning Octahedron, Round 1, Group 2' + ); + }); }); describe('activityCodeIsChild', () => { diff --git a/src/lib/domain/events.test.ts b/src/lib/domain/events.test.ts index 339db13..3728a37 100644 --- a/src/lib/domain/events.test.ts +++ b/src/lib/domain/events.test.ts @@ -26,6 +26,7 @@ describe('eventNameById', () => { expect(eventNameById('333fm')).toBe('3x3x3 Fewest Moves'); expect(eventNameById('minx')).toBe('Megaminx'); expect(eventNameById('pyram')).toBe('Pyraminx'); + expect(eventNameById('fto')).toBe('Face-Turning Octahedron'); }); it('throws for unknown event ID', () => { @@ -45,6 +46,7 @@ describe('shortEventNameById', () => { expect(shortEventNameById('333fm')).toBe('FMC'); expect(shortEventNameById('333oh')).toBe('3OH'); expect(shortEventNameById('333mbf')).toBe('MBLD'); + expect(shortEventNameById('fto')).toBe('FTO'); }); it('throws for unknown event ID', () => { @@ -123,10 +125,11 @@ describe('sortWcifEvents', () => { { id: '333', rounds: [], extensions: [] }, { id: '222', rounds: [], extensions: [] }, { id: '444', rounds: [], extensions: [] }, + { id: 'fto' as Event['id'], rounds: [], extensions: [] }, ]; const sorted = sortWcifEvents(wcifEvents); - expect(sorted.map((e) => e.id)).toEqual(['333', '222', '444', 'minx']); + expect(sorted.map((e) => e.id)).toEqual(['333', '222', '444', 'minx', 'fto']); }); it('maintains order for events not in the standard list', () => { diff --git a/src/lib/domain/events.ts b/src/lib/domain/events.ts index 28ea7cf..c4efea0 100644 --- a/src/lib/domain/events.ts +++ b/src/lib/domain/events.ts @@ -1,6 +1,8 @@ -import { type Event, type EventId } from '@wca/helpers'; +import { type Event, type EventId as WcaEventId } from '@wca/helpers'; import { sortBy } from 'lodash'; +type EventId = WcaEventId | 'fto'; + interface EventInfo { id: EventId; name: string; @@ -22,6 +24,7 @@ export const events: EventInfo[] = [ { id: 'clock', name: 'Clock', shortName: 'Clock' }, { id: 'skewb', name: 'Skewb', shortName: 'Skewb' }, { id: 'sq1', name: 'Square-1', shortName: 'Sq1' }, + { id: 'fto', name: 'Face-Turning Octahedron', shortName: 'FTO' }, { id: '444bf', name: '4x4x4 Blindfolded', shortName: '4BLD' }, { id: '555bf', name: '5x5x5 Blindfolded', shortName: '5BLD' }, { id: '333mbf', name: '3x3x3 Multi-Blind', shortName: 'MBLD' },