From 24bf96df413d592184368e49078478f4fdf2cb58 Mon Sep 17 00:00:00 2001 From: Hrishikesh Vaipurkar Date: Thu, 6 Mar 2025 16:23:16 +0100 Subject: [PATCH] feat: SW-1583 Used constants for strings --- .../hotelreservation/(standard)/utils.ts | 3 ++- .../components/BookingWidget/Client.tsx | 3 ++- .../FormContent/BookingCode/index.tsx | 11 ++++++++-- .../FormContent/RewardNight/index.tsx | 21 ++++++++++++------- .../FormContent/Voucher/index.tsx | 2 +- .../components/Forms/BookingWidget/index.tsx | 5 +++-- .../components/Forms/BookingWidget/schema.ts | 6 ++++-- .../components/GuestsRoomsPicker/Form.tsx | 13 +++++------- .../HotelCard/HotelPointsCard/index.tsx | 2 +- .../HotelReservation/HotelCard/index.tsx | 3 +++ apps/scandic-web/constants/booking.ts | 3 +++ apps/scandic-web/middlewares/bookingFlow.ts | 18 ++++++++-------- 12 files changed, 55 insertions(+), 35 deletions(-) diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts index e38f4c759..78919c291 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts +++ b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts @@ -1,5 +1,6 @@ import { notFound } from "next/navigation" +import { REDEMPTION } from "@/constants/booking" import { getLocations } from "@/lib/trpc/memoizedRequests" import { generateChildrenString } from "@/components/HotelReservation/utils" @@ -106,6 +107,6 @@ export async function getHotelSearchDetails< childrenInRoomString, childrenInRoom, bookingCode: selectHotelParams.bookingCode ?? undefined, - redemption: selectHotelParams.searchType === "redemption", + redemption: selectHotelParams.searchType === REDEMPTION, } } diff --git a/apps/scandic-web/components/BookingWidget/Client.tsx b/apps/scandic-web/components/BookingWidget/Client.tsx index 058d83f94..09cf4d697 100644 --- a/apps/scandic-web/components/BookingWidget/Client.tsx +++ b/apps/scandic-web/components/BookingWidget/Client.tsx @@ -4,6 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod" import { useEffect, useRef, useState } from "react" import { FormProvider, useForm } from "react-hook-form" +import { REDEMPTION } from "@/constants/booking" import { dt } from "@/lib/dt" import { trpc } from "@/lib/trpc/client" import { StickyElementNameEnum } from "@/stores/sticky-position" @@ -102,7 +103,7 @@ export default function BookingWidgetClient({ value: selectedBookingCode, remember: false, }, - redemption: params?.searchType === "redemption", + redemption: params?.searchType === REDEMPTION, rooms: defaultRoomsData, }, shouldFocusError: false, diff --git a/apps/scandic-web/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx b/apps/scandic-web/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx index 31d303851..2c4cc6b51 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx +++ b/apps/scandic-web/components/Forms/BookingWidget/FormContent/BookingCode/index.tsx @@ -4,6 +4,8 @@ import { type FieldError, useFormContext } from "react-hook-form" import { useIntl } from "react-intl" import { useMediaQuery } from "usehooks-ts" +import { REDEMPTION } from "@/constants/booking" + import { ErrorCircleIcon, InfoCircleIcon } from "@/components/Icons" import Modal from "@/components/Modal" import Button from "@/components/TempDesignSystem/Button" @@ -52,9 +54,14 @@ export default function BookingCode() { }) function updateBookingCodeFormValue(value: string) { + // Set value and show error if validation fails setValue("bookingCode.value", value, { shouldValidate: true }) - if (getValues("redemption")) { - setValue("redemption", false) + + if (getValues(REDEMPTION)) { + // Remove the redemption as user types booking code and show notification for the same + setValue(REDEMPTION, false) + // Hide the above notification popup after 5 seconds by re-triggering validation + // This is kept consistent with location search field error notification timeout setTimeout(function () { trigger("bookingCode.value") }, 5000) diff --git a/apps/scandic-web/components/Forms/BookingWidget/FormContent/RewardNight/index.tsx b/apps/scandic-web/components/Forms/BookingWidget/FormContent/RewardNight/index.tsx index cff1a111f..904a3e9c1 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/FormContent/RewardNight/index.tsx +++ b/apps/scandic-web/components/Forms/BookingWidget/FormContent/RewardNight/index.tsx @@ -4,6 +4,8 @@ import { useCallback, useEffect, useRef } from "react" import { useFormContext } from "react-hook-form" import { useIntl } from "react-intl" +import { REDEMPTION } from "@/constants/booking" + import { ErrorCircleIcon } from "@/components/Icons" import Checkbox from "@/components/TempDesignSystem/Form/Checkbox" import Body from "@/components/TempDesignSystem/Text/Body" @@ -13,7 +15,7 @@ import styles from "./reward-night.module.css" import type { BookingWidgetSchema } from "@/types/components/bookingWidget" -export function RewardNight() { +export default function RewardNight() { const intl = useIntl() const { setValue, @@ -23,24 +25,27 @@ export function RewardNight() { } = useFormContext() const ref = useRef(null) const reward = intl.formatMessage({ id: "Book Reward Night" }) - const redemptionErr = errors["redemption"] + const redemptionErr = errors[REDEMPTION] const bookingCode = getValues("bookingCode.value") const isMultiRoomError = redemptionErr?.message?.indexOf("Multi-room") === 0 const errorInfoColor = isMultiRoomError ? "red" : "blue" - function validateBookingWidget(value: boolean) { - trigger("redemption") + function validateRedemption(value: boolean) { + // Validate redemption as per the rules defined in the schema + trigger(REDEMPTION) if (value && bookingCode) { setValue("bookingCode.value", "", { shouldValidate: true }) + // Hide the notification popup after 5 seconds by re-triggering validation + // This is kept consistent with location search field error notification timeout setTimeout(() => { - trigger("redemption") + trigger(REDEMPTION) }, 5000) } } const resetOnMultiroomError = useCallback(() => { if (isMultiRoomError) { - setValue("redemption", false, { shouldValidate: true }) + setValue(REDEMPTION, false, { shouldValidate: true }) } }, [isMultiRoomError, setValue]) @@ -68,10 +73,10 @@ export function RewardNight() {
closeOnBlur(e.nativeEvent)}> { - validateBookingWidget(e.target.value) + validateRedemption(e.target.value) }, }} > diff --git a/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx b/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx index d7088e525..cd90bccfc 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx +++ b/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx @@ -10,7 +10,7 @@ import Caption from "@/components/TempDesignSystem/Text/Caption" import { Tooltip } from "@/components/TempDesignSystem/Tooltip" import BookingCode from "../BookingCode" -import { RewardNight } from "../RewardNight" +import RewardNight from "../RewardNight" import styles from "./voucher.module.css" diff --git a/apps/scandic-web/components/Forms/BookingWidget/index.tsx b/apps/scandic-web/components/Forms/BookingWidget/index.tsx index 40ca7578a..28a52f2ac 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/index.tsx +++ b/apps/scandic-web/components/Forms/BookingWidget/index.tsx @@ -4,6 +4,7 @@ import { useTransition } from "react" import { Form as FormRAC } from "react-aria-components" import { useFormContext } from "react-hook-form" +import { REDEMPTION } from "@/constants/booking" import { selectHotel, selectRate } from "@/constants/routes/hotelReservation" import useLang from "@/hooks/useLang" @@ -49,8 +50,8 @@ export default function Form({ ...(data.bookingCode?.value ? { bookingCode: data.bookingCode.value } : {}), - // Followed current url structure to keep searchType=redemption param incase of reward night - ...(data.redemption ? { searchType: "redemption" } : {}), + // Followed current url structure to keep searchtype=redemption param incase of reward night + ...(data.redemption ? { searchType: REDEMPTION } : {}), }) onClose() diff --git a/apps/scandic-web/components/Forms/BookingWidget/schema.ts b/apps/scandic-web/components/Forms/BookingWidget/schema.ts index 716ee1c3f..40b760b48 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/schema.ts +++ b/apps/scandic-web/components/Forms/BookingWidget/schema.ts @@ -1,5 +1,7 @@ import { z } from "zod" +import { REDEMPTION } from "@/constants/booking" + import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" import type { Location } from "@/types/trpc/routers/hotel/locations" @@ -133,7 +135,7 @@ export const bookingWidgetSchema = z ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Multi-room booking is not available with reward night.", - path: ["redemption"], + path: [REDEMPTION], }) ctx.addIssue({ code: z.ZodIssueCode.custom, @@ -145,7 +147,7 @@ export const bookingWidgetSchema = z ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Code and voucher is not available with reward night.", - path: ["redemption"], + path: [REDEMPTION], }) ctx.addIssue({ code: z.ZodIssueCode.custom, diff --git a/apps/scandic-web/components/GuestsRoomsPicker/Form.tsx b/apps/scandic-web/components/GuestsRoomsPicker/Form.tsx index a9178d3d1..72927560e 100644 --- a/apps/scandic-web/components/GuestsRoomsPicker/Form.tsx +++ b/apps/scandic-web/components/GuestsRoomsPicker/Form.tsx @@ -4,14 +4,11 @@ import { useCallback, useEffect } from "react" import { useFormContext, useWatch } from "react-hook-form" import { useIntl } from "react-intl" -import { - CloseLargeIcon, - ErrorCircleIcon, - PlusCircleIcon, - PlusIcon, -} from "../Icons" +import { REDEMPTION } from "@/constants/booking" + +import { CloseLargeIcon, PlusCircleIcon, PlusIcon } from "../Icons" + import Button from "../TempDesignSystem/Button" -import Caption from "../TempDesignSystem/Text/Caption" import { Tooltip } from "../TempDesignSystem/Tooltip" import { GuestsRoom } from "./GuestsRoom" @@ -38,7 +35,7 @@ export default function GuestsRoomsPickerDialog({ const addRoomLabel = intl.formatMessage({ id: "Add room" }) const doneLabel = intl.formatMessage({ id: "Done" }) // Disable add room if booking code is either voucher or corporate cheque, or reward night is enabled - const addRoomDisabledTextForSpecialRate = getValues("redemption") + const addRoomDisabledTextForSpecialRate = getValues(REDEMPTION) ? intl.formatMessage({ id: "Multi-room booking is not available with reward night.", }) diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsCard/index.tsx b/apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsCard/index.tsx index 55ab4d4a1..b07ec2402 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsCard/index.tsx +++ b/apps/scandic-web/components/HotelReservation/HotelCard/HotelPointsCard/index.tsx @@ -13,7 +13,7 @@ export default function HotelPointsCard({ }: PointsCardProps) { const intl = useIntl() const pointsPerStay = - productTypePoints?.localPrice.pricePerStay ?? redemptionPrice + productTypePoints?.localPrice.pointsPerStay ?? redemptionPrice return (
diff --git a/apps/scandic-web/components/HotelReservation/HotelCard/index.tsx b/apps/scandic-web/components/HotelReservation/HotelCard/index.tsx index b7eada1ce..b088911cb 100644 --- a/apps/scandic-web/components/HotelReservation/HotelCard/index.tsx +++ b/apps/scandic-web/components/HotelReservation/HotelCard/index.tsx @@ -190,10 +190,13 @@ function HotelCard({ {intl.formatMessage({ id: "Available rates" })} + {/* Display rate with full points option */} + {/* Display rate with partial points option A */} {price.redemptionA && ( )} + {/* Display rate with partial points option B */} {price.redemptionB && ( )} diff --git a/apps/scandic-web/constants/booking.ts b/apps/scandic-web/constants/booking.ts index 202a52985..c78b49e8d 100644 --- a/apps/scandic-web/constants/booking.ts +++ b/apps/scandic-web/constants/booking.ts @@ -35,6 +35,9 @@ export enum ChildBedTypeEnum { Unknown = "Unknown", } +export const REDEMPTION = "redemption" +export const SEARCHTYPE = "searchtype" + export const BOOKING_CONFIRMATION_NUMBER = "confirmationNumber" export const MEMBERSHIP_FAILED_ERROR = "MembershipFailedError" diff --git a/apps/scandic-web/middlewares/bookingFlow.ts b/apps/scandic-web/middlewares/bookingFlow.ts index b11276d69..c48ef5ac0 100644 --- a/apps/scandic-web/middlewares/bookingFlow.ts +++ b/apps/scandic-web/middlewares/bookingFlow.ts @@ -1,20 +1,20 @@ -import { NextResponse } from "next/server" +import { type NextMiddleware,NextResponse } from "next/server" + +import { REDEMPTION, SEARCHTYPE } from "@/constants/booking" +import { login } from "@/constants/routes/handleAuth" +import { getPublicNextURL } from "@/server/utils" + +import { auth } from "@/auth" +import { findLang } from "@/utils/languages" import { getDefaultRequestHeaders } from "./utils" -import type { NextMiddleware } from "next/server" - import type { MiddlewareMatcher } from "@/types/middleware" -import { auth } from "@/auth" -import { getPublicNextURL } from "@/server/utils" -import { login } from "@/constants/routes/handleAuth" -import { findLang } from "@/utils/languages" export const middleware: NextMiddleware = async (request) => { // Redirect user to login if reward nights search and not logged in const isRedemption = - request.nextUrl.searchParams.get("searchtype") === "redemption" || - request.nextUrl.searchParams.get("searchType") === "redemption" + request.nextUrl.searchParams.get(SEARCHTYPE) === REDEMPTION const session = await auth() // Check for user session if (isRedemption && (!session || session?.error)) { const lang = findLang(request.nextUrl.pathname)!