Merged in feat/SW-2241-country-map (pull request #2808)

Feat/SW-2241 country map

Approved-by: Erik Tiekstra
Approved-by: Chuma Mcphoy (We Ahead)
This commit is contained in:
Matilda Landström
2025-09-24 12:04:01 +00:00
parent af4f544b8a
commit 00689607bc
93 changed files with 1876 additions and 600 deletions

View File

@@ -0,0 +1,57 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { Badge } from './Badge.tsx'
const meta: Meta<typeof Badge> = {
title: 'Components/Badge',
component: Badge,
}
export default meta
type Story = StoryObj<typeof Badge>
export const Default: Story = {}
export const XS: Story = {
render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
<Badge number={3} color="primary" size="20" />
<Badge number={3} color="green" size="20" />
</div>
),
}
export const Small: Story = {
render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
<Badge number={3} color="primary" size="24" />
<Badge number={3} color="green" size="24" />
</div>
),
}
export const Medium: Story = {
render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
<Badge number={3} color="primary" size="28" />
<Badge number={3} color="green" size="28" />
</div>
),
}
export const Large: Story = {
render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
<Badge number={3} color="primary" size="32" />
<Badge number={3} color="green" size="32" />
</div>
),
}
export const XL: Story = {
render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
<Badge number={3} color="primary" size="36" />
<Badge number={3} color="green" size="36" />
</div>
),
}

View File

@@ -0,0 +1,35 @@
import { config } from './variants'
import { VariantProps } from 'class-variance-authority'
import { Typography } from '../Typography'
import { TypographyProps } from '../Typography/types'
interface BadgeProps extends VariantProps<typeof config> {
number: number
}
export function Badge({ number, color, size }: BadgeProps) {
const classNames = config({
color,
size,
})
return (
<Typography variant={getTypography(size)}>
<span className={classNames}>{number}</span>
</Typography>
)
}
function getTypography(size: BadgeProps['size']): TypographyProps['variant'] {
switch (size) {
case '36':
case '32':
return 'Body/Paragraph/mdBold'
case '28':
case '24':
return 'Body/Supporting text (caption)/smBold'
case '20':
return 'Label/xsRegular'
}
}

View File

@@ -0,0 +1,42 @@
.badge {
border-radius: var(--Corner-radius-xl);
display: flex;
align-items: center;
justify-content: center;
padding: var(--Space-x025);
}
.primary {
background-color: var(--Surface-Brand-Primary-2-Default);
color: var(--Text-Inverted);
}
.green {
background-color: var(--Surface-Feedback-Succes);
color: var(--Text-Feedback-Succes-Accent);
}
._36 {
width: 36px;
height: 36px;
}
._32 {
width: 32px;
height: 32px;
}
._28 {
width: 28px;
height: 28px;
}
._24 {
width: 24px;
height: 24px;
}
._20 {
width: 20px;
height: 20px;
}

View File

@@ -0,0 +1 @@
export { Badge } from './Badge'

View File

@@ -0,0 +1,23 @@
import { cva } from 'class-variance-authority'
import styles from './badge.module.css'
export const config = cva(styles.badge, {
variants: {
color: {
primary: styles.primary,
green: styles.green,
},
size: {
'36': styles._36,
'32': styles._32,
'28': styles._28,
'24': styles._24,
'20': styles._20,
},
},
defaultVariants: {
color: 'primary',
size: '28',
},
})

View File

@@ -7,14 +7,9 @@ import { useIntl } from 'react-intl'
import { IconButton } from '../../IconButton'
import { MaterialIcon } from '../../Icons/MaterialIcon'
import {
DEFAULT_ZOOM,
MAP_RESTRICTIONS,
MAX_ZOOM,
MIN_ZOOM,
} from '../mapConstants'
import { HOTEL_PAGE, MAP_RESTRICTIONS } from '../mapConstants'
import { useZoomControls } from './useZoomControls'
import { useZoomControls } from '@scandic-hotels/common/hooks/map/useZoomControls'
import { HotelListingMapContent } from './HotelListingMapContent'
import PoiMapMarkers from './PoiMapMarkers'
@@ -87,12 +82,12 @@ export function InteractiveMap({
const intl = useIntl()
const map = useMap()
const [hasInitializedBounds, setHasInitializedBounds] = useState(false)
const { zoomIn, zoomOut, isMaxZoom, isMinZoom } = useZoomControls()
const { zoomIn, zoomOut, isMaxZoom, isMinZoom } = useZoomControls(HOTEL_PAGE)
const mapOptions: MapProps = {
defaultZoom: DEFAULT_ZOOM,
minZoom: MIN_ZOOM,
maxZoom: MAX_ZOOM,
defaultZoom: HOTEL_PAGE.DEFAULT_ZOOM,
minZoom: HOTEL_PAGE.MIN_ZOOM,
maxZoom: HOTEL_PAGE.MAX_ZOOM,
defaultCenter: coordinates,
disableDefaultUI: true,
clickableIcons: false,

View File

@@ -1,42 +0,0 @@
import { useMap } from '@vis.gl/react-google-maps'
import { useEffect, useState } from 'react'
import { DEFAULT_ZOOM, MAX_ZOOM, MIN_ZOOM } from '../mapConstants'
export function useZoomControls() {
const map = useMap()
const [zoomLevel, setZoomLevel] = useState(DEFAULT_ZOOM)
const zoomIn = () => {
if (map && zoomLevel < MAX_ZOOM) {
map.setZoom(zoomLevel + 1)
}
}
const zoomOut = () => {
if (map && zoomLevel > MIN_ZOOM) {
map.setZoom(zoomLevel - 1)
}
}
useEffect(() => {
if (!map) return
const handleZoomChanged = () => {
const currentZoom = map.getZoom()
if (currentZoom != null) {
setZoomLevel(currentZoom)
}
}
const listener = map.addListener('zoom_changed', handleZoomChanged)
return () => listener.remove()
}, [map])
return {
zoomLevel,
zoomIn,
zoomOut,
isMinZoom: zoomLevel <= MIN_ZOOM,
isMaxZoom: zoomLevel >= MAX_ZOOM,
}
}

View File

@@ -4,6 +4,34 @@ export const MAP_RESTRICTIONS = {
latLngBounds: { north: 85, south: -85, west: -180, east: 180 },
}
export const DEFAULT_ZOOM = 14
export const MAX_ZOOM = 18
export const MIN_ZOOM = 8
export const HOTEL_PAGE = {
DEFAULT_ZOOM: 14,
MAX_ZOOM: 18,
MIN_ZOOM: 8,
} as const
export const DESTINATION_PAGE = {
DEFAULT_ZOOM: 10,
MAX_ZOOM: 18,
MIN_ZOOM: 3,
}
export const CITY_PAGE = {
DEFAULT_ZOOM: 10,
SELECTED_HOTEL_ZOOM: 15,
MAX_ZOOM: 18,
MIN_ZOOM: 3,
} as const
export const COUNTRY_PAGE = {
DEFAULT_ZOOM: 3,
SELECTED_HOTEL_ZOOM: 15,
MAX_ZOOM: 18,
MIN_ZOOM: 3,
} as const
export type MapType =
| typeof HOTEL_PAGE
| typeof DESTINATION_PAGE
| typeof CITY_PAGE
| typeof COUNTRY_PAGE

View File

@@ -276,7 +276,7 @@
font-style: normal;
font-weight: 400;
font-display: block;
src: url(/_static/shared/fonts/material-symbols/rounded-f2d895e1.woff2)
src: url(/_static/shared/fonts/material-symbols/rounded-1db5531f.woff2)
format('woff2');
}