page adn app header mods
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import TablePageTemplate from '../../templates/TablePageTemplate';
|
||||
import {
|
||||
fetchClusters,
|
||||
@@ -28,7 +29,6 @@ import { usePageSizeStore } from '../../store/pageSizeStore';
|
||||
import { getDifficultyLabelFromNumber, getDifficultyRange } from '../../utils/difficulty';
|
||||
import PageHeader from '../../components/common/PageHeader';
|
||||
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
|
||||
import { WorkflowInsight } from '../../components/common/WorkflowInsights';
|
||||
|
||||
export default function Clusters() {
|
||||
const toast = useToast();
|
||||
@@ -76,61 +76,6 @@ export default function Clusters() {
|
||||
const progressModal = useProgressModal();
|
||||
const hasReloadedRef = useRef(false);
|
||||
|
||||
// Calculate workflow insights
|
||||
const workflowInsights: WorkflowInsight[] = useMemo(() => {
|
||||
const insights: WorkflowInsight[] = [];
|
||||
const clustersWithIdeas = clusters.filter(c => (c.ideas_count || 0) > 0).length;
|
||||
const totalIdeas = clusters.reduce((sum, c) => sum + (c.ideas_count || 0), 0);
|
||||
const emptyClusters = clusters.filter(c => (c.keywords_count || 0) === 0).length;
|
||||
const thinClusters = clusters.filter(c => (c.keywords_count || 0) > 0 && (c.keywords_count || 0) < 3).length;
|
||||
const readyForGeneration = clustersWithIdeas;
|
||||
const generationRate = totalCount > 0 ? Math.round((readyForGeneration / totalCount) * 100) : 0;
|
||||
|
||||
if (totalCount === 0) {
|
||||
insights.push({
|
||||
type: 'info',
|
||||
message: 'Create clusters to organize keywords into topical groups for better content planning',
|
||||
});
|
||||
return insights;
|
||||
}
|
||||
|
||||
// Content generation readiness
|
||||
if (generationRate < 30) {
|
||||
insights.push({
|
||||
type: 'warning',
|
||||
message: `Only ${generationRate}% of clusters have content ideas - Generate ideas to unlock content pipeline`,
|
||||
});
|
||||
} else if (generationRate >= 70) {
|
||||
insights.push({
|
||||
type: 'success',
|
||||
message: `${generationRate}% of clusters have ideas (${totalIdeas} total) - Strong content pipeline ready`,
|
||||
});
|
||||
}
|
||||
|
||||
// Empty or thin clusters
|
||||
if (emptyClusters > 0) {
|
||||
insights.push({
|
||||
type: 'warning',
|
||||
message: `${emptyClusters} clusters have no keywords - Map keywords or delete unused clusters`,
|
||||
});
|
||||
} else if (thinClusters > 2) {
|
||||
insights.push({
|
||||
type: 'info',
|
||||
message: `${thinClusters} clusters have fewer than 3 keywords - Consider adding more related keywords for better coverage`,
|
||||
});
|
||||
}
|
||||
|
||||
// Actionable next step
|
||||
if (totalIdeas === 0) {
|
||||
insights.push({
|
||||
type: 'action',
|
||||
message: 'Select clusters and use Auto-Generate Ideas to create content briefs',
|
||||
});
|
||||
}
|
||||
|
||||
return insights;
|
||||
}, [clusters, totalCount]);
|
||||
|
||||
// Load clusters - wrapped in useCallback to prevent infinite loops
|
||||
const loadClusters = useCallback(async () => {
|
||||
setLoading(true);
|
||||
@@ -445,10 +390,20 @@ export default function Clusters() {
|
||||
<>
|
||||
<PageHeader
|
||||
title="Clusters"
|
||||
description="Keyword groups organized by topic. Generate content ideas from clusters to build topical authority."
|
||||
description="Group keywords into topic clusters"
|
||||
badge={{ icon: <GroupIcon />, color: 'purple' }}
|
||||
breadcrumb="Planner / Clusters"
|
||||
workflowInsights={workflowInsights}
|
||||
breadcrumb="Planner"
|
||||
actions={
|
||||
<Link
|
||||
to="/planner/ideas"
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 hover:bg-brand-600 rounded-lg transition-colors"
|
||||
>
|
||||
Generate Ideas
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
<TablePageTemplate
|
||||
columns={pageConfig.columns}
|
||||
|
||||
Reference in New Issue
Block a user