diff --git a/packages/web/src/api.ts b/packages/web/src/api.ts
index beb40d0..aaf9ee9 100644
--- a/packages/web/src/api.ts
+++ b/packages/web/src/api.ts
@@ -31,6 +31,7 @@ export interface OverviewData {
}
export interface Issue {
+ id?: string;
url: string;
issueType: string;
severity: 'Critical' | 'Warning' | 'Info';
@@ -38,6 +39,12 @@ export interface Issue {
pageRank: number;
pageRankScore: number;
lastSeen: string;
+ type?: string;
+ internalLinksCount?: number;
+ description?: string;
+ whyItMatters?: string;
+ howToFix?: string;
+ clusterId?: string;
}
export interface IssuesResponse {
diff --git a/packages/web/src/components/CriticalPanel.tsx b/packages/web/src/components/CriticalPanel.tsx
index 890ba38..2701188 100644
--- a/packages/web/src/components/CriticalPanel.tsx
+++ b/packages/web/src/components/CriticalPanel.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState, useContext } from 'react';
+import { useEffect, useState, useContext } from 'react';
import { AlertTriangle, ExternalLink, Network, ChevronRight } from 'lucide-react';
import { DashboardContext } from '../App';
import * as API from '../api';
diff --git a/packages/web/src/components/GraphIntelligenceSection.tsx b/packages/web/src/components/GraphIntelligenceSection.tsx
index 37d941f..b06767a 100644
--- a/packages/web/src/components/GraphIntelligenceSection.tsx
+++ b/packages/web/src/components/GraphIntelligenceSection.tsx
@@ -1,4 +1,3 @@
-import React from 'react';
import { PageRankTable } from './Graphs/PageRankTable';
import { SimpleBarChart } from './Graphs/SimpleBarChart';
import { DuplicateClusterChart } from './Graphs/DuplicateClusterChart';
diff --git a/packages/web/src/components/HealthSnapshot.tsx b/packages/web/src/components/HealthSnapshot.tsx
index 3c8bea4..58828c1 100644
--- a/packages/web/src/components/HealthSnapshot.tsx
+++ b/packages/web/src/components/HealthSnapshot.tsx
@@ -1,7 +1,20 @@
-import { healthMetrics } from '../data';
+import { useContext } from 'react';
import { Activity, Link, Ghost, Copy, Layers, TrendingUp } from 'lucide-react';
+import { DashboardContext } from '../App';
export const HealthSnapshot = () => {
+ const { overview } = useContext(DashboardContext);
+
+ if (!overview) return
;
+
+ const healthMetrics = {
+ score: overview.health.score,
+ brokenLinks: overview.totals.brokenLinks,
+ orphanPages: overview.totals.orphanPages,
+ duplicateClusters: overview.totals.duplicateClusters,
+ pagesCrawled: overview.totals.crawled,
+ efficiency: overview.crawl.efficiency,
+ };
return (
diff --git a/packages/web/src/components/Issues/IssueDrawer.tsx b/packages/web/src/components/Issues/IssueDrawer.tsx
index 2eae7eb..3dab08f 100644
--- a/packages/web/src/components/Issues/IssueDrawer.tsx
+++ b/packages/web/src/components/Issues/IssueDrawer.tsx
@@ -1,9 +1,8 @@
-import React from 'react';
import { X, ExternalLink, Link, AlertTriangle } from 'lucide-react';
-import { Issue } from '../../data';
+import * as API from '../../api';
interface IssueDrawerProps {
- issue: Issue | null;
+ issue: API.Issue | null;
onClose: () => void;
isOpen: boolean;
}
diff --git a/packages/web/src/components/IssuesTable.tsx b/packages/web/src/components/IssuesTable.tsx
index 580f5c6..5f743a2 100644
--- a/packages/web/src/components/IssuesTable.tsx
+++ b/packages/web/src/components/IssuesTable.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect, useContext } from 'react';
+import { useState, useEffect, useContext } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { AlertTriangle, AlertCircle, Info, ChevronRight, Search, ArrowUp, ArrowDown } from 'lucide-react';
import { DashboardContext } from '../App';
@@ -50,10 +50,10 @@ export const IssuesTable = () => {
// Client-side sort for current page (since API sort is limited in this scope)
const sorted = [...issues].sort((a, b) => {
- // @ts-expect-error - dynamic key access
- if (a[key] < b[key]) return direction === 'asc' ? -1 : 1;
- // @ts-expect-error - dynamic key access
- if (a[key] > b[key]) return direction === 'asc' ? 1 : -1;
+ const aVal = a[key] as any;
+ const bVal = b[key] as any;
+ if (aVal < bVal) return direction === 'asc' ? -1 : 1;
+ if (aVal > bVal) return direction === 'asc' ? 1 : -1;
return 0;
});
setIssues(sorted);
diff --git a/packages/web/src/components/WarningPanel.tsx b/packages/web/src/components/WarningPanel.tsx
index 817fd35..c1f2b4a 100644
--- a/packages/web/src/components/WarningPanel.tsx
+++ b/packages/web/src/components/WarningPanel.tsx
@@ -1,7 +1,29 @@
-import { criticalIssues } from '../data.js';
+import { useState, useEffect, useContext } from 'react';
import { AlertTriangle, ArrowRight } from 'lucide-react';
+import { DashboardContext } from '../App';
+import * as API from '../api';
export const WarningPanel = () => {
+ const { currentSnapshot } = useContext(DashboardContext);
+ const [criticalIssues, setCriticalIssues] = useState
([]);
+ const [loading, setLoading] = useState(false);
+
+ useEffect(() => {
+ if (!currentSnapshot) return;
+ const fetch = async () => {
+ setLoading(true);
+ try {
+ const data = await API.fetchIssues(currentSnapshot, 'Critical', '', 1);
+ setCriticalIssues(data.results.slice(0, 5)); // show top 5
+ } catch (e) {
+ console.error(e);
+ } finally {
+ setLoading(false);
+ }
+ };
+ fetch();
+ }, [currentSnapshot]);
+
return (
@@ -10,15 +32,17 @@ export const WarningPanel = () => {
Critical Attention
-
5 issues require immediate fix
+
+ {loading ? 'Loading...' : `${criticalIssues.length} issues require immediate fix`}
+
- {criticalIssues.map((issue) => (
-
+ {criticalIssues.map((issue, idx) => (
+
-
{issue.type}
+
{issue.issueType || issue.type}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8fcf51b..a3c5a3e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -747,79 +747,66 @@ packages:
resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.59.0':
resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==}
cpu: [arm]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.59.0':
resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.59.0':
resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-loong64-gnu@4.59.0':
resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==}
cpu: [loong64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-loong64-musl@4.59.0':
resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==}
cpu: [loong64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-ppc64-gnu@4.59.0':
resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-ppc64-musl@4.59.0':
resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==}
cpu: [ppc64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-riscv64-gnu@4.59.0':
resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.59.0':
resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.59.0':
resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.59.0':
resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.59.0':
resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@rollup/rollup-openbsd-x64@4.59.0':
resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==}