Merge branch 'develop' into feature/tracking
This commit is contained in:
@@ -3,21 +3,22 @@ import { createContext, useContext } from "react"
|
||||
import { create, useStore } from "zustand"
|
||||
|
||||
import { bedTypeSchema } from "@/components/HotelReservation/EnterDetails/BedType/schema"
|
||||
import { breakfastSchema } from "@/components/HotelReservation/EnterDetails/Breakfast/schema"
|
||||
import { breakfastStoreSchema } from "@/components/HotelReservation/EnterDetails/Breakfast/schema"
|
||||
import { detailsSchema } from "@/components/HotelReservation/EnterDetails/Details/schema"
|
||||
|
||||
import { BreakfastPackage } from "@/types/components/enterDetails/breakfast"
|
||||
import { DetailsSchema } from "@/types/components/enterDetails/details"
|
||||
import { SidePeekEnum } from "@/types/components/enterDetails/sidePeek"
|
||||
import { StepEnum } from "@/types/components/enterDetails/step"
|
||||
import { bedTypeEnum } from "@/types/enums/bedType"
|
||||
import { breakfastEnum } from "@/types/enums/breakfast"
|
||||
import { BedTypeEnum } from "@/types/enums/bedType"
|
||||
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||
|
||||
const SESSION_STORAGE_KEY = "enterDetails"
|
||||
|
||||
interface EnterDetailsState {
|
||||
data: {
|
||||
bedType: bedTypeEnum | undefined
|
||||
breakfast: breakfastEnum | undefined
|
||||
bedType: BedTypeEnum | undefined
|
||||
breakfast: BreakfastPackage | BreakfastPackageEnum.NO_BREAKFAST | undefined
|
||||
} & DetailsSchema
|
||||
steps: StepEnum[]
|
||||
currentStep: StepEnum
|
||||
@@ -26,7 +27,7 @@ interface EnterDetailsState {
|
||||
completeStep: (updatedData: Partial<EnterDetailsState["data"]>) => void
|
||||
navigate: (
|
||||
step: StepEnum,
|
||||
updatedData?: Record<string, string | boolean>
|
||||
updatedData?: Record<string, string | boolean | BreakfastPackage>
|
||||
) => void
|
||||
setCurrentStep: (step: StepEnum) => void
|
||||
openSidePeek: (key: SidePeekEnum | null) => void
|
||||
@@ -75,7 +76,7 @@ export function initEditDetailsState(currentStep: StepEnum) {
|
||||
initialData = { ...initialData, ...validatedBedType.data }
|
||||
isValid[StepEnum.selectBed] = true
|
||||
}
|
||||
const validatedBreakfast = breakfastSchema.safeParse(inputData)
|
||||
const validatedBreakfast = breakfastStoreSchema.safeParse(inputData)
|
||||
if (validatedBreakfast.success) {
|
||||
validPaths.push(StepEnum.details)
|
||||
initialData = { ...initialData, ...validatedBreakfast.data }
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
"use client"
|
||||
|
||||
import { produce } from "immer"
|
||||
import { create } from "zustand"
|
||||
import { createContext, useContext } from "react"
|
||||
import { create, useStore } from "zustand"
|
||||
|
||||
import { BedTypeEnum } from "@/types/components/bookingWidget/enums"
|
||||
import { Child } from "@/types/components/bookingWidget/guestsRoomsPicker"
|
||||
import {
|
||||
Child,
|
||||
GuestsRoom,
|
||||
} from "@/types/components/bookingWidget/guestsRoomsPicker"
|
||||
|
||||
interface GuestsRooms {
|
||||
rooms: [
|
||||
{
|
||||
adults: number
|
||||
children: Child[]
|
||||
childrenInAdultsBed: number
|
||||
},
|
||||
]
|
||||
const SESSION_STORAGE_KEY = "guests_rooms"
|
||||
|
||||
interface extendedGuestsRoom extends GuestsRoom {
|
||||
childrenInAdultsBed: number
|
||||
}
|
||||
interface GuestsRoomsState {
|
||||
rooms: extendedGuestsRoom[]
|
||||
adultCount: number
|
||||
childCount: number
|
||||
isValidated: boolean
|
||||
}
|
||||
|
||||
interface GuestsRoomsStoreState extends GuestsRoomsState {
|
||||
increaseAdults: (roomIndex: number) => void
|
||||
decreaseAdults: (roomIndex: number) => void
|
||||
increaseChildren: (roomIndex: number) => void
|
||||
@@ -30,115 +36,192 @@ interface GuestsRooms {
|
||||
setIsValidated: (isValidated: boolean) => void
|
||||
}
|
||||
|
||||
export const useGuestsRoomsStore = create<GuestsRooms>((set, get) => ({
|
||||
rooms: [
|
||||
{
|
||||
adults: 1,
|
||||
children: [],
|
||||
childrenInAdultsBed: 0,
|
||||
},
|
||||
],
|
||||
adultCount: 1,
|
||||
childCount: 0,
|
||||
isValidated: false,
|
||||
increaseAdults: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms[roomIndex].adults = state.rooms[roomIndex].adults + 1
|
||||
state.adultCount = state.adultCount + 1
|
||||
})
|
||||
),
|
||||
decreaseAdults: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms[roomIndex].adults = state.rooms[roomIndex].adults - 1
|
||||
state.adultCount = state.adultCount - 1
|
||||
if (
|
||||
state.rooms[roomIndex].childrenInAdultsBed >
|
||||
state.rooms[roomIndex].adults
|
||||
) {
|
||||
const toUpdateIndex = state.rooms[roomIndex].children.findIndex(
|
||||
(child) => child.bed == BedTypeEnum.IN_ADULTS_BED
|
||||
)
|
||||
if (toUpdateIndex != -1) {
|
||||
state.rooms[roomIndex].children[toUpdateIndex].bed =
|
||||
state.rooms[roomIndex].children[toUpdateIndex].age < 3
|
||||
? BedTypeEnum.IN_CRIB
|
||||
: BedTypeEnum.IN_EXTRA_BED
|
||||
state.rooms[roomIndex].childrenInAdultsBed =
|
||||
state.rooms[roomIndex].adults
|
||||
}
|
||||
}
|
||||
})
|
||||
),
|
||||
increaseChildren: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms[roomIndex].children.push({
|
||||
age: -1,
|
||||
bed: -1,
|
||||
export function validateBedTypes(data: extendedGuestsRoom[]) {
|
||||
data.forEach((room) => {
|
||||
room.child.forEach((child) => {
|
||||
const allowedBedTypes: number[] = []
|
||||
if (child.age <= 5 && room.adults >= room.childrenInAdultsBed) {
|
||||
allowedBedTypes.push(BedTypeEnum.IN_ADULTS_BED)
|
||||
} else if (child.age <= 5) {
|
||||
room.childrenInAdultsBed = room.childrenInAdultsBed - 1
|
||||
}
|
||||
if (child.age < 3) {
|
||||
allowedBedTypes.push(BedTypeEnum.IN_CRIB)
|
||||
}
|
||||
if (child.age > 2) {
|
||||
allowedBedTypes.push(BedTypeEnum.IN_EXTRA_BED)
|
||||
}
|
||||
if (!allowedBedTypes.includes(child.bed)) {
|
||||
child.bed = allowedBedTypes[0]
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function initGuestsRoomsState(initData?: GuestsRoom[]) {
|
||||
const isBrowser = typeof window !== "undefined"
|
||||
const sessionData = isBrowser
|
||||
? sessionStorage.getItem(SESSION_STORAGE_KEY)
|
||||
: null
|
||||
|
||||
const defaultGuestsData: extendedGuestsRoom = {
|
||||
adults: 1,
|
||||
child: [],
|
||||
childrenInAdultsBed: 0,
|
||||
}
|
||||
const defaultData: GuestsRoomsState = {
|
||||
rooms: [defaultGuestsData],
|
||||
adultCount: 1,
|
||||
childCount: 0,
|
||||
isValidated: false,
|
||||
}
|
||||
|
||||
let inputData: GuestsRoomsState = defaultData
|
||||
if (sessionData) {
|
||||
inputData = JSON.parse(sessionData)
|
||||
}
|
||||
if (initData) {
|
||||
inputData.rooms = initData.map((room) => {
|
||||
const childrenInAdultsBed = room.child
|
||||
? room.child.reduce((acc, child) => {
|
||||
acc = acc + (child.bed == BedTypeEnum.IN_ADULTS_BED ? 1 : 0)
|
||||
return acc
|
||||
}, 0)
|
||||
: 0
|
||||
return { ...defaultGuestsData, ...room, childrenInAdultsBed }
|
||||
}) as extendedGuestsRoom[]
|
||||
|
||||
inputData.adultCount = initData.reduce((acc, room) => {
|
||||
acc = acc + room.adults
|
||||
return acc
|
||||
}, 0)
|
||||
inputData.childCount = initData.reduce((acc, room) => {
|
||||
acc = acc + room.child?.length
|
||||
return acc
|
||||
}, 0)
|
||||
validateBedTypes(inputData.rooms)
|
||||
}
|
||||
|
||||
return create<GuestsRoomsStoreState>()((set, get) => ({
|
||||
...inputData,
|
||||
increaseAdults: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms[roomIndex].adults = state.rooms[roomIndex].adults + 1
|
||||
state.adultCount = state.adultCount + 1
|
||||
})
|
||||
state.childCount = state.childCount + 1
|
||||
})
|
||||
),
|
||||
decreaseChildren: (roomIndex) => {
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
const roomChildren = state.rooms[roomIndex].children
|
||||
if (
|
||||
roomChildren.length &&
|
||||
roomChildren[roomChildren.length - 1].bed == BedTypeEnum.IN_ADULTS_BED
|
||||
) {
|
||||
),
|
||||
decreaseAdults: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms[roomIndex].adults = state.rooms[roomIndex].adults - 1
|
||||
state.adultCount = state.adultCount - 1
|
||||
if (
|
||||
state.rooms[roomIndex].childrenInAdultsBed >
|
||||
state.rooms[roomIndex].adults
|
||||
) {
|
||||
const toUpdateIndex = state.rooms[roomIndex].child.findIndex(
|
||||
(child) => child.bed == BedTypeEnum.IN_ADULTS_BED
|
||||
)
|
||||
if (toUpdateIndex != -1) {
|
||||
state.rooms[roomIndex].child[toUpdateIndex].bed =
|
||||
state.rooms[roomIndex].child[toUpdateIndex].age < 3
|
||||
? BedTypeEnum.IN_CRIB
|
||||
: BedTypeEnum.IN_EXTRA_BED
|
||||
state.rooms[roomIndex].childrenInAdultsBed =
|
||||
state.rooms[roomIndex].adults
|
||||
}
|
||||
}
|
||||
})
|
||||
),
|
||||
increaseChildren: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms[roomIndex].child.push({
|
||||
age: -1,
|
||||
bed: -1,
|
||||
})
|
||||
state.childCount = state.childCount + 1
|
||||
})
|
||||
),
|
||||
decreaseChildren: (roomIndex) => {
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
const roomChildren = state.rooms[roomIndex].child
|
||||
if (
|
||||
roomChildren.length &&
|
||||
roomChildren[roomChildren.length - 1].bed ==
|
||||
BedTypeEnum.IN_ADULTS_BED
|
||||
) {
|
||||
state.rooms[roomIndex].childrenInAdultsBed =
|
||||
state.rooms[roomIndex].childrenInAdultsBed - 1
|
||||
}
|
||||
state.rooms[roomIndex].child.pop()
|
||||
state.childCount = state.childCount - 1
|
||||
})
|
||||
)
|
||||
return get().rooms[roomIndex].child
|
||||
},
|
||||
updateChildAge: (age, roomIndex, childIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms[roomIndex].child[childIndex].age = age
|
||||
})
|
||||
),
|
||||
updateChildBed: (bed, roomIndex, childIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms[roomIndex].child[childIndex].bed = bed
|
||||
})
|
||||
),
|
||||
increaseChildInAdultsBed: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms[roomIndex].childrenInAdultsBed =
|
||||
state.rooms[roomIndex].childrenInAdultsBed + 1
|
||||
})
|
||||
),
|
||||
decreaseChildInAdultsBed: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms[roomIndex].childrenInAdultsBed =
|
||||
state.rooms[roomIndex].childrenInAdultsBed - 1
|
||||
}
|
||||
state.rooms[roomIndex].children.pop()
|
||||
state.childCount = state.childCount - 1
|
||||
})
|
||||
)
|
||||
return get().rooms[roomIndex].children
|
||||
},
|
||||
updateChildAge: (age, roomIndex, childIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms[roomIndex].children[childIndex].age = age
|
||||
})
|
||||
),
|
||||
updateChildBed: (bed, roomIndex, childIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms[roomIndex].children[childIndex].bed = bed
|
||||
})
|
||||
),
|
||||
increaseChildInAdultsBed: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms[roomIndex].childrenInAdultsBed =
|
||||
state.rooms[roomIndex].childrenInAdultsBed + 1
|
||||
})
|
||||
),
|
||||
decreaseChildInAdultsBed: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms[roomIndex].childrenInAdultsBed =
|
||||
state.rooms[roomIndex].childrenInAdultsBed - 1
|
||||
})
|
||||
),
|
||||
increaseRoom: () =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms.push({
|
||||
adults: 1,
|
||||
children: [],
|
||||
childrenInAdultsBed: 0,
|
||||
})
|
||||
})
|
||||
),
|
||||
decreaseRoom: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRooms) => {
|
||||
state.rooms.splice(roomIndex, 1)
|
||||
})
|
||||
),
|
||||
setIsValidated: (isValidated) => set(() => ({ isValidated })),
|
||||
}))
|
||||
),
|
||||
increaseRoom: () =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms.push({
|
||||
adults: 1,
|
||||
child: [],
|
||||
childrenInAdultsBed: 0,
|
||||
})
|
||||
})
|
||||
),
|
||||
decreaseRoom: (roomIndex) =>
|
||||
set(
|
||||
produce((state: GuestsRoomsState) => {
|
||||
state.rooms.splice(roomIndex, 1)
|
||||
})
|
||||
),
|
||||
setIsValidated: (isValidated) => set(() => ({ isValidated })),
|
||||
}))
|
||||
}
|
||||
|
||||
export type GuestsRoomsStore = ReturnType<typeof initGuestsRoomsState>
|
||||
|
||||
export const GuestsRoomsContext = createContext<GuestsRoomsStore | null>(null)
|
||||
|
||||
export const useGuestsRoomsStore = <T>(
|
||||
selector: (store: GuestsRoomsStoreState) => T
|
||||
): T => {
|
||||
const guestsRoomsContextStore = useContext(GuestsRoomsContext)
|
||||
|
||||
if (!guestsRoomsContextStore) {
|
||||
throw new Error(
|
||||
`guestsRoomsContextStore must be used within GuestsRoomsContextProvider`
|
||||
)
|
||||
}
|
||||
|
||||
return useStore(guestsRoomsContextStore, selector)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user