Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@
"officialFeed": "Official Feed",
"officialFeedTooltip": "The transit provider has confirmed this feed should be shared with riders. This has been confirmed either by the transit provider providing the feed on their website or from personalized confirmation with the Mobility Database team.",
"officialFeedTooltipShort": "Verified feed: Confirmed by the transit provider or the Mobility Database team for rider use.",
"communityFeed": "Community Feed",
"communityFeedTooltip": "This feed is not created on behalf of the transit authority. It may have been created by a community member or third party.",
"communityFeedTooltipShort": "Community feed: Created by a third party unaffiliated with the transit provider.",
"seeDetailPageProviders": "See detail page to view {providersCount} others",
"openFullQualityReport": "Open Full Quality Report",
"subscribe": "Subscribe to get feed update notifications",
Expand Down
3 changes: 3 additions & 0 deletions messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@
"officialFeed": "Official Feed",
"officialFeedTooltip": "The transit provider has confirmed this feed should be shared with riders. This has been confirmed either by the transit provider providing the feed on their website or from personalized confirmation with the Mobility Database team.",
"officialFeedTooltipShort": "Verified feed: Confirmed by the transit provider or the Mobility Database team for rider use.",
"communityFeed": "Community Feed",
"communityFeedTooltip": "This feed has not been officially confirmed by the transit provider. It may have been created by the community or a third party.",
"communityFeedTooltipShort": "Community feed: Not officially confirmed by the transit provider.",
"seeDetailPageProviders": "See detail page to view {providersCount} others",
"openFullQualityReport": "Open Full Quality Report",
"subscribe": "S'abonner",
Expand Down
100 changes: 100 additions & 0 deletions src/app/components/FeedVerificationChip.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { type JSX } from 'react';
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from '@mui/material';
import { theme } from '../Theme';
import FeedVerificationChip from './FeedVerificationChip';

// next-intl is globally mocked in setupTests.ts: useTranslations returns (key) => key

function wrapper({ children }: { children: React.ReactNode }): JSX.Element {
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}

describe('FeedVerificationChip', () => {
describe('when status is undefined', () => {
it('renders nothing', () => {
const { container } = render(<FeedVerificationChip />, { wrapper });
expect(container).toBeEmptyDOMElement();
});
});

describe('when status is true (official feed)', () => {
it('renders the official chip with label in long display mode (default)', () => {
render(<FeedVerificationChip status={true} />, { wrapper });
expect(screen.getByTestId('official-feed-chip')).toBeInTheDocument();
expect(screen.getByText('officialFeed')).toBeInTheDocument();
});

it('renders the official icon in short display mode', () => {
render(<FeedVerificationChip status={true} isLongDisplay={false} />, {
wrapper,
});
expect(screen.getByTestId('official-feed-icon')).toBeInTheDocument();
expect(
screen.queryByTestId('official-feed-chip'),
).not.toBeInTheDocument();
});
});

describe('when status is false (community feed)', () => {
it('renders the community chip with label in long display mode (default)', () => {
render(<FeedVerificationChip status={false} />, { wrapper });
expect(screen.getByTestId('community-feed-chip')).toBeInTheDocument();
expect(screen.getByText('communityFeed')).toBeInTheDocument();
});

it('renders the community icon in short display mode', () => {
render(<FeedVerificationChip status={false} isLongDisplay={false} />, {
wrapper,
});
expect(screen.getByTestId('community-feed-icon')).toBeInTheDocument();
expect(
screen.queryByTestId('community-feed-chip'),
).not.toBeInTheDocument();
});
});

describe('long display mode (isLongDisplay=true)', () => {
it('renders official chip — not icon — for status=true', () => {
render(<FeedVerificationChip status={true} isLongDisplay={true} />, {
wrapper,
});
expect(screen.getByTestId('official-feed-chip')).toBeInTheDocument();
expect(
screen.queryByTestId('official-feed-icon'),
).not.toBeInTheDocument();
});

it('renders community chip — not icon — for status=false', () => {
render(<FeedVerificationChip status={false} isLongDisplay={true} />, {
wrapper,
});
expect(screen.getByTestId('community-feed-chip')).toBeInTheDocument();
expect(
screen.queryByTestId('community-feed-icon'),
).not.toBeInTheDocument();
});
});

describe('short display mode (isLongDisplay=false)', () => {
it('renders official icon — not chip — for status=true', () => {
render(<FeedVerificationChip status={true} isLongDisplay={false} />, {
wrapper,
});
expect(screen.getByTestId('official-feed-icon')).toBeInTheDocument();
expect(
screen.queryByTestId('official-feed-chip'),
).not.toBeInTheDocument();
});

it('renders community icon — not chip — for status=false', () => {
render(<FeedVerificationChip status={false} isLongDisplay={false} />, {
wrapper,
});
expect(screen.getByTestId('community-feed-icon')).toBeInTheDocument();
expect(
screen.queryByTestId('community-feed-chip'),
).not.toBeInTheDocument();
});
});
});
80 changes: 80 additions & 0 deletions src/app/components/FeedVerificationChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use client';
import { Chip, Tooltip } from '@mui/material';
import { useTranslations } from 'next-intl';
import VerifiedIcon from '@mui/icons-material/Verified';
import GroupsIcon from '@mui/icons-material/Groups';

