import { produce } from "immer" import { useContext } from "react" import { create, useStore } from "zustand" import { DestinationDataContext } from "@/contexts/DestinationData" import { getBasePathNameWithoutFilters, getFilteredCities, getFilteredHotels, getFiltersFromHotels, getSortedCities, getSortedHotels, isValidSortOption, } from "./helper" import type { Filter } from "@/types/components/destinationFilterAndSort" import type { DestinationDataState, InitialState, } from "@/types/stores/destination-data" export function createDestinationDataStore({ allCities, allHotels, pathname, sortItems, }: InitialState) { const defaultSort = sortItems.find((s) => s.isDefault)?.value ?? sortItems[0].value const allFilters = getFiltersFromHotels(allHotels) const allFilterSlugs = Object.values(allFilters).flatMap((filter: Filter[]) => filter.map((f) => f.slug) ) return create((set) => ({ actions: { updateActiveFiltersAndSort(filters, sort) { return set( produce((state: DestinationDataState) => { const newSort = sort && isValidSortOption(sort, state.sortItems) ? sort : state.defaultSort const filteredHotels = getFilteredHotels(state.allHotels, filters) const sortedHotels = getSortedHotels(filteredHotels, newSort) const filteredCities = state.allHotels.length ? getFilteredCities(filteredHotels, state.allCities) : [] const sortedCities = getSortedCities(filteredCities, newSort) state.activeSort = newSort state.activeFilters = filters state.activeHotels = sortedHotels state.activeCities = sortedCities state.pendingFilters = filters state.pendingSort = newSort state.pendingHotelCount = filteredHotels.length state.pendingCityCount = filteredCities.length state.isLoading = false }) ) }, setIsLoading(isLoading) { return set( produce((state: DestinationDataState) => { state.isLoading = isLoading }) ) }, setPendingSort(sort) { return set( produce((state: DestinationDataState) => { state.pendingSort = sort }) ) }, togglePendingFilter(filter) { return set( produce((state: DestinationDataState) => { const isActive = state.pendingFilters.includes(filter) const filters = isActive ? state.pendingFilters.filter((f) => f !== filter) : [...state.pendingFilters, filter] const pendingHotels = getFilteredHotels(state.allHotels, filters) const pendingCities = state.allHotels.length ? getFilteredCities(pendingHotels, state.allCities) : [] state.pendingFilters = filters state.pendingHotelCount = pendingHotels.length state.pendingCityCount = pendingCities.length }) ) }, clearPendingFilters() { return set( produce((state: DestinationDataState) => { state.pendingFilters = [] state.pendingHotelCount = state.allHotels.length state.pendingCityCount = state.allCities.length }) ) }, resetPendingValues() { return set( produce((state: DestinationDataState) => { state.pendingFilters = state.activeFilters state.pendingSort = state.activeSort state.pendingHotelCount = state.activeHotels.length state.pendingCityCount = state.activeCities.length }) ) }, }, allHotels, activeHotels: allHotels, pendingHotelCount: allHotels.length, allCities, activeCities: allCities, pendingCityCount: allCities.length, activeSort: defaultSort, pendingSort: defaultSort, defaultSort, activeFilters: [], pendingFilters: [], allFilters, allFilterSlugs, basePathnameWithoutFilters: getBasePathNameWithoutFilters( pathname, allFilterSlugs ), sortItems, isLoading: true, })) } export function useDestinationDataStore( selector: (store: DestinationDataState) => T ) { const store = useContext(DestinationDataContext) if (!store) { throw new Error("useHotelDataStore must be used within HotelDataProvider") } return useStore(store, selector) }