# План рефакторинга shop > Составлен на основе анализа кода и правил `.cursor/rules`. > Дата: 2026-05-13 --- ## Статус выполнения - ✅ 1.1 Сервер: разбить `routes/auth.js` → 6 модулей - ✅ 1.2 Клиент: разбить `AdminPage.tsx` → `AdminProductsPage` + `AdminCategoriesPage` - ✅ 1.3 Клиент: разбить `OrderDetailPage.tsx` (чаты, оплата, отзывы → features) - ✅ 2.2 FSD: роутинг из `App.tsx` → `app/routes/index.tsx` - ✅ 3.1 Клиент: разбить `AppHeader.tsx` (UserMenu, CartBadge, NavigationDrawer) - ✅ 4.1 Effector: рефакторинг `auth.ts` (persist, sample, createErrorStore) - ✅ 2.1 Недостающие сегменты FSD (catalog-slider, gallery, info, address-map-picker) - ✅ 2.3 Дублирование констант клиент/сервер - ✅ 3.2 HomePage (вынесены фильтры в хук и компонент) - ✅ 3.3 AdminOrdersPage, AdminUsersPage (shared AdminDialog + AdminTable) - ✅ 5.1 fastify.decorate вместо параметров - ✅ 5.2 Валидация через Fastify Schema - ✅ 6.1 Error Boundary - ✅ 6.2 Тесты --- ## 1. Критические точки (высокий приоритет) — ✅ Выполнено ### 1.1 Сервер: разбить `server/src/routes/auth.js` (892 → ~200 строк) | Файл | Роуты | |---|---| | `routes/auth.js` | `/api/auth/request-code`, `/api/auth/verify-code`, `/api/me`, `/api/me/change-email/*`, `/api/me/profile` | | `routes/user-addresses.js` | `/api/me/addresses` (6 роутов CRUD + default) | | `routes/user-cart.js` | `/api/me/cart` (4 роута CRUD) | | `routes/user-orders.js` | `/api/me/orders` (создание, список, деталь, подтверждение, review-eligibility) | | `routes/user-payments.js` | `/api/me/orders/:id/pay` | | `routes/user-messages.js` | `/api/me/orders/:id/messages`, unread-count, conversations, mark-read | ### 1.2 Клиент: разбить `AdminPage.tsx` (891 → 604 + 295 строк) - `pages/admin-products/` + `pages/admin-categories/` - `AdminLayoutPage` — новый нав-айтем «Категории», роут `/admin/categories` ### 1.3 Клиент: разбить `OrderDetailPage.tsx` (609 → 258 строк) - `features/order-chat/` — чат по заказу - `features/order-payment/` — секция оплаты + модалка (`OrderPaymentSection`, `PaymentDialog`) - `features/product-review/` — секция отзывов + модалка (`ReviewSection`, `ReviewDialog`) --- ## 2. FSD-архитектура ### 2.1 Создать недостающие сегменты ✅ | Слайс | Что сделано | |---|---| | `entities/catalog-slider` | `model/types.ts`, `index.ts` (barrel), импорты обновлены | | `entities/gallery` | `ui/GalleryGrid.tsx`, `index.ts`, импорты обновлены | | `entities/info` | `model/types.ts`, `index.ts`, импорты обновлены | | `features/address-map-picker` | `api/map-geocoding.ts`, `model/types.ts`, `index.ts`, импорты обновлены | ### 2.2 Вынести роутинг из `App.tsx` → `app/routes/` ✅ `AppRoutes` в `app/routes/index.tsx`. `App.tsx` — чистая точка входа. ### 2.3 Устранить дублирование констант клиент/сервер ✅ Создан `shared/constants/` с каноничными значениями (`order-status.js`, `delivery-carrier.js`, `upload-limits.js`, `payment-method.js`). Все клиентские и серверные константы импортируются оттуда. Vite + tsconfig настроены на `@shared/*` alias. --- ## 3. Клиентские компоненты ### 3.1 `AppHeader.tsx` (406 → 293 строк) ✅ - `UserMenu` → `features/user/user-menu/` - `CartBadge` → `features/cart/cart-badge/` - `NavigationDrawer` → `widgets/navigation-drawer/` ### 3.2 `HomePage.tsx` (414 → 157 строк) ✅ - `useProductFilters` хук в `pages/home/lib/` - `ProductFilters` компонент в `pages/home/ui/` - Фильтры, сортировка, масштаб карточек вынесены из страницы ### 3.3 `AdminOrdersPage.tsx`, `AdminUsersPage.tsx` ✅ - `shared/ui/AdminTable/` — компонент таблицы с loading/error/skeleton - `shared/ui/AdminDialog/` — компонент диалога с loading/error/title/actions - `AdminUsersPage`: таблица и диалог заменены на общие компоненты - `AdminOrdersPage`: диалог заменён на `AdminDialog` --- ## 4. Effector + состояние — ✅ Выполнено ### 4.1 `shared/model/auth.ts` (96 → 83 строк) - `.watch()` → `sample` + `persistTokenFx` - Убран `tokenPersistInitialized` флаг - `createErrorStore(effect)` — общий шаблон сторов ошибок - `readStoredToken` → `shared/lib/persist-token.ts` (re-export из auth.ts) - Создан `shared/lib/create-error-store.ts` --- ## 5. Сервер (низкий приоритет) ### 5.1 `fastify.decorate` вместо передачи зависимостей параметрами ✅ `slugify`, `parseMaterialsInput`, `mapProductForApi` декорированы на fastify в `api.js`. Роуты используют `request.server.*` вместо получения через параметры. ### 5.2 Валидация через Fastify Schema ✅ Добавлены JSON Schema для: - `POST /api/admin/products` — body - `PATCH /api/admin/products/:id` — body - `GET /api/products` — querystring (фильтры, пагинация) --- ## 6. Инфраструктура (низкий приоритет) ### 6.1 Error Boundary ✅ Создан `shared/ui/ErrorBoundary/ErrorBoundary.tsx` — class-компонент с `getDerivedStateFromError` / `componentDidCatch`. - Отображает MUI `Alert` с заголовком «Что-то пошло не так» и кнопкой «Попробовать снова». - Поддерживает кастомный `fallback` и колбэк `onError`. - Интегрирован в `App.tsx`: ``. ### 6.2 Тесты ✅ **Клиент (vitest + jsdom + @testing-library/react):** - `shared/lib/__tests__/get-error-message.test.ts` — 4 теста - `shared/lib/__tests__/format-price.test.ts` — 3 теста - `shared/lib/__tests__/group-orders-by-status.test.ts` — 3 теста - `shared/ui/ErrorBoundary/__tests__/ErrorBoundary.test.tsx` — 4 теста (рендер, падение, кастомный fallback, сброс) **Сервер (vitest):** - `src/lib/__tests__/escape-html.test.js` — 4 теста - `src/lib/__tests__/order-status.test.js` — 9 тестов (`canTransitionAdminOrderStatus`) **Команды:** `npm test` (vitest run), `npm run test:watch` (vitest). --- ## Сводка изменений | Область | Файлов создано | Файлов изменено | |---|---|---|---| | Server routes | 0 | 4 (декораты + схемы) | | Client pages | 3 | 2 (HomePage, AdminOrdersPage, AdminUsersPage) | | Client entities | 6 | 2 (barrel, GalleryGrid, model types) | | Client features | 3 | 2 (map-geocoding, AddressMapPicker) | | Client shared/ui | 3 | 0 (AdminDialog, AdminTable, ErrorBoundary) | | Client app config | 0 | 2 (vite.config, tsconfig) | | Client tests | 4 | 0 (vitest config, setup, 3 test files) | | Server tests | 2 | 0 (vitest config, 2 test files) | | Shared constants | 8 | 0 (order-status, delivery-carrier, etc.) | | Server constants | 0 | 3 (order-status, delivery-carrier, upload-limits) | | **Итого** | **29** | **15** |