From fc866c0e4da176eb386cdc45587626de60fc9d81 Mon Sep 17 00:00:00 2001 From: Anton Gunnarsson Date: Mon, 3 Feb 2025 08:42:16 +0000 Subject: [PATCH] Merged in feat/sw-1493-revised-comparison-block (pull request #1236) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat(SW-1493): Revised SAS comparison block * Base of new TierDetails for SAS tier comparison * Add backgrounds and content to TierDetails * Implement new cms schema for SasTierComparison * Override gap in jsontohtml styling to 0 * Add animations to comparison details * Redesign again * Update content model to new design * Add border to bottom item in tier match list * Wrap interpolate-size in @supports to be safe * Merge branch 'master' into feat/sw-1493-revised-comparison-block Approved-by: Joakim Jäderberg --- .../(standard)/step/enterDetailsTracking.tsx | 2 +- app/globals.css | 4 + components/Blocks/index.tsx | 7 +- .../SelectRate/Rooms/utils.ts | 40 +-- components/JsonToHtml/index.tsx | 5 +- components/SasTierComparison/index.tsx | 253 +++++++++--------- .../sas-tier-comparison.module.css | 205 ++++++++++---- .../Blocks/SasTierComparison.graphql | 28 +- public/_static/img/sas/sas-logotype.svg | 3 + .../schemas/blocks/sasTierComparison.ts | 41 +-- server/routers/hotels/input.ts | 2 +- server/routers/hotels/metrics.ts | 8 +- .../routers/hotels/schemas/additionalData.ts | 53 ++-- .../hotels/schemas/hotel/include/include.ts | 6 +- .../schemas/hotel/include/roomCategories.ts | 12 +- server/routers/hotels/schemas/meetingRoom.ts | 83 +++--- server/routers/hotels/utils.ts | 4 +- types/components/hotelPage/meetingRooms.ts | 4 +- .../hotelPage/sidepeek/amenities.ts | 2 +- .../components/hotelPage/sidepeek/parking.ts | 4 +- .../bookingConfirmation.ts | 2 +- .../enterDetails/breakfast.ts | 6 +- .../selectHotel/selectHotel.ts | 4 +- types/components/hotelReservation/sidePeek.ts | 2 +- types/components/hotelReservation/summary.ts | 4 +- types/transitionTypes/jsontohtml.ts | 1 + types/trpc/routers/booking/confirmation.ts | 10 +- types/trpc/routers/hotel/locations.ts | 6 +- 28 files changed, 450 insertions(+), 351 deletions(-) create mode 100644 public/_static/img/sas/sas-logotype.svg diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/enterDetailsTracking.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/enterDetailsTracking.tsx index 6659c0df2..2868a6f2c 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/enterDetailsTracking.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/step/enterDetailsTracking.tsx @@ -135,7 +135,7 @@ export default function EnterDetailsTracking(props: Props) { roomPrice: roomPrice.perStay.local.price, discount: roomRate.memberRate ? roomRate.publicRate.localPrice.pricePerStay - - roomRate.memberRate.localPrice.pricePerStay + roomRate.memberRate.localPrice.pricePerStay : 0, analyticsrateCode: getAnalyticsRateCode(roomRate.publicRate.rateCode), ancillaries: breakfastAncillary ? [breakfastAncillary] : [], diff --git a/app/globals.css b/app/globals.css index 387dd2989..b602c3835 100644 --- a/app/globals.css +++ b/app/globals.css @@ -129,6 +129,10 @@ --lightbox-z-index: 150; --default-modal-overlay-z-index: 100; --default-modal-z-index: 101; + + @supports (interpolate-size: allow-keywords) { + interpolate-size: allow-keywords; + } } * { diff --git a/components/Blocks/index.tsx b/components/Blocks/index.tsx index 87283a5a9..36a31daaf 100644 --- a/components/Blocks/index.tsx +++ b/components/Blocks/index.tsx @@ -93,12 +93,7 @@ export default function Blocks({ blocks }: BlocksProps) { case BlocksEnums.block.UspGrid: return case BlocksEnums.block.SasTierComparison: - return ( - - ) + return case BlocksEnums.block.FullWidthCampaign: return default: diff --git a/components/HotelReservation/SelectRate/Rooms/utils.ts b/components/HotelReservation/SelectRate/Rooms/utils.ts index 4ff593f1b..5a4c2f62f 100644 --- a/components/HotelReservation/SelectRate/Rooms/utils.ts +++ b/components/HotelReservation/SelectRate/Rooms/utils.ts @@ -63,16 +63,16 @@ export function filterDuplicateRoomTypesByLowestPrice( if ( !previousLowest || currentRequestedPrice < - Math.min( - Number( - previousLowest.products[0].productType.public.requestedPrice - ?.pricePerNight - ) ?? Infinity, - Number( - previousLowest.products[0].productType.member?.requestedPrice - ?.pricePerNight - ) ?? Infinity - ) || + Math.min( + Number( + previousLowest.products[0].productType.public.requestedPrice + ?.pricePerNight + ) ?? Infinity, + Number( + previousLowest.products[0].productType.member?.requestedPrice + ?.pricePerNight + ) ?? Infinity + ) || (currentRequestedPrice === Math.min( Number( @@ -85,16 +85,16 @@ export function filterDuplicateRoomTypesByLowestPrice( ) ?? Infinity ) && currentLocalPrice < - Math.min( - Number( - previousLowest.products[0].productType.public.localPrice - ?.pricePerNight - ) ?? Infinity, - Number( - previousLowest.products[0].productType.member?.localPrice - ?.pricePerNight - ) ?? Infinity - )) + Math.min( + Number( + previousLowest.products[0].productType.public.localPrice + ?.pricePerNight + ) ?? Infinity, + Number( + previousLowest.products[0].productType.member?.localPrice + ?.pricePerNight + ) ?? Infinity + )) ) { roomMap.set(roomType, room) } diff --git a/components/JsonToHtml/index.tsx b/components/JsonToHtml/index.tsx index dc9584aef..ce4ab275b 100644 --- a/components/JsonToHtml/index.tsx +++ b/components/JsonToHtml/index.tsx @@ -1,3 +1,5 @@ +import { cx } from "class-variance-authority" + import { nodesToHtml } from "./utils" import styles from "./jsontohtml.module.css" @@ -8,12 +10,13 @@ export default function JsonToHtml({ embeds, nodes, renderOptions = {}, + className, }: JsonToHtmlProps) { if (!Array.isArray(nodes) || !nodes.length) { return null } return ( -
+
{nodesToHtml(nodes, embeds, renderOptions).filter(Boolean)}
) diff --git a/components/SasTierComparison/index.tsx b/components/SasTierComparison/index.tsx index d08d978d3..3fb1bfb21 100644 --- a/components/SasTierComparison/index.tsx +++ b/components/SasTierComparison/index.tsx @@ -1,163 +1,164 @@ "use client" -import { type Key, useState } from "react" +import Image from "next/image" +import JsonToHtml from "@/components/JsonToHtml" import Link from "@/components/TempDesignSystem/Link" -import Title from "@/components/TempDesignSystem/Text/Title" -import { ArrowRightIcon, CompareArrowsIcon } from "../Icons" +import { ArrowRightIcon, ChevronDownIcon, CompareArrowsIcon } from "../Icons" import SectionContainer from "../Section/Container" -import SectionHeader from "../Section/Header" import Button from "../TempDesignSystem/Button" -import Select from "../TempDesignSystem/Select" +import Body from "../TempDesignSystem/Text/Body" +import Caption from "../TempDesignSystem/Text/Caption" +import Subtitle from "../TempDesignSystem/Text/Subtitle" +import Title from "../TempDesignSystem/Text/Title" import styles from "./sas-tier-comparison.module.css" +import type { ReactNode } from "react" + import type { SasTierComparison } from "@/types/trpc/routers/contentstack/blocks" type SasTierComparisonContent = SasTierComparison["sas_tier_comparison"] type TierComparisonProps = { content: SasTierComparisonContent - firstItem: boolean } -const scandicSasTierMappings: [string[], string[]][] = [ - [["L1", "L2", "L3"], ["Basic"]], - [["L4"], ["Silver"]], - [["L5"], ["Gold"]], - [ - ["L6", "L7"], - ["Diamond", "Pandion"], - ], -] - -export function SasTierComparison({ content, firstItem }: TierComparisonProps) { +export function SasTierComparison({ content }: TierComparisonProps) { const comparisonContent = content.sasTierComparison - const scandic = comparisonContent?.scandic_friends - const sas = comparisonContent?.sas_eb - - const [activeScandicTierCode, setActiveScandicTierCode] = useState( - scandic?.tiers.at(0)?.tier_code ?? "" - ) - const [activeSasTierCode, setActiveSasTierCode] = useState( - sas?.tiers.at(0)?.tier_code ?? "" - ) - - if (!scandic || !sas) return null - - const onChangeScandic = (k: Key) => { - const key = k.toString() - setActiveScandicTierCode(k.toString()) - - const mapping = scandicSasTierMappings.find(([tierMapping]) => - tierMapping.includes(key) - ) - if (!mapping) return - const sasTierCode = mapping[1][0] - setActiveSasTierCode(sasTierCode) - } - - const onChangeSas = (k: Key) => { - const key = k.toString() - setActiveSasTierCode(key) - - const mapping = scandicSasTierMappings.find(([_, tierMapping]) => - tierMapping.includes(key) - ) - if (!mapping) return - const scandicTierCode = mapping[0][0] - setActiveScandicTierCode(scandicTierCode) - } + if (!comparisonContent) return null return (
- + {comparisonContent.title} {comparisonContent.preamble && (

{comparisonContent.preamble}

)}
-
-
-
- - {scandic.title} - - ({ - label: tier.tier_label, - value: tier.tier_code, - }))} - value={activeSasTierCode} - onSelect={onChangeSas} - /> - {sas.read_more_link && ( - - )} -
+
+
+ Scandic logo + SAS logo + {comparisonContent.scandic_column_title} + {comparisonContent.sas_column_title} +
+
+ {comparisonContent.tier_matches.map((tierMatch, i) => ( + + + + ))}
- {comparisonContent.cta && ( -
- -
- )}
+ {comparisonContent.cta?.href && ( + + )} ) } -function ReadMoreLink({ href, title }: { href: string; title: string }) { +type TierMatch = NonNullable< + SasTierComparisonContent["sasTierComparison"] +>["tier_matches"][number] + +function TierDetails({ + children, + tierMatch, +}: { + children: React.ReactNode + tierMatch: TierMatch +}) { return ( - - {title} - +
+ +
+ + {tierMatch.scandic_friends_tier_name} + +
+ +
+
+ + {tierMatch.sas_eb_tier_name} + +
+ +
+
+
+
+
+
+
+ {tierMatch.title} +
+
{children}
+
+ {tierMatch.link?.href && ( + + {tierMatch.link.title} + + )} +
+
+ ) +} + +function ReadMoreLink({ + href, + children, +}: { + href: string + children: ReactNode +}) { + return ( + + {children} + ) } + +function ColumnTitle({ children }: { children?: ReactNode }) { + return ( +
+ + {children} + +
+ ) +} diff --git a/components/SasTierComparison/sas-tier-comparison.module.css b/components/SasTierComparison/sas-tier-comparison.module.css index 8193400d4..01d8c001a 100644 --- a/components/SasTierComparison/sas-tier-comparison.module.css +++ b/components/SasTierComparison/sas-tier-comparison.module.css @@ -1,12 +1,18 @@ .comparisonSection { width: 100%; - gap: var(--Spacing-x4); + gap: var(--Spacing-x6); + background-color: var(--Base-Surface-Primary-light-Normal); + border-radius: var(--Corner-radius-Large); + padding: var(--Spacing-x6) var(--Spacing-x2); } .header { display: flex; flex-direction: column; gap: var(--Spacing-x1); + margin: 0 auto; + align-items: center; + text-align: center; } .preamble { @@ -14,59 +20,164 @@ white-space: pre-wrap; } -.comparisonCard { - background-color: var(--Base-Surface-Subtle-Normal); - padding: var(--Spacing-x4) var(--Spacing-x3); - border-radius: var(--Corner-radius-Large); -} - -.comparisonContainer { - display: flex; - gap: var(--Spacing-x2); -} - -.comparisonBrand { - display: flex; - flex-direction: column; - gap: var(--Spacing-x2); - width: 100%; -} - -.comparisonIcon { - background-color: var(--Base-Surface-Secondary-light-Normal); - border-radius: 50%; - width: 48px; - height: 48px; - flex-shrink: 0; - display: flex; - justify-content: center; - align-items: center; - margin-top: var(--Spacing-x7); -} - -@media screen and (max-width: 767px) { - .comparisonIcon { - display: none; - } - .comparisonContainer { - flex-direction: column; - gap: var(--Spacing-x4); - } -} - .link { display: flex; align-items: center; gap: var(--Spacing-x-half); } -.ctaContainer { - border-top: 1px solid var(--Base-Border-Subtle); +.tierMatchList { display: flex; - justify-content: center; - margin-top: var(--Spacing-x4); + flex-direction: column; } -.ctaLink { - margin-top: var(--Spacing-x4); +.tierDetails { + overflow: hidden; + background-color: var(--Base-Surface-Primary-light-Normal); + transition: background-color 200ms; + transition-delay: 50ms; + border-bottom: 1px solid var(--Base-Border-Subtle); + + &:hover, + &[open] { + background-color: var(--Base-Surface-Primary-light-Hover); + + .comparisonIcon { + background-color: var(--Base-Surface-Primary-light-Normal); + } + } + + &[open] { + .chevron { + transform: rotate(180deg); + } + &::details-content { + block-size: auto; + } + } + + &::details-content { + block-size: 0; + transition: + block-size 0.4s, + content-visibility 0.4s; + transition-behavior: allow-discrete; + } +} + +.iconWrapper { + position: absolute; + right: var(--Spacing-x1); +} +.chevron { + transition: transform 200ms; + flex-shrink: 0; +} + +.tierSummary { + list-style: none; + + &::marker, + &::-webkit-details-marker { + display: none; + } +} + +.columnHeaders { + display: grid; + grid-template-columns: 1fr 1fr; + align-items: center; + row-gap: var(--Spacing-x2); + margin-bottom: var(--Spacing-x2); + place-items: center; +} + +.tierTitles { + cursor: pointer; + padding: var(--Spacing-x-half); + position: relative; + width: 100%; + height: 64px; + align-items: center; + display: grid; + grid-template-columns: 1fr auto 1fr; +} + +.tierTitle { + flex-grow: 1; + text-align: center; + font-weight: 500; + z-index: 1; +} + +.comparisonIcon { + background-color: var(--Base-Surface-Secondary-light-Normal); + border-radius: 50%; + width: 32px; + height: 32px; + flex-shrink: 0; + display: flex; + justify-content: center; + align-items: center; + z-index: 1; + transition: background-color 0.3s; + transition-delay: 50ms; +} + +.tierContent { + padding: var(--Spacing-x3); + display: flex; + flex-direction: column; + gap: var(--Spacing-x2); +} + +.tierInfo { + display: grid; + gap: var(--Spacing-x2); +} + +.htmlContent { + gap: 0; + + & ul { + padding: 0; + } +} + +.columnTitle { + width: 100%; + position: relative; + text-align: center; + + & > span { + position: relative; + padding: 0 var(--Spacing-x2); + background-color: white; + } + + &::before { + position: absolute; + bottom: calc(50% - 1px); + content: ""; + display: block; + height: 1px; + width: 100%; + background-color: var(--Base-Border-Normal); + } +} + +@media (min-width: 768px) { + .tierInfo { + grid-template-columns: 1fr 1fr; + gap: 0; + } + + .ctaButton { + width: fit-content; + margin: 0 auto; + } + + .columnHeaders { + column-gap: var(--Spacing-x3); + } } diff --git a/lib/graphql/Fragments/Blocks/SasTierComparison.graphql b/lib/graphql/Fragments/Blocks/SasTierComparison.graphql index f96f34210..7f8f6a9f6 100644 --- a/lib/graphql/Fragments/Blocks/SasTierComparison.graphql +++ b/lib/graphql/Fragments/Blocks/SasTierComparison.graphql @@ -9,33 +9,23 @@ fragment SasTierComparison_ContentPage on ContentPageBlocksSasTierComparison { ... on SasTierComparison { title preamble - scandic_friends { + scandic_column_title + sas_column_title + tier_matches { title - label - tiers { - tier_code - tier_label + scandic_friends_tier_name + sas_eb_tier_name + content { + json } - read_more_link { - href - title - } - } - sas_eb { - title - label - tiers { - tier_code - tier_label - } - read_more_link { + link { href title } } cta { - href title + href } } } diff --git a/public/_static/img/sas/sas-logotype.svg b/public/_static/img/sas/sas-logotype.svg new file mode 100644 index 000000000..326b5559e --- /dev/null +++ b/public/_static/img/sas/sas-logotype.svg @@ -0,0 +1,3 @@ + + + diff --git a/server/routers/contentstack/schemas/blocks/sasTierComparison.ts b/server/routers/contentstack/schemas/blocks/sasTierComparison.ts index 520419503..f9b22de4a 100644 --- a/server/routers/contentstack/schemas/blocks/sasTierComparison.ts +++ b/server/routers/contentstack/schemas/blocks/sasTierComparison.ts @@ -22,34 +22,19 @@ export const sasTierComparisonSchema = z.object({ node: z.object({ title: z.string(), preamble: z.string().optional(), - scandic_friends: z.object({ - title: z.string(), - label: z.string(), - tiers: z.array( - z.object({ - tier_code: z.nativeEnum(MembershipLevelEnum), - tier_label: z.string(), - }) - ), - read_more_link: link.optional(), - }), - sas_eb: z.object({ - title: z.string(), - label: z.string(), - tiers: z.array( - z.object({ - tier_code: z.enum([ - "Basic", - "Silver", - "Gold", - "Diamond", - "Pandion", - ]), - tier_label: z.string(), - }) - ), - read_more_link: link.optional(), - }), + scandic_column_title: z.string(), + sas_column_title: z.string(), + tier_matches: z.array( + z.object({ + scandic_friends_tier_name: z.string(), + sas_eb_tier_name: z.string(), + title: z.string(), + content: z.object({ + json: z.any(), // json + }), + link: link.optional(), + }) + ), cta: link.optional(), }), }) diff --git a/server/routers/hotels/input.ts b/server/routers/hotels/input.ts index 22252dc80..489d6842b 100644 --- a/server/routers/hotels/input.ts +++ b/server/routers/hotels/input.ts @@ -73,7 +73,7 @@ export const getHotelsInput = z.object({ .nullable(), hotelsToInclude: z.array(z.string()), }) -export interface GetHotelsInput extends z.infer { } +export interface GetHotelsInput extends z.infer {} export const nearbyHotelIdsInput = z.object({ hotelId: z.string(), diff --git a/server/routers/hotels/metrics.ts b/server/routers/hotels/metrics.ts index 85c15a06d..145135ac6 100644 --- a/server/routers/hotels/metrics.ts +++ b/server/routers/hotels/metrics.ts @@ -34,8 +34,12 @@ export const metrics = { }, hotelsByHotelIdAvailability: { counter: meter.createCounter("trpc.hotel.availability.hotels-by-hotel-id"), - fail: meter.createCounter("trpc.hotel.availability.hotels-by-hotel-id-fail"), - success: meter.createCounter("trpc.hotel.availability.hotels-by-hotel-id-success"), + fail: meter.createCounter( + "trpc.hotel.availability.hotels-by-hotel-id-fail" + ), + success: meter.createCounter( + "trpc.hotel.availability.hotels-by-hotel-id-success" + ), }, meetingRooms: { counter: meter.createCounter("trpc.hotels.meetingRooms"), diff --git a/server/routers/hotels/schemas/additionalData.ts b/server/routers/hotels/schemas/additionalData.ts index 86c0d14eb..c1057b74c 100644 --- a/server/routers/hotels/schemas/additionalData.ts +++ b/server/routers/hotels/schemas/additionalData.ts @@ -34,32 +34,31 @@ export const extraPageSchema = z.object({ mainBody: z.string().optional(), }) -export const additionalDataSchema = z - .object({ - attributes: z.object({ - name: z.string(), - id: z.string(), - displayWebPage: z.object({ - healthGym: z.boolean(), - meetingRoom: z.boolean(), - parking: z.boolean(), - specialNeeds: z.boolean(), - }), - specialNeedGroups: z.array(specialNeedGroupSchema), - gallery: gallerySchema.optional(), - conferencesAndMeetings: facilitySchema.optional(), - healthAndWellness: facilitySchema.optional(), - restaurantImages: facilitySchema.optional(), - restaurantsOverviewPage: restaurantsOverviewPageSchema, - meetingRooms: extraPageSchema, - healthAndFitness: extraPageSchema, - hotelParking: extraPageSchema, - hotelSpecialNeeds: extraPageSchema, - accessibilityElevatorPitchText: z.string().optional(), - hotelRoomElevatorPitchText: z.string().optional(), +export const additionalDataSchema = z.object({ + attributes: z.object({ + name: z.string(), + id: z.string(), + displayWebPage: z.object({ + healthGym: z.boolean(), + meetingRoom: z.boolean(), + parking: z.boolean(), + specialNeeds: z.boolean(), }), - type: z.literal("additionalData"), - }) + specialNeedGroups: z.array(specialNeedGroupSchema), + gallery: gallerySchema.optional(), + conferencesAndMeetings: facilitySchema.optional(), + healthAndWellness: facilitySchema.optional(), + restaurantImages: facilitySchema.optional(), + restaurantsOverviewPage: restaurantsOverviewPageSchema, + meetingRooms: extraPageSchema, + healthAndFitness: extraPageSchema, + hotelParking: extraPageSchema, + hotelSpecialNeeds: extraPageSchema, + accessibilityElevatorPitchText: z.string().optional(), + hotelRoomElevatorPitchText: z.string().optional(), + }), + type: z.literal("additionalData"), +}) export function transformAdditionalData( data: z.output @@ -67,6 +66,6 @@ export function transformAdditionalData( return { ...data.attributes, id: data.attributes.id, - type: data.type + type: data.type, } -} \ No newline at end of file +} diff --git a/server/routers/hotels/schemas/hotel/include/include.ts b/server/routers/hotels/schemas/hotel/include/include.ts index 6c5ba45e9..88e5580a0 100644 --- a/server/routers/hotels/schemas/hotel/include/include.ts +++ b/server/routers/hotels/schemas/hotel/include/include.ts @@ -7,7 +7,11 @@ import { roomCategoriesSchema, transformRoomCategories, } from "@/server/routers/hotels/schemas/hotel/include/roomCategories" -import { additionalDataSchema, transformAdditionalData } from "../../additionalData" + +import { + additionalDataSchema, + transformAdditionalData, +} from "../../additionalData" export const includeSchema = z .discriminatedUnion("type", [ diff --git a/server/routers/hotels/schemas/hotel/include/roomCategories.ts b/server/routers/hotels/schemas/hotel/include/roomCategories.ts index 42574835a..a40e3dc8b 100644 --- a/server/routers/hotels/schemas/hotel/include/roomCategories.ts +++ b/server/routers/hotels/schemas/hotel/include/roomCategories.ts @@ -86,12 +86,12 @@ export function transformRoomCategories( totalOccupancy: data.attributes.occupancy.min === data.attributes.occupancy.max ? { - max: data.attributes.occupancy.max, - range: `${data.attributes.occupancy.max}`, - } + max: data.attributes.occupancy.max, + range: `${data.attributes.occupancy.max}`, + } : { - max: data.attributes.occupancy.max, - range: `${data.attributes.occupancy.min}-${data.attributes.occupancy.max}`, - }, + max: data.attributes.occupancy.max, + range: `${data.attributes.occupancy.min}-${data.attributes.occupancy.max}`, + }, } } diff --git a/server/routers/hotels/schemas/meetingRoom.ts b/server/routers/hotels/schemas/meetingRoom.ts index 01b30d316..a08567a6c 100644 --- a/server/routers/hotels/schemas/meetingRoom.ts +++ b/server/routers/hotels/schemas/meetingRoom.ts @@ -2,49 +2,48 @@ import { z } from "zod" import { imageSchema } from "./image" -export const meetingRoomsSchema = z - .object({ - data: z.array( - z.object({ - attributes: z.object({ - name: z.string(), - email: z.string().optional(), - phoneNumber: z.string(), - size: z.number(), - doorWidth: z.number(), - doorHeight: z.number(), - length: z.number(), - width: z.number(), - height: z.number(), - floorNumber: z.number(), - content: z.object({ - images: z.array(imageSchema), - texts: z.object({ - facilityInformation: z.string().optional(), - surroundingInformation: z.string().optional(), - descriptions: z.object({ +export const meetingRoomsSchema = z.object({ + data: z.array( + z.object({ + attributes: z.object({ + name: z.string(), + email: z.string().optional(), + phoneNumber: z.string(), + size: z.number(), + doorWidth: z.number(), + doorHeight: z.number(), + length: z.number(), + width: z.number(), + height: z.number(), + floorNumber: z.number(), + content: z.object({ + images: z.array(imageSchema), + texts: z.object({ + facilityInformation: z.string().optional(), + surroundingInformation: z.string().optional(), + descriptions: z.object({ + short: z.string().optional(), + medium: z.string().optional(), + }), + meetingDescription: z + .object({ short: z.string().optional(), medium: z.string().optional(), - }), - meetingDescription: z - .object({ - short: z.string().optional(), - medium: z.string().optional(), - }) - .optional(), - }), + }) + .optional(), }), - seatings: z.array( - z.object({ - type: z.string(), - capacity: z.number(), - }) - ), - lighting: z.string(), - sortOrder: z.number().optional(), }), - id: z.string(), - type: z.string(), - }) - ), - }) \ No newline at end of file + seatings: z.array( + z.object({ + type: z.string(), + capacity: z.number(), + }) + ), + lighting: z.string(), + sortOrder: z.number().optional(), + }), + id: z.string(), + type: z.string(), + }) + ), +}) diff --git a/server/routers/hotels/utils.ts b/server/routers/hotels/utils.ts index eae6946f6..a75555341 100644 --- a/server/routers/hotels/utils.ts +++ b/server/routers/hotels/utils.ts @@ -3,6 +3,7 @@ import { unstable_cache } from "next/cache" import * as api from "@/lib/api" +import { metrics } from "./metrics" import { citiesByCountrySchema, citiesSchema, @@ -11,6 +12,7 @@ import { locationsSchema, } from "./output" +import type { Country } from "@/types/enums/country" import { PointOfInterestGroupEnum } from "@/types/enums/pointOfInterest" import type { RequestOptionsWithOutBody } from "@/types/fetch" import type { @@ -20,8 +22,6 @@ import type { } from "@/types/trpc/routers/hotel/locations" import type { Lang } from "@/constants/languages" import type { Endpoint } from "@/lib/api/endpoints" -import { Country } from "@/types/enums/country" -import { metrics } from "./metrics" export function getPoiGroupByCategoryName(category: string | undefined) { if (!category) return PointOfInterestGroupEnum.LOCATION diff --git a/types/components/hotelPage/meetingRooms.ts b/types/components/hotelPage/meetingRooms.ts index c73b68a79..2be47b264 100644 --- a/types/components/hotelPage/meetingRooms.ts +++ b/types/components/hotelPage/meetingRooms.ts @@ -1,6 +1,6 @@ -import { meetingRoomsSchema } from "@/server/routers/hotels/schemas/meetingRoom" - import type { z } from "zod" +import type { meetingRoomsSchema } from "@/server/routers/hotels/schemas/meetingRoom" + export type MeetingRoomData = z.output export type MeetingRooms = MeetingRoomData["data"] diff --git a/types/components/hotelPage/sidepeek/amenities.ts b/types/components/hotelPage/sidepeek/amenities.ts index 1f591741e..b090a2e6e 100644 --- a/types/components/hotelPage/sidepeek/amenities.ts +++ b/types/components/hotelPage/sidepeek/amenities.ts @@ -1,5 +1,5 @@ -import type { ParkingAmenityProps } from "./parking" import type { Hotel, Restaurant, RestaurantOpeningHours } from "@/types/hotel" +import type { ParkingAmenityProps } from "./parking" export type AmenitiesSidePeekProps = { amenitiesList: Hotel["detailedFacilities"] diff --git a/types/components/hotelPage/sidepeek/parking.ts b/types/components/hotelPage/sidepeek/parking.ts index 216a48463..49f5f0181 100644 --- a/types/components/hotelPage/sidepeek/parking.ts +++ b/types/components/hotelPage/sidepeek/parking.ts @@ -20,10 +20,10 @@ export interface ParkingListProps | "distanceToHotel" | "numberOfChargingSpaces" | "numberOfParkingSpots" - > { } + > {} export interface ParkingPricesProps extends Pick, - Pick, "currency"> { + Pick, "currency"> { pricing: NonNullable["ordinary"] } diff --git a/types/components/hotelReservation/bookingConfirmation/bookingConfirmation.ts b/types/components/hotelReservation/bookingConfirmation/bookingConfirmation.ts index 88fb770f3..73007a82d 100644 --- a/types/components/hotelReservation/bookingConfirmation/bookingConfirmation.ts +++ b/types/components/hotelReservation/bookingConfirmation/bookingConfirmation.ts @@ -4,4 +4,4 @@ export interface BookingConfirmationProps { confirmationNumber: string } -export interface ConfirmationProps extends BookingConfirmation { } +export interface ConfirmationProps extends BookingConfirmation {} diff --git a/types/components/hotelReservation/enterDetails/breakfast.ts b/types/components/hotelReservation/enterDetails/breakfast.ts index e6e2a4e0f..54f28e021 100644 --- a/types/components/hotelReservation/enterDetails/breakfast.ts +++ b/types/components/hotelReservation/enterDetails/breakfast.ts @@ -5,13 +5,13 @@ import type { breakfastPackagesSchema } from "@/server/routers/hotels/output" import type { breakfastPackageSchema } from "@/server/routers/hotels/schemas/packages" export interface BreakfastFormSchema - extends z.output { } + extends z.output {} export interface BreakfastPackages - extends z.output { } + extends z.output {} export interface BreakfastPackage - extends z.output { } + extends z.output {} export interface BreakfastProps { packages: BreakfastPackages diff --git a/types/components/hotelReservation/selectHotel/selectHotel.ts b/types/components/hotelReservation/selectHotel/selectHotel.ts index 253f64408..f2537cc34 100644 --- a/types/components/hotelReservation/selectHotel/selectHotel.ts +++ b/types/components/hotelReservation/selectHotel/selectHotel.ts @@ -1,9 +1,9 @@ +import type { CheckInData, Hotel, Parking } from "@/types/hotel" +import type { Lang } from "@/constants/languages" import type { AlternativeHotelsSearchParams, SelectHotelSearchParams, } from "./selectHotelSearchParams" -import type { CheckInData, Hotel, Parking } from "@/types/hotel" -import type { Lang } from "@/constants/languages" export enum AvailabilityEnum { Available = "Available", diff --git a/types/components/hotelReservation/sidePeek.ts b/types/components/hotelReservation/sidePeek.ts index 8502d6b23..feba47367 100644 --- a/types/components/hotelReservation/sidePeek.ts +++ b/types/components/hotelReservation/sidePeek.ts @@ -1,4 +1,4 @@ -import { HotelData } from "@/types/hotel" +import type { HotelData } from "@/types/hotel" export enum SidePeekEnum { hotelDetails = "hotel-detail-side-peek", diff --git a/types/components/hotelReservation/summary.ts b/types/components/hotelReservation/summary.ts index 0edd00d72..f0f13bfb1 100644 --- a/types/components/hotelReservation/summary.ts +++ b/types/components/hotelReservation/summary.ts @@ -5,11 +5,11 @@ import type { Price, RoomPrice, } from "@/types/stores/enter-details" +import type { RoomAvailability } from "@/types/trpc/routers/hotel/roomAvailability" import type { BedTypeSchema } from "./enterDetails/bedType" import type { BreakfastPackage } from "./enterDetails/breakfast" import type { DetailsSchema } from "./enterDetails/details" import type { Child, SelectRateSearchParams } from "./selectRate/selectRate" -import type { RoomAvailability } from "@/types/trpc/routers/hotel/roomAvailability" export type RoomsData = Pick & Pick & @@ -21,7 +21,7 @@ export type RoomsData = Pick & export interface SummaryProps extends Pick, - Pick { + Pick { isMember: boolean breakfastIncluded: boolean } diff --git a/types/transitionTypes/jsontohtml.ts b/types/transitionTypes/jsontohtml.ts index ecbb14739..ce92c08d8 100644 --- a/types/transitionTypes/jsontohtml.ts +++ b/types/transitionTypes/jsontohtml.ts @@ -7,6 +7,7 @@ export type JsonToHtmlProps = { embeds: Node[] nodes: RTENode[] renderOptions?: RenderOptions + className?: string } export type EmbedByUid = Record> diff --git a/types/trpc/routers/booking/confirmation.ts b/types/trpc/routers/booking/confirmation.ts index 713842cfe..57acf668b 100644 --- a/types/trpc/routers/booking/confirmation.ts +++ b/types/trpc/routers/booking/confirmation.ts @@ -4,14 +4,14 @@ import type { Hotel, Room } from "@/types/hotel" import type { bookingConfirmationSchema } from "@/server/routers/booking/output" export interface BookingConfirmationSchema - extends z.output { } + extends z.output {} export interface BookingConfirmation { booking: BookingConfirmationSchema hotel: Hotel room: - | (Room & { - bedType: Room["roomTypes"][number] - }) - | null + | (Room & { + bedType: Room["roomTypes"][number] + }) + | null } diff --git a/types/trpc/routers/hotel/locations.ts b/types/trpc/routers/hotel/locations.ts index 30e668777..f679751eb 100644 --- a/types/trpc/routers/hotel/locations.ts +++ b/types/trpc/routers/hotel/locations.ts @@ -6,7 +6,7 @@ import type { locationsSchema, } from "@/server/routers/hotels/output" -export interface LocationSchema extends z.output { } +export interface LocationSchema extends z.output {} export type Locations = LocationSchema["data"] export type Location = Locations[number] @@ -20,7 +20,7 @@ export function isHotelLocation( return location?.type === "hotels" } export interface CitiesByCountry - extends z.output { } + extends z.output {} export type CitiesGroupedByCountry = Record -export interface Countries extends z.output { } +export interface Countries extends z.output {}