diff --git a/src/pages/AnalyticsPage.jsx b/src/pages/AnalyticsPage.jsx index 981a260..629b454 100644 --- a/src/pages/AnalyticsPage.jsx +++ b/src/pages/AnalyticsPage.jsx @@ -24,11 +24,6 @@ export default function AnalyticsPage() { const [granularity, setGranularity] = useState('monthly') const [selectedRepo, setSelectedRepo] = useState('All') - if (!model) return null - - const repoNames = ['All', ...model.allRepos.slice(0, 12).map(r => r.name)] - const hasData = Object.keys(issuesData || {}).length > 0 - const allIssues = useMemo(() => { const arr = [] Object.values(issuesData || {}).forEach(issues => arr.push(...issues)) @@ -46,6 +41,10 @@ export default function AnalyticsPage() { [filteredIssues, granularity] ) + if (!model) return null + + const repoNames = ['All', ...model.allRepos.slice(0, 12).map(r => r.name)] + const hasData = Object.keys(issuesData || {}).length > 0 const hasSeries = series.length > 0 return ( diff --git a/src/pages/ContributorsPage.jsx b/src/pages/ContributorsPage.jsx index 757571b..266bda0 100644 --- a/src/pages/ContributorsPage.jsx +++ b/src/pages/ContributorsPage.jsx @@ -43,15 +43,10 @@ export default function ContributorsPage() { document.removeEventListener('mousedown', handleClickOutside) }, []) - if (!model) return null - const { contributors } = model const navigate = useNavigate() + const contributors = model?.contributors ?? [] const busFactor = useMemo(() => computeBusFactor(contributors), [contributors]) - const topActive = contributors.slice(0, 10).filter(c => c.freshness > 50).length - const freshPct = contributors.length ? Math.round(topActive / Math.min(10, contributors.length) * 100) : 0 - const connectors = contributors.filter(c => c.isConnector) - const crossOrg = contributors.filter(c => c.isCrossOrg) const filtered = useMemo(() => contributors.filter(c => !search || c.login.toLowerCase().includes(search.toLowerCase())), @@ -60,6 +55,13 @@ export default function ContributorsPage() { const { sorted, sortConfig, onSort } = useSortedData(filtered, 'totalContribs', 'desc') const visible = sorted.slice(0, shown) + if (!model) return null + + const topActive = contributors.slice(0, 10).filter(c => c.freshness > 50).length + const freshPct = contributors.length ? Math.round(topActive / Math.min(10, contributors.length) * 100) : 0 + const connectors = contributors.filter(c => c.isConnector) + const crossOrg = contributors.filter(c => c.isCrossOrg) + const riskColor = r => r === 'critical' ? 'var(--red)' : r === 'high' ? 'var(--amber)' : 'var(--green)' const riskBar = r => r === 'critical' ? '90%' : r === 'high' ? '60%' : '25%' diff --git a/src/pages/GovernancePage.jsx b/src/pages/GovernancePage.jsx index 5494ec4..daceb66 100644 --- a/src/pages/GovernancePage.jsx +++ b/src/pages/GovernancePage.jsx @@ -14,11 +14,6 @@ export default function GovernancePage() { const { model, issuesData, runAudit, govLoading } = useApp() const [tab, setTab] = useState('dead') - if (!model) return null - - const hasAudit = Object.keys(issuesData || {}).length > 0 - const daysSince = d => Math.floor((Date.now() - new Date(d)) / 86_400_000) - // Flatten all issues and tag with repo/org const allIssues = useMemo(() => { const arr = [] @@ -29,6 +24,11 @@ export default function GovernancePage() { return arr }, [issuesData]) + if (!model) return null + + const hasAudit = Object.keys(issuesData || {}).length > 0 + const daysSince = d => Math.floor((Date.now() - new Date(d)) / 86_400_000) + // Health check 1 — Dead Issues (>90 days open, not a PR) const deadIssues = allIssues .filter(i => !i.pull_request && daysSince(i.created_at) >= 90) diff --git a/src/pages/OverviewPage.jsx b/src/pages/OverviewPage.jsx index c743007..e01be4a 100644 --- a/src/pages/OverviewPage.jsx +++ b/src/pages/OverviewPage.jsx @@ -11,8 +11,6 @@ const fmt = n => n > 999 ? (n / 1000).toFixed(1) + 'k' : String(n) export default function OverviewPage() { const { orgs, model } = useApp() const navigate = useNavigate() - if (!model) return null - const [open, setOpen] = useState(false) const infoRef = useRef(null) @@ -28,6 +26,8 @@ export default function OverviewPage() { } }, []) + if (!model) return null + const { allRepos } = model const isMulti = orgs.length > 1 const totalStars = allRepos.reduce((s, r) => s + r.stargazers_count, 0) diff --git a/src/pages/RepositoriesPage.jsx b/src/pages/RepositoriesPage.jsx index a77eb4f..20ba52f 100644 --- a/src/pages/RepositoriesPage.jsx +++ b/src/pages/RepositoriesPage.jsx @@ -37,8 +37,7 @@ export default function RepositoriesPage() { }, []) const navigate = useNavigate() - if (!model) return null - const { allRepos } = model + const allRepos = model?.allRepos ?? [] const langs = useMemo(() => ['All', ...new Set(allRepos.map(r => r.language).filter(Boolean))].slice(0, 10), @@ -54,6 +53,8 @@ export default function RepositoriesPage() { const { sorted, sortConfig, onSort } = useSortedData(filtered, 'healthScore', 'desc') const visible = sorted.slice(0, shown) + if (!model) return null + const TABLE_COLS = [ ['name', 'Repository'], ['stargazers_count', 'Stars'],