interface FeedVerificationChipProps {
isLongDisplay?: boolean;
status?: boolean;
}

export default function FeedVerificationChip({
isLongDisplay = true,
status,
}: FeedVerificationChipProps): React.ReactElement | null {
const t = useTranslations('feeds');

if (status == undefined) {
return null;
}
Comment thread
Alessandro100 marked this conversation as resolved.

if (!status) {
return isLongDisplay ? (
<Tooltip title={t('communityFeedTooltip')} placement='top'>
<Chip
data-testid='community-feed-chip'
sx={{ opacity: 0.8 }}
icon={<GroupsIcon></GroupsIcon>}
label={t('communityFeed')}
variant='filled'
></Chip>
</Tooltip>
) : (
<Tooltip title={t('communityFeedTooltipShort')} placement='top'>
<GroupsIcon
data-testid='community-feed-icon'
sx={(theme) => ({
display: 'block',
ml: 0,
mr: 2,
opacity: 0.6,
backgroundColor: theme.vars.palette.grey[400],
color: theme.vars.palette.text.primary,
borderRadius: '50%',
padding: '0.2rem',
})}
></GroupsIcon>
</Tooltip>
);
}

return isLongDisplay ? (
<Tooltip title={t('officialFeedTooltip')} placement='top'>
<Chip
data-testid='official-feed-chip'
sx={(theme) => ({
background: `linear-gradient(25deg, ${theme.vars.palette.primary.light}, ${theme.vars.palette.primary.dark})`,
color: 'white',
})}
icon={<VerifiedIcon sx={{ fill: 'white' }}></VerifiedIcon>}
label={t('officialFeed')}
></Chip>
</Tooltip>
) : (
<Tooltip title={t('officialFeedTooltipShort')} placement='top'>
<VerifiedIcon
data-testid='official-feed-icon'
sx={(theme) => ({
display: 'block',
borderRadius: '50%',
padding: '0.1rem',
ml: 0,
mr: 2,
background: `linear-gradient(25deg, ${theme.vars.palette.primary.light}, ${theme.vars.palette.primary.dark})`,
color: 'white',
})}
></VerifiedIcon>
</Tooltip>
);
}
43 changes: 0 additions & 43 deletions src/app/components/OfficialChip.tsx

This file was deleted.

10 changes: 6 additions & 4 deletions src/app/screens/Feed/FeedView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Typography from '@mui/material/Typography';

