metrics adn insihigts

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-15 06:51:14 +00:00
parent cff00f87ff
commit c61cf7c39f
21 changed files with 749 additions and 129 deletions

View File

@@ -25,6 +25,7 @@ import { useProgressModal } from '../../hooks/useProgressModal';
import PageHeader from '../../components/common/PageHeader';
import ModuleNavigationTabs from '../../components/navigation/ModuleNavigationTabs';
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
import { WorkflowInsight } from '../../components/common/WorkflowInsights';
export default function Content() {
const toast = useToast();
@@ -55,6 +56,59 @@ export default function Content() {
const progressModal = useProgressModal();
const hasReloadedRef = useRef(false);
// Calculate workflow insights
const workflowInsights: WorkflowInsight[] = useMemo(() => {
const insights: WorkflowInsight[] = [];
const draftCount = content.filter(c => c.status === 'draft').length;
const reviewCount = content.filter(c => c.status === 'review').length;
const publishedCount = content.filter(c => c.status === 'published').length;
const publishingRate = totalCount > 0 ? Math.round((publishedCount / totalCount) * 100) : 0;
if (totalCount === 0) {
insights.push({
type: 'info',
message: 'No content yet - Generate content from tasks to build your content library',
});
return insights;
}
// Draft vs Review status
if (draftCount > reviewCount * 3 && draftCount >= 5) {
insights.push({
type: 'warning',
message: `${draftCount} drafts waiting for review - Move content to review stage for quality assurance`,
});
} else if (draftCount > 0) {
insights.push({
type: 'info',
message: `${draftCount} drafts in progress - Review and refine before moving to publish stage`,
});
}
// Review queue status
if (reviewCount > 0) {
insights.push({
type: 'action',
message: `${reviewCount} pieces awaiting final review - Approve and publish when ready`,
});
}
// Publishing readiness
if (publishingRate >= 60 && publishedCount >= 10) {
insights.push({
type: 'success',
message: `Strong publishing rate (${publishingRate}%) - ${publishedCount} articles ready for WordPress sync`,
});
} else if (publishedCount > 0) {
insights.push({
type: 'success',
message: `${publishedCount} articles published (${publishingRate}%) - Continue moving content through the pipeline`,
});
}
return insights;
}, [content, totalCount]);
// Load content - wrapped in useCallback
const loadContent = useCallback(async () => {
setLoading(true);
@@ -167,6 +221,7 @@ export default function Content() {
label: metric.label,
value: metric.calculate({ content, totalCount }),
accentColor: metric.accentColor,
tooltip: (metric as any).tooltip,
}));
}, [pageConfig?.headerMetrics, content, totalCount]);
@@ -238,6 +293,7 @@ export default function Content() {
title="Content Drafts"
badge={{ icon: <FileIcon />, color: 'purple' }}
navigation={<ModuleNavigationTabs tabs={writerTabs} />}
workflowInsights={workflowInsights}
/>
<TablePageTemplate
columns={pageConfig.columns}
@@ -283,27 +339,43 @@ export default function Content() {
getItemDisplayName={(row: ContentType) => row.title || `Content #${row.id}`}
/>
{/* Module Metrics Footer */}
{/* Module Metrics Footer - Pipeline Style with Cross-Module Links */}
<ModuleMetricsFooter
metrics={[
{
title: 'Total Content',
value: totalCount.toLocaleString(),
subtitle: `${content.filter(c => c.status === 'published').length} published`,
icon: <FileIcon className="w-5 h-5" />,
accentColor: 'green',
href: '/writer/content',
title: 'Tasks',
value: content.length.toLocaleString(),
subtitle: 'generated from queue',
icon: <TaskIcon className="w-5 h-5" />,
accentColor: 'blue',
href: '/writer/tasks',
},
{
title: 'Draft',
value: content.filter(c => c.status === 'draft').length.toLocaleString(),
subtitle: `${content.filter(c => c.status === 'published').length} published`,
icon: <TaskIcon className="w-5 h-5" />,
subtitle: 'needs editing',
icon: <FileIcon className="w-5 h-5" />,
accentColor: 'amber',
},
{
title: 'In Review',
value: content.filter(c => c.status === 'review').length.toLocaleString(),
subtitle: 'awaiting approval',
icon: <CheckCircleIcon className="w-5 h-5" />,
accentColor: 'blue',
href: '/writer/review',
},
{
title: 'Published',
value: content.filter(c => c.status === 'published').length.toLocaleString(),
subtitle: 'ready for sync',
icon: <CheckCircleIcon className="w-5 h-5" />,
accentColor: 'green',
href: '/writer/published',
},
]}
progress={{
label: 'Content Publishing Progress',
label: 'Content Publishing Pipeline: Content moved from draft through review to published (Draft \u2192 Review \u2192 Published)',
value: totalCount > 0 ? Math.round((content.filter(c => c.status === 'published').length / totalCount) * 100) : 0,
color: 'success',
}}

View File

@@ -492,6 +492,7 @@ export default function Images() {
label: metric.label,
value: metric.calculate({ images, totalCount }),
accentColor: metric.accentColor,
tooltip: (metric as any).tooltip,
}));
}, [pageConfig?.headerMetrics, images, totalCount]);

