- client-di2/: копия фронтенда DI2 + shared/schema.ts, main.tsx обёрнут в wouter Router base=/di2, favicon относительный - client-di2/tailwind.config.ts (свои токены DI2) подключён через @config в index.css — иначе postcss взял бы корневой конфиг iistwin - vite.config.di2.ts: base /di2/, root client-di2, outDir dist/public-di2 - package.json: build/check через && включают сборку и typecheck di2 (build:di2, check:di2), новых зависимостей нет - Навигация финансов: ссылка «Data-Insight (полная версия)» → /di2 (target=_blank) в FinanceSidebar и FinanceBottomNav - Типовые фиксы предсуществующих ошибок DI2 (casts, ruleLogic в mutation-типах, Set<string>)
6.8 KiB
6.8 KiB
Task 2 — Клиентский субапп Data-Insight2 (client-di2): отчёт
Статус: DONE
Что создано
client-di2/ — копия фронтенда DI2
src/(78 файлов: App.tsx, pages/, components/ + ui/, hooks/, lib/, index.css),public/favicon.png,index.html— как есть, кроме правок ниже.shared/schema.ts← копияtmp/Data-Insight2/shared/schema.ts.tsconfig.json— копия DI2-tsconfig:include: ["src/**/*", "shared/**/*"],target: ES2022(сначала забыл — tsc ругался на ES5, добавлено),strict, paths@/*/@shared/*→./src,./shared,types: ["node", "vite/client"],tsBuildInfoFile: ../node_modules/typescript/tsbuildinfo-di2(бриф предлагал./node_modules/...— функционально то же, но без мусорной папки client-di2/node_modules).tailwind.config.ts← копия DI2-конфига (у DI2 свои токены/радиусы, отличные от iistwin!). Content-глобы:./client-di2/index.html,./client-di2/src/**/*— относительно cwd сборки (npm-скрипты всегда из корня). Вариант{ relative: true, files: [...] }относительно конфига проверен — глобы не матчились, утилиты вырезались (css 11 kB, 0 классов.flex/.grid/...); с cwd-глобами — 88 kB, утилиты на месте.src/index.css— добавлена директива@config "../tailwind.config.ts";в начало: без неё postcss-плагин tailwindcss от cwd (корень репо) взял бы корневойtailwind.config.tsiistwin и вырезал бы стили DI2.src/main.tsx— обёртка<Router base="/di2"><App /></Router>(wouter 3.10, пропbaseподдерживается — проверено в types/router.d.ts и фактической версии node_modules).index.html— favicon сделан относительным (href="favicon.png"), чтобы не 404 на проде; script-src/src/main.tsx— дев-режим, vite переписывает при сборке.
vite.config.di2.ts (корень)
Минимальный конфиг: react() без replit-плагинов, base: "/di2/", root: client-di2, alias @/@shared → client-di2, build.outDir: dist/public-di2, emptyOutDir: true. __BUILD_SHA__ в client-di2 не используется (grep пуст) — define не добавлял. server/fs-секций нет.
package.json
build:vite build && vite build -c vite.config.di2.ts && esbuild server/index.ts ...(main client → di2 → server bundle);build:di2,check:tsc && tsc -p client-di2/tsconfig.json,check:di2.- Новых dependencies НЕ добавлено — все пакеты DI2 (wouter, @tanstack/react-query, radix-набор, recharts, cmdk, vaul, embla, input-otp, date-fns, xlsx, tailwindcss-animate, @tailwindcss/typography и пр.) уже есть в package.json iistwin (проверено скриптом).
Прочее
Dockerfile— менять не нужно:RUN npm run buildподхватит новую сборку,COPY --from=builder /app/dist ./distскопирует и public-di2..gitignore—distуже игнорируется, не тронут.- Навигация финансов: desktop-список —
client/src/components/finance/FinanceSidebar.tsx(пункт после navItems, plain<a href="/di2" target="_blank" rel="noopener">с иконкой ExternalLink, стили как у Link, поддержка collapsed); мобильная —client/src/components/finance/FinanceBottomNav.tsx(пункт в DropdownMenu «Разделы» после категорий, тот же паттерн<a><DropdownMenuItem>). Финансовые страницы оборачиваются в FinanceLayout → ссылка появляется на всех экранах финансов.
Типовые фиксы предсуществующих ошибок DI2 (DI2 под tsx никогда не прогонял tsc)
calculations.tsx: литеральные массивы полей →as any[](2 места),addCumulativeVat(grouped as any, ...)— дженерикgroupMonthlyDataвыводил T как{period: string}.income-categories.tsx/expense-categories.tsx: в типы mutationFn добавленruleLogic?: "and" | "or"(UI его отправляет, типы отставали).income.tsx/expenses.tsx/expenses-overview.tsx:new Set<string>(...)для filterableSet (строка не assignable в Set литерального union). Рантайм-поведение не менялось.
Проверки
npm run check— чисто (оба tsc: основной + client-di2).npm run build— проходит: main client (24.9s) → di2 (6.7s,dist/public-di2/index.html2.03 kB, css 88.3 kB, js 1363 kB) → esbuilddist\index.js2.7mb.ls dist/public-di2/—index.html,assets/index-*.css,assets/index-*.js,favicon.png.grep -o 'src="[^"]*"' dist/public-di2/index.html→src="/di2/assets/index-D5btRW62.js", csshref="/di2/assets/index-CLXURD96.css"— префикс/di2/на месте.- Стыковка с Task 1: серверный бандл
dist/index.jsлежит рядом сdist/public-di2→path.resolve(import.meta.dirname, "public-di2")из Task 1 сходится. Статика/di2отдастся через express.static + fallback sendFile index.html (глубокие ссылки wouter работают).
Открытые вопросы / опасения
- Рантайм-smoke в браузере не выполнялся (по брифу достаточно check/build + контроль путей). Первый реальный прогон — на проде после деплоя; если DI2-страница откроется неавторизованной — auth-gate из Task 1 редиректа не делает (вернёт 401 JSON на API, SPA покажет ошибки БД) — стоит глянуть глазами.
- DI2-SPA шрифты грузит с Google Fonts (как в оригинале) — на проде зависит от доступности fonts.googleapis.com.
- CSS предупреждение «A PostCSS plugin did not pass the
fromoption» при di2-сборке — косметическое, на выхлоп не влияет. - Размер di2-бандла 1.36 МБ без код-сплиттинга (как в оригинале DI2) — принято как есть.