Files
shop-server/docs/superpowers/specs/2026-05-25-cart-added-snackbar-design.md
T
2026-05-25 17:04:57 +05:00

92 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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-мутации