diff --git a/apps/web/src/components/page-header.tsx b/apps/web/src/components/page-header.tsx
index c50feeb..0b19a96 100644
--- a/apps/web/src/components/page-header.tsx
+++ b/apps/web/src/components/page-header.tsx
@@ -2,22 +2,19 @@ import type { ReactNode } from 'react'
interface PageHeaderProps {
title: string
- description?: string
+ description?: ReactNode
actions?: ReactNode
}
+/** Заголовок страницы как на досках макета: название 20px, описание 14px muted, действия справа. */
export function PageHeader({ title, description, actions }: PageHeaderProps) {
return (
-
-
-
{title}
- {description ? (
-
{description}
- ) : null}
+
+
+
{title}
+ {description ?
{description}
: null}
- {actions ? (
- {actions}
- ) : null}
-
+ {actions ?
{actions}
: null}
+
)
}
diff --git a/apps/web/src/routes/_auth/dashboard.tsx b/apps/web/src/routes/_auth/dashboard.tsx
index a7d36db..2920043 100644
--- a/apps/web/src/routes/_auth/dashboard.tsx
+++ b/apps/web/src/routes/_auth/dashboard.tsx
@@ -9,6 +9,10 @@ import { buildDashboardKpiCards } from '@/components/dashboard/dashboard-kpi-gri
import { DashboardNetworkHealth } from '@/components/dashboard/dashboard-network-health'
import { DashboardOperationsBreakdown } from '@/components/dashboard/dashboard-operations-breakdown'
import { DashboardQuickLinks } from '@/components/dashboard/dashboard-quick-links'
+import { ModulesListGrid } from '@/components/modules/modules-list-grid'
+import { ActivityFeed } from '@/components/portal/canvas-blocks'
+import { fmtWhen } from '@/components/portal/format'
+import type { Tone } from '@/components/portal/tone'
import { OpsDashboard } from '@/components/reui-kit'
import { chartPanelGridClassName } from '@/lib/ui-surface'
import {
@@ -69,6 +73,18 @@ function DashboardComponent() {
const speakers = speakersQ.data?.items ?? []
const jobs = jobsQ.data?.items ?? []
const kpiCards = buildDashboardKpiCards({ modules, peers, speakers, jobs })
+ const activity = jobs.slice(0, 4).map((j) => {
+ const failed = ['failed', 'error', 'cancelled'].includes(j.status.toLowerCase())
+ const running = j.status === 'running' || j.status === 'queued'
+ const tone: Tone = failed ? 'er' : running ? 'in' : 'ok'
+ return {
+ t: fmtWhen(j.finished_at ?? j.started_at ?? j.created_at),
+ title: j.kind,
+ text: j.error ?? `Статус: ${j.status}`,
+ label: failed ? 'Error' : running ? 'Running' : 'Info',
+ tone,
+ }
+ })
return (
: null}
+ queue={
+
+
+ {activity.length > 0 ? (
+
+ ) : null}
+
+ }
+ queueTitle=""
+ queueDescription=""
charts={