feat: implement state with effector instead of zustand
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
Ads,
|
||||
Design,
|
||||
Details,
|
||||
Equipment,
|
||||
ExtraSeasons,
|
||||
OptionFeatures,
|
||||
Remote,
|
||||
} from '../useConfigurationStore';
|
||||
import { combine, createStore, createEvent } from 'effector';
|
||||
|
||||
interface OptionObjectEffector<T> {
|
||||
allowMultiple: boolean;
|
||||
opts: T;
|
||||
}
|
||||
|
||||
export const setEquipment = createEvent<Equipment>();
|
||||
export const setDesign = createEvent<Design>();
|
||||
export const toggleOption = createEvent<OptionFeatures>();
|
||||
export const toggleSeason = createEvent<ExtraSeasons>();
|
||||
|
||||
const $equipment = createStore<OptionObjectEffector<Equipment>>({
|
||||
allowMultiple: false,
|
||||
opts: 'Настенная панель',
|
||||
}).on(setEquipment, (state, payload) => ({ ...state, opts: payload }));
|
||||
|
||||
const $details = createStore<Details>(300);
|
||||
|
||||
const $design = createStore<OptionObjectEffector<Design>>({
|
||||
allowMultiple: false,
|
||||
opts: 'WhiteBox.Квартиры без интерьеров',
|
||||
}).on(setDesign, (state, payload) => ({ ...state, opts: payload }));
|
||||
|
||||
const $options = createStore<OptionObjectEffector<OptionFeatures[]>>({
|
||||
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<OptionObjectEffector<ExtraSeasons[]>>({
|
||||
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<Ads>([0, 1]);
|
||||
|
||||
const $remote = createStore<Remote>(0);
|
||||
|
||||
export const $configurationStore = combine({
|
||||
Оборудование: $equipment,
|
||||
'Детальная проработка окружения': $details,
|
||||
'Дизайн интерьеров': $design,
|
||||
Опции: $options,
|
||||
Сезонность: $seasons,
|
||||
'Рекламные материалы': $ads,
|
||||
'Удаленная демонстрация': $remote,
|
||||
});
|
||||
@@ -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<{
|
||||
|
||||
+19
-25
@@ -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<T extends keyof OptionTitles, V extends OptionTitles[T]>({
|
||||
titleCategory,
|
||||
@@ -21,36 +27,24 @@ function CheckboxItem<T extends keyof OptionTitles, V extends OptionTitles[T]>({
|
||||
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 (
|
||||
<label
|
||||
className={`relative p-3 bg-[#37393B99] rounded-2xl flex-shrink-0 flex flex-col items-start justify-between snap-always ${className} ${
|
||||
|
||||
Reference in New Issue
Block a user