Skip to content

Commit

Permalink
climbing: Add legend
Browse files Browse the repository at this point in the history
  • Loading branch information
jvaclavik committed Jun 4, 2024
1 parent 364aec6 commit 5f14668
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 62 deletions.
11 changes: 2 additions & 9 deletions src/components/FeaturePanel/ImageSection/StarButton.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import Star from '@material-ui/icons/Star';
import StarBorder from '@material-ui/icons/StarBorder';
import React, { useEffect, useState } from 'react';
import React from 'react';
import { Tooltip } from '@material-ui/core';
import { t } from '../../../services/intl';
import { useStarsContext } from '../../utils/StarsContext';
import { StyledActionButton } from './utils';
import { useUserThemeContext } from '../../../helpers/theme';

const useIsClient = () => {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return isClient;
};
import { useIsClient } from '../../helpers';

const StarButtonDarkPure = ({ isStarred, toggleStar }) => (
<StyledActionButton onClick={toggleStar}>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SHOW_PROTOTYPE_UI } from '../../config';
import { LayerSwitcherButton } from '../LayerSwitcher/LayerSwitcherButton';
import { MaptilerLogo } from './MapFooter/MaptilerLogo';
import { TopMenu } from './TopMenu/TopMenu';
import { ClimbingLegend } from './MapFooter/ClimbingLegend';

const BrowserMap = dynamic(() => import('./BrowserMap'), {
ssr: false,
Expand Down Expand Up @@ -82,9 +83,10 @@ const Map = () => {
</TopRight>
<BottomRight>
{SHOW_PROTOTYPE_UI && <BugReportButton />}
<MaptilerLogo />
<ClimbingLegend />
<MapFooter />
</BottomRight>
<MaptilerLogo />
</>
);
};
Expand Down
88 changes: 88 additions & 0 deletions src/components/Map/MapFooter/ClimbingLegend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React from 'react';
import styled from 'styled-components';
import { IconButton } from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close';
import { useMapStateContext } from '../../utils/MapStateContext';
import { COLORS } from '../styles/layers/climbingLayers';
import { usePersistedState } from '../../utils/usePersistedState';
import { useIsClient } from '../../helpers';

const Dot = styled.div<{ color: string }>`
border-radius: 50%;
width: 15px;
height: 15px;
border: solid 2px white;
background: ${({ color }) => color};
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
`;
const Item = styled.div`
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
`;

const HeadingRow = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`;

const Heading = styled.div`
font-size: 12px;
font-weight: bold;
`;

const Container = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
border-radius: 8px;
padding: 8px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
color: ${({ theme }) => theme.palette.text.primary};
background-color: ${({ theme }) => theme.palette.background.paper};
`;

export const ClimbingLegend = () => {
const [isLegendVisible, setIsLegendVisible] = usePersistedState<boolean>(
'isLegendVisible',
true,
);
const isClient = useIsClient();
const { activeLayers } = useMapStateContext();

const isClimbingLayerVisible = activeLayers.includes('climbing');

const onLegendClose = () => {
setIsLegendVisible(false);
};

return isLegendVisible && isClimbingLayerVisible && isClient ? (
<Container>
<HeadingRow>
<Heading>Climbing legend</Heading>
<IconButton
size="small"
edge="end"
aria-label="close"
onClick={onLegendClose}
>
<CloseIcon fontSize="small" />
</IconButton>
</HeadingRow>
<Item>
<Dot color={COLORS.AREA.HAS_IMAGES.DEFAULT} />
Area with photos
</Item>
<Item>
<Dot color={COLORS.CRAG.HAS_IMAGES.DEFAULT} />
Crag with photos
</Item>
<Item>
<Dot color={COLORS.AREA.NO_IMAGES.DEFAULT} />
Area/crag without photos
</Item>
</Container>
) : null;
};
15 changes: 11 additions & 4 deletions src/components/Map/MapFooter/LangSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ import getConfig from 'next/config';
import React from 'react';
import { Menu, MenuItem } from '@material-ui/core';
import { useRouter } from 'next/router';
import LanguageIcon from '@material-ui/icons/Language';
import styled from 'styled-components';
import { useBoolState } from '../../helpers';
import { changeLang, intl, t } from '../../../services/intl';

const StyledLanguageIcon = styled(LanguageIcon)`
color: ${({ theme }) => theme.palette.action.active};
margin: -2px 6px 0 0;
font-size: 17px !important;
`;

export const LangSwitcher = () => {
const {
publicRuntimeConfig: { languages },
Expand Down Expand Up @@ -39,17 +47,16 @@ export const LangSwitcher = () => {
</MenuItem>
))}
</Menu>
<button
type="button"
className="linkLikeButton"
<MenuItem
aria-controls="language-switcher"
aria-haspopup="true"
onClick={open}
ref={anchorRef}
title={t('map.language_title')}
>
<StyledLanguageIcon />
{languages[intl.lang]}
</button>
</MenuItem>
</>
);
};
32 changes: 1 addition & 31 deletions src/components/Map/MapFooter/MapFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import getConfig from 'next/config';
import { Tooltip, useMediaQuery } from '@material-ui/core';
import uniq from 'lodash/uniq';
import { t, Translation } from '../../../services/intl';
import GithubIcon from '../../../assets/GithubIcon';
import { LangSwitcher } from './LangSwitcher';
import { Translation } from '../../../services/intl';
import { useMapStateContext } from '../../utils/MapStateContext';
import { osmappLayers } from '../../LayerSwitcher/osmappLayers';

