Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: more global messages contexts #479

Merged
merged 3 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
7 changes: 5 additions & 2 deletions src/components/message-box/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type MessageBoxProps = {
noStatusIcon?: boolean;
onClick?: () => void;
borderRadius?: boolean;
subtle?: boolean;
};

export const MessageBox = ({
Expand All @@ -32,12 +33,13 @@ export const MessageBox = ({
title,
onClick,
borderRadius = true,
subtle = false
}: MessageBoxProps) => {
const { color: {status} } = useTheme();
const { t } = useTranslation();
const backgroundColorStyle: HTMLAttributes<HTMLDivElement>['style'] = {
borderColor: status[type].primary.background,
backgroundColor: status[type].secondary.background,
borderColor: subtle ? undefined : status[type].primary.background,
backgroundColor: subtle ? undefined : status[type].secondary.background,
color: status[type].secondary.foreground.primary,
};
const overrideMode = useStatusThemeColor(type);
Expand All @@ -50,6 +52,7 @@ export const MessageBox = ({
className={andIf({
[style.container]: true,
[style.borderRadius]: borderRadius,
[style.subtle]: subtle
})}
style={backgroundColorStyle}
>
Expand Down
4 changes: 4 additions & 0 deletions src/components/message-box/message-box.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
.borderRadius {
border-radius: token('border.radius.regular');
}
.subtle {
background-color: token('color.background.neutral.0.background') !important;
adriansberg marked this conversation as resolved.
Show resolved Hide resolved
border: none;
}
.content {
display: flex;
flex-direction: column;
Expand Down
8 changes: 5 additions & 3 deletions src/modules/global-messages/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ function subscribeToActiveGlobalMessagesFromFirestore(
const q = query(
collection(db, 'globalMessagesV2'),
where('active', '==', true),
where('context', 'array-contains-any', [
GlobalMessageContextEnum.plannerWeb,
]),
where(
'context',
'array-contains-any',
Object.values(GlobalMessageContextEnum),
),
).withConverter<GlobalMessageType | undefined>(globalMessageConverter);

return onSnapshot(q, (querySnapshot) => {
Expand Down
3 changes: 2 additions & 1 deletion src/modules/global-messages/global-messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MessageBox } from '@atb/components/message-box';
import { getTextForLanguage, useTranslation } from '@atb/translations';
import { and } from '@atb/utils/css';
import { useActiveGlobalMessages } from './context';
import { GlobalMessageContextEnum } from './types';
import { GlobalMessageContextEnum, GlobalMessageType } from './types';
import style from './global-messages.module.css';
import { motion } from 'framer-motion';

Expand Down Expand Up @@ -46,6 +46,7 @@ export function GlobalMessages({ context, className }: GlobalMessagesProps) {
type={message.type}
title={getTextForLanguage(message.title, language)}
message={getTextForLanguage(message.body, language) ?? ''}
subtle={message.subtle}
/>
</motion.div>
))}
Expand Down
4 changes: 4 additions & 0 deletions src/modules/global-messages/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ const messageModeSchema = z.union([

export enum GlobalMessageContextEnum {
plannerWeb = 'planner-web',
plannerWebDepartures = 'planner-web-departures',
plannerWebDeparturesDetails = 'planner-web-departures-details',
plannerWebTrip = 'planner-web-trip',
plannerWebDetails = 'planner-web-details',
}

export const globalMessageTypeSchema = z.object({
Expand Down
5 changes: 5 additions & 0 deletions src/page-modules/assistant/details/details.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
grid-template-columns: 2fr 3fr;
grid-template-areas:
'header header'
'messages messages'
'trip map';
gap: token('spacing.large');
}
Expand All @@ -16,6 +17,7 @@
grid-template-areas:
'header'
'map'
'messages'
'trip';
}
}
Expand Down Expand Up @@ -56,6 +58,9 @@
display: none;
}
}
.tripMessages {
grid-area: messages;
}
.tripContainer {
grid-area: trip;
display: flex;
Expand Down
2 changes: 2 additions & 0 deletions src/page-modules/assistant/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useRouter } from 'next/router';
import { tripQueryStringToQueryParams } from './utils';
import { MessageBox } from '@atb/components/message-box';
import { getBookingStatus } from '@atb/modules/flexible/utils';
import { GlobalMessageContextEnum, GlobalMessages } from '@atb/modules/global-messages';

export type AssistantDetailsProps = {
tripPattern: TripPatternWithDetails;
Expand Down Expand Up @@ -79,6 +80,7 @@ export function AssistantDetails({ tripPattern }: AssistantDetailsProps) {
</div>
</div>
</div>
<GlobalMessages className={style.tripMessages} context={GlobalMessageContextEnum.plannerWebDetails} />
<div className={style.tripContainer}>
{requireTicketBooking && (
<MessageBox
Expand Down
3 changes: 3 additions & 0 deletions src/page-modules/assistant/trip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import TripPattern from './trip-pattern';
import EmptySearch from '@atb/components/loading-empty-results';
import { LoadingIcon } from '@atb/components/loading';
import ScreenReaderOnly from '@atb/components/screen-reader-only';
import { GlobalMessageContextEnum, GlobalMessages } from '@atb/modules/global-messages';

export type TripProps = {
tripQuery: FromToTripQuery;
Expand Down Expand Up @@ -89,6 +90,8 @@ export default function Trip({ tripQuery, fallback }: TripProps) {
return (
<>
<ScreenReaderOnly text={t(PageText.Assistant.trip.resultsFound)} role='status' />

<GlobalMessages context={GlobalMessageContextEnum.plannerWebTrip} />
<div className={style.tripResults}>
{nonTransitTrips && nonTransits.length > 0 && (
<div className={style.nonTransitResult}>
Expand Down
15 changes: 11 additions & 4 deletions src/page-modules/departures/__tests__/departure-details.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { afterEach, describe, expect, it } from 'vitest';
import userEvent from '@testing-library/user-event';
import { DeparturesDetails } from '../details';
import { formatDestinationDisplay } from '../utils';
import { GlobalMessageContextProvider } from '@atb/modules/global-messages';

afterEach(function () {
cleanup();
Expand All @@ -13,9 +14,15 @@ const serviceJourneyId = 'ATB:ServiceJourney:22_230306097862461_113';
const date = '2023-11-10';
const fromQuayId = 'NSR:Quay:74990';

const customRender = (ui: React.ReactNode) => {
return render(
<GlobalMessageContextProvider>{ui}</GlobalMessageContextProvider>,
);
};

describe('departure details page', function () {
it('should render correct header', () => {
const output = render(
const output = customRender(
<DeparturesDetails
fromQuayId={fromQuayId}
serviceJourney={serviceJourneyFixture}
Expand All @@ -29,7 +36,7 @@ describe('departure details page', function () {
});

it('should not render passed quays', () => {
const output = render(
const output = customRender(
<DeparturesDetails
fromQuayId={fromQuayId}
serviceJourney={serviceJourneyFixture}
Expand All @@ -56,7 +63,7 @@ describe('departure details page', function () {
});

it('should render passed departures when collapse button is clicked', async () => {
const output = render(
const output = customRender(
<DeparturesDetails
fromQuayId={fromQuayId}
serviceJourney={serviceJourneyFixture}
Expand Down Expand Up @@ -91,7 +98,7 @@ describe('departure details page', function () {
fromQuayIndex,
serviceJourneyFixture.estimatedCalls.length,
);
const output = render(
const output = customRender(
<DeparturesDetails
fromQuayId={fromQuayId}
serviceJourney={serviceJourneyFixture}
Expand Down
13 changes: 10 additions & 3 deletions src/page-modules/departures/__tests__/departure.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { NearestStopPlaces } from '..';
import { GeocoderApi } from '@atb/page-modules/departures/server/geocoder';
import Search from '@atb/components/search/search';
import { sortQuays } from '../server/journey-planner/utils';
import { GlobalMessageContextProvider } from '@atb/modules/global-messages';

afterEach(function () {
cleanup();
Expand All @@ -22,6 +23,12 @@ vi.mock('next/router', () => require('next-router-mock'));

mockRouter.useParser(createDynamicRouteParser(['/departures/[id]']));

const customRender = (ui: React.ReactNode) => {
return render(
<GlobalMessageContextProvider>{ui}</GlobalMessageContextProvider>,
);
};

describe('departure page', function () {
it('Should return props from getServerSideProps', async () => {
await mockRouter.push('/departures/NSR:StopPlace:123');
Expand Down Expand Up @@ -99,15 +106,15 @@ describe('departure page', function () {
});

it('should render quays', () => {
const output = render(<StopPlace departures={departureDataFixture} />);
const output = customRender(<StopPlace departures={departureDataFixture} />);

departureDataFixture.quays.forEach((q) =>
expect(output.getByText(q.name)).toBeInTheDocument(),
);
});

it('should render estimated calls', () => {
const output = render(<StopPlace departures={departureDataFixture} />);
const output = customRender(<StopPlace departures={departureDataFixture} />);
const lists = output.getAllByRole('list');
const { getAllByRole } = within(lists[0]);
const items = getAllByRole('listitem');
Expand All @@ -117,7 +124,7 @@ describe('departure page', function () {
});

it('Should collapse estimated calls list', async () => {
const output = render(<StopPlace departures={departureDataFixture} />);
const output = customRender(<StopPlace departures={departureDataFixture} />);
const button = screen.getAllByRole('button', {
name: 'Aktiver for å minimere',
});
Expand Down
2 changes: 2 additions & 0 deletions src/page-modules/departures/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import style from './details.module.css';
import { EstimatedCallRows } from './estimated-call-rows';
import { addMetadataToEstimatedCalls } from './utils';
import { formatDestinationDisplay } from '../utils';
import { GlobalMessageContextEnum, GlobalMessages } from '@atb/modules/global-messages';

export type DeparturesDetailsProps = {
fromQuayId?: string;
Expand Down Expand Up @@ -80,6 +81,7 @@ export function DeparturesDetails({
/>
<Typo.h2 textType="heading--big">{title}</Typo.h2>
</div>
<GlobalMessages context={GlobalMessageContextEnum.plannerWebDeparturesDetails} />
{realtimeText && !focusedCall.cancellation && (
<div className={style.realtimeText}>
<ColorIcon icon="status/Realtime" size="xSmall" />
Expand Down
2 changes: 2 additions & 0 deletions src/page-modules/departures/stop-place/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import style from './stop-place.module.css';
import { formatDestinationDisplay } from '../utils';
import { useTheme } from '@atb/modules/theme';
import { formatQuayName } from '@atb/page-modules/departures/details/utils';
import { GlobalMessageContextEnum, GlobalMessages } from '@atb/modules/global-messages';

export type StopPlaceProps = {
departures: DepartureData;
Expand Down Expand Up @@ -60,6 +61,7 @@ export function StopPlace({ departures }: StopPlaceProps) {
role="status"
/>

<GlobalMessages className={style.stopPlaceMessages} context={GlobalMessageContextEnum.plannerWebDepartures} />
<div className={style.quaysContainer}>
<button
onClick={() => router.reload()}
Expand Down
10 changes: 7 additions & 3 deletions src/page-modules/departures/stop-place/stop-place.module.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
.stopPlaceContainer {
display: grid;
grid-template-columns: 2fr 3fr;
grid-auto-rows: minmax(37.5rem, auto) auto;
grid-template-areas: 'quays map';
grid-auto-rows: auto minmax(37.5rem, auto) auto;
grid-template-areas: 'messages messages' 'quays map';
gap: token('spacing.small');
}

.stopPlaceMessages {
grid-area: messages;
}

.mapContainer {
grid-area: map;
max-height: 37.5rem;
Expand Down Expand Up @@ -137,7 +141,7 @@

@media only screen and (max-width: 650px) {
.stopPlaceContainer {
grid-template-areas: 'map' 'quays';
grid-template-areas: 'map' 'messages' 'quays';
grid-template-columns: auto;
grid-template-rows: auto;
}
Expand Down
Loading