Skip to content

Commit 74c86dc

Browse files
Merge pull request #267 from OneBusAway/feat/hide-agency-prefixes-ui
Feat/hide-agency-prefixes-ui
2 parents bd19185 + 960af42 commit 74c86dc

8 files changed

Lines changed: 81 additions & 16 deletions

File tree

src/components/RouteItem.svelte

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
<script>
2+
import { removeAgencyPrefix } from '$lib/utils';
3+
24
let { handleModalRouteClick, route } = $props();
35
46
function getDisplayRouteName() {
5-
if (route.shortName && route.longName) {
6-
return `${route.shortName} - ${route.longName}`;
7-
} else if (route.shortName && route.description) {
8-
return `${route.shortName} - ${route.description}`;
9-
} else if (!route.shortName && (route.longName || route.description)) {
7+
const cleanShortName = route.shortName ? removeAgencyPrefix(route.shortName) : null;
8+
9+
if (cleanShortName && route.longName) {
10+
return `${cleanShortName} - ${route.longName}`;
11+
} else if (cleanShortName && route.description) {
12+
return `${cleanShortName} - ${route.description}`;
13+
} else if (!cleanShortName && (route.longName || route.description)) {
1014
return `${route.agencyInfo.name} - ${route.longName || route.description}`;
1115
}
1216
}

src/components/search/SearchPane.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import TripPlan from '$components/trip-planner/TripPlan.svelte';
1313
import { isMapLoaded } from '$src/stores/mapStore';
1414
import { answeredSurveys, surveyStore } from '$stores/surveyStore';
15+
import { removeAgencyPrefix } from '$lib/utils';
1516
1617
let {
1718
clearPolylines,
@@ -171,7 +172,7 @@
171172
<SearchResultItem
172173
on:click={() => handleRouteClick(route)}
173174
icon={prioritizedRouteTypeForDisplay(route.type)}
174-
title={`${$t('route')} ${route.nullSafeShortName || route.id}`}
175+
title={`${$t('route')} ${removeAgencyPrefix(route.nullSafeShortName || route.id)}`}
175176
subtitle={route.description}
176177
/>
177178
{/each}

src/components/stops/StopPageHeader.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import { page } from '$app/stores';
88
99
import { t } from 'svelte-i18n';
10+
import { removeAgencyPrefix } from '$lib/utils';
1011
let { stopName, stopId, stopDirection } = $props();
1112
</script>
1213

@@ -30,7 +31,7 @@
3031
<div class="rounded-md bg-gray-50 px-2 py-1">
3132
<FontAwesomeIcon icon={faMapMarkerAlt} />
3233
<strong>{$t('schedule_for_stop.stop_id')}:</strong>
33-
{stopId}
34+
{removeAgencyPrefix(stopId)}
3435
</div>
3536
<div class="rounded-md bg-gray-50 px-2 py-1">
3637
<CompassArrow {stopDirection} />

src/components/stops/StopPane.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import HeroQuestion from '$components/surveys/HeroQuestion.svelte';
1616
import analytics from '$lib/Analytics/PlausibleAnalytics';
1717
import { filterActiveAlerts } from '$components/service-alerts/serviceAlertsHelper';
18+
import { removeAgencyPrefix } from '$lib/utils';
1819
1920
/**
2021
* @typedef {Object} Props
@@ -184,7 +185,7 @@
184185
class="relative flex flex-col gap-y-1 rounded-lg bg-brand-secondary bg-opacity-80 p-4"
185186
>
186187
<h1 class="h1 mb-0 text-white">{stop.name}</h1>
187-
<h2 class="h2 mb-0 text-white">{$t('stop')} #{stop.id}</h2>
188+
<h2 class="h2 mb-0 text-white">{$t('stop')} #{removeAgencyPrefix(stop.id)}</h2>
188189
{#if routeShortNames && routeShortNames.length > 0}
189190
<h2 class="h2 mb-0 text-white">{$t('routes')}: {routeShortNames.join(', ')}</h2>
190191
{/if}

src/components/stops/__tests__/StopPageHeader.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ describe('StopPageHeader', () => {
6969
render(StopPageHeader, { props: defaultProps });
7070

7171
expect(screen.getByText('Stop ID:')).toBeInTheDocument();
72-
expect(screen.getByText('1_75403')).toBeInTheDocument();
72+
expect(screen.getByText('75403')).toBeInTheDocument();
7373
});
7474

7575
test('displays stop direction with proper label', () => {
@@ -178,7 +178,7 @@ describe('StopPageHeader', () => {
178178

179179
render(StopPageHeader, { props: propsWithDifferentId });
180180

181-
expect(screen.getByText('1_12345')).toBeInTheDocument();
181+
expect(screen.getByText('12345')).toBeInTheDocument();
182182

183183
// Check that tab links use the new stop ID
184184
const arrivalsTab = screen.getByRole('link', { name: /arrivals & departures/i });

src/components/stops/__tests__/StopPane.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ describe('StopPane', () => {
164164
// Component should render but not show arrival data since fetch is pending
165165
// Check that the main content areas are not present
166166
expect(screen.queryByText('Pine St & 3rd Ave')).not.toBeInTheDocument();
167-
expect(screen.queryByText('Stop #1_75403')).not.toBeInTheDocument();
167+
expect(screen.queryByText('Stop #75403')).not.toBeInTheDocument();
168168
});
169169

170170
test('displays arrival data when provided directly', async () => {
@@ -197,7 +197,7 @@ describe('StopPane', () => {
197197
expect(screen.getByText('Pine St & 3rd Ave')).toBeInTheDocument();
198198
});
199199

200-
expect(screen.getByText('Stop #1_75403')).toBeInTheDocument();
200+
expect(screen.getByText('Stop #75403')).toBeInTheDocument();
201201
expect(screen.getByText('Routes: 10, 11')).toBeInTheDocument();
202202
});
203203

@@ -219,7 +219,7 @@ describe('StopPane', () => {
219219
{ timeout: 3000 }
220220
);
221221

222-
expect(screen.getByText('Stop #1_75403')).toBeInTheDocument();
222+
expect(screen.getByText('Stop #75403')).toBeInTheDocument();
223223
expect(screen.getByText('Routes: 10, 11')).toBeInTheDocument();
224224
});
225225

@@ -262,7 +262,7 @@ describe('StopPane', () => {
262262

263263
await waitFor(() => {
264264
expect(screen.getByText('Pine St & 3rd Ave')).toBeInTheDocument();
265-
expect(screen.getByText('Stop #1_75403')).toBeInTheDocument();
265+
expect(screen.getByText('Stop #75403')).toBeInTheDocument();
266266
});
267267
});
268268

@@ -498,7 +498,7 @@ describe('StopPane', () => {
498498

499499
const headings = screen.getAllByRole('heading', { level: 2 });
500500
expect(headings).toHaveLength(2);
501-
expect(headings[0]).toHaveTextContent('Stop #1_75403');
501+
expect(headings[0]).toHaveTextContent('Stop #75403');
502502
expect(headings[1]).toHaveTextContent('Routes: 10, 11');
503503
});
504504
});

src/lib/utils.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,29 @@ export function debounce(func, wait) {
66
timeout = setTimeout(() => func.apply(this, args), wait);
77
};
88
}
9+
10+
/**
11+
* Removes the agency prefix from an ID string, returning only the numeric part.
12+
* Handles IDs in the format "AGENCY_ID" or "AGENCY_NUMBER" where the separator is an underscore.
13+
*
14+
* @param {string} idString - The full ID string (e.g., "MTS_41242", "1_41242")
15+
* @returns {string} The ID without the agency prefix (e.g., "41242")
16+
*
17+
* @example
18+
* removeAgencyPrefix("MTS_41242") // returns "41242"
19+
* removeAgencyPrefix("1_41242") // returns "41242"
20+
* removeAgencyPrefix("41242") // returns "41242" (no prefix to remove)
21+
*/
22+
export function removeAgencyPrefix(idString) {
23+
if (!idString || typeof idString !== 'string') {
24+
return idString;
25+
}
26+
27+
const underscoreIndex = idString.indexOf('_');
28+
if (underscoreIndex === -1) {
29+
return idString;
30+
}
31+
32+
// Return everything after the first underscore
33+
return idString.substring(underscoreIndex + 1);
34+
}

src/tests/lib/utils.test.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
2-
import { debounce } from '$lib/utils';
2+
import { debounce, removeAgencyPrefix } from '$lib/utils';
33

44
describe('debounce', () => {
55
beforeEach(() => {
@@ -105,3 +105,35 @@ describe('debounce', () => {
105105
expect(mockFn).toBeCalledTimes(1);
106106
});
107107
});
108+
109+
describe('removeAgencyPrefix', () => {
110+
it('should remove agency prefix from ID strings', () => {
111+
expect(removeAgencyPrefix('MTS_41242')).toBe('41242');
112+
expect(removeAgencyPrefix('1_75403')).toBe('75403');
113+
expect(removeAgencyPrefix('40_12345')).toBe('12345');
114+
});
115+
116+
it('should return original string if no underscore found', () => {
117+
expect(removeAgencyPrefix('41242')).toBe('41242');
118+
expect(removeAgencyPrefix('NoPrefix')).toBe('NoPrefix');
119+
});
120+
121+
it('should handle null and undefined inputs', () => {
122+
expect(removeAgencyPrefix(null)).toBe(null);
123+
expect(removeAgencyPrefix(undefined)).toBe(undefined);
124+
});
125+
126+
it('should handle non-string inputs', () => {
127+
expect(removeAgencyPrefix(123)).toBe(123);
128+
expect(removeAgencyPrefix({})).toStrictEqual({});
129+
});
130+
131+
it('should handle empty strings', () => {
132+
expect(removeAgencyPrefix('')).toBe('');
133+
});
134+
135+
it('should handle strings with multiple underscores', () => {
136+
expect(removeAgencyPrefix('1_2_3_4')).toBe('2_3_4');
137+
expect(removeAgencyPrefix('agency_route_stop')).toBe('route_stop');
138+
});
139+
});

0 commit comments

Comments
 (0)