From a5400c1498636c8ba557f43c367fb507df577135 Mon Sep 17 00:00:00 2001 From: Simon Emanuelsson Date: Thu, 3 Oct 2024 11:12:36 +0200 Subject: [PATCH] feat: guest information form enter details --- .../hotelreservation/[section]/page.tsx | 11 +- .../SearchList/ClearSearchButton/index.tsx | 10 +- .../FormContent/Search/SearchList/index.tsx | 3 + .../FormContent/Search/index.tsx | 13 +- .../EnterDetails/Details/details.module.css | 25 ++++ .../EnterDetails/Details/index.tsx | 117 ++++++++++++++++++ .../EnterDetails/Details/schema.ts | 19 +++ .../HotelReservation/HotelCard/index.tsx | 8 +- components/Icons/Heart.tsx | 36 ++++++ components/Icons/icon.module.css | 15 +++ components/Icons/index.tsx | 1 + components/Icons/variants.ts | 3 + .../Form/Checkbox/Card/card.module.css | 70 +++++++++++ .../Form/Checkbox/Card/card.ts | 14 +++ .../Form/Checkbox/Card/index.tsx | 65 ++++++++++ .../TempDesignSystem/Form/Country/country.ts | 2 + .../TempDesignSystem/Form/Country/index.tsx | 7 +- .../Form/Input/AriaInputWithLabel/index.tsx | 25 ++++ .../Input/AriaInputWithLabel/input.module.css | 55 ++++++++ .../Form/Input/AriaInputWithLabel/input.ts | 4 + .../TempDesignSystem/Form/Input/index.tsx | 36 +++--- .../Form/Input/input.module.css | 56 --------- .../TempDesignSystem/Form/Input/input.ts | 2 +- .../Form/Label/label.module.css | 2 +- .../Form/NewPassword/index.tsx | 32 ++--- .../Form/NewPassword/newPassword.module.css | 56 --------- .../TempDesignSystem/Form/Phone/index.tsx | 40 +++--- .../Form/Phone/phone.module.css | 40 +----- .../TempDesignSystem/Form/Phone/phone.ts | 2 + .../Text/Body/body.module.css | 4 + .../TempDesignSystem/Text/Body/variants.ts | 1 + .../Text/Caption/caption.module.css | 8 ++ .../TempDesignSystem/Text/Caption/index.tsx | 3 + .../TempDesignSystem/Text/Caption/variants.ts | 8 ++ .../Text/Footnote/footnote.module.css | 2 +- .../Text/Footnote/variants.ts | 2 +- i18n/dictionaries/da.json | 48 +++---- i18n/dictionaries/de.json | 3 + i18n/dictionaries/en.json | 59 +++++---- i18n/dictionaries/fi.json | 49 ++++---- i18n/dictionaries/no.json | 48 +++---- i18n/dictionaries/sv.json | 47 +++---- lib/discriminatedUnion.ts | 8 +- lib/trpc/memoizedRequests/index.ts | 6 + server/routers/contentstack/base/output.ts | 11 +- .../contentstack/schemas/linkConnection.ts | 24 ++-- server/routers/user/query.ts | 116 +++++++++-------- types/components/enterDetails/details.ts | 11 ++ types/components/search.ts | 33 ++--- types/requests/system.ts | 10 +- 50 files changed, 833 insertions(+), 437 deletions(-) create mode 100644 components/HotelReservation/EnterDetails/Details/details.module.css create mode 100644 components/HotelReservation/EnterDetails/Details/index.tsx create mode 100644 components/HotelReservation/EnterDetails/Details/schema.ts create mode 100644 components/Icons/Heart.tsx create mode 100644 components/TempDesignSystem/Form/Checkbox/Card/card.module.css create mode 100644 components/TempDesignSystem/Form/Checkbox/Card/card.ts create mode 100644 components/TempDesignSystem/Form/Checkbox/Card/index.tsx create mode 100644 components/TempDesignSystem/Form/Input/AriaInputWithLabel/index.tsx create mode 100644 components/TempDesignSystem/Form/Input/AriaInputWithLabel/input.module.css create mode 100644 components/TempDesignSystem/Form/Input/AriaInputWithLabel/input.ts create mode 100644 types/components/enterDetails/details.ts diff --git a/app/[lang]/(live)/(public)/hotelreservation/[section]/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/[section]/page.tsx index b3ef81538..3ebb491e5 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/[section]/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/[section]/page.tsx @@ -1,11 +1,12 @@ import { notFound } from "next/navigation" +import { getProfileSafely } from "@/lib/trpc/memoizedRequests" import { serverClient } from "@/lib/trpc/server" +import Details from "@/components/HotelReservation/EnterDetails/Details" import HotelSelectionHeader from "@/components/HotelReservation/HotelSelectionHeader" import BedSelection from "@/components/HotelReservation/SelectRate/BedSelection" import BreakfastSelection from "@/components/HotelReservation/SelectRate/BreakfastSelection" -import Details from "@/components/HotelReservation/SelectRate/Details" import Payment from "@/components/HotelReservation/SelectRate/Payment" import RoomSelection from "@/components/HotelReservation/SelectRate/RoomSelection" import SectionAccordion from "@/components/HotelReservation/SelectRate/SectionAccordion" @@ -79,6 +80,7 @@ export default async function SectionsPage({ searchParams, }: PageArgs) { setLang(params.lang) + const profile = await getProfileSafely() const hotel = await serverClient().hotel.hotelData.get({ hotelId: "811", @@ -114,6 +116,11 @@ export default async function SectionsPage({ const currentSearchParams = new URLSearchParams(searchParams).toString() + let user = null + if (profile && !("error" in profile)) { + user = profile + } + return (
@@ -171,7 +178,7 @@ export default async function SectionsPage({ header={intl.formatMessage({ id: "Your details" })} path={`details?${currentSearchParams}`} > - {params.section === "details" &&
} + {params.section === "details" ?
: null} diff --git a/components/Forms/BookingWidget/FormContent/Search/SearchList/index.tsx b/components/Forms/BookingWidget/FormContent/Search/SearchList/index.tsx index 2bbc3b43d..a8736e69d 100644 --- a/components/Forms/BookingWidget/FormContent/Search/SearchList/index.tsx +++ b/components/Forms/BookingWidget/FormContent/Search/SearchList/index.tsx @@ -20,6 +20,7 @@ import type { SearchListProps } from "@/types/components/search" export default function SearchList({ getItemProps, getMenuProps, + handleClearSearchHistory, highlightedIndex, isOpen, locations, @@ -125,6 +126,7 @@ export default function SearchList({ @@ -161,6 +163,7 @@ export default function SearchList({ diff --git a/components/Forms/BookingWidget/FormContent/Search/index.tsx b/components/Forms/BookingWidget/FormContent/Search/index.tsx index 1ce969a29..353c2807b 100644 --- a/components/Forms/BookingWidget/FormContent/Search/index.tsx +++ b/components/Forms/BookingWidget/FormContent/Search/index.tsx @@ -43,6 +43,11 @@ export default function Search({ locations }: SearchProps) { [locations] ) + function handleClearSearchHistory() { + localStorage.removeItem(localStorageKey) + dispatch({ type: ActionType.CLEAR_HISTORY_LOCATIONS }) + } + function handleOnBlur() { if (!value && state.searchData?.name) { setValue(name, state.searchData.name) @@ -79,11 +84,8 @@ export default function Search({ locations }: SearchProps) { } } - function handleOnSelect(selectedItem: Location | null | "clear-search") { - if (selectedItem === "clear-search") { - localStorage.removeItem(localStorageKey) - dispatch({ type: ActionType.CLEAR_HISTORY_LOCATIONS }) - } else if (selectedItem) { + function handleOnSelect(selectedItem: Location | null) { + if (selectedItem) { const stringified = JSON.stringify(selectedItem) setValue("location", encodeURIComponent(stringified)) sessionStorage.setItem(sessionStorageKey, stringified) @@ -167,6 +169,7 @@ export default function Search({ locations }: SearchProps) { ({ + defaultValues: { + countryCode: user?.address?.countryCode ?? "", + email: user?.email ?? "", + firstname: user?.firstName ?? "", + lastname: user?.lastName ?? "", + phoneNumber: user?.phoneNumber ?? "", + }, + mode: "all", + resolver: zodResolver(user ? signedInDetailsSchema : detailsSchema), + reValidateMode: "onChange", + }) + + return ( + +
+
+ + {intl.formatMessage({ id: "Guest information" })} + +
+
+ + + + + + +
+ {user ? null : ( + + )} + +
+
+
+ ) +} diff --git a/components/HotelReservation/EnterDetails/Details/schema.ts b/components/HotelReservation/EnterDetails/Details/schema.ts new file mode 100644 index 000000000..92f1a5629 --- /dev/null +++ b/components/HotelReservation/EnterDetails/Details/schema.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { phoneValidator } from "@/utils/phoneValidator" + +export const detailsSchema = z.object({ + countryCode: z.string(), + email: z.string().email(), + firstname: z.string(), + lastname: z.string(), + phoneNumber: phoneValidator(), +}) + +export const signedInDetailsSchema = z.object({ + countryCode: z.string().optional(), + email: z.string().email().optional(), + firstname: z.string().optional(), + lastname: z.string().optional(), + phoneNumber: phoneValidator().optional(), +}) diff --git a/components/HotelReservation/HotelCard/index.tsx b/components/HotelReservation/HotelCard/index.tsx index 82b0c4b91..99feb01ab 100644 --- a/components/HotelReservation/HotelCard/index.tsx +++ b/components/HotelReservation/HotelCard/index.tsx @@ -48,10 +48,10 @@ export default async function HotelCard({ hotel }: HotelCardProps) { {hotelData.name} - + {`${hotelData.address.streetAddress}, ${hotelData.address.city}`} - + {`${hotelData.location.distanceToCentre} ${intl.formatMessage({ id: "km to city center" })}`} @@ -79,7 +79,7 @@ export default async function HotelCard({ hotel }: HotelCardProps) { {price?.regularAmount} {price?.currency} / {intl.formatMessage({ id: "night" })} - approx 280 eur + approx 280 eur
@@ -90,7 +90,7 @@ export default async function HotelCard({ hotel }: HotelCardProps) { {price?.memberAmount} {price?.currency} / {intl.formatMessage({ id: "night" })} - approx 280 eur + approx 280 eur