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:
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user