const {
publicRuntimeConfig: { osmappVersion, commitHash, commitMessage },
} = getConfig();

const StyledGithubIcon = styled(GithubIcon)`
filter: ${({ theme }) => theme.palette.invertFilter};
`;

const Wrapper = styled.div`
margin-top: 10px;
padding: 0 2px;
Expand All @@ -39,21 +28,6 @@ const Wrapper = styled.div`
}
`;

const OsmappLink = () => (
<>
<a
href="https://github.com/zbycz/osmapp"
target="_blank"
rel="noopener"
title={t('map.github_title')}
>
<StyledGithubIcon width="12" height="12" />
osmapp
</a>{' '}
<span title={`${commitHash} ${commitMessage}`}>{osmappVersion}</span>
</>
);

const Attribution = ({ label, link, title }) => (
<>
©{' '}
Expand Down Expand Up @@ -122,10 +96,6 @@ export const MapFooter = () => (
// TODO find a way how to render this in SSR (keep layer in cookies?)
<ClientOnly>
<Wrapper>
<OsmappLink />
{' | '}
<LangSwitcher />
{' | '}
<MapDataLink />
</Wrapper>
</ClientOnly>
Expand Down
12 changes: 2 additions & 10 deletions src/components/Map/MapFooter/MaptilerLogo.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import React from 'react';
import styled from 'styled-components';
import { useMapStateContext } from '../../utils/MapStateContext';
import { osmappLayers } from '../../LayerSwitcher/osmappLayers';

const Link = styled.a`
position: absolute;
right: 8px;
bottom: 19px;
z-index: 999;
`;

export const MaptilerLogo = () => {
const { activeLayers } = useMapStateContext();
const hasMaptiler = activeLayers.some((layer) =>
Expand All @@ -21,8 +13,8 @@ export const MaptilerLogo = () => {
}

return (
<Link href="https://www.maptiler.com" rel="noopener" target="_blank">
<a href="https://www.maptiler.com" rel="noopener" target="_blank">
<img src="/maptiler-api.svg" alt="MapTiler logo" width={67} height={20} />
</Link>
</a>
);
};
20 changes: 20 additions & 0 deletions src/components/Map/TopMenu/HamburgerMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ import { getIdEditorLink } from '../../../utils';
import { useUserThemeContext } from '../../../helpers/theme';
import { useOsmAuthContext } from '../../utils/OsmAuthContext';
import { LoginIcon } from './LoginIcon';
import GithubIcon from '../../../assets/GithubIcon';
import { LangSwitcher } from '../MapFooter/LangSwitcher';

const StyledGithubIcon = styled(GithubIcon)`
filter: ${({ theme }) => theme.palette.invertFilter};
margin: -2px 8px 0 0;
`;

const PencilIcon = styled(CreateIcon)`
color: ${({ theme }) => theme.palette.action.active};
Expand Down Expand Up @@ -108,6 +115,17 @@ const AboutLink = ({ closeMenu }) => {
</MenuItem>
);
};
const GithubLink = ({ closeMenu }) => (
<MenuItem
href="https://github.com/zbycz/osmapp"
component="a"
target="_blank"
onClick={closeMenu}
>
<StyledGithubIcon width={14} height={14} />
{t('map.github_title')}
</MenuItem>
);

