# Client Duplication — Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans.

**Goal:** Устранить дублирование `useQuery` для корзины (4 копии → 1 хук), устранить дублирование статусов заказа.

**Architecture:** Кастомный хук `useCartQuery` в `entities/cart/lib/`, единый источник `ORDER_STATUS_DATA`.

**Tech Stack:** TypeScript, TanStack React Query, Vitest

**Depends on:** none

---

### Task 1: useCartQuery хук + тесты

**Files:**
- Create: `client/src/entities/cart/lib/use-cart-query.ts`
- Test: `client/src/entities/cart/lib/use-cart-query.test.tsx`
- Modify: `client/src/widgets/catalog-slider/ui/AppHeader.tsx`
- Modify: `client/src/pages/cart/CartPage.tsx`
- Modify: `client/src/pages/checkout/CheckoutPage.tsx`
- Modify: `client/src/features/cart/ui/ToggleCartIcon/ToggleCartIcon.tsx`

- [ ] **Step 1: Write failing tests**

```tsx
// client/src/entities/cart/lib/use-cart-query.test.tsx
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { renderHook, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useCartQuery } from './use-cart-query'
import { fetchMyCart } from '../../api'

vi.mock('../../api', () => ({
  fetchMyCart: vi.fn(),
}))

vi.mock('@/shared/model/auth', () => ({
  useAuthUser: vi.fn(),
}))

import { useAuthUser } from '@/shared/model/auth'

function createWrapper() {
  const qc = new QueryClient()
  return ({ children }: { children: React.ReactNode }) => (
    <QueryClientProvider client={qc}>{children}</QueryClientProvider>
  )
}

describe('useCartQuery', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('returns query with correct key and enabled flag for authenticated user', async () => {
    vi.mocked(useAuthUser).mockReturnValue({ id: '1', email: 'test@test.com' })
    vi.mocked(fetchMyCart).mockResolvedValue({ items: [] })

    const { result } = renderHook(() => useCartQuery(), { wrapper: createWrapper() })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(fetchMyCart).toHaveBeenCalled()
    expect(result.current.queryKey).toEqual(['me', 'cart'])
  })

  it('does not fetch when user is not authenticated', () => {
    vi.mocked(useAuthUser).mockReturnValue(null)

    const { result } = renderHook(() => useCartQuery(), { wrapper: createWrapper() })

    expect(fetchMyCart).not.toHaveBeenCalled()
    expect(result.current.fetchStatus).toBe('idle')
  })
})
```

- [ ] **Step 2: Run to verify failure**

Run: `cd client && npx vitest run entities/cart/lib/use-cart-query.test.tsx`
Expected: FAIL

- [ ] **Step 3: Implement useCartQuery**

```ts
// client/src/entities/cart/lib/use-cart-query.ts
import { useQuery } from '@tanstack/react-query'
import { useAuthUser } from '@/shared/model/auth'
import { fetchMyCart } from '../../api'

export function useCartQuery() {
  const user = useAuthUser()

  return useQuery({
    queryKey: ['me', 'cart'],
    queryFn: fetchMyCart,
    enabled: Boolean(user),
  })
}
```

- [ ] **Step 4: Run tests**

Run: `cd client && npx vitest run entities/cart/lib/use-cart-query.test.tsx`
Expected: PASS

- [ ] **Step 5: Apply to AppHeader.tsx**

Before:
```tsx
const { data: cart } = useQuery({
  queryKey: ['me', 'cart'],
  queryFn: fetchMyCart,
  enabled: Boolean(user),
})
```

After:
```tsx
import { useCartQuery } from '@/entities/cart/lib/use-cart-query'
const { data: cart } = useCartQuery()
```

- [ ] **Step 6: Apply to CartPage.tsx, CheckoutPage.tsx, ToggleCartIcon.tsx**

Same replacement in each file.

- [ ] **Step 7: Run lint + test + build**

```bash
cd client && npm run lint && npm test && npm run build
```

- [ ] **Step 8: Commit**

```bash
git add client/src/entities/cart/lib/use-cart-query.ts client/src/entities/cart/lib/use-cart-query.test.tsx client/src/widgets/catalog-slider/ui/AppHeader.tsx client/src/pages/cart/CartPage.tsx client/src/pages/checkout/CheckoutPage.tsx client/src/features/cart/ui/ToggleCartIcon/ToggleCartIcon.tsx
git commit -m "refactor: extract useCartQuery hook"
```

---

### Task 2: Устранить дублирование статусов заказа

**Files:**
- Read: `client/src/shared/lib/order-status-data.ts`
- Read: `client/src/shared/lib/order-status-labels.ts`
- Delete: `client/src/shared/lib/order-status-labels.ts`
- Modify: all files importing from `order-status-labels`

- [ ] **Step 1: Найти все импорты orderStatusLabelRu**

Run: `rg 'orderStatusLabelRu' client/src/ --include '*.ts' --include '*.tsx'`

- [ ] **Step 2: Заменить импорты на ORDER_STATUS_DATA**

Each file importing `{ orderStatusLabelRu }` from `order-status-labels`:
- Change to import `{ ORDER_STATUS_DATA }` from `order-status-data`
- Replace `orderStatusLabelRu(status)` with `ORDER_STATUS_DATA[status].label`

- [ ] **Step 3: Delete order-status-labels.ts**

- [ ] **Step 4: Run lint + test + build**

```bash
cd client && npm run lint && npm test && npm run build
```

- [ ] **Step 5: Commit**

```bash
git add client/src/shared/lib/order-status-labels.ts client/src/shared/lib/order-status-data.ts
git commit -m "refactor: remove duplicate order status labels, use ORDER_STATUS_DATA as single source"
```
