# Cart Added Snackbar — Design Spec **Date:** 2026-05-25 ## Goal При добавлении товара в корзину показывать глобальное уведомление (Snackbar) с кнопкой «Перейти в корзину». ## Scope - `AddToCartButton` (каталог, карточки товаров) - `ToggleCartIcon` (страница товара, toggle add/remove) - Глобальный Snackbar, рендерится один раз ## Architecture ### 1. Effector store — `shared/model/cart-notifications.ts` Минимальный стор: только булев флаг открытия. ```ts import { createEvent, createStore } from 'effector' export const cartAdded = createEvent() export const cartDismissed = createEvent() export const $cartSnackOpen = createStore(false) .on(cartAdded, () => true) .on(cartDismissed, () => false) ``` ### 2. UI Component — `shared/ui/CartSnackbar.tsx` Компонент подписывается на `$cartSnackOpen` через `useUnit`. - **Текст:** «Товар добавлен в корзину» - **Кнопка действия:** «Перейти в корзину» → `navigate('/cart')` + `cartDismissed()` - **Закрытие (крестик):** `cartDismissed()` - **Авто-закрытие:** 4 секунды через `setTimeout` - **Позиция:** `anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}` - **Стиль:** MUI `` + `` Если пользователь быстро добавит несколько товаров — каждый `cartAdded()` перезапускает таймер. Очередь не нужна. ### 3. Интеграция в `AddToCartButton` В `onSuccess` мутации добавляется `cartAdded()`: ```ts const addMut = useMutation({ mutationFn: () => addToCart({ productId, qty }), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['me', 'cart'] }) cartAdded() }, }) ``` `productTitle` не передаётся — текст уведомления универсальный. ### 4. Интеграция в `ToggleCartIcon` Только add-мутация: ```ts const addMut = useMutation({ mutationFn: () => addToCart({ productId, qty: 1 }), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['me', 'cart'] }) cartAdded() }, }) ``` Remove-мутация без уведомления. ### 5. Mount point — `app/AppProviders.tsx` `` рендерится один раз в `AppProviders.tsx` (или `App.tsx`), чтобы быть доступным во всём приложении. ## Dependencies - effector / effector-react (уже используется) - @mui/material — Snackbar, Alert (уже используется) - react-router-dom — useNavigate (уже используется) ## Testing - Unit-тест `CartSnackbar`: открывается по `cartAdded()`, закрывается по `cartDismissed()` - Unit-тест `AddToCartButton`: вызывает `cartAdded()` в `onSuccess` - Unit-тест `ToggleCartIcon`: вызывает `cartAdded()` только для add-мутации