From a02e485f7d48283a17cf9f537de6878f205456dc Mon Sep 17 00:00:00 2001 From: "IGNY8 VPS (Salman)" Date: Wed, 31 Dec 2025 23:52:58 +0000 Subject: [PATCH] 2 --- .../dashboard/ThreeWidgetFooter.tsx | 387 ++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 frontend/src/components/dashboard/ThreeWidgetFooter.tsx diff --git a/frontend/src/components/dashboard/ThreeWidgetFooter.tsx b/frontend/src/components/dashboard/ThreeWidgetFooter.tsx new file mode 100644 index 00000000..733ad039 --- /dev/null +++ b/frontend/src/components/dashboard/ThreeWidgetFooter.tsx @@ -0,0 +1,387 @@ +/** + * ThreeWidgetFooter - 3-Column Layout for Table Page Footers + * + * Design from Section 3 of COMPREHENSIVE-AUDIT-REPORT.md: + * ┌─────────────────────────────────────────────────────────────────────────────────────┐ + * │ WIDGET 1: PAGE METRICS │ WIDGET 2: MODULE STATS │ WIDGET 3: COMPLETION │ + * │ (Current Page Progress) │ (Full Module Overview) │ (Both Modules Stats) │ + * │ ~33.3% width │ ~33.3% width │ ~33.3% width │ + * └─────────────────────────────────────────────────────────────────────────────────────┘ + * + * STYLING: Uses CSS tokens from styles/tokens.css: + * - --color-primary: Brand blue for primary actions/bars + * - --color-success: Green for success states + * - --color-warning: Amber for warnings + * - --color-purple: Purple accent + */ + +import React from 'react'; +import { Link } from 'react-router-dom'; +import { Card } from '../ui/card/Card'; +import { LightBulbIcon, ChevronRightIcon } from '@heroicons/react/24/solid'; + +// ============================================================================ +// TYPE DEFINITIONS +// ============================================================================ + +/** Submodule color type - matches headerMetrics accentColor */ +export type SubmoduleColor = 'blue' | 'green' | 'amber' | 'purple'; + +/** Widget 1: Page Progress - metrics in 2x2 grid + progress bar + hint */ +export interface PageProgressWidget { + title: string; + metrics: Array<{ label: string; value: string | number; percentage?: string }>; + progress: { value: number; label: string; color?: SubmoduleColor }; + hint?: string; + /** The submodule's accent color - progress bar uses this */ + submoduleColor?: SubmoduleColor; +} + +/** Widget 2: Module Stats - Pipeline flow with arrows and progress bars */ +export interface ModulePipelineRow { + fromLabel: string; + fromValue: number; + fromHref?: string; + actionLabel: string; + toLabel: string; + toValue: number; + toHref?: string; + progress: number; // 0-100 + /** Color for this pipeline row's progress bar */ + color?: SubmoduleColor; +} + +export interface ModuleStatsWidget { + title: string; + pipeline: ModulePipelineRow[]; + links: Array<{ label: string; href: string }>; +} + +/** Widget 3: Completion - Tree structure with bars for both modules */ +export interface CompletionItem { + label: string; + value: number; + color?: SubmoduleColor; +} + +export interface CompletionWidget { + title: string; + plannerItems: CompletionItem[]; + writerItems: CompletionItem[]; + creditsUsed?: number; + operationsCount?: number; + analyticsHref?: string; +} + +/** Main component props */ +export interface ThreeWidgetFooterProps { + pageProgress: PageProgressWidget; + moduleStats: ModuleStatsWidget; + completion: CompletionWidget; + submoduleColor?: SubmoduleColor; + className?: string; +} + +// ============================================================================ +// COLOR UTILITIES +// ============================================================================ + +const getProgressBarStyle = (color: SubmoduleColor = 'blue'): React.CSSProperties => { + const colorMap: Record = { + blue: 'var(--color-primary)', + green: 'var(--color-success)', + amber: 'var(--color-warning)', + purple: 'var(--color-purple)', + }; + return { backgroundColor: colorMap[color] }; +}; + +// ============================================================================ +// WIDGET 1: PAGE PROGRESS +// ============================================================================ + +function PageProgressCard({ widget, submoduleColor = 'blue' }: { widget: PageProgressWidget; submoduleColor?: SubmoduleColor }) { + const progressColor = widget.submoduleColor || widget.progress.color || submoduleColor; + + return ( + + {/* Header */} +

