diff --git a/apps/scandic-web/app/api/hoteldata/route.ts b/apps/scandic-web/app/api/hoteldata/route.ts
index 9173ec111..bee05be25 100644
--- a/apps/scandic-web/app/api/hoteldata/route.ts
+++ b/apps/scandic-web/app/api/hoteldata/route.ts
@@ -27,7 +27,7 @@ export async function GET(request: NextRequest) {
}
const caller = await serverClient()
- const hotels = await caller.hotel.hotels.getDestinationsMapData({
+ const hotels = await caller.hotel.hotels.getAllHotelData({
lang: parsedLang.data,
warmup: true,
})
diff --git a/apps/scandic-web/components/Blocks/DynamicContent/RewardNights/index.tsx b/apps/scandic-web/components/Blocks/DynamicContent/RewardNights/index.tsx
new file mode 100644
index 000000000..b755b6d7d
--- /dev/null
+++ b/apps/scandic-web/components/Blocks/DynamicContent/RewardNights/index.tsx
@@ -0,0 +1,122 @@
+import { cx } from "class-variance-authority"
+
+import Table from "@scandic-hotels/design-system/Table"
+import { TextLink } from "@scandic-hotels/design-system/TextLink"
+import { Typography } from "@scandic-hotels/design-system/Typography"
+
+import { getAllHotelData } from "@/lib/trpc/memoizedRequests"
+
+import { getIntl } from "@/i18n"
+
+import styles from "./rewardNights.module.css"
+
+export async function RewardNights() {
+ const intl = await getIntl()
+ const hotelData = await getAllHotelData()
+
+ return (
+
+
+
+
+ {intl.formatMessage({
+ id: "rewardNights.table.hotel",
+ defaultMessage: "Hotel",
+ })}
+
+
+ {intl.formatMessage({
+ id: "rewardNights.table.destination",
+ defaultMessage: "Destination",
+ })}
+
+
+ {intl.formatMessage({
+ id: "common.points",
+ defaultMessage: "Points",
+ })}
+
+
+
+
+ {hotelData.map((data) => {
+ const { hotel } = data
+ const hasCampaign = hotel.rewardNight.campaign.points
+ return (
+
+
+ {hotel.name}
+
+
+ {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
+ {`${hotel.address.city}, ${hotel.address.country}`}
+ {hasCampaign ? (
+
+ ) : null}
+
+
+
+ {formatPoints(hotel.rewardNight.points)}
+ {hasCampaign ? (
+
+
+ {formatPoints(hotel.rewardNight.campaign.points)}
+
+
+ ) : null}
+
+
+
+ )
+ })}
+
+
+ )
+}
+interface OfferPriceProps {
+ points: number
+ start: string
+ end: string
+}
+async function OfferPrice(offer: OfferPriceProps) {
+ const intl = await getIntl()
+
+ return (
+
+
+
+ {intl.formatMessage({
+ id: "rewardNights.offerPrice",
+ defaultMessage: "Offer price",
+ })}
+
+
+
+
+ {intl.formatMessage({
+ id: "rewardNights.stayBetween:",
+ defaultMessage: "Stay between:",
+ })}
+
+
+
+
+
+
+ )
+}
+
+function formatPoints(number: number) {
+ const format = new Intl.NumberFormat("fr-FR")
+ return format.format(number).replace(/\u202F/g, " ")
+}
+
+function formatDate(date: string) {
+ return new Date(date).toISOString().split("T")[0]
+}
diff --git a/apps/scandic-web/components/Blocks/DynamicContent/RewardNights/rewardNights.module.css b/apps/scandic-web/components/Blocks/DynamicContent/RewardNights/rewardNights.module.css
new file mode 100644
index 000000000..14273ea70
--- /dev/null
+++ b/apps/scandic-web/components/Blocks/DynamicContent/RewardNights/rewardNights.module.css
@@ -0,0 +1,13 @@
+.offerPrice {
+ display: grid;
+ gap: var(--Space-x05);
+}
+
+.highlightedText {
+ color: var(--Text-Interactive-Secondary);
+ padding-top: var(--Space-x2);
+}
+
+.grid {
+ display: grid;
+}
diff --git a/apps/scandic-web/components/Blocks/DynamicContent/index.tsx b/apps/scandic-web/components/Blocks/DynamicContent/index.tsx
index 049ffb3a8..f49371c8f 100644
--- a/apps/scandic-web/components/Blocks/DynamicContent/index.tsx
+++ b/apps/scandic-web/components/Blocks/DynamicContent/index.tsx
@@ -28,6 +28,7 @@ import { SJWidget } from "@/components/SJWidget"
import JobylonFeed from "./JobylonFeed"
import type { DynamicContentProps } from "@/types/components/blocks/dynamicContent"
+import { RewardNights } from "./RewardNights"
export default function DynamicContent(props: DynamicContentProps) {
return (
@@ -91,6 +92,8 @@ function DynamicContentBlocks(props: DynamicContentProps) {
case DynamicContentEnum.Blocks.components.sj_widget:
return
+ case DynamicContentEnum.Blocks.components.reward_nights:
+ return
default:
return null
}
diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx
index 4d3d3e0f0..16ab49cf1 100644
--- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx
+++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationOverviewPage/OverviewMapContainer/index.tsx
@@ -1,5 +1,5 @@
import { env } from "@/env/server"
-import { getDestinationsMapData } from "@/lib/trpc/memoizedRequests"
+import { getAllHotelData } from "@/lib/trpc/memoizedRequests"
import DynamicMap from "../../Map/DynamicMap"
import MapContent from "../../Map/MapContent"
@@ -8,7 +8,7 @@ import { getHotelMapMarkers, mapMarkerDataToGeoJson } from "../../Map/utils"
import ActiveMapCard from "./ActiveMapCard"
export default async function OverviewMapContainer() {
- const hotelData = await getDestinationsMapData()
+ const hotelData = await getAllHotelData()
if (!hotelData) {
return null
diff --git a/apps/scandic-web/lib/trpc/memoizedRequests/index.ts b/apps/scandic-web/lib/trpc/memoizedRequests/index.ts
index d4fc6b7b1..1a77b3ec2 100644
--- a/apps/scandic-web/lib/trpc/memoizedRequests/index.ts
+++ b/apps/scandic-web/lib/trpc/memoizedRequests/index.ts
@@ -203,12 +203,10 @@ export const getHotelsByCityIdentifier = cache(
})
}
)
-export const getDestinationsMapData = cache(
- async function getMemoizedDestinationsMapData() {
- const caller = await serverClient()
- return caller.hotel.hotels.getDestinationsMapData()
- }
-)
+export const getAllHotelData = cache(async function getMemoizedAllHotelData() {
+ const caller = await serverClient()
+ return caller.hotel.hotels.getAllHotelData()
+})
export const getDestinationCityPage = cache(
async function getMemoizedDestinationCityPage() {
const caller = await serverClient()
diff --git a/apps/scandic-web/services/warmup/warmupHotelData.ts b/apps/scandic-web/services/warmup/warmupHotelData.ts
index 1972d54f8..c625e9ff2 100644
--- a/apps/scandic-web/services/warmup/warmupHotelData.ts
+++ b/apps/scandic-web/services/warmup/warmupHotelData.ts
@@ -16,7 +16,7 @@ export const warmupHotelData =
try {
const caller = await serverClient()
- await caller.hotel.hotels.getDestinationsMapData({
+ await caller.hotel.hotels.getAllHotelData({
lang,
warmup: true,
})
diff --git a/packages/trpc/lib/routers/contentstack/schemas/blocks/table.ts b/packages/trpc/lib/routers/contentstack/schemas/blocks/table.ts
index de256fed8..02c88b418 100644
--- a/packages/trpc/lib/routers/contentstack/schemas/blocks/table.ts
+++ b/packages/trpc/lib/routers/contentstack/schemas/blocks/table.ts
@@ -24,7 +24,7 @@ export const tableSchema = z.object({
),
data: z.array(z.object({}).catchall(z.string())),
skipReset: z.boolean(),
- tableActionEnabled: z.boolean(),
+ tableActionEnabled: z.boolean().optional().default(false),
headerRowAdded: z.boolean().optional().default(false),
}),
}),
diff --git a/packages/trpc/lib/routers/hotels/output.ts b/packages/trpc/lib/routers/hotels/output.ts
index 14f025e42..71a48859e 100644
--- a/packages/trpc/lib/routers/hotels/output.ts
+++ b/packages/trpc/lib/routers/hotels/output.ts
@@ -26,6 +26,7 @@ import {
import { addressSchema } from "./schemas/hotel/address"
import { detailedFacilitiesSchema } from "./schemas/hotel/detailedFacility"
import { locationSchema } from "./schemas/hotel/location"
+import { rewardNightSchema } from "./schemas/hotel/rewardNight"
import { imageSchema } from "./schemas/image"
import { relationshipsSchema } from "./schemas/relationships"
import { roomConfigurationSchema } from "./schemas/roomAvailability/configuration"
@@ -600,6 +601,7 @@ export const hotelListingHotelDataSchema = z.object({
hotelType: z.string(),
type: z.literal("hotels"), // No enum here but the standard return appears to be "hotels".
description: z.string().nullable(),
+ rewardNight: rewardNightSchema,
}),
url: z.string().nullable(),
meetingUrl: z.string().nullable(),
diff --git a/packages/trpc/lib/routers/hotels/query.ts b/packages/trpc/lib/routers/hotels/query.ts
index 896bc06de..f11e801c1 100644
--- a/packages/trpc/lib/routers/hotels/query.ts
+++ b/packages/trpc/lib/routers/hotels/query.ts
@@ -229,7 +229,7 @@ export const hotelQueryRouter = router({
return hotels
}),
}),
- getDestinationsMapData: serviceProcedure
+ getAllHotelData: serviceProcedure
.input(getDestinationsMapDataInput)
.query(async function ({ input, ctx }) {
const lang = input?.lang ?? ctx.lang
diff --git a/packages/trpc/lib/routers/hotels/services/getHotelsByHotelIds.ts b/packages/trpc/lib/routers/hotels/services/getHotelsByHotelIds.ts
index c684dd668..e0110064f 100644
--- a/packages/trpc/lib/routers/hotels/services/getHotelsByHotelIds.ts
+++ b/packages/trpc/lib/routers/hotels/services/getHotelsByHotelIds.ts
@@ -94,6 +94,7 @@ export async function getHotelsByHotelIds({
address: hotel.address,
cityIdentifier: cities[0]?.cityIdentifier || null,
description: content.description || null,
+ rewardNight: hotel.rewardNight,
},
url: content.url,
meetingUrl: additionalData.meetingRooms.meetingOnlineLink || null,
diff --git a/packages/trpc/lib/types/dynamicContent.ts b/packages/trpc/lib/types/dynamicContent.ts
index 01cb3e076..075035c1a 100644
--- a/packages/trpc/lib/types/dynamicContent.ts
+++ b/packages/trpc/lib/types/dynamicContent.ts
@@ -29,6 +29,7 @@ export namespace DynamicContentEnum {
sas_tier_comparison: "sas_tier_comparison",
manage_cookie_consent: "manage_cookie_consent",
sj_widget: "sj_widget",
+ reward_nights: "reward_nights",
unknown: "unknown",
} as const