-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8f187ea
commit 6dba636
Showing
18 changed files
with
686 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { cleanup, render } from '@testing-library/react'; | ||
import { afterEach, describe, expect, it } from 'vitest'; | ||
import { MapHeader } from '@atb/components/map'; | ||
import { MapHeaderProps } from '@atb/components/map/map-header'; | ||
import { FeatureCategory } from '@atb/components/venue-icon'; | ||
|
||
const stopPlaceMock: MapHeaderProps = { | ||
layer: 'venue', | ||
name: 'Trondheim S', | ||
id: 'NSR:StopPlace:41742', | ||
street: 'Fosenkaia', | ||
category: [FeatureCategory.ONSTREET_BUS], | ||
}; | ||
|
||
const addressMock: MapHeaderProps = { | ||
layer: 'address', | ||
id: '44523952221', | ||
name: 'Prinsens gate', | ||
}; | ||
|
||
afterEach(function () { | ||
cleanup(); | ||
}); | ||
|
||
describe('MapHeader', function () { | ||
it('should render travel to and from links for stop place', async () => { | ||
const output = render(<MapHeader {...stopPlaceMock} />); | ||
|
||
expect(output.getByText('Reis fra')).toBeInTheDocument(); | ||
expect(output.getByText('Reis til')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should not render travel to and from links for address', async () => { | ||
const output = render(<MapHeader {...addressMock} />); | ||
|
||
expect(output.queryByText('Reis fra')).not.toBeInTheDocument(); | ||
expect(output.queryByText('Reis til')).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('should show icons for travel method', async () => { | ||
const output = render( | ||
<MapHeader | ||
{...stopPlaceMock} | ||
category={[FeatureCategory.ONSTREET_BUS, FeatureCategory.ONSTREET_TRAM]} | ||
/>, | ||
); | ||
expect(output.getByAltText('Buss')).toBeInTheDocument(); | ||
expect(output.getByAltText('Trikk')).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,3 @@ | ||
import React, { useRef, useEffect } from 'react'; | ||
import mapboxgl from 'mapbox-gl'; | ||
import style from './map.module.css'; | ||
import 'mapbox-gl/dist/mapbox-gl.css'; | ||
import { mapboxData } from '@atb/modules/org-data'; | ||
|
||
export type Position = { | ||
lat: number; | ||
lng: number; | ||
}; | ||
|
||
export type MapProps = { | ||
position?: Position; | ||
}; | ||
|
||
export function Map({ position = defaultPosition }: MapProps) { | ||
const mapContainer = useRef<HTMLDivElement>(null); | ||
const map = useRef<mapboxgl.Map>(); | ||
|
||
useEffect(() => { | ||
if (!mapContainer.current) return; | ||
map.current = new mapboxgl.Map({ | ||
container: mapContainer.current, | ||
accessToken: mapboxData.accessToken, | ||
style: mapboxData.style, | ||
center: [position.lng, position.lat], | ||
zoom: 13, | ||
}); | ||
|
||
return () => map.current?.remove(); | ||
}, []); // eslint-disable-line react-hooks/exhaustive-deps | ||
|
||
useEffect(() => { | ||
if (map.current) { | ||
map.current.setCenter([position.lng, position.lat]); | ||
} | ||
}, [position.lng, position.lat]); | ||
|
||
return <div ref={mapContainer} className={style.mapContainer} />; | ||
} | ||
|
||
const defaultPosition: Position = { | ||
lat: mapboxData.defaultLat, | ||
lng: mapboxData.defaultLng, | ||
}; | ||
export { Map } from './map'; | ||
export { MapWithHeader } from './map-with-header'; | ||
export { MapHeader } from './map-header'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import style from './map.module.css'; | ||
|
||
import { ButtonLink } from '@atb/components/button'; | ||
import { ComponentText, useTranslation } from '@atb/translations'; | ||
import VenueIcon, { FeatureCategory } from '@atb/components/venue-icon'; | ||
import { and } from '@atb/utils/css'; | ||
import { MonoIcon } from '@atb/components/icon'; | ||
|
||
export type MapHeaderProps = { | ||
id: string; | ||
name: string; // StopPlace name or address | ||
layer: 'address' | 'venue'; | ||
street?: string; | ||
category?: FeatureCategory[]; | ||
}; | ||
|
||
export function MapHeader({ | ||
id, | ||
name, | ||
layer, | ||
street, | ||
category, | ||
}: MapHeaderProps) { | ||
const { t } = useTranslation(); | ||
return ( | ||
<div className={style.header}> | ||
<div className={style.header__leftContainer}> | ||
<div className={style.header__icons}> | ||
{layer === 'address' || !category ? ( | ||
<div> | ||
<MonoIcon size="large" icon="map/Pin" overrideMode="dark" /> | ||
</div> | ||
) : ( | ||
category.map((type) => ( | ||
<div key={[type, 'icon'].join('-')}> | ||
<VenueIcon category={[type]} size="large" overrideMode="dark" /> | ||
</div> | ||
)) | ||
)} | ||
</div> | ||
<div className={style.header__info}> | ||
<h3 | ||
className={and( | ||
'typo-heading--medium', | ||
layer === 'address' && style['flexOrder__2'], | ||
)} | ||
> | ||
{name} | ||
</h3> | ||
<p | ||
className={and( | ||
'typo-body__secondary', | ||
style['header__info__secondary'], | ||
)} | ||
> | ||
{layer === 'venue' | ||
? t(ComponentText.Map.header.venue(street || '?')) // @TODO: better types | ||
: t(ComponentText.Map.header.address)} | ||
</p> | ||
</div> | ||
</div> | ||
|
||
{layer === 'venue' && ( | ||
<div className={style.header__buttons}> | ||
<ButtonLink | ||
mode="interactive_0" | ||
href={`/planner?travelFrom=${id}`} | ||
title={t(ComponentText.Map.button.travelFrom)} | ||
className={style.header__button} | ||
/> | ||
<ButtonLink | ||
mode="interactive_0" | ||
href={`/planner?travelTo=${id}`} | ||
title={t(ComponentText.Map.button.travelTo)} | ||
className={style.header__button} | ||
/> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import style from './map.module.css'; | ||
import { MapHeader, Map } from '.'; | ||
import { MapHeaderProps } from './map-header'; | ||
import { MapProps } from './map'; | ||
|
||
export type MapWithHeaderProps = MapHeaderProps & MapProps; | ||
|
||
export function MapWithHeader({ ...props }: MapWithHeaderProps) { | ||
return ( | ||
<div className={style.mapWithHeader}> | ||
<MapHeader {...props} /> | ||
<Map {...props} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,136 @@ | ||
.mapContainer { | ||
.mapWithHeader { | ||
height: 100%; | ||
width: 100%; | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
.header { | ||
display: flex; | ||
align-items: center; | ||
gap: var(--spacings-medium); | ||
background: var(--static-background-background_0-background); | ||
color: var(--static-background-background_0-text); | ||
border-radius: var(--border-radius-regular) var(--border-radius-regular) 0 0; | ||
padding: var(--spacings-medium); | ||
} | ||
|
||
.header__icons { | ||
display: flex; | ||
gap: var(--spacings-medium); | ||
} | ||
|
||
.header__icons div { | ||
background-color: var(--static-background-background_accent_0-background); | ||
color: var(--static-background-background_accent_0-text); | ||
padding: var(--spacings-small); | ||
border-radius: var(--border-radius-regular); | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
} | ||
|
||
.header__info { | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
||
.header__info__secondary { | ||
color: var(--text-colors-secondary); | ||
} | ||
|
||
.flexOrder__2 { | ||
order: 2; | ||
} | ||
|
||
.header__buttons { | ||
display: flex; | ||
gap: var(--spacings-medium); | ||
margin-left: auto; | ||
} | ||
|
||
.mapContainer { | ||
position: relative; | ||
height: 100%; | ||
width: 100%; | ||
} | ||
|
||
.header__leftContainer { | ||
display: flex; | ||
gap: var(--spacings-medium); | ||
} | ||
|
||
.map { | ||
height: 100%; | ||
width: 100%; | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
||
.mapWrapper { | ||
position: relative; | ||
height: 100%; | ||
width: 100%; | ||
} | ||
|
||
.fullscreenButton { | ||
display: none; | ||
} | ||
|
||
.closeButton { | ||
z-index: 250; | ||
position: absolute; | ||
top: var(--spacings-xLarge); | ||
left: var(--spacings-xLarge); | ||
display: none; | ||
} | ||
|
||
.closeButton img { | ||
display: block; | ||
} | ||
|
||
.buttonsContainer { | ||
position: absolute; | ||
right: var(--spacings-xLarge); | ||
bottom: 3rem; | ||
z-index: 250; | ||
} | ||
|
||
.pinSvg__fill { | ||
fill: var(--interactive-interactive_0-default-background); | ||
} | ||
|
||
@media only screen and (max-width: 650px) { | ||
.header { | ||
flex-direction: column; | ||
background: inherit; | ||
color: inherit; | ||
padding: var(--spacings-medium) 0; | ||
} | ||
.header__buttons { | ||
margin-left: 0; | ||
width: 100%; | ||
align-items: center; | ||
} | ||
.header__button { | ||
width: 100%; | ||
text-align: center; | ||
} | ||
.fullscreenButton { | ||
display: flex; | ||
justify-content: center; | ||
border: 2px solid #000000; | ||
} | ||
.fullscreenButton span { | ||
flex: none; | ||
} | ||
.closeButton { | ||
display: block; | ||
} | ||
.mapWrapper { | ||
z-index: 250; | ||
display: none; | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
} | ||
} |
Oops, something went wrong.