docs: cart added snackbar design spec

This commit is contained in:
Kirill
2026-05-25 17:04:57 +05:00
parent af6b249248
commit 1cfabab4c6
@@ -0,0 +1,91 @@
# 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 `<Snackbar>` + `<Alert severity="success">`
Если пользователь быстро добавит несколько товаров — каждый `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`
`<CartSnackbar />` рендерится один раз в `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-мутации