food-market/docs/sprint7-progress.md
nns 6fc74f8db6
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): пункт 5 ✓ + empty-state screenshot
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 11:21:30 +05:00

72 lines
7.3 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`.
- [ ] **6. Breadcrumbs** — на edit-страницах Reusable `<Breadcrumbs items={...}>`.
- [ ] **7. Keyboard shortcuts** — edit: Ctrl+S = save, Esc = cancel/back; list: `/` = focus search, `n` = create. Hint в footer / `?` overlay.
## Журнал
### 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`.