Merged in feat/BOOK-434-users-should-redirect-to- (pull request #3154)
* feat(BOOK-434): Moved redirect to middleware layer * feat(BOOK-434): Updated to handle no filters available scenario Approved-by: Erik Tiekstra
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { notFound, redirect } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
import { Suspense } from "react"
|
import { Suspense } from "react"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -69,11 +69,6 @@ export default async function DestinationCityPage({
|
|||||||
|
|
||||||
const activeSeoFilter = getActiveSeoFilter(seo_filters, filterFromUrl)
|
const activeSeoFilter = getActiveSeoFilter(seo_filters, filterFromUrl)
|
||||||
|
|
||||||
if (filterFromUrl && !activeSeoFilter) {
|
|
||||||
const updatedPathname = pathname.replace(`/${filterFromUrl}`, "")
|
|
||||||
return redirect(`${updatedPathname}${isMapView ? "?view=map" : ""}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const allHotels = await getHotelsByCityIdentifier(cityIdentifier)
|
const allHotels = await getHotelsByCityIdentifier(cityIdentifier)
|
||||||
const hotelFilters = getFiltersFromHotels(allHotels, lang)
|
const hotelFilters = getFiltersFromHotels(allHotels, lang)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { notFound, redirect } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
import { Suspense } from "react"
|
import { Suspense } from "react"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -70,11 +70,6 @@ export default async function DestinationCountryPage({
|
|||||||
|
|
||||||
const activeSeoFilter = getActiveSeoFilter(seo_filters, filterFromUrl)
|
const activeSeoFilter = getActiveSeoFilter(seo_filters, filterFromUrl)
|
||||||
|
|
||||||
if (filterFromUrl && !activeSeoFilter) {
|
|
||||||
const updatedPathname = pathname.replace(`/${filterFromUrl}`, "")
|
|
||||||
return redirect(`${updatedPathname}${isMapView ? "?view=map" : ""}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const [allHotels, allCities] = await Promise.all([
|
const [allHotels, allCities] = await Promise.all([
|
||||||
getHotelsByCountry(destination_settings.country),
|
getHotelsByCountry(destination_settings.country),
|
||||||
getDestinationCityPagesByCountry(destination_settings.country),
|
getDestinationCityPagesByCountry(destination_settings.country),
|
||||||
|
|||||||
@@ -40,8 +40,11 @@ export const middleware: NextMiddleware = async (request) => {
|
|||||||
if (incomingPathNameParts.length >= 2) {
|
if (incomingPathNameParts.length >= 2) {
|
||||||
const subpage = incomingPathNameParts.pop()
|
const subpage = incomingPathNameParts.pop()
|
||||||
if (subpage) {
|
if (subpage) {
|
||||||
const { contentType: parentContentType, uid: parentUid } =
|
const {
|
||||||
await getUidAndContentTypeByPath(incomingPathNameParts.join("/"))
|
contentType: parentContentType,
|
||||||
|
seoFilters,
|
||||||
|
uid: parentUid,
|
||||||
|
} = await getUidAndContentTypeByPath(incomingPathNameParts.join("/"))
|
||||||
|
|
||||||
if (parentUid) {
|
if (parentUid) {
|
||||||
switch (parentContentType) {
|
switch (parentContentType) {
|
||||||
@@ -53,8 +56,18 @@ export const middleware: NextMiddleware = async (request) => {
|
|||||||
break
|
break
|
||||||
case PageContentTypeEnum.destinationCityPage:
|
case PageContentTypeEnum.destinationCityPage:
|
||||||
case PageContentTypeEnum.destinationCountryPage:
|
case PageContentTypeEnum.destinationCountryPage:
|
||||||
// E.g. Active filters inside destination pages to filter hotels.
|
// Validate Seo Filters from CMS and redirect if not found
|
||||||
|
if (!seoFilters?.includes(subpage)) {
|
||||||
|
return NextResponse.redirect(
|
||||||
|
new URL(incomingPathNameParts.join("/"), nextUrl),
|
||||||
|
{
|
||||||
|
status: 301,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// E.g. Active Seo filters inside destination pages to filter hotels.
|
||||||
searchParams.set("filterFromUrl", subpage)
|
searchParams.set("filterFromUrl", subpage)
|
||||||
|
|
||||||
contentType = parentContentType
|
contentType = parentContentType
|
||||||
uid = parentUid
|
uid = parentUid
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -69,6 +69,17 @@ export const EntryByUrlBatch2 = gql`
|
|||||||
}
|
}
|
||||||
all_destination_country_page(where: { url: $url }, locale: $locale) {
|
all_destination_country_page(where: { url: $url }, locale: $locale) {
|
||||||
items {
|
items {
|
||||||
|
seo_filters {
|
||||||
|
filterConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
... on HotelFilter {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
system {
|
system {
|
||||||
...System
|
...System
|
||||||
}
|
}
|
||||||
@@ -77,6 +88,17 @@ export const EntryByUrlBatch2 = gql`
|
|||||||
}
|
}
|
||||||
all_destination_city_page(where: { url: $url }, locale: $locale) {
|
all_destination_city_page(where: { url: $url }, locale: $locale) {
|
||||||
items {
|
items {
|
||||||
|
seo_filters {
|
||||||
|
filterConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
... on HotelFilter {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
system {
|
system {
|
||||||
...System
|
...System
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ export const getUidAndContentTypeByPath = async (pathname: string) => {
|
|||||||
|
|
||||||
const contentTypePathName = pathWithoutTrailingSlash.replace(`/${lang}`, "")
|
const contentTypePathName = pathWithoutTrailingSlash.replace(`/${lang}`, "")
|
||||||
|
|
||||||
const { contentType, uid, error } = await resolveEntry(
|
const { contentType, seoFilters, uid, error } = await resolveEntry(
|
||||||
contentTypePathName,
|
contentTypePathName,
|
||||||
lang ?? Lang.en
|
lang ?? Lang.en
|
||||||
)
|
)
|
||||||
|
|
||||||
return { contentType, uid, error }
|
return { contentType, seoFilters, uid, error }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,37 @@
|
|||||||
import z from "zod"
|
import z from "zod"
|
||||||
|
|
||||||
|
const baseResolveSchema = z.object({
|
||||||
|
system: z.object({
|
||||||
|
content_type_uid: z.string(),
|
||||||
|
uid: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
const entryResolveSchema = z.object({
|
const entryResolveSchema = z.object({
|
||||||
|
items: z.array(baseResolveSchema),
|
||||||
|
total: z.number(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const allDestinationPageResolveSchema = z.object({
|
||||||
items: z.array(
|
items: z.array(
|
||||||
z.object({
|
baseResolveSchema.extend({
|
||||||
system: z.object({
|
seo_filters: z
|
||||||
content_type_uid: z.string(),
|
.array(
|
||||||
uid: z.string(),
|
z.object({
|
||||||
}),
|
filterConnection: z.object({
|
||||||
|
edges: z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
node: z.object({
|
||||||
|
slug: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.nullish(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.nullish(),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
total: z.number(),
|
total: z.number(),
|
||||||
@@ -22,8 +47,8 @@ export const validateEntryResolveSchema = z.object({
|
|||||||
all_current_blocks_page: entryResolveSchema,
|
all_current_blocks_page: entryResolveSchema,
|
||||||
all_hotel_page: entryResolveSchema,
|
all_hotel_page: entryResolveSchema,
|
||||||
all_destination_overview_page: entryResolveSchema,
|
all_destination_overview_page: entryResolveSchema,
|
||||||
all_destination_country_page: entryResolveSchema,
|
all_destination_country_page: allDestinationPageResolveSchema,
|
||||||
all_destination_city_page: entryResolveSchema,
|
all_destination_city_page: allDestinationPageResolveSchema,
|
||||||
all_start_page: entryResolveSchema,
|
all_start_page: entryResolveSchema,
|
||||||
all_promo_campaign_page: entryResolveSchema,
|
all_promo_campaign_page: entryResolveSchema,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -54,6 +54,17 @@ export async function resolve(url: string, lang = Lang.en) {
|
|||||||
for (const value of Object.values(validatedData.data)) {
|
for (const value of Object.values(validatedData.data)) {
|
||||||
if (value.total) {
|
if (value.total) {
|
||||||
const { content_type_uid, uid } = value.items[0].system
|
const { content_type_uid, uid } = value.items[0].system
|
||||||
|
const seoFilters =
|
||||||
|
"seo_filters" in value.items[0] ? value.items[0].seo_filters : null
|
||||||
|
if (seoFilters && seoFilters.length > 0) {
|
||||||
|
return {
|
||||||
|
contentType: content_type_uid,
|
||||||
|
uid,
|
||||||
|
seoFilters: seoFilters.flatMap((f) =>
|
||||||
|
f.filterConnection.edges?.flatMap((e) => e.node.slug)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
contentType: content_type_uid,
|
contentType: content_type_uid,
|
||||||
uid,
|
uid,
|
||||||
|
|||||||
Reference in New Issue
Block a user