feat(SW-936): add meetings sidepeek

This commit is contained in:
Fredrik Thorsson
2024-11-20 16:40:09 +01:00
parent 65d160d56d
commit f60f490887
10 changed files with 186 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
import { meetingsAndConferences } from "@/constants/routes/hotelPageParams"
import Image from "@/components/Image"
import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link"
import SidePeek from "@/components/TempDesignSystem/SidePeek"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import styles from "./meetingsAndConferences.module.css"
import { MeetingsAndConferencesSidePeekProps } from "@/types/components/hotelPage/sidepeek/meetingsAndConferences"
export default async function MeetingsAndConferencesSidePeek({
meetingFacilities,
}: MeetingsAndConferencesSidePeekProps) {
const lang = getLang()
const intl = await getIntl()
return (
<SidePeek
contentKey={meetingsAndConferences[lang]}
title={intl.formatMessage({ id: "Meetings & Conferences" })}
>
<div className={styles.wrapper}>
<Subtitle color="burgundy" asChild>
<Title level="h3">
{intl.formatMessage({ id: "Creative spaces for meetings" })}
</Title>
</Subtitle>
<div className={styles.information}>
<Image
src=""
alt=""
height={300}
width={200}
className={styles.image}
/>
<Image
src=""
alt=""
height={300}
width={200}
className={styles.image}
/>
<div className={styles.text}>{meetingFacilities?.headingText}</div>
</div>
<div className={styles.buttonContainer}>
<Button fullWidth theme="base" intent="secondary" asChild>
<Link href="" weight="bold" color="burgundy">
{intl.formatMessage({ id: "About meetings & conferences" })}
</Link>
</Button>
</div>
</div>
</SidePeek>
)
}

View File

@@ -0,0 +1,35 @@
.wrapper {
display: flex;
flex-direction: column;
gap: var(--Spacing-x4);
margin-bottom: calc(
var(--Spacing-x4) * 2 + 80px
); /* Creates space between the wrapper and buttonContainer */
}
.information {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: var(--Spacing-x2);
}
.image {
width: 100%;
height: 175px;
object-fit: cover;
}
.text {
grid-column: 1 / 3;
}
.buttonContainer {
background-color: var(--Base-Background-Primary-Normal);
border-top: 1px solid var(--Base-Border-Subtle);
padding: var(--Spacing-x4) var(--Spacing-x2);
width: 100%;
position: absolute;
left: 0;
bottom: 0;
}

View File

@@ -95,6 +95,7 @@
"Could not find requested resource": "Kunne ikke finde den anmodede ressource",
"Country": "Land",
"Country code": "Landekode",
"Creative spaces for meetings": "Kreative rum til møder",
"Credit card": "Kreditkort",
"Credit card deleted successfully": "Kreditkort blev slettet",
"Currency Code": "DKK",

View File

@@ -95,6 +95,7 @@
"Could not find requested resource": "Die angeforderte Ressource konnte nicht gefunden werden.",
"Country": "Land",
"Country code": "Landesvorwahl",
"Creative spaces for meetings": "Kreative Räume für Meetings",
"Credit card": "Kreditkarte",
"Credit card deleted successfully": "Kreditkarte erfolgreich gelöscht",
"Currency Code": "EUR",

View File

@@ -103,6 +103,7 @@
"Could not find requested resource": "Could not find requested resource",
"Country": "Country",
"Country code": "Country code",
"Creative spaces for meetings": "Creative spaces for meetings",
"Credit card": "Credit card",
"Credit card deleted successfully": "Credit card deleted successfully",
"Currency Code": "EUR",

View File

@@ -95,6 +95,7 @@
"Could not find requested resource": "Pyydettyä resurssia ei löytynyt",
"Country": "Maa",
"Country code": "Maatunnus",
"Creative spaces for meetings": "Luovia tiloja kokouksille",
"Credit card": "Luottokortti",
"Credit card deleted successfully": "Luottokortti poistettu onnistuneesti",
"Currency Code": "EUR",

View File

@@ -95,6 +95,7 @@
"Could not find requested resource": "Kunne ikke finne den forespurte ressursen",
"Country": "Land",
"Country code": "Landskode",
"Creative spaces for meetings": "Kreative rom for møter",
"Credit card deleted successfully": "Kredittkort slettet",
"Currency Code": "NOK",
"Current password": "Nåværende passord",

View File

@@ -95,6 +95,7 @@
"Could not find requested resource": "Det gick inte att hitta den begärda resursen",
"Country": "Land",
"Country code": "Landskod",
"Creative spaces for meetings": "Kreativa utrymmen för möten",
"Credit card deleted successfully": "Kreditkort har tagits bort",
"Currency Code": "SEK",
"Current password": "Nuvarande lösenord",

View File

@@ -210,6 +210,87 @@ export const getHotelData = cache(
)
export const hotelQueryRouter = router({
get: contentStackUidWithServiceProcedure.query(async ({ ctx }) => {
const { lang, uid } = ctx
const contentstackData = await getContentstackData(lang, uid)
const hotelId = contentstackData?.hotel_page_id
if (!hotelId) {
throw notFound(`Hotel not found for uid: ${uid}`)
}
const hotelData = await getHotelData(
{
hotelId,
language: ctx.lang,
},
ctx.serviceToken
)
if (!hotelData) {
throw notFound()
}
const included = hotelData.included || []
const hotelAttributes = hotelData.data.attributes
const images = hotelAttributes.gallery?.smallerImages
const hotelAlerts = hotelAttributes.specialAlerts
const roomCategories = included
? included.filter((item) => item.type === "roomcategories")
: []
const activities = contentstackData?.content
? contentstackData?.content[0]
: null
const facilities: Facility[] = [
{
...hotelData.data.attributes.restaurantImages,
id: FacilityCardTypeEnum.restaurant,
headingText:
hotelData?.data.attributes.restaurantImages?.headingText ?? "",
heroImages:
hotelData?.data.attributes.restaurantImages?.heroImages ?? [],
},
{
...hotelData.data.attributes.conferencesAndMeetings,
id: FacilityCardTypeEnum.conference,
headingText:
hotelData?.data.attributes.conferencesAndMeetings?.headingText ?? "",
heroImages:
hotelData?.data.attributes.conferencesAndMeetings?.heroImages ?? [],
},
{
...hotelData.data.attributes.healthAndWellness,
id: FacilityCardTypeEnum.wellness,
headingText:
hotelData?.data.attributes.healthAndWellness?.headingText ?? "",
heroImages:
hotelData?.data.attributes.healthAndWellness?.heroImages ?? [],
},
]
return {
hotelId,
hotelName: hotelAttributes.name,
hotelDescription: hotelAttributes.hotelContent.texts.descriptions.short,
hotelLocation: hotelAttributes.location,
hotelAddress: hotelAttributes.address,
hotelRatings: hotelAttributes.ratings,
hotelDetailedFacilities: hotelAttributes.detailedFacilities,
hotelImages: images,
pointsOfInterest: hotelAttributes.pointsOfInterest,
roomCategories,
activitiesCard: activities?.upcoming_activities_card,
facilities,
alerts: hotelAlerts,
faq: contentstackData?.faq,
healthFacilities: hotelAttributes.healthFacilities,
}
}),
availability: router({
hotels: serviceProcedure
.input(getHotelsAvailabilityInputSchema)

View File

@@ -0,0 +1,5 @@
import type { Hotel } from "@/types/hotel"
export type MeetingsAndConferencesSidePeekProps = {
meetingFacilities: Hotel["conferencesAndMeetings"]
}