Merged in feat/SW-1737-design-mystay-multiroom (pull request #1565)
Feat/SW-1737 design mystay multiroom * feat(SW-1737) Fixed member view of guest details * feat(SW-1737) fix merge issues * feat(SW-1737) Fixed price details * feat(SW-1737) removed unused imports * feat(SW-1737) removed true as statement * feat(SW-1737) updated store handling * feat(SW-1737) fixed bug showing double numbers * feat(SW-1737) small design fixed * feat(SW-1737) fixed rebase errors * feat(SW-1737) fixed create booking error with dates * feat(SW-1737) fixed view multiroom as singleroom * feat(SW-1737) fixes for multiroom * feat(SW-1737) fixed bookingsummary * feat(SW-1737) dont hide modify dates * feat(SW-1737) updated breakfast to handle number * feat(SW-1737) Added red color if member rate * feat(SW-1737) fix PR comments * feat(SW-1737) updated member tiers svg * feat(SW-1737) updated how to handle paymentMethodDescription * feat(SW-1737) fixes after testing mystay * feat(SW-1737) updated Room type to just use whats used * feat(SW-1737) fixed access * feat(SW-1737) refactor my stay after PR comments * feat(SW-1737) fix roomNumber translation * feat(SW-1737) removed log Approved-by: Arvid Norlin
This commit is contained in:
50
apps/scandic-web/stores/my-stay/manageStayStore.ts
Normal file
50
apps/scandic-web/stores/my-stay/manageStayStore.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { create } from "zustand"
|
||||
|
||||
type ActiveView =
|
||||
| "actionPanel"
|
||||
| "cancelStay"
|
||||
| "modifyStay"
|
||||
| "guaranteeLateArrival"
|
||||
|
||||
interface ManageStayState {
|
||||
isOpen: boolean
|
||||
activeView: ActiveView
|
||||
currentStep: number
|
||||
isLoading: boolean
|
||||
actions: {
|
||||
setIsOpen: (isOpen: boolean) => void
|
||||
setActiveView: (view: ActiveView) => void
|
||||
setCurrentStep: (step: number) => void
|
||||
setIsLoading: (isLoading: boolean) => void
|
||||
handleForward: () => void
|
||||
handleCloseView: () => void
|
||||
handleCloseModal: () => void
|
||||
}
|
||||
}
|
||||
|
||||
export const useManageStayStore = create<ManageStayState>((set) => ({
|
||||
isOpen: false,
|
||||
activeView: "actionPanel",
|
||||
currentStep: 1,
|
||||
isLoading: false,
|
||||
actions: {
|
||||
setIsOpen: (isOpen) => set({ isOpen }),
|
||||
setActiveView: (activeView) => set({ activeView }),
|
||||
setCurrentStep: (currentStep) => set({ currentStep }),
|
||||
setIsLoading: (isLoading) => set({ isLoading }),
|
||||
handleForward: () =>
|
||||
set((state) => ({ currentStep: state.currentStep + 1 })),
|
||||
handleCloseView: () =>
|
||||
set({
|
||||
currentStep: 1,
|
||||
isLoading: false,
|
||||
activeView: "actionPanel",
|
||||
}),
|
||||
handleCloseModal: () =>
|
||||
set({
|
||||
currentStep: 1,
|
||||
isOpen: false,
|
||||
activeView: "actionPanel",
|
||||
}),
|
||||
},
|
||||
}))
|
||||
187
apps/scandic-web/stores/my-stay/myStayRoomDetailsStore.ts
Normal file
187
apps/scandic-web/stores/my-stay/myStayRoomDetailsStore.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
import { create } from "zustand"
|
||||
|
||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||
import type { RoomPrice } from "@/types/components/hotelReservation/enterDetails/details"
|
||||
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { Packages } from "@/types/requests/packages"
|
||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||
|
||||
export type Room = Pick<
|
||||
BookingConfirmation["booking"],
|
||||
| "hotelId"
|
||||
| "adults"
|
||||
| "checkInDate"
|
||||
| "checkOutDate"
|
||||
| "childrenAges"
|
||||
| "createDateTime"
|
||||
| "rateDefinition"
|
||||
| "guaranteeInfo"
|
||||
| "linkedReservations"
|
||||
| "confirmationNumber"
|
||||
| "cancellationNumber"
|
||||
| "bookingCode"
|
||||
| "isModifiable"
|
||||
| "isCancelable"
|
||||
| "multiRoom"
|
||||
| "canChangeDate"
|
||||
| "guest"
|
||||
| "roomTypeCode"
|
||||
| "currencyCode"
|
||||
| "vatPercentage"
|
||||
> & {
|
||||
roomName: string
|
||||
roomNumber: number | null
|
||||
isCancelled: boolean
|
||||
childrenInRoom: Child[]
|
||||
childrenAsString: string
|
||||
terms: string | null
|
||||
packages: Packages | null
|
||||
bedType: BedTypeSchema
|
||||
roomPrice: RoomPrice
|
||||
breakfast: BreakfastPackage | false
|
||||
mainRoom: boolean
|
||||
}
|
||||
|
||||
interface MyStayRoomDetailsState {
|
||||
bookedRoom: Room
|
||||
linkedReservationRooms: Room[]
|
||||
actions: {
|
||||
addBookedRoom: (room: Room) => void
|
||||
updateBookedRoom: (room: Room) => void
|
||||
addLinkedReservationRoom: (room: Room) => void
|
||||
updateLinkedReservationRoom: (room: Room) => void
|
||||
}
|
||||
}
|
||||
|
||||
export const useMyStayRoomDetailsStore = create<MyStayRoomDetailsState>(
|
||||
(set) => ({
|
||||
bookedRoom: {
|
||||
hotelId: "",
|
||||
roomTypeCode: "",
|
||||
adults: 0,
|
||||
childrenAges: [],
|
||||
checkInDate: new Date(),
|
||||
checkOutDate: new Date(),
|
||||
confirmationNumber: "",
|
||||
cancellationNumber: null,
|
||||
bookingCode: null,
|
||||
currencyCode: "",
|
||||
guest: {
|
||||
email: "",
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
membershipNumber: "",
|
||||
phoneNumber: "",
|
||||
countryCode: "",
|
||||
},
|
||||
rateDefinition: {
|
||||
breakfastIncluded: false,
|
||||
cancellationRule: null,
|
||||
cancellationText: null,
|
||||
generalTerms: [],
|
||||
isMemberRate: false,
|
||||
mustBeGuaranteed: false,
|
||||
rateCode: "",
|
||||
title: null,
|
||||
},
|
||||
reservationStatus: "",
|
||||
roomPrice: {
|
||||
perNight: {
|
||||
requested: {
|
||||
price: 0,
|
||||
currency: "",
|
||||
},
|
||||
local: {
|
||||
price: 0,
|
||||
currency: "",
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: {
|
||||
price: 0,
|
||||
currency: "",
|
||||
},
|
||||
local: {
|
||||
price: 0,
|
||||
currency: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
vatPercentage: 0,
|
||||
vatAmount: 0,
|
||||
totalPriceExVat: 0,
|
||||
createDateTime: new Date(),
|
||||
canChangeDate: false,
|
||||
multiRoom: false,
|
||||
mainRoom: false,
|
||||
roomName: "",
|
||||
roomNumber: null,
|
||||
isCancelled: false,
|
||||
childrenInRoom: [],
|
||||
childrenAsString: "",
|
||||
terms: null,
|
||||
packages: null,
|
||||
bedType: {
|
||||
description: "",
|
||||
roomTypeCode: "",
|
||||
},
|
||||
breakfast: false,
|
||||
linkedReservations: [],
|
||||
isCancelable: false,
|
||||
isModifiable: false,
|
||||
},
|
||||
linkedReservationRooms: [],
|
||||
actions: {
|
||||
addBookedRoom: (room) => {
|
||||
set({ bookedRoom: room })
|
||||
},
|
||||
updateBookedRoom: (room) => {
|
||||
set({ bookedRoom: room })
|
||||
},
|
||||
addLinkedReservationRoom: (room) => {
|
||||
set((state) => {
|
||||
// Check if room exists in bookedRooms
|
||||
const existsInBookedRoom =
|
||||
state.bookedRoom.confirmationNumber === room.confirmationNumber
|
||||
|
||||
if (existsInBookedRoom) {
|
||||
return state
|
||||
}
|
||||
|
||||
// Check if room with this ID already exists in linkedReservationRooms
|
||||
const existingIndex = state.linkedReservationRooms.findIndex(
|
||||
(r) => r.confirmationNumber === room.confirmationNumber
|
||||
)
|
||||
let newRooms = [...state.linkedReservationRooms]
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
// Update existing room
|
||||
newRooms[existingIndex] = room
|
||||
} else {
|
||||
// Add new room
|
||||
newRooms.push(room)
|
||||
}
|
||||
|
||||
return {
|
||||
linkedReservationRooms: newRooms,
|
||||
}
|
||||
})
|
||||
},
|
||||
updateLinkedReservationRoom: (room) => {
|
||||
set((state) => {
|
||||
const existingIndex = state.linkedReservationRooms.findIndex(
|
||||
(r) => r.confirmationNumber === room.confirmationNumber
|
||||
)
|
||||
let newRooms = [...state.linkedReservationRooms]
|
||||
if (existingIndex >= 0) {
|
||||
newRooms[existingIndex] = room
|
||||
}
|
||||
return {
|
||||
linkedReservationRooms: newRooms,
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
68
apps/scandic-web/stores/my-stay/myStayTotalPrice.ts
Normal file
68
apps/scandic-web/stores/my-stay/myStayTotalPrice.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { create } from "zustand"
|
||||
|
||||
interface RoomPrice {
|
||||
id: string
|
||||
totalPrice: number
|
||||
currencyCode: string
|
||||
isMainBooking?: boolean
|
||||
}
|
||||
|
||||
interface MyStayTotalPriceState {
|
||||
rooms: RoomPrice[]
|
||||
totalPrice: number | null
|
||||
currencyCode: string
|
||||
actions: {
|
||||
// Add a single room price
|
||||
addRoomPrice: (room: RoomPrice) => void
|
||||
|
||||
// Get the calculated total
|
||||
getTotalPrice: () => number | null
|
||||
}
|
||||
}
|
||||
|
||||
export const useMyStayTotalPriceStore = create<MyStayTotalPriceState>(
|
||||
(set, get) => ({
|
||||
rooms: [],
|
||||
totalPrice: null,
|
||||
currencyCode: "",
|
||||
actions: {
|
||||
addRoomPrice: (room) => {
|
||||
set((state) => {
|
||||
// Check if room with this ID already exists
|
||||
const existingIndex = state.rooms.findIndex((r) => r.id === room.id)
|
||||
let newRooms = [...state.rooms]
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
// Update existing room
|
||||
newRooms[existingIndex] = room
|
||||
} else {
|
||||
// Add new room
|
||||
newRooms.push(room)
|
||||
}
|
||||
|
||||
// Get currency from main booking or first room
|
||||
const mainRoom = newRooms.find((r) => r.isMainBooking) || newRooms[0]
|
||||
const currencyCode = mainRoom?.currencyCode || ""
|
||||
|
||||
// Calculate total (only same currency for now)
|
||||
const total = newRooms.reduce((sum, r) => {
|
||||
if (r.currencyCode === currencyCode) {
|
||||
return sum + r.totalPrice
|
||||
}
|
||||
return sum
|
||||
}, 0)
|
||||
|
||||
return {
|
||||
rooms: newRooms,
|
||||
totalPrice: total,
|
||||
currencyCode,
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getTotalPrice: () => {
|
||||
return get().totalPrice
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
@@ -3,22 +3,29 @@ import { create } from "zustand"
|
||||
import { trackOpenSidePeekEvent } from "@/utils/tracking"
|
||||
|
||||
import type { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import type { User } from "@/types/user"
|
||||
|
||||
interface SidePeekState {
|
||||
activeSidePeek: SidePeekEnum | null
|
||||
hotelId: string | null
|
||||
roomTypeCode: string | null
|
||||
showCTA: boolean
|
||||
user: User | null
|
||||
confirmationNumber: string
|
||||
openSidePeek: ({
|
||||
key,
|
||||
hotelId,
|
||||
roomTypeCode,
|
||||
showCTA,
|
||||
user,
|
||||
confirmationNumber,
|
||||
}: {
|
||||
key: SidePeekEnum | null
|
||||
hotelId: string
|
||||
roomTypeCode?: string
|
||||
showCTA?: boolean
|
||||
user?: User
|
||||
confirmationNumber?: string
|
||||
}) => void
|
||||
closeSidePeek: () => void
|
||||
}
|
||||
@@ -28,12 +35,33 @@ const useSidePeekStore = create<SidePeekState>((set) => ({
|
||||
hotelId: null,
|
||||
roomTypeCode: null,
|
||||
showCTA: true,
|
||||
openSidePeek: ({ key, hotelId, roomTypeCode, showCTA }) => {
|
||||
user: null,
|
||||
confirmationNumber: "",
|
||||
openSidePeek: ({
|
||||
key,
|
||||
hotelId,
|
||||
roomTypeCode,
|
||||
showCTA,
|
||||
user,
|
||||
confirmationNumber,
|
||||
}) => {
|
||||
trackOpenSidePeekEvent(key, hotelId, window.location.pathname, roomTypeCode)
|
||||
set({ activeSidePeek: key, hotelId, roomTypeCode, showCTA })
|
||||
set({
|
||||
activeSidePeek: key,
|
||||
hotelId,
|
||||
roomTypeCode,
|
||||
showCTA,
|
||||
user,
|
||||
confirmationNumber,
|
||||
})
|
||||
},
|
||||
closeSidePeek: () =>
|
||||
set({ activeSidePeek: null, hotelId: null, roomTypeCode: null }),
|
||||
set({
|
||||
activeSidePeek: null,
|
||||
hotelId: null,
|
||||
roomTypeCode: null,
|
||||
confirmationNumber: "",
|
||||
}),
|
||||
}))
|
||||
|
||||
export default useSidePeekStore
|
||||
|
||||
Reference in New Issue
Block a user