/** * 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 ? (
Loading stats...
) : ( <> {/* 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 };