Skip to content

npp-web

npp-web — защищённый frontend платформы на Nuxt 3 + TypeScript + Tailwind CSS + Apollo GraphQL.

Он отвечает не за сбор или расчёт данных, а за то, чтобы пользователь мог безопасно читать и управлять контуром через единый кабинет.

За что отвечает

  • страница входа и сессионный UX;
  • дашборд;
  • аналитические разделы;
  • список закупок и карточки;
  • источники, запуски и административные экраны;
  • отчёты и профиль пользователя;
  • визуальная интерпретация GraphQL-контракта.

Что не должен делать frontend

  • ходить напрямую в базу;
  • читать очереди или артефакты напрямую;
  • считать бизнес-метрики, если они уже должны приходить с backend;
  • знать детали внешнего HTML/JSON конкретных источников.

Основные маршруты

МаршрутНазначение
/loginвход в систему
/dashboardсводный экран платформы
/procurementsсписок закупок
/procurements/:idкарточка закупки
/sourcesисточники и их состояние
/jobsжурнал запусков
/reportsсписок и просмотр отчётов
/analytics/*аналитические разделы
/profileпрофиль текущего пользователя
/usersуправление пользователями

Как устроен frontend

Верхнеуровнево проект состоит из:

  • pages/ — маршруты Nuxt;
  • components/ — UI-компоненты и аналитические секции;
  • composables/ — запросы и клиентская orchestration-логика;
  • graphql/ — документы и типы;
  • utils/ — форматирование и вспомогательные правила;
  • layouts/ и middleware/ — auth и каркас приложения.

Работа с GraphQL

Frontend зависит от backend через Apollo.

Обычно поток такой:

  1. документ запроса лежит в graphql/documents.ts;
  2. типы лежат в graphql/types.ts;
  3. composable вызывает запрос;
  4. страница или аналитический компонент отображает данные.

Это важно, потому что удобнее менять frontend через composables и типизированные документы, а не через ad-hoc запросы внутри компонентов.

Типовой клиентский слой выглядит так:

ts
const httpLink = new HttpLink({
  uri: config.public.graphqlEndpoint,
  fetch
});

const authLink = new ApolloLink((operation, forward) => {
  const accessToken = import.meta.client
    ? window.localStorage.getItem(AUTH_STORAGE_KEYS.accessToken)
    : null;

  operation.setContext(({ headers = {} }) => ({
    headers: {
      ...headers,
      ...(accessToken ? { authorization: `Bearer ${accessToken}` } : {})
    }
  }));

  return forward(operation);
});

Здесь важно, что frontend не знает ничего о Prisma, очередях или raw-событиях. Он работает только через GraphQL и ролевую модель.

Аналитические экраны

Frontend отображает несколько разных аналитических срезов:

  • общий overview;
  • поставщики;
  • атомный контур;
  • отчёты;
  • operational health по источникам.

Если аналитика выглядит пустой, это не всегда frontend-баг. Часто причина в том, что backend-агрегат зависит от более узкого доменного слоя, чем кажется по UI.

Ролевая модель как часть UX

Frontend NPPWEB устроен не как “один интерфейс для всех”, а как ролевой кабинет:

  • USER видит только базовый контур;
  • ANALYST получает закупки, аналитику, источники и бизнес-отчёты;
  • DEVELOPER работает с источниками, jobs, parser-runs и parser-admin;
  • ADMIN объединяет оба контура и управление пользователями.

Маршрутизация защищается глобальным middleware:

ts
export default defineNuxtRouteMiddleware(async (to) => {
  const auth = useAuthSession();
  await auth.initialize();

  if (!auth.isAuthenticated.value) {
    return navigateTo(`/login?redirect=${encodeURIComponent(to.fullPath)}`);
  }

  const roles = Array.isArray(to.meta.roles) ? (to.meta.roles as UserRole[]) : [];
  if (roles.length > 0 && !roles.includes(auth.user.value?.role ?? "USER")) {
    return navigateTo(`/forbidden?from=${encodeURIComponent(to.fullPath)}`);
  }
});

То есть frontend отвечает не только за отображение, но и за безопасную навигацию по ролям.

Переменные окружения

  • NUXT_PUBLIC_GRAPHQL_ENDPOINT
  • NUXT_GRAPHQL_PROXY_TARGET

Пример:

bash
NUXT_PUBLIC_GRAPHQL_ENDPOINT=/graphql
NUXT_GRAPHQL_PROXY_TARGET=http://localhost:3000

Локальный запуск

bash
cd npp-web
npm install
npm run dev

По умолчанию dev-сервер обычно доступен на http://localhost:4173.

Production-сценарий

bash
npm run typecheck
npm run build
node .output/server/index.mjs

Что чаще всего меняют в этом репозитории

  • новый экран или секцию аналитики;
  • таблицы, фильтры, карточки и маршруты;
  • Apollo/composable слой;
  • UX авторизации;
  • форматирование и визуальную интерпретацию метрик.

Как правильно читать frontend-проблемы

Если экран ведёт себя странно, полезно задавать вопросы в таком порядке:

  1. GraphQL-ответ вообще пришёл?
  2. У пользователя есть нужная роль?
  3. Правильно ли подключён composable?
  4. Это проблема пустых данных или проблема отображения?
  5. Не сломан ли layout / route meta / auth middleware?

Так проще отличить настоящий UI-баг от backend- или role-based ограничения.

Когда проблема почти точно не здесь

Если:

  • SourceRun падают;
  • backend health не готов;
  • GraphQL отдаёт пустую агрегацию;
  • в доменной модели нет нужных связей;

то менять frontend рано. Сначала нужно проверить scrape-helper, processing-worker или npp-backend.

Качество

bash
npm run typecheck
npm run build

Для локальной smoke-проверки полезно:

  1. поднять backend;
  2. войти в интерфейс;
  3. открыть dashboard, analytics, procurements;
  4. убедиться, что нет GraphQL runtime-ошибок и layout-регрессий.

Техническая и аналитическая документация платформы NPPWEB.