Commit Graph

3 Commits

Author SHA1 Message Date
Дмитрий 143cc458c1 fix(a11y): Q.DEFER.002 sub-B — 12 patterns fixed across 16 auth views
Q.DEFER.002 sub-B closure: manual Pa11y audit-pass via Playwright MCP login +
axe-core CDN inject on 16 auth-required views. Found ~13 unique violation
patterns, 12 fixed, 3 deferred to Q.DEFER.004.

ROOT CAUSE found: AdminLayout `<v-navigation-drawer color="secondary"
theme="dark">` resolved to Vuetify default-dark `secondary=#54b6b2` (Teal
mid) instead of liderraForest `#012019` теало-нуар. Switching to direct hex
preserves design intent + restores white-text contrast across all 8 admin
views (~50 nodes color-contrast violations cleared).

Patterns fixed:

1. AdminLayout sidebar palette (8 admin views):
   - color="secondary" → color="#012019" (root cause)
   - .brand-sub red #b94837 → #e06155 (3.41 → 5.08)
   - .nav-count gray #7a8c87 → #8a9c95 (4.26 → 5.34)
   - <v-list nav> + role="navigation" + aria-label (aria-required-children
     fix: <v-list role=list> had [role=link] children — undefined для list)

2. DashboardBalance .runway-bar — role="img" (aria-prohibited-attr fix)

3. DashboardKpiRow .delta-up — #2e8b57 → #1b6e3b (4.27 → 6.25)

4. TransactionsTable .tx-amount-up — #2e8b57 → #1b6e3b (same fix)

5. RemindersList .empty-hint — #9a9690 → #6b6356 (2.98 → 5.74; +liderra-muted alignment)

6. KanbanView .kanban-board — tabindex="0" role="region" aria-label
   (scrollable-region-focusable fix)

7. ProjectCard:
   - .v-progress-linear + :aria-label="Прогресс дневной нормы: N%"
   - icon menu :aria-label="Меню действий проекта «...»"
   - bulk-select .card-check input :aria-label="Выбрать проект «...»"

8. useStatusPill in_progress #3F7C95 → #2A5A6E (4.07 → 6.11);
   useStatusPill.spec.ts sync

9. ProjectsView toolbar select-all input aria-label

10. AdminTenants impersonate v-btn aria-label

11. Global app.css:
    `.v-messages, .v-field-label { --v-medium-emphasis-opacity: 0.7; }`
    Vuetify default ~0.52 → rendered #7a7a7a/#767471 fails 4.20-4.29:1;
    0.7 → rendered ≈#595959 → 7.9:1+ passes WCAG AA.

Re-verified post-fix via axe-core on all affected views: all clean except
DEV-only `.dev-index-num` chip (tree-shaked в prod, not a real violation).

Vitest verified post-fix: 79 files / 614 passed / 3 skipped / 0 failed
(baseline preserved).

3 patterns deferred to Q.DEFER.004:
- DealsTable VDataTable show-select bulk-checkboxes (6 nodes) — Vuetify
  slot rewrite needed
- AdminSupplierPrices 9 form inputs — v-text-field/v-switch label props
- Vuetify v-tooltip eager-mount aria-tooltip-name — library-level cosmetic

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 22:09:48 +03:00
Дмитрий cb05657f30 chore(format): prettier --write across 37 .vue/.ts files
Phase 1B audit found 48 files failing `prettier --check`. Auto-apply
via `npx prettier --write resources/js/**/*.{ts,vue,css}` produced
style-only changes:
- consistent quote style
- trailing comma normalization
- spaces around : in v-card style="position: relative" attrs
- explicit ; insertion

No semantic changes. No code-behavior changes. Production-code only;
test files batched separately into `test(frontend):` commit.

Verification:
- npx vitest run → 79/79 files, 614/614 + 3 skipped (no regression).
- npx vue-tsc --noEmit → 0 errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 20:24:33 +03:00
Дмитрий 849bc73290 refactor(frontend): Sprint 4 Phase B/2 — split 3 user views (audit O-refactor-04 хвост)
BillingView 416→114 (+ BalanceCard 155 + TransactionsTable 113 + InvoicesTable 90
+ billingFormatters 51 composable: formatPlain/formatCost/statusChipColor/
statusLabel/formatLabel/formatIcon/txAmountClass).
SecurityTab 354→39 (+ ChangePasswordCard 17 + TwoFactorCard 218 + RecoveryCodesCard 104
+ SessionsTable 66; auth-store читается напрямую в каждом sub-component).
RemindersView 345→183 (+ RemindersFilters 51 + RemindersList 173;
ReminderDialog уже отдельный с прошлой фазы — служит как ReminderForm).

State (`activeTab`, `editingReminder`, `deletingReminderId` в RemindersView)
остаётся в parent ради единого reload-flow + confirm-dialog'ов. Auth-store
читается напрямую в TwoFactorCard/RecoveryCodesCard через useAuthStore() —
без prop-drilling. Reminders-store читается напрямую в RemindersFilters/
RemindersList.

Все sub-components <250 строк (acceptance threshold). 3 view-shells: 114/39/183.

Регрессия: ESLint 0 + vue-tsc 0 + Vitest 416/416 + build OK 968 ms.

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