Merged develop into feat/hotel-page-tab-navigation

This commit is contained in:
Chuma Mcphoy (We Ahead)
2024-08-13 07:03:40 +00:00
14 changed files with 141 additions and 11 deletions

View File

@@ -42,3 +42,6 @@ OPENSSL_MODULES="/var/lang/lib/ossl-modules"
PUBLIC_URL="http://localhost:3000"
AUTH_URL="$PUBLIC_URL/api/web/auth"
NEXTAUTH_URL="$PUBLIC_URL/api/web/auth"
GOOGLE_STATIC_MAP_KEY=""
GOOGLE_STATIC_MAP_SIGNATURE_SECRET=""

View File

@@ -1,12 +1,19 @@
.main {
display: grid;
grid-template-columns: repeat(3, minmax(min-content, max-content));
grid-template-columns: repeat(2, minmax(min-content, max-content));
gap: var(--Spacing-x4);
padding: var(--Spacing-x4) var(--Spacing-x4) 0 var(--Spacing-x4);
height: 100dvh;
background-color: var(--Scandic-Brand-Warm-White);
}
.section {
.hotelCards {
display: grid;
gap: var(--Spacing-x4);
}
.link {
display: flex;
align-items: center;
padding: var(--Spacing-x2) var(--Spacing-x0);
}

View File

@@ -2,6 +2,10 @@ import { serverClient } from "@/lib/trpc/server"
import HotelCard from "@/components/HotelReservation/HotelCard"
import HotelFilter from "@/components/HotelReservation/SelectHotel/HotelFilter"
import { ChevronRightIcon } from "@/components/Icons"
import StaticMap from "@/components/Maps/StaticMap"
import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n"
import styles from "./page.module.css"
@@ -10,6 +14,8 @@ import { LangParams, PageArgs } from "@/types/params"
export default async function SelectHotelPage({
params,
}: PageArgs<LangParams>) {
const intl = await getIntl()
const { attributes } = await serverClient().hotel.getHotel({
hotelId: "d98c7ab1-ebaa-4102-b351-758daf1ddf55",
language: params.lang,
@@ -20,10 +26,30 @@ export default async function SelectHotelPage({
hotelId: "d98c7ab1-ebaa-4102-b351-758daf1ddf55",
})
const tempSearchTerm = "Stockholm"
return (
<main className={styles.main}>
<HotelFilter filters={hotelFilters} />
<section className={styles.section}>
<section>
<StaticMap
city={tempSearchTerm}
width={340}
height={180}
zoomLevel={11}
mapType="roadmap"
/>
<Link
className={styles.link}
color="burgundy"
variant="underscored"
href="#"
>
{intl.formatMessage({ id: "Show map" })}
<ChevronRightIcon color="burgundy" className={styles.icon} />
</Link>
<HotelFilter filters={hotelFilters} />
</section>
<section className={styles.hotelCards}>
{hotels.map((hotel) => (
<HotelCard key={hotel.name} hotel={hotel} />
))}

View File

@@ -3,6 +3,7 @@
background-color: var(--Base-Surface-Primary-light-Normal);
border: 1px solid var(--Base-Border-Subtle);
border-radius: var(--Corner-radius-Small);
overflow: hidden;
height: 460px;
width: 480px;
}
@@ -11,7 +12,6 @@
height: auto;
max-height: 180px;
object-fit: cover;
overflow: hidden;
width: 100%;
}

View File

@@ -0,0 +1,30 @@
# Google Map Static API
### About
The Google Maps Static API lets you embed a Google Maps image on your web page. The Google Maps Static API service creates your map based on URL parameters sent through a standard HTTP request and returns the map as an image you can display on your web page. Due to regulations from Google we are not allowed to store and serve copies of images generated using the Google Maps Static API. All web pages that require static images must link the src attribute of an HTML img tag or as a background-image using CSS.
### API Key Restrictions
You can restrict your API key on websites, IP addresses, Android apps and iOS apps. For now (12/8-24) the API key is restricted by IP address, hence the request will only work at Scandic HQ network. This will be changed to a referrer website in the future.
[Read more about API key restrictions](https://developers.google.com/maps/api-security-best-practices#restricting-api-keys)
### Digital Signature
Requests exceeding 25,000 requests per day require an API key and a digital signature. However, it is strongly recommended by Google to use both an API key and digital signature, regardless of the usage.
The digital signature is set on the Google Maps Platform. For dynamically generated requests, the signature is handled through server side signing appending the signature as base64 on the request url.
[Read more about digital signature](https://developers.google.com/maps/documentation/maps-static/digital-signature)
### Generating new API keys
Regenerating an API key creates a new key that has all the old key's restrictions. This process also starts a 24-hour timer after which the old API key is deleted. During this time window, both the old and new key are accepted, giving you a chance to migrate your apps to use the new key. However, after this time period elapses, any apps still using the old API key stop working.
**Caution:** Only regenerate an API key if you absolutely must to avoid unauthorized use. This process can shut down legitimate traffic and prevent your apps from functioning properly.
[Read more about regenerating keys](https://developers.google.com/maps/api-security-best-practices#regenerate-apikey)
### Version history
| Description | Version | Date | Author |
| ------------------- | ------- | ------- | ---------------- |
| Create ReadMe file. | 1.0.0 | 12/8-24 | Fredrik Thorsson |

View File

@@ -0,0 +1,46 @@
/* eslint-disable @next/next/no-img-element */
import crypto from "node:crypto"
import { env } from "@/env/server"
import { StaticMapProps } from "@/types/components/maps/staticMap/staticMap"
function removeWebSafe(safeEncodedString: string) {
return safeEncodedString.replace(/-/g, "+").replace(/_/g, "/")
}
function makeWebSafe(encodedString: string) {
return encodedString.replace(/\+/g, "-").replace(/\//g, "_")
}
function decodeBase64Hash(code: string) {
return Buffer.from(code, "base64")
}
function encodeBase64Hash(key: Buffer, data: string) {
return crypto.createHmac("sha1", key).update(data).digest("base64")
}
export default function StaticMap({
city,
width,
height,
zoomLevel,
mapType,
}: StaticMapProps) {
const key = env.GOOGLE_STATIC_MAP_KEY
const secret = env.GOOGLE_STATIC_MAP_SIGNATURE_SECRET
const safeSecret = decodeBase64Hash(removeWebSafe(secret))
const url = new URL(
`https://maps.googleapis.com/maps/api/staticmap?center=${city}&zoom=${zoomLevel}&size=${width}x${height}&maptype=${mapType}&key=${key}`
)
const hashedSignature = makeWebSafe(
encodeBase64Hash(safeSecret, url.pathname + url.search)
)
const src = url.toString() + "&signature=" + hashedSignature
return <img src={src} alt={`Map of ${city} city center`} />
}

5
env/server.ts vendored
View File

@@ -58,6 +58,8 @@ export const env = createEnv({
SEAMLESS_LOGOUT_SV: z.string(),
WEBVIEW_ENCRYPTION_KEY: z.string(),
BOOKING_ENCRYPTION_KEY: z.string(),
GOOGLE_STATIC_MAP_KEY: z.string(),
GOOGLE_STATIC_MAP_SIGNATURE_SECRET: z.string(),
},
emptyStringAsUndefined: true,
runtimeEnv: {
@@ -102,5 +104,8 @@ export const env = createEnv({
SEAMLESS_LOGOUT_SV: process.env.SEAMLESS_LOGOUT_SV,
WEBVIEW_ENCRYPTION_KEY: process.env.WEBVIEW_ENCRYPTION_KEY,
BOOKING_ENCRYPTION_KEY: process.env.BOOKING_ENCRYPTION_KEY,
GOOGLE_STATIC_MAP_KEY: process.env.GOOGLE_STATIC_MAP_KEY,
GOOGLE_STATIC_MAP_SIGNATURE_SECRET:
process.env.GOOGLE_STATIC_MAP_SIGNATURE_SECRET,
},
})

View File

@@ -132,5 +132,6 @@
"Zip code": "Postnummer",
"Room facilities": "Værelsesfaciliteter",
"Hotel facilities": "Hotel faciliteter",
"Hotel surroundings": "Hotel omgivelser"
"Hotel surroundings": "Hotel omgivelser",
"Show map": "Vis kort"
}

View File

@@ -126,5 +126,6 @@
"Zip code": "PLZ",
"Room facilities": "Zimmerausstattung",
"Hotel facilities": "Hotel-Infos",
"Hotel surroundings": "Umgebung des Hotels"
"Hotel surroundings": "Umgebung des Hotels",
"Show map": "Karte anzeigen"
}

View File

@@ -137,5 +137,6 @@
"Zip code": "Zip code",
"Room facilities": "Room facilities",
"Hotel facilities": "Hotel facilities",
"Hotel surroundings": "Hotel surroundings"
"Hotel surroundings": "Hotel surroundings",
"Show map": "Show map"
}

View File

@@ -132,5 +132,6 @@
"Zip code": "Postinumero",
"Room facilities": "Huoneen varustelu",
"Hotel facilities": "Hotellin palvelut",
"Hotel surroundings": "Hotellin ympäristö"
"Hotel surroundings": "Hotellin ympäristö",
"Show map": "Näytä kartta"
}

View File

@@ -132,5 +132,6 @@
"Zip code": "Post kode",
"Room facilities": "Romfasiliteter",
"Hotel facilities": "Hotelfaciliteter",
"Hotel surroundings": "Hotellomgivelser"
"Hotel surroundings": "Hotellomgivelser",
"Show map": "Vis kart"
}

View File

@@ -134,5 +134,6 @@
"Zip code": "Postnummer",
"Room facilities": "Rumlfaciliteter",
"Hotel facilities": "Hotellfaciliteter",
"Hotel surroundings": "Hotellomgivning"
"Hotel surroundings": "Hotellomgivning",
"Show map": "Visa karta"
}

View File

@@ -0,0 +1,7 @@
export type StaticMapProps = {
city: string
width: number
height: number
zoomLevel: number
mapType: "roadmap" | "satellite" | "terrain" | "hybrid"
}