/**
* WorkflowCompletionWidget - Standardized Workflow Stats Widget
*
* A centralized widget component that displays consistent workflow completion
* stats across all Planner and Writer module pages.
*
* Features:
* - Unified data fetching via useWorkflowStats hook
* - Time-based filtering (Today, 7, 30, 90 days)
* - Credits consumption display
* - Consistent appearance across all pages
*
* IMPORTANT: Uses "Content Pages" not "Articles" per design requirements
*/
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { Card } from '../ui/card/Card';
import Button from '../ui/button/Button';
import { ChevronRightIcon } from '@heroicons/react/24/solid';
import { useWorkflowStats, TimeFilter } from '../../hooks/useWorkflowStats';
import { WORKFLOW_COLORS } from '../../config/colors.config';
// ============================================================================
// TYPE DEFINITIONS
// ============================================================================
export type SubmoduleColor = 'blue' | 'green' | 'amber' | 'purple';
export interface WorkflowCompletionWidgetProps {
/** Show credits consumption section */
showCredits?: boolean;
/** Link to analytics page */
analyticsHref?: string;
/** Additional CSS classes */
className?: string;
}
// ============================================================================
// TIME FILTER COMPONENT
// ============================================================================
interface TimeFilterProps {
value: TimeFilter;
onChange: (value: TimeFilter) => void;
}
function TimeFilterButtons({ value, onChange }: TimeFilterProps) {
const options: { value: TimeFilter; label: string }[] = [
{ value: 'today', label: 'Today' },
{ value: '7', label: '7d' },
{ value: '30', label: '30d' },
{ value: '90', label: '90d' },
];
return (
{options.map((option) => (
))}
);
}
// ============================================================================
// COMPLETION ITEM COMPONENT
// ============================================================================
interface CompletionItemProps {
label: string;
value: number;
barColor: string;
maxValue: number;
isLast: boolean;
}
function CompletionItem({ label, value, barColor, maxValue, isLast }: CompletionItemProps) {
const barWidth = maxValue > 0 ? (value / maxValue) * 100 : 0;
const prefix = isLast ? '└─' : '├─';
return (
{/* Tree prefix */}
{prefix}
{/* Label */}
{label}
{/* Progress bar */}
{/* Value */}
{value.toLocaleString()}
);
}
// ============================================================================
// MAIN COMPONENT
// ============================================================================
export default function WorkflowCompletionWidget({
showCredits = true,
analyticsHref = '/account/usage',
className = '',
}: WorkflowCompletionWidgetProps) {
const [timeFilter, setTimeFilter] = useState('30');
const { planner, writer, credits, loading } = useWorkflowStats(timeFilter);
// Define planner items with unified colors from config
// WORKFLOW_COLORS contains CSS variable names, so wrap with var()
const plannerItems = [
{ label: 'Keywords Clustered', value: planner.keywordsClustered, barColor: `var(${WORKFLOW_COLORS.planner.keywordsClustered})` },
{ label: 'Clusters Created', value: planner.clustersCreated, barColor: `var(${WORKFLOW_COLORS.planner.clustersCreated})` },
{ label: 'Ideas Generated', value: planner.ideasGenerated, barColor: `var(${WORKFLOW_COLORS.planner.ideasGenerated})` },
];
// Define writer items - using "Content Pages" not "Articles"
// Total content = drafts + review + approved + published
const totalContent = writer.contentDrafts + writer.contentReview + writer.contentPublished;
const writerItems = [
{ label: 'Content Pages', value: totalContent, barColor: `var(${WORKFLOW_COLORS.writer.contentPages})` },
{ label: 'Images Created', value: writer.imagesCreated, barColor: `var(${WORKFLOW_COLORS.writer.imagesCreated})` },
{ label: 'Pages Published', value: writer.contentPublished, barColor: `var(${WORKFLOW_COLORS.writer.pagesPublished})` },
];
// Calculate max value for proportional bars (across both columns)
const allValues = [...plannerItems, ...writerItems].map(i => i.value);
const maxValue = Math.max(...allValues, 1);
return (
{/* Header with Time Filter */}
Workflow Completion
{/* Loading State */}
{loading ? (
) : (
<>
{/* Two-column layout: Planner | Writer */}
{/* Planner Column */}
Planner
{plannerItems.map((item, idx) => (
))}
{/* Writer Column */}
Writer
{writerItems.map((item, idx) => (
))}
{/* Credits Used Section - Always show */}
{showCredits && (
Credits Used:{' '}
{credits.totalCreditsUsed.toLocaleString()}
{credits.plannerCreditsUsed > 0 && (
<>
│
Planner:{' '}
{credits.plannerCreditsUsed.toLocaleString()}
>
)}
{credits.writerCreditsUsed > 0 && (
<>
│
Writer:{' '}
{credits.writerCreditsUsed.toLocaleString()}
>
)}
)}
{/* Analytics Link */}
{analyticsHref && (
View Full Analytics
)}
>
)}
);
}
export { WorkflowCompletionWidget };