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

FeaturePanel: display route paths on climbing=area #502

Merged
merged 2 commits into from
Sep 2, 2024
Merged
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
4 changes: 2 additions & 2 deletions pages/api/og-image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ const renderSvg = async (
export default async (req: NextApiRequest, res: NextApiResponse) => {
const t1 = Date.now();
try {
const shortId = getApiId(req.query.id);
const feature = await fetchWithMemberFeatures(shortId);
const osmId = getApiId(req.query.id);
const feature = await fetchWithMemberFeatures(osmId);
const def = feature.imageDefs?.[0]; // TODO iterate when first not found
if (!def) {
throw new Error('No image definition found');
Expand Down
156 changes: 71 additions & 85 deletions src/components/FeaturePanel/CragsInArea.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import styled from '@emotion/styled';
import { Box, useTheme } from '@mui/material';
import { Box } from '@mui/material';
import React from 'react';
import Router from 'next/router';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
import { useFeatureContext } from '../utils/FeatureContext';
import { getOsmappLink, getUrlOsmId } from '../../services/helpers';
import { Feature } from '../../services/types';
import { Feature, isInstant, OsmId } from '../../services/types';
import { useMobileMode } from '../helpers';
import { getWikimediaCommonsKeys } from './Climbing/utils/photo';
import { useScrollShadow } from './Climbing/utils/useScrollShadow';
import { getLabel } from '../../helpers/featureLabel';

import { getCommonsImageUrl } from '../../services/images/getCommonsImageUrl';
import { Slider, Wrapper } from './ImagePane/FeatureImages';
import { Image } from './ImagePane/Image/Image';
import { getInstantImage } from '../../services/images/getImageDefs';

const ArrowIcon = styled(ArrowForwardIosIcon)`
opacity: 0.2;
Expand All @@ -21,6 +21,7 @@ const HeadingRow = styled.div`
display: flex;
flex-direction: row;
align-items: center;
padding: 0 12px;
`;
const Container = styled.div`
overflow: auto;
Expand All @@ -30,7 +31,7 @@ const Container = styled.div`
justify-content: space-between;
cursor: pointer;
border-radius: 8px;
padding: 12px;
padding: 12px 0;
background-color: ${({ theme }) => theme.palette.background.elevation};
&:hover {
${ArrowIcon} {
Expand All @@ -44,12 +45,13 @@ const CragList = styled.div`
flex-direction: column;
gap: 12px;
`;
const Anchor = styled.a`
const Link = styled.a`
text-decoration: none !important;
`;
const Content = styled.div`
flex: 1;
`;

const CragName = styled.div`
padding: 0;
font-weight: 900;
Expand All @@ -64,108 +66,92 @@ const NumberOfRoutes = styled.div`
font-size: 13px;
color: ${({ theme }) => theme.palette.secondary.main};
`;
const Gallery = styled.div`
display: flex;
gap: 8px;
border-radius: 8px;
overflow: auto;
margin-top: 12px;
`;
const Image = styled.img`
border-radius: 8px;
height: 200px;
flex: 1;
object-fit: cover;
`;
const CragItem = ({ feature }: { feature: Feature }) => {
const theme: any = useTheme();
const Header = ({
imagesCount,
label,
routesCount,
}: {
label: string;
routesCount: number;
imagesCount: number;
}) => (
<HeadingRow>
<Content>
<CragName>{label}</CragName>{' '}
<Attributes>
{routesCount > 0 && (
<NumberOfRoutes>{routesCount} routes </NumberOfRoutes>
)}
{imagesCount > 0 && (
<NumberOfRoutes>{imagesCount} photos</NumberOfRoutes>
)}
</Attributes>
</Content>
<ArrowIcon color="primary" />
</HeadingRow>
);

const Gallery = ({ images }) => {
return (
<Wrapper>
<Slider>
{images.map((item) => (
<Image key={item.image.imageUrl} def={item.def} image={item.image} />
))}
</Slider>
</Wrapper>
);
};

const getOnClickWithHash = (apiId: OsmId) => (e) => {
e.preventDefault();
Router.push(`/${getUrlOsmId(apiId)}${window.location.hash}`);
};

const CragItem = ({ feature }: { feature: Feature }) => {
const mobileMode = useMobileMode();
const { setPreview } = useFeatureContext();
const { osmMeta } = feature;
const handleClick = (e) => {
e.preventDefault();
setPreview(null);
Router.push(`/${getUrlOsmId(osmMeta)}${window.location.hash}`);
};
const handleHover = () => feature.center && setPreview(feature);

const cragPhotoKeys = getWikimediaCommonsKeys(feature.tags);
const images =
feature?.imageDefs?.filter(isInstant)?.map((def) => ({
def,
image: getInstantImage(def),
})) ?? [];

const {
scrollElementRef,
onScroll,
ShadowContainer,
ShadowLeft,
ShadowRight,
} = useScrollShadow();
return (
<Anchor
href={`/${getUrlOsmId(osmMeta)}`}
onClick={handleClick}
<Link
href={`/${getUrlOsmId(feature.osmMeta)}`}
onClick={getOnClickWithHash(feature.osmMeta)}
onMouseEnter={mobileMode ? undefined : handleHover}
onMouseLeave={() => setPreview(null)}
>
<Container>
<HeadingRow>
<Content>
<CragName>{getLabel(feature)}</CragName>{' '}
<Attributes>
{feature.members?.length > 0 && (
<NumberOfRoutes>
{feature.members.length} routes{' '}
</NumberOfRoutes>
)}
{cragPhotoKeys.length > 0 && (
<NumberOfRoutes>{cragPhotoKeys.length} photos </NumberOfRoutes>
)}
</Attributes>
</Content>
<ArrowIcon color="primary" />
</HeadingRow>
{cragPhotoKeys.length > 0 && (
<ShadowContainer>
<ShadowLeft
backgroundColor={theme.palette.background.elevation}
gradientPercentage={7}
opacity={0.9}
/>
<Gallery onScroll={onScroll} ref={scrollElementRef}>
{cragPhotoKeys.map((cragPhotoTag) => {
const photoPath = feature.tags[cragPhotoTag];
const url = getCommonsImageUrl(photoPath, 410);
return <Image src={url} key={cragPhotoTag} />;
})}
</Gallery>
<ShadowRight
backgroundColor={theme.palette.background.elevation}
gradientPercentage={7}
opacity={0.9}
/>
</ShadowContainer>
)}
<Header
label={getLabel(feature)}
routesCount={feature.members?.length}
imagesCount={images.length}
/>
{images.length ? <Gallery images={images} /> : null}
</Container>
</Anchor>
</Link>
);
};

export const CragsInArea = () => {
const {
feature: { memberFeatures, tags },
} = useFeatureContext();
const { feature } = useFeatureContext();

if (!memberFeatures?.length) {
if (!feature.memberFeatures?.length) {
return null;
}

const isClimbingArea = tags.climbing === 'area';
if (!isClimbingArea) {
if (feature.tags.climbing !== 'area') {
return null;
}

return (
<Box mt={4}>
<CragList>
{memberFeatures.map((item) => (
{feature.memberFeatures.map((item) => (
<CragItem key={getOsmappLink(item)} feature={item} />
))}
</CragList>
Expand Down
5 changes: 4 additions & 1 deletion src/components/FeaturePanel/FeaturePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { RouteDistributionInPanel } from './Climbing/RouteDistribution';
import { RouteListInPanel } from './Climbing/RouteList/RouteList';
import { FeaturePanelFooter } from './FeaturePanelFooter';
import { ClimbingRouteGrade } from './ClimbingRouteGrade';
import { Box } from '@mui/material';

const Flex = styled.div`
flex: 1;
Expand Down Expand Up @@ -61,7 +62,9 @@ export const FeaturePanel = () => {
<CragsInArea />
</PanelSidePadding>

<FeatureImages />
<Box mb={2}>
<FeatureImages />
</Box>
<RouteDistributionInPanel />
<RouteListInPanel />

Expand Down
6 changes: 2 additions & 4 deletions src/components/FeaturePanel/ImagePane/FeatureImages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ import { useLoadImages } from './useLoadImages';
import { NoImage } from './NoImage';
import { HEIGHT, ImageSkeleton } from './helpers';

const Wrapper = styled.div`
export const Wrapper = styled.div`
width: 100%;
height: calc(${HEIGHT}px + 10px); // 10px for scrollbar
min-height: calc(${HEIGHT}px + 10px); // otherwise it shrinks b/c of flex

margin-bottom: 16px;
`;

const StyledScrollbars = styled(Scrollbars)`
Expand All @@ -25,7 +23,7 @@ const StyledScrollbars = styled(Scrollbars)`
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
`;
const Slider = ({ children }) => (
export const Slider = ({ children }) => (
<StyledScrollbars universal autoHide>
{children}
</StyledScrollbars>
Expand Down
1 change: 1 addition & 0 deletions src/components/Map/behaviour/useInitMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const filterConsoleLog = () => {
// eslint-disable-next-line no-console
console.warn = (message, ...optionalParams) => {
if (
typeof message === 'string' &&
!message.includes(
'Please make sure you have added the image with map.addImage',
)
Expand Down
2 changes: 0 additions & 2 deletions src/components/Map/behaviour/useUpdateStyle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ export const useUpdateStyle = createMapEffectHook(

const style = cloneDeep(getBaseStyle(key));
addOverlaysToStyle(map, style, overlays);
console.log('style', map.loaded(), map.getStyle()); // eslint-disable-line no-console
map.setStyle(style, { diff: map.loaded() });
console.log('style2', map.loaded(), map.getStyle()); // eslint-disable-line no-console

setUpHover(map, layersWithOsmId(style));
},
Expand Down
Loading
Loading