autoamtiona nd other pages udpates,

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-01 01:40:34 +00:00
parent a02e485f7d
commit 0d3e25e50f
11 changed files with 701 additions and 434 deletions

View File

@@ -7,15 +7,15 @@ import React from 'react';
import { AutomationRun, InitialSnapshot, StageProgress, GlobalProgress } from '../../services/automationService';
import { BoltIcon, CheckCircleIcon, PauseIcon } from '../../icons';
// Stage colors matching AutomationPage STAGE_CONFIG
// Stage colors matching AutomationPage STAGE_CONFIG exactly
const STAGE_COLORS = [
'from-brand-500 to-brand-600', // Stage 1: Keywords → Clusters
'from-purple-500 to-purple-600', // Stage 2: Clusters → Ideas
'from-purple-500 to-purple-600', // Stage 3: Ideas → Tasks
'from-success-500 to-success-600', // Stage 4: Tasks → Content
'from-warning-500 to-warning-600', // Stage 5: Content → Image Prompts
'from-purple-500 to-purple-600', // Stage 6: Image Prompts → Images
'from-success-500 to-success-600', // Stage 7: Manual Review Gate
'from-brand-500 to-brand-600', // Stage 1: Keywords → Clusters (brand/teal)
'from-purple-500 to-purple-600', // Stage 2: Clusters → Ideas (purple)
'from-warning-500 to-warning-600', // Stage 3: Ideas → Tasks (amber)
'from-brand-500 to-brand-600', // Stage 4: Tasks → Content (brand/teal)
'from-success-500 to-success-600', // Stage 5: Content → Image Prompts (green)
'from-purple-500 to-purple-600', // Stage 6: Image Prompts → Images (purple)
'from-success-500 to-success-600', // Stage 7: Review Gate (green)
];
const STAGE_NAMES = [
@@ -25,7 +25,7 @@ const STAGE_NAMES = [
'Tasks',
'Content',
'Prompts',
'Review',
'Publish',
];
// Helper to get processed count from stage result using correct key
@@ -76,13 +76,9 @@ const GlobalProgressBar: React.FC<GlobalProgressBarProps> = ({
// Fallback: Calculate from currentRun and initialSnapshot
const snapshot = initialSnapshot || (currentRun as any)?.initial_snapshot;
if (!snapshot) {
return { percentage: 0, completed: 0, total: 0 };
}
const totalInitial = snapshot.total_initial_items || 0;
// Calculate total completed from all stage results
let totalCompleted = 0;
for (let i = 1; i <= 7; i++) {
const result = (currentRun as any)[`stage_${i}_result`];
if (result) {
@@ -90,12 +86,26 @@ const GlobalProgressBar: React.FC<GlobalProgressBarProps> = ({
}
}
const percentage = totalInitial > 0 ? Math.round((totalCompleted / totalInitial) * 100) : 0;
// Calculate total items - sum of ALL stage initials from snapshot (updated after each stage)
// This accounts for items created during the run (e.g., keywords create clusters, clusters create ideas)
let totalItems = 0;
if (snapshot) {
for (let i = 1; i <= 7; i++) {
const stageInitial = snapshot[`stage_${i}_initial`] || 0;
totalItems += stageInitial;
}
}
// Use the updated total from snapshot, or fallback to total_initial_items
const finalTotal = totalItems > 0 ? totalItems : (snapshot?.total_initial_items || 0);
// Ensure completed never exceeds total (clamp percentage to 100%)
const percentage = finalTotal > 0 ? Math.round((totalCompleted / finalTotal) * 100) : 0;
return {
percentage: Math.min(percentage, 100),
completed: totalCompleted,
total: totalInitial,
total: finalTotal,
};
};
@@ -139,46 +149,46 @@ const GlobalProgressBar: React.FC<GlobalProgressBarProps> = ({
return (
<div className={`
rounded-xl p-4 mb-6 border-2 transition-all
rounded-2xl p-5 mb-6 border-2 transition-all
${isPaused
? 'bg-gradient-to-r from-warning-50 to-warning-100 dark:from-warning-900/20 dark:to-warning-800/20 border-warning-300 dark:border-warning-700'
: 'bg-gradient-to-r from-brand-50 to-brand-100 dark:from-brand-900/20 dark:to-brand-800/20 border-brand-300 dark:border-brand-700'
}
`}>
{/* Header Row */}
<div className="flex justify-between items-center mb-3">
<div className="flex justify-between items-center mb-4">
<div className="flex items-center gap-3">
<div className={`
size-10 rounded-lg flex items-center justify-center shadow-md
size-12 rounded-xl flex items-center justify-center shadow-lg
${isPaused
? 'bg-gradient-to-br from-warning-500 to-warning-600'
: 'bg-gradient-to-br from-brand-500 to-brand-600'
}
`}>
{isPaused ? (
<PauseIcon className="w-5 h-5 text-white" />
<PauseIcon className="w-6 h-6 text-white" />
) : percentage >= 100 ? (
<CheckCircleIcon className="w-5 h-5 text-white" />
<CheckCircleIcon className="w-6 h-6 text-white" />
) : (
<BoltIcon className="w-5 h-5 text-white animate-pulse" />
<BoltIcon className="w-6 h-6 text-white animate-pulse" />
)}
</div>
<div>
<div className={`font-bold ${isPaused ? 'text-warning-800 dark:text-warning-200' : 'text-brand-800 dark:text-brand-200'}`}>
<div className={`text-lg font-bold ${isPaused ? 'text-warning-800 dark:text-warning-200' : 'text-brand-800 dark:text-brand-200'}`}>
{isPaused ? 'Pipeline Paused' : 'Full Pipeline Progress'}
</div>
<div className="text-xs text-gray-600 dark:text-gray-400">
<div className="text-sm text-gray-600 dark:text-gray-400">
Stage {currentStage} of 7 {formatDuration()}
</div>
</div>
</div>
<div className={`text-3xl font-bold ${isPaused ? 'text-warning-600 dark:text-warning-400' : 'text-brand-600 dark:text-brand-400'}`}>
<div className={`text-4xl font-bold ${isPaused ? 'text-warning-600 dark:text-warning-400' : 'text-brand-600 dark:text-brand-400'}`}>
{percentage}%
</div>
</div>
{/* Segmented Progress Bar */}
<div className="flex h-4 rounded-full overflow-hidden bg-gray-200 dark:bg-gray-700 gap-0.5 mb-2">
{/* Segmented Progress Bar - Taller & More Vibrant */}
<div className="flex h-5 rounded-full overflow-hidden bg-gray-200 dark:bg-gray-700 gap-0.5 mb-3 shadow-inner">
{[1, 2, 3, 4, 5, 6, 7].map(stageNum => {
const status = getStageStatus(stageNum);
const stageColor = STAGE_COLORS[stageNum - 1];
@@ -188,9 +198,9 @@ const GlobalProgressBar: React.FC<GlobalProgressBarProps> = ({
key={stageNum}
className={`flex-1 transition-all duration-500 relative group ${
status === 'completed'
? `bg-gradient-to-r ${stageColor}`
? `bg-gradient-to-r ${stageColor} shadow-sm`
: status === 'active'
? `bg-gradient-to-r ${stageColor} opacity-60 ${!isPaused ? 'animate-pulse' : ''}`
? `bg-gradient-to-r ${stageColor} opacity-70 ${!isPaused ? 'animate-pulse' : ''} shadow-sm`
: 'bg-gray-300 dark:bg-gray-600'
}`}
title={`Stage ${stageNum}: ${STAGE_NAMES[stageNum - 1]}`}
@@ -206,20 +216,22 @@ const GlobalProgressBar: React.FC<GlobalProgressBarProps> = ({
})}
</div>
{/* Footer Row */}
<div className="flex justify-between text-xs text-gray-600 dark:text-gray-400">
<span>{completed} / {total} items processed</span>
<div className="flex gap-4">
{/* Footer Row - Larger Font for Stage Numbers */}
<div className="flex justify-between items-center text-sm text-gray-700 dark:text-gray-300">
<span className="font-medium">{completed} / {total} items processed</span>
<div className="flex gap-3">
{[1, 2, 3, 4, 5, 6, 7].map(stageNum => {
const status = getStageStatus(stageNum);
return (
<span
key={stageNum}
className={`
${status === 'completed' ? 'text-success-600 dark:text-success-400 font-medium' : ''}
${status === 'active' ? `${isPaused ? 'text-warning-600 dark:text-warning-400' : 'text-brand-600 dark:text-brand-400'} font-bold` : ''}
${status === 'pending' ? 'text-gray-400 dark:text-gray-500' : ''}
`}
className={`text-base font-semibold ${
status === 'completed' ? 'text-success-600 dark:text-success-400' : ''
} ${
status === 'active' ? `${isPaused ? 'text-warning-600 dark:text-warning-400' : 'text-brand-600 dark:text-brand-400'}` : ''
} ${
status === 'pending' ? 'text-gray-400 dark:text-gray-500' : ''
}`}
>
{stageNum}
{status === 'completed' && '✓'}