Merged in feat/SW-1370/Guarantee-my-stay-ancillaries (pull request #1545)

Feat/SW-1370/Guarantee my stay ancillaries

* feat(SW-1370): guarantee for ancillaries

* feat(SW-1370): remove console log

* feat(SW-1370): add translations

* feat(SW-1370): small fix

* feat(SW-1370): fix must be guaranteed

* feat(SW-1370): fix logic and comments pr

* feat(SW-1370): fix comments pr

* feat(SW-1370): fix comments pr

* feat(SW-1370): add translation

* feat(SW-1370): add translation and fix pr comment

* feat(SW-1370): fix pr comment

* feat(SW-1370): fix encoding path refId issue

* feat(SW-1370): refactor AddAncillaryStore usage and introduce context provider

* feat(SW-1370): refactor

* feat(SW-1370): refactor ancillaries

* feat(SW-1370): fix merge


Approved-by: Simon.Emanuelsson
This commit is contained in:
Bianca Widstam
2025-03-21 07:29:04 +00:00
parent 2bc14a6eeb
commit 3c1eee88b1
62 changed files with 1838 additions and 912 deletions

View File

@@ -1,42 +1,206 @@
import { create } from "zustand"
import { produce } from "immer"
import { useContext } from "react"
import { create, useStore } from "zustand"
import type { Ancillary } from "@/types/components/myPages/myStay/ancillaries"
import { clearAncillarySessionData } from "@/components/HotelReservation/MyStay/Ancillaries/utils"
import { AddAncillaryContext } from "@/contexts/AddAncillary"
interface AddAncillaryState {
step: number
totalSteps: number
nextStep: () => void
prevStep: () => void
resetStore: () => void
selectedAncillary: Ancillary["ancillaryContent"][number] | null
setSelectedAncillary: (
ancillary: Ancillary["ancillaryContent"][number]
) => void
confirmationNumber: string
setConfirmationNumber: (confirmationNumber: string) => void
openedFrom: "list" | "grid" | null
setOpenedFrom: (source: "list" | "grid") => void
isGridOpen: boolean
setGridIsOpen: (isOpen: boolean) => void
import type {
Ancillaries,
Ancillary,
SelectedAncillary,
} from "@/types/components/myPages/myStay/ancillaries"
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
export enum AncillaryStepEnum {
selectAncillary = 0,
selectQuantity = 1,
selectDelivery = 2,
confirmation = 3,
}
type Step = {
step: AncillaryStepEnum
isValid: boolean
}
type Steps = {
[AncillaryStepEnum.selectAncillary]?: Step
[AncillaryStepEnum.selectQuantity]: Step
[AncillaryStepEnum.selectDelivery]: Step
[AncillaryStepEnum.confirmation]: Step
}
export const useAddAncillaryStore = create<AddAncillaryState>((set) => ({
step: 1,
totalSteps: 3,
nextStep: () =>
set((state) =>
state.step < state.totalSteps ? { step: state.step + 1 } : {}
),
prevStep: () =>
set((state) => (state.step > 1 ? { step: state.step - 1 } : {})),
resetStore: () => set({ step: 1 }),
selectedAncillary: null,
setSelectedAncillary: (ancillary) => set({ selectedAncillary: ancillary }),
confirmationNumber: "",
setConfirmationNumber: (confirmationNumber) =>
set({ confirmationNumber: confirmationNumber }),
openedFrom: null,
setOpenedFrom: (source) => set({ openedFrom: source }),
isGridOpen: false,
setGridIsOpen: (isOpen) => set({ isGridOpen: isOpen }),
}))
export interface AddAncillaryState {
currentStep: number
steps: Steps
booking: BookingConfirmation["booking"]
ancillaries: Ancillaries
categories: Ancillary["categoryName"][]
selectedCategory: string
selectCategory: (category: string) => void
ancillariesBySelectedCategory: Ancillary["ancillaryContent"]
openModal: VoidFunction
closeModal: VoidFunction
prevStep: VoidFunction
isOpen: boolean
selectedAncillary: SelectedAncillary | null
selectAncillary: (ancillary: SelectedAncillary) => void
selectQuantity: VoidFunction
selectDeliveryTime: VoidFunction
selectQuantityAndDeliveryTime: VoidFunction
}
function findAncillaryByCategory(
ancillaries: Ancillaries,
selectedCategory: string
) {
return (
ancillaries.find((ancillary) => ancillary.categoryName === selectedCategory)
?.ancillaryContent ?? []
)
}
export const createAddAncillaryStore = (
booking: BookingConfirmation["booking"],
ancillaries: Ancillaries
) => {
const selectedCategory = ancillaries[0].categoryName
const ancillariesBySelectedCategory = findAncillaryByCategory(
ancillaries,
selectedCategory
)
const categories = ancillaries.map((ancillary) => ancillary.categoryName)
const steps = {
[AncillaryStepEnum.selectAncillary]: {
step: AncillaryStepEnum.selectAncillary,
isValid: true,
},
[AncillaryStepEnum.selectQuantity]: {
step: AncillaryStepEnum.selectQuantity,
isValid: false,
},
[AncillaryStepEnum.selectDelivery]: {
step: AncillaryStepEnum.selectDelivery,
isValid: false,
},
[AncillaryStepEnum.confirmation]: {
step: AncillaryStepEnum.confirmation,
isValid: false,
},
}
return create<AddAncillaryState>((set) => ({
booking,
ancillaries,
categories,
selectedCategory,
ancillariesBySelectedCategory,
currentStep: AncillaryStepEnum.selectAncillary,
selectedAncillary: null,
isOpen: false,
steps,
openModal: () =>
set(
produce((state: AddAncillaryState) => {
state.isOpen = true
state.currentStep = AncillaryStepEnum.selectAncillary
})
),
closeModal: () =>
set(
produce((state: AddAncillaryState) => {
state.isOpen = false
clearAncillarySessionData()
state.selectedAncillary = null
state.steps = steps
})
),
selectCategory: (category) =>
set(
produce((state: AddAncillaryState) => {
state.selectedCategory = category
state.ancillariesBySelectedCategory = findAncillaryByCategory(
state.ancillaries,
category
)
})
),
selectQuantity: () =>
set(
produce((state: AddAncillaryState) => {
if (state.selectedAncillary?.requiresDeliveryTime) {
state.currentStep = AncillaryStepEnum.selectDelivery
} else {
state.steps[AncillaryStepEnum.selectDelivery].isValid = true
state.currentStep = AncillaryStepEnum.confirmation
}
state.steps[AncillaryStepEnum.selectQuantity].isValid = true
})
),
selectQuantityAndDeliveryTime: () =>
set(
produce((state: AddAncillaryState) => {
state.steps[AncillaryStepEnum.selectQuantity].isValid = true
state.steps[AncillaryStepEnum.selectDelivery].isValid = true
state.currentStep = AncillaryStepEnum.confirmation
})
),
selectDeliveryTime: () =>
set(
produce((state: AddAncillaryState) => {
state.steps[AncillaryStepEnum.selectDelivery].isValid = true
state.currentStep = AncillaryStepEnum.confirmation
})
),
prevStep: () =>
set(
produce((state: AddAncillaryState) => {
if (
state.currentStep === AncillaryStepEnum.selectAncillary ||
(state.currentStep === AncillaryStepEnum.selectQuantity &&
!state.steps[AncillaryStepEnum.selectAncillary])
) {
state.isOpen = false
clearAncillarySessionData()
state.selectedAncillary = null
state.steps = steps
} else {
if (
!state.selectedAncillary?.requiresDeliveryTime &&
state.currentStep === AncillaryStepEnum.confirmation
) {
state.currentStep = AncillaryStepEnum.selectQuantity
} else if (state.currentStep === AncillaryStepEnum.selectQuantity) {
state.currentStep = state.currentStep - 1
state.selectedAncillary = null
} else {
state.currentStep = state.currentStep - 1
}
}
})
),
selectAncillary: (ancillary) =>
set(
produce((state: AddAncillaryState) => {
if (state.isOpen) {
state.steps[AncillaryStepEnum.selectAncillary]!.isValid = true
} else {
state.isOpen = true
delete state.steps[AncillaryStepEnum.selectAncillary]
}
state.selectedAncillary = ancillary
state.currentStep = AncillaryStepEnum.selectQuantity
})
),
}))
}
export const useAddAncillaryStore = <T>(
selector: (state: AddAncillaryState) => T
) => {
const store = useContext(AddAncillaryContext)
if (!store) {
throw new Error(
"useAddAncillaryStore must be used within AddAncillaryProvider"
)
}
return useStore(store, selector)
}