Merged in fix/linting (pull request #2708)

Fix/linting

* fix import issues and add lint check no-extraneous-dependencies
* fix use type HotelType instead of string

Approved-by: Anton Gunnarsson
This commit is contained in:
Joakim Jäderberg
2025-08-27 09:22:37 +00:00
parent 67bdf5bbcf
commit 80c3327419
55 changed files with 250 additions and 135 deletions

View File

@@ -29,7 +29,7 @@ export default defineConfig([
"react/function-component-definition": "error",
"import/no-relative-packages": "error",
"simple-import-sort/imports": [
"error",
"warn",
{
groups: [
["^\\u0000"],

View File

@@ -16,6 +16,8 @@ import { trackMapClick } from "@/utils/tracking/destinationPage"
import HotelMapCard from "../../../HotelMapCard"
import type { HotelType } from "@scandic-hotels/common/constants/hotelType"
import type { MarkerProperties } from "@/types/components/maps/destinationMarkers"
interface MarkerProps {
@@ -60,7 +62,7 @@ export default function Marker({ position, properties }: MarkerProps) {
<HotelMarkerByType
size={isHovered || isActive ? "large" : "small"}
hotelId={properties.id}
hotelType={properties.type}
hotelType={properties.type as HotelType}
/>
{isActive && isDesktop && (

View File

@@ -24,8 +24,8 @@ import Sidebar from "./Sidebar"
import styles from "./hotelMapPage.module.css"
import type { MarkerInfo } from "@scandic-hotels/design-system/Map/types"
import type { PointOfInterest } from "@scandic-hotels/trpc/types/hotel"
import type { MarkerInfo } from "@scandic-hotels/trpc/types/marker"
import type { Coordinates } from "@/types/components/maps/coordinates"

View File

@@ -7,6 +7,8 @@ import { getLang } from "@/i18n/serverContext"
import HotelMapPageClient from "./Client"
import type { HotelType } from "@scandic-hotels/common/constants/hotelType"
interface HotelMapPageProps {
hotelId: string
}
@@ -35,7 +37,7 @@ export default async function HotelMapPage({ hotelId }: HotelMapPageProps) {
apiKey={env.GOOGLE_STATIC_MAP_KEY}
mapId={env.GOOGLE_DYNAMIC_MAP_ID}
hotelName={name}
markerInfo={{ hotelId, hotelType }}
markerInfo={{ hotelId, hotelType: hotelType as HotelType }} // TODO: Update attributes schema instead
coordinates={coordinates}
pointsOfInterest={pointsOfInterest}
/>

View File

@@ -51,6 +51,8 @@ import {
import styles from "./hotelPage.module.css"
import type { HotelType } from "@scandic-hotels/common/constants/hotelType"
import type { HotelPageProps } from "@/types/components/hotelPage/hotelPage"
import { AlertName } from "@/types/enums/alert"
import { HotelHashValues } from "@/types/enums/hotelPage"
@@ -242,7 +244,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
<StaticMap
coordinates={coordinates}
hotelName={name}
markerInfo={{ hotelType, hotelId }}
markerInfo={{ hotelType: hotelType as HotelType, hotelId }} // TODO: Update hotel attributes schema instead
/>
</Link>
<MapCard

View File

@@ -1,4 +1,4 @@
import type { MarkerInfo } from "@scandic-hotels/trpc/types/marker"
import type { MarkerInfo } from "@scandic-hotels/design-system/Map/types"
import type { Coordinates } from "../../maps/coordinates"

View File

@@ -27,7 +27,7 @@ export default defineConfig([
"react/function-component-definition": "error",
"import/no-relative-packages": "error",
"simple-import-sort/imports": [
"error",
"warn",
{
groups: [
["^\\u0000"],

View File

@@ -1,5 +1,9 @@
const config = {
"*.{ts,tsx}": [() => "tsc -p tsconfig.json --noEmit", "prettier --write"],
"*.{ts,tsx}": [
() => "yarn lint",
() => "tsc -p tsconfig.json --noEmit",
"prettier --write",
],
"*.{js,cjs,mjs}": "prettier --write",
}

View File

@@ -33,7 +33,7 @@ export default defineConfig([
"no-unused-vars": "off",
"import/no-relative-packages": "error",
"simple-import-sort/imports": [
"error",
"warn",
{
groups: [
["^\\u0000"],

View File

@@ -1,5 +1,9 @@
const config = {
"*.{ts,tsx}": [() => "tsc -p tsconfig.json --noEmit", "prettier --write"],
"*.{ts,tsx}": [
() => "yarn lint",
() => "tsc -p tsconfig.json --noEmit",
"prettier --write",
],
"*.{json,md}": "prettier --write",
"*.{html,js,cjs,mjs,css}": "prettier --write",
}

View File

@@ -7,11 +7,16 @@ import js from '@eslint/js'
import importPlugin from 'eslint-plugin-import'
import formatjs from 'eslint-plugin-formatjs'
import { fileURLToPath } from 'node:url'
import path from 'node:path'
const compat = new FlatCompat({
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
})
const packageDir = path.dirname(fileURLToPath(import.meta.url))
export default defineConfig([
{
languageOptions: {
@@ -31,8 +36,28 @@ export default defineConfig([
import: importPlugin,
formatjs,
},
settings: {
// Ensure the plugin can resolve workspace packages and TS path aliases
'import/resolver': {
typescript: {
project: [path.join(packageDir, 'tsconfig.json')],
alwaysTryTypes: true,
},
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
rules: {
'import/no-relative-packages': 'error',
'import/no-extraneous-dependencies': [
'error',
{
includeInternal: true,
includeTypes: true,
packageDir: [packageDir],
},
],
'react-refresh/only-export-components': [
'warn',
{
@@ -53,5 +78,11 @@ export default defineConfig([
'formatjs/prefer-pound-in-plural': ['error'],
},
},
globalIgnores(['**/dist', '**/.eslintrc.cjs']),
{
files: ['**/*.stories.tsx'],
rules: {
'formatjs/no-literal-string-in-jsx': 'off',
},
},
globalIgnores(['**/dist', '**/.eslintrc.cjs', '**/storybook-static']),
])

View File

@@ -1,4 +1,4 @@
import type { Meta, StoryObj } from '@storybook/react-vite'
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { fn } from 'storybook/test'
import { BookingCodeChip } from './index'

View File

@@ -1,11 +1,11 @@
import { Button as ButtonRAC } from 'react-aria-components'
import { useIntl } from 'react-intl'
import IconChip from '@scandic-hotels/design-system/IconChip'
import DiscountIcon from '@scandic-hotels/design-system/Icons/DiscountIcon'
import FilledDiscountIcon from '@scandic-hotels/design-system/Icons/FilledDiscountIcon'
import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon'
import { Typography } from '@scandic-hotels/design-system/Typography'
import IconChip from '../IconChip'
import DiscountIcon from '../Icons/Nucleo/Benefits/discount-2-2'
import FilledDiscountIcon from '../Icons/Nucleo/Benefits/FilledDiscount'
import { MaterialIcon } from '../Icons/MaterialIcon'
import { Typography } from '../Typography'
import styles from './bookingCodeChip.module.css'

View File

@@ -556,7 +556,6 @@ export const TextWithIcon: Story = {
args: {
onPress: fn(),
children: (
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
<>
Text with icon
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
@@ -578,7 +577,6 @@ export const TextWithIconInverted: Story = {
args: {
onPress: fn(),
children: (
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
<>
Text with icon
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />

View File

@@ -1,4 +1,4 @@
import Footnote from '@scandic-hotels/design-system/Footnote'
import Footnote from '../Footnote'
import { chipVariants } from './variants'
import { VariantProps } from 'class-variance-authority'

View File

@@ -35,6 +35,8 @@ interface SelectProps
type SelectPortalContainer = HTMLDivElement | undefined
type SelectPortalContainerArgs = HTMLDivElement | null
const DELIMITER = ':'
/**
* @deprecated Do not use.
*/
@@ -102,7 +104,7 @@ export default function Select({
size={discreet ? 'discreet' : 'regular'}
>
{label}
{discreet && `:`}
{discreet && DELIMITER}
</Label>
{selectedText && (
<Body className={optionsIcon ? styles.iconLabel : ''}>

View File

@@ -1,4 +1,4 @@
import type { Meta, StoryObj } from '@storybook/react-vite'
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { FacilityEnum } from '@scandic-hotels/common/constants/facilities'

View File

@@ -1,10 +1,9 @@
import type { Meta, StoryObj } from '@storybook/react-vite'
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { HotelCard } from './index'
import { fn } from 'storybook/test'
import { RateTypeEnum } from '@scandic-hotels/common/constants/rateType'
import { HotelTypeEnum } from '@scandic-hotels/trpc/enums/hotelType'
import { Button } from '@scandic-hotels/design-system/Button'
import { Button } from '../Button'
import { MaterialIcon } from '../Icons/MaterialIcon'
const meta: Meta<typeof HotelCard> = {
@@ -37,7 +36,7 @@ export const Default: Story = {
name: 'Test Hotel',
address: { streetAddress: '123 Test Street', city: 'Test City' },
description: 'A great place to stay.',
hotelType: HotelTypeEnum.Signature,
hotelType: 'signature',
detailedFacilities: [],
ratings: {
tripAdvisor: 4,
@@ -81,7 +80,6 @@ export const Default: Story = {
onPress={() => fn()}
variant="Text"
typography="Body/Paragraph/mdBold"
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
>
Read more
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />

View File

@@ -1,7 +1,7 @@
import Image from '@scandic-hotels/design-system/Image'
import Image from '../../Image'
import { hotelCardDialogImageVariants } from './variants'
import { TripAdvisorChip } from '@scandic-hotels/design-system/TripAdvisorChip'
import { TripAdvisorChip } from '../../TripAdvisorChip'
import styles from './hotelCardDialogImage.module.css'

View File

@@ -1,4 +1,4 @@
import SkeletonShimmer from '@scandic-hotels/design-system/SkeletonShimmer'
import SkeletonShimmer from '../SkeletonShimmer'
import styles from './HotelCardSkeleton.module.css'

View File

@@ -1,12 +1,23 @@
import { useIntl } from 'react-intl'
import { CurrencyEnum } from '@scandic-hotels/common/constants/currency'
import Caption from '@scandic-hotels/design-system/Caption'
import Subtitle from '@scandic-hotels/design-system/Subtitle'
import Caption from '../../Caption'
import Subtitle from '../../Subtitle'
import styles from './hotelChequeCard.module.css'
import type { ProductTypeCheque } from '@scandic-hotels/trpc/types/availability'
type ProductTypeCheque = {
localPrice: {
numberOfCheques: number
additionalPricePerStay: number
currency: CurrencyEnum | null | undefined
}
requestedPrice?: {
numberOfCheques: number
additionalPricePerStay: number
currency: CurrencyEnum | null | undefined
}
}
export default function HotelChequeCard({
productTypeCheque,

View File

@@ -1,4 +1,4 @@
import type { Meta, StoryObj } from '@storybook/react-vite'
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { StandaloneHotelCardDialog } from './index'
import { fn } from 'storybook/test'

View File

@@ -4,15 +4,15 @@ import { useState } from 'react'
import { useIntl } from 'react-intl'
import { selectRate } from '@scandic-hotels/common/constants/routes/hotelReservation'
import Body from '@scandic-hotels/design-system/Body'
import Caption from '@scandic-hotels/design-system/Caption'
import Footnote from '@scandic-hotels/design-system/Footnote'
import { IconButton } from '@scandic-hotels/design-system/IconButton'
import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon'
import Link from '@scandic-hotels/design-system/Link'
import { OldDSButton as Button } from '@scandic-hotels/design-system/OldDSButton'
import Subtitle from '@scandic-hotels/design-system/Subtitle'
import { Typography } from '@scandic-hotels/design-system/Typography'
import Body from '../../../Body'
import Caption from '../../../Caption'
import Footnote from '../../../Footnote'
import { IconButton } from '../../../IconButton'
import { MaterialIcon } from '../../../Icons/MaterialIcon'
import Link from '../../../Link'
import { OldDSButton as Button } from '../../../OldDSButton'
import Subtitle from '../../../Subtitle'
import { Typography } from '../../../Typography'
import { NoPriceAvailableCard } from '../../NoPriceAvailableCard'
import { HotelCardDialogImage } from '../../HotelCardDialogImage'
@@ -20,7 +20,7 @@ import { HotelCardDialogImage } from '../../HotelCardDialogImage'
import styles from './standaloneHotelCardDialog.module.css'
import { Lang } from '@scandic-hotels/common/constants/language'
import { HotelPin } from '../../../Map/types'
import { FacilityToIcon } from '@scandic-hotels/design-system/FacilityToIcon'
import { FacilityToIcon } from '../../../FacilityToIcon'
import { HotelPointsRow } from '../../HotelPointsRow'
interface StandaloneHotelCardProps {

View File

@@ -1,7 +1,7 @@
import { useIntl } from 'react-intl'
import Caption from '@scandic-hotels/design-system/Caption'
import Subtitle from '@scandic-hotels/design-system/Subtitle'
import Caption from '../../Caption'
import Subtitle from '../../Subtitle'
import styles from './hotelPointsRow.module.css'

View File

@@ -1,10 +1,10 @@
import { cx } from 'class-variance-authority'
import { useIntl } from 'react-intl'
import Body from '@scandic-hotels/design-system/Body'
import Caption from '@scandic-hotels/design-system/Caption'
import { Divider } from '@scandic-hotels/design-system/Divider'
import Subtitle from '@scandic-hotels/design-system/Subtitle'
import Body from '../../Body'
import Caption from '../../Caption'
import { Divider } from '../../Divider'
import Subtitle from '../../Subtitle'
import { RateTypeEnum } from '@scandic-hotels/common/constants/rateType'
import styles from './hotelPriceCard.module.css'

View File

@@ -1,12 +1,14 @@
import { useIntl } from 'react-intl'
import { CurrencyEnum } from '@scandic-hotels/common/constants/currency'
import Caption from '@scandic-hotels/design-system/Caption'
import Subtitle from '@scandic-hotels/design-system/Subtitle'
import Caption from '../../Caption'
import Subtitle from '../../Subtitle'
import styles from './hotelVoucherCard.module.css'
import type { ProductTypeVoucher } from '@scandic-hotels/trpc/types/availability'
type ProductTypeVoucher = {
numberOfVouchers: number
}
export default function HotelVoucherCard({
productTypeVoucher,

View File

@@ -1,7 +1,7 @@
import { useIntl } from 'react-intl'
import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon'
import { Typography } from '@scandic-hotels/design-system/Typography'
import { MaterialIcon } from '../../Icons/MaterialIcon'
import { Typography } from '../../Typography'
import styles from './noPriceAvailable.module.css'

View File

@@ -11,17 +11,15 @@ import {
selectRate,
} from '@scandic-hotels/common/constants/routes/hotelReservation'
import { getSingleDecimal } from '@scandic-hotels/common/utils/numberFormatting'
import Caption from '@scandic-hotels/design-system/Caption'
import { Divider } from '@scandic-hotels/design-system/Divider'
import { FacilityToIcon } from '@scandic-hotels/design-system/FacilityToIcon'
import HotelLogoIcon from '@scandic-hotels/design-system/Icons/HotelLogoIcon'
import ImageGallery, {
GalleryImage,
} from '@scandic-hotels/design-system/ImageGallery'
import Caption from '../Caption'
import { Divider } from '../Divider'
import { FacilityToIcon } from '../FacilityToIcon'
import HotelLogoIcon from '../Icons/Logos'
import ImageGallery, { GalleryImage } from '../ImageGallery'
import { HotelPointsRow } from './HotelPointsRow'
import { NoPriceAvailableCard } from './NoPriceAvailableCard'
import Link from '@scandic-hotels/design-system/Link'
import { Typography } from '@scandic-hotels/design-system/Typography'
import Link from '../Link'
import { Typography } from '../Typography'
import HotelChequeCard from './HotelChequeCard'
import { HotelPriceCard } from './HotelPriceCard'

View File

@@ -1,12 +1,12 @@
import { cx } from 'class-variance-authority'
import { Divider } from '@scandic-hotels/design-system/Divider'
import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon'
import Image from '@scandic-hotels/design-system/Image'
import ImageContainer from '@scandic-hotels/design-system/ImageContainer'
import Link from '@scandic-hotels/design-system/Link'
import Table from '@scandic-hotels/design-system/Table'
import { Typography } from '@scandic-hotels/design-system/Typography'
import { Divider } from '../Divider'
import { MaterialIcon } from '../Icons/MaterialIcon'
import Image from '../Image'
import ImageContainer from '../ImageContainer'
import Link from '../Link'
import Table from '../Table'
import { Typography } from '../Typography'
import {
hasAvailableParagraphFormat,

View File

@@ -94,6 +94,7 @@ export default function FullView({
<div className={styles.header}>
<Typography variant="Tag/sm">
<span className={styles.imageCount}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${currentIndex + 1} / ${totalImages}`}
</span>
</Typography>

View File

@@ -1,8 +1,8 @@
import { useIntl } from 'react-intl'
import { formatPrice } from '@scandic-hotels/common/utils/numberFormatting'
import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon'
import { Typography } from '@scandic-hotels/design-system/Typography'
import { MaterialIcon } from '../../../../Icons/MaterialIcon'
import { Typography } from '../../../../Typography'
import HotelMarker from '../../../Markers/HotelMarker'
@@ -15,7 +15,7 @@ interface HotelPinProps {
hotelAdditionalPrice?: number
hotelAdditionalCurrency?: string
}
const NOT_AVAILABLE = '-'
export function HotelPin({
isActive,
hotelPrice,
@@ -45,7 +45,7 @@ export function HotelPin({
<Typography variant="Body/Paragraph/mdRegular">
<p>
{isNotAvailable
? '—'
? NOT_AVAILABLE
: formatPrice(
intl,
hotelPrice,

View File

@@ -4,15 +4,13 @@ import {
} from '@vis.gl/react-google-maps'
import { useIntl } from 'react-intl'
import { Typography } from '@scandic-hotels/design-system/Typography'
import { Typography } from '../../../Typography'
import { HotelMarkerByType } from '../../Markers/HotelMarkerByType'
import { PoiMarker } from '../../Markers/PoiMarker'
import styles from './poiMapMarkers.module.css'
import type { PointOfInterest } from '@scandic-hotels/trpc/types/hotel'
import type { MarkerInfo } from '@scandic-hotels/trpc/types/marker'
import { MarkerInfo, PointOfInterest } from '../../types'
export type PoiMapMarkersProps = {
activePoi?: string | null

View File

@@ -4,8 +4,8 @@ import { Map, type MapProps, useMap } from '@vis.gl/react-google-maps'
import { useEffect, useState } from 'react'
import { useIntl } from 'react-intl'
import { IconButton } from '@scandic-hotels/design-system/IconButton'
import { MaterialIcon } from '@scandic-hotels/design-system/Icons/MaterialIcon'
import { IconButton } from '../../IconButton'
import { MaterialIcon } from '../../Icons/MaterialIcon'
import {
DEFAULT_ZOOM,
@@ -21,9 +21,7 @@ import PoiMapMarkers from './PoiMapMarkers'
import styles from './interactiveMap.module.css'
import type { PointOfInterest } from '@scandic-hotels/trpc/types/hotel'
import type { MarkerInfo } from '@scandic-hotels/trpc/types/marker'
import { HotelPin } from '../types'
import { HotelPin, MarkerInfo, PointOfInterest } from '../types'
import { Lang } from '@scandic-hotels/common/constants/language'
export type InteractiveMapProps = {
@@ -32,7 +30,7 @@ export type InteractiveMapProps = {
lat: number
lng: number
}
activePoi?: PointOfInterest['name'] | null
activePoi?: string | null
hotelPins?: HotelPin[]
pointsOfInterest?: PointOfInterest[]
markerInfo?: MarkerInfo
@@ -44,7 +42,7 @@ export type InteractiveMapProps = {
isUserLoggedIn: boolean
onTilesLoaded?: () => void
onActivePoiChange?: (poi: PointOfInterest['name'] | null) => void
onActivePoiChange?: (poi: string | null) => void
onClickHotel?: (hotelId: string) => void

View File

@@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { HotelMarkerByType } from './HotelMarkerByType'
import { SignatureHotelEnum } from '@scandic-hotels/common/constants/signatureHotels'
import { Typography } from 'lib/components/Typography'
import { Typography } from '../../Typography'
const meta: Meta<typeof HotelMarkerByType> = {
title: 'Components/Map/Hotel Marker By Type',
@@ -48,7 +48,7 @@ type Story = StoryObj<typeof HotelMarkerByType>
export const PrimaryDefault: Story = {
args: {
hotelId: 'Other',
hotelType: 'Regular',
hotelType: 'regular',
size: 'large',
},
}
@@ -56,7 +56,7 @@ export const PrimaryDefault: Story = {
export const ScandicGo: Story = {
args: {
hotelId: 'Other',
hotelType: 'Scandic Go',
hotelType: 'scandicgo',
size: 'large',
},
argTypes: {
@@ -76,7 +76,7 @@ export const ScandicGo: Story = {
export const Signature: Story = {
args: {
hotelId: 'DowntownCamper',
hotelType: 'Signature',
hotelType: 'signature',
size: 'large',
},
argTypes: {
@@ -100,7 +100,7 @@ const exampleMarkers = [
{
name: 'Default',
hotelId: 'Other',
hotelType: 'Regular',
hotelType: 'regular',
},
{
name: 'Scandic Go',

View File

@@ -1,5 +1,3 @@
import { HotelTypeEnum } from '@scandic-hotels/trpc/enums/hotelType'
import { DowntownCamperMarker } from './HotelMarker/SignatureHotel/DowntownCamper'
import { DowntownCamperSmallMarker } from './HotelMarker/SignatureHotel/DowntownCamperSmall'
import { GrandHotelMarker } from './HotelMarker/SignatureHotel/GrandHotel'
@@ -17,9 +15,14 @@ import { ScandicSmallMarker } from './HotelMarker/SignatureHotel/ScandicSmall'
import { TheDockMarker } from './HotelMarker/SignatureHotel/TheDock'
import { TheDockSmallMarker } from './HotelMarker/SignatureHotel/TheDockSmall'
import type { MarkerInfo } from '@scandic-hotels/trpc/types/marker'
import { SignatureHotelEnum } from '@scandic-hotels/common/constants/signatureHotels'
import {
HotelTypes,
type HotelType,
} from '@scandic-hotels/common/constants/hotelType'
import { MarkerInfo } from '../types'
export interface HotelMarkerByTypeProps
extends MarkerInfo,
React.SVGAttributes<HTMLOrSVGElement> {
@@ -35,12 +38,6 @@ export function HotelMarkerByType({
size = 'large',
...props
}: HotelMarkerByTypeProps) {
const typeEntry = byHotelType[hotelType as keyof typeof byHotelType]
if (typeEntry) {
const Cmp = typeEntry[size]
return <Cmp {...props} />
}
const sigatureHotelEntry =
bySignatureHotel[hotelId as keyof typeof bySignatureHotel]
if (sigatureHotelEntry) {
@@ -48,6 +45,12 @@ export function HotelMarkerByType({
return <Cmp {...props} />
}
const typeEntry = byHotelType[hotelType as keyof typeof byHotelType]
if (typeEntry) {
const Cmp = typeEntry[size]
return <Cmp {...props} />
}
const Cmp = defaultMarkers[size]
return <Cmp {...props} />
}
@@ -58,10 +61,10 @@ const defaultMarkers: Record<'large' | 'small', MarkerComponent> = {
}
const byHotelType: Record<
Exclude<HotelTypeEnum, HotelTypeEnum.Regular | HotelTypeEnum.Signature>,
Exclude<HotelType, 'regular' | 'signature'>,
Record<'large' | 'small', MarkerComponent>
> = {
[HotelTypeEnum.ScandicGo]: {
[HotelTypes.ScandicGo]: {
large: ScandicGoMarker,
small: ScandicGoSmallMarker,
},

View File

@@ -1,4 +1,4 @@
import { IconByIconName } from '@scandic-hotels/design-system/Icons/IconByIconName'
import { IconByIconName } from '../../../Icons/IconByIconName'
import { getIconByPoiGroupAndCategory } from '../utils'
import { poiVariants } from './variants'

View File

@@ -1,4 +1,4 @@
import { IconName } from '@scandic-hotels/design-system/Icons/iconName'
import { IconName } from '../../Icons/iconName'
import { PointOfInterestGroup } from './PoiMarker'
export function getIconByPoiGroupAndCategory(

View File

@@ -1,5 +1,6 @@
import { CurrencyEnum } from '@scandic-hotels/common/constants/currency'
import { FacilityEnum } from '@scandic-hotels/common/constants/facilities'
import { HotelType } from '@scandic-hotels/common/constants/hotelType'
export type HotelPin = {
bookingCode?: string | null
@@ -40,3 +41,29 @@ export type HotelPin = {
facilityIds: number[]
hasEnoughPoints: boolean
}
export const PointOfInterestGroups = {
PublicTransport: 'Public transport',
Attractions: 'Attractions',
Business: 'Business',
Location: 'Location',
Parking: 'Parking',
ShoppingAndDining: 'Shopping & Dining',
} as const
export type PointOfInterestGroup =
(typeof PointOfInterestGroups)[keyof typeof PointOfInterestGroups]
export type PointOfInterest = {
id: string
categoryName: string
coordinates: { lat: number; lng: number }
distance: number
group: PointOfInterestGroup
name: string
}
export type MarkerInfo = {
hotelId: string
hotelType: HotelType
}

View File

@@ -2,8 +2,8 @@
import { useIntl } from 'react-intl'
import { Divider } from '@scandic-hotels/design-system/Divider'
import { Typography } from '@scandic-hotels/design-system/Typography'
import { Divider } from '../../Divider'
import { Typography } from '../../Typography'
import { getGroupedOpeningHours } from '../utils'

View File

@@ -2,8 +2,8 @@ import { describe, expect, it } from 'vitest'
import { getGroupedOpeningHours } from './utils'
import type { RestaurantOpeningHours } from '@scandic-hotels/trpc/types/hotel'
import type { IntlShape } from 'react-intl'
import { OpeningHours } from './openingHoursTypes'
// Mock IntlShape for testing
const mockIntl = {
@@ -25,7 +25,7 @@ const mockIntl = {
describe('getGroupedOpeningHours', () => {
it('should group all days as closed', () => {
const allDaysClosed: RestaurantOpeningHours = {
const allDaysClosed: OpeningHours = {
isActive: true,
name: 'Opening hours',
nameEnglish: 'Opening hours',
@@ -84,7 +84,7 @@ describe('getGroupedOpeningHours', () => {
})
it('should group all days with same opening hours', () => {
const allDaysSameHours: RestaurantOpeningHours = {
const allDaysSameHours: OpeningHours = {
isActive: true,
name: 'Opening hours',
nameEnglish: 'Opening hours',
@@ -143,7 +143,7 @@ describe('getGroupedOpeningHours', () => {
})
it('should handle mixed opening hours', () => {
const mixedOpeningHours: RestaurantOpeningHours = {
const mixedOpeningHours: OpeningHours = {
isActive: true,
name: 'Opening hours',
nameEnglish: 'Opening hours',
@@ -206,7 +206,7 @@ describe('getGroupedOpeningHours', () => {
})
it('should handle always open days', () => {
const someAlwaysOpen: RestaurantOpeningHours = {
const someAlwaysOpen: OpeningHours = {
isActive: true,
name: 'Opening hours',
nameEnglish: 'Opening hours',
@@ -269,7 +269,7 @@ describe('getGroupedOpeningHours', () => {
})
it('should handle missing days', () => {
const missingDays: RestaurantOpeningHours = {
const missingDays: OpeningHours = {
isActive: true,
name: 'Opening hours',
nameEnglish: 'Opening hours',
@@ -304,7 +304,7 @@ describe('getGroupedOpeningHours', () => {
})
it('should not group non-consecutive days with same hours', () => {
const nonConsecutiveSameHours: RestaurantOpeningHours = {
const nonConsecutiveSameHours: OpeningHours = {
isActive: true,
name: 'Opening hours',
nameEnglish: 'Opening hours',
@@ -339,7 +339,7 @@ describe('getGroupedOpeningHours', () => {
})
it('should handle nullable opening/closing times', () => {
const nullableHours: RestaurantOpeningHours = {
const nullableHours: OpeningHours = {
isActive: true,
name: 'Opening hours',
nameEnglish: 'Opening hours',
@@ -374,7 +374,7 @@ describe('getGroupedOpeningHours', () => {
})
it('should handle inactive restaurant hours', () => {
const inactiveHours: RestaurantOpeningHours = {
const inactiveHours: OpeningHours = {
isActive: false,
name: 'Opening hours',
nameEnglish: 'Opening hours',

View File

@@ -73,6 +73,7 @@ export default function ParkingPrices({
<Typography variant="Body/Paragraph/mdRegular">
<div className={styles.information}>
<dt>{intl.formatMessage({ defaultMessage: 'From' })}</dt>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<dd>{`${startTime}-${endTime}`}</dd>
</div>
</Typography>

View File

@@ -99,6 +99,7 @@ export default function CampaignRateCard({
</Modal>
{rateTitle}
<span className={styles.textSecondary}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{` / ${paymentTerm}`}
</span>
</h3>
@@ -116,6 +117,7 @@ export default function CampaignRateCard({
</Typography>
<Typography variant="Title/Subtitle/md">
<p>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rate.price} `}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{rate.unit}</span>
@@ -130,6 +132,7 @@ export default function CampaignRateCard({
</Typography>
<Typography variant="Title/Subtitle/md">
<p>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${memberRate.price} `}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{memberRate.unit}</span>
@@ -144,6 +147,7 @@ export default function CampaignRateCard({
<p>
<span className={styles.strikethrough}>
{comparisonRate.price}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
</span>{' '}
<Typography variant="Body/Supporting text (caption)/smBold">
<span className={styles.strikethrough}>

View File

@@ -95,6 +95,7 @@ export default function CodeRateCard({
</Modal>
{rateTitle}
<span className={styles.textSecondary}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{` / ${paymentTerm}`}
</span>
</h3>
@@ -112,6 +113,7 @@ export default function CodeRateCard({
</Typography>
<Typography variant="Title/Subtitle/md">
<p>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rate.price} `}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{rate.unit}</span>
@@ -125,6 +127,7 @@ export default function CodeRateCard({
<p>
<span className={styles.strikethrough}>
{comparisonRate.price}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
</span>{' '}
<Typography variant="Body/Supporting text (caption)/smBold">
<span className={styles.strikethrough}>

View File

@@ -37,6 +37,7 @@ export default function NoRateAvailableCard({
<IconButton theme="Black" style="Muted">
<MaterialIcon icon="info" size={20} color="Icon/Default" />
</IconButton>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rateTitle} / ${paymentTerm}`}
</h3>
</Typography>

View File

@@ -77,6 +77,7 @@ export default function PointsRateCard({
</Modal>
{rateTitle}
<span className={styles.textSecondary}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{` / ${paymentTerm}`}
</span>
</h3>
@@ -97,9 +98,11 @@ export default function PointsRateCard({
<div className={styles.pointsRow}>
<Typography variant="Title/Subtitle/md">
<p>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rate.points} `}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rate.currency} ${rate.additionalPrice ? ' + ' : ''}`}
</span>
</Typography>
@@ -108,6 +111,7 @@ export default function PointsRateCard({
{rate.additionalPrice && (
<Typography variant="Title/Subtitle/md">
<p>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rate.additionalPrice.price} `}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{rate.additionalPrice.currency}</span>

View File

@@ -88,6 +88,7 @@ export default function RegularRateCard({
</Modal>
{rateTitle}
<span className={styles.textSecondary}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{` / ${paymentTerm}`}
</span>
</h3>
@@ -104,6 +105,7 @@ export default function RegularRateCard({
</Typography>
<Typography variant="Title/Subtitle/md">
<p>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rate.price} `}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{rate.unit}</span>
@@ -119,6 +121,7 @@ export default function RegularRateCard({
</Typography>
<Typography variant="Title/Subtitle/md">
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${memberRate.price} `}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{memberRate.unit}</span>
@@ -133,6 +136,7 @@ export default function RegularRateCard({
className={`${styles.rateRow} ${styles.strikeThroughRate}`}
>
<s>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${rate.price} `}
<Typography variant="Tag/sm">
<span>{rate.unit}</span>

View File

@@ -42,6 +42,7 @@ export default function SkeletonShimmer({
}}
>
{/* zero width space, allows for font styles to affect height */}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<span aria-hidden="true">&#8203;</span>
</span>
)

View File

@@ -1,7 +1,7 @@
import { cva, type VariantProps } from 'class-variance-authority'
import TripadvisorIcon from '@scandic-hotels/design-system/Icons/TripadvisorIcon'
import TripadvisorIcon from '../Icons/Customised/Socials/Tripadvisor'
import styles from './tripAdvisorChip.module.css'
import { Typography } from '@scandic-hotels/design-system/Typography'
import { Typography } from '../Typography'
const container = cva(styles.container, {
variants: {

View File

@@ -1,3 +1,4 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */
import copy from 'copy-to-clipboard'
import { kebabify } from '../../generate/utils'

View File

@@ -1,5 +1,9 @@
const config = {
'*.{ts,tsx}': [() => 'tsc -p tsconfig.json --noEmit', 'prettier --write'],
'*.{ts,tsx}': [
() => 'yarn lint',
() => 'tsc -p tsconfig.json --noEmit',
'prettier --write',
],
'*.{json,md}': 'prettier --write',
'*.{html,js,cjs,mjs,css}': 'prettier --write',
}

View File

@@ -133,6 +133,7 @@
"./Map/mapConstants": "./lib/components/Map/mapConstants.ts",
"./Map/Markers/HotelMarkerByType": "./lib/components/Map/Markers/HotelMarkerByType.tsx",
"./Map/Markers/PoiMarker": "./lib/components/Map/Markers/PoiMarker/index.tsx",
"./Map/types": "./lib/components/Map/types.ts",
"./Modal": "./lib/components/Modal/index.tsx",
"./Modal/ModalContentWithActions": "./lib/components/Modal/ModalContentWithActions/index.tsx",
"./NoRateAvailableCard": "./lib/components/RateCard/NoRateAvailable/index.tsx",
@@ -198,6 +199,8 @@
"@scandic-hotels/common": "workspace:*"
},
"peerDependencies": {
"@babel/core": "^7.27.4",
"@hookform/error-message": "^2.0.1",
"@internationalized/date": "^3.8.0",
"@radix-ui/react-slot": "^1.2.2",
"@vis.gl/react-google-maps": "^1.5.2",
@@ -233,6 +236,7 @@
"copy-to-clipboard": "^3.3.3",
"deepmerge-ts": "^7.1.5",
"eslint": "^9",
"eslint-plugin-formatjs": "^5.3.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",

View File

@@ -33,7 +33,7 @@ export default defineConfig([
"no-unused-vars": "off",
"import/no-relative-packages": "error",
"simple-import-sort/imports": [
"error",
"warn",
{
groups: [
["^\\u0000"],

View File

@@ -1,5 +1,9 @@
const config = {
"*.{ts,tsx}": [() => "tsc -p tsconfig.json --noEmit", "prettier --write"],
"*.{ts,tsx}": [
() => "yarn lint",
() => "tsc -p tsconfig.json --noEmit",
"prettier --write",
],
"*.{js,cjs,mjs}": "prettier --write",
}

View File

@@ -1,17 +1,17 @@
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"dev": {
"persistent": true,
"cache": false
},
"lint": {},
"test": {},
"check-types": {}
}
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"dev": {
"persistent": true,
"cache": false
},
"lint": { "dependsOn": [] },
"test": {},
"check-types": {}
}
}

View File

@@ -6192,6 +6192,7 @@ __metadata:
copy-to-clipboard: "npm:^3.3.3"
deepmerge-ts: "npm:^7.1.5"
eslint: "npm:^9"
eslint-plugin-formatjs: "npm:^5.3.1"
eslint-plugin-import: "npm:^2.31.0"
eslint-plugin-react-hooks: "npm:^5.2.0"
eslint-plugin-react-refresh: "npm:^0.4.20"
@@ -6217,6 +6218,8 @@ __metadata:
vitest: "npm:^3.2.4"
vitest-browser-react: "npm:^1.0.1"
peerDependencies:
"@babel/core": ^7.27.4
"@hookform/error-message": ^2.0.1
"@internationalized/date": ^3.8.0
"@radix-ui/react-slot": ^1.2.2
"@vis.gl/react-google-maps": ^1.5.2