Commit Graph

106 Commits

Author SHA1 Message Date
Дмитрий a51a94830c phase2(deals): DealsView - центральный экран CRM (список сделок)
- DealsView (/deals): page-head со stats (всего/в работе/ждут оплату) +
  Экспорт/Новая сделка кнопки. filter-bar с 5-tab chiprow (Все/Активные/
  Ждут оплату/Закрытые/Невалидные) + поиск по name/phone/project.
  v-data-table с 6 колонками: Лид (avatar+name+phone), Статус (tonal-chip
  с colorHex из lead_statuses), Проект, Менеджер, Стоимость (Intl.NumberFormat
  ru-RU JBM tnum), Время (formatRelative мин/ч/д назад). show-select для
  будущих bulk-actions. Empty-state.
- composables/mockDeals.ts: 12 mock-сделок + DEALS_TABS (5 срезов с slug[]).
- Маршрут /deals (meta.layout=app) в router + web.php.
- .gitleaks.toml: mockDeals.ts в allowlist (фиктивные имена/телефоны).

Vue regex quirk: ESLint no-irregular-whitespace в regex с literal nbsp -
\s в JS уже matches U+00A0/U+202F из Intl.NumberFormat, использовать \s+.

Vitest +8 (всего 56/56 за 5.66s): заголовок + page-stats + 5 tabs +
дефолт active-фильтр (5/12 строк) + кнопки + 6 колонок + format «2 400 ₽» +
format «7 мин назад».

Регресс: lint+type+format OK; vitest 56/56; vite build (DealsView lazy-chunk
87.54KB - v-data-table крупный, но грузится только на /deals); story:build
11/15 за 31.93s; Pest 48/48 за 4.96s.

CLAUDE.md v1.22->v1.23, реестр Открытых_вопросов v1.31->v1.32.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:45:25 +03:00
Дмитрий 290e7dbc34 phase2(charts): ActivityChart + FunnelChart - Dashboard закрыт по дизайну
- ActivityChart: native SVG line chart (без chart-library, чтобы не +400KB
  зависимость для статичных дашборд-графиков). Y-grid 5 линий, area-gradient,
  7 точек (предпоследняя выделена primary teal как «сегодня»), 3 tabs
  (Принято/Оплачено/Отказ).