const InstallLink = ({ closeMenu }) => {
const handleClick = () => {
Expand Down Expand Up @@ -221,6 +239,8 @@ export const HamburgerMenu = () => {
<EditLink closeMenu={close} />
<InstallLink closeMenu={close} />
<AboutLink closeMenu={close} />
<GithubLink closeMenu={close} />
<LangSwitcher />
</Menu>
<LoginIcon onClick={open} />
<IconButton
Expand Down
51 changes: 45 additions & 6 deletions src/components/Map/styles/layers/climbingLayers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,31 @@ import type {
} from '@maplibre/maplibre-gl-style-spec';
import type { DataDrivenPropertyValueSpecification } from 'maplibre-gl';

export const CRAG_VISIBLE_FROM_ZOOM = 14;

export const COLORS = {
AREA: {
HAS_IMAGES: {
HOVER: 'rgba(0, 59, 210, 0.7)',
DEFAULT: 'rgba(0, 59, 210, 1)',
},
NO_IMAGES: {
HOVER: 'black',
DEFAULT: '#666',
},
},
CRAG: {
HAS_IMAGES: {
HOVER: 'rgba(234, 85, 64, 0.7)',
DEFAULT: '#ea5540',
},
NO_IMAGES: {
HOVER: 'black',
DEFAULT: '#666',
},
},
};

const linear = (
from: number,
num1: number,
Expand Down Expand Up @@ -111,7 +136,7 @@ const crags: LayerSpecification = {
id: 'climbing-2-crags',
type: 'symbol',
source: 'climbing',
minzoom: 15,
minzoom: CRAG_VISIBLE_FROM_ZOOM,
maxzoom: 20,
filter: [
'all',
Expand Down Expand Up @@ -146,7 +171,15 @@ const crags: LayerSpecification = {
'text-halo-blur': 0.5,
'text-halo-width': 1.5,
'text-halo-color': '#ffffff',
'text-color': ifHasImages('#ea5540', '#666'),
'text-color': [
'case',
['boolean', ['feature-state', 'hover'], false],
ifHasImages(COLORS.CRAG.HAS_IMAGES.HOVER, COLORS.CRAG.NO_IMAGES.HOVER),
ifHasImages(
COLORS.CRAG.HAS_IMAGES.DEFAULT,
COLORS.CRAG.NO_IMAGES.DEFAULT,
),
],
},
};

Expand All @@ -173,8 +206,11 @@ const areas: LayerSpecification[] = [
'circle-color': [
'case',
['boolean', ['feature-state', 'hover'], false],
ifHasImages('rgba(0, 59, 210, 0.7)', 'black'),
ifHasImages('rgba(0, 59, 210, 1)', '#666'),
ifHasImages(COLORS.AREA.HAS_IMAGES.HOVER, COLORS.AREA.NO_IMAGES.HOVER),
ifHasImages(
COLORS.AREA.HAS_IMAGES.DEFAULT,
COLORS.AREA.NO_IMAGES.DEFAULT,
),
],
},
},
Expand Down Expand Up @@ -209,8 +245,11 @@ const areas: LayerSpecification[] = [
'text-color': [
'case',
['boolean', ['feature-state', 'hover'], false],
ifHasImages('rgba(0, 59, 210, 0.7)', 'black'),
ifHasImages('rgba(0, 59, 210, 1)', '#666'),
ifHasImages(COLORS.AREA.HAS_IMAGES.HOVER, COLORS.AREA.NO_IMAGES.HOVER),
ifHasImages(
COLORS.AREA.HAS_IMAGES.DEFAULT,
COLORS.AREA.NO_IMAGES.DEFAULT,
),
],
'text-halo-color': 'rgba(250, 250, 250, 1)',
'text-halo-width': 2,
Expand Down
8 changes: 8 additions & 0 deletions src/components/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,11 @@ export const isDesktop = '(min-width: 500px)';
// is mobile device - specific behaviour like longpress or geouri
export const isMobileDevice = () =>
isBrowser() && /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); // TODO this can be isomorphic ? otherwise we have hydration error

export const useIsClient = () => {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return isClient;
};
Loading

0 comments on commit 5f14668

Please sign in to comment.