+ {widget.title} +

+ + {/* 2x2 Metrics Grid */} +
+ {widget.metrics.slice(0, 4).map((metric, idx) => ( +
+ {metric.label} +
+ + {typeof metric.value === 'number' ? metric.value.toLocaleString() : metric.value} + + {metric.percentage && ( + ({metric.percentage}) + )} +
+
+ ))} +
+ + {/* Progress Bar */} +
+
+
+
+
+ {widget.progress.label} + {widget.progress.value}% +
+
+ + {/* Hint with icon */} + {widget.hint && ( +
+ + {widget.hint} +
+ )} + + + ); +} + +// ============================================================================ +// WIDGET 2: MODULE STATS +// ============================================================================ + +function ModuleStatsCard({ widget }: { widget: ModuleStatsWidget }) { + return ( + + {/* Header */} +

+ {widget.title} +

+ + {/* Pipeline Rows */} +
+ {widget.pipeline.map((row, idx) => ( +
+ {/* Row header: FromLabel Value ► ToLabel Value */} +
+ {/* From side */} +
+ {row.fromHref ? ( + + {row.fromLabel} + + ) : ( + {row.fromLabel} + )} + + {row.fromValue} + +
+ + {/* Arrow icon */} + + + {/* To side */} +
+ {row.toHref ? ( + + {row.toLabel} + + ) : ( + {row.toLabel} + )} + + {row.toValue} + +
+
+ + {/* Progress bar */} +
+
+
+
+ ))} +
+ + {/* Navigation Links */} +
+ {widget.links.map((link, idx) => ( + + + {link.label} + + ))} +
+ + ); +} + +// ============================================================================ +// WIDGET 3: COMPLETION +// ============================================================================ + +function CompletionCard({ widget }: { widget: CompletionWidget }) { + // Calculate max for proportional bars (across both columns) + const allValues = [...widget.plannerItems, ...widget.writerItems].map(i => i.value); + const maxValue = Math.max(...allValues, 1); + + const renderItem = (item: CompletionItem, isLast: boolean) => { + const barWidth = (item.value / maxValue) * 100; + const prefix = isLast ? '└─' : '├─'; + const color = item.color || 'blue'; + + return ( +
+ {/* Tree prefix */} + {prefix} + + {/* Label */} + {item.label} + + {/* Progress bar */} +
+
+
+ + {/* Value */} + + {item.value} + +
+ ); + }; + + return ( + + {/* Header */} +

+ {widget.title} +

+ + {/* Two-column layout: Planner | Writer */} +
+ {/* Planner Column */} +
+
+ Planner +
+
+ {widget.plannerItems.map((item, idx) => + renderItem(item, idx === widget.plannerItems.length - 1) + )} +
+
+ + {/* Writer Column */} +
+
+ Writer +
+
+ {widget.writerItems.map((item, idx) => + renderItem(item, idx === widget.writerItems.length - 1) + )} +
+
+
+ + {/* Footer Stats - Credits Used & Operations */} + {(widget.creditsUsed !== undefined || widget.operationsCount !== undefined) && ( +
+ {widget.creditsUsed !== undefined && ( + + Credits Used: {widget.creditsUsed.toLocaleString()} + + )} + {widget.creditsUsed !== undefined && widget.operationsCount !== undefined && ( + + )} + {widget.operationsCount !== undefined && ( + + Operations: {widget.operationsCount} + + )} +
+ )} + + {/* Analytics Link */} + {widget.analyticsHref && ( +
+ + View Full Analytics + + +
+ )} +
+ ); +} + +// ============================================================================ +// MAIN COMPONENT +// ============================================================================ + +export default function ThreeWidgetFooter({ + pageProgress, + moduleStats, + completion, + submoduleColor = 'blue', + className = '', +}: ThreeWidgetFooterProps) { + return ( +
+ {/* + * Widget widths adjusted per requirements: + * - Widget 1 (Page Progress): 28.3% (reduced by 5%) + * - Widget 2 (Module Stats): 28.3% (reduced by 5%) + * - Widget 3 (Workflow Completion): 43.4% (increased by 10%) + */} +
+ + + +
+
+ ); +} + +// Also export sub-components for flexibility +export { PageProgressCard, ModuleStatsCard, CompletionCard };