diff --git a/bun.lockb b/bun.lockb index 45b63483..a131a215 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 9194cc72..a1a9ac3d 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "@tinymce/tinymce-react": "^5.1.1", "countries-phone-masks": "^1.1.0", "date-fns": "^3.6.0", + "effector": "^23.3.0", + "effector-react": "^23.3.0", "framer-motion": "^11.17.0", "html-react-parser": "^5.1.18", "jose": "^5.9.3", diff --git a/src/components/Layout/CategoryCounter.tsx b/src/components/Layout/CategoryCounter.tsx index a9c23615..e381fd26 100644 --- a/src/components/Layout/CategoryCounter.tsx +++ b/src/components/Layout/CategoryCounter.tsx @@ -1,14 +1,15 @@ import { categories } from '@/consts/categories'; import PlusIcon from '../../../public/icons/plus.svg'; -import { useConfigurationStore } from '@/stores/useConfigurationStore'; import { imagesCategories } from '@/consts/categories'; +import { $configurationStore } from '@/stores/configurator-store/configurationStore'; +import { useUnit } from 'effector-react'; function CategoryCounter({ titleCategory, }: { titleCategory: keyof typeof categories; }) { - const { configuration, setConfiguration } = useConfigurationStore(); + const configuration = useUnit($configurationStore); const arrayCounters = categories[titleCategory]; const isAdvertisementMaterials = Array.isArray(arrayCounters) && diff --git a/src/stores/configurator-store/configurationStore.ts b/src/stores/configurator-store/configurationStore.ts new file mode 100644 index 00000000..636732e7 --- /dev/null +++ b/src/stores/configurator-store/configurationStore.ts @@ -0,0 +1,66 @@ +import { + Ads, + Design, + Details, + Equipment, + ExtraSeasons, + OptionFeatures, + Remote, +} from '../useConfigurationStore'; +import { combine, createStore, createEvent } from 'effector'; + +interface OptionObjectEffector { + allowMultiple: boolean; + opts: T; +} + +export const setEquipment = createEvent(); +export const setDesign = createEvent(); +export const toggleOption = createEvent(); +export const toggleSeason = createEvent(); + +const $equipment = createStore>({ + allowMultiple: false, + opts: 'Настенная панель', +}).on(setEquipment, (state, payload) => ({ ...state, opts: payload })); + +const $details = createStore
(300); + +const $design = createStore>({ + allowMultiple: false, + opts: 'WhiteBox.Квартиры без интерьеров', +}).on(setDesign, (state, payload) => ({ ...state, opts: payload })); + +const $options = createStore>({ + allowMultiple: true, + opts: ['Аватар клиента', 'Интерактивное окно'], +}).on(toggleOption, (state, payload) => ({ + ...state, + opts: state.opts.includes(payload) + ? state.opts.filter((opt) => opt !== payload) + : [...state.opts, payload], +})); + +const $seasons = createStore>({ + allowMultiple: true, + opts: [], +}).on(toggleSeason, (state, payload) => ({ + ...state, + opts: state.opts.includes(payload) + ? state.opts.filter((opt) => opt !== payload) + : [...state.opts, payload], +})); + +const $ads = createStore([0, 1]); + +const $remote = createStore(0); + +export const $configurationStore = combine({ + Оборудование: $equipment, + 'Детальная проработка окружения': $details, + 'Дизайн интерьеров': $design, + Опции: $options, + Сезонность: $seasons, + 'Рекламные материалы': $ads, + 'Удаленная демонстрация': $remote, +}); diff --git a/src/stores/useConfigurationStore.ts b/src/stores/useConfigurationStore.ts index c424abda..24cb33a9 100644 --- a/src/stores/useConfigurationStore.ts +++ b/src/stores/useConfigurationStore.ts @@ -36,12 +36,18 @@ export type OptionFeatures = export type ExtraSeasons = 'Лето' | 'Зима' | 'Весна' | 'Осень'; +export type Details = 300 | 500 | 700 | 1000; + +export type Ads = [number, number]; + +export type Remote = number; + export interface IConfiguration { Оборудование: { allowMultiple: false; opts: Equipment; }; - 'Детальная проработка окружения': 300 | 500 | 700 | 1000; + 'Детальная проработка окружения': Details; 'Дизайн интерьеров': { allowMultiple: false; opts: Design; @@ -54,8 +60,8 @@ export interface IConfiguration { allowMultiple: true; opts: ExtraSeasons[]; }; - 'Рекламные материалы': [number, number]; - 'Удаленная демонстрация': number; + 'Рекламные материалы': Ads; + 'Удаленная демонстрация': Remote; } export const useConfigurationStore = create<{ diff --git a/src/ui/CheckboxItem.tsx b/src/ui/CheckboxItem.tsx index 8d2b7131..3196f6ea 100644 --- a/src/ui/CheckboxItem.tsx +++ b/src/ui/CheckboxItem.tsx @@ -3,11 +3,17 @@ import { Equipment, ExtraSeasons, OptionFeatures, - OptionObject, OptionTitles, - useConfigurationStore, } from '@/stores/useConfigurationStore'; import { PropsWithChildren } from 'react'; +import { useUnit } from 'effector-react'; +import { + $configurationStore, + setEquipment, + setDesign, + toggleOption, + toggleSeason, +} from '@/stores/configurator-store/configurationStore'; function CheckboxItem({ titleCategory, @@ -21,36 +27,24 @@ function CheckboxItem({ item: Equipment | Design | OptionFeatures | ExtraSeasons; className?: string; }>) { - const { configuration, setConfiguration } = useConfigurationStore(); - const { allowMultiple, opts } = configuration[titleCategory] as OptionObject; + const configurator = useUnit($configurationStore); + const { allowMultiple, opts } = configurator[titleCategory]; function handleCheck(item: V[number]) { if (typeof opts === 'number') { return; } - - if (!Array.isArray(opts)) { - setConfiguration({ - ...configuration, - [titleCategory]: { allowMultiple, opts: item }, - }); - } else { - if (opts.includes(item as OptionFeatures & ExtraSeasons)) { - setConfiguration({ - ...configuration, - [titleCategory]: { - allowMultiple, - opts: opts.filter((i) => i !== item), - }, - }); - } else { - setConfiguration({ - ...configuration, - [titleCategory]: { allowMultiple, opts: [...opts, item] }, - }); - } + if (titleCategory === 'Оборудование') { + setEquipment(item as Equipment); + } else if (titleCategory === 'Дизайн интерьеров') { + setDesign(item as Design); + } else if (titleCategory === 'Опции') { + toggleOption(item as OptionFeatures); + } else if (titleCategory === 'Сезонность') { + toggleSeason(item as ExtraSeasons); } } + return (