Merged in fix/SW-742 (pull request #801)

fix: prevent phone input from running validation on mount when empty

Approved-by: Christel Westerberg
This commit is contained in:
Simon.Emanuelsson
2024-11-01 08:16:25 +00:00
8 changed files with 56 additions and 35 deletions

View File

@@ -1,5 +1,3 @@
import { notFound } from "next/navigation"
import { import {
getProfileSafely, getProfileSafely,
getSelectedRoomAvailability, getSelectedRoomAvailability,
@@ -12,7 +10,6 @@ import { SelectRateSearchParams } from "@/types/components/hotelReservation/sele
import { LangParams, PageArgs, SearchParams } from "@/types/params" import { LangParams, PageArgs, SearchParams } from "@/types/params"
export default async function SummaryPage({ export default async function SummaryPage({
params,
searchParams, searchParams,
}: PageArgs<LangParams, SearchParams<SelectRateSearchParams>>) { }: PageArgs<LangParams, SearchParams<SelectRateSearchParams>>) {
const selectRoomParams = new URLSearchParams(searchParams) const selectRoomParams = new URLSearchParams(searchParams)
@@ -38,25 +35,25 @@ export default async function SummaryPage({
const prices = user const prices = user
? { ? {
local: { local: {
price: availability.memberRate?.localPrice.pricePerStay, price: availability.memberRate?.localPrice.pricePerStay,
currency: availability.memberRate?.localPrice.currency, currency: availability.memberRate?.localPrice.currency,
}, },
euro: { euro: {
price: availability.memberRate?.requestedPrice?.pricePerStay, price: availability.memberRate?.requestedPrice?.pricePerStay,
currency: availability.memberRate?.requestedPrice?.currency, currency: availability.memberRate?.requestedPrice?.currency,
}, },
} }
: { : {
local: { local: {
price: availability.publicRate?.localPrice.pricePerStay, price: availability.publicRate?.localPrice.pricePerStay,
currency: availability.publicRate?.localPrice.currency, currency: availability.publicRate?.localPrice.currency,
}, },
euro: { euro: {
price: availability.publicRate?.requestedPrice?.pricePerStay, price: availability.publicRate?.requestedPrice?.pricePerStay,
currency: availability.publicRate?.requestedPrice?.currency, currency: availability.publicRate?.requestedPrice?.currency,
}, },
} }
return ( return (
<Summary <Summary

View File

@@ -49,7 +49,8 @@ export default async function StepPage({
toDate, toDate,
} = getQueryParamsForEnterDetails(selectRoomParams) } = getQueryParamsForEnterDetails(selectRoomParams)
void getBreakfastPackages(searchParams.hotel) const breakfastInput = { adults, fromDate, hotelId, toDate }
void getBreakfastPackages(breakfastInput)
void getSelectedRoomAvailability({ void getSelectedRoomAvailability({
hotelId: parseInt(searchParams.hotel), hotelId: parseInt(searchParams.hotel),
adults, adults,
@@ -74,7 +75,7 @@ export default async function StepPage({
rateCode, rateCode,
roomTypeCode, roomTypeCode,
}) })
const breakfastPackages = await getBreakfastPackages(searchParams.hotel) const breakfastPackages = await getBreakfastPackages(breakfastInput)
const user = await getProfileSafely() const user = await getProfileSafely()
const savedCreditCards = await getCreditCardsSafely() const savedCreditCards = await getCreditCardsSafely()

View File

@@ -12,7 +12,6 @@ import CountrySelect from "@/components/TempDesignSystem/Form/Country"
import Input from "@/components/TempDesignSystem/Form/Input" import Input from "@/components/TempDesignSystem/Form/Input"
import Phone from "@/components/TempDesignSystem/Form/Phone" import Phone from "@/components/TempDesignSystem/Form/Phone"
import Body from "@/components/TempDesignSystem/Text/Body" import Body from "@/components/TempDesignSystem/Text/Body"
import { toast } from "@/components/TempDesignSystem/Toasts"
import { detailsSchema, signedInDetailsSchema } from "./schema" import { detailsSchema, signedInDetailsSchema } from "./schema"
import Signup from "./Signup" import Signup from "./Signup"

View File

@@ -58,8 +58,14 @@ export default function Phone({
forceDialCode: true, forceDialCode: true,
value: phone, value: phone,
onChange: (value) => { onChange: (value) => {
setValue(name, value.phone) // If not checked trigger(name) forces validation on mount
trigger(name) // which shows error message before user even can see the form
if (value.inputValue) {
setValue(name, value.phone)
trigger(name)
} else {
setValue(name, "")
}
}, },
}) })

View File

@@ -9,6 +9,8 @@ import {
import { serverClient } from "../server" import { serverClient } from "../server"
import type { BreackfastPackagesInput } from "@/types/requests/packages"
export const getLocations = cache(async function getMemoizedLocations() { export const getLocations = cache(async function getMemoizedLocations() {
return serverClient().hotel.locations.get() return serverClient().hotel.locations.get()
}) })
@@ -135,7 +137,7 @@ export const getSiteConfig = cache(async function getMemoizedSiteConfig() {
}) })
export const getBreakfastPackages = cache(async function getMemoizedPackages( export const getBreakfastPackages = cache(async function getMemoizedPackages(
hotelId: string input: BreackfastPackagesInput
) { ) {
return serverClient().hotel.packages.breakfast({ hotelId }) return serverClient().hotel.packages.breakfast(input)
}) })

View File

@@ -68,6 +68,15 @@ export const getHotelDataInputSchema = z.object({
include: z.array(z.nativeEnum(HotelIncludeEnum)).optional(), include: z.array(z.nativeEnum(HotelIncludeEnum)).optional(),
}) })
export const getBreakfastPackageInput = z.object({ export const getBreakfastPackageInputSchema = z.object({
adults: z.number().min(1, { message: "at least one adult is required" }),
fromDate: z
.string()
.min(1, { message: "fromDate is required" })
.pipe(z.coerce.date()),
hotelId: z.string().min(1, { message: "hotelId is required" }), hotelId: z.string().min(1, { message: "hotelId is required" }),
toDate: z
.string()
.min(1, { message: "toDate is required" })
.pipe(z.coerce.date()),
}) })

View File

@@ -2,6 +2,7 @@ import { metrics } from "@opentelemetry/api"
import { Lang } from "@/constants/languages" import { Lang } from "@/constants/languages"
import * as api from "@/lib/api" import * as api from "@/lib/api"
import { dt } from "@/lib/dt"
import { GetHotelPage } from "@/lib/graphql/Query/HotelPage/HotelPage.graphql" import { GetHotelPage } from "@/lib/graphql/Query/HotelPage/HotelPage.graphql"
import { request } from "@/lib/graphql/request" import { request } from "@/lib/graphql/request"
import { import {
@@ -31,7 +32,7 @@ import {
getRoomPackagesSchema, getRoomPackagesSchema,
} from "./schemas/packages" } from "./schemas/packages"
import { import {
getBreakfastPackageInput, getBreakfastPackageInputSchema,
getHotelDataInputSchema, getHotelDataInputSchema,
getHotelInputSchema, getHotelInputSchema,
getHotelsAvailabilityInputSchema, getHotelsAvailabilityInputSchema,
@@ -982,14 +983,14 @@ export const hotelQueryRouter = router({
return validatedPackagesData.data return validatedPackagesData.data
}), }),
breakfast: safeProtectedServiceProcedure breakfast: safeProtectedServiceProcedure
.input(getBreakfastPackageInput) .input(getBreakfastPackageInputSchema)
.query(async function ({ ctx, input }) { .query(async function ({ ctx, input }) {
const params = { const params = {
Adults: 2, Adults: input.adults,
EndDate: "2024-10-28", EndDate: dt(input.toDate).format("YYYY-MM-DD"),
StartDate: "2024-10-25", StartDate: dt(input.fromDate).format("YYYY-MM-DD"),
} }
const metricsData = { ...input, ...params } const metricsData = { ...params, hotelId: input.hotelId }
breakfastPackagesCounter.add(1, metricsData) breakfastPackagesCounter.add(1, metricsData)
console.info( console.info(
"api.package.breakfast start", "api.package.breakfast start",

View File

@@ -0,0 +1,6 @@
import { z } from "zod"
import { getBreakfastPackageInputSchema } from "@/server/routers/hotels/input"
export interface BreackfastPackagesInput
extends z.input<typeof getBreakfastPackageInputSchema> {}