diff --git a/frontend/src/components/Map/DetailsMap/PointsSecondary.tsx b/frontend/src/components/Map/DetailsMap/PointsSecondary.tsx index f78781345..51e2cfb31 100644 --- a/frontend/src/components/Map/DetailsMap/PointsSecondary.tsx +++ b/frontend/src/components/Map/DetailsMap/PointsSecondary.tsx @@ -1,10 +1,9 @@ -import React, { FC, useMemo } from 'react'; +import { useMemo } from 'react'; +import Image from 'next/image'; import { Tooltip } from 'react-leaflet'; import { Signage } from 'components/Icons/Signage'; import { renderToStaticMarkup } from 'react-dom/server'; import { SignageDictionary } from 'modules/signage/interface'; -import styled, { css } from 'styled-components'; -import { desktopOnly, getSpacing } from 'stylesheet'; import { RawCoordinate2D } from 'modules/interface'; import { InfrastructureDictionary } from 'modules/infrastructure/interface'; import { FormattedMessage } from 'react-intl'; @@ -12,7 +11,7 @@ import { HoverableMarker } from '../components/HoverableMarker'; export type PointsSecondaryProps = { dictionary?: SignageDictionary | InfrastructureDictionary | null; - icon?: FC; + icon?: React.FC; }; type Locations = { @@ -57,14 +56,23 @@ export const PointsSecondary: React.FC = ({ pictogramUri={location.pictogramUri} type={null} > - +
- {location.imageUrl !== null && } + {location.imageUrl !== null && ( + + )}
{location.type}
- +

{location.name} - +

{Boolean(location.description) && (

= ({ )}

-
+ ))} ); }; - -const desktopWidth = 288; -const desktopImgHeight = 122; -const mobileWidth = 215; -const mobileImgHeight = 133; - -const StyledTooltip = styled(Tooltip)` - padding: 0; - border: 0px !important; - border-radius: ${getSpacing(4)} !important; - overflow: hidden; - white-space: initial !important; - width: ${mobileWidth}px; - ${desktopOnly(css` - width: ${desktopWidth}px; - `)}; -`; - -const Name = styled.span` - ${desktopOnly(css` - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - display: block; - `)} -`; - -const CoverImage = styled.img` - height: ${mobileImgHeight}px; - ${desktopOnly(css` - height: ${desktopImgHeight}px; - `)} - object-fit: cover; -`; diff --git a/frontend/src/components/Map/components/Popup/index.tsx b/frontend/src/components/Map/components/Popup/index.tsx index 2220fc84d..e2522de18 100644 --- a/frontend/src/components/Map/components/Popup/index.tsx +++ b/frontend/src/components/Map/components/Popup/index.tsx @@ -1,64 +1,94 @@ -import React, { useState } from 'react'; +import { useState } from 'react'; +import Image from 'next/image'; import { routes } from 'services/routes'; -import styled, { css } from 'styled-components'; import { Popup as LeafletPopup, Tooltip as LeafletTooltip } from 'react-leaflet'; import { FormattedMessage } from 'react-intl'; import Loader from 'components/Loader'; -import { desktopOnly, getSpacing } from 'stylesheet'; import { Button } from 'components/Button'; import { generateResultDetailsUrl } from 'components/pages/search/utils'; import Link from 'components/Link'; +import { PopupResult } from 'modules/trekResult/interface'; import { usePopupResult } from '../../hooks/usePopupResult'; interface Props { - id: number; + id: number | string; parentId?: number; handleOpen?: () => void; handleClose?: () => void; - type: 'TREK' | 'TOURISTIC_CONTENT' | 'OUTDOOR_SITE' | 'TOURISTIC_EVENT'; + type: 'TREK' | 'TOURISTIC_CONTENT' | 'OUTDOOR_SITE' | 'TOURISTIC_EVENT' | null; + content?: PopupResult; } interface PropsPC { showButton: boolean; - id: number; - type: 'TREK' | 'TOURISTIC_CONTENT' | 'OUTDOOR_SITE' | 'TOURISTIC_EVENT'; + id: number | string; + type: 'TREK' | 'TOURISTIC_CONTENT' | 'OUTDOOR_SITE' | 'TOURISTIC_EVENT' | null; parentId?: number; + content?: PopupResult; } -const getRoute = (type: string) => { - if (type === 'TOURISTIC_CONTENT') return routes.TOURISTIC_CONTENT; - if (type === 'OUTDOOR_SITE') return routes.OUTDOOR_SITE; - if (type === 'TOURISTIC_EVENT') return routes.TOURISTIC_EVENT; - return routes.TREK; -}; +const getRoute = (type: PropsPC['type']) => (type && routes[type]) ?? routes.TREK; + +const PopupContent: React.FC = ({ showButton, id, type, parentId, content }) => { + let isLoading = false; + let trekPopupResult = null; -const PopupContent: React.FC = ({ showButton, id, type, parentId }) => { - const { isLoading, trekPopupResult } = usePopupResult(id.toString(), true, type); + const popupResult = usePopupResult(id.toString(), true, type); + + if (!content && type) { + isLoading = popupResult.isLoading; + trekPopupResult = popupResult.trekPopupResult; + } else { + trekPopupResult = content; + } return ( {trekPopupResult && (
- +
- - {trekPopupResult.place} - -

+ {trekPopupResult.place && ( + + {trekPopupResult.place} + + )} +

{trekPopupResult.title}

{showButton && ( - - - + <> + {trekPopupResult.button?.onClick ? ( + + ) : ( + + + + + + )} + )}
@@ -67,85 +97,37 @@ const PopupContent: React.FC = ({ showButton, id, type, parentId }) => ); }; -export const Popup: React.FC = ({ id, parentId, handleOpen, handleClose, type }) => { +export const Popup: React.FC = ({ + id, + parentId, + handleOpen, + handleClose, + type, + content, +}) => { const [hideTooltip, setHideTooltip] = useState(false); return ( <> {!hideTooltip && ( - - - + + + )} - { setHideTooltip(true); - handleOpen && handleOpen(); + handleOpen?.(); }} onClose={() => { setHideTooltip(false); - handleClose && handleClose(); + handleClose?.(); }} offset={[0, -12]} > - - + + ); }; - -const desktopWidth = 288; -const desktopImgHeight = 122; -const mobileWidth = 215; -const mobileImgHeight = 133; - -const StyledTooltip = styled(LeafletTooltip)` - padding: 0; - border: 0px !important; - border-radius: ${getSpacing(4)} !important; - overflow: hidden; - white-space: initial !important; - width: ${mobileWidth}px; - ${desktopOnly(css` - width: ${desktopWidth}px; - `)}; -`; - -const StyledPopup = styled(LeafletPopup)` - .leaflet-popup-content { - margin: 0; - - // Show the loader properly - position: relative; - min-height: 120px; - min-width: 120px; - } - - .leaflet-popup-content-wrapper { - padding: 0; - - border-radius: ${getSpacing(4)}; - overflow: hidden; - - width: ${mobileWidth}px; - ${desktopOnly(css` - width: ${desktopWidth}px; - `)}; - } - - // Removes native leaflet popup triangle below the content - // https://stackoverflow.com/a/51457598/14707543 - .leaflet-popup-tip { - background: rgba(0, 0, 0, 0) !important; - box-shadow: none !important; - } -`; - -const CoverImage = styled.img` - height: ${mobileImgHeight}px; - ${desktopOnly(css` - height: ${desktopImgHeight}px; - `)} - object-fit: cover; -`; diff --git a/frontend/src/components/Map/hooks/usePopupResult.ts b/frontend/src/components/Map/hooks/usePopupResult.ts index 99385a4fd..c665353c4 100644 --- a/frontend/src/components/Map/hooks/usePopupResult.ts +++ b/frontend/src/components/Map/hooks/usePopupResult.ts @@ -12,7 +12,7 @@ import { getOutdoorSitePopupResult } from '../../../modules/outdoorSite/connecto export const usePopupResult = ( id: string, shouldFetch: boolean, - type: 'TREK' | 'TOURISTIC_CONTENT' | 'OUTDOOR_SITE' | 'TOURISTIC_EVENT', + type: 'TREK' | 'TOURISTIC_CONTENT' | 'OUTDOOR_SITE' | 'TOURISTIC_EVENT' | null, ) => { const language = useRouter().locale ?? getDefaultLanguage(); const commonDictionaries = queryCommonDictionaries(language); @@ -31,7 +31,7 @@ export const usePopupResult = ( const { data: trekPopupResult, isLoading } = useQuery( ['popupResult', id, language], fetchData, - { enabled: shouldFetch && commonDictionaries !== undefined }, + { enabled: type !== null && shouldFetch && commonDictionaries !== undefined }, ); return { diff --git a/frontend/src/modules/trekResult/interface.ts b/frontend/src/modules/trekResult/interface.ts index 8f24f9b14..f29f2f419 100644 --- a/frontend/src/modules/trekResult/interface.ts +++ b/frontend/src/modules/trekResult/interface.ts @@ -10,4 +10,8 @@ export interface PopupResult { title: string; place: string; imgUrl: string; + button?: { + label: string; + onClick?: () => void; + }; } diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index dab6d978c..bd39c1aeb 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -33,6 +33,7 @@ border-hardKO ; } + .textarea { @apply bg-white @@ -50,6 +51,27 @@ ; } +/* Leaflet */ +.leaflet-popup .leaflet-popup-content { + @apply m-0; + /* Show the loader properly */ + @apply relative; + min-height: 120px; + min-width: 120px; +} + +.leaflet-popup .leaflet-popup-content-wrapper { + @apply p-0 rounded-xl overflow-hidden w-55 desktop:w-70; +} + +.leaflet-popup .leaflet-popup-tip { + /* Removes native leaflet popup triangle below the content + https://stackoverflow.com/a/51457598/14707543 + */ + background: rgba(0, 0, 0, 0) !important; + box-shadow: none !important; +} + .hasDrawer .leaflet-bottom { @apply mb-12; @apply desktop:mb-0; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 7b984a6c3..16eded00e 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -45,6 +45,7 @@ module.exports = { 30: `${SPACING_UNIT * 30}px`, 40: `${SPACING_UNIT * 40}px`, 50: `${SPACING_UNIT * 50}px`, + 55: `${SPACING_UNIT * 55}px`, 60: `${SPACING_UNIT * 60}px`, 70: `${SPACING_UNIT * 70}px`, 90: `${SPACING_UNIT * 90}px`,