// Components
import FeedTitle from './components/FeedTitle';
import OfficialChip from '../../components/OfficialChip';
import FeedVerificationChip from '../../components/FeedVerificationChip';
import DataQualitySummary from './components/DataQualitySummary';
import FeedSummary from './components/FeedSummary';
import FeedNavigationControls from './components/FeedNavigationControls';
Expand Down Expand Up @@ -194,14 +194,16 @@ export default async function FeedView({
{feed?.data_type === 'gtfs' && (
<DataQualitySummary
feedStatus={feed?.status}
isOfficialFeed={feed.official === true}
isOfficialFeed={feed.official}
latestDataset={latestDataset}
/>
)}

{feed?.data_type === 'gtfs_rt' && feed.official === true && (
{feed?.data_type === 'gtfs_rt' && feed.official != null && (
<Box sx={{ my: 1 }}>
<OfficialChip></OfficialChip>
<FeedVerificationChip
status={feed.official}
></FeedVerificationChip>
</Box>
)}

Expand Down
6 changes: 3 additions & 3 deletions src/app/screens/Feed/components/DataQualitySummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { type components } from '../../../services/feeds/types';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import { WarningContentBox } from '../../../components/WarningContentBox';
import { FeedStatusChip } from '../../../components/FeedStatus';
import OfficialChip from '../../../components/OfficialChip';
import FeedVerificationChip from '../../../components/FeedVerificationChip';
import { getTranslations } from 'next-intl/server';
import { getUserRemoteConfigValues } from '../../../../lib/remote-config.server';

export interface DataQualitySummaryProps {
feedStatus: components['schemas']['Feed']['status'];
isOfficialFeed: boolean;
isOfficialFeed: boolean | undefined;
latestDataset: components['schemas']['GtfsDataset'] | undefined;
}

Expand All @@ -36,7 +36,7 @@ export default async function DataQualitySummary({
{config.enableFeedStatusBadge && (
<FeedStatusChip status={feedStatus ?? ''}></FeedStatusChip>
)}
{isOfficialFeed && <OfficialChip></OfficialChip>}
<FeedVerificationChip status={isOfficialFeed}></FeedVerificationChip>
{latestDataset?.validation_report !== undefined &&
latestDataset.validation_report !== null && (
<>
Expand Down
9 changes: 5 additions & 4 deletions src/app/screens/Feeds/AdvancedSearchTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import LockIcon from '@mui/icons-material/Lock';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import GtfsRtEntities from './GtfsRtEntities';
import { getEmojiFlag, type TCountryCode } from 'countries-list';
import OfficialChip from '../../components/OfficialChip';
import FeedVerificationChip from '../../components/FeedVerificationChip';
import { getFeatureComponentDecorators } from '../../utils/consts';
import PopoverList from './PopoverList';
import ProviderTitle from './ProviderTitle';
Expand Down Expand Up @@ -337,9 +337,10 @@ export default function AdvancedSearchTable({
></ProviderTitle>
</Typography>

{feed.official === true && (
<OfficialChip isLongDisplay={false}></OfficialChip>
)}
<FeedVerificationChip
isLongDisplay={false}
status={feed.official}
></FeedVerificationChip>
{feed.data_type !== 'gbfs' && (
<FeedStatusIndicator
status={feed.status}
Expand Down
9 changes: 5 additions & 4 deletions src/app/screens/Feeds/SearchTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import GtfsRtEntities from './GtfsRtEntities';
import NextLinkComposed from 'next/link';
import { useRouter } from '../../../i18n/navigation';
import { getEmojiFlag, type TCountryCode } from 'countries-list';
import OfficialChip from '../../components/OfficialChip';
import FeedVerificationChip from '../../components/FeedVerificationChip';
import ProviderTitle from './ProviderTitle';

export interface SearchTableProps {
Expand Down Expand Up @@ -216,9 +216,10 @@ export default function SearchTable({
setAnchorEl(el);
}}
></ProviderTitle>
{feed.official === true && (
<OfficialChip isLongDisplay={false}></OfficialChip>
)}
<FeedVerificationChip
isLongDisplay={false}
status={feed.official}
></FeedVerificationChip>
</Box>
</TableCell>
<TableCell className='feed-column' component={Box}>
Expand Down
9 changes: 0 additions & 9 deletions src/app/styles/VerificationBadge.styles.ts

This file was deleted.

Loading