Files
ct-forms-portal/docs/CT-PORT.md
T
Тимур Городецкий 109053e3af объединение CT, KPS, OID и дашборда в один портал
Перенос, декомпозиция и перекраска форм CT/KPS/OID на @tnsu/ui-kit,
config-driven дашборд-реестр по трём типам документов. Из отслеживания
исключены артефакты сборки (lib-commonjs/jest-output/release) — забыты
в .gitignore ранее.
2026-08-28 16:21:34 +05:00

19 KiB
Raw Blame History

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 → перекраска.