food-market/docs/sprint7-progress.md
nns 64af42167b
Some checks are pending
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
docs(sprint7): пункты 6-7 ✓ + итог по спринту
Все 7 пунктов закрыты. Stage прошёл smoke-тест 5/5 после последнего деплоя.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 11:52:00 +05:00

99 lines
10 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.

# Sprint 7 — UX-полировка stage + демо-данные
Цель: `https://test.admin.food-market.kz` открывается → наполненные модули видны сразу, UI удобен (confirm на destructive, toast'ы, скелеты, empty-states, breadcrumbs, shortcuts).
Старт: 2026-05-29. Исполнитель: Claude Opus 4.7 (автономный режим).
## Принципы
- Каждый пункт: build + тесты + `~/deploy-stage.sh` + Playwright-скриншот retest на стенде + коммит + `[x]` в этом доке.
- НЕ трогать: global.json, прод-стек (admin.food-market.kz), POS WPF.
- Команды для теста UI на стенде: `cd src/food-market.web && pnpm dev` локально к API; либо Playwright против `https://test.admin.food-market.kz` после деплоя.
## Чек-лист
- [x] **1. Demo-data seeder для stage** — POST /api/admin/seed-demo + admin-кнопка «Заполнить демо-данными». 50 товаров / 5 групп / 10 контрагентов / 5 приёмок / 30 продаж / 1 опт / 1 списание / 1 перемещение / 1 инвентаризация. Идемпотентно (маркер DEMO-). E2E 5/5 ✓ на стейдже.
- [x] **2. ConfirmDialog на destructive actions** — общий `<ConfirmDialog>` + хук `useConfirm()`. Применён к 17 страницам + ProductImageGallery. Esc=cancel, focus-on-Cancel, tone='danger'|'warning'. Org-archive уже использует Modal с confirmation-name (не трогали). 2FA UI ещё не существует в web — пропущено. Скриншот стейджа: `tests/e2e/reports/confirm-dialog-1780119970286.png`.
- [x] **3. Toast-система ошибок** — собственная `lib/toast.ts` + `<Toaster>`. Axios interceptor: 4xx/5xx → error toast (humanizeError() читает ProblemDetails: errors.X[0] / detail / message / title). 401 — refresh-flow, без toast. Success — глобальный mutation onSuccess (через `meta.successMessage`): useCatalogMutations + 36 мутаций на doc-edit pages. Top-right, autoclose 5s, дедуп, ручное закрытие X. Скриншот: `tests/e2e/reports/toast-error-*.png`.
- [x] **4. Loading skeletons**`Skeleton.tsx` экспортирует `<Skeleton variant>`, `<TableSkeleton>`, `<FormSkeleton>`. DataTable рендерит TableSkeleton при isLoading. 9 doc-edit pages + OrganizationSettingsPage показывают FormSkeleton пока тащат документ. DashboardPage график → Skeleton block. Скриншот: `tests/e2e/reports/skeleton-table-*.png`.
- [x] **5. Empty states с CTA**`EmptyState.tsx` (icon + title + description + action/secondary). Применён к 14 list-страницам (Products/Counterparties/Enters/Losses/Transfers/Inventories/Demands/SupplierReturns/Supplies/RetailSales + 4 отчёта). Показывается только когда нет поиска/фильтров. Скриншот: `tests/e2e/reports/empty-state-products-*.png`.
- [x] **6. Breadcrumbs** — Reusable `<Breadcrumbs items={[{label, to?}]}>` (ChevronRight разделитель, последний item — semibold). Применён к 9 edit-страницам (Product + Supply/Enter/Loss/Transfer/Inventory/SupplierReturn/Demand/RetailSale). Дублирующая subtitle убрана. Скриншот: `tests/e2e/reports/breadcrumbs-product-*.png`.
- [x] **7. Keyboard shortcuts**`useShortcuts(map, enabled?)` хук + `<ShortcutsOverlay>` (открывается клавишей `?`). Поддерживает `mod+s`, одиночные клавиши скипают input/textarea. Edit (9 страниц): mod+s=save (через `canSave`), Esc=back-to-list. Гард `!dialogProps.open` чтобы Esc не воровал у ConfirmDialog. List (10 страниц): `/`=focus search (SearchBar теперь forwardRef), `n`=create new. ShortcutsOverlay смонтирован в AppLayout, `?` всегда доступен.
## Журнал
### 2026-05-29 — старт
- Stage-testing спринта 6 закрыт (`docs/stage-testing-progress.md`, 13 сценариев / 94/94 шага ✓).
- Создан этот файл, перехожу к пункту 1.
### 2026-05-30 — пункт 1 ✓
- `DemoTenantSeeder` + `DemoSeedController` + UI-секция «Демо-данные» в OrganizationSettingsPage.
- Идемпотентность через маркер `Article startsWith "DEMO-"`.
- E2E `stage-demo-seed` (5 шагов) — green локально + на `test.admin.food-market.kz` (после deploy-stage.sh).
- Коммит: `ad09b56 feat(stage): demo-data seeder для test.admin.food-market.kz`.
### 2026-05-30 — пункт 2 ✓
- `<ConfirmDialog>` + хук `useConfirm()`. Button переведён на forwardRef.
- Применил к ProductEdit + 6 doc-edit + RetailSaleEdit + 8 list-pages + EmployeesPage + ProductImageGallery (всего 18 файлов).
- Esc=cancel, фокус на Cancel (Enter не подтверждает). Tone='danger'/'warning'.
- Скриншот стейджа: `tests/e2e/reports/confirm-dialog-*.png` — диалог рендерится, Esc-закрытие работает.
- Коммит: `17a6da2 feat(web): ConfirmDialog компонент + useConfirm hook`.
### 2026-05-30 — пункт 3 ✓
- `lib/toast.ts` + `<Toaster>`: top-right, autoclose 5s, дедуп, ручное закрытие, role=alert.
- Axios interceptor (src/lib/api.ts): 4xx/5xx → toast.error c humanizeError (ProblemDetails-aware), 401 — refresh-flow без шума.
- Global mutation onSuccess (App.tsx) подтягивает meta.successMessage.
- useCatalogMutations: create/update/remove получили дефолтные тексты — автоматически работает на всех list-pages, использующих хук.
- Doc-edit pages: 36 мутаций (save/post/unpost/remove) получили meta.
- Скриншот: `tests/e2e/reports/toast-error-1780120703501.png` — toast «Не найдено / Not Found» рендерится top-right.
- Коммит: `27ce8dd feat(web): toast-система`.
### 2026-05-30 — пункт 4 ✓
- `Skeleton.tsx`: базовый `<Skeleton variant='line'|'block'|'circle'>` + готовые шаблоны `<TableSkeleton>`, `<FormSkeleton>`.
- DataTable: при isLoading рендерит 8 строк скелета по числу колонок (псевдослучайная ширина для естественности).
- Edit-pages: 9 doc-форм + OrganizationSettingsPage показывают `<FormSkeleton />` при `existing.isLoading`.
- DashboardPage: график выручки — `Skeleton block h-72`.
- Скриншот: `tests/e2e/reports/skeleton-table-1780121234164.png` — shimmer на /catalog/products при искусственной 3-сек задержке через page.route().
- Коммит: `faa1352 feat(web): loading skeletons`.
### 2026-05-30 — пункт 5 ✓
- `EmptyState.tsx`: 16×16 круглая иконка из Lucide, заголовок, описание, основная кнопка + secondary link.
- 10 list-страниц + 4 reports: Products / Counterparties / Enters / Losses / Transfers / Inventories / Demands / SupplierReturns / Supplies / RetailSales + 4 отчёта (Sales / Stock / Profit / Abc).
- Тексты — объясняют что за сущность («Списания фиксируют выбытие — просрочка, брак»). CTA на навигацию `/sales/demands/new`, на Counterparties — открыть create-modal.
- Гард: показываем только когда `!search && filters.empty`. На фильтрованном результате — обычный «Нет данных».
- Скриншот: `tests/e2e/reports/empty-state-products-1780122048413.png`.
- Коммит: `8d53292 feat(web): Empty states с CTA`.
### 2026-05-30 — пункт 6 ✓
- `Breadcrumbs.tsx`: ChevronRight разделитель, последний item — semibold/не кликабельный.
- 9 edit-страниц: Product (Каталог / Товары / <name>), Supply (Закупки / Приёмки / <number>), Enter/Loss/Transfer/Inventory (Остатки / ...), SupplierReturn (Закупки / Возвраты поставщикам / <number>), Demand (Продажи / Оптовые отгрузки / <number>), RetailSale (Продажи / Чеки / <number>).
- Дублирующая subtitle «Черновик — товар не списан…» убрана; зелёный бейдж «Проведён <дата>» остаётся.
- Скриншот: `tests/e2e/reports/breadcrumbs-product-*.png`.
- Коммит: `821bc4e feat(web): Breadcrumbs на edit-страницах`.
### 2026-05-30 — пункт 7 ✓
- `useShortcuts(map, enabled?)`: 'mod+s' (Ctrl/Cmd), бэр-клавиши скипают input/textarea/contenteditable, preventDefault автоматический.
- Фикс: бэр-клавиши матчатся только по `e.key`, без проверки модификаторов — это нужно для '?' (вводится через Shift+/).
- 9 edit-pages: mod+s = save (через canSave + !save.isPending), Escape = navigate(list); guard `!dialogProps.open` чтобы не конфликтовать с ConfirmDialog.
- 10 list-pages: '/' = focus search (SearchBar теперь forwardRef), 'n' = create new.
- `<ShortcutsOverlay>` смонтирован в AppLayout — '?' открывает модал со списком всех шорткатов.
- Скриншот overlay: `tests/e2e/reports/shortcuts-overlay-1780123856118.png`.
- Коммиты: `76cbe78 feat(web): keyboard shortcuts`, `c2ebbcc fix(web): useShortcuts — бэр-клавиши`.
## Итог
Все 7 пунктов ✓. После последнего деплоя:
- `tests/e2e/run.sh stage-smoke --api-only` → 5/5 ✓
- `tests/e2e/run.sh stage-demo-seed --api-only` → 5/5 ✓
- Скриншоты подтверждают визуально: ConfirmDialog, Toaster, Skeleton, EmptyState, Breadcrumbs, ShortcutsOverlay.
Stage URL: https://test.admin.food-market.kz. Свежий signup → нажать «Заполнить демо-данными» в Настройках орги → все модули наполнены.