View File

@@ -133,6 +133,7 @@ export default function Review() {
pageConfig.headerMetrics.map(metric => ({
...metric,
value: metric.calculate({ content, totalCount }),
tooltip: (metric as any).tooltip,
})),
[pageConfig.headerMetrics, content, totalCount]
);

View File

@@ -31,6 +31,8 @@ import { useSectorStore } from '../../store/sectorStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
import PageHeader from '../../components/common/PageHeader';
import ModuleNavigationTabs from '../../components/navigation/ModuleNavigationTabs';
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
import { WorkflowInsight } from '../../components/common/WorkflowInsights';
export default function Tasks() {
const toast = useToast();
@@ -79,6 +81,63 @@ export default function Tasks() {
// Progress modal for AI functions
const progressModal = useProgressModal();
// Calculate workflow insights
const workflowInsights: WorkflowInsight[] = useMemo(() => {
const insights: WorkflowInsight[] = [];
const queuedCount = tasks.filter(t => t.status === 'queued').length;
const processingCount = tasks.filter(t => t.status === 'in_progress').length;
const completedCount = tasks.filter(t => t.status === 'completed').length;
const failedCount = tasks.filter(t => t.status === 'failed').length;
const completionRate = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0;
if (totalCount === 0) {
insights.push({
type: 'info',
message: 'No tasks yet - Queue ideas from Planner to start generating content automatically',
});
return insights;
}
// Queue status
if (queuedCount > 10) {
insights.push({
type: 'warning',
message: `Large queue detected (${queuedCount} tasks) - Content generation may take time, consider prioritizing`,
});
} else if (queuedCount > 0) {
insights.push({
type: 'info',
message: `${queuedCount} tasks in queue - Content generation pipeline is active`,
});
}
// Processing status
if (processingCount > 0) {
insights.push({
type: 'action',
message: `${processingCount} tasks actively generating content - Check back soon for completed drafts`,
});
}
// Failed tasks
if (failedCount > 0) {
insights.push({
type: 'warning',
message: `${failedCount} tasks failed - Review errors and retry or adjust task parameters`,
});
}
// Completion success
if (completionRate >= 70 && completedCount >= 5) {
insights.push({
type: 'success',
message: `High completion rate (${completionRate}%) - ${completedCount} pieces of content ready for review`,
});
}
return insights;
}, [tasks, totalCount]);
// AI Function Logs state
const [aiLogs, setAiLogs] = useState<Array<{
timestamp: string;
@@ -522,6 +581,7 @@ export default function Tasks() {
label: metric.label,
value: metric.calculate({ tasks, totalCount }),
accentColor: metric.accentColor,
tooltip: (metric as any).tooltip,
}));
}, [pageConfig?.headerMetrics, tasks, totalCount]);
@@ -573,6 +633,7 @@ export default function Tasks() {
title="Content Queue"
badge={{ icon: <TaskIcon />, color: 'indigo' }}
navigation={<ModuleNavigationTabs tabs={writerTabs} />}
workflowInsights={workflowInsights}
/>
<TablePageTemplate
columns={pageConfig.columns}
@@ -678,6 +739,47 @@ export default function Tasks() {
}}
/>
{/* Module Metrics Footer - Pipeline Style with Cross-Module Links */}
<ModuleMetricsFooter
metrics={[
{
title: 'Ideas',
value: clusters.reduce((sum, c) => sum + (c.ideas_count || 0), 0).toLocaleString(),
subtitle: 'from planner',
icon: <TaskIcon className="w-5 h-5" />,
accentColor: 'orange',
href: '/planner/ideas',
},
{
title: 'In Queue',
value: tasks.filter(t => t.status === 'queued').length.toLocaleString(),
subtitle: 'waiting for processing',
icon: <TaskIcon className="w-5 h-5" />,
accentColor: 'amber',
},
{
title: 'Processing',
value: tasks.filter(t => t.status === 'in_progress').length.toLocaleString(),
subtitle: 'generating content',
icon: <TaskIcon className="w-5 h-5" />,
accentColor: 'blue',
},
{
title: 'Ready for Review',
value: tasks.filter(t => t.status === 'completed').length.toLocaleString(),
subtitle: 'content generated',
icon: <CheckCircleIcon className="w-5 h-5" />,
accentColor: 'green',
href: '/writer/content',
},
]}
progress={{
label: 'Content Generation Pipeline: Tasks successfully completed (Queued → Processing → Completed)',
value: totalCount > 0 ? Math.round((tasks.filter(t => t.status === 'completed').length / totalCount) * 100) : 0,
color: 'success',
}}
/>
{/* Progress Modal for AI Functions */}
<ProgressModal
isOpen={progressModal.isOpen}