- FunnelChart: segmented bar по 14 статусам + funnel-list (sort desc).
- composables/leadStatuses.ts: snapshot 14 статусов из db/schema.sql:2130
  (НЕ из BRANDBOOK §3.6 - расхождение #1 handoff vs ТЗ из реестра v1.13).
  14 правильных slug'ов: new/viewed/worked/base/missed/negotiations/
  waiting_payment/partnership/paid/closed/test_drive/hot/replacement/final_missed.
- DashboardView интегрирует оба чарта в charts-row (md=7+5).
- cspell-words.txt: ldot, композаблом, инлайнингом, инлайнены.

Vue compiler quirk: withDefaults factory не разрешает референсить module-level
const'ы (checkInvalidScopeReference). Обходим инлайнингом литерала.

Vitest +13 тестов (всего 48/48 за 5.5s):
- ActivityChart 6 (3 tabs + 7 circles + 'сегодня' + custom points + legend)
- FunnelChart 7 (14 segments + 14 list-items + assertion на отсутствие
  'Думает'/'Спам' из handoff + сортировка + colorHex + total)

Stories +2 с 3 variants каждый (Histoire 10/14 за 30.43s).

Регресс: lint+type-check+format OK; vitest 48/48; vite build (DashboardView
chunk 14.9->21.17 KB с чартами); story:build 10/14 за 30.43s; Pest 48/48 за 5.10s.

CLAUDE.md v1.21->v1.22, реестр Открытых_вопросов v1.30->v1.31.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:32:58 +03:00
Дмитрий 1e233a70c8 phase2(dashboard): AppLayout + DashboardView - default-layout приложения
- AppLayout: v-navigation-drawer (теало-нуар sidebar 240px) + brand-block
  + nav-tree из 8 пунктов в 3 группах (Работа/Финансы/Команда), v-app-bar
  с crumb «Рабочая область → currentPage» + search ⌘K + bell + user-chip.
  Mobile (md<): drawer toggleable.
- DashboardView: page-head «Доброе утро, Иван» + page-meta + range-toggle
  4 опции (Сегодня/7д/30д/Период). KPI-row из 4 cards: 3 outlined (получено
  лидов/конверсия/активные проекты) + 1 hero balance с runway-bar 4/7
  заполненных сегментов teal #32C8A9.
- AppShell упрощён до layout-mapper (route.meta.layout 'app'/'auth').
- Маршрут /dashboard (meta.layout='app') в router + web.php.
- histoire.setup расширен 8 app-stub-маршрутами для AppLayout.
- Vitest +11 тестов: AppLayout 6 (brand+3 группы+8 пунктов+счётчики+crumb),
  DashboardView 5, AppShell.spec.ts переписан под layout-mapper.
- cspell-words.txt: JBM.

Регресс: lint+type-check+format OK; vitest 35/35 за 4.92s; vite build
DashboardView lazy-chunk 14.9KB; story:build 8/8 за 28.97s; Pest 48/48 за 4.88s.

CLAUDE.md v1.20->v1.21, реестр Открытых_вопросов v1.29->v1.30.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:21:19 +03:00
Дмитрий 19096552b4 phase2(auth): закрыты 4 оставшихся auth-экрана из v8_login.html
- RegisterView: email + password (strength-meter 0..4) + 2 click-wrap'а
  (оферта + ПДн). 3-й «маркетинг» из handoff НЕ реализован (расхождение
  #2 реестра v1.13 - handoff противоречит ТЗ §1.5/§4.1).
- TwoFactorView: 6 input-cell с auto-focus вперёд при вводе цифры,
  Backspace назад при empty, paste 6 цифр заполняет все.
- ForgotPasswordView: email + alert «5 попыток / 15 минут» по ТЗ §1.7.
- RecoveryCodesView: 8 кодов в 2-column grid + Скачать .txt (Blob/URL.createObjectURL)
  + Копировать (navigator.clipboard) + warning о невозможности повторного просмотра.

Router: 4 новых маршрута (/register, /2fa, /forgot, /recovery), все
meta.layout='auth', lazy-imports.

Vitest +14 тестов (всего 24/24 за 3.29s):
- RegisterView 4 (вкл. assertion на отсутствие маркетингового click-wrap)
- TwoFactorView 3, ForgotPasswordView 3, RecoveryCodesView 4

Stories +4 (Histoire 6/6 за 29.17s).

Регресс: lint+type-check+format OK; vitest 24/24; vite build 5 lazy-chunks
для views + Vuetify в отдельные chunks (app chunk 198KB→78KB); Pest 48/48 за 4.85s.

CLAUDE.md v1.19→v1.20, реестр Открытых_вопросов v1.28→v1.29.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:09:56 +03:00
Дмитрий e909a95a8d phase2(login): vue-router 4 + AuthLayout + LoginView - первый реальный экран
- vue-router@^4.6.4 (--legacy-peer-deps из-за Histoire vs Vite 8 peerDep).
- resources/js/router/index.ts: createWebHistory + lazy-imports + meta.layout.
  Маршрут / -> /login, /login -> LoginView (meta.layout=auth).
- resources/js/layouts/AuthLayout.vue: двухпанельный (brand-pane тёмный с
  radial-gradient акцентами + form-pane warm ivory). На mobile brand-pane скрыт.
- resources/js/views/auth/LoginView.vue: форма Vuetify по v8_login.html
  секция #form-login - email/password (autocomplete + eye-icon), primary submit,
  Yandex 360 SSO, RouterLink на /register и /forgot.
- AppShell.vue: layout-mapper по route.meta.layout (default/auth).
- routes/web.php: явные Route::view для 6 SPA-путей (НЕ catch-all - он перехватывал
  /_test/* в Pest beforeEach и валил 5 SetTenantContextTest).
- Vitest: +LoginView.spec.ts (5), +router.spec.ts (2), AppShell.spec.ts переписан (3).
  Vitest 10/10 за 3.01s.
- LoginView.story.vue для Histoire. Setup расширен memory-router'ом.
- cspell-words.txt: рендерят, коммиты, Лидерру.
- Регресс: lint:vue OK, type-check OK, format:check OK, vitest 10/10,
  vite build 212 модулей за 383ms (LoginView lazy-chunk 43.5KB JS / 51.7KB CSS),
  story:build 2/2 за 29.94s, Pest 48/48 за 4.86s.

CLAUDE.md v1.18->v1.19, реестр Открытых_вопросов v1.27->v1.28.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:59:00 +03:00
Дмитрий 952373fce5 phase2(trigger): Vue 3 + Vuetify 3 + ESLint+Prettier+Vue + vue-tsc + Vitest
Триггер фазы 2 выполнен — первый коммит в app/resources/js/. Активирует
5 из 6 инструментов фазы 2 (CLAUDE.md §3.3) — без Histoire (отдельно).

Tailwind удалён (правило CLAUDE.md §5 п.2).

Стек:
  - vue@3.5, vuetify@3.12, @vitejs/plugin-vue@6 (для Vite 8 совместимости —
    @vitejs/plugin-vue@5 поддерживает только Vite 5/6), vite-plugin-vuetify@2
    (auto-import), sass-embedded
  - eslint@10 (flat-config), eslint-plugin-vue@10,
    @vue/eslint-config-typescript@14, eslint-config-prettier, prettier@3.8
  - typescript@6, vue-tsc@3.2
  - vitest@4.1, @vue/test-utils, jsdom, @vitest/coverage-v8

Конфиги:
  - app/vite.config.js — vue + vuetify auto-import
  - app/vitest.config.ts — jsdom + setup file для ResizeObserver/
    IntersectionObserver/matchMedia/CSS.supports stubs (без них Vuetify
    падает в JSDOM)
  - app/eslint.config.js — flat-config
  - app/.prettierrc.json, app/tsconfig.json

Frontend-структура:
  - resources/js/app.ts — точка входа
  - resources/js/plugins/vuetify.ts — палитра Forest (Teal/ivory/теало-нуар
    из BRANDBOOK_v2 §3)
  - resources/js/components/AppShell.vue — первый компонент: v-app +
    v-app-bar + v-card
  - resources/css/app.css — Inter (UI, opsz axis), JetBrains Mono
    (.numeric, tnum)
  - resources/views/welcome.blade.php — упрощён под Vue mount

Smoke-тесты Vitest 3/3 за 2.8 сек:
  - монтируется без ошибок
  - содержит «Лидерра.»
  - рендерит chip с фазой 2

Build: 158 модулей за 386 ms (184 KB JS / 295 KB CSS gzipped).

npm-scripts: lint:vue, format, format:check, type-check, test:vue.
lefthook job #8 (ESLint на staged .ts/.vue) добавлен в pre-commit.
Полный type-check (vue-tsc) и Vitest — отдельно вручную (медленно для
pre-commit: ~3 сек на каждый).

CLAUDE.md v1.16 → v1.17 (фаза 1 → фаза 2 в §6).
Реестр Открытые_вопросы v1.25 → v1.26.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:07:14 +03:00