109053e3af
Перенос, декомпозиция и перекраска форм CT/KPS/OID на @tnsu/ui-kit, config-driven дашборд-реестр по трём типам документов. Из отслеживания исключены артефакты сборки (lib-commonjs/jest-output/release) — забыты в .gitignore ранее.
175 lines
19 KiB
Markdown
175 lines
19 KiB
Markdown
# CT — перенос в ct-forms-portal (Фаза 3)
|
||
|
||
Порядок (утверждён): **Этап 1 перенос 1:1 → Этап 2 декомпозиция под структуру KPS → Этап 3 перекраска на ui-kit.**
|
||
Правило: сохранить 100% поведения; build после каждого этапа. Эталон структуры — `forms/kps/`.
|
||
Связано: `docs/REPAINT-MAP.md` (перекраска), `docs/BEHAVIORS.md`.
|
||
|
||
Источник: `ct-create-form/src/webparts/ctCreateForm/`. CT = 6953 стр, god-компоненты.
|
||
|
||
## Этап 1 — перенос 1:1 — ✅ ЗАВЕРШЁН (heft build зелёный)
|
||
1. ✅ Скопированы `components/` и `services/` → `forms/ct/{components,services}/` (17 файлов, 1:1).
|
||
2. ✅ Правки для сборки в портале (минимум, поведение не менялось):
|
||
- `CtService`: конструктор `(context, siteUrl?)`, `baseUrl = siteUrl ?? absoluteUrl` (как KPS).
|
||
`kpFolder` тоже параметризован через `siteUrl` (было жёстко на `context.pageContext.web.serverRelativeUrl`).
|
||
- `ICtCreateFormProps` + `siteUrl?`; `CtCreateForm` → `new CtService(context, siteUrl)`.
|
||
- Web-part-специфичных зависимостей (loc strings) в components/services не было — ничего убирать не пришлось.
|
||
3. ✅ Обвязка портала:
|
||
- `ctDocumentConfig.ts`: `inPortal: true` + `buildInPortalParams: (row) => ({ [row.status==='Черновик'?'ctId':'ctid']: row.id })`
|
||
(сверено с `useCtForm.ts` — читает именно `ctId`/`ctid`, совпало 1:1). siteUrl уже `/sites/sed`.
|
||
- `CtFormsPortal.tsx`: ветка `form==='ct'` → `<CtCreateForm .../>` + «← К реестру» (по образцу KPS-ветки).
|
||
4. ✅ `heft build` зелёный.
|
||
|
||
**Открытие при переносе:** CT уже частично зависел от `@tnsu/ui-kit@^0.4.0` — 3 файла
|
||
(`Step1PositionSelection.tsx`, `Step2CommercialOffers.tsx`, `CurrencyRatesForm.tsx`) уже используют
|
||
`Button`/`Alert` из кита. API совпадает 1:1 с текущим `0.11.0` (variant="secondary"/"accent", Alert
|
||
variant="err") — конфликтов не было, работает как есть. Ускорит Этап 3.
|
||
|
||
## Этап 2 — декомпозиция (карта резки god-компонентов)
|
||
|
||
**Статус:** [x] Step2CommercialOffers ✅ | [x] Step4Approval ✅ | [~] Step3ComparisonTable (в работе)
|
||
|
||
### [~] Step3ComparisonTable (2217) — В РАБОТЕ, по чекпоинтам
|
||
- ✅ **CP1 согласование** (build ок): `useStep3Approval.ts` (голосование/делегат, 1:1) + `InlineApprovalChain.tsx`
|
||
(вью цепочки + диалоги решение/делегат + баннер notifyWarning; хелперы APPROVAL_STATUS_*). Контейнер 2217→1918.
|
||
- ✅ **CP2 AI/PDF** (build ок): `useAiComment.ts` (aiComment/isAiLoading/aiError/isPdfLoading/showAiPromptDialog +
|
||
handleAiComment/handleGeneratePdfReport/handleDeleteAiComment + loadCtComment-effect + decodeHtmlEntities,
|
||
buildPayload передаётся аргументом из контейнера — матричные данные не копируются в хук) + `AiCommentBlock.tsx`
|
||
(только блок отображения, диалог-промпт остался в контейнере — как у KPS). PDF-ошибка идёт через колбэк
|
||
`onPdfError` в общий `saveError` (сохранили родной баннер).
|
||
- ✅ **CP3 хелперы/типы** (build ок): типы (ExtraSupplier/ExtraPosition/PositionRow/CellEdit/EditableOffers) →
|
||
`matrixTypes.ts`; константы (SUPPLIER_STATUS_OPTIONS/DELIVERY_TYPE_OPTIONS) + чистые ф-ции
|
||
(formatKzt/Num/Qty/round2Str/getSubCols/computeOffer/buildOfferKey) → `matrixHelpers.ts`.
|
||
`extraIdCounter` (мутабельный) оставлен в контейнере — уедет вместе с CP4.
|
||
- **Контейнер после CP1-3: 2217 → 1735 строк (−22%).**
|
||
- ✅ **CP4 ядро матрицы** (build ок): весь стейт/рефы(~15)/эффекты(loadCriteria/loadOffers/refs-sync/beforeunload/
|
||
unmount-persist)/мемо(suppliersWithOffer/allPositions/supplierCurrencies/computedOffers/minTotalByPosition/
|
||
recommendedSupplierId)/все update*/add*/delete*-хендлеры/handleSave → `useStep3Matrix.ts` (856, перенос
|
||
ВЕРБАТИМ). В контейнере — **деструктуризация** результата, поэтому render (984) НЕ менялся. `CriteriaEntry`
|
||
переехал в matrixTypes (общий). approval+ai хуки остались в контейнере (берут значения из деструктуризации).
|
||
- **Контейнер: 2217 → 984 строки (−56%). Логика матрицы вся в хуке. Этап 2 для CT ЗАВЕРШЁН.**
|
||
- ✅ **CP4 happy-path проверен в workbench**: полный проход по всем 4 шагам (создание СТ → загрузка КП → матрица →
|
||
согласование) прошёл без ошибок. Основной риск (грубый регресс/краш) снят.
|
||
⚠️ Не проверены детально: bundle-строки (комплект), перевод ед. изм. (тумблер), доп.расходы/логистика,
|
||
F5 (beforeunload-persist), критерии/AI-комментарий, делегат/замена в согласовании. Смотреть при случае,
|
||
не блокирует дальнейшую работу.
|
||
- ⏭️ **CP4 матрица-ядро** (САМЫЙ РИСК): ~15 рефов + эффекты (loadCriteria/loadOffers/beforeunload/unmount-persist) +
|
||
мемо (suppliersWithOffer/allPositions/supplierCurrencies/computedOffers/minTotalByPosition/recommendedSupplierId) +
|
||
все update*/add*/delete*-хендлеры + handleSave → `useStep3Matrix.ts` (перенос ВЕРБАТИМ, не переписывать!).
|
||
⚠️ Клубок рефов; компилятор не ловит регресс поведения. ЖЕЛАТЕЛЬНО делать при возможности workbench-теста
|
||
(после провижининга списков). Рендер таблицы (thead/tbody/итоги/критерии) дробить на ComparisonMatrix/
|
||
MatrixRowView/OfferCells/CriteriaTable/AddExtraRow — на Этапе 3 вместе с перекраской.
|
||
Метод: чисто механический перенос блоков (логику не трогать), Fluent оставляем (перекраска — Этап 3),
|
||
build после каждого god-компонента.
|
||
**Уточнённая граница Этап2/Этап3:** Этап 2 = вынос ЛОГИКИ (хуки/persist), «раз-god-ивание». Финальное
|
||
дробление оставшейся ВЬЮХИ на под-компоненты (диалоги/списки) + размеры <200 — на Этапе 3 вместе с
|
||
перекраской (диалоги всё равно → ui-kit Dialog), чтобы не трогать файлы дважды.
|
||
|
||
### ✅ Step4Approval (886) — СДЕЛАНО (build ок)
|
||
886 → `useStep4Approval.ts` (вся логика: chain-ops, add/delete/replace, handleActionConfirm, send/incore/restart,
|
||
производные флаги + удобные методы selectAddSuggestion/cancelAddRow/openReplace/…) + view `Step4Approval.tsx`
|
||
(~370, только разметка + helpers STATUS_LABELS/getStatusClass/formatDate; Fluent). Вьюху добьём на Этапе 3.
|
||
|
||
### ✅ Step2CommercialOffers (597) — СДЕЛАНО (build ок, 2 чекпоинта)
|
||
597 → контейнер `Step2CommercialOffers.tsx` (~155) + `kpTypes.ts` + `useKpProcessing.ts` (конвейер Syntex/Flow)
|
||
+ `step2Persist.ts` (handleSave→функция, возвращает patch) + вьюхи `SuppliersWithoutKp.tsx` (владеет add-стейтом)
|
||
/ `UploadedKpList.tsx`. Одно семантич. уточнение: в persist `formDataRef.current`→`formData` (в момент save совпадают).
|
||
|
||
|
||
### Step3ComparisonTable.tsx (2217) → по образцу `Step3BuildCt/*` + отдать approval в Step4
|
||
| Секции CT (строки) | Куда (аналог KPS) |
|
||
|---|---|
|
||
| 25–179 типы/хелперы/формат | `types/domain.ts`, `utils/format.ts`, `useStep3Matrix.ts` |
|
||
| 196–435 стейт матрицы | `useStep3Matrix.ts` |
|
||
| 285–394 approval-хендлеры | → Step4 `useStep4Approval.ts` |
|
||
| 396–405, 947–1017 AI/PDF | `useAiComment.ts` + `AiCommentBlock.tsx` |
|
||
| 439–604 useEffect загрузка/persist | `step3Persist.ts` + `useStep3Matrix.ts` |
|
||
| 606–706 useMemo производные | `useStep3Matrix.ts` |
|
||
| 708–789 редактируемые ячейки | `OfferCells.tsx` |
|
||
| 791–945 хендлеры строк | `AddExtraRow.tsx` + `useStep3Matrix.ts` |
|
||
| 1019–1193 handleSave | `step3Persist.ts` |
|
||
| 1197–1239 тулбар + тумблер ед.изм. | `Step3BuildCt.tsx` (+ доменное `unitConversion`) |
|
||
| 1241–1337 thead | `ComparisonMatrix.tsx` |
|
||
| 1339–1806 tbody + итоги | `MatrixRowView.tsx` + `OfferCells.tsx` + `ComparisonMatrix.tsx` |
|
||
| 1807–1864 инлайн-добавление | `AddExtraRow.tsx` |
|
||
| 1865–2029 критерии + AI + PDF | `CriteriaTable.tsx` + `AiCommentBlock.tsx` |
|
||
| 2030–2114 инлайн-цепочка (Teams) | → Step4 `InlineApprovalChain.tsx` |
|
||
| 2115–2211 диалоги (делегирование/решение) | ui-kit `Dialog` в `Step4Approval.tsx` |
|
||
|
||
### Step4Approval.tsx (886) → `useStep4Approval.ts` + `Step4Approval.tsx` + `InlineApprovalChain.tsx`
|
||
(стейт+манипуляции цепочкой 94–352, handleActionConfirm/Send/Incore/Restart 239–474 → хук; render 476–763; диалоги 764–885 → ui-kit Dialog)
|
||
|
||
### Step2CommercialOffers.tsx (597) → `useKpProcessing.ts`/`kpPipeline.ts`/`kpOffers.ts`/`step2Persist.ts` + view (`Step2LoadKp`,`KpFileList`,`CurrencyRatesForm`,`SuppliersWithoutKp`,`UploadedKpList`)
|
||
|
||
### CtService.ts (1532) — ввести `siteUrl?` (крит.) + при желании обобщённые CRUD-примитивы как в KPS. Создать `common/*` (StepShell/FormHeader/Pill) + единый `StepProps`.
|
||
|
||
## Доменные отличия CT (НЕ терять при декомпозиции!)
|
||
- Шаг 1 — из **SP-списка** (`fetchRequests(days)`), не из TNSU API (KPS).
|
||
- Колонки позиций: **disciplineCode (марка), smrType (SMR), agskCode**, uniqueCode, organization.
|
||
- `CT.number` — строковый, `generateCtNumber(projectName)` (per-project).
|
||
- `utils/unitConversion.ts` — пересчёт в ед. изм. заявки (тумблер) — нет в KPS.
|
||
- `SUPPLIER_STATUS_OPTIONS` (Завод/Дистрибьютор…) — нет в KPS.
|
||
- CurrencyRate/SupplierOffer — иные поля (rateToKzt; deliveryCostKzt/additionalCostsKzt/totalWithExtraKzt/pricePerUnitKzt).
|
||
- `getCurrentUserCompany()==='astel-k'` → `isRestrictedView` (скрытие цен).
|
||
|
||
## Этап 3 — перекраска (карта A/B/C из REPAINT-MAP)
|
||
Fluent в CT: PrimaryButton/DefaultButton→Button, TextField→TextInput/TextArea, MessageBar→Alert,
|
||
IconButton/Icon, Spinner→Spinner, Dialog→ui-kit Dialog, Checkbox→Checkbox, статусы→Pill/Badge.
|
||
Особые: **Toggle** (пересчёт ед.изм.) и **NormalPeoplePicker** (делегирование) — прямых аналогов в ките нет:
|
||
Toggle → ui-kit Toggle (есть!); people picker → TextInput + searchUsers()+suggestions (как KPS Step4).
|
||
|
||
**✅✅ Этап 3 ЗАВЕРШЁН (механическая перекраска) — Fluent полностью удалён из CT (0 импортов @fluentui
|
||
во всей `forms/ct/`), heft build ожидается пользователем.**
|
||
- Все 12 файлов с Fluent переведены на `@tnsu/ui-kit`: RequestsTable/FileUploadArea/UploadedKpList
|
||
(Checkbox/IconButton), SuppliersWithoutKp/CurrencyRatesForm/Step1PositionSelection/
|
||
Step2CommercialOffers/AiCommentBlock (TextInput/Spinner/Alert/IconButton/FormField),
|
||
useStep3Approval/InlineApprovalChain/Step4Approval (делегат/замена — NormalPeoplePicker заменён
|
||
на паттерн KPS: query+debounce(300ms)+suggestions+select, `useStep4Approval`/`useStep3Approval`
|
||
получили `handleAddQueryChange(val)`/`setDelegateQuery(val)` вместо Fluent-сигнатуры (event, val)),
|
||
и главный контейнер `Step3ComparisonTable.tsx` (984 строки, вся матрица/критерии/футер/AI-диалог).
|
||
- Правило замен применено: `TextField`→`TextInput`/`TextArea` (multiline→TextArea rows=1, автовысоты
|
||
нет — принято как в KPS `CriteriaTable`); без `className`→обёрнуто в `<div>`; `Toggle` без `label`→
|
||
обёрнут в `<label>` вручную (span рядом); иконки Fluent→спрайт (Delete→trash, Cancel→close,
|
||
Add→plus, Accept/CheckMark→check, ChevronLeft→arrow-left, PDF→document, Forward→chevron-right,
|
||
AddFriend/Switch→plus/swap, DoubleChevron*→chevron-left/right повторно, Lightbulb→без иконки).
|
||
- SCSS: все `:global(.ms-TextField-*)`-селекторы (таргетили Fluent DOM) заменены на `input`/`textarea`
|
||
(таргетят нативный тег внутри обёртки ui-kit — рабочий приём, т.к. хэши классов ui-kit непредсказуемы).
|
||
- ⚠️ **Осталось на будущее (сознательно НЕ делали сейчас):** финальное дробление `Step3ComparisonTable.tsx`
|
||
render на под-компоненты `ComparisonMatrix`/`OfferCells`/`MatrixRowView`/`AddExtraRow`/`CriteriaTable`
|
||
по образцу KPS `Step3BuildCt/*`. Причина отказа сейчас: KPS-хук `useStep3Matrix` даёт чистый API
|
||
(`matrix.rows`/`matrix.rateOf`/`matrix.editNumber`...), а CT-хук `useStep3Matrix` (856 строк, CP4)
|
||
перенесён ВЕРБАТИМ с сырыми именами (`updateEdit`/`updatePriceKzt`...) и НЕ верифицирован в runtime —
|
||
редизайн его публичного API сейчас добавил бы риск поверх уже непроверенного риска. Делать этот шаг
|
||
ТОЛЬКО после workbench-теста CP4 (см. ниже), отдельным заходом, вместе с рефакторингом API хука под
|
||
форму KPS.
|
||
- ✅ **Workbench happy-path пройден** (все 4 шага, создание→согласование, без ошибок) — основной риск CP4+перекраски
|
||
снят. Не проверены детально: bundle-строки, Toggle перевода ед.изм., доп.расходы/логистика, критерии/AI,
|
||
делегат/замена в согласовании, F5-persist. Смотреть по возможности, не блокирует дальнейшую работу.
|
||
- Отдельно найден и починен степпер (`Breadcrumbs.tsx`) — жил вне грепа по `@fluentui` (свой хендрол на
|
||
Fluent-синих литералах без Fluent-импорта), переведён на адаптер `Stepper`+`FormHeader`+`Badge` (как KPS).
|
||
- ✅✅ **Полный проход по литералам-цветам ЗАВЕРШЁН** (весь набор Fluent-палитры, не только синий):
|
||
создан мост `forms/ct/components/common/_theme.scss` (точное зеркало `forms/kps/.../common/_theme.scss`,
|
||
тот же маппинг: $accent/$accent-bg/$accent-border/$accent-dark/$accent-hover ← Fluent-синий,
|
||
$text/$muted/$muted-2/$border/$border-strong/$head-bg/$hover/$surface ← Fluent-серый,
|
||
$ok/$ok-bg/$danger/$danger-bg/$warn-fg/$warn-bg ← Fluent-статусы). Импорт `@import '../common/theme'`
|
||
добавлен в 9 файлов (Breadcrumbs, CtCreateForm, RequestsTable, Step1PositionSelection, CurrencyRatesForm,
|
||
FileUploadArea, Step2CommercialOffers, Step3ComparisonTable, Step4Approval) — bulk sed-заменой всех
|
||
Fluent hex-литералов на семантические переменные (~150+ подстановок). Один найденный баг при массовой
|
||
замене: в `CtCreateForm.module.scss` есть SPFx-плейсхолдер темы `"[theme:bodyText, default: #hex]"` —
|
||
это НЕ SCSS-код, а строка, которую парсит SPFx-лоадер во время сборки; sed случайно подставил туда
|
||
`$text` вместо литерала — исправлено обратно на реальный hex (`#111827`, эквивалент `$gray-900`).
|
||
Оставлены как есть (сознательно, вне палитры Fluent): dark-theme цвета (`#1b1a19`/`#252423`),
|
||
один `#fefefe` (незначим).
|
||
- Отдельно найден и починен степпер (`Breadcrumbs.tsx`) — жил вне грепа по `@fluentui` (свой хендрол на
|
||
Fluent-синих литералах без Fluent-импорта), переведён на адаптер `Stepper`+`FormHeader`+`Badge` (как KPS).
|
||
- Точечные UX-правки после визуальной проверки пользователем: степпер сужен до `30vw` (обёртка
|
||
`.stepperWrap`, прижат влево, откат на 100% ширины ниже `$bp-md`) — применено и в CT, и в KPS;
|
||
подсветка «выбран поставщик» (`.colSelected`) переведена с `$warn-bg` (семантически неверно —
|
||
«предупреждение») на полупрозрачную золотую заливку `rgba($gold-500, 0.02)`; заливка строк
|
||
Логистика/Доп.расходы (`.extraRow`) убрана полностью (были на `$warn-bg`, читались слишком ярко).
|
||
|
||
## ✅✅✅ ФОРМА CT ПОЛНОСТЬЮ ЗАВЕРШЕНА
|
||
Этап 1 (перенос) → Этап 2 (декомпозиция, включая рискованный CP4) → Этап 3 (перекраска компонентов +
|
||
полный проход по цветовым токенам + финальное дробление render Step3ComparisonTable) — всё сделано,
|
||
собрано и подтверждено пользователем в workbench (полный проход по 4 шагам после каждого крупного этапа).
|
||
Дальше по плану — **OID**, тем же маршрутом: перенос 1:1 → декомпозиция под структуру KPS → перекраска.
|